LIST OFF ; *** M I L L I P E D E *** ; Copyright 1984 Atari, Inc. ; Designers: Dave Staugas ; ; Analyzed, labeled and commented ; by Dennis Debro ; Last Update: October 27, 2023 ; ; *** 126 BYTES OF SUPERCHIP RAM USED 2 BYTES FREE ; ; NTSC ROM usage stats ; ------------------------------------------- ; *** 126 BYTES OF ZP RAM USED 2 BYTES FREE ; ; *** 95 BYTES OF ROM FREE IN BANK0 ; *** 331 BYTES OF ROM FREE IN BANK1 ; *** 846 BYTES OF ROM FREE IN BANK2 ; *** 237 BYTES OF ROM FREE IN BANK3 ; =========================================== ; *** 1,509 TOTAL BYTES FREE ; ; PAL50 ROM usage stats ; ------------------------------------------- ; *** 128 BYTES OF ZP RAM USED 0 BYTES FREE ; ; *** 95 BYTES OF ROM FREE IN BANK0 ; *** 331 BYTES OF ROM FREE IN BANK1 ; *** 853 BYTES OF ROM FREE IN BANK2 ; *** 215 BYTES OF ROM FREE IN BANK3 ; =========================================== ; *** 1,494 TOTAL BYTES 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 © 1984, ATARI INC. = ; = = ; ============================================================================== ; 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 ;=============================================================================== ; 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 || COMPILE_REGION = PAL50 || COMPILE_REGION = PAL60) echo "" echo "*** ERROR: Invalid COMPILE_REGION value" echo "*** Valid values: NTSC = 0, PAL50 = 1, PAL60 = 2" echo "" err ENDIF IFNCONST ORIGINAL_ROM ORIGINAL_ROM = TRUE ENDIF IF !(ORIGINAL_ROM = TRUE || ORIGINAL_ROM = FALSE) echo "" echo "*** ERROR: Invalid ORIGINAL_ROM value" echo "*** Valid values: FALSE = 0, TRUE = 1" echo "" err ENDIF IFNCONST CHEAT_ENABLE CHEAT_ENABLE = FALSE ; set to TRUE to enable no death collisions ENDIF IF !(CHEAT_ENABLE = TRUE || CHEAT_ENABLE = FALSE) echo "" echo "*** ERROR: Invalid CHEAT_ENABLE value" echo "*** Valid values: FALSE = 0, TRUE = 1" echo "" err ENDIF include "macro.h" include "tia_constants.h" include "vcs.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 ;=============================================================================== ; F R A M E T I M I N G S ;=============================================================================== IF COMPILE_REGION = NTSC || COMPILE_REGION = PAL60 VBLANK_TIME = 127 + 43 OVERSCAN_TIME = 127 + 35 ELSE VBLANK_TIME = 127 + 78 OVERSCAN_TIME = 127 + 59 ENDIF ;=============================================================================== ; C O L O R - C O N S T A N T S ;=============================================================================== IF COMPILE_REGION = NTSC COLORS_ORANGE = BRICK_RED + 4 COLORS_BLUE = BLUE + 4 COLORS_YELLOW = YELLOW + 8 COLORS_PURPLE = PURPLE + 6 COLORS_RED = RED + 4 COLORS_COBALT_BLUE = COBALT_BLUE + 6 COLORS_DK_GREEN = DK_GREEN + 6 COLORS_DK_BLUE = DK_BLUE + 8 COLORS_GREY = BLACK + 8 COLORS_SHOOTER_ZONE = BLACK + 2 COLORS_SHOOTER_ZONE_FLASH = RED COLORS_SCORE = ULTRAMARINE_BLUE + 15 COLORS_POISONED_MUSHROOM_LUMINANCE = 8 ELSE COLORS_ORANGE = BRICK_RED + 6 COLORS_BLUE = BLUE_2 + 4 COLORS_YELLOW = YELLOW + 8 COLORS_PURPLE = COBALT_BLUE + 6 COLORS_RED = RED + 4 COLORS_COBALT_BLUE = CYAN + 6 COLORS_DK_GREEN = DK_GREEN + 8 COLORS_DK_BLUE = TURQUOISE + 10 COLORS_GREY = WHITE COLORS_SHOOTER_ZONE = BLACK_03 + 2 COLORS_SHOOTER_ZONE_FLASH = RED + 4 COLORS_SCORE = PURPLE + 15 COLORS_POISONED_MUSHROOM_LUMINANCE = 14 ENDIF ; ; Color table offset values ; BEE_COLOR_OFFSET = 1 EARWIG_COLOR_OFFSET = 2 MILLIPEDE_COLOR_OFFSET = 2 SPIDER_COLOR_OFFSET = 3 MOSQUITO_COLOR_OFFSET = 4 DDT_CLOUD_COLOR_OFFSET = 4 DRAGONFLY_COLOR_OFFSET = 5 INCHWORM_COLOR_OFFSET = 6 BEETLE_COLOR_OFFSET = 7 DDT_BOMB_COLOR_OFFSET = 14 BONUS_POINTS_COLOR_OFFSET = 32 ;=============================================================================== ; U S E R - C O N S T A N T S ;=============================================================================== BANK0_BASE = $1000 BANK1_BASE = $2000 BANK2_BASE = $3000 BANK3_BASE = $4000 BANK0_REORG = $9000 BANK1_REORG = $B000 BANK2_REORG = $D000 BANK3_REORG = $F000 BANK0STROBE = $FFF6 BANK1STROBE = $FFF7 BANK2STROBE = $FFF8 BANK3STROBE = $FFF9 H_TITLE_BITMAP = 38 H_GAME_OVER_BITMAP = 16 H_DIGITS = 7 H_DDT_CLOUD = 8 H_SPRITE = 8 H_SHOOTER = 6 W_BLANK_SPRITE = 0 W_SHOOTER = 4 W_BEE = 8 W_EARWIG = 8 W_SPIDER = 8 W_MOSQUITO = 8 W_DRAGONFLY = 8 W_INCHWORM = 8 W_BEETLE = 8 W_MILLIPEDE_HEAD = 4 W_MILLIPEDE_SEGMENT = 8 W_DDT = 8 W_MILLIPEDE_SEGMENT_00 = 16 XMIN = 0 XMAX = 128 SHOOTER_START_X = 60 SHOOTER_START_Y = 56 SHOOTER_YMIN = 40 SHOOTER_YMAX = 56 MILLIPEDE_START_X = 60 INCHWORM_STARTING_WAVE = 2 MUSHROOM_TALLY_GROUP_VALUE = 3 SELECT_DELAY = 15 MAX_LEVEL = 15 MAX_KERNEL_SECTIONS = 21 MAX_MILLIPEDE_SEGMENTS = 9 MUSHROOM_ARRAY_SIZE = 38 INIT_LIVES = 3 MAX_LIVES = 15 LIVES_MASK = $0F GAME_WAVE_MASK = $0F ; ; low game state flags ; GAME_ACTIVE_MASK = %10000000 GAME_SELECTION_MASK = %01000000 SPAWN_HEAD_MASK = %00100000 SPAWN_EXTRA_SPIDER_MASK = %00010000 GS_GAME_OVER = 1 << 7 GS_GAME_ACTIVE = 0 << 7 GS_SELECTING_GAME = 1 << 6 GS_SPAWN_MILLIPEDE_HEAD = 1 << 5 GS_EXTRA_SPIDER_SPAWNED = 1 << 4 ; ; high game state flags ; SHOW_GAME_OVER_MASK = %10000000 SPAWN_INCHWORM_TIMER_MASK = %00001111 GS_SHOW_GAME_OVER = 1 << 7 INIT_INCHWORM_SPAWN_TIMER = 15 ; ; wave state flags ; SWARMING_MASK = %10000000 SHOW_LITERAL_MASK = %01000000 ACTION_BUTTON_DEBOUNCE = %00100000 SWARMING_WAVE_MASK = %00001100 SWARMING = 1 << 7 NOT_SWARMING = 0 << 7 SHOW_LITERALS = 1 << 6 NOT_SHOW_LITERALS = 0 << 6 ACTION_BUTTON_RELEASED = 1 << 5 ACTION_BUTTON_HELD = 0 << 5 SELECT_DEBOUNCE_MASK = %01000000 SELECT_SWITCH_HELD = 1 << 6 SELECT_SWITCH_RELEASED = 0 << 6 EVEN_NORMAL_MUSHROOM_MASK = $AA ODD_NORMAL_MUSHROOM_MASK = $55 EVEN_REFLECTED_MUSHROOM_MASK = $55 ODD_REFLECTED_MUSHROOM_MASK = $AA ; ; Kernel zone attribute values ; MUSHROOM_POISON_MASK = %10000000 DRAW_INSECT_MASK = %10000000 DRAW_DDT_CLOUD_MASK = %01000000 SPRITE_ID_IDX_MASK = %00111111 POISON_MUSHROOM_ZONE = 1 << 7 NORMAL_MUSHROOM_ZONE = 0 << 7 SKIP_DRAW_INSECT_ZONE = 1 << 7 DRAW_INSECT_ZONE = 0 << 7 DRAW_MILLIPEDE_CHAIN_ZONE = 3 << 6 DRAW_DDT_CLOUD_ZONE = 2 << 6 DRAW_LITERAL_ZONE = 1 << 6 ; ; Temporary values for Millipede speed ; FAST_MILLIPEDE_VALUE = -1 SLOW_MILLIPEDE_VALUE = 0 MAX_HORIZ_FRICTION_VALUE = 23 MAX_DDT_BOMBS = 5 INIT_BEETLE_KERNEL_ZONE = 8 ; ; Number font values ; ID_ZERO = 0 ID_ONE = 1 ID_TWO = 2 ID_THREE = 3 ID_FOUR = 4 ID_FIVE = 5 ID_SIX = 6 ID_SEVEN = 7 ID_EIGHT = 8 ID_NINE = 9 ID_BLANK_FONT = 10 ; ; Sprite Id values ; ID_BLANK = 0 ID_BEE = 1 ; 1 - 2 ID_EARWIG = 3 ; 3 - 6 ID_SPIDER = 7 ; 7 - 9 ID_MOSQUITO = 10 ; 10 - 13 ID_DRAGONFLY = 14 ; 14 - 16 ID_INCHWORM = 17 ; 17 - 19 ID_BEETLE = 20 ; 20 - 27 ID_SHOOTER_DEATH = 28 ; 28 - 31 ID_SPARK = 32 ; 32 - 33 ID_MILLIPEDE_HEAD = 34 ID_MILLIPEDE_SEGMENT = 35 ID_POINTS_200 = 36 ID_POINTS_300 = 37 ID_POINTS_400 = 38 ID_POINTS_500 = 39 ID_POINTS_600 = 40 ID_POINTS_700 = 41 ID_POINTS_800 = 42 ID_POINTS_900 = 43 ID_POINTS_1000 = 44 ID_POINTS_1200 = 45 ID_POINTS_1800 = 46 ID_DDT = 47 ID_DDT_CLOUD = 48 ID_MILLIPEDE_CHAIN = 64 ; ; Point values (BCD) ; POINTS_MILLIPEDE_SEGMENT = $0010 POINTS_MILLIPEDE_HEAD = $0100 POINTS_SPIDER_DISTANT = $0300 POINTS_SPIDER_MEDIUM = $0600 POINTS_SPIDER_CLOSE = $0900 POINTS_SPIDER_CLOSEST = $1200 POINTS_INCHWORM = $0100 POINTS_BEE = $0200 POINTS_BEETLES = $0300 POINTS_MOSQUITO = $0400 POINTS_DRAGONFLY = $0500 POINTS_DDT_BOMB = $0800 POINTS_EARWIG = $1000 POINTS_ELIMINATE_MUSHROOM = 1 POINTS_REMAINING_MUSHROOMS = 5 KERNEL_ZONE_MASK = %00011111 PLAYER_MOVEMENT_MASK = %10000000 INSECT_SPEED_MASK = %01000000 PLAYER_MOVEMENT_HALT = 1 << 7 PLAYER_MOVEMENT_NORMAL = 0 << 7 INSECT_SPEED_SLOW = 1 << 6 INSECT_SPEED_NORMAL = 0 << 6 ; ; Object attribute values ; OBJECT_HORIZ_DIR_MASK = %10000000 OBJECT_DIR_LEFT = 0 << 7 OBJECT_DIR_RIGHT = 1 << 7 ; ; Beetle attribute values ; BEETLE_HORIZ_DIR_MASK = %10000000 BEETLE_VERT_DIR_MASK = %01000000 BEETLE_HORIZ_MOVE = 1 << 7 BEETLE_NO_HORIZ_MOVE = 0 << 7 BEETLE_DIR_UP = 1 << 6 BEETLE_DIR_DOWN = 0 << 6 ; ; Dragonfly attribute values ; DRAGONFLY_HORIZ_OFFSET_MASK = %11100000 ; ; Inchworm attribute values ; INCHWORM_SPEED_MASK = %10000000 INCHWORM_HORIZ_DIR_MASK = %01000000 INCHWORM_FAST = 1 << 7 INCHWORM_SLOW = 0 << 7 INCHWORM_DIR_RIGHT = 0 << 6 INCHWORM_DIR_LEFT = 1 << 6 ; ; Earwig attribute values ; EARWIG_SPEED_MASK = %10000000 EARWIG_FAST = 1 << 7 EARWIG_SLOW = 0 << 7 ; ; Millipede attribute values ; MILLIPEDE_SPEED_MASK = %01000000 MILLIPEDE_POISONED_MASK = %00100000 MILLIPEDE_FAST = 1 << 6 MILLIPEDE_SLOW = 0 << 6 MILLIPEDE_POISONED = 1 << 5 MILLIPEDE_NORMAL = 0 << 5 ; ; Mosquito attribute values ; MOSQUITO_SPEED_MASK = %10000000 MOSQUITO_FAST = 1 << 7 MOSQUITO_SLOW = 0 << 7 ; ; Spider attribute values ; SPIDER_VERT_DIR_MASK = %01000000 SPIDER_HORIZ_MOVE_MASK = %00100000 SPIDER_DIR_UP = 0 << 6 SPIDER_DIR_DOWN = 1 << 6 SPIDER_HORIZ_MOVE = 1 << 5 SPIDER_NO_HORIZ_MOVE = 0 << 5 MAX_SPIDER_KERNEL_ZONE = 10 ; ; Bee state values ; BEE_STATE_ANGRY = 1 << 7 BEE_STATE_NORMAL = 0 << 7 ; ; Millipede state values ; MILLIPEDE_SEGMENT_MASK = %10000000 MILLIPEDE_VERT_DIR_MASK = %01000000 MILLIPEDE_HORIZ_DIR_MASK = %00100000 MILLIPEDE_BODY_SEGMENT = 1 << 7 MILLIPEDE_HEAD_SEGMENT = 0 << 7 MILLIPEDE_DIR_UP = 1 << 6 MILLIPEDE_DIR_DOWN = 0 << 6 MILLIPEDE_DIR_LEFT = 1 << 5 MILLIPEDE_DIR_RIGHT = 0 << 5 SHOOTER_HORIZ_DIR_MASK = %11000000 SHOOTER_HORIZ_DELAY_MASK = %00111111 MILLIPEDE_BODY_HORIZ_OFFSET = 4 SHOOTER_MOVE_LEFT = 1 << 7 SHOOTER_MOVE_RIGHT = 1 << 6 DEMO_SHOOTER_VERT_DIR = %10000000 DEMO_SHOOTER_HORIZ_DIR = %01000000 DEMO_SHOOTER_MOVE_UP = 0 << 7 DEMO_SHOOTER_MOVE_DOWN = 1 << 7 DEMO_SHOOTER_MOVE_RIGHT = 0 << 6 DEMO_SHOOTER_MOVE_LEFT = 1 << 6 ; ; Kernel Shooter state ; POSITION_SHOOTER_MASK = %01000000 POSITION_SHOOTER = 1 << 6 MUSHROOM_TALLY_AUDIO_FREQUENCY = 10 MUSHROOM_TALLY_AUDIO_VOLUME = 255 MUSHROOM_TALLY_AUDIO_TONE = 8 SHOT_AUDIO_VOLUME = 255 SHOT_AUDIO_TONE = 8 END_AUDIO_TUNE = 0 SHOOTER_EXPLOSION_AUDIO_VOLUME = 255 SHOOTER_EXPLOSION_AUDIO_TONE = 8 HEARTBEAT_AUDIO_TONE = 15 OBJECT_SPAWNING_BEE = 1 << 7 OBJECT_SPAWNING_DRAGONFLY = 1 << 5 OBJECT_SPAWNING_MOSQUITO = 1 << 3 OBJECT_SPAWNING_EARWIG = 1 << 2 OBJECT_SPAWNING_INCHWORM = 1 << 1 MAX_SWARMING_INSECTS_00 = 20 MAX_SWARMING_INSECTS_01 = 30 MAX_SWARMING_INSECTS_02 = 40 ;=============================================================================== ; M A C R O S ;=============================================================================== MAC DDT_CREATURE_POINT_VALUE IF {1} < $10 .byte [(({1} * 3) / 10) * 16 | ({1} * 3) % 10] ELSE .byte {1} * 3 ENDIF ENDM ; ; Set sound values macros ; MAC SET_AUDIO_TONE .byte {1} << 3 | 0 ENDM MAC SET_AUDIO_FREQUENCY .byte {1} << 3 | 1 ENDM MAC SET_SLOWDOWN_AUDIO_FREQUENCY .byte {1} << 3 | 5 ENDM MAC SET_AUDIO_VOLUME .byte {1} << 3 | 2 ENDM MAC SET_AUDIO_DURATION .byte {1} << 3 | 3 ENDM MAC JMP_AUDIO_START .byte 0 << 3 | 4 .byte {1} ENDM ; ; time wasting macros ; MAC SLEEP_5 lda shooterZoneBackgroundColor SLEEP 2 ENDM MAC SLEEP_6 IF ORIGINAL_ROM cmp (tmpBitmapDisplayLoop,x) ELSE SLEEP 6 ENDIF ENDM MAC SLEEP_7 pha pla ENDM ;------------------------------------------------------- ; FILL_BOUNDARY byte# ; Original author: Dennis Debro (borrowed from Bob Smith / Thomas Jentzsch) ; ; Push data to a certain position inside a page and keep count of how ; many free bytes the programmer will have. ; ; eg: FILL_BOUNDARY 5, 234 ; position at byte #5 in page with $EA is byte filler FREE_BYTES SET 0 .BYTES_TO_SKIP SET 0 MAC FILL_BOUNDARY IF <. > {1} .BYTES_TO_SKIP SET (256 - <.) + {1} ELSE .BYTES_TO_SKIP SET (256 - <.) - (256 - {1}) ENDIF REPEAT .BYTES_TO_SKIP FREE_BYTES SET FREE_BYTES + 1 .byte {2} REPEND ENDM MAC FILL_NOP REPEAT {1} NOP REPEND ENDM ;=============================================================================== ; Z P - V A R I A B L E S ;=============================================================================== SEG.U GAME_ZP_VARIABLES .org $80 frameCount ds 2 gameState ds 2 random ds 2 kernelZoneAttributes_00 ds MAX_KERNEL_SECTIONS + 1 kernelZoneAdjustment ds 1 kernelZoneAttributes_01 ds MAX_KERNEL_SECTIONS gameWaveValues ds 1 inchwormWaveState ds 1 displayScanOutControl ds 1 gardenShiftValues ds 1 beetleSpawnTimer ds 1 objectSpawningValues ds 1 waveState ds 1 leftSoundChannelIndex ds 1 rightSoundChannelIndex ds 1 leftSoundAudioDuration ds 1 rightSoundAudioDuration ds 1 soundRoutineVector ds 2 tmpAudioValue ds 1 ;-------------------------------------- tmpObjectKernelZone = tmpAudioValue shooterVertPos ds 1 shooterHorizPos ds 1 shooterHorizFrictionValue ds 1 ;-------------------------------------- demoShooterDirectionValues = shooterHorizFrictionValue shotVertPos ds 1 shotHorizPos ds 1 numberOfMillipedeSegments ds 1 ;-------------------------------------- waveTransitionTimer = numberOfMillipedeSegments millipedeSegmentState ds MAX_MILLIPEDE_SEGMENTS millipedeHorizPosition ds MAX_MILLIPEDE_SEGMENTS ;-------------------------------------- waveNumberSwarmingInsects = millipedeHorizPosition + 3 ;-------------------------------------- mushroomTallyGardenArrayIndex = waveNumberSwarmingInsects numberActiveSwarmingInsects = millipedeHorizPosition + 4 ;-------------------------------------- mushroomTallyGardenIndex = numberActiveSwarmingInsects tmpMushroomTallyFrameDelay = millipedeHorizPosition + 5 ;-------------------------------------- tmpSwarmingInsectSpawningTimer = tmpMushroomTallyFrameDelay insectSwarmShootTally = millipedeHorizPosition + 6 ;-------------------------------------- tmpRemainingMushroomPointValue = insectSwarmShootTally poisonedMushroomColor ds 1 tmpRemainingLivesColor ds 1 ;-------------------------------------- tmpNormalMushroomColor = tmpRemainingLivesColor shooterZoneBackgroundColor ds 1 growingMushroomGardenArrayIndex ds 1 growingMushroomGardenIndex ds 1 objectListEndValue ds 1 millipedeBodyKernelZone ds 1 shotMushroomIndex ds 1 playerScore ds 3 kernelZoneConflictArray ds 6 conflictArrayStartingIndex ds 1 IF COMPILE_REGION = PAL50 creatureFrameCount ds 2 ENDIF tmpKernelZone_BANK0 ds 1 graphicsPointers ds 12 ;-------------------------------------- tmpPoints = graphicsPointers ;-------------------------------------- tmpThousandsPoints = tmpPoints tmpHundredsPoints = tmpPoints + 1 tmpOnesPoints = tmpPoints + 2 ;-------------------------------------- tmpCoarsePositionObject0Vector = graphicsPointers tmpCoarsePositionObject1Vector = tmpCoarsePositionObject0Vector + 2 tmpCoarsePositionShooterVector = tmpCoarsePositionObject1Vector + 2 ;-------------------------------------- tmpShotCollisionRoutineVector = tmpCoarsePositionShooterVector ;-------------------------------------- tmpObjectMoveRoutineVector = tmpShotCollisionRoutineVector ;-------------------------------------- tmpObjectSpawningVector = tmpObjectMoveRoutineVector ;-------------------------------------- tmpObjectFineHorizValue = tmpObjectSpawningVector tmpConflictingZoneValues = graphicsPointers + 6 ;-------------------------------------- tmpGRP0GraphicIndex = tmpConflictingZoneValues playerShotEnableIndex = tmpGRP0GraphicIndex + 1 tmpGRP1GraphicIndex = playerShotEnableIndex + 1 kernelShooterState = tmpGRP1GraphicIndex + 1 shooterKernelZoneValue = kernelShooterState + 1 tmpLeftPF1MushroomGraphics = shooterKernelZoneValue + 1 ;-------------------------------------- tmpKernelEnableBALL = tmpLeftPF1MushroomGraphics tmpZeroSuppressValue ds 1 ;-------------------------------------- tmpExtraLifeState = tmpZeroSuppressValue ;-------------------------------------- tmpSwarmingWaveValue = tmpExtraLifeState ;-------------------------------------- tmpMillipedeSegmentIndex = tmpSwarmingWaveValue ;-------------------------------------- tmpLeftPF2MushroomGraphics = tmpMillipedeSegmentIndex ;-------------------------------------- tmpBitmapDisplayLoop = tmpLeftPF2MushroomGraphics ;-------------------------------------- tmpShotUpperKernelZone = tmpBitmapDisplayLoop ;-------------------------------------- tmpMushroomArrayIdx = tmpShotUpperKernelZone ;-------------------------------------- tmpMushroomMaskingBits = tmpMushroomArrayIdx ;-------------------------------------- tmpSpriteIdx = tmpMushroomMaskingBits ;-------------------------------------- tmpMillipedeChainEnd = tmpSpriteIdx ;-------------------------------------- tmpSpiderAttributes = tmpMillipedeChainEnd ;-------------------------------------- tmpSpiderKernelZoneMax = tmpSpiderAttributes ;-------------------------------------- tmpInchwormPointValue = tmpSpiderKernelZoneMax ;-------------------------------------- tmpSpawnDDTBomb = tmpInchwormPointValue ;-------------------------------------- tmpScoreThousandsValue = tmpSpawnDDTBomb ;-------------------------------------- tmpMushroomXOR = tmpScoreThousandsValue ;-------------------------------------- tmpShouldProcessObjectMovements = tmpMushroomXOR ;-------------------------------------- tmpIsolatedMushroomBitValue = tmpShouldProcessObjectMovements tmpKernelZoneAdjustment ds 1 ;-------------------------------------- tmpMillipedeChainGroupHorizOffset = tmpKernelZoneAdjustment ;-------------------------------------- tmpCharHolder = tmpMillipedeChainGroupHorizOffset ;-------------------------------------- tmpHundredsValueHolder = tmpCharHolder ;-------------------------------------- tmpMillipedeState = tmpHundredsValueHolder ;-------------------------------------- tmpRightPF1Graphics = tmpMillipedeState ;-------------------------------------- tmpShooterKernelZone = tmpRightPF1Graphics ;-------------------------------------- tmpSpiderKernelZone = tmpShooterKernelZone ;-------------------------------------- tmpMosquitoMovementDelay = tmpSpiderKernelZone ;-------------------------------------- tmpBeeMovementDelay = tmpMosquitoMovementDelay ;-------------------------------------- tmpMillipedeSpeed = tmpBeeMovementDelay ;-------------------------------------- tmpBeetleKernelZone = tmpMillipedeSpeed ;-------------------------------------- tmpInsectKernelZone = tmpBeetleKernelZone ;-------------------------------------- tmpNumberOfMushrooms = tmpInsectKernelZone ;-------------------------------------- tmpSwarmingSpawningInsectValue = tmpNumberOfMushrooms ;-------------------------------------- tmpMushroomMaskingBitValue = tmpSwarmingSpawningInsectValue ;-------------------------------------- tmpDragonflyMovementFrame = tmpMushroomMaskingBitValue ;-------------------------------------- tmpConflictingKernelZoneValue = tmpDragonflyMovementFrame tmpLeadingSegmentKernelZone ds 1 ;-------------------------------------- tmpRightPF2Graphics = tmpLeadingSegmentKernelZone ;-------------------------------------- tmpPlayerShotEnableIndex = tmpRightPF2Graphics ;-------------------------------------- tmpShotObjectHorizDistance = tmpPlayerShotEnableIndex ;-------------------------------------- tmpMillipedeChainIndex = tmpShotObjectHorizDistance ;-------------------------------------- tmpObjectCollisionIdx = tmpMillipedeChainIndex tmpShotMillipedeState ds 1 ;-------------------------------------- tmpMushroomMaskingBitIndex = tmpShotMillipedeState ;-------------------------------------- tmpLeftPF1FlowerGraphics = tmpMushroomMaskingBitIndex ;-------------------------------------- tmpKernelShooterState = tmpLeftPF1FlowerGraphics ;-------------------------------------- tmpDDTCloudUpperKernelZone = tmpKernelShooterState ;-------------------------------------- tmpKernelZoneAttributes_00 = tmpDDTCloudUpperKernelZone ;-------------------------------------- tmpBuildingMillipedeChainIndex = tmpKernelZoneAttributes_00 ;-------------------------------------- tmpMushroomTallyIndex = tmpBuildingMillipedeChainIndex tmpLeftPF2FlowerGraphics ds 1 ;-------------------------------------- tmpShooterKernelZoneValue = tmpLeftPF2FlowerGraphics ;-------------------------------------- tmpMillipedeSegmentZone = tmpShooterKernelZoneValue ;-------------------------------------- tmpDDTCloudLowerKernelZone = tmpMillipedeSegmentZone ;-------------------------------------- tmpShotKernelZone = tmpDDTCloudLowerKernelZone ;-------------------------------------- tmpMushroomTallyGroupCount = tmpShotKernelZone tmpRightPF1FlowerGraphics ds 1 ;-------------------------------------- tmpDDTCloudHorizPosition = tmpRightPF1FlowerGraphics ;-------------------------------------- tmpMillipedeHorizPos = tmpDDTCloudHorizPosition ;-------------------------------------- tmpEndDDTCloudMushroomMaskingIndex = tmpMillipedeHorizPos tmpShotMillipedeIndex ds 1 ;-------------------------------------- tmpRightPF2FlowerGraphics = tmpShotMillipedeIndex ;-------------------------------------- tmpNumberOfMillipedeSegments = tmpRightPF2FlowerGraphics ;-------------------------------------- tmpKernelZone_BANK3 = tmpNumberOfMillipedeSegments ;-------------------------------------- tmpShotLowerKernelZone = tmpKernelZone_BANK3 echo "***",(* - $80)d, "BYTES OF ZP RAM USED", ($100 - *)d, "BYTES FREE" ;=============================================================================== ; S U P E R C H I P R A M - V A R I A B L E S ;=============================================================================== SEG.U scWriteVars .org $1000 objectHorizPositions_W ;-------------------------------------- ddtBombHorizPosition_W ds MAX_DDT_BOMBS creatureHorizPositions_W ds 14 ;-------------------------------------- beetleHorizPositions_W = creatureHorizPositions_W ;-------------------------------------- inchwormHorizPosition_W = beetleHorizPositions_W + 1 ;-------------------------------------- gardenInsectHorizPosition_W = creatureHorizPositions_W + 2 ;-------------------------------------- beeHorizPosition_W = gardenInsectHorizPosition_W ;-------------------------------------- dragonflyHorizPosition_W = gardenInsectHorizPosition_W ;-------------------------------------- earwigHorizPosition_W = gardenInsectHorizPosition_W ;-------------------------------------- mosquitoHorizPosition_W = gardenInsectHorizPosition_W objectAttributes_W ;-------------------------------------- ddtBombAttributes_W ds MAX_DDT_BOMBS creatureAttributes_W ds 14 ;-------------------------------------- sparkAttributes_W = creatureAttributes_W ;-------------------------------------- beetleAttributes_W = sparkAttributes_W ;-------------------------------------- inchwormAttributes_W = beetleAttributes_W + 1 ;-------------------------------------- gardenInsectAttributes_W = creatureAttributes_W + 2 ;-------------------------------------- beeAttributes_W = gardenInsectAttributes_W ;-------------------------------------- dragonflyAttributes_W = gardenInsectAttributes_W ;-------------------------------------- earwigAttributes_W = gardenInsectAttributes_W ;-------------------------------------- mosquitoAttributes_W = gardenInsectAttributes_W spriteIdArray_W ;-------------------------------------- ddtBombSpriteIds_W ds MAX_DDT_BOMBS creatureSpriteIds_W ds 14 ;-------------------------------------- sparkSpriteId_W = creatureSpriteIds_W ;-------------------------------------- beetleSpriteId_W = sparkSpriteId_W ;-------------------------------------- inchwormSpriteId_W = beetleSpriteId_W + 1 ;-------------------------------------- gardenInsectSpriteId_W = creatureSpriteIds_W + 2 ;-------------------------------------- beeSpriteId_W = gardenInsectSpriteId_W ;-------------------------------------- dragonflySpriteId_W = gardenInsectSpriteId_W ;-------------------------------------- earwigSpriteId_W = gardenInsectSpriteId_W ;-------------------------------------- mosquitoSpriteId_W = gardenInsectSpriteId_W tmpMaxStartingScoreThousandsValue_W = spriteIdArray_W + 12 tmpMaxStartingScoreHundredsValue_W = spriteIdArray_W + 13 leftFlowerArray_W ds 11 millipedeAttributes_W ds MAX_MILLIPEDE_SEGMENTS rightFlowerArray_W ds 11 mushroomArray_W ds MUSHROOM_ARRAY_SIZE ;-------------------------------------- leftMushroomArray_W = mushroomArray_W rightMushroomArray_W = leftMushroomArray_W + [MUSHROOM_ARRAY_SIZE / 2] + 1 echo "***",(* - $1000)d, "BYTES OF SUPERCHIP RAM USED", ($1080 - *)d, "BYTES FREE" SEG.U scReadVars .org $1080 objectHorizPositions_R ;-------------------------------------- ddtBombHorizPosition_R ds MAX_DDT_BOMBS creatureHorizPositions_R ds 14 ;-------------------------------------- beetleHorizPositions_R = creatureHorizPositions_R ;-------------------------------------- inchwormHorizPosition_R = beetleHorizPositions_R + 1 ;-------------------------------------- gardenInsectHorizPosition_R = creatureHorizPositions_R + 2 ;-------------------------------------- beeHorizPosition_R = gardenInsectHorizPosition_R ;-------------------------------------- dragonflyHorizPosition_R = gardenInsectHorizPosition_R ;-------------------------------------- earwigHorizPosition_R = gardenInsectHorizPosition_R ;-------------------------------------- mosquitoHorizPosition_R = gardenInsectHorizPosition_R objectAttributes_R ;-------------------------------------- ddtBombAttributes_R ds MAX_DDT_BOMBS creatureAttributes_R ds 14 ;-------------------------------------- sparkAttributes_R = creatureAttributes_R ;-------------------------------------- beetleAttributes_R = sparkAttributes_R ;-------------------------------------- inchwormAttributes_R = beetleAttributes_R + 1 ;-------------------------------------- gardenInsectAttributes_R = creatureAttributes_R + 2 ;-------------------------------------- beeAttributes_R = gardenInsectAttributes_R ;-------------------------------------- dragonflyAttributes_R = gardenInsectAttributes_R ;-------------------------------------- earwigAttributes_R = gardenInsectAttributes_R ;-------------------------------------- mosquitoAttributes_R = gardenInsectAttributes_R spriteIdArray_R ;-------------------------------------- ddtBombSpriteIds_R ds MAX_DDT_BOMBS creatureSpriteIds_R ds 14 ;-------------------------------------- sparkSpriteId_R = creatureSpriteIds_R ;-------------------------------------- beetleSpriteId_R = sparkSpriteId_R ;-------------------------------------- inchwormSpriteId_R = beetleSpriteId_R + 1 ;-------------------------------------- gardenInsectSpriteId_R = creatureSpriteIds_R + 2 ;-------------------------------------- beeSpriteId_R = gardenInsectSpriteId_R ;-------------------------------------- dragonflySpriteId_R = gardenInsectSpriteId_R ;-------------------------------------- earwigSpriteId_R = gardenInsectSpriteId_R ;-------------------------------------- mosquitoSpriteId_R = gardenInsectSpriteId_R tmpMaxStartingScoreThousandsValue_R = spriteIdArray_R + 12 tmpMaxStartingScoreHundredsValue_R = spriteIdArray_R + 13 leftFlowerArray_R ds 11 millipedeAttributes_R ds MAX_MILLIPEDE_SEGMENTS rightFlowerArray_R ds 11 mushroomArray_R ds MUSHROOM_ARRAY_SIZE ;-------------------------------------- leftMushroomArray_R = mushroomArray_R rightMushroomArray_R = leftMushroomArray_R + [MUSHROOM_ARRAY_SIZE / 2] + 1 ;=============================================================================== ; R O M - C O D E (BANK0) ;=============================================================================== SEG Bank0 .org BANK0_BASE .rorg BANK0_REORG FREE_BYTES SET 0 .ds 256, 0 ; first page reserved for Superchip RAM SetupGameDisplayKernel ldx millipedeBodyKernelZone cpx #MAX_KERNEL_SECTIONS + 1 bcs PositionShotHorizontally sta WSYNC ; wait for next scan line lda #$7F and kernelZoneAttributes_01 - 1,x tay lda BANK0_HMOVE_Table + 1,y sta.w HMM0 ; set missile fine motion value and #$0F ; keep coarse position value tay .coarsePositionMissile_00 dey bpl .coarsePositionMissile_00 sta RESM0 sta WSYNC ; wait for next scan line lda kernelZoneAttributes_01 - 1,x and #$7F tay lda BANK0_HMOVE_Table,y sta.w HMM1 ; set missile fine motion value and #$0F ; keep coarse position value tay .coarsePositionMissile_01 dey bpl .coarsePositionMissile_01 sta RESM1 PositionShotHorizontally sta WSYNC ; wait for next scan line lda #MSBL_SIZE1 | PF_REFLECT sta CTRLPF clc ldx shotHorizPos ; get Shot horizontal position lda BANK0_HMOVE_Table + 1,x sta HMBL ; set Shot fine motion value and #$0F ; keep coarse position value tay .coarsePositionShot dey bpl .coarsePositionShot sta RESBL bit waveState ; check current wave state value bvc .waitTime lda #DRAW_LITERAL_ZONE | ID_BLANK ldx kernelZoneAdjustment ; get kernel zone adjustment value sta kernelZoneAttributes_00 + 14,x .waitTime lda INTIM bmi .waitTime lda displayScanOutControl ; get display scan out value sta WSYNC ;-------------------------------------- sta HMOVE ; 3 sta VBLANK ; 3 = @06 sta COLUBK ; 3 = @09 sta tmpKernelEnableBALL ; 3 lda #>CoarsePositionObject0Routines;2 sta tmpCoarsePositionObject0Vector + 1;3 lda #>CoarsePositionObject1Routines;2 sta tmpCoarsePositionObject1Vector + 1;3 lda #>CoarsePositionShooterRoutines;2 sta tmpCoarsePositionShooterVector + 1;3 lda #DRAW_LITERAL_ZONE | ID_BLANK;2 ldx kernelZoneAdjustment ; 3 get kernel zone adjustment value sta kernelZoneAttributes_00,x;4 txa ; 2 adc #MAX_KERNEL_SECTIONS - 1;2 tax ; 2 stx tmpKernelZone_BANK0 ; 3 lda #6 ; 2 adc kernelZoneAdjustment ; 3 increment by kernel zone adjustment sta shooterKernelZoneValue ; 3 SLEEP_7 ; 7 sta HMCLR ; 3 = @63 ldy kernelZoneAttributes_00,x;4 get object 0 zone attributes bmi .skipDrawInsectZone ; 2³ branch if SKIP_DRAW_INSECT_ZONE ldx objectHorizPositions_R,y;4 ;-------------------------------------- lda BANK0_HMOVE_Table,x ; 4 = @01 sta HMP0 ; 3 = @04 and #$0F ; 2 keep coarse position value tax ; 2 lda BANK0_CoarsePositionRoutineTableObject_00,x;4 sta tmpCoarsePositionObject0Vector;3 tya ; 2 move zone attributes to accumulator ldx tmpKernelZone_BANK0 ; 3 jmp (tmpCoarsePositionObject0Vector);5 = @25 .skipDrawInsectZone ;-------------------------------------- SLEEP_7 ; 7 = @01 SLEEP_7 ; 7 tya ; 2 move zone attributes to accumulator ldy #0 ; 2 jmp CheckToDrawMillipedeChain;3 BANK0_CoarsePositionRoutineTableObject_00 .byte CollisionRoutines sta tmpShotCollisionRoutineVector + 1 lda ShotCollisionRoutineLSBValues,y sta tmpShotCollisionRoutineVector jmp (tmpShotCollisionRoutineVector) .checkShotCollisionWithDDT ldx #MAX_DDT_BOMBS jmp .checkCreatureShotCollisions CreatureWithinShooterVertRange lda creatureSpriteIds_R - MAX_DDT_BOMBS,x;get creature sprite id value bpl .determineCreatureWithinShooterHorizRange;branch if not Millipede chain clc adc #$80 ; remove MILLIPEDE_CHAIN value .determineCreatureWithinShooterHorizRange tay lda shooterHorizPos ; get Shooter horizontal position sec sbc objectHorizPositions_R,x ; subtract object horizontal position bcc .creatureToTheLeftOfShooter ; branch if to the left of object cmp SpriteWidthValues,y lda tmpShooterKernelZone bcs .checkObjectWithinDDTCloudVertRange;branch if not in horizontal range bcc CreatureCollisionWithShooter ; unconditional branch .creatureToTheLeftOfShooter cmp #<-[W_SHOOTER - 1] lda tmpShooterKernelZone bcc .checkObjectWithinDDTCloudVertRange;branch if not in horizontal range lda SpriteWidthValues,y bne CreatureCollisionWithShooter lda tmpShooterKernelZone bcs .checkObjectWithinDDTCloudVertRange;unconditional branch CreatureWithinDDTCloudVertRange lda creatureSpriteIds_R - MAX_DDT_BOMBS,x;get creature sprite id value bpl .determineCreatureWithinCloudHorizRange;branch if not Millipede chain clc adc #$80 ; remove MILLIPEDE_CHAIN value .determineCreatureWithinCloudHorizRange tay lda tmpDDTCloudHorizPosition ; get DDT cloud horizontal position sec sbc creatureHorizPositions_R - MAX_DDT_BOMBS,x;subtract creature position bcc .creatureLeftOfDDTCloud ; branch if cloud left of creature cmp SpriteWidthValues,y bcc .creatureCollisionWithDDTCloud jmp .checkNextCreatureShotCollision;branch if not in horizontal range .creatureLeftOfDDTCloud cmp #<-15 bcs .creatureCollisionWithDDTCloud jmp .checkNextCreatureShotCollision;branch if not in horizontal range CreatureCollisionWithShooter lda waveState ; get current wave state value IF CHEAT_ENABLE ora #$80 ELSE and gameState ; mask with game state ENDIF bmi .skipCreatureCollisionWithShooter;branch if GS_GAME_OVER and SWARMING lda #<~INSECT_SPEED_MASK sta inchwormWaveState lda #<[ShooterCollisionAudioValues - LeftSoundChannelValues] sta leftSoundChannelIndex lda #<[InsectSlowDownAudioValues - RightSoundChannelValues] - 1 cmp rightSoundChannelIndex bcs .checkToIncrementSwarmingWave; branch to keep right sound channel value lda #0 sta rightSoundChannelIndex ; reset right sound channel value .checkToIncrementSwarmingWave lda waveState ; get current wave state value bpl .doneCreatureCollisionWithShooter;branch if NOT_SWARMING clc adc #1 << 2 ; increment swarming wave and #SWARMING_WAVE_MASK ; keep SWARMING_WAVE value sta tmpSwarmingWaveValue lda waveState ; get current wave state value and #<~SWARMING_WAVE_MASK ; clear SWARMING_WAVE number ora tmpSwarmingWaveValue sta waveState .doneCreatureCollisionWithShooter stx shotMushroomIndex lda #0 sta growingMushroomGardenArrayIndex jmp CheckIfEnoughTimeToBuildMillipedeSegments .skipCreatureCollisionWithShooter lda tmpShooterKernelZone jmp .checkObjectWithinDDTCloudVertRange .creatureCollisionWithDDTCloud cpy #ID_MILLIPEDE_CHAIN bcs CheckCloudCollisionWithMillipede cpy #ID_MILLIPEDE_HEAD beq CheckCloudCollisionWithMillipede cpy #ID_MILLIPEDE_SEGMENT beq CheckCloudCollisionWithMillipede cpy #ID_SHOOTER_DEATH bcs .doneDetermineCloudCollisionRoutine lda #>CollisionRoutines sta tmpShotCollisionRoutineVector + 1 bit waveState ; check current wave state value bpl DetermineCloudCollisionRoutine;branch if not SWARMING lda ShotCollisionRoutineLSBValues,y sta tmpShotCollisionRoutineVector jmp (tmpShotCollisionRoutineVector) DetermineCloudCollisionRoutine lda CloudCollisionRoutineLSBValues,y sta tmpShotCollisionRoutineVector lda DDTCloudPointValues,y jmp (tmpShotCollisionRoutineVector) .doneDetermineCloudCollisionRoutine jmp .checkNextCreatureShotCollision SwarmingInsectSpawningValues .byte ID_BEE, ID_BEE, ID_BEE, ID_BEE .byte ID_DRAGONFLY, ID_DRAGONFLY, ID_DRAGONFLY, ID_DRAGONFLY .byte ID_MOSQUITO + 1, ID_MOSQUITO, ID_MOSQUITO + 1, ID_MOSQUITO .byte ID_BEE, ID_DRAGONFLY, ID_MOSQUITO + 1, ID_MOSQUITO SwarmingInsectAudioValues .byte <[BeeAudioValues - RightSoundChannelValues] .byte <[BeeAudioValues - RightSoundChannelValues] .byte <[BeeAudioValues - RightSoundChannelValues] .byte <[BeeAudioValues - RightSoundChannelValues] .byte <[DragonflyAudioValues - RightSoundChannelValues] .byte <[DragonflyAudioValues - RightSoundChannelValues] .byte <[DragonflyAudioValues - RightSoundChannelValues] .byte <[DragonflyAudioValues - RightSoundChannelValues] .byte <[MosquitoAudioValues - RightSoundChannelValues] .byte <[MosquitoAudioValues - RightSoundChannelValues] .byte <[MosquitoAudioValues - RightSoundChannelValues] .byte <[MosquitoAudioValues - RightSoundChannelValues] .byte <[MosquitoAudioValues - RightSoundChannelValues] .byte <[DragonflyAudioValues - RightSoundChannelValues] .byte <[MosquitoAudioValues - RightSoundChannelValues] .byte <[BeeAudioValues - RightSoundChannelValues] CheckCloudCollisionWithMillipede ldx #0 ldy #0 lda numberOfMillipedeSegments ; get number of Millipede segments sta tmpNumberOfMillipedeSegments .checkCloudCollisionWithMillipede lda millipedeSegmentState,x ; get Millipede segment state and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value sec sbc tmpDDTCloudUpperKernelZone cmp #<-2 bcc .checkCurrentMillipedeChainDone lda tmpDDTCloudHorizPosition ; get DDT cloud horizontal position sec sbc millipedeHorizPosition,x ; subtract segment horizontal position bcc .millipedeLeftOfDDTCloud cmp #W_MILLIPEDE_HEAD bcs .checkCurrentMillipedeChainDone bcc .scorePointsForCloudCollisionWithMillipede;unconditional branch .millipedeLeftOfDDTCloud cmp #<-15 bcc .checkCurrentMillipedeChainDone .scorePointsForCloudCollisionWithMillipede sed clc lda millipedeSegmentState,x ; get Millipede segment state bmi .scoreForMillipedeSegmentCloudCollision;branch if MILLIPEDE_BODY_SEGMENT lda #<[POINTS_MILLIPEDE_SEGMENT * 3] adc tmpOnesPoints sta tmpOnesPoints lda #1 - 1 beq .incrementHundredsPointValue ; unconditional branch .scoreForMillipedeSegmentCloudCollision lda #[POINTS_MILLIPEDE_HEAD >> 8] * 3 .incrementHundredsPointValue adc tmpHundredsPoints sta tmpHundredsPoints lda tmpThousandsPoints adc #1 - 1 sta tmpThousandsPoints cld dec numberOfMillipedeSegments ; reduce number of Millipede segments cpx tmpNumberOfMillipedeSegments inx bcc .checkCloudCollisionWithMillipede bcs .doneCheckCloudCollisionWithMillipede;unconditional branch .checkCurrentMillipedeChainDone sty tmpMillipedeChainIndex cpx tmpMillipedeChainIndex beq .checkMillipedeChainDone lda millipedeSegmentState,x ; get Millipede segment state and #<~MILLIPEDE_SEGMENT_MASK bpl .setSegmentStateForDDTCloudCollision;set to MILLIPEDE_HEAD_SEGMENT .breakTheChainForDDTCloudCollision lda millipedeSegmentState,x ; get Millipede segment state .setSegmentStateForDDTCloudCollision sta millipedeSegmentState,y lda millipedeHorizPosition,x ; get Millipede segment horizontal position sta millipedeHorizPosition,y lda millipedeAttributes_R,x sta millipedeAttributes_W,y iny cpx tmpNumberOfMillipedeSegments inx bcc .breakTheChainForDDTCloudCollision bcs .doneCheckCloudCollisionWithMillipede;unconditional branch .checkMillipedeChainDone iny cpx tmpNumberOfMillipedeSegments inx bcc .checkCloudCollisionWithMillipede .doneCheckCloudCollisionWithMillipede jmp .checkToSpeedUpLastRemainingMillipedeHead CloudCollisionRoutineLSBValues .byte > 8] DDTCloudCollisionWithBee DDTCloudCollisionWithDragonfly jmp ScorePointsForPotentialSwarmingInsect ShotCollisionWithMillipede jmp ShotInMillipedeHorizRange ShotCollisionWithEarwig lda #0 sta shotVertPos ; set to turn off shot lda #[POINTS_EARWIG >> 8] DDTCloudCollisionWithEarwig jmp ScorePointsForDestroyingInsect ShotCollisionWithDragonfly lda #0 sta shotVertPos ; set to turn off shot lda #[POINTS_DRAGONFLY >> 8] jmp ScorePointsForPotentialSwarmingInsect ShotCollisionWithBeetle lda #0 sta shotVertPos ; set to turn off shot lda #[POINTS_BEETLES >> 8] DDTCloudCollisionWithBeetle dec gardenShiftValues ; set to shift garden down jmp ScorePointsForDestroyingInsect ShotCollisionWithMosquito lda #0 sta shotVertPos ; set to turn off shot lda #[POINTS_MOSQUITO >> 8] DDTCloudCollisionWithMosquito inc gardenShiftValues ; set to shift garden up jmp ScorePointsForPotentialSwarmingInsect ShotCollisionWithInchworm lda #0 sta shotVertPos ; set to turn off shot lda #[POINTS_INCHWORM >> 8] DDTCloudCollisionWithInchworm sta tmpInchwormPointValue ; save Inchworm point value lda gameState + 1 ; get high game state value ora #INIT_INCHWORM_SPAWN_TIMER sta gameState + 1 ; reinitialize Inchworm spawn timer lda tmpInchwormPointValue ; restore Inchworm point value to accumulator IF COMPILE_REGION = PAL50 ldy #PLAYER_MOVEMENT_NORMAL | INSECT_SPEED_SLOW | 10 ELSE ldy #PLAYER_MOVEMENT_NORMAL | INSECT_SPEED_SLOW ENDIF sty inchwormWaveState ldy rightSoundChannelIndex ; get right sound channel index value beq .setToPlayInsectSlowDownSounds;branch if right sound channel off cpy #<[InsectSlowDownAudioValues - RightSoundChannelValues] bcc .doneShotCollisionWithInchworm .setToPlayInsectSlowDownSounds ldy #<[InsectSlowDownAudioValues - RightSoundChannelValues] sty rightSoundChannelIndex .doneShotCollisionWithInchworm jmp ScorePointsForDestroyingInsect ScorePointsForSpiderShot lda #0 sta shotVertPos ; set to turn off shot lda objectAttributes_R,x ; get Spider attribute value and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value sta objectAttributes_W,x sec sbc tmpShooterKernelZone ; subtract Shooter kernel zone beq .spiderInShooterKernelZone bcc .checkNextShotCollision tay ; move distance to y register lda SpiderPointValues,y sta tmpHundredsPoints lda SpiderPointSpriteIdValues,y sta spriteIdArray_W,x jmp SetSoundChannelValuesForPointScore .spiderInShooterKernelZone jmp CreatureWithinShooterVertRange IgnoreShotCollision .checkNextShotCollision lda tmpShotUpperKernelZone ; get Shot upper kernel zone jmp .checkNextDDTBombShotCollision IgnoreDDTCloudCollision jmp .checkNextCreatureShotCollision ShotCollisionWithDDTBomb lda #<[DDTBombExplosionAudioValues - LeftSoundChannelValues] sta leftSoundChannelIndex lda objectHorizPositions_R,x ; get DDT horizontal position sec sbc #4 ; subtract by 4 sta objectHorizPositions_W,x ; set horizontal position for DDT Cloud lsr bcc .evenDDTCloudHorizPosition ; branch if even position lsr sec bcs .setDDTCloudMushroomMaskingBitIndex;unconditional branch .evenDDTCloudHorizPosition lsr .setDDTCloudMushroomMaskingBitIndex tay ; set mushroom masking index adc #4 sta tmpEndDDTCloudMushroomMaskingIndex lda #ID_DDT_CLOUD sta spriteIdArray_W,x ; set initial DDT Cloud sprite id lda #0 sta shotVertPos ; turn off Shot lda #[POINTS_DDT_BOMB >> 8] sta tmpHundredsPoints ; set point value for DDT lda tmpShotUpperKernelZone clc adc kernelZoneAdjustment ; increment by kernel zone adjustment sta tmpShotUpperKernelZone .determineDDTCloudMushroomMaskingBitIndex lda tmpShotUpperKernelZone cpy #16 bcc .removeMushroomForDDTCloud adc #<[rightMushroomArray_W - leftMushroomArray_W] - 1 .removeMushroomForDDTCloud tax ; move adjusted zone value to x register lsr tya ; move mushroom masking index to accumulator bcs .removeRightSideMushroomsForDDTCloud lsr lda #$FF bcs .removeLeftSideOddScanlineMushroom eor BANK1_EvenMushroomMaskingBits,y;isolate Mushroom masking bit and mushroomArray_R - 2,x ; remove Mushroom bit sta mushroomArray_W - 2,x lda #$FF eor BANK1_EvenMushroomMaskingBits,y;isolate Flower masking bit and leftFlowerArray_R - 2,x ; remove Flower bit jmp .checkToRemoveFlowerForDDTCloud .removeLeftSideOddScanlineMushroom eor BANK1_OddMushroomMaskingBits,y;isolate Mushroom masking bit dex and mushroomArray_R - 2,x sta mushroomArray_W - 2,x lda #$FF eor BANK1_OddMushroomMaskingBits,y;isolate Mushroom masking bit and leftFlowerArray_R - 2,x jmp .checkToRemoveFlowerForDDTCloud .removeRightSideMushroomsForDDTCloud lsr lda #$FF bcs .removeRightSideOddScanlineMushroom eor BANK1_EvenMushroomMaskingBits,y;isolate Mushroom masking bit dex and mushroomArray_R - 2,x sta mushroomArray_W - 2,x lda #$FF eor BANK1_EvenMushroomMaskingBits,y;isolate Mushroom masking bit and leftFlowerArray_R - 2,x jmp .checkToRemoveFlowerForDDTCloud .removeRightSideOddScanlineMushroom eor BANK1_OddMushroomMaskingBits,y;isolate Mushroom masking bit and mushroomArray_R - 2,x sta mushroomArray_W - 2,x lda #$FF eor BANK1_OddMushroomMaskingBits,y;isolate Mushroom masking bit and leftFlowerArray_R - 2,x .checkToRemoveFlowerForDDTCloud cpx #<[millipedeAttributes_W - leftFlowerArray_W] + 2 bcc .removeFlowerForDDTCloud ; branch if within left Flower index range cpx #<[rightFlowerArray_W - leftFlowerArray_W] + 2 bcc .incrementMushroomMaskingBitValue;branch if not in right Flower index range cpx #<[mushroomArray_W - leftFlowerArray_W] + 2 bcs .incrementMushroomMaskingBitValue;branch if not in Flower index range .removeFlowerForDDTCloud sta leftFlowerArray_W - 2,x .incrementMushroomMaskingBitValue iny cpy tmpEndDDTCloudMushroomMaskingIndex bne .determineDDTCloudMushroomMaskingBitIndex jmp CheckIfEnoughTimeToBuildMillipedeSegments ShotInMillipedeHorizRange lda tmpObjectKernelZone ; get Millipede kernel zone cmp tmpShotLowerKernelZone ; compare with lower shot zone value bne .shotInMillipedeHorizRange ; branch if not in same zone jmp CheckCreatureVerticalRangeCollisions .shotInMillipedeHorizRange dec tmpShotUpperKernelZone lda tmpShotObjectHorizDistance ; get horizontal distance value and #<~3 clc adc objectHorizPositions_R,x ; increment by Millipede segment tay iny stx tmpObjectCollisionIdx ; save object index for later ldx numberOfMillipedeSegments ; get number of Millipede segments .checkShootingNextMillipedeSegment lda millipedeSegmentState,x ; get Millipede segment state and #KERNEL_ZONE_MASK ; keep Millipede KERNEL_ZONE value cmp tmpShotUpperKernelZone beq .millipedeShot ; branch if Millipede in Shot kernel zone dex bpl .checkShootingNextMillipedeSegment bmi .doneShotInMillipedeHorizRange;unconditional branch .millipedeShot tya sec sbc millipedeHorizPosition,x ; subtract segment horizontal position cmp #W_MILLIPEDE_HEAD - 1 bcc .scorePointsForShootingMillipede;branch if shot Millipede segment dex bpl .checkShootingNextMillipedeSegment .doneShotInMillipedeHorizRange inc tmpShotUpperKernelZone ldx tmpObjectCollisionIdx ; restore object index to x register jmp .checkNextDDTBombShotCollision .scorePointsForShootingMillipede dey lda millipedeSegmentState,x ; get Millipede segment state sta tmpShotMillipedeState bpl .scorePointsForShootingMillipedeHead;branch if MILLIPEDE_HEAD_SEGMENT lda #POINTS_MILLIPEDE_SEGMENT sta tmpOnesPoints bne .checkEndOfMillipedeChain ; unconditional branch .scorePointsForShootingMillipedeHead lda #[POINTS_MILLIPEDE_HEAD >> 8] sta tmpHundredsPoints .checkEndOfMillipedeChain lda millipedeHorizPosition,x ; get Millipede segment horizontal position sta tmpMillipedeHorizPos stx tmpShotMillipedeIndex cpx numberOfMillipedeSegments beq .foundEndOfMillipedeChain lda millipedeSegmentState + 1,x ; get trailing Millipede segment state and #<~MILLIPEDE_SEGMENT_MASK ; set to MILLIPEDE_HEAD_SEGMENT bpl .setMillipedeSegmentState ; unconditional branch .breakTheChain lda millipedeSegmentState + 1,x ; get trailing Millipede segment state .setMillipedeSegmentState sta millipedeSegmentState,x lda millipedeHorizPosition + 1,x ; get trailing segment horizontal position sta millipedeHorizPosition,x lda millipedeAttributes_R + 1,x ; get trailing Millipede segment attributes sta millipedeAttributes_W,x inx cpx numberOfMillipedeSegments bne .breakTheChain .foundEndOfMillipedeChain dec numberOfMillipedeSegments bmi .determineShotMillipedeLocation ldx tmpShotMillipedeIndex ; get index value of shot Millipede segment dex ; decrement to get leading Millipede segment bmi .determineShotMillipedeLocation lda tmpMillipedeHorizPos .findShotMillipedeSegmentHorizPos cmp millipedeHorizPosition,x beq CheckToPlaceMushroomForShotMillipede dex bpl .findShotMillipedeSegmentHorizPos bmi .determineShotMillipedeLocation;unconditional branch CheckToPlaceMushroomForShotMillipede lda millipedeSegmentState,x ; get Millipede segment state and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value cmp tmpShotUpperKernelZone beq .checkEndOfMillipedeChain .determineShotMillipedeLocation lda shotVertPos ; get Shot vertical position eor kernelZoneAdjustment eor #1 sta tmpShotKernelZone lsr ; shift D0 to carry tya ; move Shot horiz position to accumulator bcc .determineMushroomHorizPosition;branch on even scan line sbc #W_MILLIPEDE_HEAD .determineMushroomHorizPosition tay ; set to Millipede horizonal position lda tmpShotMillipedeState ; get shot Millipede segment state and #MILLIPEDE_HORIZ_DIR_MASK ; keep MILLIPEDE_HORIZ_DIR bne .determineMushroomMaskingBitIndex;branch if MILLIPEDE_DIR_LEFT tya ; get Millipede horizontal position clc adc #[W_MILLIPEDE_HEAD * 2] - 1 tay .determineMushroomMaskingBitIndex tya ; get Millipede horizontal position lsr lsr and #<~1 tay lda tmpShotKernelZone ; get Shot adjusted kernel zone lsr tya ; get Millipede horizontal position bcs .setMushroomMaskingBitIndex ; branch if Shot in odd zone adc #<[BANK1_EvenMushroomMaskingBits - BANK1_MushroomMaskingBits - 1] .setMushroomMaskingBitIndex tax inx cmp #63 bmi .determineMushroomLocation ldx #63 .determineMushroomLocation txa ; move Mushroom masking index to accumulator and #$10 beq .placeMushroomForShotMillipede;branch for left Mushroom array lda #<[rightMushroomArray_W - leftMushroomArray_W] .placeMushroomForShotMillipede sec adc tmpShotUpperKernelZone adc kernelZoneAdjustment ; increment by kernel zone adjustment tay lda mushroomArray_R - 2,y ora BANK1_MushroomMaskingBits,x sta mushroomArray_W - 2,y lda beetleSpawnTimer ora #$80 sta beetleSpawnTimer .checkToSpeedUpLastRemainingMillipedeHead lda numberOfMillipedeSegments ; get number of Millipede segments bne CheckForWaveCompleted ; branch if more Millipede segments lda millipedeAttributes_R ora #MILLIPEDE_FAST sta millipedeAttributes_W jmp .checkToPlayMushroonTallySounds CheckForWaveCompleted bpl .turnOffShot ; branch if more Millipede segments lda gameWaveValues ; get current game wave values cmp #3 bne .determineWaveTransitionTimerValue;branch if not growing Mushroom Garden ldy #<[rightMushroomArray_W - leftMushroomArray_W] sty growingMushroomGardenArrayIndex ldy #0 sty growingMushroomGardenIndex lda #128 - 256 bne .setWaveTransitionTimerValue ; unconditional branch .determineWaveTransitionTimerValue lsr ; shift D0 to carry lda #128 - 256 bcc .setWaveTransitionTimerValue ; branch if an even wave lda #255 - 256 .setWaveTransitionTimerValue sta waveTransitionTimer .turnOffShot lda #0 sta shotVertPos jmp .checkToPlayMushroonTallySounds ; ; This code is never executed. It looks as if it could have been an old routine ; for shooting a Bee. ; IF ORIGINAL_ROM .byte $BD,$93,$10,$30,$07,$09,$80,$9D,$13,$10,$30,$61,$A9,$02,$D0,$06 ENDIF ScorePointsForDestroyingInsect bit waveState ; check current wave state values bpl .scorePointsForNonSwarmingInsects;branch if NOT_SWARMING bmi .scorePointsForSwarmingInsects;unconditional branch ScorePointsForPotentialSwarmingInsect bit waveState ; check current wave state values bpl .scorePointsForNonSwarmingInsects;branch if NOT_SWARMING dec numberActiveSwarmingInsects ; reduce number of active Swarming insects .scorePointsForSwarmingInsects ldy insectSwarmShootTally bpl .setPointsForDestroyingSwarmingInsect tay ; move hundreds point value to y register cpy #$10 bcc .determinePointIndexForDDTCloud;branch if point value less than 1,000 ldy #2 .determinePointIndexForDDTCloud lda DDTBonusPointIndexValues,y ; get bound point index value for DDT_CLOUD tay ; move index value to y register .setPointsForDestroyingSwarmingInsect lda objectAttributes_R,x ; get object attribute value and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value sta objectAttributes_W,x lda BonusPointSpriteIdValues,y ; get swarming bonus point sprite id value sta spriteIdArray_W,x ; set sprite id to swarming bonus point lda BonusPointHundredsValues,y ; get bonus point hundreds value sta tmpHundredsPoints dey bmi .checkToPlayMushroonTallySounds sty insectSwarmShootTally bpl .checkToPlayMushroonTallySounds;unconditional branch .scorePointsForNonSwarmingInsects sta tmpHundredsPoints lda #0 sta objectAttributes_W,x ; clear object attribute value SetSoundChannelValuesForPointScore ldy spriteIdArray_R,x ; get sprite id value cpy #ID_SHOOTER_DEATH bcc .checkToResetRightSoundChannelIndex;branch if an insect cpy #ID_POINTS_300 bcc .checkToPlayMushroonTallySounds;branch if ID_SPARK or ID_MILLIPEDE cpy #ID_DDT bcs .checkToPlayMushroonTallySounds;branch if ID_DDT or ID_DDT_CLOUD ldy #7 .checkToResetRightSoundChannelIndex lda rightSoundChannelIndex ; get right sound channel index value cmp BANK1_RightAudioValueLowerBounds,y bcc .checkToPlayMushroonTallySounds cmp BANK1_RightAudioValueUpperBounds,y bcs .checkToPlayMushroonTallySounds lda #0 sta rightSoundChannelIndex ; reset right sound channel index .checkToPlayMushroonTallySounds lda #<[MushroomTallyAudioValues - LeftSoundChannelValues] ldx leftSoundChannelIndex ; get left sound channel index value beq .setLeftSoundChannelIndex ; branch if playing heart beat cmp leftSoundChannelIndex bcs .doneSetSoundChannelValuesForPointScore .setLeftSoundChannelIndex sta leftSoundChannelIndex .doneSetSoundChannelValuesForPointScore jmp CheckIfEnoughTimeToBuildMillipedeSegments TimeNeededForMillipedeMovement .byte 127 + 6 .byte 127 + 7 .byte 127 + 8 .byte 127 + 9 .byte 127 + 10 .byte 127 + 11 .byte 127 + 12 .byte 127 + 13 .byte 127 + 14 SpiderPointValues .byte POINTS_SPIDER_CLOSEST >> 8, POINTS_SPIDER_CLOSEST >> 8 .byte POINTS_SPIDER_CLOSE >> 8, POINTS_SPIDER_CLOSE >> 8 .byte POINTS_SPIDER_MEDIUM >> 8, POINTS_SPIDER_MEDIUM >> 8 .byte POINTS_SPIDER_DISTANT >> 8, POINTS_SPIDER_DISTANT >> 8 .byte POINTS_SPIDER_DISTANT >> 8, POINTS_SPIDER_DISTANT >> 8 SpiderPointSpriteIdValues .byte ID_POINTS_1200, ID_POINTS_1200, ID_POINTS_900, ID_POINTS_900, ID_POINTS_600 .byte ID_POINTS_600, ID_POINTS_300, ID_POINTS_300, ID_POINTS_300, ID_POINTS_300 DDTBonusPointIndexValues .byte 8, 8, 8 ; ID_POINTS_200 .byte 7 ; ID_POINTS_300 .byte 6 ; ID_POINTS_400 .byte 5 ; ID_POINTS_500 .byte 4 ; ID_POINTS_600 .byte 3 ; ID_POINTS_700 .byte 2 ; ID_POINTS_800 .byte 1 ; ID_POINTS_900 FILL_BOUNDARY 256, 0 BonusPointHundredsValues .byte [$1000 >> 8] .byte [$0900 >> 8] .byte [$0800 >> 8] .byte [$0700 >> 8] .byte [$0600 >> 8] .byte [$0500 >> 8] .byte [$0400 >> 8] .byte [$0300 >> 8] .byte [$0200 >> 8] BonusPointSpriteIdValues .byte ID_POINTS_1000, ID_POINTS_900, ID_POINTS_800, ID_POINTS_700 .byte ID_POINTS_600, ID_POINTS_500, ID_POINTS_400, ID_POINTS_300, ID_POINTS_200 ShotCollisionRoutineLSBValues .byte ObjectSpawningRoutines sta tmpObjectSpawningVector + 1 lda ObjectSpawningRoutineTable,x sta tmpObjectSpawningVector jmp (tmpObjectSpawningVector) ObjectSpawningRoutineTable .byte > 8] DDT_CREATURE_POINT_VALUE [POINTS_BEE >> 8] DDT_CREATURE_POINT_VALUE [POINTS_EARWIG >> 8] DDT_CREATURE_POINT_VALUE [POINTS_EARWIG >> 8] DDT_CREATURE_POINT_VALUE [POINTS_EARWIG >> 8] DDT_CREATURE_POINT_VALUE [POINTS_EARWIG >> 8] DDT_CREATURE_POINT_VALUE [POINTS_SPIDER_MEDIUM >> 8] DDT_CREATURE_POINT_VALUE [POINTS_SPIDER_MEDIUM >> 8] DDT_CREATURE_POINT_VALUE [POINTS_SPIDER_MEDIUM >> 8] DDT_CREATURE_POINT_VALUE [POINTS_MOSQUITO >> 8] DDT_CREATURE_POINT_VALUE [POINTS_MOSQUITO >> 8] DDT_CREATURE_POINT_VALUE [POINTS_MOSQUITO >> 8] DDT_CREATURE_POINT_VALUE [POINTS_MOSQUITO >> 8] DDT_CREATURE_POINT_VALUE [POINTS_DRAGONFLY >> 8] DDT_CREATURE_POINT_VALUE [POINTS_DRAGONFLY >> 8] DDT_CREATURE_POINT_VALUE [POINTS_DRAGONFLY >> 8] DDT_CREATURE_POINT_VALUE [POINTS_INCHWORM >> 8] DDT_CREATURE_POINT_VALUE [POINTS_INCHWORM >> 8] DDT_CREATURE_POINT_VALUE [POINTS_INCHWORM >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] DDT_CREATURE_POINT_VALUE [POINTS_BEETLES >> 8] IF ORIGINAL_ROM FILL_BOUNDARY 228, 0 .byte " DAVE STAUGAS LOVES BEATRICE HABLIG " ELSE FILL_BOUNDARY 256, 0 ENDIF FILL_BOUNDARY 228, 0 BANK1_ProcessObjectMovements lda BANK2STROBE jmp.w $00 BANK1_SwitchToScoreKernel lda BANK1STROBE jmp Overscan BANK1_Start lda BANK3STROBE jmp BANK3_Start .byte 0, 0, 0, 0 ; hotspot locations not available for data FILL_BOUNDARY 250, 0 echo "***", (FREE_BYTES)d, "BYTES OF ROM FREE IN BANK1" .word BANK1_Start .word BANK1_Start .word BANK1_Start ;=============================================================================== ; R O M - C O D E (BANK2) ;=============================================================================== SEG Bank2 .org BANK2_BASE .rorg BANK2_REORG FREE_BYTES SET 0 .ds 256, 0 ; first page reserved for Superchip RAM ScoreKernel lda #>NumberFonts ; 2 = @35 sta graphicsPointers + 1 ; 3 sta graphicsPointers + 3 ; 3 SLEEP 2 ; 2 ldy #BLACK ; 2 lda playerScore ; 3 get score thousands value lsr ; 2 shift upper nybbles to lower nybbles lsr ; 2 lsr ; 2 lsr ; 2 bne .setHundredThousandsZeroSuppressValue;2³ lda #ID_BLANK_FONT ; 2 suppress leading zero .setHundredThousandsZeroSuppressValue sta tmpZeroSuppressValue ; 3 tax ; 2 lda NumberTable,x ; 4 get graphic LSB value sta graphicsPointers ; 3 set digit graphic pointer LSB value lda gameWaveValues ; 3 get current game wave values ;-------------------------------------- clc ; 2 = @01 adc #6 ; 2 tax ; 2 lda BANK2_WaveColorValues,x; 4 set to score border color index and #$F0 ; 2 keep color value ora #7 ; 2 set luminance value sty COLUBK ; 3 = @16 sta COLUPF ; 3 = @19 lda #$FF ; 2 sta PF1 ; 3 = @24 sta PF2 ; 3 = @27 sty GRP1 ; 3 = @30 sty GRP0 ; 3 = @33 lda playerScore ; 3 get score thousands value and #$0F ; 2 keep lower nybbles bne .setTenThousandsZeroSuppressValue;2³ lda #ID_BLANK_FONT ; 2 cmp tmpZeroSuppressValue ; 3 bmi .setTenThousandsZeroSuppressValue;2³ beq .setTenThousandsZeroSuppressValue;2³ lda #ID_ZERO ; 2 .setTenThousandsZeroSuppressValue sta tmpZeroSuppressValue ; 3 tay ; 2 lda NumberTable,y ; 4 get graphic LSB value sta graphicsPointers + 2 ; 3 set digit graphic pointer LSB value lda playerScore + 1 ; 3 get score hundreds value lsr ; 2 shift upper nybbles to lower nybbles lsr ; 2 lsr ; 2 lsr ; 2 bne .setThousandsZeroSuppressValue;2³ lda #ID_BLANK_FONT ; 2 cmp tmpZeroSuppressValue ; 3 beq .setThousandsZeroSuppressValue;2³ lda #ID_ZERO ; 2 .setThousandsZeroSuppressValue sta tmpZeroSuppressValue ; 3 tay ; 2 lda NumberTable,y ; 4 get graphic LSB value sta graphicsPointers + 4 ; 3 set digit graphic pointer LSB value lda playerScore + 1 ; 3 get score hundreds value and #$0F ; 2 keep lower nybbles bne .setHundredsZeroSuppressValue;2³ lda #ID_BLANK_FONT ; 2 cmp tmpZeroSuppressValue ; 3 beq .setHundredsZeroSuppressValue;2³ lda #ID_ZERO ; 2 .setHundredsZeroSuppressValue sta tmpZeroSuppressValue ; 3 tay ; 2 lda NumberTable,y ; 4 get graphic LSB value sta graphicsPointers + 6 ; 3 set digit graphic pointer LSB value lda playerScore + 2 ; 3 get score ones value lsr ; 2 shift upper nybbles to lower nybbles lsr ; 2 lsr ; 2 lsr ; 2 tay ; 2 lda NumberTable,y ; 4 sta graphicsPointers + 8 ; 3 sta WSYNC ;--------------------------------------- lda.w playerScore + 2 ; 4 get score ones value and #$0F ; 2 keep lower nybbles tay ; 2 lda NumberTable,y ; 4 get graphic LSB value sta graphicsPointers + 10 ; 3 set digit graphic pointer LSB value ldx #BLACK ; 2 stx COLUPF ; 3 = @20 lda gameState ; 3 get current game state and #LIVES_MASK ; 2 keep number of lives tay ; 2 lda LivesGraphicsPF1Values,y;4 sta PF1 ; 3 = @34 lda LivesGraphicsPF2Values,y;4 sta PF2 ; 3 = @41 stx HMP1 ; 3 = @44 set to HMOVE_0 (i.e. x = 0) inx ; 2 x = 1 stx VDELP0 ; 3 = @49 lda #THREE_COPIES ; 2 sta RESP0 ; 3 = @54 sta RESP1 ; 3 = @57 stx VDELP1 ; 3 = @60 sta NUSIZ0 ; 3 = @63 sta NUSIZ1 ; 3 = @66 lda #HMOVE_R1 ; 2 sta HMP0 ; 3 = @71 lda frameCount ; 3 get current frame count ldx #COLORS_SCORE ; 2 = @76 ;-------------------------------------- sta HMOVE ; 3 bit gameState ; 3 check current game state bvc .currentlySelectingGame; 2³ branch if not GS_SELECTING_GAME SLEEP 2 ; 2 and #8 ; 2 beq .flashScoreColors ; 2³ bne .setScoreColors ; 3 unconditional branch .currentlySelectingGame jmp .checkToSetColorsForTitleScreen;3 .checkToSetColorsForTitleScreen bmi .flashScoreColors ; 2³ branch if GS_GAME_OVER bpl .setScoreColors ; 3 unconditional branch .flashScoreColors tax ; 2 .setScoreColors stx COLUP0 ; 3 = @20 stx COLUP1 ; 3 = @23 lda #>NumberFonts ; 2 sta graphicsPointers + 5 ; 3 sta graphicsPointers + 7 ; 3 sta graphicsPointers + 9 ; 3 sta graphicsPointers + 11 ; 3 ldx displayScanOutControl ; 3 get display scan out value lda RemainingLivesColorMaskValues,x;4 ldx gameWaveValues ; 3 get current game wave values and BANK2_WaveColorValues,x; 4 sta tmpRemainingLivesColor ; 3 SLEEP_6 ; 6 lda #TitleScreenGraphics ; 2 sta graphicsPointers + 1 ; 3 sta graphicsPointers + 3 ; 3 sta graphicsPointers + 5 ; 3 sta graphicsPointers + 7 ; 3 sta graphicsPointers + 9 ; 3 sta graphicsPointers + 11 ; 3 lda #BLACK ; 2 sta COLUBK ; 3 = @72 sta WSYNC ;-------------------------------------- sta HMOVE ; 3 sta VBLANK ; 3 = @06 enable TIA (i.e. D1 = 0) lda #CoarsePositionObject0Routines;2 sta tmpCoarsePositionObject0Vector + 1;3 lda #>CoarsePositionObject1Routines;2 sta tmpCoarsePositionObject1Vector + 1;3 lda #>CoarsePositionShooterRoutines;2 sta tmpCoarsePositionShooterVector + 1;3 lda tmpKernelShooterState ; 3 sta kernelShooterState ; 3 lda tmpKernelZone_BANK0 ; 3 beq .doneBitmapKernelForSelectingScore;2³ lda tmpShooterKernelZoneValue;3 sta shooterKernelZoneValue ; 3 jmp BANK2_JumpIntoGraphicsZone_05;3 .doneBitmapKernelForSelectingScore jmp DoneBitmapKernelForSelectingScore;3 FILL_BOUNDARY 256, 0 BANK2_HMOVE_Table .byte HMOVE_L5 | 0, HMOVE_L4 | 0, HMOVE_L3 | 0, HMOVE_L2 | 0, HMOVE_L1 | 0 .byte HMOVE_0 | 0, HMOVE_R1 | 0, HMOVE_R2 | 0, HMOVE_R3 | 0, HMOVE_R4 | 0 .byte HMOVE_R5 | 0, HMOVE_R6 | 0, HMOVE_R7 | 0, HMOVE_R8 | 0 .byte HMOVE_L6 | 1, HMOVE_L5 | 1, HMOVE_L4 | 1, HMOVE_L3 | 1, HMOVE_L2 | 1 .byte HMOVE_L1 | 1, HMOVE_0 | 1, HMOVE_R1 | 1, HMOVE_R2 | 1, HMOVE_R3 | 1 .byte HMOVE_R4 | 1, HMOVE_R5 | 1, HMOVE_R6 | 1, HMOVE_R7 | 1, HMOVE_R8 | 1 .byte HMOVE_L6 | 2, HMOVE_L5 | 2, HMOVE_L4 | 2, HMOVE_L3 | 2, HMOVE_L2 | 2 .byte HMOVE_L1 | 2, HMOVE_0 | 2, HMOVE_R1 | 2, HMOVE_R2 | 2, HMOVE_R3 | 2 .byte HMOVE_R4 | 2, HMOVE_R5 | 2, HMOVE_R6 | 2, HMOVE_R7 | 2, HMOVE_R8 | 2 .byte HMOVE_L6 | 3, HMOVE_L5 | 3, HMOVE_L4 | 3, HMOVE_L3 | 3, HMOVE_L2 | 3 .byte HMOVE_L1 | 3, HMOVE_0 | 3, HMOVE_R1 | 3, HMOVE_R2 | 3, HMOVE_R3 | 3 .byte HMOVE_R4 | 3, HMOVE_R5 | 3, HMOVE_R6 | 3, HMOVE_R7 | 3, HMOVE_R8 | 3 .byte HMOVE_L6 | 4, HMOVE_L5 | 4, HMOVE_L4 | 4, HMOVE_L3 | 4, HMOVE_L2 | 4 .byte HMOVE_L1 | 4, HMOVE_0 | 4, HMOVE_R1 | 4, HMOVE_R2 | 4, HMOVE_R3 | 4 .byte HMOVE_R4 | 4, HMOVE_R5 | 4, HMOVE_R6 | 4, HMOVE_R7 | 4, HMOVE_R8 | 4 .byte HMOVE_L6 | 5, HMOVE_L5 | 5, HMOVE_L4 | 5, HMOVE_L3 | 5, HMOVE_L2 | 5 .byte HMOVE_L1 | 5, HMOVE_0 | 5, HMOVE_R1 | 5, HMOVE_R2 | 5, HMOVE_R3 | 5 .byte HMOVE_R4 | 5, HMOVE_R5 | 5, HMOVE_R6 | 5, HMOVE_R7 | 5, HMOVE_R8 | 5 .byte HMOVE_L6 | 6, HMOVE_L5 | 6, HMOVE_L4 | 6, HMOVE_L3 | 6, HMOVE_L2 | 6 .byte HMOVE_L1 | 6, HMOVE_0 | 6, HMOVE_R1 | 6, HMOVE_R2 | 6, HMOVE_R3 | 6 .byte HMOVE_R4 | 6, HMOVE_R5 | 6, HMOVE_R6 | 6, HMOVE_R7 | 6, HMOVE_R8 | 6 .byte HMOVE_L6 | 7, HMOVE_L5 | 7, HMOVE_L4 | 7, HMOVE_L3 | 7, HMOVE_L2 | 7 .byte HMOVE_L1 | 7, HMOVE_0 | 7, HMOVE_R1 | 7, HMOVE_R2 | 7, HMOVE_R3 | 7 .byte HMOVE_R4 | 7, HMOVE_R5 | 7, HMOVE_R6 | 7, HMOVE_R7 | 7, HMOVE_R8 | 7 .byte HMOVE_L6 | 8, HMOVE_L5 | 8, HMOVE_L4 | 8, HMOVE_L3 | 8, HMOVE_L2 | 8 .byte HMOVE_L1 | 8, HMOVE_0 | 8, HMOVE_R1 | 8, HMOVE_R2 | 8 BANK2_CoarsePositionRoutineTableObject_00 .byte GameOverBitmap ; 2 sta graphicsPointers + 1 ; 3 sta graphicsPointers + 3 ; 3 sta graphicsPointers + 5 ; 3 sta graphicsPointers + 7 ; 3 sta graphicsPointers + 9 ; 3 sta graphicsPointers + 11 ; 3 bvs SetupPointersForStartingScore;2³ branch if GS_SELECTING_GAME lda #ObjectMovementRoutines sta tmpObjectMoveRoutineVector + 1 bit waveState ; check current game wave values bpl .processObjectMoveRoutines ; branch if NOT_SWARMING ldx #13 .processObjectMoveRoutines lda INTIM ; get RIOT timer value cmp #127 + 4 bpl .timeToSafelyProcessMovement ; branch if time available to process move jmp SwitchBankForNewFrame .timeToSafelyProcessMovement ldy creatureAttributes_R,x ; get creature attribute values bne .processObjectMovementRoutine; branch if creature present MoveNextObject dex bpl .processObjectMoveRoutines jmp SwitchBankForNewFrame .processObjectMovementRoutine lda creatureSpriteIds_R,x ; get creature sprite id value stx tmpSpriteIdx tax lda ObjectMoveRoutineTable,x sta tmpObjectMoveRoutineVector ldx tmpSpriteIdx jmp (tmpObjectMoveRoutineVector) GameOverBitmap GameOverBitmap_00 .byte $00 ; |........| .byte $00 ; |........| .byte $73 ; |.XXX..XX| .byte $FB ; |XXXXX.XX| .byte $FB ; |XXXXX.XX| .byte $CB ; |XX..X.XX| .byte $CB ; |XX..X.XX| .byte $CB ; |XX..X.XX| .byte $CB ; |XX..X.XX| .byte $DB ; |XX.XX.XX| .byte $C3 ; |XX....XX| .byte $C3 ; |XX....XX| .byte $FB ; |XXXXX.XX| .byte $79 ; |.XXXX..X| .byte $00 ; |........| .byte $00 ; |........| GameOverBitmap_01 .byte $00 ; |........| .byte $00 ; |........| .byte $5A ; |.X.XX.X.| .byte $5A ; |.X.XX.X.| .byte $5A ; |.X.XX.X.| .byte $5A ; |.X.XX.X.| .byte $5A ; |.X.XX.X.| .byte $5A ; |.X.XX.X.| .byte $5A ; |.X.XX.X.| .byte $DA ; |XX.XX.X.| .byte $5A ; |.X.XX.X.| .byte $5A ; |.X.XX.X.| .byte $DF ; |XX.XXXXX| .byte $8F ; |X...XXXX| .byte $00 ; |........| .byte $00 ; |........| GameOverBitmap_02 .byte $00 ; |........| .byte $00 ; |........| .byte $BC ; |X.XXXX..| .byte $BC ; |X.XXXX..| .byte $B0 ; |X.XX....| .byte $B0 ; |X.XX....| .byte $B0 ; |X.XX....| .byte $B0 ; |X.XX....| .byte $B0 ; |X.XX....| .byte $BC ; |X.XXXX..| .byte $B0 ; |X.XX....| .byte $B0 ; |X.XX....| .byte $BC ; |X.XXXX..| .byte $3C ; |..XXXX..| .byte $00 ; |........| .byte $00 ; |........| GameOverBitmap_03 .byte $00 ; |........| .byte $00 ; |........| .byte $0E ; |....XXX.| .byte $1F ; |...XXXXX| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $1F ; |...XXXXX| .byte $0E ; |....XXX.| .byte $00 ; |........| .byte $00 ; |........| GameOverBitmap_04 .byte $00 ; |........| .byte $00 ; |........| .byte $33 ; |..XX..XX| .byte $33 ; |..XX..XX| .byte $7B ; |.XXXX.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $6B ; |.XX.X.XX| .byte $00 ; |........| .byte $00 ; |........| GameOverBitmap_05 .byte $00 ; |........| .byte $00 ; |........| .byte $D9 ; |XX.XX..X| .byte $D9 ; |XX.XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $1B ; |...XX.XX| .byte $1E ; |...XXXX.| .byte $DF ; |XX.XXXXX| .byte $19 ; |...XX..X| .byte $19 ; |...XX..X| .byte $DF ; |XX.XXXXX| .byte $DE ; |XX.XXXX.| .byte $00 ; |........| .byte $00 ; |........| SelectStartingScoreBitmap SelectStartingScoreBitmap_00 .byte $C9 ; |XX..X..X| .byte $49 ; |.X..X..X| .byte $49 ; |.X..X..X| .byte $C9 ; |XX..X..X| .byte $89 ; |X...X..X| .byte $89 ; |X...X..X| .byte $DD ; |XX.XXX.X| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| SelectStartingScoreBitmap_01 .byte $54 ; |.X.X.X..| .byte $54 ; |.X.X.X..| .byte $58 ; |.X.XX...| .byte $DC ; |XX.XXX..| .byte $54 ; |.X.X.X..| .byte $54 ; |.X.X.X..| .byte $DD ; |XX.XXX.X| .byte $00 ; |........| .byte $00 ; |........| .byte $39 ; |..XXX..X| .byte $09 ; |....X..X| .byte $09 ; |....X..X| .byte $39 ; |..XXX..X| .byte $21 ; |..X....X| .byte $21 ; |..X....X| .byte $39 ; |..XXX..X| SelectStartingScoreBitmap_02 .byte $94 ; |X..X.X..| .byte $94 ; |X..X.X..| .byte $94 ; |X..X.X..| .byte $95 ; |X..X.X.X| .byte $97 ; |X..X.XXX| .byte $96 ; |X..X.XX.| .byte $D4 ; |XX.X.X..| .byte $00 ; |........| .byte $00 ; |........| .byte $CE ; |XX..XXX.| .byte $08 ; |....X...| .byte $08 ; |....X...| .byte $C8 ; |XX..X...| .byte $08 ; |....X...| .byte $08 ; |....X...| .byte $C8 ; |XX..X...| SelectStartingScoreBitmap_03 .byte $B8 ; |X.XXX...| .byte $A8 ; |X.X.X...| .byte $A8 ; |X.X.X...| .byte $B8 ; |X.XXX...| .byte $A0 ; |X.X.....| .byte $A0 ; |X.X.....| .byte $B8 ; |X.XXX...| .byte $00 ; |........| .byte $00 ; |........| .byte $73 ; |.XXX..XX| .byte $42 ; |.X....X.| .byte $42 ; |.X....X.| .byte $72 ; |.XXX..X.| .byte $42 ; |.X....X.| .byte $42 ; |.X....X.| .byte $73 ; |.XXX..XX| SelectStartingScoreBitmap_04 .byte $DB ; |XX.XX.XX| .byte $52 ; |.X.X..X.| .byte $52 ; |.X.X..X.| .byte $D2 ; |XX.X..X.| .byte $92 ; |X..X..X.| .byte $92 ; |X..X..X.| .byte $DB ; |XX.XX.XX| .byte $00 ; |........| .byte $00 ; |........| .byte $88 ; |X...X...| .byte $08 ; |....X...| .byte $08 ; |....X...| .byte $08 ; |....X...| .byte $08 ; |....X...| .byte $08 ; |....X...| .byte $9C ; |X..XXX..| SelectStartingScoreBitmap_05 .byte $AB ; |X.X.X.XX| .byte $AA ; |X.X.X.X.| .byte $B2 ; |X.XX..X.| .byte $BB ; |X.XXX.XX| .byte $AA ; |X.X.X.X.| .byte $AA ; |X.X.X.X.| .byte $BB ; |X.XXX.XX| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| .byte $00 ; |........| FILL_BOUNDARY 256, 0 ObjectMovementRoutines MoveBeetle jmp MoveBeetleRoutine MoveBee jmp MoveBeeRoutine MoveEarwig tya ; move Earwig attributes to accumulator asl ; shift EARWIG_SPEED to carry lda #3 ; move 1/4 of the time bcc .checkMoveEarwigFrame ; branch if EARWIG_SLOW lda #1 ; move 1/2 of the time .checkMoveEarwigFrame and frameCount bne .doneMoveEarwig ; branch if not time to move Earwig lda creatureSpriteIds_R,x ; get Earwig sprite id value lsr ldy creatureHorizPositions_R,x ; get Earwig horizontal position bcc .moveEarwigRight dey ; decrement Earwig horizontal position dey bpl .setEarwigHorizontalPositionValue .earwigReachedEdge lda creatureAttributes_R,x ; get Earwig attribute values and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value clc adc kernelZoneAdjustment ; increment by kernel zone adjustment tay lda #POISON_MUSHROOM_ZONE sta kernelZoneAttributes_01 - 1,y lda #0 sta creatureAttributes_W,x jmp CheckToTurnOffRightSoundChannel .moveEarwigRight iny ; increment Earwig horizontal position iny cpy #XMAX - 3 bcs .earwigReachedEdge .setEarwigHorizontalPositionValue tya ; move horizontal position to accumulator sta creatureHorizPositions_W,x ; set Earwig horizontal position .doneMoveEarwig jmp MoveNextObject MoveInchworm jmp MoveInchwormRoutine MoveDragonfly txa ; move array index to accumulator and #7 ; 0 <= a <= 7 sta tmpDragonflyMovementFrame lda frameCount ; get current frame count and #7 ; 0 <= a <= 7 cmp tmpDragonflyMovementFrame bne SkipObjectMove ; branch if not time to move tya ; move Dragonfly attributes to accumulator lsr lsr lsr lsr lsr tay lda creatureHorizPositions_R,x ; get Dragonfly horizontal position value clc adc DragonflyHorizontalMovementValues,y sta creatureHorizPositions_W,x ; set Dragonfly horizontal position lda creatureAttributes_R,x ; get Dragonfly attribute value clc adc #<~DRAGONFLY_HORIZ_OFFSET_MASK;adjust horizontal and vertical position sta creatureAttributes_W,x and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value bne .checkToGenerateMushroomForDragonfly sta creatureAttributes_W,x bit waveState ; check current game wave values bpl .doneMoveDragonfly ; branch if NOT_SWARMING dec numberActiveSwarmingInsects ; reduce number of active swarming insects jmp MoveNextObject .doneMoveDragonfly jmp CheckToTurnOffRightSoundChannel .checkToGenerateMushroomForDragonfly jmp CheckToGenerateMushroom MoveMosquito tya ; move Mosquito attributes to accumulator bpl .slowMovingMosquito txa ; move array index to accumulator and #3 ; 0 <= a <= 3 sta tmpMosquitoMovementDelay lda #3 bne .checkToMoveMosquito ; unconditional branch .slowMovingMosquito txa ; move array index to accumulator and #7 ; 0 <= a <= 7 sta tmpMosquitoMovementDelay lda #7 .checkToMoveMosquito and frameCount cmp tmpMosquitoMovementDelay bne .doneMoveMosquito dey ; move Mosquito down tya ; move Mosquito attributes to accumulator sta creatureAttributes_W,x ; set new Mosquito attribute values and #KERNEL_ZONE_MASK ; keep Mosquito KERNEL_ZONE bne .moveMosquitoHorizontally sta creatureAttributes_W,x bit waveState ; check current game wave values bpl .checkToTurnOffRightSoundChannel;branch if NOT_SWARMING dec numberActiveSwarmingInsects ; reduce number of active swarming insects SkipObjectMove jmp MoveNextObject .checkToTurnOffRightSoundChannel jmp CheckToTurnOffRightSoundChannel .moveMosquitoHorizontally lda creatureSpriteIds_R,x ; get Mosquito sprite id value tay lsr lda creatureHorizPositions_R,x bcc .moveMosquitoLeft ; branch if Mosquito moving left adc #8 - 1 ; carry set cmp #XMAX - 3 bcc .setMosquitoHorizontalPosition .changeMosquitoHorizontalDirection tya ; move Mosquito sprite id to accumulator eor #1 sta creatureSpriteIds_W,x bpl .doneMoveMosquito ; unconditional branch .moveMosquitoLeft sbc #8 - 1 ; carry clear bmi .changeMosquitoHorizontalDirection .setMosquitoHorizontalPosition sta creatureHorizPositions_W,x .doneMoveMosquito jmp MoveNextObject MoveFloatingBonusPoints lda frameCount ; get current frame count and #7 ; 0 <= a <= 7 cmp #7 bne SkipObjectMove tya ; move object attributes to accumulator clc adc #1 << 5 sta creatureAttributes_W,x bcc SkipObjectMove bit waveState ; check current game wave values bpl .removeSpiderPointSprite ; branch if NOT_SWARMING lda #0 sta creatureAttributes_W,x ; clear object attribute value jmp MoveNextObject .removeSpiderPointSprite jmp RemoveSpiderPointSprite MoveSpider lda frameCount ; get current frame count and #7 ; 0 <= a <= 7 cmp tmpSpriteIdx IF COMPILE_REGION = PAL50 beq .checkToChangeSpiderDirections ELSE beq SkipObjectMove cmp SpiderMoveFrequencyValues,x beq SkipObjectMove ENDIF lsr lda playerScore ; get score thousands value bne .moveSpider ; branch if score greater than 9,999 IF COMPILE_REGION = PAL50 bcs .checkToChangeSpiderDirections;branch on odd frames ELSE bcs SkipObjectMove ; branch on odd frames ENDIF .moveSpider lda creatureHorizPositions_R,x ; get Spider horizontal position beq TurnOffSpiderSounds ; branch if Spider reached left edge cmp #XMAX - 7 beq TurnOffSpiderSounds ; branch if Spider reached right edge tya ; move Spider attributes to accumulator asl ; shift OBJECT_HORIZ_DIR to carry and #[SPIDER_HORIZ_MOVE_MASK << 1];keep SPIDER_HORIZ_MOVE value beq .checkToChangeSpiderDirections;branch if SPIDER_NO_HORIZ_MOVE lda #1 bcs .adjustSpiderHorizontalPosition;branch if Spider moving right lda #<-1 .adjustSpiderHorizontalPosition clc adc creatureHorizPositions_R,x sta creatureHorizPositions_W,x .checkToChangeSpiderDirections IF COMPILE_REGION = PAL50 lda creatureFrameCount cmp tmpSpriteIdx ELSE lda frameCount ; get current frame count and #7 ; 0 <= a <= 7 cmp ChangeSpiderDirectionFrequencyValues,x ENDIF bne .skipSpiderChangingDirections; branch if not time to change direction ldy #MAX_SPIDER_KERNEL_ZONE lda playerScore ; get score thousands value cmp #$03 bcc .setSpiderKernelZoneMaximum ; branch if less than 30,000 dey ; reduce Spider maxium height by 2 dey cmp #$10 bcc .setSpiderKernelZoneMaximum ; branch if score 30,000 <= a < 100,000 dey ; reduce Spider maxium height by 2 dey .setSpiderKernelZoneMaximum sty tmpSpiderKernelZoneMax ldy creatureAttributes_R,x ; get Spider attribute values tya ; move Spider attributes to accumulator and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value cmp #1 beq .setSpiderDirectionToUp ; branch if Spider in kernel zone 1 cmp tmpSpiderKernelZoneMax bcs .setSpiderDirectionToDown lda random and SpiderVerticalAdjustmentFrequencyValues,x bne .adjustSpiderVerticalPosition tya ; move Spider attributes to accumulator eor #SPIDER_VERT_DIR_MASK ; flip Spider SPIDER_VERT_DIR value .determineSpiderHorizontalMovement and #<~SPIDER_HORIZ_MOVE_MASK ; clear SPIDER_HORIZ_MOVE value sta tmpSpiderAttributes lda random + 1 and SpiderHorizontalAdjustmentFrequencyValues,x beq .setSpiderHorizontalMovementValue lda #SPIDER_HORIZ_MOVE .setSpiderHorizontalMovementValue ora tmpSpiderAttributes sta creatureAttributes_W,x tay ; move Spider attributes to y register .adjustSpiderVerticalPosition tya ; move Spider attributes to accumulator iny ; increment Spider kernel zone and #SPIDER_VERT_DIR_MASK beq .setSpiderVerticalPosition ; branch if SPIDER_DIR_UP dey dey .setSpiderVerticalPosition tya sta creatureAttributes_W,x jmp MoveNextObject .setSpiderDirectionToDown tya ; move Spider attributes to accumulator ora #SPIDER_DIR_DOWN bne .determineSpiderHorizontalMovement;unconditional branch .setSpiderDirectionToUp tya ; move Spider attributes to accumulator and #<~SPIDER_DIR_DOWN ; clear SPIDER_DIR_VALUE jmp .determineSpiderHorizontalMovement TurnOffSpiderSounds lda rightSoundChannelIndex ; get right sound channel index value cmp #<[SpiderAudioValues - RightSoundChannelValues] bcc .doneTurnOffSpiderSounds ; branch if less than Spider audio value cmp #<[MosquitoAudioValues - RightSoundChannelValues] bcs .doneTurnOffSpiderSounds ; branch if greater than Spoder audio value lda #0 sta rightSoundChannelIndex ; turn off Spider audio sounds .doneTurnOffSpiderSounds jmp RemoveSpiderPointSprite .skipSpiderChangingDirections cmp SpiderRemovingMushroomFrequencyValues,x beq CheckSpiderForRemovingMushroom .doneMoveSpider jmp MoveNextObject CheckSpiderForRemovingMushroom lda creatureAttributes_R,x ; get Spider attribute values and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value clc adc kernelZoneAdjustment ; increment by kernel zone adjustment sta tmpSpiderKernelZone cmp #2 bcc .doneMoveSpider ; branch if lower than zone 2 lda creatureHorizPositions_R,x ; get Spider horizontal position lsr lsr ; divide value by 4 tay ; move horizontal position to y register eor tmpSpiderKernelZone lsr ; shift D0 to carry bcc .determineMushroomBitIndex iny ; increment horizontal position .determineMushroomBitIndex lda tmpSpiderKernelZone ; get Spider kernel zone cpy #16 bcc .setMushroomArrayBitIndex adc #<[rightMushroomArray_W - leftMushroomArray_W] - 1 .setMushroomArrayBitIndex tax lsr ; shift D0 to carry tya ; get Spider adjusted horizontal position and #<~1 bcs .setMushroomMaskingBitIndex adc #<[BANK2_EvenMushroomMaskingBits - BANK2_MushroomMaskingBits - 1] .setMushroomMaskingBitIndex tay iny cmp #63 bmi .spiderRemovingMushroom ldy #63 .spiderRemovingMushroom lda BANK2_MushroomMaskingBits,y ; get Mushroom masking bit value eor #$FF ; flip the bits tay and mushroomArray_R - 2,x ; remove Mushroom from array sta mushroomArray_W - 2,x tya and leftFlowerArray_R - 2,x ; remove Flower from array sta leftFlowerArray_W - 2,x ldx tmpSpriteIdx jmp MoveNextObject RemoveSpiderPointSprite lda gameWaveValues ; get current game wave values beq .setCreatureSpriteIdToSpider ; branch if first game wave lda #ID_BLANK cpx #3 bcc .setCreatureSpriteId .setCreatureSpriteIdToSpider lda #ID_SPIDER .setCreatureSpriteId sta creatureSpriteIds_W,x lda #0 sta creatureAttributes_W,x lda random and #$0F ; 0 <= a <= 15 ora #1 ; 1 <= a <= 15 sta creatureHorizPositions_W,x jmp MoveNextObject MoveInchwormRoutine tya ; move Inchworm attributes to accumulator asl ; shift INCHWORM_SPEED to carry lda #3 ; move 1/4 of the time bcc .checkMoveInchwormFrame lda #1 ; move 1/2 of the time .checkMoveInchwormFrame IF COMPILE_REGION = PAL50 and creatureFrameCount ELSE and frameCount ENDIF bne .doneMoveInchworm tya ; move Inchworm attributes to accumulator ldy creatureHorizPositions_R,x ; get Inchworm horizontal position and #INCHWORM_HORIZ_DIR_MASK ; keep INCHWORM_HORIZ_DIR value bne .moveInchwormLeft iny iny cpy #XMAX - 3 bcc .setInchwormHorizontalPosition .inchwormReachedEdge lda #0 sta creatureAttributes_W,x lda gameState + 1 ; get high game state value ora #INIT_INCHWORM_SPAWN_TIMER sta gameState + 1 ; reinitialize Inchworm spawn timer jmp CheckToTurnOffRightSoundChannel .moveInchwormLeft dey dey bmi .inchwormReachedEdge .setInchwormHorizontalPosition tya sta creatureHorizPositions_W,x .doneMoveInchworm jmp MoveNextObject MoveBeetleRoutine lda #7 IF COMPILE_REGION = PAL50 and creatureFrameCount ; 0 <= a <= 7 ELSE and frameCount ; 0 <= a <= 7 ENDIF cmp tmpSpriteIdx beq .moveBeetle ; branch if same value as index cmp BeetleMoveFrequencyValues,x beq .moveBeetle ; branch if time to move Beetle jmp MoveNextObject .moveBeetle tya ; move Beetle attributes to accumulator bpl .moveBeetleVertically cmp #BEETLE_HORIZ_MOVE | 1 beq .moveLowestZoneBeetleHorizontally lda creatureSpriteIds_R,x ; get Beetle sprite id value lsr lda creatureHorizPositions_R,x ; get Beetle horizontal position bcs .moveBeetleLeft ; branch if Beetle moving left adc #2 cmp #XMAX - 2 jmp .setBeetleHorizontalPosition .moveBeetleLeft sbc #2 cmp #XMIN - 16 .setBeetleHorizontalPosition sta creatureHorizPositions_W,x bcc CheckToAddFlowerFromBeetle lda #0 sta creatureAttributes_W,x jmp CheckToTurnOffRightSoundChannel .moveLowestZoneBeetleHorizontally lda creatureSpriteIds_R,x ; get Beetle sprite id value lsr lda creatureHorizPositions_R,x ; get Beetle horizontal position bcs .moveLowestZoneBeetleLeft ; branch if Beetle moving left adc #2 cmp #111 sta creatureHorizPositions_W,x bcs .setBeetleToMoveUp ; branch if Bettle greater than pixel 190 cmp #64 bcs .determineToSetBeetleToTravelUp;branch if Beetle greater than pixel 143 bcc .doneMoveBeetle ; unconditional branch .moveLowestZoneBeetleLeft sbc #2 cmp #9 sta creatureHorizPositions_W,x bcc .setBeetleToMoveUp ; branch if Beetle less than pixel 88 cmp #60 bcs .doneMoveBeetle ; branch if Beetle greater than pixel 139 .determineToSetBeetleToTravelUp and #2 bne .doneMoveBeetle lda random cmp #32 bcs .doneMoveBeetle .setBeetleToMoveUp lda #BEETLE_NO_HORIZ_MOVE | BEETLE_DIR_UP | 1 sta creatureAttributes_W,x .doneMoveBeetle jmp MoveNextObject .moveBeetleVertically IF COMPILE_REGION = PAL50 lda creatureFrameCount lsr ; shift D0 to carry bcc .doneMoveBeetle ; branch on even frame count lda creatureFrameCount + 1 lsr ; shift D0 to carry bcs .doneMoveBeetle ELSE lda frameCount ; get current frame count lsr ; shift D0 to carry bcc .doneMoveBeetle ; branch on even frame and #4 ; a = 0 || a = 4 bne .doneMoveBeetle ENDIF tya ; move Beetle attributes to accumulator and #BEETLE_VERT_DIR_MASK ; keep BEETLE_VERT_DIR value bne .moveBeetleUp tya ; move Beetle attributes to accumulator sec sbc #1 ; decrement kernel zone (i.e. move Beetle down) cmp #1 bne .setBeetleAttributeValues ; branch if Beetle not in lowest zone lda #BEETLE_HORIZ_MOVE | 1 .setBeetleAttributeValues sta creatureAttributes_W,x bmi .doneMoveBeetle bne CheckToAddFlowerFromBeetle .moveBeetleUp tya ; move Beetle attributes to accumulator clc adc #1 ; increment kernel zone (i.e. move Beetle up) cmp #BEETLE_NO_HORIZ_MOVE | BEETLE_DIR_UP | 8 bcc .setMovingBeetleAttributeValue cmp #BEETLE_NO_HORIZ_MOVE | BEETLE_DIR_UP | 11 bcs .setBeetleToMoveHorizontally ; branch if Beetle reached highest zone ldy #64 cpy random + 1 bcc .setMovingBeetleAttributeValue .setBeetleToMoveHorizontally and #<~BEETLE_VERT_DIR_MASK ; set to clear BEETLE_VERT_DIR value ora #BEETLE_HORIZ_MOVE .setMovingBeetleAttributeValue sta creatureAttributes_W,x CheckToAddFlowerFromBeetle SUBROUTINE lda creatureAttributes_R,x ; get Beetle attribute values and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value clc adc kernelZoneAdjustment ; increment by kernel zone adjustment sta tmpBeetleKernelZone lda creatureHorizPositions_R,x ; get Beetle horizontal position lsr ; divide by 4 lsr tay eor tmpBeetleKernelZone lsr ; shift D0 to carry bcc .determineMushroomBitIndex iny .determineMushroomBitIndex lda tmpBeetleKernelZone ; get Bettle kernel zone cpy #16 bcc .setMushroomArrayBitIndex adc #<[rightMushroomArray_W - leftMushroomArray_W] - 1 .setMushroomArrayBitIndex tax lsr tya and #<~1 bcs .setMushroomMaskingBitIndex adc #<[BANK2_EvenMushroomMaskingBits - BANK2_MushroomMaskingBits] - 1 .setMushroomMaskingBitIndex tay iny cmp #63 bmi .spawnMushroomToFlower ldy #63 .spawnMushroomToFlower lda mushroomArray_R - 2,x ; get Mushroom array value and BANK2_MushroomMaskingBits,y ; keep Mushroom bit value ora leftFlowerArray_R - 2,x sta leftFlowerArray_W - 2,x ldx tmpSpriteIdx jmp MoveNextObject DragonflyHorizontalMovementValues .byte 0, 5, 10, 5, 0, -5, -10, -5 SpiderRemovingMushroomFrequencyValues .byte 2, 2, 0, 4, 6 ChangeSpiderDirectionFrequencyValues .byte 6, 6, 4, 0, 2 BeetleMoveFrequencyValues .byte 1, 2, 3, 0, 1 SpiderMoveFrequencyValues .byte 3, 4, 5, 6, 7 SpiderHorizontalAdjustmentFrequencyValues .byte 1, 2, 4, 8, 16 SpiderVerticalAdjustmentFrequencyValues .byte ~81, ~196, ~7, ~138, ~97 MoveBeeRoutine SUBROUTINE tya ; move Bee attributes to accumulator bpl .slowMovingBee ; branch if BEE_STATE_NORMAL txa and #1 sta tmpBeeMovementDelay lda #1 bne .checkToMoveBee ; unconditional branch .slowMovingBee txa and #3 sta tmpBeeMovementDelay lda #3 .checkToMoveBee and frameCount cmp tmpBeeMovementDelay bne .doneCheckToGenerateMushroom dey ; decrement Bee kernel zone tya ; move Bee attributes to accumulator sta creatureAttributes_W,x ; set Bee new kernel zone and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value bne CheckToGenerateMushroom ; branch if Bee still active sta creatureAttributes_W,x ; clear Bee attribute values (i.e. a = 0) bit waveState ; check current game wave values bpl .doneMoveBeeRoutine ; branch if NOT_SWARMING dec numberActiveSwarmingInsects ; reduce number of active swarming insects jmp MoveNextObject .doneMoveBeeRoutine jmp CheckToTurnOffRightSoundChannel CheckToGenerateMushroom cmp #2 bcc .doneCheckToGenerateMushroom ; branch if below kernel zone 2 ldy #224 bit waveState ; check current game wave values bpl .determineToGenerateMushroom ; branch if NOT_SWARMING ldy #32 .determineToGenerateMushroom cpy random + 1 bcc .doneCheckToGenerateMushroom clc adc kernelZoneAdjustment ; increment by kernel zone adjustment sta tmpInsectKernelZone lda creatureHorizPositions_R,x ; get creature horizontal position lsr ; divide by 4 lsr tay lda tmpInsectKernelZone cpy #16 bcc .setMushroomArrayBitIndex adc #<[rightMushroomArray_W - leftMushroomArray_W] - 1 .setMushroomArrayBitIndex tax lsr tya bcs .setMushroomMaskingBitIndex adc #<[BANK2_EvenMushroomMaskingBits - BANK2_MushroomMaskingBits] .setMushroomMaskingBitIndex tay lda mushroomArray_R - 2,x ; get Mushroom array value ora BANK2_MushroomMaskingBits,y sta mushroomArray_W - 2,x .doneCheckToGenerateMushroom ldx tmpSpriteIdx jmp MoveNextObject CheckToTurnOffRightSoundChannel ldy creatureSpriteIds_R,x ; get creature sprite id value cpy #ID_SHOOTER_DEATH bcs .doneCheckToTurnOffRightSoundChannel lda rightSoundChannelIndex ; get right sound channel index value cmp BANK2_RightAudioValueLowerBounds,y bcc .doneCheckToTurnOffRightSoundChannel;branch if current sound has priority cmp BANK2_RightAudioValueUpperBounds,y bcs .doneCheckToTurnOffRightSoundChannel lda #0 sta rightSoundChannelIndex .doneCheckToTurnOffRightSoundChannel jmp MoveNextObject ObjectMoveRoutineTable .byte BANK0_SoundRoutines sta soundRoutineVector + 1 SetInitInchwormValues lda #0 sta inchwormWaveState sta gardenShiftValues ; clear garden shift value lda gameState + 1 ; get high game state value ora #INIT_INCHWORM_SPAWN_TIMER sta gameState + 1 ; reinitialize Inchworm spawn timer ldx #9 stx objectListEndValue lda #<[kernelZoneConflictArray + 5] sta conflictArrayStartingIndex ; set value to end of array lda numberOfMillipedeSegments ; get number of Millipede segments bpl .decrementGameWaveValue dec gardenShiftValues ; set to shift garden down jmp .setShooterInitialPositionValues .decrementGameWaveValue dec gameWaveValues .setShooterInitialPositionValues lda #SHOOTER_START_Y sta shooterVertPos lda #SHOOTER_START_X sta shooterHorizPos lda #0 sta leftSoundChannelIndex ldx #MAX_DDT_BOMBS - 1 .setInitialCreatureValues sta creatureAttributes_W,x dex bpl .setInitialCreatureValues sta shotVertPos ; turn off Shot lda gameState ; get current game state and #<~SPAWN_EXTRA_SPIDER_MASK ; clear SPAWN_EXTRA_SPIDER value sta gameState ResetGameWaveValues lda #0 sta beetleSpawnTimer lda gameState ; get current game state and #<~SPAWN_HEAD_MASK ; clear SPAWN_HEAD value sta gameState and #GAME_SELECTION_MASK beq .setNotSelectingGameValues ; branch if not GS_SELECTING_GAME lda #<-1 sta numberOfMillipedeSegments inc gameWaveValues jmp SetShooterAndShotKernelValues .setNotSelectingGameValues ldx #MAX_MILLIPEDE_SEGMENTS - 1 stx numberOfMillipedeSegments lda gameWaveValues ; get current game wave values clc adc #1 ; increment wave by 1 and #GAME_WAVE_MASK ; keep GAME_WAVE value sta gameWaveValues beq BuildMillipedeForGameWave ; branch if game wave rolled over cmp #4 beq SetGameWaveObjectSpawningValues lsr ; shift D0 to carry bcs SetGameWaveObjectSpawningValues;branch on an odd game wave .alternateSwarmingValue lda waveState ; get current game wave values eor #SWARMING_MASK ; flip SWARMING value sta waveState bpl SetGameWaveObjectSpawningValues;branch if NOT_SWARMING lda gameState ; get current game state bmi .reduceGameWaveValues ; branch if GS_GAME_OVER and #SPAWN_EXTRA_SPIDER_MASK ; keep SPAWN_EXTRA_SPIDER value beq .alternateSwarmingValue ; branch if extra Spider not spawned .reduceGameWaveValues dec gameWaveValues ldx #8 lda #0 .clearCreatureAttributesForStartingSwarm sta creatureAttributes_W + 5,x dex bpl .clearCreatureAttributesForStartingSwarm stx numberOfMillipedeSegments lda playerScore ; get score thousands value ldy #MAX_SWARMING_INSECTS_00 cmp #$04 bcc .setWaveMaximumSwarmingInsects;branch if score less than 40,000 ldy #MAX_SWARMING_INSECTS_01 cmp #$10 bcc .setWaveMaximumSwarmingInsects;branch if score less than 100,000 ldy #MAX_SWARMING_INSECTS_02 .setWaveMaximumSwarmingInsects sty waveNumberSwarmingInsects ldy #0 ldx #2 .countActiveSwarmingInsects lda creatureAttributes_R,x ; get creature attribute values beq .countNextActiveSwarmingInsects;branch if object not present lda creatureSpriteIds_R,x ; get creature sprite id value beq .countNextActiveSwarmingInsects;branch if ID_BLANK cmp #ID_EARWIG bcc .incrementActiveSwarmingInsects;branch if ID_BEE cmp #ID_MOSQUITO bcc .countNextActiveSwarmingInsects;branch if ID_EARWIG or ID_SPIDER cmp #ID_INCHWORM bcs .countNextActiveSwarmingInsects;branch if not ID_MOSQUITO or ID_DRAGONFLY .incrementActiveSwarmingInsects iny .countNextActiveSwarmingInsects dex bpl .countActiveSwarmingInsects sty numberActiveSwarmingInsects lda #5 sta tmpSwarmingInsectSpawningTimer lda #<-1 sta insectSwarmShootTally lda #18 sta objectListEndValue jmp SetShooterAndShotKernelValues SetGameWaveObjectSpawningValues lda gameWaveValues ; get current game wave values sec sbc #1 and #3 ; 0 <= a <= 3 tax lda WaveObjectSpawnValues,x ora objectSpawningValues sta objectSpawningValues BuildMillipedeForGameWave lda gameWaveValues ; get current game wave values ldy #FAST_MILLIPEDE_VALUE lsr ; shift D0 to carry bcc .setMillipedeSpeed ; branch on an even wave...MILLIPEDE_FAST ldx playerScore ; get score thousands value cpx #$04 bcs .setMillipedeSpeed ; MILLIPEDE_FAST if score greater than 39,999 ldy #SLOW_MILLIPEDE_VALUE .setMillipedeSpeed sty tmpMillipedeSpeed lda #MAX_LEVEL sec sbc gameWaveValues ; subtract current game wave and #GAME_WAVE_MASK ; keep GAME_WAVE value clc adc #3 ; increment game wave difference by 3 lsr ; divide value by 2 (i.e. 1 <= a <= 9) sta tmpMillipedeChainEnd lda #MILLIPEDE_START_X ldy #MILLIPEDE_BODY_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_LEFT | 19 ldx #0 .buildMillipedeSegment cpx tmpMillipedeChainEnd bmi .buildMillipedeBodySegment ; branch if less than Millipede chain end lda InitMillipedeHeadHorizPos,x sta millipedeHorizPosition,x ; set Millipede head horizontal position lda InitMillipedeHeadState,x sta millipedeSegmentState,x ; set Millipede head state lda #MILLIPEDE_FAST sta millipedeAttributes_W,x ; set Millipede head to MILLIPEDE_FAST jmp .buildNextMillipedePart InitMillipedeHeadHorizPos .byte 64, 47, 77, 14, 108, 31, 93, 2, 124 InitMillipedeHeadState .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_LEFT | 19 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_RIGHT | 18 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_LEFT | 18 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_RIGHT | 18 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_LEFT | 18 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_RIGHT | 18 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_LEFT | 19 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_RIGHT | 19 .byte MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_LEFT | 19 WaveObjectSpawnValues .byte 0 .byte OBJECT_SPAWNING_EARWIG .byte $40 .byte $10 .buildMillipedeBodySegment clc adc #W_MILLIPEDE_HEAD ; increment by W_MILLIPEDE_HEAD sta millipedeHorizPosition,x ; set position of Millipede body part sty millipedeSegmentState,x ; set initial state of Millipede body part bit tmpMillipedeSpeed bmi .buildFastMovingMillipede lda millipedeAttributes_R,x ; get Millipede attribute values and #<~[MILLIPEDE_SPEED_MASK | MILLIPEDE_POISONED_MASK] sta millipedeAttributes_W,x jmp .buildNextMillipedePart .buildFastMovingMillipede lda #MILLIPEDE_FAST sta millipedeAttributes_W,x .buildNextMillipedePart inx lda millipedeHorizPosition - 1,x ; get Millipede segment horizontal position cpx #MAX_MILLIPEDE_SEGMENTS bne .buildMillipedeSegment lda #MILLIPEDE_HEAD_SEGMENT | MILLIPEDE_DIR_DOWN | MILLIPEDE_DIR_LEFT | 19 sta millipedeSegmentState lda shotVertPos ; get Shot vertical position beq .setShotKernelValues ; branch if Shot not active asl ; multiply by 2 adc shotVertPos ; multiply by 3 (i.e. [x * 2] + x) sec sbc #2 .setShotKernelValues sta playerShotEnableIndex lda shooterVertPos sec sbc playerShotEnableIndex sta kernelShooterState lda playerShotEnableIndex bne .doneCheckToLaunchPlayerShot dec playerShotEnableIndex inc kernelShooterState .doneCheckToLaunchPlayerShot lda #MAX_KERNEL_SECTIONS + 1 sta millipedeBodyKernelZone jmp SwitchBanksToSetupGameDisplayKernel NewFrame SUBROUTINE .waitTime lda INTIM bmi .waitTime lda #START_VERT_SYNC | 1 sta WSYNC ; wait for next scan line sta VSYNC ; start vertical sync (i.e. D1 = 1) lda random + 1 asl eor random + 1 asl asl rol random rol random + 1 rol random lda playerScore + 1 ; get score hundreds value cmp #$50 ; set carry if score greater than 4,999 ror ; rotate carry to D7 sta tmpExtraLifeState bit gameState ; check current game state bpl .incrementScore ; branch if GS_GAME_ACTIVE lda #> 1;keep MILLIPEDE_HORIZ_DIR value bne .determineMushroomMaskingBitIndex;branch if MILLIPEDE_DIR_LEFT iny iny .determineMushroomMaskingBitIndex dey bmi .moveMillipedeSegmentHorizontally tya bcs .setMillipedeMushroomMaskingBitIndex;branch if Millipede in odd zone adc #<[BANK3_EvenMushroomMaskingBits - BANK3_MushroomMaskingBits] .setMillipedeMushroomMaskingBitIndex sta tmpMushroomMaskingBitIndex tay lda millipedeAttributes_R,x ; get Millipede attribute values and #MILLIPEDE_POISONED_MASK beq .checkNormalMillipedeCollisionWithMushroom;branch if MILLIPEDE_NORMAL lda BANK3_MushroomMaskingBits,y bne CheckToMoveMillipedeSegmentVertically beq .moveMillipedeSegmentHorizontally;unconditional branch .checkNormalMillipedeCollisionWithMushroom lda tmpMillipedeState ; get Millipede segment state and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value clc adc kernelZoneAdjustment ; increment by kernel zone adjustment sta tmpMillipedeSegmentZone beq .moveMillipedeSegmentHorizontally lda tmpMushroomMaskingBitIndex ; get Mushroom masking index and #$10 beq .checkMushroomPresent ; branch for left Mushroom array lda #MAX_KERNEL_SECTIONS - 1 .checkMushroomPresent adc tmpMillipedeSegmentZone tay lda mushroomArray_R - 1,y ; get Mushroom array value ldy tmpMushroomMaskingBitIndex and BANK3_MushroomMaskingBits,y ; mask Mushroom bit value beq .moveMillipedeSegmentHorizontally;branch if Mushroom not present ldy tmpMillipedeSegmentZone lda kernelZoneAttributes_01,y bpl CheckToMoveMillipedeSegmentVertically;branch if NORMAL_MUSHROOM_ZONE lda millipedeAttributes_R,x ora #MILLIPEDE_POISONED sta millipedeAttributes_W,x CheckToMoveMillipedeSegmentVertically lda tmpMillipedeState ; get Millipede segment state tay and #KERNEL_ZONE_MASK ; keep KERNEL_ZONE value beq .millipedeReachedBottomZone ; branch if reached bottom zone cmp #5 bne .moveMillipedeSegmentVertically bit tmpMillipedeState ; check Millipede segment state bvc .moveMillipedeSegmentDown ; branch if MILLIPEDE_DIR_DOWN bvs .changeMillipedeVerticalDirection;unconditional branch .millipedeReachedBottomZone lda millipedeAttributes_R,x and #MILLIPEDE_POISONED_MASK ; keep MILLIPEDE_POISONED value beq .setMillipedeStateForReachingBottom;branch if MILLIPEDE_NORMAL lda millipedeAttributes_R,x and #<~MILLIPEDE_POISONED_MASK ; clear MILLIPEDE_POISONED value sta millipedeAttributes_W,x jmp .changeMillipedeVerticalDirection .setMillipedeStateForReachingBottom lda gameState ; get current game state ora #GS_SPAWN_MILLIPEDE_HEAD sta gameState lda tmpMillipedeSegmentIndex beq .changeMillipedeVerticalDirection tay lda millipedeSegmentState,y ; get Millipede segment state eor #MILLIPEDE_SEGMENT_MASK | MILLIPEDE_HORIZ_DIR_MASK sta millipedeSegmentState,y .changeMillipedeVerticalDirection lda tmpMillipedeState eor #MILLIPEDE_VERT_DIR_MASK tay .moveMillipedeSegmentVertically tya ; move Millipede state to accumulator and #MILLIPEDE_VERT_DIR_MASK ; keep MILLIPEDE_VERT_DIR value beq .moveMillipedeSegmentDown ; branch if MILLIPEDE_DIR_DOWN iny ; increment Millipede KERNEL_ZONE value iny .moveMillipedeSegmentDown dey ; decrement Millipede KERNEL_ZONE value tya ; move Millipede state to accumulator eor #MILLIPEDE_HORIZ_DIR_MASK ; flip MILLIPEDE_HORIZ_DIR value sta millipedeSegmentState,x jmp .checkIfDoneMovingMillipedeChain IF ORIGINAL_ROM .byte $4C,$E4,$FF ;never executed ENDIF BANK3_RightAudioValueLowerBounds .byte