RasterLine1 = $00 ;Position of raster line 1 RasterLine2 = $79 ;Position of raster line 2 RasterLine3 = $ea ;Position of raster line 3
;Front End
;The main front end routine
.FrontEnd sei ;Set INIT interrupt flags lda #$00 ;Black border and background sta $d020 ;set. sta $d021 sta PageDelay ;Set delay for title screen sta PageDelay+1 ;page flip routine sta PageCounter ;Zero page routines ;Init starting position for the starfield in the title screen ldx #$00 SetPosition lda PosTable,x ;Load X,Y positions for sprites sta ObjPos,x ;store those in virtual sprite position inx ;next one, until 16 bytes is cpx #$10 ;read. bne SetPosition lda #$01 ;Place a dot in blank sprite sta $7bbf ;area at $7bbf to make star. ;Setup the star sprite frames, and set star colours as light blue.
ldx #$00 SetSpriteTypes lda #$ef ;Load value of sprite type sta $7ff8,x ;store it to actual sprite type. lda #$0e ;Light blue sta $d027,x ;Store to sprite colours (all 8) inx cpx #$08 bne SetSpriteTypes lda #$ff ;Switch on all sprites (the title screen stars) sta $d015 ;Store to sprites enabled hardware lda #$00 ;No multicolour sprites required sta $d01c ;Store to sprites multicolour hardware lda #$ff ;All sprites behind background sta $d01b ;Store to sprite/background priorities hardware lda #$00 ;No expanded sprites please. sta $d01d ;Store to expand sprite X sta $d017 ;Store to expand sprite Y ldx #$00 ;Reset colour pointer, using X stx ColourPointer ;Store to self-mod colour pointer lda #$00 ;Destroy existing interrupts. sta $d019 ;Store them to the IRQ vectors sta $d01a lda #$81 ;Switch CIA timer OFF sta $dc0d lda #$36 ;C64 Kernal switched back on sta $01 ;for the timebeing jsr .ClearScreen ;Clear the screen subroutine lda #$02 ;Selfmod fixup somewhere in pic. sta PicPos ;Setup the Front End Logo colour / video DATA (Steps of 40 cols)
ldx #$00 .SetupLogo lda $8000,x ;Where logo colour data is read from sta $d800,x ;then store it to Colour RAM lda $8028,x ;($d800-$dbe8). We just copy the sta $d828,x ;memory from the logo colour + screen lda $8050,x ;data and then paste it in rows on sta $d850,x ;to the main screen. lda $8078,x ; sta $d878,x ;Logo colour RAM: $8000,x lda $80a0,x ;Screen colour RAM: $D800-$DBE8 sta $d8a0,x ; lda $80c8,x ;Logo video RAM $8400,x sta $d8c8,x ;No change to the screen RAM as the lda $80f0,x ;logo video RAM is already stored sta $d8f0,x ;and the raster split (later in this source) lda $8118,x ;will set the CORRECT screen RAM/char RAM value sta $d918,x ;for the logo. lda $8140,x sta $d940,x inx cpx #$28 bne .SetupLogo ;Setup the credits page, by default. Read the text ;data and then store it to the screen row position ;starting from the first column. Read 40 bytes ($28) ;and store. ;Screen RAM in VIC BANK 2 is being used
;A line row = 40 chars
ldx #$00 .PutCreds lda Credits1,x ;Read first line of credits sta $7d68,x ;store it to screen ROW position $7D68,x lda Credits2,x ;Read second line of credits sta $7db8,x ;store it to the next screen ROW position $7DB8 lda Credits3,x ;Read third line of credits sta $7de0,x ;store it to the next screen ROW position ($7de0,x), etc ... lda Credits4,x sta $7e30,x lda Credits5,x sta $7e58,x lda Credits6,x sta $7ea8,x lda Credits7,x sta $7ed0,x lda Credits8,x sta $7f20,x lda Credits9,x sta $7f70,x ;White text ... lda #$01 ;Set colour white on each row where the credits are. sta $d968,x ;store to the colour RAM. sta $d9b8,x sta $d9e0,x sta $da30,x sta $da58,x sta $daa8,x sta $dad0,x sta $db20,x sta $db70,x inx ;Move to the next char on each row. cpx #$28 ;Until last char (40) has been read. bne .PutCreds ;Otherwise just loop back to .PutCreds. ;until the last character on each row ;is complete. ;Initialise the scroll text by storing a low and hi byte of ;ScrollText into the self-mod pointer .MessRead. So that any ;time the title screen restarts, the scroll text does as well.
lda #<ScrollText ;Lo-byte of the scroll text message sta .MessRead+1 ;Store to low byte scroll read memory lda #>ScrollText ;Hi-byte of the scroll text message sta .MessRead+2 ;Store to hi-byte scroll read memory ;Set up / initialise the title screen IRQ raster interrupts. For ;this title screen, there will be multiple interrupts. lda #<.Irq1 ;Low byte of interrupt IRQ1 sta $0314 ;Store to kernal IRQ low-byte read lda #>.Irq1 ;Hi byte of interrupt IRQ sta $0315 ;Store to kernal IRQ hi-byte read lda #$7f ;CIA interrupt set sta $dc0d ;Store CIA interrupt sta $dd0d ;and enable it lda #$00 ;Starting raster position sta $d012 ;Store raster position lda #$1b ;Screen on sta $d011 ;Store screen on lda #$01 ;ACK IRQ vector sta $d01a ;Store SYNC IRQ vector lda #$01 ;Title music value jsr MusicInit ;Initialise title music player lda #0 ;Initialise fire on both joysticks sta FirePort1 ;Init joystick port 1 fire button sta FirePort2 ;Init joystick port 2 fire button lda #3 sta $7bdf sta $7bff cli ;Synchronize timer ... and front end loop .FrontEndLoop lda #$00 ;Interrupt sets 1 to the Sync timer, if sta Sync ;the Sync timer = 0 then it should not synchronize cmp Sync ;the subroutines below until it reads the timer in the interrupt beq *-3 ;Some subroutines to do various infinite tricks unless ;the fire button has been pressed to start the game. jsr .SpriteField ;Subroutine to move the star sprites jsr .DoScroll ;Scrolltext subroutine jsr .ColourScroll ;Colour washing subroutine jsr .CheckSoundOption ;Sound option check subroutine jsr .SetPages ;Page flipping subroutine lda $dc00 ;Check for joystick port 2 lsr ;up lsr ;down lsr ;left bcs .CheckRight1 ;not left jsr .SetAsMusic ;Set music option jmp .FireButton1 ;Test fire .CheckRight1 lsr ;right bcs .FireButton1b ;not right jsr .SetAsSfx ;Set sound effects option .FireButton1b jmp .FireButton1 ;jump to check fire button subroutine
;Sound option must be set as either music or in game sound effects ;0 = music ;1 = sfx
;Set music option .SetAsMusic lda #$00 ;Value 0 = in game music sta SoundOption ;Store to the sound option pointer rts ;Set sfx option .SetAsSfx lda #$01 ;Value 1 = sound effects sta SoundOption ;Store to the sound option pointer rts ;Check sound option to see whether or not music or sound effects ;should be forced into the SEUCK game code? .CheckSoundOption lda SoundOption ;Load SoundOption pointer cmp #$00 ;Check for music beq .MusicOnly ;Yes, can only play music cmp #$01 ;Check for sound effects beq .SFXOnly ;Yes, can only play sfx rts ;Force music only by changing low/hi bytes of SoundPlayer, by ;replacing the SFX pointers with the low/hi bytes of music play pointers
.MusicOnly lda #$2c ;BIT out the SFX SID sta $5c0d ;registers. This is a very cheap sta $5c10 ;and most simplest way in order sta $5c13 ;to have just in game music, uninterrupted sta $5c18 ;by the SEUCK sfx. It is extremely difficult to sta $5c24 ;mix actual SEUCK sfx with in game music sta $5c27 ;That is why many SEUCK games I enhanced have sta $5c2a ;either just SFX or in game music. sta $5c2f sta $5c52 sta $5c55 sta $5c58 lda #<MusicPlay ;Set lowbyte of MusicPlay (into A) ldx #>MusicPlay ;and hibyte of MusicPlay (into X) sta .SoundPlayer+1 ;Store low byte (into A) stx .SoundPlayer+2 ;Store hi byte (into X) ;Place characters 'MUSIC' on to the screen ldx #$00 .PutMusicText lda OptionMusic,x ;Read label 'Music' and then sta $7f39,x ;store it to the title screen inx cpx #$06 ;read 6 chars bne .PutMusicText ;Loop if not 6th char read rts .SFXOnly ; sta $dbe7 lda #$8d ;LOAD in all sound fx sta $5c0d ;pointers, so that in sta $5c10 ;game music is enabled. sta $5c13 sta $5c24 sta $5c27 sta $5c2a lda #$9d sta $5c2f sta $5c52 sta $5c55 sta $5c58 lda #<$5c94 ;SEUCK SFX player low-byte ldx #>$5c94 ;SEUCK SFX player hi-byte sta .SoundPlayer+1 ;Store to low-byte of the sound player subroutine stx .SoundPlayer+2 ;Store to hi-byte of the sound player subroutine ;Place SFX option text on to the title screen ldx #$00 .PutSFXText lda OptionSfx,x ;read label OptionSfx sta $7f39,x ;Store to screen. inx cpx #$06 ;read 6 chars bne .PutSFXText ;loop if not 6th char read. rts ;Wait for fire button in joystick ;port 2 to be pressed ... .FireButton1 lda $dc00 lsr ;command UP lsr ;command DOWN lsr ;command LEFT lsr ;command RIGHT lsr ;command FIRE bit FirePort2 ;Avoid fire from being HELD ror FirePort2 ;Avoid fire from being HELD bmi .CheckJoy1 ;Ignore fire bvc .CheckJoy1 ;----------- jmp .GetReady ;Run GET READY screen jmp .FrontEndLoop ;Otherwise continue ;the main loop inside ;the title screen. ;Or maybe wait for fire button in ;joystick port 1 to be pressed ... ;(Just like above) .CheckJoy1 lda $dc01 lsr lsr lsr lsr lsr bit FirePort1 ror FirePort1 bmi .FrontEndLoop2 bvc .FrontEndLoop2 jmp .GetReady .FrontEndLoop2 jmp .FrontEndLoop
;Switch off all of the interrupts, reset amount of ;generators to be destroyed (Zero the GeneratorsToDestroy ;counter). Reset the fire button on the joystick .GetReady sei lda #$00 ;Switch off interrupts $D019 + $D01A .ClearRAM sta $d019 ;and also all sprites sta $d01a sta $d015 sta GeneratorsToDestroy ;Init amount of generators to destroy sta GeneratorsDestroyed ;Init amount of generators destroyed sta FirePort1 ;Refresh fire button in joystick port 1 sta FirePort2 ;Refresh fire button in joystick port 2 lda #$1b ;Screen on sta $d011 lda #$81 ;CIA interrupt disabled sta $dc0d lda #$02 ;VIC2 BANK #2 sta $dd00 ;Store VIC2 Bank lda #$1b ;Screen ON sta $d011 lda #$fe ;Charset SET to display text charset. sta $d018 lda #$08 ;No multicolour set. sta $d016 jsr .ClearScreen ;Clear the screen ;Display the GET READY text. Simply by reading ;each line of 40 characters from GetReadyText1,x etc... ;then storing it to the chosen screen ROW in VIC2 BANK 2 ; ldx #$00 .PutGetReady lda GetReadyText1,x ;Read line 1 of the Get Ready Text sta $7d90,x ;Store to screen ROW $7d90,x lda GetReadyText2,x ;... You might know the rest of this sta $7de0,x ;it is basically the same, but different lda GetReadyText3,x ;screen address. :) sta $7e30,x inx ;Move to next char cpx #$28 ;check 40 chars read per row bne .PutGetReady ;if not loop back to .PutGetReady ;Setup the interrupts (IRQ4) for thye Get Ready screen. IRQ 4 is ;a single IRQ. lda #<.Irq4 ;Read low-byte of single IRQ (.Irq4) sta $0314 ;store to read low-byte IRQ pointer lda #>.Irq4 ;Read hi-byte of single IRQ (.Irq4) sta $0315 ;store to read hi-byte IRQ pointer lda #$7f ;Enable CIA interrupt sta $dc0d ;Store CIA interrupt A sta $dd0d ;and B lda #$1b ;Screen switched on, char mode sta $d011 lda #$00 ;Initialised raster position sta $d012 ;store raster position lda #$01 ;Enable IRQ sta $d01a ;store it lda #$02 ;Initialise sub tune (Get Ready tune) jsr MusicInit cli .GetReadyLoop lda #0 ;Sync loop (as before) sta Sync cmp Sync beq *-3 jsr .FlashGetReady ;Call subroutine to flash text ;Wait for fire button response lda $dc00 lsr lsr lsr lsr lsr bit FirePort2 ror FirePort2 bmi .H2 bvc .H2 jmp .SetUpGame ;Set up the game defaults .H2 lda $dc01 lsr lsr lsr lsr lsr bit FirePort1 ror FirePort1 bmi .GetReadyLoop bvc .GetReadyLoop ;Setup the game defaults before the main game is ;activated with the new enhancements. .SetUpGame lda #$00 ;In game music jsr MusicInit ;Zero fill the SID chip so for a split second ;no sounds play, while setting up other routines. ldx #$00 KillM lda #$00 sta $d400,x inx cpx #$18 bne KillM ;Initialise the linked explosion timer lda #0 sta ExplodeTimer ;Initialise player start positions. Note player 2 ;MUST be linked to player 1 to make a 2 sprite space ship. jmp .InitPlayerStartPositions
;Game over subroutine. Init everything as ;before for Get Ready screen. .GameOver sei lda #$00 ;Disable IRQs sta $d019 sta $d01a sta FirePort1 ;Init joystick button press sta FirePort2 sta $d015 ;No sprites lda #$1b ;Screen on sta $d011 lda #$81 ;Disable interrupt sta $dc0d lda #$36 ;Switch KERNAL back on sta $01 lda #$02 ;Set VIC2 bank as 2 sta $dd00 lda #$1b ;Screen on sta $d011 lda #$fe ;Set text charset $7800-$8000 and screen $7c00-$7fe8 sta $d018 ;NOTE if charset is more than 3 blocks on disk, the screen will ;overwrite the second half. lda #$08 sta $d016 ;Disable screen multicolour jsr .ClearScreen ;Call subroutine to clear the screen ;Please refer to the GET READY screen subroutine. ;\/ ldx #$00 .PutGameOver lda GameOverText1,x sta $7d90,x lda GameOverText2,x sta $7de0,x lda GameOverText3,x sta $7e30,x inx cpx #$28 bne .PutGameOver ;Initialise single IRQ interrupt for Game over screen. lda #<.Irq4 sta $0314 lda #>.Irq4 sta $0315 lda #$7f sta $dc0d sta $dd0d lda #$1b sta $d011 lda #$00 sta $d012 lda #$01 sta $d01a lda #$03 ;Initialise Game Over subtune jsr MusicInit cli ;Sync timer again .GameOverLoop lda #0 sta Sync cmp Sync beq *-3 jsr .FlashGetReady ;Exactly the same type of sub routine for flash ;game over. Recreated. ;Read joystick in port 2, and check for firebutton ;(as done before). lda $dc00 lsr lsr lsr lsr lsr bit FirePort2 ror FirePort2 bmi .H3 bvc .H3 jmp .HiScoreCheck ;Same for joystick port 1 .H3 lda $dc01 lsr lsr lsr lsr lsr bit FirePort1 ror FirePort1 bmi .GameOverLoop bvc .GameOverLoop jmp .HiScoreCheck ;Interrupt 1 - The smooth scroll text mesage
.Irq1 lda $d019 and #1 sta $d019 lda #$29 sta $d012 ldx #$0a ;Time it out a little dex bne *-1 ;Setup the lower raster colour bar. And also ;time it. ldx #$00 .SetRasterColours1 ldy RasTime2,x ;read raster timing table to Y nop ;delay a bit dey ;decrement delay bne *-1 lda RasterCol2,x ;read colour table sta $d020 ;Store to VIC2 border colour sta $d021 ;and VIC2 background colour inx ;until read 8 bytes from the cpx #$08 ;table. Otherwise loop. bne .SetRasterColours1 ldx #0 ;Last raster set to black, in stx $d021 ;the value of X of border and stx $d020 ;background colour. lda #$01 ;VIC2 BANK set to #$01 for bitmap sta $dd00 lda #$18 ;VIC2 charset / screen at BANK 1 ($8400-$87e8) sta $d018 lda #$3b ;VIC2 Screen set to bitmap sta $d011 lda #$18 ;VIC2 charset multicolour ON sta $d016 lda #<.Irq2 ;Call low byte of next IRQ sta $0314 ;Store to Kernal IRQ vector low byte lda #>.Irq2 ;Call hi byte of next IRQ sta $0315 ;Store to Kernal IRQ vector hi byte lda #1 ;Enable Sync timer sta Sync jsr MusicPlay ;Play the music jmp $ea7e ;Infinite interrupt loop (Use this instead of JMP $EA31). ;Interrupt 2 - The logo displayer .Irq2 lda $d019 and #$01 sta $d019 lda #RasterLine2 ;Setup next raster line sta $d012 ;and store it. ldx #$0a ;Time out the raster line dex bne *-1 ldx #$00 .SetRasterColours2 ldy RasTime1,x ;Read the RasTime1 table for the upper raster nop ;Delay it dey bne *-1 lda RasterCol1,x ;Read the colour table for the upper raster sta $d020 ;Store it to Border and Background colour sta $d021 ;inside the raster split, until repeated 8 inx ;Times. cpx #$08 bne .SetRasterColours2 nop ;More timing bunf ... nop nop nop nop nop nop nop nop nop nop nop nop nop nop ldx #0 ;Black border and background colour stx $d021 ;stored to X. stx $d020 lda #$01 ;VIC Bank 1 for bitmap sta $dd00 lda #$3b ;Bitmap mode enabled sta $d011 lda #$18 ;Set Bitmap screen ($A000-$BF70) although not a full bitmap sta $d018 lda #$18 ;Screen multicolour enabled. sta $d016 ;lda #3 ;sta $d020 lda #<.Irq3 ;Set low-byte of next raster interrupt sta $0314 ;Store IRQ low byte lda #>.Irq3 ;Set hi-byte of next raster interrupt sta $0315 ;Store IRQ hi byte jmp $ea7e ;Loop interrupt ;Interrupt 3 - The static text displayer
.Irq3 lda $d019 and #$01 sta $d019 lda #$ea ;End position for static text displayer sta $d012 lda #$02 ;VIC2 Bank #2 set sta $dd00 lda #$1b ;Normal screen mode / Bitmap disabled sta $d011 lda #$fe ;Set and display font ($7800-$8000) in raster sta $d018 lda #$08 ;Disable screen multicolour sta $d016 ;lda #$4 ;sta $d020 lda #<.Irq4a ;Call next IRQ low-byte sta $0314 ;Store to low byte interrupt lda #>.Irq4a ;Call next IRQ hi-byte sta $0315 ;Store to hi byte interrupt jmp $ea7e ;Loop .Irq4a lda $d019 and #$01 sta $d019 lda #$fa ;Set end position of scroll text raster sta $d012 lda #<.Irq1 ;Call low-byte of first IRQ sta $0314 ;Store to low-byte interrupt lda #>.Irq1 ;Call hi-byte of first IRQ sta $0315 ;Store to hi-byte interrupt lda xpos ;Load in pointer XPOS into HSP sta $d016 ;store to HSP / Screen Horizonal Position to form ;a smooth scroll. jmp $ea7e ;Infinite IRQ loop. ;Single IRQ ... This will only enable synchronized timer ;and play music. Suitable for Get Ready, Game Over, End ;text and Hi-Score table .name entry routines. .Irq4 lda $d019 and #$01 sta $d019 lda #$fa sta $d012 lda #$01 sta Sync jsr MusicPlay jmp $ea7e ;Clear screen - MEMORY $7c00-$7fe8 ;This is always required as a JSR statement, to reduce the amount ;of code where possible.
.ClearScreen ldx #$00 .ClearLoop lda #$20 ;Read spacebar character sta $7c00,x ;Store it 256 timers in sta $7d00,x ;each location on screen. sta $7e00,x sta $7ee8,x inx bne .ClearLoop rts ;Scrolling text subroutine. .DoScroll lda xpos ;Read pointer xpos sec ; sbc #$02 ;Subtract it by 2 to get the speed. and #$07 ;Only allow values $00-$07 for HSP sta xpos ;Store HSP value for smooth scroll delay bcs .EndScroll ;Else exit to .EndScroll and terminate. ;This next bit will pull the next char column to the previous one, giving ;it a scroll effect with the text. (Marquee trick) ldx #$00 .MoveScroll lda $7fc1,x ;Fetch next char in current row to the end sta $7fc0,x ;Store it to the previous char in current row behind inx ;Read next char cpx #40 ;Do it 40 times else bne .MoveScroll ;loop to .MoveScroll ;Check scroll text address / value .MessRead lda ScrollText ;read value of scroll text address from self-mod label cmp #$00 ;If value 00 (@ char) is not detected, then move on to bne .StoreCharacter ;subroutine .StoreCharacter. lda #<ScrollText ;Initialise the low-byte of the scroll text sta .MessRead+1 ;Store to self-mod value of the message read subroutine lda #>ScrollText ;Initialise the hi-byte of the scroll text sta .MessRead+2 ;Store to self-mod value of the message read subroutine jmp .MessRead ;Now wrapped text, jump back to .MessRead and read again. .StoreCharacter sta $7fe7 ;Store letter/symbol to the last column in the char's row inc .MessRead+1 ;Add 1 to the selfmod low-byte addr of .MessRead, bne .EndScroll ;not exceeded $ff inc .MessRead+2 ;Add 1 to the selfmod hi-byte addr of .MessRead .EndScroll rts ;Scroll routine finished.
;Subroutine for colour washing and scrolling, flashing, etc. This creates ;a flashing effect, inside the colour pointer. Reads a table from a ;loop and then stores the colour from the table into the ColourStore byte. ;In order to get the colours on to the screen to flash, the .ColourScroll ;subroutine should be called using JSR .ColourScroll, and then ;another subroutine to place the colour scroll on to the actual char screen colour. .ColourScroll ldx ColourPointer ;Read byte value of ColourPointer in X loop lda ColourTable,x ;Read byte from ColourTable sta ColourStore ;Store it to byte ColourStore inx ;Move to next byte on table until cpx #$70 ;Until 112 bytes of colours are read beq .ResetColourPointer ;If so, jump .ResetColourPointer inc ColourPointer ;Otherwise store next byte value in ColourPointer jsr .FillScreen ;Call colour washing to char subroutine rts ;Exit subroutine .ResetColourPointer ldx #$00 ;Zero the byte ColourPointer so that the stx ColourPointer ;colour table gets read from the start again. rts ;This next sub routine will fill the screen colour data ;first by plotting a byte of the colours, and then ;calling a loop to constantly wash the colours over the ;existing text. .FillScreen lda ColourStore ;Read byte ColourStore sta $d968+39 ;Place byte at last char at row $D968 sta $d9b8 ;Place byte at first char at row $D9B8 sta $d9e0+39 ;Place byte at last char at row $D9E0 sta $da30 ;Place byte at first char at row $DA30 sta $da58+39 ;Place byte at last char at row $DA58 sta $daa8 ;Place byte at first char at row $DAA8 sta $dad0+39 ;Place byte at last char at row $DAD0 sta $db20 ;Place byte at first char at row $DB20 sta $db70+39 ;Place byte at last char at row $DB70 sta $dbc0 ;Place byte at first char at row $DBC0 jsr .ColScrollForward ;Call subroutine to move colour chars forwards jsr .ColScrollBackward ;Call subroutine to move colour chars backwards rts ;Exit ;Subroutine which moves coloured chars forwards. .ColScrollForward ldx #$27 ;Set starting value of X to 39 (We are moving backwards this time) .ColScrLoop1 lda $d9b7,x ;Fetch all chars from colour char row-1 sta $d9b8,x ;Store all chars to char row +0. lda $da2f,x ; sta $da30,x ;Same procedure follows for the rest of the chars lda $daa7,x ; sta $daa8,x ; lda $db1f,x ; sta $db20,x ; dex ;Decrement value of X, to lower value until X=0 bne .ColScrLoop1 ;Otherwise continue the moving each colour char until reached 0 rts ;Exit ;Now scroll the colours of selected rows backwards. .ColScrollBackward ldx #$00 ;Set X loop pointer as zero .ColScrLoop2 lda $d969,x ;Read one char after the first char in current row sta $d968,x ;Store to previous char, to give the washing effect. lda $d9e1,x ; sta $d9e0,x ;Same procedure follows for the rest of the chars lda $da59,x sta $da58,x lda $dad1,x sta $dad0,x lda $db71,x sta $db70,x lda ColourStore ;Instead of colour was, use ColourStore for flashing row $DBC0 sta $dbc0,x inx ;Increment next char cpx #$28 ;until it reaches 40 characters. Otherwise bne .ColScrLoop2;Loop back to .ColScrLoop2 and do the next char rts ;Done ... ;The get Ready Screen uses colour flashing instead of colour ;rolling. A similar method is used, to the loop above, apart ;from no colours get move across the character. Instead the ;variable FlashStore - FlashStore+2 is stored to the char colours. .FlashGetReady jsr .FlashMain ;Call subroutine .FlashMain (Used for Get Ready + Game Over)
ldx #$00 ;X=0 - Starting amount of colours to read .PutGetReadyColours lda FlashStore ;Read byte FlashStore sta $d990,x ;Store it to the current chosen char row lda FlashStore+1 ;Read the next byte of FlashStore sta $d9e0,x ;Store it to the next chosen char row lda FlashStore+2 ;Read the next byte of FlashStore sta $da30,x ;Store it to the next chosen char row inx ;Move on to the next colour cpx #40 ;Has the colour reached 40 chars? bne .PutGetReadyColours ;Keep repeating until it has rts ;Exit ;A new flash routine for Get Ready+Game Over ... I think you may have already ;noticed what this will do. .FlashMain ldx FlashPointer ;Read set value of X-Loop FlashPointer lda FlashTable1,x ;Read bytes from FlashTable1 sta FlashStore ;Store to byte FlashStore lda FlashTable2,x ;Read bytes from FlashTable2 sta FlashStore+1 ;Store to next byte of FlashStore lda FlashTable3,x ;Read bytes from FlashTable3 sta FlashStore+2 ;Store to next byte of FlashStore lda FlashTable4,x ;Read bytes from FlashTable4 sta FlashStore+3 ;Store to next byte of FlashStore inx ;Increment the value of byte FlashPointer cpx #16 ;If 16 colours are read from the table beq .ResetFlash ;Jump to the subroutine .ResetFlash (To zero the FlashPointer) inc FlashPointer ;Otherwise increment to next value of loop FlashPointer rts ;Exit ;Reset FlashPointer .ResetFlash ldx #$00 ;Set value to 0 stx FlashPointer ;Store to X-loop FlashPointer rts ;TITLE SCREEN - Page flipping subroutine. This will first ;read the delay value before checking which page ;should be displayed on the title screen. Should it be ;credits or Hi-score table? ;Page delay subroutine ... .SetPages lda PageDelay ;Read byte PageDelay cmp #$ca ;Delay value expired? beq DelayEnd ;Yes, go to subroutine DelayEnd inc PageDelay ;No, increment byte PageDelay by 1 rts ;then exit from subroutine. ;Delay of the first part of the delay has ;expired. So now call subroutine DelayEnd in ;order to call another delay to make the delay ;of the page flipping last longer. DelayEnd lda #$00 ;Reset first byte of PageDelay byte setting 0 sta PageDelay ;to it. lda PageDelay+1 ;Now do the same trick with the next byte of PageDelay cmp #$02 ;Delay value expired beq DelayEnd2 ;YES, move to the next subroutine DelayEnd2 inc PageDelay+1 ;Otherwise increment the second byte of PageDelay rts ;and return from subroutine. ;Delays all have expired. Reset the second byte of PageDelay ;and then test the page counter, to see which page the title ;screen should flip to. DelayEnd2 lda #0 ;Zero second byte of PageDelay sta PageDelay+1 inc PageCounter ;Increment value of page counter. lda PageCounter ;Read PageCounter cmp #$01 ;If PageCounter = 1 beq .Page2 ;call subroutine .Page2 cmp #$02 ;If PageCounter = 2 beq .Page1 ;call subroutine .Page1 rts ;Exit ;Page 2 subroutine - Jump to subroutine .AddHiScores. ;This displays the hi-score table. .Page2 jmp .AddHiScores .Page1 ;Page 1 subroutine - zero's byte PageCounter and then ;jumps to subroutine .AddCredits, which will display the ;game credits. lda #$00 ;Set Zero byte PageCounter sta PageCounter ;Store to byte PageCounter jmp .AddCredits ;Jump to subroutine .AddCredits rts .AddCredits ;Display credits on to the screen (You should already ;know the text display routine. No explanation necessary. ldx #$00 .PutCreds2 lda Credits1,x sta $7d68,x lda Credits2,x sta $7db8,x lda Credits3,x sta $7de0,x lda Credits4,x sta $7e30,x lda Credits5,x sta $7e58,x lda Credits6,x sta $7ea8,x lda Credits7,x sta $7ed0,x inx cpx #$28 bne .PutCreds2 rts ;Show hi-score table on to the screen. .AddHiScores ldx #$00 .PutHis lda Hi1,x sta $7d68,x lda Hi2,x sta $7db8,x lda Hi3,x sta $7de0,x lda Hi4,x sta $7e30,x lda Hi5,x sta $7e58,x lda Hi6,x sta $7ea8,x lda Hi7,x sta $7ed0,x inx cpx #$28 bne .PutHis rts
;Star sprites subroutine .SpriteField jsr .Expand ;Call subroutine to expand X-MSB sprite position ldx #$00 ; MoveObject lda ObjPos+$00,x;Read all X-position of sprites using GhostBytes sec ; sbc ObjSpeed,x ;Subtract position by the value of speed (going backwards) sta ObjPos+$00,x;Store back new X-Position to sprites using GhostBytes inx ; inx ;Increment byte twice, and move on to next sprite cpx #$10 ;Until 16 sprites GhostBytes have been counted. bne MoveObject ;Otherwise return to loop MoveObject rts ;Read sprite GhostBytes and then store these positions to the ;actual hardware. Expand the area for X-Position so that the ;sprites can use the WHOLE screen area, rather than 2 thirds ;of the screen. .Expand ldx #$00 ;Read pointer value X .ExpandLoop lda ObjPos+$01,x ;Read sprite Y-position from GhostByte table ObjPos (1,3,5,7,9,11,13,15) sta $D001,x ;Store it to the hardware sprite position Y lda ObjPos+$00,x ;Read sprite X-position from GhostByte table ObjPos (0,2,4,6,8,10,12,14) asl ;multiply area size ror $d010 ;rotate sprite MSB to the right sta $d000,x ;Store it to the hardware sprite position X inx ;Increment pointer value X twice inx ; cpx #$10 ;Until 16 bytes read in total (2x8) bne .ExpandLoop ;otherwise loop back to .ExpandLoop rts ;Import source hi-score table + name entry routines !source "hiscore.asm"
;Default starting sprite position tables for the moving star sprites. PosTable !byte $20,$80,$60,$98,$a0,$b0,$40,$c8,$c0,$88,$00,$a8,$e0,$c0,$80,$d8,$00
;GhostByte position self-mod table for storing the 8 star sprites ObjPos !byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;Speed table (X+Y) for sprites ObjSpeed !byte 1,0,3,0,2,0,4,0,3,0,1,0,2,0,4,0,0
xpos !byte $00 ;$D016 Scroll control counter
PageDelay !byte $00,$00 ;Self mod delay pointers for page flipping on title screen PageCounter !byte $00,$00 ;Page counter for page flipping on title screen PicPos !byte $00 FirePort1 !byte $00 ;Control for firebutton on joystick port 1 FirePort2 !byte $00 ;Control for firebutton on joysstick port 2 OptionType !byte $00 ;Game options
Credits !ct scr Credits1 !text " #2014-2016 the new dimension " Credits2 !text " game design, graphics and ideas by " Credits3 !text " richard bayliss and alf yngve " Credits4 !text " logo bitmap artwork drawn by " Credits5 !text " johan 'jsl' janssen " Credits6 !text " front end, enhancements and music by " Credits7 !text " richard bayliss " Credits8 !text " current option: " OptionText !text " " Credits9 !text " press -fire- to start your mission " HiScores !ct scr Hi1 !text " today's leaders of the dark force " Hi2 !text " -- 1 -- " Hi3 !text " " Name1 !text "alf yngve ............... " HiScore1 !text "014000 " Hi4 !text " -- 2 -- " Hi5 !text " " Name2 !text "richard b ............... " HiScore2 !text "007200 " Hi6 !text " -- 3 -- " Hi7 !text " " Name3 !text "jsl ............... " HiScore3 !text "005000 "
OptionMusic !text "music " ;Text for music option OptionSfx !text " sfx " ;Text for sfx option SoundOption !byte 0 ;Sound option pointer ColourPointer !byte 0 ;Colour pointer counter ColourStore !byte 0,0,0,0,0 ;4-byte storing for flashing colours FlashPointer !byte 0 ;Colour pointer counter FlashStore !byte 0,0,0,0 ;4-byte storing for flashing colours
RasterCol1 !byte $09,$02,$08,$0a,$07,$01,$00,$00 ;Colour table for the top raster colour bar RasterCol2 !byte $00,$01,$07,$0a,$08,$02,$09,$00 ;Colour table for the bottom raster colour bar
RasTime1 !byte $01,$08,$08,$08,$08,$08,$08,$08 ;Timing table for top raster colour bar RasTime2 !byte $01,$08,$08,$08,$08,$08,$08,$08 ;Timing table for bottom raster colour bar
FlashTable1 !byte $00,$0b,$09,$02,$08,$0a,$0f,$07 ;Colour table for flashing sequence 1 !byte $01,$07,$0f,$0a,$08,$02,$09,$00 ;GET READY + GAME OVER FlashTable2 !byte $0b,$09,$02,$08,$0a,$0f,$07 ;Colour table for flashing sequence 2 !byte $01,$07,$0f,$0a,$08,$02,$09,$00,$00 ;GET READY + GAME OVER FlashTable3 !byte $09,$02,$08,$0a,$0f,$07 ;Colour table for flashing sequence 3 !byte $01,$07,$0f,$0a,$08,$02,$09,$00,$00,$0b ;GET READY + GAME OVER
FlashTable4 !byte $02,$08,$0a,$0f,$07 ;Colour table for flashing sequence 4 !byte $01,$07,$0f,$0a,$08,$02,$09,$00,$00,$0b,$09 ;GET READY + GAME OVER ColourTable ;Colour table for the title screen colour-wash routine !byte $01,$01,$01,$01,$07,$0f,$0a,$08,$02,$09,$0b,$00,$0b,$09,$02,$08 !byte $0a,$07,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 !byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01 |