Skip to content

Latest commit

 

History

History
1208 lines (1017 loc) · 55.8 KB

Code.md

File metadata and controls

1208 lines (1017 loc) · 55.8 KB

Double Gap

Double Gap

cpu 6502

memoryTable hard Hardware Info

This is the listing file from the assembler. TODO Make the listing file the same as the other disassembly files so it web-ifies nicely.

TODO include the assembly input file(s) in the nav list. TODO disassemble the output in the usual way. I have the raw ASM file here if needed.

; RAM Usage
.TMP0      = 128
.TMP1      = 129
.TMP2      = 130
.PLAYR0Y   = 131
.PLAYR1Y   = 132
.MUS_TMP0  = 133
.MUS_TMP1  = 134
.SCANCNT   = 135
.MODE      = 136
.WALL_INC  = 137
.WALLCNT   = 138
.WALLDELY  = 139
.WALLDELYR = 140
.ENTROPYA  = 141
.ENTROPYB  = 142
.ENTROPYC  = 143
.DEBOUNCE  = 144
.WALLDRELA = 145
.WALLDRELB = 146
.WALLDRELC = 147
.WALLSTART = 148
.WALLHEI   = 149
.GAPBITS   = 150
.SCORE_PF1 = 151
.SCORE_PF2 = 157
.MUSADEL   = 163
.MUSAIND   = 164
.MUSAVOL   = 165
.MUSBDEL   = 166
.MUSBIND   = 167
.MUSBVOL   = 168

F000:
main:
F000: 78           SEI                       ; Turn off interrupts
F001: D8           CLD                       ; Clear the "decimal" flag
F002: A2 FF        LDX      #0xFF            ; Set stack ...
F004: 9A           TXS                       ; ... to the end of RAM
F005: 20 07 F1     JSR      INIT             ; Initialize game environment
F008: 20 DB F1     JSR      INIT_SELMODE     ; Start out in SELECT-MODE

VIDEO_KERNEL:

F00B: A9 02        LDA      #2               ; D1 bit ON
F00D: 85 02        STA      WSYNC            ; Wait for the end of the current line
F00F: 85 01        STA      VBLANK           ; Turn the electron beam off
F011: 85 02        STA      WSYNC            ; Wait for all ...
F013: 85 02        STA      WSYNC            ; ... the electrons ...
F015: 85 02        STA      WSYNC            ; ... to drain out.
F017: 85 00        STA      VSYNC            ; Trigger the vertical sync signal
F019: 85 02        STA      WSYNC            ; Hold the vsync signal for ...
F01B: 85 02        STA      WSYNC            ; ... three ...
F01D: 85 02        STA      WSYNC            ; ... scanlines
F01F: 85 2A        STA      HMOVE            ; Tell hardware to move all game objects
F021: A9 00        LDA      #0               ; D1 bit OFF
F023: 85 00        STA      VSYNC            ; Release the vertical sync signal
F025: A9 2B        LDA      #43              ; Set timer to 43*64 = 2752 machine ...
F027: 8D 96 02     STA      TIM64T           ; ... 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

F02A: E6 8D        INC      ENTROPYA         ; Counting video frames as part of the random number
F02C: A5 88        LDA      MODE             ; What are we doing between frames?

F02E: C9 00        CMP      #0               ; Mode is ...
F030: F0 10        BEQ      DoGameOverMode   ; ... "game over"
F032: C9 01        CMP      #1               ; Mode is ...
F034: F0 06        BEQ      DoPlayMode       ; ... "game play"
F036: 20 EA F1     JSR      SELMODE          ; Mode is "select game"
F039: 4C 45 F0     JMP      DrawFrame        ; Continue to the visible screen area

DoPlayMode:
F03C: 20 64 F1     JSR      PLAYMODE         ; Playing-game processing
F03F: 4C 45 F0     JMP      DrawFrame        ; Continue to the visible screen area

DoGameOverMode:
F042: 20 43 F2     JSR      GOMODE           ; Game-over processing

    ;  ***** LENGTHY GAME LOGIC PROCESSING ENDS HERE *****

DrawFrame:
F045: AD 84 02     LDA      INTIM            ; Wait for ...
F048: C9 00        CMP      #0               ; ... the visible area ...
F04A: D0 F9        BNE      DrawFrame        ; ... of the screen

F04C: 85 02        STA      WSYNC            ; 37th scanline
F04E: A9 00        LDA      #0               ; Turn the ...
F050: 85 01        STA      VBLANK           ; ... electron beam back on

F052: A9 00        LDA      #0               ; Zero out ...
F054: 85 87        STA      SCANCNT          ; ... scanline count ...
F056: 85 80        STA      TMP0             ; ... and all ...
F058: 85 81        STA      TMP1             ; ... returns ...
F05A: 85 82        STA      TMP2             ; ... expected ...
F05C: AA           TAX                       ; ... to come from ...
F05D: A8           TAY                       ; ... BUILDROW

F05E: 85 2C        STA      CXCLR            ; Clear collision detection

DrawVisibleRows:

F060: A5 80        LDA      TMP0             ; Get A ready (PF0 value)
F062: 85 02        STA      WSYNC            ; Wait for very start of row
F064: 86 1B        STX      GRP0             ; Player 0 -- in X
F066: 84 1C        STY      GRP1             ; Player 1 -- in Y
F068: 85 0D        STA      PF0              ; PF0      -- in TMP0 (already in A)
F06A: A5 81        LDA      TMP1             ; PF1      -- in TMP1
F06C: 85 0E        STA      PF1              ; ...
F06E: A5 82        LDA      TMP2             ; PP2      -- in TMP2
F070: 85 0F        STA      PF2              ; ...

F072: 20 90 F0     JSR      BUILDROW         ; This MUST take through to the next line

F075: E6 87        INC      SCANCNT          ; Next scan line
F077: A5 87        LDA      SCANCNT          ; Do 109*2 = 218 lines
F079: C9 6D        CMP      #109             ; All done?
F07B: D0 E3        BNE      DrawVisibleRows  ; No ... get all the visible rows

    ;  END VISIBLE PART OF FRAME

F07D: A9 00        LDA      #0               ; Turn off electron beam
F07F: 85 02        STA      WSYNC            ; Next scanline
F081: 85 0D        STA      PF0              ; Play field 0 off
F083: 85 1B        STA      GRP0             ; Player 0 off
F085: 85 1C        STA      GRP1             ; Player 1 off
F087: 85 0E        STA      PF1              ; Play field 1 off
F089: 85 0F        STA      PF2              ; Play field 2 off
F08B: 85 02        STA      WSYNC            ; Next scanline

F08D: 4C 0B F0     JMP      VIDEO_KERNEL

BUILDROW:

F090: A5 87        LDA      SCANCNT          ; Where are we on the screen?

F092: C9 06        CMP      #6               ; If we are in the ...
F094: 90 40        BCC      ShowScore        ; ... score area

