run start RTCLOK = $14 ATRACT = $4d VDSLST = $200 SDMCTL = $22f SDLSTL = $230 GPRIOR = $26f STICK0 = $278 STRIG0 = $284 PCOLR0 = $2c0 PCOLR1 = $2c1 PCOLR2 = $2c2 CHBAS = $02f4 HPOSP0 = $d000 M2PF = $d002 HPOSP1 = $d001 HPOSM2 = $d006 P0PF = $d004 P1PF = $d005 SIZEM = $d00c COLPM0 = $d012 COLBK = $d01a COLPF0 = $d016 GRACTL = $d01d HITCLR = $d01e AUDF1 = $d200 AUDC1 = $d201 AUDF2 = $d202 AUDC2 = $d203 AUDF3 = $d204 AUDC3 = $d205 AUDCTL = $d208 RANDOM = $d20a HSCROL = $d404 PMBASE = $d407 NMIEN = $d40e WSYNC = $d40a PMBASEADR = $3000 ; Player/missile data locations PMDATA = PMBASEADR+$200 PMDATA2 = PMBASEADR+$280 MDATA = PMBASEADR+$180 PMSHAPESIZE = PMSHAPE2-PMSHAPE+1 STARTPOSH = 60 ; Horizontal starting position of players STARTPOSV = 56 ; Vertical starting position of players ANTICMODE = $57+$80 ; Standard ANTIC mode WIDTH = 32 ; Width of (virtual) screen BGCOL = 12 ; Number of background lines to be coloured in DLI LINES = 8 ; Number of scrolling lines CLOCKS = 8 ; Fine scrolling clocks P0POS = $80 ; Vertical position of player 1 P0POSH = $81 ; Horizontal position of player 1 M2POS = $82 ; Vertical position of missile M2POSH = $83 ; Horizontal position of missile, initialized with horizontal position of player 1 plus 6 MVSRCE = $84 ; Source pointer for moveing subroutine MVDEST = $86 ; Destination pointer for moveing subroutine LENPTR = $88 ; Length of block move, normally .word, in this case .byte is enough BGCOUNTER = $89 ; Counter for background colors, initialized with number of lines CHRADR = $8a ; Pointer to charset LMSV = $8c ; Pointer to screen memory (Load Memory Scan) ; DELPOSH = $8e ; Horizontal location of character to be removed ; DELPOSV = $8f ; Vertical location of character to be removed SPEED = $8e ; Scrolling speed TIMER = $8f ; Timer variable SHOTSPEED = $90 ; Speed of Missile ; TEMP = $91 ; Temporary variable org $91 VBIFLAG .byte 1 ; VBI execute flag SHOTFIRED .byte 0 ; Shot fired flag ;LMSC .byte $100 when you use SOUND above - but works :)... org $2000 start lda #43 sta SDMCTL lda #DLIST sta SDLSTL+1 sta AUDCTL ; high byte of DLIST is 0 because of zero-page location, so we can reuse it here sta RTCLOK lda #DLI sta VDSLST+1 lda #192 sta NMIEN setVBI ldy #VBI lda #6 jsr $e45c /* lda LMS1 ; set counter flag for end of (virtual) screen clc adc #WIDTH sta LMSC */ restart lda RTCLOK cmp #25 bne checktrig nextvoice lda #$a8 sta AUDC1 sta AUDC2 ; sta AUDC3 lda RANDOM and #%00000011 tax lda SOUND,x ; sta AUDF3 lsr sta AUDF1 lda SOUND+2,x sta AUDF2 lda #0 sta RTCLOK checktrig lda STRIG0 ; wait for trigger before game starts bne restart sta ATRACT ; use 0 to disable ATTRACT mode sta AUDC1 sta AUDC2 ; sta AUDC3 tax ; save 0 for later waitrelease lda STRIG0 beq waitrelease ; button released? sta SPEED ; use 1 to set to lower speed (=1) lda #3 ; set player configurations 35 / 232 sta PCOLR1 sta GRACTL sta SHOTSPEED lda #8 sta PCOLR0 asl ; 16 sta SIZEM asl ; 32 sta GPRIOR lda #>PMBASEADR sta PMBASE lda LENPTR ; If LENPTR has not been used yet (i.e. first time the game starts), then do not clear playfield beq playerinit txa ; get back 0 from above wipe sta line2,x sta line2+256,x ; sta line2+512,x sta PMDATA,x dex bne wipe playerinit sta HITCLR lda #STARTPOSV sta P0POS lda #STARTPOSH sta P0POSH ldy #9 ; display score resetscore lda SCORETXT,y sta line10+2,y dey bpl resetscore main lda P0PF ; Collision between player and playfield? sta VBIFLAG beq highscore ; if not, then continue game gameover ; otherwise: game over lda #0 sta AUDC2 ; stop missile sound lda #214 ; move missile out of screen sta HPOSM2 sta M2POSH lda #$8f sta AUDC1 sta RTCLOK waitsound lda RTCLOK ; play crash sound for 255-143 frames (i.e. aprrox. 2 second) sta AUDF1 sta PCOLR0 ; and flash player accordingly bne waitsound ; until RTCLOK = 0 sta AUDC1 ; then turn crash sound off overtext ldy #9 textend lda GAMEOVERTXT,y ; output GAME OVER text sta line10+2,y dey bpl textend jmp restart highscore tay ; Y = 0 after playfield collision check checkhigh lda line10+8,y cmp line10+18,y bcc prepmove bne sethigh iny cpy #2 bne checkhigh sethigh ldy #4 copyscore lda line10+7,y ; start copy from colon after score, so no need for colon in HIGHTXT, saves one byte ;) sta line10+17,y dey bpl copyscore ldy #3 hightext lda HIGHTXT,y sta line10+13,y dey bpl hightext prepmove lda #PMSHAPE ; sta MVSRCE+1 lda P0POSH sta HPOSP0 sta HPOSP1 movepm1 lda #PMDATA sta MVDEST+1 lda #PMSHAPESIZE ; sta LENPTR+1 jsr move lda #PMSHAPE2 ; sta MVSRCE+1 movepm2 lda #PMDATA2 ; as PMDATA2 is in the same page as PMDATA, we can save a few bytes here... ; sta MVDEST+1 lda #PMSHAPESIZE ; sta LENPTR+1 jsr move ; lda #MSHAPE ; sta MVSRCE+1 movem lda SHOTFIRED ; has missile been fired? beq noshot lda #MDATA sta MVDEST+1 ldy #0 lda MSHAPE sta (MVDEST),y ; instead of move-subroutine write missile directly as it is just one byte ; lda #1 ; sta LENPTR ; lda #0 ; sta LENPTR+1 lda M2POSH sta HPOSM2 sta PCOLR2 ; change missile color while flying sbc P0POSH ; use horizontal missile position sta AUDF2 ; to generate missile flying sound lda #$6a sta AUDC2 noshot lda TIMER ; read timer variable (1/50 seconds) wait cmp TIMER ; has it changed? beq wait ; if not then wait lda STRIG0 ; fire button pressed? bne checkmove jsr shot ; yes? then initiate shot checkmove ldx P0POS ; use vertical position to generate flying noise stx AUDF1 lda #$83 sta AUDC1 lda STICK0 tay and #%00000001 bne down cpx #32 ; X still holds the vertical position we can now use for checking boundaries bcc left dec P0POS down tya and #%00000010 bne left cpx #84 bcs left inc P0POS left ldx P0POSH ; doing the same with the horizontal position... tya and #%00000100 bne right cpx #45 bcc endmove dec P0POSH right tya and #%00001000 bne endmove cpx #200 bcs endmove inc P0POSH endmove lda SCROLLCOUNT cmp #8 bne checkshot lda #0 sta SCROLLCOUNT lda CHBAS clc adc #2 sta CHRADR+1 lda RANDOM and #%11111000 sta CHRADR lda LMS1 ; store LMS in zeropage clc adc #24 sta LMSV lda LMS1+1 adc #0 sta LMSV+1 ldy #0 nextbyte ; clc ldx #8 lda (CHRADR),y nextbit asl pha bcc setblank lda #"O" bcs checkbit setblank lda #" " checkbit sta (LMSV),y inc LMSV bne singlebyte2 inc LMSV+1 singlebyte2 pla dex bne nextbit lda LMSV clc adc #WIDTH*2-9 bcc singlebyte inc LMSV+1 singlebyte sta LMSV iny cpy #8 bne nextbyte checkshot lda SHOTFIRED bne delchar jmp noshot2 delchar lda M2PF beq nocoll lda M2POSH sec sbc #$1e sbc SCROLLPOS lsr lsr lsr ; sta DELPOSH tay ; Y = DELPOSH lda M2POS sec sbc #$1f lsr lsr lsr ; sta DELPOSV tax ; X = DELPOSV ; line2+(width*2+1)*DELPOSV lda LMS1 sta LMSV lda LMS1+1 sta LMSV+1 cpx #0 beq clearchar nextline lda LMSV clc adc #WIDTH*2 bcc onebyte inc LMSV+1 onebyte sta LMSV dex bne nextline clearchar lda #" " sta (LMSV),y ldy #2 ; increase score if stone is hit scoreloop lda line10+8,y clc adc #$01 cmp #":" bne writescore lda #"0" sta line10+8,y dey bpl scoreloop writescore sta line10+8,y cpy #0 ; If score >= 100 then double scrolling speed bne resmissile cmp #"1" bne resmissile stx SPEED ; x is still zero from above inc SHOTSPEED ; increase shooting speed resmissile lda #211 sta M2POSH sta HITCLR nocoll lda M2POSH clc adc SHOTSPEED sta M2POSH cmp #212 bcc noshot2 lda #0 ; reset fire flag and sound sta AUDC2 sta SHOTFIRED ldy #$80 clearm sta MDATA,y ; clear missile dey bne clearm ; jsr contshot noshot2 jmp main shot lda SHOTFIRED cmp #1 bne contshot rts contshot inc SHOTFIRED ; SHOTFIRED = 1 lda P0POS clc adc #6 sta M2POS lda P0POSH sta M2POSH rts move ldy #0 /* ; Move blocks are less than 256 bytes in this program, so this part can be skipped ldx LENPTR+1 beq mvpart mvpage lda (MVSRCE),y sta (MVDEST),y iny bne mvpage inc MVSRCE+1 inc MVDEST+1 dex bne mvpage */ sty MVSRCE+1 mvpart ldx LENPTR ; beq mvexit mvlast lda (MVSRCE),y sta (MVDEST),y iny dex bne mvlast mvexit rts VBI lda #BGCOL ; reset color counter for DLI each new frame sta BGCOUNTER lda TIMER ; Timer alternates between 1 and 2, every 1/50th second eor #%00000011 sta TIMER ldx #2 animate lda ANTRIEB,x eor #%11000000 sta ANTRIEB,x dex bpl animate lda VBIFLAG bne exitvbi lda SCROLLPOS sta HSCROL lda TIMER and SPEED bne exitvbi dec SCROLLPOS bpl exitvbi setmove lda LMS1 ; cmp LMSC cmp