LIST OFF ; *** T U R M O I L *** ; Copyright 1982 Sirius ; Programmer: Mark Turmell ; Analyzed, labeled and commented ; by Dennis Debro ; Last Update: December 7, 2018 ; ; *** 121 BYTES OF RAM USED 7 BYTES FREE ; *** 143 BYTES OF ROM FREE ; ; ============================================================================== ; = THIS REVERSE-ENGINEERING PROJECT IS BEING SUPPLIED TO THE PUBLIC DOMAIN = ; = FOR EDUCATIONAL PURPOSES ONLY. THOUGH THE CODE WILL ASSEMBLE INTO THE = ; = EXACT GAME ROM, THE LABELS AND COMMENTS ARE THE INTERPRETATION OF MY OWN = ; = AND MAY NOT REPRESENT THE ORIGINAL VISION OF THE AUTHOR. = ; = = ; = THE ASSEMBLED CODE IS © 1982, SIRIUS = ; = = ; ============================================================================== processor 6502 ; ; NOTE: You must compile this with vcs.h version 105 or greater. ; TIA_BASE_READ_ADDRESS = $30 ; set the read address base so this runs on ; the real VCS and compiles to the exact ; ROM image include vcs.h include macro.h include tia_constants.h ; ; Make sure we are using vcs.h version 1.05 or greater. ; IF VERSION_VCS < 105 echo "" echo "*** ERROR: vcs.h file *must* be version 1.05 or higher!" echo "*** Updates to this file, DASM, and associated tools are" echo "*** available at https://dasm-assembler.github.io/" echo "" err ENDIF ; ; Make sure we are using macro.h version 1.01 or greater. ; IF VERSION_MACRO < 101 echo "" echo "*** ERROR: macro.h file *must* be version 1.01 or higher!" echo "*** Updates to this file, DASM, and associated tools are" echo "*** available at https://dasm-assembler.github.io/" echo "" err ENDIF LIST ON ;=============================================================================== ; A S S E M B L E R - S W I T C H E S ;=============================================================================== NTSC = 0 PAL50 = 1 PAL60 = 2 TRUE = 1 FALSE = 0 IFNCONST COMPILE_REGION COMPILE_REGION = NTSC ; change to compile for different regions ENDIF IF COMPILE_REGION != NTSC echo "" echo "*** ERROR: Invalid COMPILE_REGION value" echo "*** Valid values: NTSC = 0" echo "" err ENDIF ;=============================================================================== ; F R A M E - T I M I N G S ;=============================================================================== FPS = 60 ; ~60 frames per second VSYNC_TIME = 42 VBLANK_TIME = 59 OVERSCAN_SCANLINES = 23 ;=============================================================================== ; C O L O R - C O N S T A N T S ;=============================================================================== BLACK = $00 WHITE = $0F YELLOW = $10 RED_ORANGE = $20 BRICK_RED = $30 RED = $40 PURPLE = $50 COBALT_BLUE = $60 ULTRAMARINE_BLUE = $70 BLUE = $80 LT_BLUE = $90 OLIVE_GREEN = $B0 GREEN = $C0 ORANGE_GREEN = $E0 ;=============================================================================== ; U S E R - C O N S T A N T S ;=============================================================================== ROM_BASE = $F000 H_DIGITS = 8 H_KERNEL = 212 H_LEVEL_TRANSITION_KERNEL = 144 H_KERNEL_LANE = 15 H_SNEAKERS = 10 INIT_RESERVED_SHIPS = 3 MAX_RESERVED_SHIPS = 6 XMIN = 0 XMAX = 160 INIT_PLAYER_SHIP_HORIZ = (XMAX / 2) - 6 INIT_RESERVED_SHIPS_HORIZ = 10 INIT_PLAYER_SHIP_ALLEY = 5 NUM_LANES = 7 MAX_GAME_LEVEL = 8 OBSTACLE_ANIMATION_RATE = 24 MAX_COLLECTED_PRIZES = 15 ; obstacle attribute values OBSTACLE_DIR_MASK = %00000001 OBSTACLE_DIR_LEFT = 0 OBSTACLE_DIR_RIGHT = 1 ;obstacle ids ID_BLANK = 0 ID_CANNON_BALL = 1 ID_ENEMY_FIGHTER_01 = 2 ID_PRIZE = 3 ID_TIE_FIGHTER = 4 ID_BULLET = 5 ID_MISSILE = 6 ID_ENEMY_FIGHTER_02 = 7 ID_CRAWLER = 8 ID_ARROW = 9 ID_TANK = 10 ID_EXPLOSION = 11 ID_GHOST_SHIP = 12 ; point value constants (BCD) POINT_VALUE_BLANK = $000 POINT_VALUE_CANNON_BALL = $100 POINT_VALUE_FIGHTER_01 = $020 POINT_VALUE_PRIZE = $060 POINT_VALUE_TIE_FIGHTER = $060 POINT_VALUE_BULLET = $010 POINT_VALUE_MISSILE = $030 POINT_VALUE_FIGHTER_02 = $010 POINT_VALUE_CRAWLER = $040 POINT_VALUE_ARROW = $100 POINT_VALUE_TANK = $050 POINT_VALUE_EXPLOSION = $000 POINT_VALIE_GHOST_SHIP = $080 ; game level obstacles limit values OBSTACLE_LIMIT_LEVEL_01 = 64 OBSTACLE_LIMIT_LEVEL_02 = 112 OBSTACLE_LIMIT_LEVEL_03 = 144 OBSTACLE_LIMIT_LEVEL_04 = 176 OBSTACLE_LIMIT_LEVEL_05 = 192 OBSTACLE_LIMIT_LEVEL_06 = 208 OBSTACLE_LIMIT_LEVEL_07 = 224 OBSTACLE_LIMIT_LEVEL_08 = 240 OBSTACLE_LIMIT_LEVEL_09 = 240 OBSTACLE_LIMIT_LEVEL_10 = 255 INIT_GHOST_SHIP_SOUND_INDEX = 25 INIT_ARROW_SPAWN_SOUND_INDEX = 30 ;=============================================================================== ; M A C R O S ;=============================================================================== ; ; time wasting macros ; MAC SLEEP_3 bit $FF ENDM MAC SLEEP_7 rol ROM_BASE,x ENDM ;=============================================================================== ; Z P - V A R I A B L E S ;=============================================================================== SEG.U variables .org $80 tmpObstacleIndex ds 1 ; holds index for new spawning obstacles currentKernelLane ds 1 ; lane being drawn in kernel obstacleAnimationIndex ds 1 ; animation index for obstacle playerShipGraphicPtr ds 2 ; graphic pointers for Player Ship tmpScoreIndexValues ds 4 playerScore ds 2 ; two bytes for score (BCD) digitGraphicPtrs ds 2 ; graphic pointers to character display ;-------------------------------------- tmpLivesGraphicPtrs_00 = digitGraphicPtrs ;-------------------------------------- tmpPlayLevelGraphicPtrs = tmpLivesGraphicPtrs_00 ;-------------------------------------- tmpObstacleHorizPosPtrs = tmpPlayLevelGraphicPtrs ;-------------------------------------- tmpObstacleTypePtrs = tmpObstacleHorizPosPtrs ;-------------------------------------- tmpTurmoilLiteral_05 = tmpObstacleTypePtrs tmpTurmoilFontLoop = tmpPlayLevelGraphicPtrs + 1 playerShotSoundIndex ds 1 ; value for playing Play Ship shot sounds playerShipAlley ds 1 ; alley occupied by Player Ship newSpawnedObstacle ds 1 ; new "random" obstacle to spawn ;-------------------------------------- gameOverSoundNoteHoldValue = newSpawnedObstacle laneColor ds 1 ; color value for lanes playerShipColorPtrs ds 2 ; set but never used random ds 2 ; 16-bit random number playerShipVertDelay ds 1 ; delay value for Player Ship movement playerShipVertSoundIndex ds 1 ; value for playing Player Ship movement unused_00 ds 1 objectHorizPos ds 16 ; horizontal position values ;-------------------------------------- playerShipHorizPos = objectHorizPos obstacleHorizPos = objectHorizPos + 1 playerShipShotHorizPos = obstacleHorizPos + 7 reservedShipsHorizPos = playerShipShotHorizPos + 7 ;-------------------------------------- tmpTransitionKernelBKColor = playerShipShotHorizPos kernelFCPosValues ds 16 ; fine / coarse horizontal values ;-------------------------------------- playerShipFCValue = kernelFCPosValues obstacleFCValues = playerShipFCValue + 1 playerShipShotFCValues = obstacleFCValues + 7 reservedShipsFCValue = playerShipShotFCValues + 7 gameState ds 1 reservedShips ds 1 ; number of reserved ships prizeFrameTimer ds 1 obstacleGraphicPtr ds 2 ; graphic pointers for obstacles unused_01 ds 1 obstacleList ds 7 ; list of obstacles gameOverSoundIndex ds 1 ; value for playing game over sounds selectDebounce ds 1 obstacleSpeedValue ds 1 ; speed of obstacles allowedToSpawnObstacles ds 1 obstaclesDestroyed ds 1 ; number of obstacles destroyed levelTransitionSoundIndex ds 1 ; value for playing level transition sounds laneColorStatus ds 1 ; value to color lanes or BLACK them out tmpHighScoreIndexValues ds 4 savedGameLevel ds 1 ; set but never referenced unused_02 ds 1 prizesCollected ds 1 ; number of prizes collected for the level prizePointValue ds 1 ; prize point value...reduced each frame prizeFrameLoopCount ds 1 currentPrizeLane ds 1 ; lane occupied by ID_PRIZE tmpLivesGraphicPtrs_01 ds 2 ;-------------------------------------- tmpKernelShipGraphicPtr = tmpLivesGraphicPtrs_01 obstacleGraphicLSBPtr ds 2 ; pointer to read obstacle graphic values obstacleAttributes ds 7 ; obstacle movement values resetDebounce ds 1 tmpHundredsGraphic ds 1 ;-------------------------------------- tmpPlayerShipGraphic = tmpHundredsGraphic ;-------------------------------------- tmpObstacleMovementDelay = tmpPlayerShipGraphic playerShipShotHorizDir ds 7 ; direction values for Player Ship shots gameLevel ds 1 ; current game level playerShipShotPtr ds 2 ; pointer to draw Player Ship shoots startBWValue ds 1 ; B/W values read at boot up for pause obstacleColorPtrs ds 2 ; pointer to obstacle colors arrowSpawnSoundIndex ds 1 ; value for playing arrow spawning tankSpawnSoundIndex ds 1 ; value for playing Tank spawning obstacleShotCollisionValues ds 1 ; each bit represents a lane playerShipReflectValue ds 1 ; reflect state of Player Ship tmpTurmoilLiteralColor ds 1 ;-------------------------------------- tmpPlayerShipCollisionValue = tmpTurmoilLiteralColor playerShipCollisionSoundIndex ds 1 unused_03 ds 1 sneakerGraphicPtr ds 2 ; graphic pointer for Sneaker graphics ;-------------------------------------- transitionKernelBKColor = sneakerGraphicPtr tmpTransitionKernelPFColorIdx = transitionKernelBKColor + 1 tmpEnableDisablePlayShot ds 1 ;-------------------------------------- transitionKernelPFColor = tmpEnableDisablePlayShot kernelStatus ds 1 ghostShipSoundIndex ds 1 ; value for playing Ghost Ship sounds ;-------------------------------------- tmpPlayLevelIndex = ghostShipSoundIndex ghostShipSpawnTimer ds 1 ; timer to spawn Ghost Ship for non-movement echo "***",(* - $80 - 4)d, "BYTES OF RAM USED", ($100 - * + 4)d, "BYTES FREE" ;=============================================================================== ; R O M - C O D E ;=============================================================================== SEG Bank0 .org ROM_BASE Start ; ; Set up everything so the power up state is known. ; sei cld lda #0 tax .clearLoop sta VSYNC,x inx bne .clearLoop dex ; x = #$FF txs ; set stack to the beginning lda SWCHB ; read console switches and #BW_MASK ; get the B/W switch value sta startBWValue ; save B/W switch value at cart startup lda #>ObstacleGraphics sta obstacleGraphicPtr + 1 ; set obstacle graphics MSB value lda #ObstacleColorValues sta obstacleColorPtrs + 1 ; set default obstacle color MSB value lda #254 sta random + 1 sta obstacleGraphicLSBPtr + 1 lda #REFLECT sta playerShipReflectValue ; set player ship to point right lda #1 sta tmpObstacleIndex sta CTRLPF ; set playfield to REFLECT (i.e. D0 = 1) lda #INIT_PLAYER_SHIP_ALLEY sta playerShipAlley lda #INIT_PLAYER_SHIP_HORIZ sta playerShipHorizPos lda #INIT_RESERVED_SHIPS_HORIZ sta reservedShipsHorizPos lda #20 sta newSpawnedObstacle lda #YELLOW + 8 sta laneColor lda #PlayerShipColorValues sta playerShipColorPtrs + 1 lda #PlayerShipGraphics sta playerShipGraphicPtr + 1 lda #1 sta obstacleSpeedValue jsr SetObstacleValuesForGameLevel NewFrame ldx #VSYNC_TIME sta WSYNC ; wait for next scanline stx VBLANK ; disable TIA (i.e. D1 = 1) stx VSYNC ; start VSYNC (i.e. D1 = 1) stx TIM8T ; set timer for VSYNC period inc ghostShipSpawnTimer ; increment Ghost Ship timer each frame lda playerScore ; get player score value and #$0F ; keep lower nybbles (i.e. tens value) asl ; multiply by 8 (i.e. H_DIGITS) asl asl sta tmpScoreIndexValues lda playerScore ; get player score value and #$F0 ; keep upper nybbles (i.e. hundreds value) lsr ; divide by 2 (i.e. multiply by 8) sta tmpScoreIndexValues + 1 lda playerScore + 1 ; get player score value and #$0F ; keep lower nybbles (i.e. thousands value) asl ; multiply by 8 (i.e. H_DIGITS) asl asl sta tmpScoreIndexValues + 2 lda playerScore + 1 ; get player score value and #$F0 ; keep upper nybbles (i.e. ten thousands) lsr ; divide by 2 (i.e. multiply by 8) sta tmpScoreIndexValues + 3 inc random lda gameState ; get current game state bmi VerticalBlank ; branch if game in progress inc tmpTurmoilLiteralColor lda #0 sta laneColorStatus ; clear lane color status VerticalBlank ldx #VBLANK_TIME .waitTime lda INTIM bne .waitTime sta WSYNC ; wait for next scanline sta VSYNC ; end VSYNC (i.e. D1 = 0) stx TIM64T ; set timer for VBLANK period lda gameState ; get current game state bpl .skipGamePaused ; branch if game not in progress lda SWCHB ; read console switches and #BW_MASK ; get the B/W switch value cmp startBWValue ; compare with value at startup beq .skipGamePaused ; branch if game not paused lda #0 sta AUDV1 ; turn off channel 1 sound sta AUDV0 ; turn off channel 0 sound lda laneColor ; get current lane color clc adc #16 ; increment color value sta laneColor ; set new lane color value jmp DisplayKernel .skipGamePaused ldx #NUM_LANES - 1 lda kernelStatus ; get kernel status value cmp #1 beq AdvanceToNextLevel ; branch if transitioning level lda obstaclesDestroyed ; get number of obstacles destroyed ldy gameLevel ; get current game level cmp NumberOfObstaclesToDestroy,y ; compare with obstacles to destroy bcc CheckObstaclesDestroyedForLevel; branch if not destroyed all obstacles .checkAllObjectsRemoved lda obstacleList,x ; get obstacle type for lane bne CheckObstaclesDestroyedForLevel; branch if not ID_BLANK dex bpl .checkAllObjectsRemoved AdvanceToNextLevel lda #0 sta obstaclesDestroyed ; reset number of obstacles destroyed sta ghostShipSpawnTimer ; reset Ghost Ship timer lda #1 sta playerShipAlley ; place player ship in alley 1 lda #INIT_PLAYER_SHIP_HORIZ sta playerShipHorizPos ; set player ship to starting horiz position lda #0 sta tankSpawnSoundIndex ; clear Tank spawn sound index sta playerShotSoundIndex sta playerShipVertSoundIndex ; clear vertical sound index sta playerShipCollisionSoundIndex; clear player ship collision sound index lda gameState ; get current game state bpl .incrementReservedShips ; branch if game not in progress inc gameLevel ; increment game level lda gameLevel ; get current game level cmp #MAX_GAME_LEVEL + 1 bcc .incrementReservedShips ; branch if not reached max level lda #MAX_GAME_LEVEL sta gameLevel ; set to max game level .incrementReservedShips inc reservedShips ; increment number of reserved ships lda reservedShips ; get number of reserved ships cmp #MAX_RESERVED_SHIPS + 1 bcc .setReservedShipsHorizPos ; branch if not reached max reserved ships lda #MAX_RESERVED_SHIPS sta reservedShips ; set to max reserved ships .setReservedShipsHorizPos tay ; move reserved ships value to y register lda ReservedShipsHorizPosValues,y sta reservedShipsHorizPos lda #255 sta levelTransitionSoundIndex beq CheckToPlayLevelTransitionSound; branch never taken sta kernelStatus ; set kernel status to show transition bmi CheckToPlayLevelTransitionSound CheckObstaclesDestroyedForLevel lda obstaclesDestroyed ; get number of obstacles destroyed ldy gameLevel ; get current game level cmp NumberOfObstaclesToDestroy,y ; compare with obstacles to destroy bcc CheckToPlayLevelTransitionSound; branch if not destroyed all obstacles lda #<-1 sta allowedToSpawnObstacles ; set to not allow obstacle spawning CheckToPlayLevelTransitionSound lda levelTransitionSoundIndex ; get level transition sound index beq CheckToPlayGameOverSounds ; branch if done level transition sound dec levelTransitionSoundIndex beq .donePlayLevelTransitionSound tay ; save level transition sound to y register lsr ; divide value by 8 for frequency lsr lsr sta AUDF0 sta AUDF1 tya ; get level transition sound index and #$0F sta AUDV1 sta AUDV0 lda #4 sta AUDC0 lda #7 sta AUDC1 jmp CalculateObjectHMOVEValues .donePlayLevelTransitionSound lda #0 sta AUDV1 sta AUDV0 sta levelTransitionSoundIndex sta allowedToSpawnObstacles ; set to allow obstacle spawning sta playerShipCollisionSoundIndex; clear player ship collision sound index sta tmpPlayerShipCollisionValue ; clear player ship collision value sta kernelStatus ; set kernel status to show game kernel sta playerShipShotHorizPos sta playerShipShotHorizPos + 1 sta playerShipShotHorizPos + 2 sta playerShipShotHorizPos + 3 sta playerShipShotHorizPos + 4 sta playerShipShotHorizPos + 5 sta playerShipShotHorizPos + 6 sta prizesCollected ; clear number of prizes collected lda #PlayerShipGraphics sta playerShipGraphicPtr + 1 ldx #1 stx playerShipAlley ; place player ship in alley 1 ldx #$FF txs jsr SetObstacleValuesForGameLevel lda gameLevel ; get current game level cmp #3 bcc .resetLaneColor ; branch if less than level 3 lda laneColorStatus ; get lane color status beq .setLaneColorToBlack ; branch if cycling lane colors .resetLaneColor lda #ULTRAMARINE_BLUE + 8 sta laneColor lda #0 sta laneColorStatus ; clear lane color status beq CheckToPlayGameOverSounds ; unconditional branch .setLaneColorToBlack lda #<-1 sta laneColorStatus ; set to not cycle lane color lda #BLACK sta laneColor ; color lanes to BLACK CheckToPlayGameOverSounds lda gameOverSoundIndex ; get game over sound index beq CheckForGameRestart dec gameOverSoundNoteHoldValue ; decrement value to hold game over notes bne .jmpCheckForResetSwitchPressed lda #6 sta gameOverSoundNoteHoldValue ; hold note for 6 frames inc gameOverSoundIndex ; increment game over sound index lda gameOverSoundIndex ; get game over sound index tay ; save game over sound index to y register lda #4 sta AUDC0 lda #5 sta AUDC1 ; set game over audio channel values lda #15 sta AUDV0 sta AUDV1 ; set to maximum volume tya ; move game over sound index to accumulator eor #$0F ; flip lower nybbles to decrease value sta AUDF0 tya ; move game over sound index to accumulator eor #8 sta AUDF1 cpy #48 bcs .donePlayGameOverSounds .jmpCheckForResetSwitchPressed jmp .checkForResetSwitchPressed .donePlayGameOverSounds lda #PlayerShipGraphics sta playerShipGraphicPtr + 1 lda #0 sta AUDV1 ; turn off sound by reducing volume sta AUDV0 sta gameOverSoundIndex ; clear game over sound index sta gameState sta gameLevel sta obstaclesDestroyed ; reset number of obstacles destroyed ldx #$FF txs jsr SetObstacleValuesForGameLevel lda #ULTRAMARINE_BLUE + 8 sta laneColor lda tmpHighScoreIndexValues ; get high score ten thousands index cmp tmpScoreIndexValues + 3 ; compare with score ten thousands index bcc .setHighScoreValues ; set high score values bne CheckForGameRestart lda tmpHighScoreIndexValues + 1 ; get high score thousands index value cmp tmpScoreIndexValues + 2 ; compare with score thousands index value bcc .setHighScoreValues ; set high score values bne CheckForGameRestart lda tmpHighScoreIndexValues + 2 ; get high score hundreds index value cmp tmpScoreIndexValues + 1 ; compare with score hundreds index value bcc .setHighScoreValues ; set high score values bne CheckForGameRestart lda tmpHighScoreIndexValues + 3 ; get high score tens index value cmp tmpScoreIndexValues ; compare with score tens index value bcc .setHighScoreValues ; set high score values bne CheckForGameRestart .setHighScoreValues lda tmpScoreIndexValues + 3 ; get score ten thousands index sta tmpHighScoreIndexValues ; set high score ten thousands index lda tmpScoreIndexValues + 2 ; get score thousands index value sta tmpHighScoreIndexValues + 1 ; set high score thousands index value lda tmpScoreIndexValues + 1 ; get score hundreds index value sta tmpHighScoreIndexValues + 2 ; set high score hundreds index value lda tmpScoreIndexValues ; get score tens index value sta tmpHighScoreIndexValues + 3 ; set high score tens index value CheckForGameRestart lda INPT4 ; read left port action button bmi .checkForResetSwitchPressed ; branch if button not pressed lda gameState ; get current game state bpl .startNewGame ; branch if game not in progress .checkForResetSwitchPressed lda SWCHB ; read console switches lsr ; shift RESET to carry bcs .checkForResetSwitchReleased ; branch if RESET not pressed .startNewGame ldy #<-1 sty resetDebounce ; set D7 high to show RESET held sty gameState ; set game state to game in progress iny ; y = 0 sty prizeFrameLoopCount ; clear prize frame loop count sty currentPrizeLane ; clear value for prize lane sty playerScore sty playerScore + 1 sty AUDV1 ; turn off sound by reducing volume sty AUDV0 sty gameOverSoundIndex ; clear game over sound index sty levelTransitionSoundIndex sty allowedToSpawnObstacles ; set to allow obstacle spawning iny ; y = 1 sty laneColorStatus ; set to not cycle lane color sty playerShipAlley ; place player ship in alley 1 lda #INIT_RESERVED_SHIPS sta reservedShips ; set initial number of reserved ships lda ReservedShipsHorizPosValues + 3 sta reservedShipsHorizPos jmp CalculateObjectHMOVEValues .checkForResetSwitchReleased lda resetDebounce ; get RESET debounce value bpl .checkForGameOverDisplayState; branch if RESET switch not held sta gameState ldx #$FF txs jsr SetObstacleValuesForGameLevel lda #0 sta resetDebounce ; clear debounce to show RESET not held sta tmpPlayerShipCollisionValue ; clear player ship collision value sta obstaclesDestroyed ; reset number of obstacles destroyed lda #1 sta kernelStatus ; set kernel status to show transition lda gameLevel ; get current game level sta savedGameLevel ; never used or referenced dec gameLevel ; decrement game level lda #PlayerShipGraphics sta playerShipGraphicPtr + 1 jmp CalculateObjectHMOVEValues .checkForGameOverDisplayState lda gameOverSoundIndex ; get game over sound index beq CheckGameSelectSwitch ; branch if not playing game over sounds jmp DisplayKernel CheckGameSelectSwitch lda SWCHB ; read console switches lsr ; shift RESET to carry lsr ; shift SELECT to carry bcc .selectSwitchPressed sta selectDebounce ; clear D7 value to show SELECT not pressed bpl CheckPlayerShipCollision ; unconditional branch .selectSwitchPressed lda #0 sta AUDV1 ; turn off sound by reducing volume sta AUDV0 sta prizeFrameLoopCount ; clear prize frame loop count sta playerShipCollisionSoundIndex; clear player ship collision sound index lda #INIT_PLAYER_SHIP_HORIZ sta playerShipHorizPos lda #PlayerShipGraphics sta playerShipGraphicPtr + 1 lda #ULTRAMARINE_BLUE + 8 sta laneColor lda selectDebounce ; get SELECT debounce value bpl .incrementGameSelection ; branch if SELECT released lda gameState ; get current game state clc adc #3 ; increment value by 3 sta gameState bpl CheckPlayerShipCollision ; branch if less than 128 lda #0 ; increment game selection ~43 frames sta gameState .incrementGameSelection inc gameLevel ; increment game level lda gameLevel ; get current game level cmp #MAX_GAME_LEVEL + 1 bcc .setSelectDebounceToSelectHeld lda #0 sta gameLevel ; reset game level .setSelectDebounceToSelectHeld lda #<-1 sta selectDebounce ; set debounce to show SELECT held ldx #$FF txs jsr SetObstacleValuesForGameLevel CheckPlayerShipCollision SUBROUTINE lda playerShipCollisionSoundIndex; get player ship collision sound index bne .cycleLaneColorsForCollision ; branch if playing collision sound lda tmpPlayerShipCollisionValue ; get player ship collision value bpl .jmpToResetPlayerShipGraphics; branch if no collision lda gameState ; get current game state bmi .playerShipCollisionWithObstacle; branch if game in progress .jmpToResetPlayerShipGraphics jmp .resetPlayerShipGraphics .playerShipCollisionWithObstacle ldy playerShipAlley ; get Player Ship alley lda obstacleList - 1,y ; get obstacle type in Player Ship alley cmp #ID_PRIZE bne .playerShipCollidedWithObstacle; branch if ID_PRIZE not in alley sta tmpPlayerShipCollisionValue ; clear collision value for ID_PRIZE lda #80 sta prizePointValue ; rewarded 800 points for collecting prize lda #0 sta prizeFrameLoopCount ; clear prize frame loop count lda #ID_GHOST_SHIP sta obstacleList - 1,y ; spawn ID_PRIZE to ID_GHOST_SHIP lda playerShipHorizPos cmp #INIT_PLAYER_SHIP_HORIZ bcs .placeGhostShipOnLeftSide lda #XMAX - 5 sta obstacleHorizPos - 1,y lda #1 << 4 | OBSTACLE_DIR_LEFT sta obstacleAttributes - 1,y bne .jmpToResetPlayerShipGraphics; unconditional branch .placeGhostShipOnLeftSide lda #XMIN + 6 sta obstacleHorizPos - 1,y lda #1 << 4 | OBSTACLE_DIR_RIGHT sta obstacleAttributes - 1,y bne .jmpToResetPlayerShipGraphics .playerShipCollidedWithObstacle lda #ID_BLANK sta obstacleList - 1,y ; remove obstacle from list .cycleLaneColorsForCollision lda gameOverSoundNoteHoldValue cmp #2 beq .changeLaneColorForDeathSequence cmp #8 bne .setReservedShipsHorizPos .changeLaneColorForDeathSequence inc playerShipCollisionSoundIndex lda laneColorStatus ; get lane color status bne .playShipDeathSound ; branch if not cycling lane colors inc laneColor ; increment lane color luminance .playShipDeathSound lda playerShipCollisionSoundIndex; get player ship collision sound index tay ; move sound index to y register lda #13 sta AUDC0 lda #4 sta AUDC1 lda #15 sta AUDV0 sta AUDV1 tya ; move sound index to accumulator eor #$0F sta AUDF0 tya ; move sound index to accumulator eor #8 sta AUDF1 cpy #23 bcs .setValuesForDeathSequenceEnd; branch if sound index greater than 22 lda PlayerShipDeathGraphicsLSBValues,y sta playerShipGraphicPtr lda #>PlayerShipDeathGraphics sta playerShipGraphicPtr + 1 bmi .setReservedShipsHorizPos ; unconditional branch .setValuesForDeathSequenceEnd lda #PlayerShipGraphics sta playerShipGraphicPtr + 1 lda #0 sta prizePointValue sta tankSpawnSoundIndex ; clear Tank spawn sound index sta arrowSpawnSoundIndex ; clear Arrow spawn sound index sta levelTransitionSoundIndex sta AUDV0 ; turn off sound by reducing volume sta AUDV1 sta playerShipCollisionSoundIndex; clear player ship collision sound index sta tmpPlayerShipCollisionValue sta ghostShipSpawnTimer ; reset Ghost Ship timer lda #10 sta arrowSpawnSoundIndex lda #INIT_PLAYER_SHIP_HORIZ sta playerShipHorizPos lda laneColorStatus ; get lane color status bne .decrementReservedShips ; branch if not cycling lane colors lda #ULTRAMARINE_BLUE + 8 sta laneColor .decrementReservedShips dec reservedShips ; decrement number of reserved ships bpl .resetPlayerShipGraphics ldy #0 sty reservedShips ; set number of reserved ships to 0 iny ; y = 1 sty gameOverSoundIndex .resetPlayerShipGraphics lda #> 4 sta playerScore lda playerScore + 1 ; get score thousands value adc #1 - 1 ; increment by one when carry set sta playerScore + 1 cld .setObstacleToExplosion lda #ID_EXPLOSION sta obstacleList,x ; get obstacle type to ID_EXPLOSION lda obstacleAttributes,x and #OBSTACLE_DIR_MASK ; keep DIRECTION value beq .explosionTravelingLeft ; branch if obstacle traveling left lda obstacleList,x ; BUG?? should be obstacleHorizPos,x?? cmp #(XMAX / 2) + 5 bcs .movePlayerShipShot lda obstacleAttributes,x ; get obstacle movement values eor #OBSTACLE_DIR_MASK ; flip obstacle direction bit sta obstacleAttributes,x .explosionTravelingLeft lda obstacleHorizPos,x ; get obstacle horizontal position cmp #(XMAX / 2) + 5 bcc .movePlayerShipShot ; branch if obstacle on left side lda obstacleAttributes,x ; get obstacle movement values eor #OBSTACLE_DIR_MASK ; flip obstacle direction bit sta obstacleAttributes,x .movePlayerShipShot lda playerShipShotHorizPos,x ; get player ship shot horizontal position beq .nextLane ; branch if reached left side clc adc playerShipShotHorizDir,x ; increment by direction value sta playerShipShotHorizPos,x ; set player ship shot horizontal position cmp #XMAX - 2 bcs .turnOffPlayerShot ; branch if reached right side cmp #XMIN + 1 bcs .nextLane .turnOffPlayerShot lda #XMIN sta playerShipShotHorizPos,x .nextLane dex bmi AnimateObstacleGraphics jmp .processPlayerShots AnimateObstacleGraphics lda obstacleAnimationIndex ; get obstacle animation index value clc adc #OBSTACLE_ANIMATION_RATE ; animate obstacles ~ every 5 frames sta obstacleAnimationIndex ; set new animation index value bpl .firstObstacleAnimationPtrs ; branch if animation index is positive lda #SneakerGraphics sta sneakerGraphicPtr + 1 ; set Sneaker MSB value lda sneakerGraphicPtr ; get Sneaker LSB value cmp #> 4 ; keep MOVE_RIGHT value beq .checkForJoystickMovingLeft ldx playerShipAlley ; get Player Ship alley lda obstacleList - 1,x ; get obstacle type in Player Ship alley cmp #ID_PRIZE beq .checkToMovePlayerShipRight lda playerShipHorizPos cmp #INIT_PLAYER_SHIP_HORIZ beq .facePlayerShipRight .checkToMovePlayerShipRight lda playerShipHorizPos ; get player ship horizontal position cmp #XMAX - 16 bcs .facePlayerShipRight ; branch if reached right side lda gameState ; get current game state bpl .facePlayerShipRight ; branch if game not in progress inc playerShipHorizPos ; move player ship right inc playerShipHorizPos ; move player ship right .facePlayerShipRight lda #NO_REFLECT sta playerShipReflectValue beq .checkForJoystickMovingUp ; unconditional branch .checkForJoystickMovingLeft tya ; move joystick values to accumulator and #<(~MOVE_LEFT) >> 4 ; keep MOVE_LEFT value beq .checkForJoystickMovingUp ldx playerShipAlley ; get Player Ship alley lda obstacleList - 1,x ; get obstacle type in Player Ship alley cmp #ID_PRIZE beq .checkToMovePlayerShipLeft lda playerShipHorizPos cmp #(XMAX / 2) - 6 beq .facePlayerShipLeft .checkToMovePlayerShipLeft lda playerShipHorizPos cmp #XMIN + 8 bcc .facePlayerShipLeft lda gameState ; get current game state bpl .facePlayerShipLeft ; branch if game not in progress dec playerShipHorizPos dec playerShipHorizPos .facePlayerShipLeft lda #REFLECT sta playerShipReflectValue .checkForJoystickMovingUp tya ; move joystick values to accumulator and #<(~MOVE_UP) >> 4 ; keep MOVE_UP value beq .checkForJoystickMovingDown ; branch if joystick not moved up inc playerShipVertDelay ; increment player ship vertical delay value lda playerShipVertDelay ; get player ship vertical delay value cmp #4 bcc .doneCheckToMovePlayerShip ; branch if not time to move lda #0 sta playerShipVertDelay sta ghostShipSpawnTimer ; clear timer for vertical movement lda #14 sta playerShipVertSoundIndex lda playerShipHorizPos cmp #(XMAX / 2) - 10 bcc .doneCheckToMovePlayerShip cmp #(XMAX / 2) bcs .doneCheckToMovePlayerShip lda #INIT_PLAYER_SHIP_HORIZ sta playerShipHorizPos inc playerShipAlley ; move player ship up lda playerShipAlley ; get player ship alley cmp #NUM_LANES bcc .doneCheckToMovePlayerShip lda #NUM_LANES sta playerShipAlley bpl .doneCheckToMovePlayerShip .checkForJoystickMovingDown tya ; move joystick values to accumulator and #<(~MOVE_DOWN) >> 4 ; keep MOVE_DOWN value beq .doneCheckToMovePlayerShip ; branch if joystick not moved down inc playerShipVertDelay ; increment player ship vertical delay value lda playerShipVertDelay ; get player ship vertical delay value cmp #4 bcc .doneCheckToMovePlayerShip ; branch if not time to move lda #14 sta playerShipVertSoundIndex lda #0 sta playerShipVertDelay sta ghostShipSpawnTimer ; clear timer for vertical movement lda playerShipHorizPos cmp #(XMAX / 2) - 10 bcc .doneCheckToMovePlayerShip cmp #(XMAX / 2) - 1 bcs .doneCheckToMovePlayerShip lda #INIT_PLAYER_SHIP_HORIZ sta playerShipHorizPos dec playerShipAlley ; move player ship down bne .doneCheckToMovePlayerShip inc playerShipAlley .doneCheckToMovePlayerShip lda gameState ; get current game state bpl .playerShipFiringShot ; branch if game not in progress lda INPT4 ; read left port action button bmi CalculateObjectHMOVEValues ; branch if button not pressed .playerShipFiringShot lda playerShipHorizPos cmp #INIT_PLAYER_SHIP_HORIZ bne CalculateObjectHMOVEValues ldy playerShipAlley ; get Player Ship alley inc random + 1 dey lda playerShipShotHorizPos,y ; get shot horizontal position bne CalculateObjectHMOVEValues ; branch if Player Shot active in alley lda obstacleList,y ; get obstacle type for lane cmp #ID_PRIZE beq CalculateObjectHMOVEValues ; don't allow shots in alley with ID_PRIZE lda #(XMAX / 2) - 2 sta playerShipShotHorizPos,y ; set player shot inital horizontal position lda #14 sta playerShotSoundIndex lda playerShipReflectValue ; get player ship direction bne .setPlayerShotDirToTravelLeft; branch if player ship traveling left lda #4 sta playerShipShotHorizDir,y bpl CalculateObjectHMOVEValues ; unconditional branch .setPlayerShotDirToTravelLeft lda #<-4 sta playerShipShotHorizDir,y CalculateObjectHMOVEValues ldy #15 .calculateObjectHMOVEValues lda objectHorizPos,y ; get object horizontal position ldx #1 .determineObjectCoarseValue cmp #15 bcc .setObjectFineCoarsePositionValue sec sbc #15 ; divide position value by 15 inx ; increment x for coarse value bne .determineObjectCoarseValue ; unconditional branch .setObjectFineCoarsePositionValue stx kernelFCPosValues,y ; set object coarse value tax ; shift div15 remainder to x register lda ObjectFineHMOVEValues,x ; get fine motion value based on remainder ora kernelFCPosValues,y ; combine with coarse value sta kernelFCPosValues,y ; set object fine / coarse position value dey bpl .calculateObjectHMOVEValues DisplayKernel SUBROUTINE .waitTime lda INTIM bne .waitTime sta WSYNC ;-------------------------------------- sta VBLANK ; 3 = @03 enable TIA (i.e. D1 = 0) lda #7 ; 2 sta currentKernelLane ; 3 ldx #H_KERNEL ; 2 .displayKernel sta WSYNC ;-------------------------------------- cpx #H_KERNEL ; 2 beq DrawTurmoilLiteralKernel;2³ .waitForKernelDone dex ; 2 beq .doneDisplayKernel ; 2³ jmp .displayKernel ; 3 .doneDisplayKernel lda #BLACK ; 2 sta COLUPF ; 3 = @14 jmp NewFrame .jmpToDrawScoreKernel jmp DrawScoreKernel ; 3 DrawTurmoilLiteralKernel lda #NO_REFLECT ; 2 sta REFP0 ; 3 = @10 sta REFP1 ; 3 = @13 lda gameState ; 3 get current game state bmi .jmpToDrawScoreKernel ; 2³ branch if game in progress lda laneColor ; 3 cmp #ULTRAMARINE_BLUE + 8 ; 2 bcs .jmpToDrawScoreKernel ; 2³ sta HMCLR ; 3 = @28 lda tmpTurmoilLiteralColor ; 3 sta COLUP0 ; 3 = @34 sta COLUP1 ; 3 = @37 ldx #4 ; 2 sta WSYNC ;-------------------------------------- .skip4Scanlines dex ; 2 bne .skip4Scanlines ; 2³ SLEEP 2 ; 2 SLEEP 2 ; 2 SLEEP_7 ; 7 SLEEP 2 ; 2 lda #HMOVE_L1 ; 2 sta HMP1 ; 3 = @22 sta RESP0 ; 3 = @25 sta RESP1 ; 3 = @28 sta WSYNC ;-------------------------------------- sta HMOVE ; 3 lda #THREE_COPIES ; 2 sta NUSIZ0 ; 3 = @08 sta NUSIZ1 ; 3 = @11 lda #H_DIGITS - 1 ; 2 sta tmpTurmoilFontLoop ; 3 sta VDELP0 ; 3 = @19 sta VDELP1 ; 3 = @22 .drawTurmoilLiteral ldy tmpTurmoilFontLoop ; 3 lda TurmoilLiteral_05,y ; 4 sta.w tmpTurmoilLiteral_05 ; 4 sta WSYNC ;-------------------------------------- lda TurmoilLiteral_04,y ; 4 tax ; 2 lda TurmoilLiteral_00,y ; 4 SLEEP 2 ; 2 SLEEP_3 ; 3 sta GRP0 ; 3 = @18 lda TurmoilLiteral_01,y ; 4 sta.w GRP1 ; 4 = @26 lda TurmoilLiteral_02,y ; 4 sta.w GRP0 ; 4 = @34 lda TurmoilLiteral_03,y ; 4 ldy.w tmpTurmoilLiteral_05 ; 4 sta GRP1 ; 3 = @45 stx GRP0 ; 3 = @48 sty GRP1 ; 3 = @51 sta GRP0 ; 3 = @54 dec tmpTurmoilFontLoop ; 5 bpl .drawTurmoilLiteral ; 2³ lda #0 ; 2 sta VDELP0 ; 3 = @66 sta VDELP1 ; 3 = @69 sta GRP0 ; 3 = @72 sta GRP1 ; 3 = @75 ;-------------------------------------- jmp .doneTopStatusKernel ; 3 = @02 DrawScoreKernel sta HMCLR ; 3 = @32 lda #WHITE ; 2 sta COLUP0 ; 3 = @37 sta COLUP1 ; 3 = @40 lda #NO_REFLECT ; 2 sta REFP0 ; 3 = @45 ldx #4 ; 2 lda #HMOVE_L1 ; 2 sta HMP1 ; 3 = @52 sta WSYNC ;-------------------------------------- lda #ONE_COPY ; 2 sta NUSIZ0 ; 3 = @05 sta REFP1 ; 3 = @08 SLEEP_3 ; 3 SLEEP_3 ; 3 SLEEP 2 ; 2 SLEEP_3 ; 3 .coarsePositionScoreDigits dex ; 2 bne .coarsePositionScoreDigits;2³ sta RESP0 ; 3 sta RESP1 ; 3 sta WSYNC ;-------------------------------------- sta HMOVE ; 3 lda #one ; 2 sta tmpPlayLevelGraphicPtrs + 1;3 lda #THREE_COPIES ; 2 sta NUSIZ0 ; 3 = @18 lda #TWO_COPIES ; 2 sta NUSIZ1 ; 3 = @23 lda gameState ; 3 get current game state bmi .drawScore ; 2³ branch if game in progress lda laneColor ; 3 cmp #OLIVE_GREEN + 8 ; 2 bcc .drawScore ; 2³ lda #BRICK_RED + 8 ; 2 sta COLUP0 ; 3 sta COLUP1 ; 3 bpl .drawHighScore ; 3 unconditional branch .drawScore ldy tmpScoreIndexValues ; 3 get value for tens position lda (digitGraphicPtrs),y ; 5 get tens value graphic data tax ; 2 move tens position graphic data to x ldy tmpScoreIndexValues + 3; 3 get value for ten thousands position sta WSYNC ;-------------------------------------- SLEEP 2 ; 2 lda (digitGraphicPtrs),y ; 5 get ten thousands value graphic data ldy tmpScoreIndexValues + 2; 3 get value for thousands position sta GRP0 ; 3 = @13 lda (digitGraphicPtrs),y ; 5 get thousands value graphic data sta GRP1 ; 3 = @21 ldy tmpScoreIndexValues + 1; 3 get value for hundreds position lda (digitGraphicPtrs),y ; 5 get hundreds value graphic data sta tmpHundredsGraphic ; 3 ldy #NumberFonts ; 2 sta tmpPlayLevelGraphicPtrs + 1;3 sta WSYNC ;-------------------------------------- dec transitionKernelBKColor;5 sta WSYNC ;-------------------------------------- sta WSYNC ;-------------------------------------- sta WSYNC ;-------------------------------------- sta WSYNC ;-------------------------------------- sta WSYNC ;-------------------------------------- inc tmpTransitionKernelPFColorIdx;5 ldx #H_LEVEL_TRANSITION_KERNEL;2 ldy transitionKernelBKColor; 3 lda tmpTransitionKernelPFColorIdx;3 sta transitionKernelPFColor; 3 lda #$C8 ; 2 sta PF0 ; 3 = @21 lda #$3C ; 2 sta PF1 ; 3 = @26 lda #$2C ; 2 sta PF2 ; 3 = @31 SLEEP_3 ; 3 SLEEP_3 ; 3 SLEEP 2 ; 2 sta RESP1 ; 3 = @42 sta.w RESP0 ; 4 = @46 sta COLUP1 ; 3 = @49 lda #QUAD_SIZE ; 2 sta NUSIZ1 ; 3 = @54 .levelTransitionKernel dec transitionKernelPFColor; 5 lda transitionKernelPFColor; 3 sta WSYNC ;-------------------------------------- sta COLUPF ; 3 = @03 dey ; 2 sty COLUBK ; 3 = @08 cpx #H_LEVEL_TRANSITION_KERNEL - 84;2 bne .checkToDrawSecondKernelSection;2³ lda #0 ; 2 sta GRP1 ; 3 = @17 sta GRP0 ; 3 = @20 beq .nextLevelTransitionLine;3 unconditional branch .checkToDrawSecondKernelSection bcc .nextLevelTransitionLine;2³ cpx #H_LEVEL_TRANSITION_KERNEL - 54;2 bcs .nextLevelTransitionLine;2³ cpx #H_LEVEL_TRANSITION_KERNEL - 64;2 bcc .checkToDrawPlayLevel ; 2³ lda #$FF ; 2 sta GRP1 ; 3 = @28 lda #0 ; 2 sta GRP0 ; 3 = @33 sta COLUP1 ; 3 = @36 beq .nextLevelTransitionLine;3 unconditional branch .checkToDrawPlayLevel cpx #H_LEVEL_TRANSITION_KERNEL - 72;2 bcc .clearPlayLevelGraphics; 2³ sty tmpTransitionKernelBKColor;3 ldy tmpPlayLevelIndex ; 3 lda (tmpPlayLevelGraphicPtrs),y;5 sta GRP0 ; 3 = @42 dec tmpPlayLevelIndex ; 5 ldy tmpTransitionKernelBKColor;3 bne .nextLevelTransitionLine;2³ .clearPlayLevelGraphics lda #0 ; 2 sta GRP0 ; 3 .nextLevelTransitionLine dex ; 2 bne .levelTransitionKernel ; 2³ + 1 sta WSYNC ;-------------------------------------- stx COLUPF ; 3 = @03 stx COLUBK ; 3 = @06 stx NUSIZ1 ; 3 = @09 ldx #4 ; 2 .wait4Scanlines sta WSYNC ;-------------------------------------- dex ; 2 bne .wait4Scanlines ; 2³ jmp DrawStatusKernel ; 3 GamePlayKernel lda #MSBL_SIZE8 ; 2 sta NUSIZ0 ; 3 lda playerShipFCValue ; 3 sta HMP0 ; 3 and #$0F ; 2 tax ; 2 sta WSYNC ;-------------------------------------- lda playerShipReflectValue ; 3 get player ship reflect value sta REFP0 ; 3 = @06 lda playerShipFCValue ; 3 waste 3 cycles SLEEP 2 ; 2 SLEEP_3 ; 3 SLEEP_3 ; 3 .coarsePositionPlayerShip dex ; 2 bne .coarsePositionPlayerShip;2³ sta RESP0 ; 3 sta WSYNC ;-------------------------------------- sta HMOVE ; 3 sta WSYNC ;-------------------------------------- stx HMP0 ; 3 = @03 BeginLaneKernel ldy currentKernelLane ; 3 lda playerShipShotFCValues - 1,y;4 get Player Ship shot HMOVE value and #$0F ; 2 keep coarse position value tax ; 2 sta WSYNC ;-------------------------------------- lda playerShipShotFCValues - 1,y;4 get Player Ship shot HMOVE value sta HMM0 ; 3 = @07 set Player Ship fine motion value sta CXCLR ; 3 = @10 clear all collisions lda laneColor ; 3 sta COLUPF ; 3 = @16 .coarsePositionPlayerShot dex ; 2 bne .coarsePositionPlayerShot;2³ sta RESM0 ; 3 sta WSYNC ;-------------------------------------- lda #$FF ; 2 sta PF0 ; 3 = @05 sta PF1 ; 3 = @08 lda LanePF2GraphicData,y ; 4 sta PF2 ; 3 = @15 lda obstacleFCValues - 1,y ; 4 sta HMP1 ; 3 = @22 and #$0F ; 2 tax ; 2 sta WSYNC ;-------------------------------------- lda obstacleFCValues - 1,y; 4 SLEEP 2 ; 2 SLEEP 2 ; 2 SLEEP 2 ; 2 SLEEP 2 ; 2 SLEEP_3 ; 3 .coarsePositionObstacle dex ; 2 bne .coarsePositionObstacle; 2³ sta RESP1 ; 3 sta WSYNC ;-------------------------------------- lda playerShipShotHorizPos - 1,y;4 beq .playerShotDisabled ; 2³ lda #PlayerShotEnabledGraphicValues;2 sta playerShipShotPtr + 1 ; 3 bmi .determineObstacleColorLSBValue;3 unconditional branch .playerShotDisabled lda #BlankGraphic ; 2 sta playerShipShotPtr + 1 ; 3 .determineObstacleColorLSBValue lda obstacleList - 1,y ; 4 = @23 get obstacle type tay ; 2 shift obstacle type to y register cpy #ID_ARROW ; 2 beq .setObstacleColorLSBForArrow;2³ cpy #ID_GHOST_SHIP ; 2 beq .setObstacleColorLSBForGhostShip;2³ cpy #ID_EXPLOSION ; 2 bcc .setObstacleColorLSBValue;2³ lda #BlankGraphic ; 2 sta tmpKernelShipGraphicPtr + 1;3 bmi .startDrawKernelLane ; 3 unconditional branch .setToDrawPlayerShip lda playerShipGraphicPtr ; 3 sta tmpKernelShipGraphicPtr; 3 lda playerShipGraphicPtr + 1;3 sta tmpKernelShipGraphicPtr + 1;3 .startDrawKernelLane sta WSYNC ;-------------------------------------- sta HMOVE ; 3 lda #0 ; 2 sta PF0 ; 3 = @08 sta PF1 ; 3 = @11 sta PF2 ; 3 = @14 dec currentKernelLane ; 5 bmi DrawStatusKernel ; 2³ jmp DrawKernelLane ; 3 DrawStatusKernel lda #NO_REFLECT ; 2 sta REFP0 ; 3 = @27 sta REFP1 ; 3 = @30 lda gameState ; 3 get current game state bmi DrawReservedShipsKernel; 2³ branch if game in progress lda transitionKernelBKColor; 3 waste 3 cycles ldy gameLevel ; 3 get current game level lda NumberLSBValues,y ; 4 sta tmpPlayLevelGraphicPtrs; 3 lda #>NumberFonts ; 2 sta tmpPlayLevelGraphicPtrs + 1;3 lda #HMOVE_R4 | 5 ; 2 sta HMP0 ; 3 and #$0F ; 2 tax ; 2 sta WSYNC ;-------------------------------------- SLEEP_3 ; 3 SLEEP 2 ; 2 SLEEP 2 ; 2 SLEEP_3 ; 3 SLEEP_3 ; 3 SLEEP_3 ; 3 SLEEP_3 ; 3 .coarsePositionPlayLevel dex ; 2 bne .coarsePositionPlayLevel;2³ sta RESP0 ; 3 sta WSYNC ;-------------------------------------- lda laneColor ; 3 cmp #ULTRAMARINE_BLUE + 8 ; 2 bcc DrawSneakerKernel ; 2³ ldy #H_DIGITS ; 2 .drawDemoPlayLevelValue lda #WHITE ; 2 sta WSYNC ;-------------------------------------- sta COLUP0 ; 3 = @03 lda (tmpPlayLevelGraphicPtrs),y;5 sta GRP0 ; 3 = @11 dey ; 2 bpl .drawDemoPlayLevelValue; 2³ lda #0 ; 2 sta GRP0 ; 3 = @20 sta WSYNC ;-------------------------------------- sta WSYNC ;-------------------------------------- .jmpIntoDoneStatusKernel sta WSYNC ;-------------------------------------- sta WSYNC ;-------------------------------------- sta WSYNC ;-------------------------------------- jmp .doneStatusKernel ; 3 DrawSneakerKernel ldy #H_SNEAKERS - 1 ; 2 .drawSneakerKernel sta WSYNC ;-------------------------------------- lda SneakerColorValues,y ; 4 sta COLUP0 ; 3 = @07 lda (sneakerGraphicPtr),y ; 5 sta GRP0 ; 3 = @15 dey ; 2 bpl .drawSneakerKernel ; 2³ sta WSYNC ;-------------------------------------- SLEEP 2 ; 2 SLEEP 2 ; 2 SLEEP 2 ; 2 lda #0 ; 2 sta GRP0 ; 3 = @11 beq .jmpIntoDoneStatusKernel;3 unconditional branch DrawReservedShipsKernel lda #NO_REFLECT ; 2 sta REFP0 ; 3 = @41 sta REFP1 ; 3 = @44 ldy reservedShips ; 3 get number of reserved ships lda GRP0_ReservedLivesLSBValues,y;4 sta tmpLivesGraphicPtrs_00 ; 3 lda GRP0_ReservedLivesMSBValues,y;4 sta tmpLivesGraphicPtrs_00 + 1;3 lda GRP1_ReservedLivesLSBValues,y;4 sta tmpLivesGraphicPtrs_01 ; 3 lda GRP1_ReservedLivesMSBValues,y;4 sta tmpLivesGraphicPtrs_01 + 1;3 lda reservedShipsFCValue ; 3 sta HMP0 ; 3 sta HMP1 ; 3 and #$0F ; 2 tax ; 2 sta WSYNC ;-------------------------------------- ldy reservedShips ; 3 get number of reserved ships lda LeftReservedShipNUSIZValues,y;4 sta NUSIZ0 ; 3 = @10 lda RightReservedShipNUSIZValues,y;4 sta NUSIZ1 ; 3 = @17 .coarsePositionReservedShips dex ; 2 bne .coarsePositionReservedShips;2³ sta RESP0 ; 3 SLEEP 2 ; 2 SLEEP 2 ; 2 SLEEP_3 ; 3 SLEEP_3 ; 3 SLEEP_3 ; 3 sta RESP1 ; 3 sta WSYNC ;-------------------------------------- sta HMOVE ; 3 ldy #12 ; 2 .drawReservedShips lda (tmpLivesGraphicPtrs_00),y ;5 ldx PlayerShipColorValues,y; 4 sta WSYNC ;-------------------------------------- sta GRP0 ; 3 = @03 stx COLUP0 ; 3 = @06 stx COLUP1 ; 3 = @09 lda (tmpLivesGraphicPtrs_01),y;5 sta GRP1 ; 3 = @17 dey ; 2 bpl .drawReservedShips ; 2³ .doneStatusKernel ldx #OVERSCAN_SCANLINES ; 2 jmp .waitForKernelDone ; 3 DrawKernelLane ldy #H_KERNEL_LANE - 1 ; 2 .drawKernelLane lda (obstacleColorPtrs),y ; 5 tax ; 2 lda (tmpKernelShipGraphicPtr),y;5 sta tmpPlayerShipGraphic ; 3 lda (playerShipShotPtr),y ; 5 sta tmpEnableDisablePlayShot;3 lda (obstacleGraphicPtr),y ; 5 sta WSYNC ;-------------------------------------- sta GRP1 ; 3 = @03 lda PlayerShipColorValues,y; 4 sta COLUP0 ; 3 = @10 lda tmpEnableDisablePlayShot;3 sta ENAM0 ; 3 = @16 lda tmpPlayerShipGraphic ; 3 stx COLUP1 ; 3 = @22 sta GRP0 ; 3 = @25 dey ; 2 bpl .drawKernelLane ; 2³ lda CXPPMM ; 3 read player collision values bpl .checkPlayerObstacleCollision;2³ branch if players didn't collide sta tmpPlayerShipCollisionValue;3 bmi .jmpToBeginLaneKernel ; 3 unconditional branch .checkPlayerObstacleCollision lda CXM0P ; 3 read player missile 0 collision value bpl .jmpToBeginLaneKernel ; 2³ branch if obstacle not shot ldy currentKernelLane ; 3 lda obstacleShotCollisionValues;3 ora LaneShotCollisionMaskValues,y;4 sta obstacleShotCollisionValues;3 .jmpToBeginLaneKernel jmp BeginLaneKernel ; 3 SpawnNewObstacle ldx playerShipAlley ; get Player Ship alley dex ; decrement for player ship lane lda obstacleHorizPos,x ; get obstacle horizontal position bne .newRandom ; branch if obstacle moving lda ghostShipSpawnTimer ; get Ghost Ship timer value bpl .newRandom ; branch if not spawning Ghost Ship lda #INIT_GHOST_SHIP_SOUND_INDEX sta ghostShipSoundIndex lda #ID_GHOST_SHIP sta ghostShipSpawnTimer ; set Ghost Ship timer value bne .setNewObstacle ; spawn Ghost Ship in player ship lane .newRandom jmp NewRandom DetermineLocationForSpawnedObstacle lda random + 1 ; get random high byte lsr ; divide value by 32 lsr lsr lsr lsr tax ; set for new spawned obstacle position beq .checkIfObstaclePresentInPosition; branch if top of list dex .checkIfObstaclePresentInPosition lda obstacleHorizPos,x ; get obstacle horizontal position beq .checkIfAllowedToSpawnObstacles; branch if obstacle not present ldx tmpObstacleIndex .checkIfAllowedToSpawnObstacles lda newSpawnedObstacle ldy playerShipCollisionSoundIndex; get player ship collision sound index bne .spawnBlankObstacle ; branch if playing collision sound ldy allowedToSpawnObstacles ; get value to allow obstacle spawning bpl .setNewObstacle ; branch if obstacle spawning allowed .spawnBlankObstacle lda #ID_BLANK .setNewObstacle tay sta obstacleList,x ; place new obstacle type in list cmp #ID_CANNON_BALL bne .checkForSpawnedArrow ; branch if new type not ID_CANNON_BALL inc obstacleList,x ; increment type to ID_ENEMY_FIGHTER_01 .checkForSpawnedArrow cmp #ID_ARROW bne .determineNewObstacleDirection; branch if new type not ID_ARROW lda #INIT_ARROW_SPAWN_SOUND_INDEX sta arrowSpawnSoundIndex ; set sound index value for ID_ARROW .determineNewObstacleDirection lda random bpl .placeNewObstacleOnLeft lda #XMAX - 5 sta obstacleHorizPos,x ; spawn new obstacle on right side lda InitSpawnedObstacleSpeedValues,y sta obstacleAttributes,x ; set new obstacle attribute value bpl .checkForSpawnedPrize ; unconditional branch .placeNewObstacleOnLeft lda #XMIN + 6 sta obstacleHorizPos,x ; spawn new obstacle on left side lda #OBSTACLE_DIR_RIGHT ora InitSpawnedObstacleSpeedValues,y sta obstacleAttributes,x ; set new obstacle attribute value .checkForSpawnedPrize cpy #ID_PRIZE bne .resetMovingObstacleIndex ; branch if new type not ID_PRIZE lda prizeFrameLoopCount ; get prize frame loop count bne .spawnBlankObstacle ; branch if prize currently present lda prizesCollected ; get number of prizes collected cmp #MAX_COLLECTED_PRIZES bcs .spawnBlankObstacle ; spawn ID_BLANK if reached prize limit lda #2 sta prizeFrameLoopCount ; spawn to ID_CANNON_BALL in ~4 seconds stx currentPrizeLane ; set lane number for ID_PRIZE lda #$FF sta obstacleAttributes,x ; set attribute values for ID_PRIZE .resetMovingObstacleIndex lda tmpObstacleIndex tax rts SetObstacleValuesForGameLevel ldy #NUM_LANES - 1 ldx gameLevel ; get current game level .setObstacleValuesForGameLevel lda InitObstacleHorizPosLSBValues,x sta tmpObstacleHorizPosPtrs lda #>InitObstacleHorizPosLevel_01 sta tmpObstacleHorizPosPtrs + 1 lda (tmpObstacleHorizPosPtrs),y sta obstacleHorizPos,y lda #0 << 4 | OBSTACLE_DIR_LEFT sta obstacleAttributes,y lda InitObstacleTypeLSBValues,x sta tmpObstacleTypePtrs lda (tmpObstacleTypePtrs),y sta obstacleList,y dey bpl .setObstacleValuesForGameLevel lda ObstacleSpeedValues,x sta obstacleSpeedValue rts ; ; The following 23 bytes aren't used and come from Fast Eddie ; .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$70,$70,$47,$47,$44,$44,$7C .byte $FE,$F0,$E0,$E6,$E6,$7C,$38 BOUNDARY 0 ObstacleGraphics CrawlerGraphic_00 .byte $00 ; |........| .byte $00 ; |........| .byte $1E ; |...XXXX.| .byte $10 ; |...X....| .byte $18 ; |...XX...| .byte $24 ; |..X..X..| .byte $42 ; |.X....X.| .byte $81 ; |X......X| .byte $42 ; |.X....X.| .byte $24 ; |..X..X..| .byte $18 ; |...XX...| .byte $08 ; |....X...| .byte $78 ; |.XXXX...| .byte $00 ; |........| CrawlerGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $78 ; |.XXXX...| .byte $08 ; |....X...| .byte $18 ; |...XX...| .byte $3C ; |..XXXX..| .byte $7E ; |.XXXXXX.| .byte $FF ; |XXXXXXXX| .byte $7E ; |.XXXXXX.| .byte $3C ; |..XXXX..| .byte $18 ; |...XX...| .byte $10 ; |...X....| .byte $1E ; |...XXXX.| BulletGraphic_00 BulletGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $FF ; |XXXXXXXX| .byte $00 ; |........| .byte $FF ; |XXXXXXXX| .byte $00 ; |........| .byte $FF ; |XXXXXXXX| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| TankGraphic_00 .byte $00 ; |........| .byte $7E ; |.XXXXXX.| .byte $D5 ; |XX.X.X.X| .byte $AB ; |X.X.X.XX| .byte $7E ; |.XXXXXX.| .byte $18 ; |...XX...| .byte $F8 ; |XXXXX...| .byte $CF ; |XX..XXXX| .byte $F8 ; |XXXXX...| .byte $18 ; |...XX...| .byte $7E ; |.XXXXXX.| .byte $AB ; |X.X.X.XX| .byte $D5 ; |XX.X.X.X| .byte $7E ; |.XXXXXX.| PrizeGraphic_00 .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $18 ; |...XX...| .byte $3C ; |..XXXX..| .byte $66 ; |.XX..XX.| .byte $C3 ; |XX....XX| .byte $C3 ; |XX....XX| .byte $C3 ; |XX....XX| .byte $66 ; |.XX..XX.| .byte $3C ; |..XXXX..| .byte $18 ; |...XX...| .byte $00 ; |........| .byte $00 ; |........| Cannon_Ball_Graphic_00 Cannon_Ball_Graphic_01 PrizeGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $18 ; |...XX...| .byte $3C ; |..XXXX..| .byte $3C ; |..XXXX..| .byte $3C ; |..XXXX..| .byte $18 ; |...XX...| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| TankGraphic_01 .byte $00 ; |........| .byte $7E ; |.XXXXXX.| .byte $AB ; |X.X.X.XX| .byte $D5 ; |XX.X.X.X| .byte $7E ; |.XXXXXX.| .byte $18 ; |...XX...| .byte $F8 ; |XXXXX...| .byte $CF ; |XX..XXXX| .byte $F8 ; |XXXXX...| .byte $18 ; |...XX...| .byte $7E ; |.XXXXXX.| .byte $D5 ; |XX.X.X.X| .byte $AB ; |X.X.X.XX| .byte $7E ; |.XXXXXX.| EnemyFighterGraphic_00 .byte $00 ; |........| .byte $00 ; |........| .byte $FF ; |XXXXXXXX| .byte $42 ; |.X....X.| .byte $24 ; |..X..X..| .byte $18 ; |...XX...| .byte $18 ; |...XX...| .byte $FF ; |XXXXXXXX| .byte $18 ; |...XX...| .byte $18 ; |...XX...| .byte $24 ; |..X..X..| .byte $42 ; |.X....X.| .byte $FF ; |XXXXXXXX| .byte $00 ; |........| EnemyFighterGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $81 ; |X......X| .byte $C3 ; |XX....XX| .byte $A5 ; |X.X..X.X| .byte $99 ; |X..XX..X| .byte $99 ; |X..XX..X| .byte $FF ; |XXXXXXXX| .byte $99 ; |X..XX..X| .byte $99 ; |X..XX..X| .byte $A5 ; |X.X..X.X| .byte $C3 ; |XX....XX| .byte $81 ; |X......X| .byte $00 ; |........| TieFighterGraphic_00 .byte $00 ; |........| .byte $FE ; |XXXXXXX.| .byte $10 ; |...X....| .byte $10 ; |...X....| .byte $10 ; |...X....| .byte $38 ; |..XXX...| .byte $7C ; |.XXXXX..| .byte $6C ; |.XX.XX..| .byte $7C ; |.XXXXX..| .byte $38 ; |..XXX...| .byte $10 ; |...X....| .byte $10 ; |...X....| .byte $10 ; |...X....| .byte $FE ; |XXXXXXX.| TieFighterGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $FE ; |XXXXXXX.| .byte $10 ; |...X....| .byte $38 ; |..XXX...| .byte $7C ; |.XXXXX..| .byte $6C ; |.XX.XX..| .byte $7C ; |.XXXXX..| .byte $38 ; |..XXX...| .byte $10 ; |...X....| .byte $FE ; |XXXXXXX.| .byte $00 ; |........| .byte $00 ; |........| MissileGraphic_00 .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $60 ; |.XX.....| .byte $78 ; |.XXXX...| .byte $BE ; |X.XXXXX.| .byte $71 ; |.XXX...X| .byte $BE ; |X.XXXXX.| .byte $78 ; |.XXXX...| .byte $60 ; |.XX.....| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| MissileGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $60 ; |.XX.....| .byte $B8 ; |X.XXX...| .byte $7E ; |.XXXXXX.| .byte $B1 ; |X.XX...X| .byte $7E ; |.XXXXXX.| .byte $B8 ; |X.XXX...| .byte $60 ; |.XX.....| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| BlankGraphic .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| ArrowGraphic_00 ArrowGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $10 ; |...X....| .byte $18 ; |...XX...| .byte $0C ; |....XX..| .byte $06 ; |.....XX.| .byte $FF ; |XXXXXXXX| .byte $FF ; |XXXXXXXX| .byte $06 ; |.....XX.| .byte $0C ; |....XX..| .byte $18 ; |...XX...| .byte $10 ; |...X....| .byte $00 ; |........| GhostShipGraphic_00 GhostShipGraphic_01 .byte $00 ; |........| .byte $18 ; |...XX...| .byte $18 ; |...XX...| .byte $3C ; |..XXXX..| .byte $7E ; |.XXXXXX.| .byte $FF ; |XXXXXXXX| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $FF ; |XXXXXXXX| .byte $7E ; |.XXXXXX.| .byte $3C ; |..XXXX..| .byte $18 ; |...XX...| .byte $18 ; |...XX...| ExplosionGraphic_00 .byte $00 ; |........| .byte $12 ; |...X..X.| .byte $24 ; |..X..X..| .byte $22 ; |..X...X.| .byte $94 ; |X..X.X..| .byte $FA ; |XXXXX.X.| .byte $1D ; |...XXX.X| .byte $38 ; |..XXX...| .byte $7C ; |.XXXXX..| .byte $9A ; |X..XX.X.| .byte $54 ; |.X.X.X..| .byte $24 ; |..X..X..| .byte $24 ; |..X..X..| .byte $62 ; |.XX...X.| ExplosionGraphic_01 .byte $00 ; |........| .byte $00 ; |........| .byte $08 ; |....X...| .byte $44 ; |.X...X..| .byte $69 ; |.XX.X..X| .byte $A5 ; |X.X..X.X| .byte $DA ; |XX.XX.X.| .byte $7C ; |.XXXXX..| .byte $1E ; |...XXXX.| .byte $29 ; |..X.X..X| .byte $6B ; |.XX.X.XX| .byte $58 ; |.X.XX...| .byte $50 ; |.X.X....| .byte $88 ; |X...X...| ; ; The following 16 bytes aren't used. ; .byte $8A,$8A,$8A,$8A,$8A,$8A,$8A,$0F,$0F,$8A,$8A,$8A,$8A,$8A,$00,$00 PlayerShipGraphics .byte $00 ; |........| .byte $00 ; |........| .byte $F8 ; |XXXXX...| .byte $E0 ; |XXX.....| .byte $F8 ; |XXXXX...| .byte $FE ; |XXXXXXX.| .byte $FF ; |XXXXXXXX| .byte $E0 ; |XXX.....| .byte $FF ; |XXXXXXXX| .byte $FE ; |XXXXXXX.| .byte $F8 ; |XXXXX...| .byte $E0 ; |XXX.....| .byte $F8 ; |XXXXX...| .byte $00 ; |........| LeftReservedShipNUSIZValues .byte ONE_COPY, ONE_COPY, TWO_COPIES, THREE_COPIES .byte THREE_COPIES, THREE_COPIES, THREE_COPIES RightReservedShipNUSIZValues .byte ONE_COPY, ONE_COPY, ONE_COPY, ONE_COPY .byte ONE_COPY, TWO_COPIES, THREE_COPIES InitObstacleHorizPosLevel_02 InitObstacleHorizPosLevel_06 .byte 0, 0, 0, 64, 32, 16, 48 InitObstacleHorizPosLevel_03 InitObstacleHorizPosLevel_07 .byte 0, 0, 64, 16, 48, 32, 56 InitObstacleHorizPosLevel_04 InitObstacleHorizPosLevel_08 .byte 0, 64, 56, 37, 48, 16, 24 InitObstacleTypesLevel_02 InitObstacleTypesLevel_06 .byte ID_BLANK, ID_BLANK, ID_BLANK, ID_TIE_FIGHTER .byte ID_BULLET, ID_MISSILE, ID_BULLET InitObstacleTypesLevel_03 InitObstacleTypesLevel_07 .byte ID_BLANK, ID_BLANK, ID_TIE_FIGHTER, ID_TIE_FIGHTER .byte ID_BULLET, ID_MISSILE, ID_BULLET InitObstacleTypesLevel_04 InitObstacleTypesLevel_08 .byte ID_BLANK, ID_BULLET, ID_BULLET, ID_MISSILE .byte ID_MISSILE, ID_TIE_FIGHTER, ID_TIE_FIGHTER InitObstacleHorizPosLevel_05 InitObstacleHorizPosLevel_09 .byte 35, 40, 48, 64, 136, 142, 128 InitObstacleTypesLevel_05 InitObstacleTypesLevel_09 .byte ID_TIE_FIGHTER, ID_MISSILE, ID_BULLET .byte ID_CRAWLER, ID_BULLET, ID_BULLET, ID_MISSILE InitObstacleHorizPosLevel_01 .byte 0, 0, 0, 0, 32, 64, 16 InitObstacleTypesLevel_01 .byte ID_BLANK, ID_BLANK, ID_BLANK, ID_BLANK .byte ID_MISSILE, ID_TIE_FIGHTER, ID_PRIZE PlayerShipColorValues .byte BLACK, RED_ORANGE + 5, RED_ORANGE + 5, RED_ORANGE + 5, BLUE + 11 .byte BLUE + 9, WHITE, RED_ORANGE + 5, WHITE, BLUE + 9, BLUE + 11 .byte RED_ORANGE + 5, RED_ORANGE + 5, RED_ORANGE + 5, BLACK ArrowAndGhostShipColorValues .byte WHITE, WHITE, BLUE + 10, BLUE + 10, BLUE + 10, BLUE + 10, BLUE + 10 .byte WHITE, WHITE, BLUE + 10, BLUE + 10, BLUE + 10, BLUE + 10, WHITE, WHITE .byte WHITE ExplosionColorValues .byte BLACK, RED_ORANGE + 12, RED_ORANGE + 9, RED_ORANGE + 5, RED_ORANGE + 9 .byte RED_ORANGE + 7, RED_ORANGE + 15, WHITE, RED_ORANGE + 10, RED_ORANGE + 10 .byte RED_ORANGE + 3, RED_ORANGE + 5, RED_ORANGE + 9, RED_ORANGE + 12 ObstacleColorValues .byte BLACK, BRICK_RED + 8, RED + 8, PURPLE + 8, COBALT_BLUE + 8, GREEN + 8 .byte ORANGE_GREEN + 8, RED_ORANGE + 5, ORANGE_GREEN + 8, GREEN + 8 .byte PURPLE + 8, RED + 8, BRICK_RED + 8, RED_ORANGE + 8 SneakerGraphics SneakerGraphic_00 .byte $07 ; |.....XXX| .byte $07 ; |.....XXX| .byte $E4 ; |XXX..X..| .byte $E4 ; |XXX..X..| .byte $24 ; |..X..X..| .byte $FF ; |XXXXXXXX| .byte $DB ; |XX.XX.XX| .byte $DB ; |XX.XX.XX| .byte $7E ; |.XXXXXX.| .byte $3C ; |..XXXX..| SneakerGraphic_01 .byte $E0 ; |XXX.....| .byte $E0 ; |XXX.....| .byte $27 ; |..X..XXX| .byte $27 ; |..X..XXX| .byte $24 ; |..X..X..| .byte $FF ; |XXXXXXXX| .byte $DB ; |XX.XX.XX| .byte $DB ; |XX.XX.XX| .byte $7E ; |.XXXXXX.| .byte $3C ; |..XXXX..| SneakerColorValues .byte WHITE, WHITE, WHITE, WHITE, WHITE, LT_BLUE + 8 .byte LT_BLUE + 8, LT_BLUE + 8, LT_BLUE + 8, LT_BLUE + 8 ; ; The following 57 bytes aren't used and come from Fast Eddie. ; .byte $A5,$99,$6A,$A5,$B1,$6A,$45,$99,$A6,$B1,$85,$B1,$86,$99,$4C,$64 .byte $FA,$70,$60,$50,$40,$30,$20,$10,$00,$F0,$E0,$D0,$C0,$B0,$A0,$90 .byte $00,$E0,$0E,$EE,$00,$05,$06,$07,$08,$35,$31,$9E,$BA,$B0,$A0,$90 .byte $00,$E0,$0E,$EE,$00,$05,$06,$07,$08 BOUNDARY 0 NumberFonts zero .byte $3E ; |..XXXXX.| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $3E ; |..XXXXX.| one .byte $1E ; |...XXXX.| .byte $0C ; |....XX..| .byte $0C ; |....XX..| .byte $0C ; |....XX..| .byte $0C ; |....XX..| .byte $0C ; |....XX..| .byte $1C ; |...XXX..| .byte $0C ; |....XX..| two .byte $7F ; |.XXXXXXX| .byte $60 ; |.XX.....| .byte $60 ; |.XX.....| .byte $3E ; |..XXXXX.| .byte $03 ; |......XX| .byte $03 ; |......XX| .byte $43 ; |.X....XX| .byte $3E ; |..XXXXX.| three .byte $3E ; |..XXXXX.| .byte $43 ; |.X....XX| .byte $03 ; |......XX| .byte $03 ; |......XX| .byte $1E ; |...XXXX.| .byte $03 ; |......XX| .byte $43 ; |.X....XX| .byte $3E ; |..XXXXX.| four .byte $06 ; |.....XX.| .byte $06 ; |.....XX.| .byte $06 ; |.....XX.| .byte $7F ; |.XXXXXXX| .byte $26 ; |..X..XX.| .byte $16 ; |...X.XX.| .byte $0E ; |....XXX.| .byte $06 ; |.....XX.| five .byte $3E ; |..XXXXX.| .byte $43 ; |.X....XX| .byte $03 ; |......XX| .byte $03 ; |......XX| .byte $7E ; |.XXXXXX.| .byte $60 ; |.XX.....| .byte $60 ; |.XX.....| .byte $7F ; |.XXXXXXX| six .byte $3E ; |..XXXXX.| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $7E ; |.XXXXXX.| .byte $60 ; |.XX.....| .byte $60 ; |.XX.....| .byte $3E ; |..XXXXX.| seven .byte $30 ; |..XX....| .byte $30 ; |..XX....| .byte $10 ; |...X....| .byte $08 ; |....X...| .byte $04 ; |.....X..| .byte $02 ; |......X.| .byte $41 ; |.X.....X| .byte $7F ; |.XXXXXXX| eight .byte $3E ; |..XXXXX.| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $3E ; |..XXXXX.| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $3E ; |..XXXXX.| nine .byte $3E ; |..XXXXX.| .byte $43 ; |.X....XX| .byte $03 ; |......XX| .byte $3F ; |..XXXXXX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $63 ; |.XX...XX| .byte $3E ; |..XXXXX.| GRP0_ReservedLivesLSBValues .byte BlankGraphic, >PlayerShipGraphics, >PlayerShipGraphics .byte >PlayerShipGraphics, >PlayerShipGraphics, >PlayerShipGraphics .byte >PlayerShipGraphics GRP1_ReservedLivesMSBValues .byte >BlankGraphic, >BlankGraphic, >BlankGraphic, >BlankGraphic .byte >PlayerShipGraphics, >PlayerShipGraphics, >PlayerShipGraphics ObstacleGraphicLSBValues_00 .byte > 4, POINT_VALUE_CANNON_BALL >> 4 .byte POINT_VALUE_FIGHTER_01 >> 4, POINT_VALUE_PRIZE >> 4 .byte POINT_VALUE_TIE_FIGHTER >> 4, POINT_VALUE_BULLET >> 4 .byte POINT_VALUE_MISSILE >> 4, POINT_VALUE_FIGHTER_02 >> 4 .byte POINT_VALUE_CRAWLER >> 4, POINT_VALUE_ARROW >> 4 .byte POINT_VALUE_TANK >> 4, POINT_VALUE_EXPLOSION >> 4 .byte POINT_VALIE_GHOST_SHIP >> 4 NumberLSBValues .byte