F096: 29 07        AND      #7               ; Lower 3 bits as an index again
F098: A8           TAY                       ; Using Y to lookup graphics
F099: B9 3C F5     LDA      GR_PLAYER,Y      ; Get the graphics (if enabled on this row)
F09C: AA           TAX                       ; Hold it (for return as player 0)
F09D: A8           TAY                       ; Hold it (for return as player 1)
F09E: A5 87        LDA      SCANCNT          ; Scanline count again
F0A0: 4A           LSR      A                ; This time ...
F0A1: 4A           LSR      A                ; ... we divide ...
F0A2: 4A           LSR      A                ; ... by eight (8 rows in picture)

F0A3: C5 83        CMP      PLAYR0Y          ; Scanline group of the P0 object?
F0A5: F0 02        BEQ      ShowP0           ; Yes ... keep the picture
F0A7: A2 00        LDX      #0               ; Not time for Player 0 ... no graphics
ShowP0:

F0A9: C5 84        CMP      PLAYR1Y          ; Scanline group of the P1 object?
F0AB: F0 02        BEQ      ShowP1           ; Yes ... keep the picture
F0AD: A0 00        LDY      #0               ; Not time for Player 0 ... no graphics
ShowP1:

F0AF: A5 94        LDA      WALLSTART        ; Calculate ...
F0B1: 18           CLC                       ; ... the bottom ...
F0B2: 65 95        ADC      WALLHEI          ; ... of ...
F0B4: 85 80        STA      TMP0             ; ... the wall

F0B6: A5 87        LDA      SCANCNT          ; Scanline count

F0B8: C5 94        CMP      WALLSTART        ; Past upper part of wall?
F0BA: 90 11        BCC      NoWall           ; No ... skip it
F0BC: C5 80        CMP      TMP0             ; Past lower part of wall
F0BE: B0 0D        BCS      NoWall           ; Yes ... skip it

    ;  The wall is on this row
F0C0: A5 91        LDA      WALLDRELA        ; Draw wall ...
F0C2: 85 80        STA      TMP0             ; ... by transfering ...
F0C4: A5 92        LDA      WALLDRELB        ; ... playfield ...
F0C6: 85 81        STA      TMP1             ; ... patterns ...
F0C8: A5 93        LDA      WALLDRELC        ; ... to ...
F0CA: 85 82        STA      TMP2             ; ... return area
F0CC: 60           RTS                       ; Done

NoWall:
    ;  The wall is NOT on this row
F0CD: A9 00        LDA      #0               ; No walls on this row
F0CF: 85 80        STA      TMP0             ; ... clear ...
F0D1: 85 81        STA      TMP1             ; ... out ...
F0D3: 85 82        STA      TMP2             ; ... the playfield
F0D5: 60           RTS                       ; Done

ShowScore:
F0D6: 29 07        AND      #7               ; OLine=182  Only need the lower 3 bits
F0D8: A8           TAY                       ; OLine=183  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.

F0D9: A2 00        LDX      #0               ; Blank bit pattern
F0DB: 86 80        STX      TMP0             ; This will always be blank
F0DD: 86 0E        STX      PF1              ; Turn off playfield ...
F0DF: 86 0F        STX      PF2              ; ... for right half of the screen

F0E1: AA           TAX                       ; Another index
F0E2: B9 97 00     LDA      SCORE_PF1,Y      ; Lookup the PF1 graphics for this row
F0E5: 85 81        STA      TMP1             ; Return it to the caller
F0E7: A8           TAY                       ; We'll need this value again in a second
F0E8: B5 9D        LDA      SCORE_PF2,X      ; Lookup the PF2 graphics for this row
F0EA: 85 82        STA      TMP2             ; Return it to the caller

F0EC: 85 02        STA      WSYNC            ; Now on the next row

F0EE: 84 0E        STY      PF1              ; Repeat the left-side playfield ...
F0F0: 85 0F        STA      PF2              ; ... onto the new row

F0F2: B5 9D        LDA      SCORE_PF2,X      ; Kill some time waiting for the ...
F0F4: B5 9D        LDA      SCORE_PF2,X      ; ... beam to pass the left half ...
F0F6: B5 9D        LDA      SCORE_PF2,X      ; ... of the playfield again
F0F8: B5 9D        LDA      SCORE_PF2,X      ; ...
F0FA: B5 9D        LDA      SCORE_PF2,X      ; ...
F0FC: B5 9D        LDA      SCORE_PF2,X      ; ...

F0FE: A2 00        LDX      #0               ; Return 0 (off) for player 0 ...
F100: A0 00        LDY      #0               ; ... and player 1

    ;  The beam is past the left half of the field again.
    ;  Turn off the playfield.

F102: 86 0E        STX      PF1              ; 0 to PF1 ...
F104: 86 0F        STX      PF2              ; ... and PF2
F106: 60           RTS                       ;  Done

INIT:
    ;  This function is called ONCE at power-up/reset to initialize various
    ;  game settings and variables.
                                           
F107: A9 40        LDA      #64              ; Wall is ...
F109: 85 08        STA      COLUPF           ; ... redish
F10B: A9 7E        LDA      #126             ; P0 is ...
F10D: 85 06        STA      COLUP0           ; ... white
F10F: A9 00        LDA      #0               ; P1 ...
F111: 85 07        STA      COLUP1           ; ... black
                                           
F113: A9 05        LDA      #5               ; Right half of playfield is reflection of left ...
F115: 85 0A        STA      CTRLPF           ; ... and playfield is on top of players

    ; TODO other hardware inits here
                                           
F117: A2 04        LDX      #4               ; Player 0 position count
F119: A0 03        LDY      #3               ; Player 1 position count
F11B: 85 02        STA      WSYNC            ; Get a fresh scanline
                                           
TimeP0Pos:
F11D: CA           DEX                       ; Kill time while the beam moves ...
F11E: E0 00        CPX      #0               ; ... to desired ...
F120: D0 FB        BNE      TimeP0Pos        ; ... position
F122: 85 10        STA      RESP0            ; Mark player 0's X position
                                           
TimeP1Pos:
F124: 88           DEY                       ; Kill time while the beam moves ...
F125: C0 00        CPY      #0               ; ... to desired ...
F127: D0 FB        BNE      TimeP1Pos        ; ... position
F129: 85 11        STA      RESP1            ; Mark player 1's X position

F12B: 20 1D F3     JSR      EXPERTISE        ; Initialize the players' Y positions base on expert-settings
                                           
F12E: A9 0A        LDA      #10              ; Wall is ...
F130: 85 95        STA      WALLHEI          ; ... 10 double-scanlines high
                                           
F132: A9 00        LDA      #0               ; Set score to ...
F134: 85 8A        STA      WALLCNT          ; ... 0
F136: 20 9D F2     JSR      MAKE_SCORE       ; Blank the score digits
F139: A9 00        LDA      #0               ; Blank bits ...
F13B: 85 A2        STA      SCORE_PF2+5      ; ... on the end of each ...
F13D: 85 9C        STA      SCORE_PF1+5      ; ... digit pattern
                                           
F13F: 20 48 F3     JSR      ADJUST_DIF       ; Initialize the wall parameters
F142: 20 6F F2     JSR      NEW_GAPS         ; Build the wall's initial gap
                                           
