;--------------------------------------- ;assemble it - game 3 - missile blasta ;the remastered edition ; ;(Requires version 5.7a of C64Studio) ; ;written by richard bayliss ;(c)2018 the new dimension ;--------------------------------------- ;improved with: ;-improved missile movement ;-individual enemy object properties (where ; missiles have individual speed and death ; check properties. ;-missiles can rock and move ;-4 different tunes (title, in game, game over, ending) ;-better presentation and graphics ;generate program file !to "missileblasta.prg",cbm ;variables /pointers for the game spritepos = $0370 ;positions for the ;sprites collision = $03f0 ;collision dection gameon = $0331 ;to check if game ;is on, or not levelct = $0332 ;our level counter pointer = $0340 ;pointer for multi ;purpose animation ;with sprites nomovebull = $0342 destroy = $0350 ;pointer to check ;explosion anim plrdestroy = $0351 gameover = $0352 ;Music is relocated to $8000, due to the size of the tune musicinit = $8000 ; init music musicplay = $8003 ; play music sfxplay = $8006 ;play sfx ;some zeropages for you! xpos = $02 ;x-position control of scrolling message firebutton = $03 ;fire button control (prevent button held) missilecounter = $04 ;missile counter before flipping to next level ;setup basic / sys start address (since nothing ;is overlapping memory $0801) *=$0801 !basic 2018,$3800 *=$0c00 attribs !bin "bin/attributes.bin" ;insert the sprites *=$2000 !bin "bin/sprites.bin" ;insert the status screen (pre-built from older build) *=$2700 !bin "bin/status.prg",,2 ;insert the game binary charset *=$2800 !bin "bin/charset.bin" ;insert the game screen binary (made from charpad) *=$3000 gamematrix ;insert the title screen matrix (made from charpad) !bin "bin/screen.bin" *=$3400 titlematrix !bin "bin/titlescreen.bin" ;insert the game screen colour attributes *= $3800 ;where we start our ;jmp address restart sei ;set irq flag lda #$00 ;init xscroll sta xpos sta firebutton sta animdelay1 ;reset animation timers sta animdelay2 sta missilecounter ;reset number of missiles to destroy lda #$18 ;turn on screen sta $d016 ;multicolour lda #$1a sta $d018 ;charset at $2800 lda #$0e ;screen colour sta $d022 ; lda #$06 ;blue is my favourite colour :) sta $d023 lda #$00 ;black the frame and sta $d021 ;background sta $d020 ; ;draw the title screen from the exported binary ;from charpad. ldx #$00 drawtitle lda titlematrix,x sta $400,x lda titlematrix+$100,x sta $0500,x lda titlematrix+$200,x sta $0600,x lda titlematrix+$2e8,x sta $06e8,x inx bne drawtitle ;paint the charsets from the charset attributes ;and place them into the colour RAM ldx #$00 colourtitle ldy $0400,x lda attribs,y sta $d800,x ldy $0500,x lda attribs,y sta $d900,x ldy $0600,x lda attribs,y sta $da00,x ldy $06e8,x lda attribs,y sta $dae8,x inx bne colourtitle ;pad the very bottom row of the title screen ;with the spacebar character, to make way for the ;smooth scroll text. ldx #$00 clearscrollline lda #$20 sta $07c0,x inx cpx #$28 bne clearscrollline ;copy previous score to title screen ;at the very top row. ldx #$00 copylastscore lda scorebackup,x sta $0400,x inx cpx #$28 bne copylastscore lda #$1a ;charset type sta $d018 ;read from $2800 lda #$00 ;no sprites on sta $d015 ;screen ;reset title screen message lda #scrolltext sta messread+2 ;call out interrupts for the title screen, to ;display the title screen scrolling message ;and also to play music. (You should already know ;how to unlatch interrupts by now :) ldx #titleirq lda #$36 stx $0314 sty $0315 sta $d012 lda #$7f sta $dc0d lda #$1b sta $d011 lda #$01 sta $d01a lda #$01 ;Track 2 in music player - Title music jsr musicinit cli jmp * ;Title screen fire button press wait subroutine. ;to prevent sensitivity skipping. Fire cannot be held, therefore ;a special command is added to check for firepressing waitfire lda $dc00 ;check for firebutton pressed lsr lsr lsr lsr lsr bit firebutton ror firebutton bmi waitfire2 bvc waitfire2 jmp exittitle waitfire2 rts ;switch off irq interrupts from title screen exittitle sei ldx #$31 ldy #$ea lda #$00 sta $d01a sta $d019 stx $0314 sty $0315 lda #$81 sta $dc0d sta $dd0d lda #$00 sta firebutton jmp gamestart ;title screen irq interrupt titleirq inc $d019 lda $dc0d sta $dd0d lda #$30 cmp $d012 bne *-3 lda #$18 sta $d016 jsr dotitlescroll lda #$f1 cmp $d012 bne *-3 lda xpos sta $d016 jsr colroll jsr waitfire jsr palntsccheck ;check system for music player` jmp $ea7e ;produce and perform the scroller for the title ;screen. dotitlescroll jsr scrollflash ;subroutine to flash text on scroller jsr fireflash lda xpos ;smooth scroller control sec sbc #2;speed set for example title and #7 sta xpos bcs endscroll ldx #$00 shiftchr lda $07c1,x ;move text chars back on scroller sta $07c0,x lda titleflashstore sta $dbc0,x inx cpx #$27 bne shiftchr messread ;test message lda scrolltext cmp #$00 bne storechar lda #scrolltext sta messread+2 jmp messread storechar sta $07e7 inc messread+1 bne endscroll inc messread+2 endscroll rts ;main subroutine for flashing the scrolltext scrollflash lda titleflashdelay cmp #2 beq dotitleflash inc titleflashdelay rts dotitleflash lda #0 sta titleflashdelay ldx titleflashpointer lda titleflashcolour,x sta titleflashstore lda fireflashtable,x sta fireflashstore inx cpx #titleflashend-titleflashcolour beq resettitleflash inc titleflashpointer rts resettitleflash ldx #0 stx titleflashpointer rts fireflash ldx #$00 flashloop2 lda fireflashstore sta $db7b,x inx cpx #18 bne flashloop2 rts titleflashdelay !byte 0 titleflashpointer !byte 0 titleflashstore !byte 0 fireflashstore !byte 0 titleflashcolour !byte $06,$04,$0e,$03,$0d,$01,$0d,$03,$0e,$04,$06,$00 titleflashend fireflashtable !byte $06,$05,$03,$01,$03,$05,$06,$00,$00,$00,$00,$00 gamestart lda #$ff ;this is where we sta $d015 ;setup and init. sta $d01c ;all the sprites lda #$0b ;for our game sta $d025 ; lda #$01 ; sta $d026 ; lda #$80 ; sta $07f8 ; lda #$82 ; sta $07f9 ; lda #$8a ;Chosen clear sprite sta $07fa ; sta $07fb ; sta $07fc ; sta $07fd ; sta $07fe ; sta $07ff ; sta missileframe lda #%11111100 ;Expand sprite mode sta $d017 ;reposition sprites according to ;postable. ldx #$00 possprts lda postable+$00,x sta spritepos+$00,x inx cpx #$10 bne possprts ;set some colours for the game sprites, according ;to the colour table ldx #$00 spcols lda spritecolourtable,x sta $d027,x inx cpx #$08 bne spcols ;draw the space background from reading ;the stored screen ($3000-$33e8) ldx #$00 drawgamescreen lda gamematrix,x sta $0400,x lda gamematrix+$100,x sta $0500,x lda gamematrix+$200,x sta $0600,x lda gamematrix+$2e8,x sta $06e8,x inx bne drawgamescreen ;once again, draw the attributes on to ;the screen colours ldx #$00 drawattribs ldy $0400,x lda attribs,y sta $d800,x ldy $0500,x lda attribs,y sta $d900,x ldy $0600,x lda attribs,y sta $da00,x ldy $06e8,x lda attribs,y sta $dae8,x inx bne drawattribs lda #$18 ;turn on screen sta $d016 ;multicolour mode lda #$1a ;turn on charset sta $d018 ;fron $2800 lda #$06 ;use blue for sta $d023 ;multicolour 1 lda #$0e ;and lt blue for sta $d022 ;multicolour 2 ldx #$00 ;read 40 chars to status lda $2700,x ;paste the score sta $0400,x ;from $2700 to the lda #$07 ;screen ram ($400) sta $d800,x ; inx ; cpx #$28 ; bne status ; lda #$01 ; disable destroy sta destroy ; and set levelct sta levelct ; to level1 lda #$00 ; init the no of sta missilecounter ; missiles blasted sta pointer ;initialise the sta pointer+$01;pointers and sta nomovebull ;bullet status sta gameover ;disable ;game over lda #1 sta levelpointer jsr levelsetup lda #0 sta missile1speed sta missile2speed sta missile3speed sta missile4speed sta missile5speed sta missile6speed sta missile1expdelay sta missile1exppointer sta missile2expdelay sta missile2exppointer sta missile3expdelay sta missile3exppointer sta missile4expdelay sta missile4exppointer sta missile5expdelay sta missile5exppointer sta missile6expdelay sta missile6exppointer lda #$08 jsr $ffd2 ;disable shift+cbm lda #gameirq ;initialise and ldy #$00 ;we prepare to play sta $0314 ;the irq request stx $0315 ;flag, to run a sty $d012 ;continuous loop lda #$7f ;to perform more sta $dc0d ;tasks. sta $dd0d ; lda #$01 ; sta $d019 ; sta $d01a ; lda #0 ;TUNE #1 - In game music jsr musicinit jsr playlevelupsfx cli gameloop lda #0 sta gamesync lda gamesync cmp gamesync beq *-3 lda gameover ;is game over? if cmp #$01 ;so, end the game beq endgame jsr expand ;call expand jsr mvplayer ;call mvplayer jsr bulletmv ;call bulletmv jsr shipcol ;call shipcol jsr setmissileproperties ;call missile properties jsr setrockingproperties ;missile x direction control jsr animate ;call animate jsr bullcol ;call bullcol jsr random ;call random jmp gameloop ;irq loop endgame jsr explplr ;call explplr jmp gameloop ;custom code to setup each level (missile speed properties) levelsetup ldx levelpointer ;Read pointer position according to level lda levelxtbllo,x ;Read low-byte of xspeed table for missiles sta levelsm1+1 ;store to selfmod low-byte for random xspeed of missile lda levelxtblhi,x ;Read hi-byte of xspeed table for missiles sta levelsm1+2 ;store to selfmod hi-byte for random yspeed lda levelytbllo,x ;Read low-byte of yspeed table for missiles sta levelsm2+1 ;store to selfmod low-byte for random yspeed lda levelytblhi,x ;Read hi-byte of yspeed table for missiles sta levelsm2+2 ;store to selfmod hi-byte for random missiles lda mcol1,x ;Read selected byte from level colour table 1 sta $d022 ;then place it to char multicolour #1 lda mcol2,x ;Read selected byte from level colour table 2 sta $d023 ;then place it to char multicolour #2 inx cpx #9 ;Level over - No more levels to play! beq gamecomplete inc levelpointer ;Increment next position of level pointer ;Simple self-mod code, for setting up the level speed table ;for the x and y speed of missiles ldy #$00 levelsm1 lda $ffff,y ;Self-mod position for missile randomxspeed sta ranxspeed,y levelsm2 lda $ffff,y ;Self-mod position for missile randomyspeed sta ranyspeed,y iny cpy #24 bne levelsm1 gamecomplete rts ;Game interrupts ... gameirq inc $d019 ;our main irq flag lda $dc0d sta $dd0d lda #$fa ;Bottom raster position sta $d012 lda #1 ;Unlatch synchronised timer (Must also be zeroed outside irq) sta gamesync jsr colroll ;call colroll jsr palntsccheck ;test for PAL / NTSC jmp $ea7e ;expand sprite positions and put read ;data from spritepos into the main ;sprite position formats ($d000-$d00f) expand ldx #$00 xloop lda spritepos+$01,x ;Pick position Y of sprites in loop sta $d001,x ;Store to sprite Y hardware position lda spritepos+$00,x ;Pick position X of sprites in loop asl ;x position is more ror $d010 ;than 256 pixels sta $d000,x ;Store to hardware X sprite position inx ;Increment pointer twice ... Once for X position and inx ;once for Y position cpx #$10 bne xloop rts ;read the joystick in port 2 and move ;the player around the screen. pressing ;firebutton will make the player shoot ;a rocket. you should already know how ;the joystick control works. so no help ;is really reqired here. mvplayer lda $dc00 ;read joystick up lsr a ;check up bcs down ;not up ldy spritepos+$01; dey ;move player dey ;up, until it cpy #$48 ;reaches #$48 bcs setup ;then stop ldy #$48 ;moving player setup sty spritepos+$01 down lsr a ;check down bcs left ;not down ldy spritepos+$01; iny ;move player iny ;down until it cpy #$e2 ;reaches #$ec bcc setdown ;then stop ldy #$e2 ;moving player setdown sty spritepos+$01 left lsr a ;read left bcs right ;not left ldy spritepos+$00 dey ;as with up cpy #$0e ;and down, but bcs setleft ;moving left ldy #$0e ; setleft sty spritepos+$00 right lsr a ;read right bcs fire ;not right ldy spritepos+$00 iny ;as up and cpy #$9e ;down but bcc setright ;moving right ldy #$9e setright sty spritepos+$00 fire lsr a ;read fire bit firebutton ;prevent firebutton hold down ror firebutton ;when firing. bmi nojoy ;not fire bvc nojoy lda #0 sta firebutton lda spritepos+2 cmp #$f0 ;check if bullet is out of beq oktofire ;the screen. jmp nojoy ;else just ignore it oktofire jsr playplayershootsfx ;Play player shoot sfx lda spritepos+$00;place bullet sta spritepos+$02;on ship and lda spritepos+$01;fire bullet sta spritepos+$03;process nojoy ;done rts ;the moving bullet ;this routine (as you already seen ;before) will check whether the bullet ;is at its home position, or is moving ;if the bullet is not moving then we ;call moveit, else we just jump on to ;nomovebl which ignores the bullet ;moving process. bulletmv moveit lda spritepos+$03 sec sbc #$0c ;bullet fast enough? cmp #$36 ;reached outside screen? bcs storebull ;no. store it to next position ;reset bullet x/yposition lda #$f0 sta spritepos+$02 rts storebull sta spritepos+$03 lda #$82 sta $07f9 rts nomovebl ;check and perform the enemy to bullet ;collision detection. if bullet smacks ;the enemy, add points to the score. ;you already seen this sort of routine ;in our previous 2 player game tutorial ;you will also notice that this routine ;also works with control loops. where ;we kill the enemies. bullcol lda spritepos+$02 ;Grab bullet object position X sec sbc #$06 ;Calculate collision position LEFT sta collision+$00 clc adc #$0c ;Calculate collision position RIGHT sta collision+$01 lda spritepos+$03 ;Grab bullet object position Y sec sbc #$0c*2 ;Calculate collision position UP (x2 for Y expanded sprites) sta collision+$02 ;after all, we are fighting against large missiles. clc adc #$18*2 ;Calculate collision position DOWN (x2 for Y epanded sprites) sta collision+$03 ;macro generated missile/bullet collision detection ;test. ;Tests whether a missile is already dead, if so. Ignore ;collision. Otherwise, check whether or not the bullet is ;in range of the missile. If it is within range of the ;collision area, the missile gets destroyed, and the player ;will score 100 points. !macro missiletobullet missiledead, bulletx, bullety, speedx { lda missiledead ;Is the missile alread destroyed? cmp #1 ;Yes? beq .nomissilecollision ;Do not read missile collision lda bulletx ;bullet x range to missile cmp collision+$00 ;Left range bcc .nomissilecollision ;no collision cmp collision+$01 ;Right range bcs .nomissilecollision ;no collision lda bullety ;bullet y range to missile cmp collision+$02 ;Top range bcc .nomissilecollision ;no collision cmp collision+$03 ;bottom range bcs .nomissilecollision ;no collision lda #0 sta spritepos+2 ;move bullet out of screen sta speedx ;also stop missile speed x lda #1 ;then destroy the missile. sta missiledead jsr playmissileexplosionsfx ;play explosion sound effects jsr doscore ;call score adding routine. .nomissilecollision } ;end of macro jsr M1B ;M1B = Statement: Missile 1 to bullet jsr M2B ;M2B = Statement: Missile 2 to bullet jsr M3B ;M3B = Statement: Missile 3 to bullet jsr M4B ;M4B = Statement: Missile 4 to bullet jsr M5B ;M5B = Statement: Missile 5 to bullet jsr M6B ;M6B = Statement: Missile 6 to bullet rts ;Linked to MACRO subroutine. : Missile 1 to Bullet M1B +missiletobullet missile1dead, spritepos+4, spritepos+5, missile1speed rts ;Linked to MACRO subroutine. : Missile 2 to Bullet M2B +missiletobullet missile2dead, spritepos+6, spritepos+7, missile2speed rts ;Linked to MACRO subroutine. : Missile 3 to Bullet M3B +missiletobullet missile3dead, spritepos+8, spritepos+9, missile3speed rts ;Linked to MACRO subroutine. : Missile 4 to Bullet M4B +missiletobullet missile4dead, spritepos+10, spritepos+11, missile4speed rts ;Linked to MACRO subroutine. : Missile 5 to Bullet M5B +missiletobullet missile5dead, spritepos+12, spritepos+13, missile5speed rts ;Linked to MACRO subroutine. : Missile 6 to Bullet M6B +missiletobullet missile6dead, spritepos+14, spritepos+15, missile6speed rts ;this is how we add points to the score ;increment the character at screen ram ;$040b (the last zero digit on screen) ;by one, and then we call a loop, which ;will use the previous five zero digits ;to increment each number after reaching ;the nearest digit (after reaching '9' ;we increment each digit - and so on doscore inc $0409 ;give 100 points to the player ldx #$03 score lda $0406,x cmp #$3a bne setscore lda #$30 sta $0406,x inc $0405,x setscore dex bne score ;this is where we increment the amount ;of missiles that have been shot. if ;100 missiles have not been shot then ;ignore the rest of the process. else ;add 1 to levelct - which will increase ;the playing speed. also increment the ;character at $0427, which is the char ;at the end of the screen. inc missilecounter ;Add 1 to missile counter lda missilecounter ;Check if total number of cmp #50 ;missiles hit = 50 bne stoploop ;NO. Exit missile count routine lda #$00 ;Yes. Reset missile counter sta missilecounter jsr levelsetup ;Setup next level. inc $0427 jsr playlevelupsfx ;Play level up sound effects (Siren) inc levelct ;Increment level counter, and lda levelct ;check if the counter is past 8. cmp #9 ;past level 8? bne stoploop ;no. Exit routine. lda #1 ;game won. reset to level 1 and then sta levelct ;automatically force number 9 on level lda #$38 ;digit to become 8. sta $0427 jmp gameending ;execute game ending. stoploop rts ;missile to ship collision. if missile ;hits the player, make the player lose ;a shield from the ship and replace the ;enemy missile shipcol lda spritepos+$00 ;read player sec ;sprite and sbc #$06 ;calculate sta collision+$04 ;the position - The same way as clc ;we did with the bullet/missile adc #$0c ;collision calculation sta collision+$05 lda spritepos+$01 sec sbc #$0c*2 sta collision+$06 clc adc #$18*2 sta collision+$07 ;generate a fair macro code, in which tests each sprite ;individually for player/missile collision. ;First it tests whether or not the missile is already ;dead (just like the missile to bullet collision). If ;the missile is dead, ignore collision with player. !macro missiletoplayer missiledead, spritex, spritey { lda missiledead ;is the missile already dead? cmp #1 ;yes? ... beq .noplayercollision ;no player collision lda spritex ;read collision of missile x pos cmp collision+$04 ;check collision boundary left bcc .noplayercollision cmp collision+$05 ;check collision boundary right bcs .noplayercollision lda spritey ;read collision of missile y pos cmp collision+$06 ;check collision boundary top bcc .noplayercollision cmp collision+$07 ;check collision boundary bottom bcs .noplayercollision jsr playplayershieldhitsfx ;play player shield hit lda #1 sta missiledead jmp loseshield ;exit macro and make player lose ;a shield .noplayercollision } ;corresponding to the macro up above. jsr m1p ;STATEMENT: Missile 1 to player jsr m2p ;STATEMENT: Missile 2 to player jsr m3p ;STATEMENT: Missile 3 to player jsr m4p ;STATEMENT: Missile 4 to player jsr m5p ;STATEMENT: Missile 5 to player jsr m6p ;STATEMENT: Missile 6 to player rts m1p ;Linked macro for missile 1 to player +missiletoplayer missile1dead, spritepos+4, spritepos+5 rts m2p ;Linked macro for missile 2 to player +missiletoplayer missile2dead, spritepos+6, spritepos+7 rts m3p ;Linked macro for missile 3 to player +missiletoplayer missile3dead, spritepos+8, spritepos+9 rts m4p ;Linked macro for missile 4 to player +missiletoplayer missile4dead, spritepos+10, spritepos+11 rts m5p ;Linked macro for missile 5 to player +missiletoplayer missile5dead, spritepos+12, spritepos+13 rts m6p ;Linked macro for missile 6 to player +missiletoplayer missile6dead, spritepos+14, spritepos+15 rts ;decrement the player's shield. if the ;player has lost all shields, switch on ;game over (where we destroy the player ;ship) to lock other functions. loseshield dec $0419 ;Decrement value of shield. lda $0419 cmp #$30 ;Shield char = $30 (Char 0)? bne stopscol ;No ... game is not over jsr playplayerexplodesfx ;Else play explosion sound effect lda #$01 ;Trigger GAME OVER enabled sta gameover stopscol rts ;depending on whether or not missiles are dead or not ;call a macro to check whether or not a missile is already ;dead. if it is then the missile wont be able to move. ;otherwise allow it to move. each missile's behaviour ;is to be set via a macro code. setmissileproperties !macro missile_properties missiledead, explodedelay, explodepointer, sprframe, missilex, speedx, missiley, speedy, occupiedposition { lda missiledead ;is the missile already dead? cmp #1 ;yes ... bne .missileok ;else continue to missile move code ;otherwise do enemy death animation lda explodedelay cmp #$03 beq .resetexplode inc explodedelay jmp .exit .resetexplode lda #$00 sta explodedelay ldx explodepointer lda expltbl,x sta sprframe inx cpx #8 beq .explodeend inc explodepointer rts .explodeend ;reset explosion for the next enemy death. ldx #0 stx explodepointer lda #0 sta missiley lda #0 sta missiledead jmp .updatemissilex ;the missile is not dead, so we can move the missiles ;according to selected speed from tables. .missileok lda missileframe ;grab animation frame for missile sta sprframe ;store it to selected sprite frame lda missiley ;grab y position of missile sprite clc adc speedy ;move it according to speed counter cmp #$12 ;below position #12 should call a bcs .updatemissiley ;update Y position of missile ;randomizer subroutine to select next X position of missile .newposition jsr random ;position/sprite properties lda ranyspeed ;set random speed from table for y missiles sta speedy lda ranxspeed ;set random speed for x missiles sta speedx .occupytest ldy #$00 .occupyloop lda ranpos cmp xposoccupied,y ;Is position already occupied by another missile? bne .occupynext ;Yes it is ... Else, NO store new position. jsr random jmp .occupytest .occupynext iny cpy #6 bne .occupyloop .updatemissilex sta missilex ;then set new position of sprite sta occupiedposition lda #$12 ;and reset y position of missile .updatemissiley sta missiley ;update new y position of missile .exit } ;end of macro ;seperate properties, to check whether or not a missile has ;been killed otherwise allow it to move. jsr m1props ;Statement: Missile 1 properties ... jsr m2props ;Statement: Missile 2 properties ... jsr m3props ;Statement: Missile 3 properties ... jsr m4props ;Statement: Missile 3 properties ... jsr m5props ;Statement: Missile 4 properties ... jsr m6props ;Statement: Missile 6 properties ... rts m1props ;Linked to macro: Missile 1 properties +missile_properties missile1dead, missile1expdelay, missile1exppointer, $07fa, spritepos+4, missile1speed, spritepos+5, missile1speed+1, xposoccupied rts m2props ;Linked to macro: Missile 2 properties +missile_properties missile2dead, missile2expdelay, missile2exppointer, $07fb, spritepos+6, missile2speed, spritepos+7, missile2speed+1, xposoccupied+1 rts m3props ;Linked to macro: Missile 3 properties +missile_properties missile3dead, missile3expdelay, missile3exppointer, $07fc, spritepos+8, missile3speed, spritepos+9, missile3speed+1, xposoccupied+2 rts m4props ;Linked to macro: Missile 4 properties +missile_properties missile4dead, missile4expdelay, missile4exppointer, $07fd, spritepos+10, missile4speed, spritepos+11, missile4speed+1, xposoccupied+3 rts m5props ;Linked to macro: Missile 5 properties +missile_properties missile5dead, missile5expdelay, missile5exppointer, $07fe, spritepos+12, missile5speed, spritepos+13, missile5speed+1, xposoccupied+4 rts m6props ;Linked to macro: Missile 6 properties +missile_properties missile6dead, missile6expdelay, missile6exppointer, $07ff, spritepos+14, missile6speed, spritepos+15, missile6speed+1, xposoccupied+5 rts ;additional properties for missiles. basically it tests ;the time which the missiles can move, before they can ;change direction. Important, every time the counter ;is switched. The direction of the missile moving should ;also be updated. ;as well as this. The rocking missiles must avoid reaching ;outside the left/right area of the screen, during movement ;so a failsafe code is added to automatically reset the ;movement time and update the new position of the missile. setrockingproperties !macro rockingmissile missiledead, missiletime, direction, missilex, speedx { lda missiledead ;is the missile already destroyed? cmp #1 ;yes ... leave it and then beq .skipxtimer ;exit the code. jsr .readtime ;call subroutine to set time calculation lda direction ;which direction are the missiles moving? cmp #1 ;right? ... beq .moveright ;yes, they are moving right ... else: lda missilex ;code to make individual missile move sec ;to the left. sbc speedx cmp #$0c ;does the missile reach the very left bcs .missileleftok jmp .timeexpired .missileleftok sta missilex ;of the screen? jmp .readtime .moveright lda missilex ;code to make individual missile move clc ;to the right. adc speedx cmp #$a2 ;does the missile reach the end of ;the screen? if so, change direction bcc .missilerightok jmp .timeexpired .missilerightok sta missilex .readtime ;timer code (calculates time, and also lda missiletime ;switches direction the sprites move. cmp #$70 beq .timeexpired inc missiletime jmp .skipxtimer .timeexpired ;missile time reset and direction checked lda #0 sta missiletime lda direction cmp #1 ;direction right? beq .setleft ;yes, right. Switch to LEFT! lda #1 sta direction jmp .skipxtimer .setleft lda #0 sta direction .skipxtimer } ;call the pointers in which control the value of the ;rockers - for some reason without the jsr's the macro ;combined goes really crazy :) ;as a failsafe, add multiple jsrs for the rocking missiles ;code. jsr rocker1 jsr rocker2 jsr rocker3 jsr rocker4 jsr rocker5 jsr rocker6 rts rocker1 +rockingmissile missile1dead, missile1xtime, missile1direction, spritepos+4, missile1speed rts rocker2 +rockingmissile missile2dead, missile2xtime, missile2direction, spritepos+6, missile2speed rts rocker3 +rockingmissile missile3dead, missile3xtime, missile3direction, spritepos+8, missile3speed rts rocker4 +rockingmissile missile4dead, missile4xtime, missile4direction, spritepos+10, missile4speed rts rocker5 +rockingmissile missile5dead, missile5xtime, missile5direction, spritepos+12, missile5speed rts rocker6 +rockingmissile missile6dead, missile6xtime, missile6direction, spritepos+14, missile6speed rts ;sprite animation table setup routine. this will ;set up the animation for the player alive, and ;also the falling missiles. animate lda animdelay1 cmp #2 beq doanimation1 inc animdelay1 rts doanimation1 lda #$00 sta animdelay1 ldx pointer animloop lda misstbl+$00,x sta missileframe lda plrtble+$00,x sta $07f8 inx cpx #7 beq reset inc pointer rts reset ldx #$00 stx pointer rts ;a control loop to read the random ;position table - to make the game more ;interesting :) (that is okay as it is!) random lda ranpos+$00 sta ranpos+$18 lda ranxspeed+$00 sta ranxspeed+$18 lda ranyspeed+$00 sta ranyspeed+$18 ldx #$00 ranloop lda ranpos+$01,x sta ranpos+$00,x lda ranxspeed+$01,x sta ranxspeed+$00,x lda ranyspeed+$01,x sta ranyspeed+$00,x inx cpx #$18 bne ranloop rts ;game is over and the player is dead so ;now we create our own explosion routine ;Explode all missiles as well as player on sight explplr lda animdelay2 cmp #$02 beq allowexplode inc animdelay2 rts allowexplode lda #$00 sta animdelay2 ldx pointer+$01 eloop lda expltbl+$00,x sta $07f8 sta $07f9 sta $07fa sta $07fb sta $07fc sta $07fd sta $07fe sta $07ff lda explodecolour,x ;Flash the screen sta $d020 sta $d021 inx cpx #7 ;max no of frames beq reset3 inc pointer+$01 rts reset3 ldx #$00 stx pointer+$01 ;display the game over text on screen. lda #0 sta $d015 lda #2 ;Set Track 3 - GAME OVER jsr musicinit ldx #$00 setgameovertext lda goline1,x sta $0590,x lda goline2,x sta $0590+80,x lda goline3,x sta $0590+120,x lda goline4,x sta $0590+160,x lda pressfiretext,x sta $0590+280,x lda #2 sta $d990,x lda #1 sta $d990+80,x sta $d990+120,x sta $d990+160,x lda #7 sta $d990+280,x inx cpx #40 bne setgameovertext lda #0 sta firebutton waitfireexit lda $dc00 lsr lsr lsr lsr lsr bit firebutton ror firebutton bmi waitfireexit bvc waitfireexit ;backup the status from title screen ldx #$00 dobackup lda $0400,x sta scorebackup,x inx cpx #40 bne dobackup jmp restart ;game complete text gameending lda #$01 ;End scenario ... sta $d015 ;Make player fly upwards off screen endloop lda #0 sta gamesync cmp gamesync beq *-3 jsr expand ;Expand sprite MSB as before jsr animate ;animate player sprite jsr checkplayerzone ;check X area of player lda spritepos+1 ;Read player Y position sec ;Subtract it by 1 sbc #1 cmp #$12 ;until player reached outside screen bcs notleftscreen jmp addendscreen ;then run the end text screen notleftscreen sta spritepos+1 ;Update y position of player jmp endloop ;Check zone where player is based so we move it to ;the middle of the screen. checkplayerzone lda spritepos ;read player X position cmp #54 ;Middle? ;Is the player at the middle bcc under ;No, it is under. Move X position cmp #54 ;Is the player exactly at middle beq inplace ;Yes. It is in place sec ;Else move the player LEFT, until sbc #1 ;it reaches the middle of the screen inplace lda #$54 ;Fix middle position to player. sta spritepos rts under ;Player position is BELOW #54 clc ;move it to the RIGHT until it adc #1 ;has reached the middle of the screen sta spritepos rts ;Call end screen text routine addendscreen lda #3 ;Track 4 game complete music jsr musicinit ldx #$00 setgamecompletetext lda endline1,x ;Read end text and place it on to sta $0590,x ;the screen. lda endline2,x sta $0590+80,x lda endline3,x sta $0590+120,x lda endline4,x sta $0590+160,x lda pressfiretext,x sta $0590+280,x lda #$05 ;Set colour RAM colours for text sta $d990,x lda #$01 sta $d990+80,x sta $d990+120,x sta $d990+160,x lda #7 sta $d990+280,x inx cpx #40 ;rows of 40 chars. bne setgamecompletetext lda #0 sta $d015 jmp waitfireexit ;Jump directly to the press fire code ;in the GAME OVER screen. ;subroutine that does a colour washing effect over ;the status text at the top of the screen. colroll lda colours+$00 ;Grab first colour from table sta colours+$28 ;Place it to 40th byte on table (To wrap) ldx #$00 col1 lda colours+$01,x ;Move colour table LEFT sta colours+$00,x ;one byte. lda colours+$00,x sta $d800,x ;Store to colour RAM (Over the score panel) inx cpx #$28 bne col1 rts ;pal/ntsc speed check to detect music speed palntsccheck lda $02a6 ;Hardware machine type cmp #$01 ;1 = PAL, 0 = NTSC beq pal ;PAL detected ;Create a slight delay on NTSC machines inc ntscpointer lda ntscpointer cmp #6 beq resetntsc pal jsr musicplay ;Play music rts ;NTSC timer reset resetntsc lda #$00 sta ntscpointer rts ;GOAT TRACKER Sound effects player subroutine ;Play sound effect - Player shooting a laser playplayershootsfx lda #shootsfx ;Hi byte of sound ldx #7 ;Sound channel (2) jsr sfxplay ;Play SFX rts ;Play sound effect - Player exploding playplayerexplodesfx lda #playerexplosionsfx ldx #7 ;middle channel jsr sfxplay rts ;Play sound effect - Missile exploding playmissileexplosionsfx lda #missileexplosionsfx ldx #7 jsr sfxplay rts ;Play sound effect - Level Up playlevelupsfx lda #levelupsfx ldx #14 jsr sfxplay rts ;Play sound effect - Player shield hit playplayershieldhitsfx lda #playerhitsfx ldx #14 jsr sfxplay rts levelpointer !byte 0 ;pointer to indicate whether or not a missile ;has been destroyed or not. if it has been ;destroyed missilexdead is set to 1. missile1dead !byte 0 missile2dead !byte 0 missile3dead !byte 0 missile4dead !byte 0 missile5dead !byte 0 missile6dead !byte 0 ;pointer to indicate x + y ;speed of falling missiles. missile1speed !byte 0,1 missile2speed !byte 0,2 missile3speed !byte 0,1 missile4speed !byte 0,2 missile5speed !byte 0,1 missile6speed !byte 0,2 ;pointer to indicate enemy explosion ;properties. missile1expdelay !byte 0 missile1exppointer !byte 0 missile2expdelay !byte 0 missile2exppointer !byte 0 missile3expdelay !byte 0 missile3exppointer !byte 0 missile4expdelay !byte 0 missile4exppointer !byte 0 missile5expdelay !byte 0 missile5exppointer !byte 0 missile6expdelay !byte 0 missile6exppointer !byte 0 ;missile directions (according to timer) missile1direction !byte 0 missile2direction !byte 0 missile3direction !byte 0 missile4direction !byte 0 missile5direction !byte 0 missile6direction !byte 0 ;missile x movement time missile1xtime !byte 0 missile2xtime !byte 0 missile3xtime !byte 0 missile4xtime !byte 0 missile5xtime !byte 0 missile6xtime !byte 0 missileframe !byte 0 animdelay1 !byte 0 animdelay2 !byte 0 ntscpointer !byte 0 gamesync !byte 0 ;sprite colour table spritecolourtable !byte $03,$07,$0c,$0f,$0c,$0f,$0c,$0f ;colour washing table. colours !byte $06,$06,$02,$02,$04,$04 !byte $05,$05,$03,$03,$07,$07 !byte $01,$01,$07,$07,$03,$03 !byte $05,$05,$04,$04,$02,$02 !byte $06,$06,$06,$06,$06,$06 !byte $06,$06,$06,$06,$06,$06 !byte $06,$06,$06,$06,$06,$06 !byte $06,$06,$06,$06,$06,$06 !byte $06 ;starting position table for the sprites ;before the game commences. postable !byte $58,$e0,$f0,$00,$0c,$30 !byte $32,$40,$5c,$50,$82,$60 !byte $45,$70,$75,$80 ;Explosion colour - for background flashing explodecolour !byte $01,$07,$0a,$08,$02,$09,$00,$00,$00,$00,$00,$00 ;Series of bytes to be read in order to prevent the ;X-position of sprite to be occupied. So that sprites ;selected (during respawn) cannot use the same position. xposoccupied !byte 0,0,0,0,0,0,0 plrtble ;animation table for the player ship !byte $80,$81,$80,$81,$80,$81,$80 ;animation table for rotating missiles ;that are falling through space. misstbl !byte $8a,$8b,$8c,$8d,$8e,$8f,$90 ;explosion animation frame table expltbl !byte $83,$84,$85,$86,$87,$88,$89,$91 ;a small little random table, for ;randomly selecting the position of ;the next sprite x position ranpos !byte $18,$58,$80,$38,$20,$48 !byte $78,$98,$10,$50,$68,$40 !byte $38,$a0,$28,$70,$30,$88 !byte $60,$29,$98,$a0,$48,$70 !byte $40 ;a small little random table, for ;randomly selecting the x-speed of ;the missiles. ranxspeed !byte $00,$00,$00,$00,$00,$00 !byte $00,$00,$00,$00,$00,$00 !byte $00,$00,$00,$00,$00,$00 !byte $00,$00,$00,$00,$00,$00 !byte $00 ranxspeedend ;a small little random table, for ;randomly selecting the y-speed of ;the missiles. ranyspeed !byte $01,$02,$01,$01,$02,$01 !byte $02,$01,$01,$02,$01,$01 !byte $01,$02,$01,$01,$02,$01 !byte $02,$01,$01,$02,$02,$01 !byte $01 ;level random speed tables (to select and copy ;to the game code). ;level 1 - only allow missiles to go downwards ;no x-direction allowed! ;level 1 y table - missiles at speed 1 and 2 only level1xspdtbl !byte $00,$00,$00,$00,$00,$00 !byte $00,$00,$00,$00,$00,$00 !byte $00,$00,$00,$00,$00,$00 !byte $00,$00,$00,$00,$00,$00 !byte $00 level1yspdtbl !byte $01,$02,$01,$01,$02,$01 !byte $02,$01,$01,$02,$01,$01 !byte $01,$02,$01,$01,$02,$01 !byte $02,$01,$01,$02,$02,$01 !byte $01 ;level 2 - fewer missiles can go left/right - missiles ;at speed 1 and 2 only. level2xspdtbl !byte $00,$00,$00,$01,$00,$00 !byte $00,$00,$00,$01,$00,$00 !byte $00,$00,$00,$01,$00,$00 !byte $00,$00,$00,$01,$00,$00 !byte $00 level2yspdtbl !byte $01,$01,$02,$01,$01,$02 !byte $01,$01,$01,$02,$01,$02 !byte $01,$02,$01,$01,$01,$01 !byte $01,$01,$02,$01,$02,$01 !byte $02 ;level 3 - more missiles can go left/right - missiles ;at speed 1 and 2 only - but speed 2 more frequent level3xspdtbl !byte $00,$01,$00,$00,$01,$00 !byte $00,$00,$01,$00,$00,$01 !byte $00,$00,$01,$00,$00,$01 !byte $01,$00,$00,$01,$00,$01 !byte 0 level3yspdtbl !byte $01,$02,$02,$01,$02,$02 !byte $02,$01,$02,$02,$01,$02 !byte $02,$01,$02,$02,$02,$01 !byte $02,$02,$01,$02,$02,$01 !byte $02 ;level 4 - missiles can go left/right, but a faster ;x speed can also be set on this stage. level4xspdtbl !byte $00,$01,$00,$00,$02,$01 !byte $00,$00,$01,$00,$02,$01 !byte $00,$01,$02,$01,$00,$00 !byte $00,$00,$00,$01,$02,$00 !byte $00 level4yspdtbl !byte $02,$01,$01,$02,$01,$02 !byte $02,$01,$02,$01,$02,$01 !byte $02,$02,$01,$01,$02,$01 !byte $02,$01,$01,$02,$01,$02 !byte $00 ;Level 5 - more frequent fast x-speed missiles moving ;in level5xspdtbl !byte $00,$01,$02,$01,$00,$01 !byte $02,$01,$00,$01,$02,$01 !byte $00,$01,$02,$01,$00,$01 !byte $02,$01,$00,$01,$02,$00 !byte $00 level5yspdtbl !byte $01,$02,$02,$02,$01,$02 !byte $02,$02,$02,$01,$02,$02 !byte $02,$01,$02,$02,$02,$01 !byte $01,$02,$02,$02,$01,$02 !byte $02 ;Level 6 - the game gets insanely more tougher ;fast falling missiles as well as moving left/right ;but left/right should be less fast. level6xspdtbl !byte $01,$00,$00,$01,$00,$00 !byte $01,$00,$01,$00,$01,$00 !byte $00,$01,$00,$01,$00,$01 !byte $01,$00,$00,$01,$00,$01 !byte $01 level6yspdtbl !byte $01,$02,$03,$02,$01,$02 !byte $02,$01,$02,$01,$03,$02 !byte $01,$02,$02,$01,$02,$03 !byte $02,$01,$02,$01,$03,$02 !byte $01 ;Level 7 - all missiles, moving different speed, ;including the fast X movement level7xspdtbl !byte $00,$02,$00,$00,$01,$02 !byte $00,$02,$01,$00,$00,$02 !byte $01,$02,$00,$00,$02,$01 !byte $00,$00,$02,$01,$00,$01 !byte $02 level7yspdtbl !byte $02,$03,$01,$02,$03,$02 !byte $03,$02,$01,$03,$02,$03 !byte $02,$01,$03,$02,$03,$01 !byte $01,$02,$03,$02,$01,$03 !byte $03 ;Level 8 - The final showdown, a forth speed level8xspdtbl !byte $02,$01,$02,$01,$02,$02 !byte $01,$02,$01,$02,$01,$01 !byte $01,$02,$02,$01,$02,$01 !byte $02,$01,$02,$02,$01,$02 !byte $02 level8yspdtbl !byte $01,$02,$04,$03,$02,$03 !byte $01,$04,$02,$01,$03,$01 !byte $04,$02,$01,$03,$02,$04 !byte $04,$03,$04,$02,$01,$02 !byte $02 ;Lo/Hi byte table for setting up the game levels levelxtbllo !byte 0 !byte level1xspdtbl !byte >level2xspdtbl !byte >level3xspdtbl !byte >level4xspdtbl !byte >level5xspdtbl !byte >level6xspdtbl !byte >level7xspdtbl !byte >level8xspdtbl levelytbllo !byte 0 !byte level1yspdtbl !byte >level2yspdtbl !byte >level3yspdtbl !byte >level4yspdtbl !byte >level5yspdtbl !byte >level6yspdtbl !byte >level7yspdtbl !byte >level8yspdtbl ;Depending on level set - Screen multicolour values :) mcol1 !byte $0e,$0e,$08,$0a,$05,$0e,$0d,$04,$08 mcol2 !byte $06,$06,$09,$02,$09,$04,$05,$09,$02 ;game over text !ct scr goline1 !text " game over " goline2 !text " you have lost all of your shields. " goline3 !text " your ship has been destroyed, and now " goline4 !text " planet earth has been destroyed! " ;game end text !ct scr endline1 !text " congratulations " endline2 !text " you have blasted enough missiles in " endline3 !text " order to save earth from complete " endline4 !text " destruction. " pressfiretext !text " press fire to continue " scrolltext !text "... welcome to version 2 of - missile " !text "blasta - resmastered - ... programmi" !text "ng, graphics, sound effects and music were all done b" !text "y richard bayliss ... i guess you al" !text "ready knew that :) ... plug a joysti" !text "ck into port 2 ... missiles from out" !text " of space are heading towards planet e" !text "arth ... we have transported a space" !text " craft into deep space, where you, the" !text " pilot must blast 50 giant missiles in each " !text "of the 8 levels ... complete your ta" !text "sk successfully, you will move on to t" !text "he new level ... if you lose all 5 s" !text "hields and your ship is destroyed, wav" !text "e bye, bye to your home planet ... i" !text "f you complete all 8 levels, you will " !text "have saved planet earth ... this is " !text "much better and improved version of th" !text "e third game ... the game consists o" !text "f brand new graphics ... loads of tu" !text "nes ... new game sprites ... also " !text "a slight overhaul of game play, and pr" !text "esentation ... level 1 is pretty muc" !text "h simple, but should you progress on to future le" !text "vels, you will face a real challenge " !text "ahead ... special thank you goes to " !text "simon querhorst for suggesting the imp" !text "rovements ... hopefully although a v" !text "ery simple concept, i hope it is much " !text "better quality, compared to the previo" !text "us version ... special thanks goes t" !text "o subchrist software for the excellent" !text " charpad v2.0 and sprite pad v2.0, whi" !text "ch i used to create the game graphics " !text "and sprites ... to cadaver for goat tracker v2.7 ... " !text " also thank goes to e" !text "ndurion, for the latest version of c64" !text " studio v5.7a - it is a whole lot more" !text " helpful creating macro labels ... t" !text "hank you also goes to zagon, for exomi" !text "zer v3.0 - depack speed is really fast" !text " ... i love it ... and finally a " !text "huge thank you goes out all of you who" !text " either likes this game, downloaded it" !text " or are following and enjoying my asse" !text "mble it programming tutorials ... i " !text "like to do all this for a hobby, not f" !text "or money ... heheheh :) ... okay " !text "i think this about wraps things up ..." !text " so, until next time, it is goodbye fo" !text "r now, and - press fire to start - ..." !text " " !byte 0 scorebackup !bin "bin/status.prg",,2 ;insert the music (,,2 prg) *=$8000 !bin "bin/music.prg",,2 ;goat tracker custom sound effects table ;Sound for player shooting shootsfx !byte $0E,$EE,$00,$CC,$21,$cc,$ca,$c8,$c6,$c4,$c2,$10 !byte $90,$00 ;Sound for player losing a shield playerhitsfx !byte $0A,$AA,$00,$bA,$31,$b8,$b4,$b2,$90,$b8,$b4,$b2,$90,$11,$00 ;Sound for missile explosion missileexplosionsfx !byte $0C,$00,$00,$90,$81,$AC,$21,$AA,$A4,$BF,$81,$AF,$9F,$BF,$AF,$9F !byte $BF,$AF,$90,$00 ;Sound for player explosion playerexplosionsfx !byte $0A,$00,$00,$CC,$81,$AE,$21,$CC,$81,$AC,$21,$CC,$81,$AA,$21,$CC !byte $81,$A8,$21,$CC,$81,$BB,$BB,$BB,$00 ;Sound for level up levelupsfx !byte $0C,$00,$00 !byte $B1,$61,$B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC !byte $BD,$BE,$BF,$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 !byte $B1,$61,$B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC !byte $BD,$BE,$BF,$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 !byte $B1,$61,$B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC !byte $BD,$BE,$BF,$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 !byte $B1,$61,$B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC !byte $BD,$BE,$BF,$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 !byte $90,$11,$00