; DoubleGap by Christopher Cantrell 2006 ;##$CPU none ;##$OriginalBinary gap.bin ;##- ;##Menu 3 "Code" ;##MenuLink RAM "RAM Map" ;##MenuLink Main "Main Loop" ;##MenuLink Kernel "Video Kernel" ;##MenuLink Init "Init" ;##MenuLink InitPlayMode "Init Play Mode" ;##MenuLink PlayMode "Play Mode" ;##MenuLink InitSelectMode "Init Select Mode" ;##MenuLink SelectMode "Select Mode" ;##MenuLink InitGoMode "Init Go Mode" ;##MenuLink GoMode "Go Mode" ;##MenuLink Utils "Utils" ;##MenuLink InitMusic "Init Music" ;##MenuLink ProcessMusic "Process Music" ;##MenuLink GoFX "Go FX" ;##MenuLink MusicCommands "Music Commands" ;##MenuLink SkillValues "Skill Values" ;##MenuLink Images "Images" ;##MenuLink Vectors "6502 Vectors" ;##- ; TO DO ; - Expert switches are backwards ; - Debounce switches ; build-command java Blend gap.asm g2.asm ; build-command tasm -b -65 g2.asm g2.bin ; This file uses the "BLEND" program for assembly pre-processing processor 6502 #include "Stella.asm" ; Equates to give names to hardware memory locations ;##RAM ; RAM usage ; TMP0 .EQU 0x80 ; Temporary storage TMP1 .EQU 0x81 ; Temporary storage TMP2 .EQU 0x82 ; Temporary storage PLAYR0Y .EQU 0x83 ; Player 0's Y location (normal or pro) PLAYR1Y .EQU 0x84 ; Player 1's Y location (normal, pro, or off) MUS_TMP0 .EQU 0x85 ; Game-over mode sound FX storage (frame delay) MUS_TMP1 .EQU 0x86 ; Game-over mode sound FX storage (frequency) SCANCNT .EQU 0x87 ; Scanline counter during screen drawing MODE .EQU 0x88 ; Game mode: 0=GameOver 1=Play 2=Select WALL_INC .EQU 0x89 ; How much to add to wall's Y position WALLCNT .EQU 0x8A ; Number of walls passed (score) WALLDELY .EQU 0x8B ; Wall movement frame skip counter WALLDELYR .EQU 0x8C ; Number of frames to skip between wall increments ENTROPYA .EQU 0x8D ; Incremeneted with every frame ENTROPYB .EQU 0x8E ; SWCHA adds in ENTROPYC .EQU 0x8F ; Left/Right movements added to other entropies DEBOUNCE .EQU 0x90 ; Last state of the Reset/Select switches WALLDRELA .EQU 0x91 ; PF0 pattern for wall WALLDRELB .EQU 0x92 ; PF1 pattern for wall WALLDRELC .EQU 0x93 ; PF2 pattern for wall WALLSTART .EQU 0x94 ; Wall's Y position (scanline) WALLHEI .EQU 0x95 ; Height of wall GAPBITS .EQU 0x96 ; Wall's gap pattern (used to make WALLDRELx) SCORE_PF1 .EQU 0x97 ; 6-bytes. PF1 pattern for each row of the score SCORE_PF2 .EQU 0x9D ; 6-bytes. PF2 pattern for each row of the score MUSADEL .EQU 0xA3 ; Music A delay count MUSAIND .EQU 0xA4 ; Music A pointer MUSAVOL .EQU 0xA5 ; Music A volume MUSBDEL .EQU 0xA6 ; Music B delay count MUSBIND .EQU 0xA7 ; Music B pointer MUSBVOL .EQU 0xA8 ; Music B volume ; Remember, stack builds down from $FF ... leave some space ; ; 80 - A8 ... that's 41 bytes of RAM used .org 0xF000 ;##Main main() { I_Flag = 1 ; Turn off interrupts D_Flag = 0 ; Clear the "decimal" flag X = 0xFF ; Set the stack pointer ... S = X ; ... to the end of RAM INIT() ; Initialize game environment INIT_SELMODE() ; Start out in SELECT-MODE VIDEO_KERNEL() ; There should be no return from the KERNEL } ;##Kernel VIDEO_KERNEL() { ; (start here at the END of every frame) ; while(true) { A = 2 ; D1 bit ON WSYNC = A ; Wait for the end of the current line VBLANK = A ; Turn the electron beam off WSYNC = A ; Wait for all ... WSYNC = A ; ... the electrons ... WSYNC = A ; ... to drain out. VSYNC = A ; Trigger the vertical sync signal WSYNC = A ; Hold the vsync signal for ... WSYNC = A ; ... three ... WSYNC = A ; ... scanlines HMOVE = A ; Tell hardware to move all game objects A = 0 ; D1 bit OFF VSYNC = A ; Release the vertical sync signal A = 43 ; Set timer to 43*64 = 2752 machine ... TIM64T = A ; ... cycles 2752/(228/3) = 36 scanlines ; ***** LENGTHY GAME LOGIC PROCESSING BEGINS HERE ***** ; Do one of 3 routines while the beam travels back to the top ; 0 = Game Over processing ; 1 = Playing-Game processing ; 2 = Selecting-Game processing ++ENTROPYA ; Counting video frames as part of the random number A = MODE ; What are we doing between frames? if(A==0) { GOMODE() ; Game-over processing } else if(A==1) { PLAYMODE() ; Playing-game processing } else { SELMODE() ; Selecting game processing } ; ***** LENGTHY GAME LOGIC PROCESSING ENDS HERE ***** do { A = INTIM ; Wait for the visible area of the screen } while(A!=0); WSYNC = A ; 37th scanline A = 0 ; Turn the ... VBLANK = A ; ... electron beam back on A = 0 ; Zero out ... SCANCNT = A ; ... scanline count ... TMP0 = A ; ... and all ... TMP1 = A ; ... returns ... TMP2 = A ; ... expected ... X = A ; ... to come from ... Y = A ; ... BUILDROW CXCLR = A ; Clear collision detection ; BEGIN VISIBLE PART OF FRAME do { A = TMP0 ; Get A ready (PF0 value) WSYNC = A ; Wait for very start of row GRP0 = X ; Player 0 -- in X GRP1 = Y ; Player 1 -- in Y PF0 = A ; PF0 -- in TMP0 (already in A) A = TMP1 ; PF1 -- in TMP1 PF1 = A ; ... A = TMP2 ; PP2 -- in TMP2 PF2 = A ; ... BUILDROW() ; This MUST take through to the next line ++SCANCNT ; Next scan line A = SCANCNT ; Do 109*2 = 218 lines } while(A!=109) ; END VISIBLE PART OF FRAME A = 0 ; Turning off visuals WSYNC = A ; Next scanline PF0 = A ; Play field 0 off GRP0 = A ; Player 0 off GRP1 = A ; Player 1 off PF1 = A ; Play field 1 off PF2 = A ; Play field 2 off WSYNC = A ; Next scanline } } ; ====================================== BUILDROW() { A = SCANCNT ; Current scanline if(A<6) { ; Top 6 rows are for the score A = A & 7 ; Only need the lower 3 bits Y = A ; Soon to be an index into a list ; At this point, the beam is past the loading of the ; playfield for the left half. We want to make sure ; that the right half of the playfield is off, so do that ; now. X = 0 ; Blank bit pattern TMP0 = X ; This will always be blank PF1 = X ; Turn off playfield ... PF2 = X ; ... for right half of the screen X = A ; Another index A = SCORE_PF1[Y] ; Lookup the PF1 graphics for this row TMP1 = A ; Return it to the caller Y = A ; We'll need this value again in a second A = SCORE_PF2[X] ; Lookup the PF2 graphics for this row TMP2 = A ; Return it to the caller WSYNC = A ; Now on the next row PF1 = Y ; Repeat the left-side playfield ... PF2 = A ; ... onto the new row A = SCORE_PF2[X] ; Kill some time waiting for the ... A = SCORE_PF2[X] ; ... beam to pass the left half ... A = SCORE_PF2[X] ; ... of the playfield again A = SCORE_PF2[X] ; A = SCORE_PF2[X] ; A = SCORE_PF2[X] ; X = 0 ; Return 0 (off) for player 0 ... Y = 0 ; ... and player 1 ; The beam is past the left half of the field again. ; Turn off the playfield. PF1 = X ; 0 to PF1 ... PF2 = X ; ... and PF2 } else { ; Rest of the rows are for the game area A = A &7 ; Lower 3 bits as an index again Y = A ; Using Y to lookup graphics A = GR_PLAYER[Y] ; Get the graphics (if enabled on this row) X = A ; Hold it (for return as player 0) Y = A ; Hold it (for return as player 1) A = SCANCNT ; Scanline count again A>>1 ; This time ... A>>1 ; ... we divide ... A>>1 ; ... by eight (8 rows in picture) if(A!=PLAYR0Y) { X = 0 ; Not time for Player 0 ... no graphics } if(A!=PLAYR1Y) { Y = 0 ; Not time for Player 0 ... no graphics } A = WALLSTART ; Calculate ... A = A + WALLHEI ; ... the bottom of ... TMP0 = A ; ... the wall A = SCANCNT ; Scanline count if(A>=WALLSTART && A=112 if wall is off screen WALLSTART = A ; Store new wall position A = 0 ; Return flag that wall did NOT restart } else { A = 0 ; Else restart ... WALLSTART = A ; ... wall at top of screen A = 1 ; Return flag that wall DID restart } } } ; ====================================== NEW_GAPS() { ; ; This function builds the PF0, PF1, and PF2 graphics for a wall ; with the gap pattern (GAPBITS) placed at random in the 20 bit ; area. ; A = 255 ; Start with ... WALLDRELA = A ; ... solid wall in PF0 ... WALLDRELB = A ; ... and PF1 A = GAPBITS ; Store the gap pattern ... WALLDRELC = A ; ... in PF2 A = ENTROPYA ; Get ... A = A + C_Flag + ENTROPYB ; ... a randomish ... A = A + C_Flag + ENTROPYC ; ... number ... ENTROPYC = A A = A &15 ; ... 0 to 15 if(A>12) { ;A = A - 9 A = A - C_Flag - 9 } while(A!=0) { C_Flag = 1 ; Roll gap ... ROR WALLDRELC ; ... left ... ROL WALLDRELB ; ... desired ... ROR WALLDRELA ; ... times ... A = A - 1 } } ; ====================================== MAKE_SCORE() { ; ; This function builds the PF1 and PF2 graphics rows for ; the byte value passed in A. The current implementation is ; two-digits only ... PF2 is blank. ; X = 0 ; 100's digit Y = 0 ; 10's digit while(A>=100) { ++X ; Count ... A = A - 100 ; ... value } while(A>=10) { ++Y ; Count ... A = A - 10 ; ... value } A<<1 ; One's digit ... A<<1 ; ... *8 .... A<<1 ; ... to find picture X = A ; One's digit picture to X A = Y ; Now the 10's digit A<<1 ; Multiply ... A<<1 ; ... by 8 ... A<<1 ; ... to find picture Y = A ; 10's picture in Y A = DIGITS[Y] ; Get the 10's digit A = A & 0xF0 ; Only use the left side of the picture SCORE_PF1 = A ; Store left side A = DIGITS[X] ; Get the 1's digit A = A & 0x0F ; Only use the right side of the picture A = A | SCORE_PF1 ; Put left and right half together SCORE_PF1 = A ; And store image A = DIGITS+1[Y] ; Repeat for 2nd line of picture A = A & 0xF0 SCORE_PF1[1] = A A = DIGITS+1[X] A = A & 0x0F A = A | SCORE_PF1[1] SCORE_PF1[1] = A A = DIGITS+2[Y] ; Repeat for 3nd line of picture A = A & 0xF0 SCORE_PF1[2] = A A = DIGITS+2[X] A = A & 0x0F A = A | SCORE_PF1[2] SCORE_PF1[2] = A A = DIGITS+3[Y] ; Repeat for 4th line of picture A = A & 0xF0 SCORE_PF1[3] = A A = DIGITS+3[X] A = A & 0x0F A = A | SCORE_PF1[3] SCORE_PF1[3] = A A = DIGITS+4[Y] ; Repeat for 5th line of picture A = A & 0xF0 SCORE_PF1[4] = A A = DIGITS+4[X] A = A & 0x0F A = A | SCORE_PF1[4] SCORE_PF1[4] = A A = 0 ; For now ... SCORE_PF2 = A ; ... there ... SCORE_PF2[1] = A ; ... is ... SCORE_PF2[2] = A ; ... no ... SCORE_PF2[3] = A ; ... 100s ... SCORE_PF2[4] = A ; ... digit drawn } ; ====================================== EXPERTISE() { ; ; This function changes the Y position of the players based on the ; position of their respective pro/novice switches. The player 1 ; position is NOT changed if the mode is a single-player game. ; A = SWCHB ; Pro/novice settings A = A & 0x80 ; Novice for Player 0? if(A==0) { A = 12 ; Novice ... near the bottom } else { A = 8 ; Pro ... near the top } PLAYR0Y = A ; ... to Player 0 X = PLAYR1Y if(X!=255) { ; Only move player 1 if it is a 2-player game A = SWCHB A = A & 0x40 if(A==0) { X = 12 ; Novice ... near the bottom } else { X = 8 ; Pro ... near the top } PLAYR1Y = X } } ; ====================================== ADJUST_DIF() { ; ; This function adjusts the wall game difficulty values based on the ; current score. The music can also change with the difficulty. A single ; table describes the new values and when they take effect. ; X = 0 ; Starting at index 0 while(true) { A = SKILL_VALUES[X] ; Get the score match if(A==255) { return ; End of the table ... leave it alone } if(A==WALLCNT) { ++X ; Copy ... A = SKILL_VALUES[X] ; ... new ... WALL_INC = A ; ... wall increment ++X ; Copy ... A = SKILL_VALUES[X] ; ... new ... WALLDELY = A ; ... wall ... WALLDELYR = A ; ... delay ++X ; Copy ... A = SKILL_VALUES[X] ; ... new ... GAPBITS = A ; ... gap pattern ++X ; Copy ... A = SKILL_VALUES[X] ; ... new ... MUSAIND = A ; ... MusicA index ++X ; Copy ... A = SKILL_VALUES[X] ; ... new ... MUSBIND = A ; ... MusicB index A = 1 ; Force ... MUSADEL = A ; ... music to ... MUSBDEL = A ; ... start new return } ++X ; Move ... ++X ; ... X ... ++X ; ... to ... ++X ; ... next ... ++X ; ... row of ... ++X ; ... table } } ; ====================================== SEL_RESET_CHK() { ; ; This function checks for changes to the reset/select ; switches and debounces the transitions. ; X = DEBOUNCE ; Hold onto old value A = SWCHB ; New value A = A & 3 ; Only need bottom 2 bits if(A==DEBOUNCE) { A = 0 ; Return 0 ... nothing changed } else { DEBOUNCE = A ; Hold new value A = A ^ 0xFF ; Complement the value (active low hardware) A = A & 3 ; Only need select/reset } } ;##InitMusic ; ====================================== INIT_MUSIC() { ; ; This function initializes the hardware and temporaries ; for 2-channel music ; A = 0x06 ; Initialize sound ... AUDC0 = A ; ... to pure ... AUDC1 = A ; ... tones A = 0 ; Turn off ... AUDV0 = A ; ... all ... AUDV1 = A ; ... sound MUSAIND = A ; Music pointers ... MUSBIND = A ; ... to top of data A = 1 ; Force ... MUSADEL = A ; ... music ... MUSBDEL = A ; ... reload A = 15 ; Set volume levels ... MUSAVOL = A ; ... to ... MUSBVOL = A ; ... maximum } ;##ProcessMusic ; ====================================== PROCESS_MUSIC() { ; ; This function is called once per frame to process the ; 2 channel music. Two tables contain the commands/notes ; for individual channels. This function changes the ; notes at the right time. ; --MUSADEL ; Last note ended? if(ZERO_SET) { do { X = MUSAIND ; Voice-A index A = MUSICA[X] ; Get the next music command if(A==0) { ; A==0 for JUMP command ++X ; Point to jump value A = X ; X to ... Y = A ; ... Y (pointer to jump value) ++X ; Point one past jump value A = X ; Into A so we can subtract A = A - MUSICA[Y] ; New index MUSAIND = A ; Store it A = 0 ; Continue processing } else if(A==1) { ; A==1 for CONTROL command ++X ; Point to the control value ++MUSAIND ; Bump the music pointer A = MUSICA[X] ; Get the control value ++MUSAIND ; Bump the music pointer AUDC0 = A ; Store the new control value A = 0 ; Continue processing } else if(A==2) { ; A==2 for VOLUME command ++X ; Point to volume value ++MUSAIND ; Bump the music pointer A = MUSICA[X] ; Get the volume value ++MUSAIND ; Bump the music pointer MUSAVOL=A ; Store the new volume value A = 0 ; Continue processing } } while(A==0); Y = MUSAVOL ; Get the volume A = A & 31 ; Lower 5 bits are frequency if(A==31) { Y = 0 ; Frequency of 31 flags silence } AUDF0 = A ; Store the frequency AUDV0 = Y ; Store the volume A = MUSICA[X] ; Get the note value again ++MUSAIND ; Bump to the next command ROR A ; The upper ... ROR A ; ... three ... ROR A ; ... bits ... ROR A ; ... hold ... ROR A ; ... the ... A = A & 7 ; ... delay C_Flag = 0 ; No accidental carry ROL A ; Every delay tick ... ROL A ; ... is *4 frames MUSADEL = A ; Store the note delay } --MUSBDEL ; Repeat Channel A sequence for Channel B if(ZERO_SET) { do { X = MUSBIND A = MUSICB[X] if(A==0) { ++X A = X Y = A ++X A = X A = A - MUSICB[Y] MUSBIND = A A = 0 } else if(A==1) { ++X ++MUSBIND A = MUSICB[X] ++MUSBIND AUDC1 = A A = 0 } else if(A==2) { ++X ++MUSBIND A = MUSICB[X] ++MUSBIND MUSBVOL = A A = 0 } } while(A==0); Y = MUSBVOL A = A & 31 if(A==31) { Y = 0 } AUDF1 = A AUDV1 = Y A = MUSICB[X] ++MUSBIND ROR A ROR A ROR A ROR A ROR A A = A & 7 C_Flag = 0 ROL A ROL A MUSBDEL = A } } ;##GoFX ; ====================================== INIT_GO_FX() { ; ; This function initializes the hardware and temporaries ; to play the soundeffect of a player hitting the wall ; A = 5 ; Set counter for frame delay ... MUS_TMP1 = A ; ... between frequency change A = 3 ; Tone type ... AUDC0 = A ; ... poly tone A = 15 ; Volume A ... AUDV0 = A ; ... to max A = 0 ; Volume B ... AUDV1 = A ; ... silence A = 240 ; Initial ... MUS_TMP0 = A ; ... sound ... AUDF0 = A ; ... frequency } ; ====================================== PROCESS_GO_FX() { ; ; This function is called once per scanline to play the ; soundeffects of a player hitting the wall. ; --MUS_TMP1 ; Time to change the frequency? if(ZERO_SET) { A = 5 ; Reload ... MUS_TMP1 = A ; ... the frame count ++MUS_TMP0 ; Increment ... A = MUS_TMP0 ; ... the frequency divisor AUDF0 = A ; Change the frequency if(A==0) { A = 1 ; All done ... return 1 return } } A = 0 } ;##MusicCommands ; ====================================== ; Music commands for Channel A and Channel B ; A word on music and wall timing ... ; Wall moves between scanlines 0 and 111 (112 total) ; Wall-increment frames-to-top ; 3 336 ; 2 224 ; 1 112 ; 0.5 56 ; Ah ... but we are getting one less ; Each tick is multiplied by 4 to yield 4 frames per tick ; 32 ticks/song = 32*4 = 128 frames / song ; We want songs to start with wall at top ... ; Find the least-common-multiple ; 336 and 128 : 2688 8 walls, 21 musics ; 224 and 128 : 896 4 walls, 7 musics ; 112 and 128 : 896 8 walls, 7 musics ; 56 and 128 : 896 16 walls, 7 musics ; Wall moving every other gives us 112*2=224 scanlines ; Song and wall are at start every 4 ; 1 scanline, every 8 ; Wall delay=3 gives us 128*3=336 scanlines 2 ; MUSIC EQUATES ; MUSCMD_JUMP .equ 0 MUSCMD_CONTROL .equ 1 MUSCMD_VOLUME .equ 2 MUS_REST .equ 31 MUS_DEL_1 .equ 32*1 MUS_DEL_2 .equ 32*2 MUS_DEL_3 .equ 32*3 MUS_DEL_4 .equ 32*4 MUSICA MA_SONG_1 .BYTE MUSCMD_CONTROL, 0x0C ; Control (pure tone) .BYTE MUSCMD_VOLUME, 15 ; Volume (full) MA1_01 .BYTE MUS_DEL_3 + 15 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_3 + 15 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 7 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 7 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_2 + MUS_REST .BYTE MUS_DEL_1 + 8 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_4 + MUS_REST .BYTE MUS_DEL_2 + 17 .BYTE MUS_DEL_2 + MUS_REST .BYTE MUS_DEL_2 + 17 .BYTE MUS_DEL_2 + MUS_REST .BYTE MUS_DEL_3 + 16 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUSCMD_JUMP, (MA1_END - MA1_01) ; Repeat back to top MA1_END MA_SONG_2 .BYTE MUSCMD_CONTROL, 0x0C .BYTE MUSCMD_VOLUME, 15 MA2_01 .BYTE MUS_DEL_1 + 15 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 15 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_2 + MUS_REST .BYTE MUS_DEL_4 + 7 .BYTE MUS_DEL_4 + MUS_REST .BYTE MUS_DEL_2 + 15 .BYTE MUS_DEL_4 + MUS_REST .BYTE MUS_DEL_2 + 12 .BYTE MUS_DEL_2 + MUS_REST .BYTE MUS_DEL_2 + 15 .BYTE MUS_DEL_2 + MUS_REST .BYTE MUS_DEL_2 + 17 .BYTE MUS_DEL_2 + MUS_REST .BYTE MUSCMD_JUMP, (MA2_END - MA2_01) ; Repeat back to top MA2_END MUSICB MB_SONG_1 .BYTE MUSCMD_CONTROL, 0x08 ; Control (white noise) .BYTE MUSCMD_VOLUME, 8 ; Volume (half) MB1_01 .BYTE MUS_DEL_1 + 10 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 20 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 30 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 15 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 10 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 20 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 30 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 15 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUSCMD_JUMP, (MB1_END - MB1_01) ; Repeat back to top MB1_END MB_SONG_2 .BYTE MUSCMD_CONTROL, 0x08 .BYTE MUSCMD_VOLUME, 8 MB2_01 .BYTE MUS_DEL_1 + 1 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 1 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 1 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 1 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 30 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 30 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 30 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUS_DEL_1 + 30 .BYTE MUS_DEL_1 + MUS_REST .BYTE MUSCMD_JUMP, (MB2_END - MB2_01) ; Repeat back to top MB2_END ;##SkillValues ; ====================================== SKILL_VALUES ; ; This table describes how to change the various ; difficulty parameters as the game progresses. ; For instance, the second entry in the table ; says that when the score is 4, change the values of ; wall-increment to 1, frame-delay to 2, gap-pattern to 0, ; MusicA to 24, and MusicB to 22. ; ; A 255 on the end of the table indicates the end ; ; Wall Inc Delay Gap MA MB .BYTE 0, 1, 3, 0 ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB .BYTE 4, 1, 2, 0 ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB .BYTE 8, 1, 1, 0 ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB .BYTE 16, 1, 1, 1 ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB .BYTE 24, 1, 1, 3 ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB .BYTE 32, 1, 1, 7 ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB .BYTE 40, 1, 1, 15 ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB .BYTE 48, 2, 1, 0 ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB .BYTE 64, 2, 1, 1 ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB .BYTE 80, 2, 1, 3 ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB .BYTE 96 , 2, 1, 7 ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB .BYTE 255 ;##Images ; ====================================== ; Image for players GR_PLAYER: .BYTE 0x10 ; ...*.... .BYTE 0x10 ; ...*.... .BYTE 0x28 ; ..*.*... .BYTE 0x28 ; ..*.*... .BYTE 0x54 ; .*.*.*.. .BYTE 0x54 ; .*.*.*.. .BYTE 0xAA ; *.*.*.*. .BYTE 0x7C ; .*****.. ; ====================================== ; Images for numbers DIGITS: ; We only need 5 rows, but the extra space on the end makes each digit 8 rows, ; which makes it the multiplication easier. .BYTE 0x0E ,0x0A ,0x0A ,0x0A ,0x0E, 0,0,0 ; 00 .BYTE 0x22 ,0x22 ,0x22 ,0x22 ,0x22, 0,0,0 ; 11 .BYTE 0xEE ,0x22 ,0xEE ,0x88 ,0xEE, 0,0,0 ; 22 .BYTE 0xEE ,0x22 ,0x66 ,0x22 ,0xEE, 0,0,0 ; 33 .BYTE 0xAA ,0xAA ,0xEE ,0x22 ,0x22, 0,0,0 ; 44 .BYTE 0xEE ,0x88 ,0xEE ,0x22 ,0xEE, 0,0,0 ; 55 .BYTE 0xEE ,0x88 ,0xEE ,0xAA ,0xEE, 0,0,0 ; 66 .BYTE 0xEE ,0x22 ,0x22 ,0x22 ,0x22, 0,0,0 ; 77 .BYTE 0xEE ,0xAA ,0xEE ,0xAA ,0xEE, 0,0,0 ; 88 .BYTE 0xEE ,0xAA ,0xEE ,0x22 ,0xEE, 0,0,0 ; 99 ;##Vectors ; ====================================== ; 6502 Hardware vectors at the end of memory .org 0xF7FA ; Ghosting to 0xFFFA for 2K part .WORD 0x0000 ; NMI vector (not used) .WORD main ; Reset vector (top of program) .WORD 0x0000 ; IRQ and BRK vector (not used) .end