F145: A9 70        LDA      #112             ; Set wall position off bottom ...
F147: 85 94        STA      WALLSTART        ; ... to force a restart on first move
                                           
F149: A9 00        LDA      #0               ; Zero out ...
F14B: 85 20        STA      HMP0             ; ... player 0 motion ...
F14D: 85 21        STA      HMP1             ; ... and player 1 motion
                                           
F14F: 60           RTS                       ; Done

INIT_PLAYMODE:

    ;  This function initializes the game play mode

F150: A9 C0        LDA      #192             ; Background is ...
F152: 85 09        STA      COLUBK           ; ... greenish
F154: A9 01        LDA      #1               ; Game mode is ...
F156: 85 88        STA      MODE             ; ... SELECT
F158: A9 FF        LDA      #255             ; Restart wall score to ...
F15A: 85 8A        STA      WALLCNT          ; ... 0 on first move
F15C: A9 70        LDA      #112             ; Force wall to start ...
F15E: 85 94        STA      WALLSTART        ; ... over on first move
F160: 20 9B F3     JSR      INIT_MUSIC       ; Initialize the music
F163: 60           RTS                       ; Done

PLAYMODE:

    ;  This function is called once per frame to process the main game play.


F164: 20 86 F3     JSR      SEL_RESET_CHK    ; Check to see if Reset/Select has changed

F167: C9 00        CMP      #0               ; Is select pressed?
F169: F0 06        BEQ      NoSelect         ; No ... skip
F16B: 86 90        STX      DEBOUNCE         ; Restore the old value ...
F16D: 20 DB F1     JSR      INIT_SELMODE     ; ... and let select-mode process the toggle
F170: 60           RTS                       ; Done

NoSelect:
F171: 20 B8 F3     JSR      PROCESS_MUSIC    ; Process any playing music
F174: 20 4E F2     JSR      MOVE_WALLS       ; Move the walls

F177: C9 01        CMP      #1               ; Wall on first row?
F179: D0 0D        BNE      NoFirst          ; No ... move on
F17B: E6 8A        INC      WALLCNT          ; Bump the score
F17D: 20 48 F3     JSR      ADJUST_DIF       ; Change the wall parameters based on score
F180: A5 8A        LDA      WALLCNT          ; Change the ...
F182: 20 9D F2     JSR      MAKE_SCORE       ; ... score pattern
F185: 20 6F F2     JSR      NEW_GAPS         ; Calculate the new gap position

NoFirst:
F188: A5 02         LDA      CXP0FB          ; Player 0 collision with playfield
F18A: 85 80         STA      TMP0            ; Hold it
F18C: A5 03         LDA      CXP1FB          ; Player 1 collision with playfield
F18E: 05 80         ORA      TMP0            ; Did either ...
F190: 29 80         AND      #128            ; ... player hit ...
F192: C9 00         CMP      #0              ; ... wall?
F194: F0 04         BEQ      NoHit           ; No ... move on
F196: 20 17 F2      JSR      INIT_GOMODE     ; Go to Game-Over mode
F199: 60            RTS                      ; Done

NoHit:
F19A: AD 80 02      LDA      SWCHA           ; Joystick
F19D: 29 80         AND      #128            ; Player 0 ...
F19F: C9 00         CMP      #0              ; ... moving left?
F1A1: F0 13         BEQ      MoveP0Left      ; Yes ... move left
F1A3: AD 80 02      LDA      SWCHA           ; Joystick
F1A6: 29 40         AND      #64             ; Player 0 ...
F1A8: C9 00         CMP      #0              ; ... moving right?
F1AA: F0 05         BEQ      MoveP0Right     ; Yes ... move right
F1AC: A9 00         LDA      #0              ; Not moving value
F1AE: 4C B8 F1      JMP      SetMoveP0       ; Don't move the player
MoveP0Right:
F1B1: A9 10         LDA      #16             ; +1
F1B3: 4C B8 F1      JMP      SetMoveP0       ; Set HMP0
MoveP0Left:
F1B6: A9 F0         LDA      #240            ; -1
SetMoveP0:
F1B8: 85 20         STA      HMP0            ; New movement value P0

F1BA: AD 80 02      LDA      SWCHA           ; Joystick
F1BD: 29 08         AND      #8              ; Player 1 ...
F1BF: C9 00         CMP      #0              ; ... moving left?
F1C1: F0 13         BEQ      MoveP1Left      ; Yes ... move left
F1C3: AD 80 02      LDA      SWCHA           ; Joystick
F1C6: 29 04         AND      #4              ; Player 0 ...
F1C8: C9 00         CMP      #0              ; ... moving right?
F1CA: F0 05         BEQ      MoveP1Right     ; Yes ... move right
F1CC: A9 00         LDA      #0              ; Not moving value
F1CE: 4C D8 F1      JMP      SetMoveP1       ; Don't move the player
MoveP1Right:
F1D1: A9 10         LDA      #16             ; +1
F1D3: 4C D8 F1      JMP      SetMoveP1       ; Set HMP0
MoveP1Left:
F1D6: A9 F0         LDA      #240            ; -1
SetMoveP1:
F1D8: 85 21         STA      HMP1            ; New movement value P1

F1DA: 60            RTS                      ; Done

INIT_SELMODE:

     ;  This function initializes the games SELECT-MODE

F1DB: A9 00         LDA      #0              ; Turn off ...
F1DD: 85 19         STA      AUDV0           ; ... all ...
F1DF: 85 1A         STA      AUDV1           ; ... sound
F1E1: A9 C8         LDA      #200            ; Background ...
F1E3: 85 09         STA      COLUBK          ; ... greenish bright
F1E5: A9 02         LDA      #2              ; Now in ...
F1E7: 85 88         STA      MODE            ; SELECT game mode
F1E9: 60            RTS                      ; Done


SELMODE:

     ;  This function is called once per frame to process the SELECT-MODE.
     ;  The wall moves here, but doesn't change or collide with players.
     ;  This function selects between 1 and 2 player game.

F1EA: 20 4E F2      JSR      MOVE_WALLS       ; Move the walls
F1ED: 20 86 F3      JSR      SEL_RESET_CHK    ; Check the reset/select switches
F1F0: C9 01         CMP      #1               ; RESET button?
F1F2: F0 1C         BEQ      SelStartGame     ; Yes ... start game
F1F4: C9 03         CMP      #3               ; RESET and SELECT?
F1F6: F0 18         BEQ      SelStartGame     ; Yes ... start game
F1F8: C9 02         CMP      #2               ; Select only?
F1FA: D0 17         BNE      SelExp           ; No ... stay in this mode
F1FC: A5 84         LDA      PLAYR1Y          ; Select toggled. Get player 1 Y coordinate
F1FE: C9 FF         CMP      #255             ; 2nd player on the screen?
F200: F0 07         BEQ      SelP1On          ; No ... toggle it on
F202: A9 FF         LDA      #255             ; Yes ...
F204: 85 84         STA      PLAYR1Y          ; ... toggle it off
F206: 4C 13 F2      JMP      SelExp           ; Move to expertise
SelP1On:
F209: A9 0C         LDA      #12              ; Y coordinate
F20B: 85 84         STA      PLAYR1Y          ; On screen now
F20D: 4C 13 F2      JMP      SelExp           ; Move to expertise

