;"Frantic Diamonds" ;Written by Six of Style in 6 hours on May 30, 2006 ;For the 2006 minigame compo. ; ;Source donated to The Fridge because Judd is my hero. ; org $0801 processor 6502 ;============================================================================ ;MACROS MAC blt bcc {1} ENDM MAC bge bcs {1} ENDM ;============================================================================ ;EQUATES BULLTEMP = $b0 MOVTMP = $b2 MOVTM2 = $b4 BULLET = $51 PLAYER = $58 DIAMOND = $5a TOPMARK = $53 BLANK = $20 ;============================================================================ BASIC ;SYS 2064 dc.b $0c,$08,$06,$00,$9e,$20,$32,$30 dc.b $36,$34,$00,$00,$00,$00,$00 START lda #$0f sta $d418 ;SID Volume to max lda #$40 sta difficulty ;reset difficulty to easy lda #$00 tax START0 sta $d400,x ;clear SID (except volume inx cpx #$17 bne START0 jsr InitScr ;Initialize the screen jsr PopTop ;Draw a row of diamonds jsr DrawScore ;draw the initial scoreboard LOOPACK1 lda #$10 bit $dc00 ;wait for fire button not pressed beq LOOPACK1 ;to avoid making bad initial move LOOP dec playerlagtick ;only read joystick movement periodicly bne LOOP1 ;this prevents crazy fast movement jsr GetInput ;read joystick lda playerlag ;reset player lag counter sta playerlagtick LOOP1 jsr DrawPlayer ;draw player and top pointer dec bulltick ;tick for bullet speed bne LOOP2 lda bullspeed ;reset bullet speed counter sta bulltick lda #BLANK jsr DrawBulls ;erase bullets jsr MoveBulls ;move bullets lda #BULLET jsr DrawBulls ;draw bullets (at new positions) LOOP2 lda #$10 ;wait for fire button up before the player bit $dc00 ;can shoot again. This prevents nasty beq LOOP4 ;doubleshots lda #$01 sta canshoot ;set shoot enable flag LOOP4 dec downtick1 ;dec our subticker bne LOOPx ;Thus each master tick = 255 subticks dec downtick ;dec our master down move ticker bne LOOPx lda difficulty ;set our delay for the next move down sta downtick lda #BLANK ;erase our bullets jsr DrawBulls jsr MoveDown ;move the playfield down dec difficulty dec difficulty ;next move will be more difficult jsr PopTop ;populate the top line with diamonds jsr CheckBulls ;check to see if this move has caused any hits lda #BULLET ;redraw our bullets jsr DrawBulls LOOPx jsr CheckBottom ;check for end of game bcc LOOPx1 LOOPACK lda #$10 ;wait for no fire button bit $dc00 ;so it doesn't immediately start a new game beq LOOPACK LOOPLOCK ldx #$00 LOOPL1 jsr Random sta $d400,x ;make wierd noises inx cpx #$17 bne LOOPL1 jsr Random ;flash the border sta $d020 lda #$10 bit $dc00 bne LOOPLOCK ;restart on firebutton jmp START LOOPx1 jsr WaitRast ;waste a little time jmp LOOP ;============================================================================ InitScr ;Setup Screen lda #$00 sta $d020 ;border = black sta $d021 ;background = black lda #$01 sta $0286 ;char color = white jsr $e544 ldx #$00 IS0 lda #$40 sta $0428,x ;draw the divider at the top lda #DIAMOND sta $0450,x ;draw a row of diamonds inx cpx #$28 bne IS0 rts ;============================================================================ MoveDown ;Move all blocks down and populate the top row with random blocks jsr beep lda #$07 sta MOVTMP+1 sta MOVTM2+1 lda #$70 sta MOVTMP lda #$98 sta MOVTM2 jsr MoveWonk ;move screen ram down by one line lda #$db sta MOVTMP+1 sta MOVTM2+1 lda #$70 sta MOVTMP lda #$98 sta MOVTM2 jsr MoveWonk ;move color ram down by one line rts ;============================================================================ MoveWonk ;move a block of data, expects MOVTMP and MOVTMP2 to be set ldx #$00 MW0 ldy #$00 MW1 lda (MOVTMP),y sta (MOVTM2),y iny cpy #$28 ;move first row bne MW1 lda MOVTMP sec sbc #$28 sta MOVTMP bcs MW2 dec MOVTMP+1 ;sub $28 (40) from source address MW2 lda MOVTM2 sec sbc #$28 sta MOVTM2 bcs MW3 dec MOVTM2+1 ;sub $28 (40) from dest address MW3 inx cpx #21 ;do 21 lines bne MW0 rts rts ;============================================================================ PopTop ; Populate top line ldx #$00 PT0 jsr Random ;get a random number and #$10 ;if bit 4 is set bne PT3 ;duplicate the color below us ; otherwise, get a new color PT5 jsr Random ;get a random number and #$0f ;mask out bits 4-7 beq PT3 ;if it's black, dupe the color below us sta $d850,x ;else stash it. jmp PT2 ;and go on to the next one PT3 ;dupe color below lda $d878,x ;get color below us beq PT5 ;black? dammit! try again PT2 jsr Random ;gen a random number cmp #$40 ;is it greater than or equal to $40 (64)? blt PT1 ;If not, skip this slot lda #DIAMOND ;else sta $0450,x ;stash a diamond there. PT1 inx cpx #$28 ;and carry on like this for the whole line bne PT0 rts ;============================================================================ CheckBottom ; check for lose, sec on lose, clc on n/a ldx #$00 CB0 lda $0750,x cmp #DIAMOND ;diamond here? beq CB1 inx cpx #$28 bne CB0 clc rts CB1 sec rts ;============================================================================ GetInput ;reads joystick input lda #$01 bit $dc00 bne GI0 inc playercol lda playercol cmp #$10 bne GIU0 lda #$01 sta playercol GIU0 rts GI0 ;Dn lda #$02 bit $dc00 bne GI1 ;Left dec playercol lda playercol cmp #$00 bne GID0 lda #$0f sta playercol GID0 rts GI1; Left lda #$04 bit $dc00 bne GI2 ;Right lda playerx beq GIL0 dec playerx GIL0 rts GI2; Right lda #$08 bit $dc00 bne GI3;fire lda playerx cmp #$27 beq GIR0 inc playerx GIR0 rts GI3 lda #$10 bit $dc00 bne GIF0 jsr Shoot GIF0 rts ;============================================================================ DrawPlayer ;draw the player and the pointer ldx #$00 DP1 cpx playerx bne DP0 lda #PLAYER sta $07c0,x lda #TOPMARK sta $0428,x lda playercol sta $dbc0,x sta $d828,x jmp DP2 DP0 lda #BLANK sta $07c0,x lda #$40 sta $0428,x lda #$01 sta $dbc0,x sta $d828,x DP2 inx cpx #$28 bne DP1 rts ;============================================================================ Shoot ;launch a diamond lda canshoot beq Shootx jsr dropsnd jsr FreeBull bcs Shootx ;flag this bullet as active lda #$01 sta bullstat,x lda playercol sta bullcol,x ;Initial location is player location - $28 lda #$07 sta bulladdrsh,x lda #$c0 clc adc playerx sec sbc #$28 sta bulladdrsl,x lda #$00 sta canshoot Shootx rts ;============================================================================ dropsnd lda #$20 sta $d40b lda #$80 sta $d407 lda #$07 sta $d408 lda #$24 sta $d40c lda #$00 sta $d40d lda #$21 sta $d40b rts ;============================================================================ beep lda #$10 sta $d404 lda #$04 sta $d400 lda #$08 sta $d401 lda #$09 sta $d405 lda #$00 sta $d406 lda #$11 sta $d404 rts ;BULLET ROUTINES==================================================== FreeBull ;returns sec on no free, x and clc if free ldx #$00 FrB0 lda bullstat,x beq FrB1 ;is this bullet slot free? inx cpx #$06 bne FrB0 sec rts FrB1 clc rts ;============================================================================ MoveBulls ;each bullet moves to bulladdr-40 unless bulladdr-40 ;contains a diamond ldx #$00 MoVB0 lda bullstat,x beq MoVB1 ;get target addy of curr addy - $28 lda bulladdrsh,x sta BULLTEMP+1 lda bulladdrsl,x sec sbc #$28 sta BULLTEMP bcs MoVB2 dec BULLTEMP+1 MoVB2 ;check target addy for block ldy #$00 lda (BULLTEMP),y cmp #DIAMOND beq MoVB4 ;or top lda BULLTEMP+1 cmp #$04 bne MoVB3 lda BULLTEMP cmp #$50 bge MoVB3 MoVB4 jsr ProcBull ;Process this bullet landing at it's current loc MoVB3 lda BULLTEMP sta bulladdrsl,x lda BULLTEMP+1 sta bulladdrsh,x MoVB1 inx cpx #$06 bne MoVB0 rts ;============================================================================ DrawBulls ;a=BLANK erase a=BULLET draw (self modifying routine) tay ldx #$00 DBl0 lda bullstat,x beq DBl1 lda bulladdrsh,x sta DBl2+2 clc adc #$d4 sta DBl3+2 lda bulladdrsl,x sta DBl2+1 sta DBl3+1 tya DBl2 sta $0400 ;(this address gets modified) store bullet lda bullcol,x DBl3 sta $d800 ;(this address gets modified) store color DBl1 inx cpx #$06 bne DBl0 rts ;============================================================================ ProcBull ;bull number in x lda #$00 tay sta bullstat,x ;bullet is now inactive jsr GetBullAd ;get its address in BULLTEMP lda #DIAMOND sta (BULLTEMP),y ;store a diamond there lda BULLTEMP+1 clc adc #$d4 sta BULLTEMP+1 lda bullcol,x sta (BULLTEMP),y ;store bullet color lda BULLTEMP+1 sec sbc #$d4 sta BULLTEMP+1 ;reset BULLTEMP jsr CheckBull rts ;============================================================================ CheckBulls ;check each bullet for a match ldx #$00 CBs0 jsr GetBullAd ;get bullet address in BULLTEMP jsr CheckBull ;check it to see if it has landed bcc CBs1 lda #$00 ;if it has, deactivate it. sta bullstat,x CBs1 inx cpx #$06 bne CBs0 rts ;============================================================================ CheckBull ;Bull# in x, bulladd in BULLTEMP, returns carry if killed jsr CheckUp bcc CBlx ;if they match, kill both, follow on up CheckLoop jsr CheckUp bcc CBlxx jmp CheckLoop CBlxx ;finally, kill our bullet jsr GetBullAd jsr BullBlank sec rts CBlx clc rts ;============================================================================ CheckUp ;checks bullad-$28 for diamond of bullcol,x sec on found ;If the next slot up is a diamond lda BULLTEMP sec sbc #$28 sta BULLTEMP bcs CU0 dec BULLTEMP+1 CU0 lda (BULLTEMP),y cmp #DIAMOND bne CUx ;and it is our color lda BULLTEMP+1 clc adc #$d4 sta BULLTEMP+1 lda (BULLTEMP),y and #$0f cmp bullcol,x bne CUx ;blank it lda BULLTEMP+1 sec sbc #$d4 sta BULLTEMP+1 jsr BullBlank ;inc score jsr incscore ;and return sec rts CUx clc rts ;============================================================================ GetBullAd ;load BULLTEMP with bulladdr x lda bulladdrsh,x sta BULLTEMP+1 lda bulladdrsl,x sta BULLTEMP rts ;============================================================================ BullBlank ;draw a blank space at (BULLTEMP) lda #BLANK sta (BULLTEMP),y rts ;============================================================================ Random ;returns a semi-random number in a lda $dc04 eor $dc05 eor $dd04 adc $dd05 eor $dd06 eor $dd07 rts ;============================================================================ WaitRast ;waste a rasterline or so of time ldy $d012 WV0 cpy $d012 beq WV0 rts ;============================================================================ incscore ;Increments score by running through the digits txa pha ldx #$06 incs0 inc $0405,x lda $0405,x cmp #$3a ;overflow? bne isx ;no, we're done. lda #$30 ;then set to 0 and inc the previous one. sta $0405,x dex bne incs0 isx pla tax rts ;============================================================================ DrawScore ;Draw initial SCORE:000000 ldx #$00 DrSc0 lda scorestr,x sta $0400,x inx cpx #$0c bne DrSc0 rts ;============================================================================ DATA scorestr dc.b $13,$03,$0f,$12,$05,$3a,$30,$30,$30,$30,$30,$30 playerx dc.b $00 ;x position of player playercol dc.b $01 ;current color of player playerlag dc.b $20 ;lag of player movement playerlagtick dc.b $04 ;ticker for player movement difficulty dc.b $40 ;ticker reset value for down move downtick dc.b $10 ;counter for down move downtick1 dc.b $ff ;sub-ticker for down move bulladdrsh dc.b $00,$00,$00,$00,$00,$00 ;hi-byte of bullet screen addy bulladdrsl dc.b $00,$00,$00,$00,$00,$00 bullstat dc.b $00,$00,$00,$00,$00,$00 ;lo-byte of bullet screen addy bullcol dc.b $00,$00,$00,$00,$00,$00 bullspeed dc.b $20 ;lag for bullet movement bulltick dc.b $20 ;ticker for bullet movement canshoot dc.b $01 ;flag to allow player to shoot