SelStartGame:
F210: 20 50 F1      JSR      INIT_PLAYMODE    ; Reset toggled ... start game
SelExp:
F213: 20 1D F3      JSR      EXPERTISE        ; Adjust both players for pro settings
F216: 60            RTS                       ; Done

INIT_GOMODE:

     ;  This function initializes the GAME-OVER game mode.

F217: 85 2B         STA      HMCLR            ; Stop both players from moving
F219: A5 02         LDA      CXP0FB           ; P0 collision ...
F21B: 29 80         AND      #128             ; ... with wall
F21D: C9 00         CMP      #0               ; Did P0 hit the wall?
F21F: D0 04         BNE      GoCheckP1        ; Yes ... leave it at bottom
F221: A9 02         LDA      #2               ; No ... move player 0 ...
F223: 85 83         STA      PLAYR0Y          ; ... up the screen to show win

GoCheckP1:
F225: A5 03         LDA      CXP1FB           ; P1 collision ...
F227: 29 80         AND      #128             ; ... with wall
F229: C9 00         CMP      #0               ; Did P1 hit the wall?
F22B: D0 0A         BNE      GoP1Hit          ; Yes ... leave it at the bottom
F22D: A5 84         LDA      PLAYR1Y          ; Is P1 even ...
F22F: C9 FF         CMP      #255             ; ... on the screen (2 player game?)
F231: F0 04         BEQ      GoP1Hit          ; No ... skip it
F233: A9 02         LDA      #2               ; Player 1 is onscreen and didn't collide ...
F235: 85 84         STA      PLAYR1Y          ; ... move up the screen to show win

GoP1Hit:
F237: A9 00         LDA      #0               ; Going to ...
F239: 85 88         STA      MODE             ; ... game-over mode
F23B: 85 19         STA      AUDV0            ; Turn off any ...
F23D: 85 1A         STA      AUDV1            ; ... sound
F23F: 20 71 F4      JSR      INIT_GO_FX       ; Initialize sound effects
F242: 60            RTS                       ; Done

GOMODE:

     ; This function is called every frame to process the game
     ; over sequence. When the sound effect has finished, the
     ; game switches to select mode.

F243: 20 88 F4      JSR      PROCESS_GO_FX    ; Process the sound effects
F246: C9 00         CMP      #0               ; Effects still running?
F248: F0 03         BEQ      GoKeepGoing      ; Yes ... let them run
F24A: 20 DB F1      JSR      INIT_SELMODE     ; When effect is over, go to select mode
GoKeepGoing:
F24D: 60            RTS                       ; Done

MOVE_WALLS:

     ;  This function moves the wall down the screen and back to position 0
     ;  when it reaches (or passes) 112.

F24E: C6 8B         DEC      WALLDELY         ; Wall motion timer
F250: A5 8B         LDA      WALLDELY         ; Time to ...
F252: C9 00         CMP      #0               ; ... move the wall?
F254: D0 16         BNE      WallDone         ; No ... leave it alone
F256: A5 8C         LDA      WALLDELYR        ; Reset the ...
F258: 85 8B         STA      WALLDELY         ; ... delay count
F25A: A5 94         LDA      WALLSTART        ; Current wall position
F25C: 18            CLC                       ; Increment ...
F25D: 65 89         ADC      WALL_INC         ; ... wall position
F25F: C9 70         CMP      #112             ; At the bottom?
F261: 90 07         BCC      WallOK           ; No ... leave it alone
F263: A9 00         LDA      #0               ; Else restart ...
F265: 85 94         STA      WALLSTART        ; ... wall at top of screen
F267: A9 01         LDA      #1               ; Return flag that wall DID restart
F269: 60            RTS                       ; Done
WallOK:
F26A: 85 94         STA      WALLSTART        ; Store new wall position
WallDone:
F26C: A9 00         LDA      #0               ; Return flag that wall did NOT restart
F26E: 60            RTS                       ; Done


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.

F26F: A9 FF         LDA      #255             ; Start with ...
F271: 85 91         STA      WALLDRELA        ; ... solid wall in PF0 ...
F273: 85 92         STA      WALLDRELB        ; ... and PF1
F275: A5 96         LDA      GAPBITS          ; Store the gap pattern ...
F277: 85 93         STA      WALLDRELC        ; ... in PF2

F279: A5 8D         LDA      ENTROPYA         ; Get ...
F27B: 65 8E         ADC      ENTROPYB         ; ... a randomish ...
F27D: 65 8F         ADC      ENTROPYC         ; ... number ...
F27F: 85 8F         STA      ENTROPYC         ; Update the random seed
F281: 29 0F         AND      #15              ; 0 to 15
F283: C9 0C         CMP      #12              ; Too far to the right?
F285: F0 04         BEQ      GapOK            ; No ... 12 is OK
F287: 90 02         BCC      GapOK            ; No ... less than 12 is OK
F289: E9 09         SBC      #9               ; Back up 9

GapOK:
F28B: C9 00         CMP      #0               ; Gap already at far left?
F28D: F0 0D         BEQ      GapDone          ; Yes ... done
F28F: 38            SEC                       ; Roll gap ...
F290: 66 93         ROR      WALLDRELC        ; ... left ...
F292: 26 92         ROL      WALLDRELB        ; ... desired ...
F294: 66 91         ROR      WALLDRELA        ; ... times ...
F296: 38            SEC                       ; All rolls ...
F297: E9 01         SBC      #1               ; ... done?
F299: 4C 8B F2      JMP      GapOK            ; No ... do them all
GapDone:
F29C: 60            RTS                       ; New wall pattern is ready

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.

F29D: A2 00         LDX      #0               ; 100's digit
F29F: A0 00         LDY      #0               ; 10's digit

Count100s:
F2A1: C9 64         CMP      #100             ; Need another 100s digit?
F2A3: 90 07         BCC      Count10s         ; No ... move on to 10s
F2A5: E8            INX                       ; Count ...
F2A6: 38            SEC                       ; ... value
F2A7: E9 64         SBC      #100             ; Take off this 100
F2A9: 4C A1 F2      JMP      Count100s        ; Keep counting
Count10s:
F2AC: C9 0A         CMP      #10              ; Need another 10s digit?
F2AE: 90 07         BCC      CountDone        ; No ... got all the tens
F2B0: C8            INY                       ; Count ...
F2B1: 38            SEC                       ; ... value
F2B2: E9 0A         SBC      #10              ; Take off this 10
F2B4: 4C AC F2      JMP      Count10s         ; Keep counting

CountDone:
F2B7: 0A            ASL      A                ; One's digit ...
F2B8: 0A            ASL      A                ; ... *8 ....
F2B9: 0A            ASL      A                ; ... to find picture
F2BA: AA            TAX                       ; One's digit picture to X
F2BB: 98            TYA                       ; Now the 10's digit
F2BC: 0A            ASL      A                ; Multiply ...
F2BD: 0A            ASL      A                ; ... by 8 ...
F2BE: 0A            ASL      A                ; ... to find picture
F2BF: A8            TAY                       ; 10's picture in Y

F2C0: B9 44 F5      LDA      DIGITS,Y         ; Get the 10's digit
F2C3: 29 F0         AND      #0xF0            ; Upper nibble
F2C5: 85 97         STA      SCORE_PF1        ; Store left side
F2C7: BD 44 F5      LDA      DIGITS,X         ; Get the 1's digit
F2CA: 29 0F         AND      #0x0F            ; Lower nibble
F2CC: 05 97         ORA      SCORE_PF1        ; Put left and right half together
F2CE: 85 97         STA      SCORE_PF1        ; And store image

     ; We have plenty of code space. Time and registers are at a premium.
     ; So copy/past the code for each row

F2D0: B9 45 F5      LDA      DIGITS+1,Y       ; Repeat for 2nd line of picture ...
F2D3: 29 F0         AND      #0xF0            ; ...
F2D5: 85 98         STA      SCORE_PF1+1      ; ...
F2D7: BD 45 F5      LDA      DIGITS+1,X       ; ...
F2DA: 29 0F         AND      #15              ; ...
F2DC: 05 98         ORA      SCORE_PF1+1      ; ...
F2DE: 85 98         STA      SCORE_PF1+1      ; ...

F2E0: B9 46 F5      LDA      DIGITS+2,Y       ; Repeat for 3nd line of picture
F2E3: 29 F0         AND      #0xF0            ; ...
F2E5: 85 99         STA      SCORE_PF1+2      ; ...
F2E7: BD 46 F5      LDA      DIGITS+2,X       ; ...
F2EA: 29 0F         AND      #0x0F            ; ...
F2EC: 05 99         ORA      SCORE_PF1+2      ; ...
F2EE: 85 99         STA      SCORE_PF1+2      ; ...

F2F0: B9 47 F5      LDA      DIGITS+3,Y       ; Repeat for 4th line of picture
F2F3: 29 F0         AND      #0xF0            ; ...
F2F5: 85 9A         STA      SCORE_PF1+3      ; ...
F2F7: BD 47 F5      LDA      DIGITS+3,X       ; ...
F2FA: 29 0F         AND      #0x0F            ; ...
F2FC: 05 9A         ORA      SCORE_PF1+3      ; ...
F2FE: 85 9A         STA      SCORE_PF1+3      ; ...

F300: B9 48 F5      LDA      DIGITS+4,Y       ; Repeat for 5th line of picture
F303: 29 F0         AND      #0xF0            ; ...
F305: 85 9B         STA      SCORE_PF1+4      ; ...
F307: BD 48 F5      LDA      DIGITS+4,X       ; ...
F30A: 29 0F         AND      #0x0F            ; ...
F30C: 05 9B         ORA      SCORE_PF1+4      ; ...
F30E: 85 9B         STA      SCORE_PF1+4      ; ...

F310: A9 00         LDA      #0               ; For now ...
F312: 85 9D         STA      SCORE_PF2        ; ... there ...
F314: 85 9E         STA      SCORE_PF2+1      ; ... is ...
F316: 85 9F         STA      SCORE_PF2+2      ; ... no ...
F318: 85 A0         STA      SCORE_PF2+3      ; ... 100s ...
F31A: 85 A1         STA      SCORE_PF2+4      ; ... digit drawn

F31C: 60            RTS                       ; Done

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.
                                           
F31D: AD 82 02      LDA      SWCHB            ; Check P0 ...
F320: 29 40         AND      #0x40            ; ... pro/novice settings
F322: C9 00         CMP      #0               ; Amateur?
F324: F0 05         BEQ      ExpP0Ama         ; Yes ... near the bottom of screen
F326: A9 08         LDA      #8               ; Pro ... near the top
F328: 4C 2D F3      JMP      ExpP1            ; Store and check P0
ExpP0Ama:
F32B: A9 0C         LDA      #12              ; near the bottom

ExpP1:
F32D: 85 83         STA      PLAYR0Y          ; Player 0 Y coordinate
                                           
F32F: A6 84         LDX      PLAYR1Y          ; Is P1 on ...
F331: E0 FF         CPX      #255             ; ... the screen?
F333: F0 12         BEQ      ExpNoP1          ; No ... skip all this
F335: AD 82 02      LDA      SWCHB            ; Check P1 ...
F338: 29 80         AND      #0x80            ; ... pro/novice settings
F33A: C9 00         CMP      #0               ; Amateur?
F33C: F0 05         BEQ      ExpP1Ama         ; Yes ... near the bottom of the screen
F33E: A2 08         LDX      #8               ; Pro ... near the top
F340: 4C 45 F3      JMP      ExpDone          ; Store and out
ExpP1Ama:
F343: A2 0C         LDX      #12              ; Novice ... near the bottom
ExpDone:
F345: 86 84         STX      PLAYR1Y          ; Player 1 Y coordinate
ExpNoP1:
F347: 60            RTS                       ; Done

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.

F348: A2 00         LDX      #0               ; Starting at index 0
                                           
AdjNextRow:
F34A: BD F9 F4      LDA      SKILL_VALUES,X   ; Get the score match
F34D: C9 FF         CMP      #255             ; At the end of the table?
F34F: D0 01         BNE      AdjCheckTable    ; No ... check this row
F351: 60            RTS                       ; End of the table ... leave it alone
AdjCheckTable:
F352: C5 8A         CMP      WALLCNT          ; Is this our row?
F354: D0 27         BNE      AdjBump          ; No ... bump to next
F356: E8            INX                       ; Copy ...
F357: BD F9 F4      LDA      SKILL_VALUES,X   ; ... new ...
F35A: 85 89         STA      WALL_INC         ; ... wall increment
F35C: E8            INX                       ; Copy ...
F35D: BD F9 F4      LDA      SKILL_VALUES,X   ; ... new ...
F360: 85 8B         STA      WALLDELY         ; ... wall ...
F362: 85 8C         STA      WALLDELYR        ; ... delay
F364: E8            INX                       ; Copy ...
F365: BD F9 F4      LDA      SKILL_VALUES,X   ; ... new ...
F368: 85 96         STA      GAPBITS          ; ... gap pattern
F36A: E8            INX                       ; Copy ...
F36B: BD F9 F4      LDA      SKILL_VALUES,X   ; ... new ...
F36E: 85 A4         STA      MUSAIND          ; ... MusicA index
F370: E8            INX                       ; Copy ...
F371: BD F9 F4      LDA      SKILL_VALUES,X   ; ... new ...
F374: 85 A7         STA      MUSBIND          ; ... MusicB index
F376: A9 01         LDA      #1               ; Force ...
F378: 85 A3         STA      MUSADEL          ; ... music to ...
F37A: 85 A6         STA      MUSBDEL          ; ... start new
F37C: 60            RTS                       ; Done
AdjBump:
F37D: E8            INX                       ; Move ...
F37E: E8            INX                       ; ... X ...
F37F: E8            INX                       ; ... to ...
F380: E8            INX                       ; ... next ...
F381: E8            INX                       ; ... row of ...
F382: E8            INX                       ; ... table
F383: 4C 4A F3      JMP      AdjNextRow       ; Try next row
                                           
                                           
SEL_RESET_CHK:
                                           
     ;  This function checks for changes to the reset/select
     ;  switches and debounces the transitions.
     ;  xxxxxxSR (Select, Reset)
                                           
F386: A6 90         LDX      DEBOUNCE         ; Get the last value
F388: AD 82 02      LDA      SWCHB            ; New value
F38B: 29 03         AND      #3               ; Only need bottom 2 bits
F38D: C5 90         CMP      DEBOUNCE         ; Same as before?
F38F: F0 07         BEQ      SelDebounce      ; Yes ... return nothing changed
F391: 85 90         STA      DEBOUNCE         ; Hold new last value
F393: 49 FF         EOR      #255             ; Active low to active high
F395: 29 03         AND      #3               ; Only need select/reset
F397: 60            RTS                       ; Return changes
SelDebounce:
F398: A9 00         LDA      #0               ; Return 0 ...
F39A: 60            RTS                       ; ... nothing changed

                                           
INIT_MUSIC:

     ;  This function initializes the hardware and temporaries
     ;  for 2-channel music

F39B: A9 06         LDA      #6               ; Audio control ...
F39D: 85 15         STA      AUDC0            ; ... to pure ...
F39F: 85 16         STA      AUDC1            ; ... tones
F3A1: A9 00         LDA      #0               ; Turn off ...
F3A3: 85 19         STA      AUDV0            ; ... all ...
F3A5: 85 1A         STA      AUDV1            ; ... sound
F3A7: 85 A4         STA      MUSAIND          ; Music pointers ...
F3A9: 85 A7         STA      MUSBIND          ; ... to top of data
F3AB: A9 01         LDA      #1               ; Force ...
F3AD: 85 A3         STA      MUSADEL          ; ... music ...
F3AF: 85 A6         STA      MUSBDEL          ; ... reload
F3B1: A9 0F         LDA      #15              ; Set volume levels ...
F3B3: 85 A5         STA      MUSAVOL          ; ... to ...
F3B5: 85 A8         STA      MUSBVOL          ; ... maximum
F3B7: 60            RTS                       ; Done

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.

F3B8: C6 A3         DEC      MUSADEL          ; Current note on Channel A ended?
F3BA: D0 58         BNE      MusDoB           ; No ... let it play
                                           
MusChanA:
F3BC: A6 A4         LDX      MUSAIND          ; Voice-A index
F3BE: BD A0 F4      LDA      MUSICA,X         ; Get the next music command
F3C1: C9 00         CMP      #0               ; Jump?
F3C3: F0 22         BEQ      MusCmdJumpA      ; Yes ... handle it
F3C5: C9 01         CMP      #1               ; Control?
F3C7: F0 11         BEQ      MusCmdCtrlA      ; Yes ... handle it
F3C9: C9 02         CMP      #2               ; Volume?
F3CB: D0 28         BNE      MusCmdToneA      ; No ... must be a note
F3CD: E8            INX                       ; Point to volume value
F3CE: E6 A4         INC      MUSAIND          ; Bump the music pointer
F3D0: BD A0 F4      LDA      MUSICA,X         ; Get the volume value
F3D3: E6 A4         INC      MUSAIND          ; Bump the music pointer
F3D5: 85 A5         STA      MUSAVOL          ; Store the new volume value
F3D7: 4C BC F3      JMP      MusChanA         ; Keep processing through a tone

MusCmdCtrlA:
F3DA: E8            INX                       ; Point to the control value
F3DB: E6 A4         INC      MUSAIND          ; Bump the music pointer
F3DD: BD A0 F4      LDA      MUSICA,X         ; Get the control value
F3E0: E6 A4         INC      MUSAIND          ; Bump the music pointer
F3E2: 85 15         STA      AUDC0            ; Store the new control value
F3E4: 4C BC F3      JMP      MusChanA         ; Keep processing through a tone

MusCmdJumpA:
F3E7: E8            INX                       ; Point to jump value
F3E8: 8A            TXA                       ; X to ...
F3E9: A8            TAY                       ; ... Y (pointer to jump value)
F3EA: E8            INX                       ; Point one past jump value
F3EB: 8A            TXA                       ; Into A so we can subtract
F3EC: 38            SEC                       ; New ...
F3ED: F9 A0 F4      SBC      MUSICA,Y         ; ... index
F3F0: 85 A4         STA      MUSAIND          ; Store it
F3F2: 4C BC F3      JMP      MusChanA         ; Keep processing through a tone

MusCmdToneA:
F3F5: A4 A5         LDY      MUSAVOL          ; Get the volume
F3F7: 29 1F         AND      #0x1F            ; Lower 5 bits are frequency
F3F9: C9 1F         CMP      #0x1F            ; Is this a silence?
F3FB: D0 02         BNE      MusNoteA         ; No ... play it
F3FD: A0 00         LDY      #0               ; Frequency of 31 flags silence
MusNoteA:
F3FF: 85 17         STA      AUDF0            ; Store the frequency
F401: 84 19         STY      AUDV0            ; Store the volume
F403: BD A0 F4      LDA      MUSICA,X         ; Get the note value again
F406: E6 A4         INC      MUSAIND          ; Bump to the next command
F408: 6A            ROR      A                ; The upper ...
F409: 6A            ROR      A                ; ... three ...
F40A: 6A            ROR      A                ; ... bits ...
F40B: 6A            ROR      A                ; ... hold ...
F40C: 6A            ROR      A                ; ... the ...
F40D: 29 07         AND      #7               ; ... delay
F40F: 18            CLC                       ; No accidental carry
F410: 2A            ROL      A                ; Every delay tick ...
F411: 2A            ROL      A                ; ... is *4 frames
F412: 85 A3         STA      MUSADEL          ; Store the note delay

MusDoB:
                                           
F414: C6 A6         DEC      MUSBDEL
F416: D0 58         BNE      MusDoDone
                                           
MusChanB:
F418: A6 A7         LDX      MUSBIND
F41A: BD CD F4      LDA      MUSICB,X
F41D: C9 00         CMP      #0
F41F: F0 22         BEQ      MusCmdJumpB
F421: C9 01         CMP      #1
F423: F0 11         BEQ      MusCmdCtrlB
F425: C9 02         CMP      #2
F427: D0 28         BNE      MusCmdToneB
F429: E8            INX
F42A: E6 A7         INC      MUSBIND
F42C: BD CD F4      LDA      MUSICB,X
F42F: E6 A7         INC      MUSBIND
F431: 85 A8         STA      MUSBVOL
F433: 4C 18 F4      JMP      MusChanB

MusCmdCtrlB:
F436: E8            INX
F437: E6 A7         INC      MUSBIND
F439: BD CD F4      LDA      MUSICB,X
F43C: E6 A7         INC      MUSBIND
F43E: 85 16         STA      AUDC1
F440: 4C 18 F4      JMP      MusChanB

MusCmdJumpB:
F443: E8            INX
F444: 8A            TXA
F445: A8            TAY
F446: E8            INX
F447: 8A            TXA
F448: 38            SEC
F449: F9 CD F4      SBC      MUSICB,Y
F44C: 85 A7         STA      MUSBIND
F44E: 4C 18 F4      JMP      MusChanB

MusCmdToneB:
F451: A4 A8         LDY      MUSBVOL
F453: 29 1F         AND      #0x1F
F455: C9 1F         CMP      #0x1F
F457: D0 02         BNE      MusNoteB
F459: A0 00         LDY      #0
MusNoteB:
F45B: 85 18         STA      AUDF1
F45D: 84 1A         STY      AUDV1
F45F: BD CD F4      LDA      MUSICB,X
F462: E6 A7         INC      MUSBIND
F464: 6A            ROR      A
F465: 6A            ROR      A
F466: 6A            ROR      A
F467: 6A            ROR      A
F468: 6A            ROR      A
F469: 29 07         AND      #7
F46B: 18            CLC
F46C: 2A            ROL      A
F46D: 2A            ROL      A
F46E: 85 A6         STA      MUSBDEL

MusDoDone:
F470: 60            RTS                       ; Done


INIT_GO_FX:
                                           
     ;  This function initializes the hardware and temporaries
     ;  to play the soundeffect of a player hitting the wall
                                           
F471: A9 05         LDA      #5               ; Set counter for frame delay ...
F473: 85 86         STA      MUS_TMP1         ; ... between frequency change
F475: A9 03         LDA      #3               ; Tone type ...
F477: 85 15         STA      AUDC0            ; ... poly tone
F479: A9 0F         LDA      #15              ; Volume A ...
F47B: 85 19         STA      AUDV0            ; ... to max
F47D: A9 00         LDA      #0               ; Volume B ...
F47F: 85 1A         STA      AUDV1            ; ... silence
F481: A9 F0         LDA      #240             ; Initial ...
F483: 85 85         STA      MUS_TMP0         ; ... sound ...
F485: 85 17         STA      AUDF0            ; ... frequency
F487: 60            RTS                       ; Done

PROCESS_GO_FX:
                                           
     ;  This function is called once per scanline to play the
     ;  soundeffects of a player hitting the wall.

F488: C6 86         DEC      MUS_TMP1         ; Time to change the frequency?
F48A: D0 11         BNE      FxRun            ; No ... let it run
F48C: A9 05         LDA      #5               ; Reload ...
F48E: 85 86         STA      MUS_TMP1         ; ... the frame count
F490: E6 85         INC      MUS_TMP0         ; Increment ...
F492: A5 85         LDA      MUS_TMP0         ; ... the frequency divisor
F494: 85 17         STA      AUDF0            ; Change the frequency
F496: C9 00         CMP      #0
F498: D0 03         BNE      FxRun
F49A: A9 01         LDA      #1               ; All done ... return 1
F49C: 60            RTS                       ; Done
FxRun:
F49D: A9 00         LDA      #0               ; Keep playing
F49F: 60            RTS                       ; Done

  ;  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

.MUSCMD_JUMP      =     0      ; Music command value for JUMP
.MUSCMD_CONTROL   =     1      ; Music command value for CONTROL
.MUSCMD_VOLUME    =     2      ; Music command value for VOLUME
.MUS_REST         =     31     ; Frequency value for silence
.MUS_DEL_1        =     32*1   ; Note duration 1
.MUS_DEL_2        =     32*2   ; Note duration 2
.MUS_DEL_3        =     32*3   ; Note duration 3
.MUS_DEL_4        =     32*4   ; Note duration 4
                                           
MUSICA:
                                           
MA_SONG_1:
                                           
F4A0: 01 0C         .byte    MUSCMD_CONTROL, 12
F4A2: 02 0F         .byte    MUSCMD_VOLUME,  15 ; Volume (full)
                                           
MA1_01:
F4A4: 6F            .byte    MUS_DEL_3  +  15
F4A5: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4A6: 6F            .byte    MUS_DEL_3  +  15
F4A7: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4A8: 27            .byte    MUS_DEL_1  +  7
F4A9: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4AA: 27            .byte    MUS_DEL_1  +  7
F4AB: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4AC: 5F            .byte    MUS_DEL_2  +  MUS_REST
F4AD: 28            .byte    MUS_DEL_1  +  8
F4AE: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4AF: 9F            .byte    MUS_DEL_4  +  MUS_REST
F4B0: 51            .byte    MUS_DEL_2  +  17
F4B1: 5F            .byte    MUS_DEL_2  +  MUS_REST
F4B2: 51            .byte    MUS_DEL_2  +  17
F4B3: 5F            .byte    MUS_DEL_2  +  MUS_REST
F4B4: 70            .byte    MUS_DEL_3  +  16
F4B5: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4B6: 00 14         .byte    MUSCMD_JUMP, (MA1_END - MA1_01) ; Repeat back to top
MA1_END:
                                           
MA_SONG_2:
F4B8: 01 0C         .byte    MUSCMD_CONTROL, 12
F4BA: 02 0F         .byte    MUSCMD_VOLUME,  15
                                           
MA2_01:
F4BC: 2F            .byte    MUS_DEL_1  +  15
F4BD: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4BE: 2F            .byte    MUS_DEL_1  +  15
F4BF: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4C0: 5F            .byte    MUS_DEL_2  +  MUS_REST
F4C1: 87            .byte    MUS_DEL_4  +  7
F4C2: 9F            .byte    MUS_DEL_4  +  MUS_REST
F4C3: 4F            .byte    MUS_DEL_2  +  15
F4C4: 9F            .byte    MUS_DEL_4  +  MUS_REST
F4C5: 4C            .byte    MUS_DEL_2  +  12
F4C6: 5F            .byte    MUS_DEL_2  +  MUS_REST
F4C7: 4F            .byte    MUS_DEL_2  +  15
F4C8: 5F            .byte    MUS_DEL_2  +  MUS_REST
F4C9: 51            .byte    MUS_DEL_2  +  17
F4CA: 5F            .byte    MUS_DEL_2  +  MUS_REST
F4CB: 00 11         .byte    MUSCMD_JUMP, (MA2_END - MA2_01) ; Repeat back to top
MA2_END:
                                           
MUSICB:
                                           
MB_SONG_1:
                                           
F4CD: 01 08         .byte    MUSCMD_CONTROL, 8
F4CF: 02 08         .byte    MUSCMD_VOLUME,  8 ; Volume (half)
                                           
MB1_01:
F4D1: 2A            .byte    MUS_DEL_1  +  10
F4D2: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4D3: 34            .byte    MUS_DEL_1  +  20
F4D4: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4D5: 3E            .byte    MUS_DEL_1  +  30
F4D6: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4D7: 2F            .byte    MUS_DEL_1  +  15
F4D8: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4D9: 2A            .byte    MUS_DEL_1  +  10
F4DA: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4DB: 34            .byte    MUS_DEL_1  +  20
F4DC: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4DD: 3E            .byte    MUS_DEL_1  +  30
F4DE: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4DF: 2F            .byte    MUS_DEL_1  +  15
F4E0: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4E1: 00 12         .byte    MUSCMD_JUMP, (MB1_END - MB1_01) ; Repeat back to top
MB1_END:
                                           
MB_SONG_2:
                                           
F4E3: 01 08         .byte    MUSCMD_CONTROL, 8
F4E5: 02 08         .byte    MUSCMD_VOLUME,  8
                                           
MB2_01:
F4E7: 21            .byte    MUS_DEL_1  +  1
F4E8: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4E9: 21            .byte    MUS_DEL_1  +  1
F4EA: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4EB: 21            .byte    MUS_DEL_1  +  1
F4EC: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4ED: 21            .byte    MUS_DEL_1  +  1
F4EE: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4EF: 3E            .byte    MUS_DEL_1  +  30
F4F0: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4F1: 3E            .byte    MUS_DEL_1  +  30
F4F2: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4F3: 3E            .byte    MUS_DEL_1  +  30
F4F4: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4F5: 3E            .byte    MUS_DEL_1  +  30
F4F6: 3F            .byte    MUS_DEL_1  +  MUS_REST
F4F7: 00 12         .byte    MUSCMD_JUMP, (MB2_END - MB2_01) ; Repeat back to top
MB2_END:

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
F4F9: 00 01 03 00 00 00      .byte    0,     1,   3,     0  ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB
F4FF: 04 01 02 00 18 16      .byte    4,     1,   2,     0  ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB
F505: 08 01 01 00 00 00      .byte    8,     1,   1,     0  ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB
F50B: 10 01 01 01 18 16      .byte    16,    1,   1,     1  ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB
F511: 18 01 01 03 00 00      .byte    24,    1,   1,     3  ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB
F517: 20 01 01 07 18 16      .byte    32,    1,   1,     7  ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB
F51D: 28 01 01 0F 00 00      .byte    40,    1,   1,    15  ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB
F523: 30 02 01 00 18 16      .byte    48,    2,   1,     0  ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB
F529: 40 02 01 01 00 00      .byte    64,    2,   1,     1  ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB
F52F: 50 02 01 03 18 16      .byte    80,    2,   1,     3  ,MA_SONG_2-MUSICA , MB_SONG_2-MUSICB
F535: 60 02 01 07 00 00      .byte    96 ,   2,   1,     7  ,MA_SONG_1-MUSICA , MB_SONG_1-MUSICB
F53B: FF            .byte    255
                                           
GR_PLAYER:
     ;  Image for players (8x8)
     .subs .=0, *=1
     ;
F53C: 10            .byte    0b__...*....
F53D: 10            .byte    0b__...*....
F53E: 28            .byte    0b__..*.*...
F53F: 28            .byte    0b__..*.*...
F540: 54            .byte    0b__.*.*.*..
F541: 54            .byte    0b__.*.*.*..
F542: AA            .byte    0b__*.*.*.*.
F543: 7C            .byte    0b__.*****..
                                           
DIGITS:
     ;  Images for numbers
     ;  We only need 5 rows, but the extra space on the end makes each digit 8 rows,
     ;  which makes it the multiplication easier.

F544: 0E            .byte   0b__....***.  ; 0 (leading 0 is blank)
F545: 0A            .byte   0b__....*.*.
F546: 0A            .byte   0b__....*.*.
F547: 0A            .byte   0b__....*.*.
F548: 0E            .byte   0b__....***.
F549: 00            .byte   0b__........
F54A: 00            .byte   0b__........
F54B: 00            .byte   0b__........

F54C: 22            .byte   0b__..*...*.  ; 1
F54D: 22            .byte   0b__..*...*.
F54E: 22            .byte   0b__..*...*.
F54F: 22            .byte   0b__..*...*.
F550: 22            .byte   0b__..*...*.
F551: 00            .byte   0b__........
F552: 00            .byte   0b__........
F553: 00            .byte   0b__........

F554: EE            .byte   0b__***.***.  ; 2
F555: 22            .byte   0b__..*...*.
F556: EE            .byte   0b__***.***.
F557: 88            .byte   0b__*...*...
F558: EE            .byte   0b__***.***.
F559: 00            .byte   0b__........
F55A: 00            .byte   0b__........
F55B: 00            .byte   0b__........

F55C: EE            .byte   0b__***.***.  ; 3
F55D: 22            .byte   0b__..*...*.
F55E: 66            .byte   0b__.**..**.
F55F: 22            .byte   0b__..*...*.
F560: EE            .byte   0b__***.***.
F561: 00            .byte   0b__........
F562: 00            .byte   0b__........
F563: 00            .byte   0b__........

F564: AA            .byte   0b__*.*.*.*.  ; 4
F565: AA            .byte   0b__*.*.*.*.
F566: EE            .byte   0b__***.***.
F567: 22            .byte   0b__..*...*.
F568: 22            .byte   0b__..*...*.
F569: 00            .byte   0b__........
F56A: 00            .byte   0b__........
F56B: 00            .byte   0b__........

F56C: EE            .byte   0b__***.***. ; 5
F56D: 88            .byte   0b__*...*...
F56E: EE            .byte   0b__***.***.
F56F: 22            .byte   0b__..*...*.
F570: EE            .byte   0b__***.***.
F571: 00            .byte   0b__........
F572: 00            .byte   0b__........
F573: 00            .byte   0b__........

F574: EE            .byte   0b__***.***. ; 6
F575: 88            .byte   0b__*...*...
F576: EE            .byte   0b__***.***.
F577: AA            .byte   0b__*.*.*.*.
F578: EE            .byte   0b__***.***.
F579: 00            .byte   0b__........
F57A: 00            .byte   0b__........
F57B: 00            .byte   0b__........

F57C: EE            .byte   0b__***.***. ; 7
F57D: 22            .byte   0b__..*...*.
F57E: 22            .byte   0b__..*...*.
F57F: 22            .byte   0b__..*...*.
F580: 22            .byte   0b__..*...*.
F581: 00            .byte   0b__........
F582: 00            .byte   0b__........
F583: 00            .byte   0b__........

F584: EE            .byte   0b__***.***. ; 8
F585: AA            .byte   0b__*.*.*.*.
F586: EE            .byte   0b__***.***.
F587: AA            .byte   0b__*.*.*.*.
F588: EE            .byte   0b__***.***.
F589: 00            .byte   0b__........
F58A: 00            .byte   0b__........
F58B: 00            .byte   0b__........

F58C: EE            .byte   0b__***.***. ; 9
F58D: AA            .byte   0b__*.*.*.*.
F58E: EE            .byte   0b__***.***.
F58F: 22            .byte   0b__..*...*.
F590: EE            .byte   0b__***.***.
F591: 00            .byte   0b__........
F592: 00            .byte   0b__........
F593: 00            .byte   0b__........

F7FA:
  ; 6502 vectors
F7FA: 00 F0         .word main
F7FC: 00 F0         .word main  ; Reset vector (top of program)
F7FE: 00 F0         .word main