Monsters disassembly ==================== Published by Acornsoft for the BBC Micro in 1982, Monsters is a conversion of Universal Entertainment Corporation's 1980 arcade game Space Panic. Arguably more playable than the original, it requires the player to dig holes in platforms to trap monsters, then fill them in before the monsters mutate. The following disassembly was created by reverse engineering a binary image without access to any source code. It is nevertheless reasonably complete, allowing the technical approaches used to be understood. The author of this disassembly imposes no additional copyright restrictions beyond those already present on the game itself. It is provided for educational purposes only, and it is hoped that the original authors will accept it in the good faith it was intended - as a tribute to their skills. Technical notes =============== The sixteen colours of a standard MODE 2 are redefined to use particular bits to specify the status of pixels. The top bit (8) of a ladder remains set even when player or monster sprites (colours 1, 2, 3 and 4) are EORed over it. The bottom bit (1) of a platform (colours 4 and 6) is set when a hole is dug, but the resulting colours (5 and 7) are displayed as black. logical physical purpose 0 0 (black) background 1 1 (red) player; red, white and green monsters 2 7 (white) player; red, white and green monsters; points 3 3 (yellow) player; red and white monsters 4 2 (green) undug platform bricks; green monsters 5 0 (black) dug platform bricks 6 0 (black) undug platform mortar 7 0 (black) dug platform mortar 8 5 (magenta) ladder 9 1 (red) player, red, white and green monsters on ladder 10 7 (white) player, red, white and green monsters on ladder 11 3 (yellow) player, red, and white monsters on ladder 12 2 (green) green monsters on ladder 13 6 (cyan) score and oxygen background 14 4 (blue) 15 4 (blue) player lives For many variables, the player is considered as a zeroth monster. Cycling through the eight slots, a fixed number of monsters are updated every frame. This is two for the first six stages, but increases to three from stage seven. The game thus becomes 50% faster. The player and monsters each have a state and flags: 0 PLAYER_RUNNING the player is on a platform 1 PLAYER_CLIMBING the player is on a ladder 2 PLAYER_DIGGING the player is digging or filling a hole 3 PLAYER_FALLING the player is falling through a hole 4 PLAYER_FILLING_MONSTER the player by a hole containing a monster 5 PLAYER_FILLED_MONSTER the player is no longer by such a hole 20 PLAYER_PAUSED the player is watching monsters fall 0 MONSTER_RUNNING the monster is on a platform 1 MONSTER_CLIMBING the monster is on a ladder 2 MONSTER_TRAPPED the monster is in a hole, partial or full 3 MONSTER_FALLING the monster is falling through a hole 4 MONSTER_POINTS the monster has become a display of points 5 MONSTER_REMOVED the monster has been removed from the screen 8 MONSTER_TAIL the monster is the last to fall through a hole 10 MONSTER_LEAD the monster is the first to fall through a hole 20 MONSTER_PAUSED the monster isn't involved in the current fall 40 MONSTER_KILLED the monster has been killed 80 MONSTER_FULLY_TRAPPED the monster has been in a full hole Game-play notes =============== The monsters present on a given stage are as follows: Stage 1 R R R 2000 oxygen, 20 per tick Stage 2 R R R R R Stage 3 R R R R R R R Stage 4 R G R 3000 oxygen, 30 per tick Stage 5 R G R R R Stage 6 R G R R R R R Stage 7 R G W 4000 oxygen, 40 per tick. Game is 50% faster. Stage 8 R G W R R Stage 9 R G W R R R R Stage 10 reverts back to stage 7 Each stage has the same time limit. Later ones score more for remaining oxygen. A hole requires three digs to complete. If a monster or the player falls on a one dig hole, it is treated as a platform. If a monster of the player falls on a two dig hole, it is treated as a complete hole. This allows a column of two dig holes to score highly without any danger of an unfilled monster mutating. The points awarded for killing a monster are as follows: crushed 1 hole 2 holes 3 holes 4 holes 5 holes Red 100 100 200 300 400 500 Green 300 300* 300 500 700 1500 White 700 700* 700* 700 1000 2000 (* only if the monster falls on top of another monster) The maximum score achievable from a single fill is therefore 5800 points. An extra life is awarded at 3000 points. The likelihood of a monster homing in on the player is as follows: number of monsters on screen 1 2 3 4 5 6 7 Red 1/2 1/3 1/4 1/5 1/6 1/7 1/8 Green 1/1 1/1 1/2 1/2 1/3 1/3 1/4 White 1/1 1/1 1/1 1/1 1/1 1/1 1/2 Interesting Pokes ================= &122b = &b0, &2108 = &60 player is invulnerable &1a61 = &06, &1ba4 = &ad, &1bab = &7f infinite lives &1a02 = &60 infinite oxygen The following pokes need a new game to be started to take effect: &1eff = x, &1923 = &ee set game speed to x (default = &02; &03 = 50% faster, as per stage 7) &1b2b = &60, &278e = &00, &27d1 = &06 show logical colours &1ee2 = &02 start with five green monsters &1ee2 = &03 start with seven white monsters Disassembly =========== $.Monster initialises the following envelopes and character definitions: ; OS envelope storage area &08c0 0a ff ff 00 02 02 01 78 00 00 88 78 78 00 00 00 ; envelope 1 &08d0 02 00 00 00 01 01 01 78 88 88 88 78 00 00 00 00 ; envelope 2 &08e0 02 ff ff ff ff ff ff 78 00 00 88 78 78 00 00 00 ; envelope 3 &08f0 03 00 00 00 01 01 01 78 fb fb f6 78 5a 00 00 00 ; envelope 4 ; Character definitions &0c00 3c 3c 66 66 60 60 6e 6e ; G (top) &0c08 66 66 66 66 3c 3c 00 00 ; G (bottom) &0c10 00 00 00 00 3c 3c 06 06 ; a (top) &0c18 3e 3e 66 66 3e 3e 00 00 ; a (bottom) &0c20 00 00 00 00 36 36 7f 7f ; m (top) &0c28 6b 6b 6b 6b 63 63 00 00 ; m (bottom) &0c30 00 00 00 00 3c 3c 66 66 ; e (top) &0c38 7e 7e 60 60 3c 3c 00 00 ; e (bottom) &0c40 3c 3c 66 66 66 66 66 66 ; O (top) &0c48 66 66 66 66 3c 3c 00 00 ; O (bottom) &0c50 00 00 00 00 66 66 66 66 ; v (top) &0c58 66 66 3c 3c 18 18 00 00 ; v (bottom) &0c60 00 00 00 00 6c 6c 76 76 ; r (top) &0c68 60 60 60 60 60 60 00 00 ; r (bottom) then chains $.MON2, which displays instructions, loads and relocates $.Monst. ; $.Monst ; 001900 001900 002600 # Relocated from &1900-&3eff to &0e00-&33ff ; unused &0e00 0d ff ; entry_point &0e02 4c f5 1d JMP &1df5 ; initialise_game ; check_keys &0e05 a0 05 LDY #&05 &0e07 8c b1 22 STY &22b1 ; key_to_check ; check_keys_loop &0e0a a9 81 LDA #&81 ; Scan for a particular key &0e0c be b2 22 LDX &22b2,Y ; keys_to_check &0e0f a0 ff LDY #&ff &0e11 20 f4 ff JSR &fff4 ; OSBYTE &0e14 8a TXA &0e15 ac b1 22 LDY &22b1 ; key_to_check &0e18 99 06 00 STA &0006,Y ; keys_pressed &0e1b ce b1 22 DEC &22b1 ; key_to_check &0e1e 88 DEY &0e1f 10 e9 BPL &0e0a ; check_keys_loop &0e21 60 RTS ; handle_player_running # The player is on a platform &0e22 a5 07 LDA &07 ; right_pressed &0e24 38 SEC &0e25 e5 06 SBC &06 ; left_pressed &0e27 d0 05 BNE &0e2e ; player_pressed_left_or_right # If the player didn't press left or right, or pressed &0e29 85 1c STA &1c ; player_direction # both, then their direction is zero &0e2b 4c df 0e JMP &0edf ; player_didn't_move_horizontally ; player_pressed_left_or_right &0e2e c9 ff CMP #&ff &0e30 f0 17 BEQ &0e49 ; player_pressed_right ; player_pressed_left # If the player pressed left, but not right, &0e32 a9 02 LDA #&02 &0e34 c5 0c CMP &0c ; player_x &0e36 b0 27 BCS &0e5f ; skip_setting_player_direction # Is the player at the left edge of the screen? &0e38 a5 1c LDA &1c ; player_direction &0e3a 30 23 BMI &0e5f ; skip_setting_player_direction # If not, is the player already facing left? &0e3c a9 fc LDA #&fc ; LEFT &0e3e 85 1c STA &1c ; player_direction &0e40 a5 24 LDA &24 ; player_sprite &0e42 29 01 AND #&01 # If not, set player sprite facing left &0e44 85 24 STA &24 ; player_sprite &0e46 4c 5f 0e JMP &0e5f ; skip_setting_player_direction ; player_pressed_right # If the player pressed right, but not left, &0e49 a5 0c LDA &0c ; player_x &0e4b c9 96 CMP #&96 # Is the player at the right edge of the screen? &0e4d b0 10 BCS &0e5f ; skip_setting_player_direction &0e4f a5 1c LDA &1c ; player_direction &0e51 30 02 BMI &0e55 ; set_player_direction &0e53 d0 0a BNE &0e5f ; skip_setting_player_direction # If not, is the player already facing right? ; set_player_direction &0e55 a9 04 LDA #&04 ; RIGHT &0e57 85 1c STA &1c ; player_direction &0e59 a5 24 LDA &24 ; player_sprite &0e5b 09 02 ORA #&02 # If not, set player sprite facing right &0e5d 85 24 STA &24 ; player_sprite ; skip_setting_player_direction &0e5f a5 1c LDA &1c ; player_direction &0e61 d0 03 BNE &0e66 ; player_is_moving_horizontally &0e63 4c df 0e JMP &0edf ; player_didn't_move_horizontally ; player_is_moving_horizontally &0e66 a5 0c LDA &0c ; player_x &0e68 38 SEC &0e69 e9 01 SBC #&01 # Consider a pixel either one pixel to the left &0e6b a4 1c LDY &1c ; player_direction &0e6d 30 03 BMI &0e72 ; player_facing_left &0e6f 18 CLC &0e70 69 09 ADC #&09 # or one pixel to the right of the player ; player_facing_left &0e72 aa TAX &0e73 a5 14 LDA &14 ; player_y &0e75 38 SEC &0e76 e9 10 SBC #&10 # and one pixel below their feet &0e78 a8 TAY &0e79 20 6d 29 JSR &296d ; get_screen_colour_at_position &0e7c c9 00 CMP #&00 # Is the player stepping off a ladder or into a monster? &0e7e f0 3b BEQ &0ebb ; player_is_stepping_off_ladder_or_into_half_buried_monster &0e80 8d 94 25 STA &2594 ; colour_of_floor_player_is_about_to_move_onto &0e83 29 08 AND #&08 # Is the player moving onto a ladder? &0e85 d0 1a BNE &0ea1 ; player_is_moving_onto_ladder_or_platform # If so, they can move &0e87 ad 94 25 LDA &2594 ; colour_of_floor_player_is_about_to_move_onto &0e8a 29 04 AND #&04 # Is the player moving onto a trapped monster? &0e8c f0 27 BEQ &0eb5 ; player_can't_move_horizontally # If so, they can't move onto it &0e8e ad 94 25 LDA &2594 ; colour_of_floor_player_is_about_to_move_onto &0e91 29 01 AND #&01 # Is the player moving onto a hole? &0e93 f0 0c BEQ &0ea1 ; player_is_moving_onto_ladder_or_platform # If not, they can move &0e95 98 TYA &0e96 38 SEC &0e97 e9 07 SBC #&07 # If so, is it a fully dug hole? &0e99 a8 TAY &0e9a 20 6d 29 JSR &296d ; get_screen_colour_at_position &0e9d 29 01 AND #&01 &0e9f f0 14 BEQ &0eb5 ; player_can't_move_horizontally # If not, they can't move onto it ; player_is_moving_onto_ladder_or_platform &0ea1 a5 0c LDA &0c ; player_x &0ea3 c9 02 CMP #&02 # Player can't move beyond the left edge of the screen &0ea5 b0 04 BCS &0eab ; player_can't_move_horizontally &0ea7 a5 1c LDA &1c ; player_direction &0ea9 30 0a BMI &0eb5 ; player_can't_move_horizontally &0eab a9 96 LDA #&96 &0ead c5 0c CMP &0c ; player_x # Player can't move beyond the right edge of the screen &0eaf b0 1a BCS &0ecb ; check_if_player_is_about_to_fall_through_hole &0eb1 a5 1c LDA &1c ; player_direction &0eb3 30 16 BMI &0ecb ; check_if_player_is_about_to_fall_through_hole ; player_can't_move_horizontally &0eb5 a9 00 LDA #&00 &0eb7 85 1c STA &1c ; player_direction &0eb9 f0 24 BEQ &0edf ; consider_if_player_is_digging_or_filling ; player_is_stepping_off_ladder_or_into_half_buried_monster &0ebb e8 INX # Consider a pixel one pixel below player's left &0ebc a5 1c LDA &1c ; player_direction &0ebe 30 02 BMI &0ec2 ; player_facing_left &0ec0 ca DEX # or one pixel below the player's right &0ec1 ca DEX ; player_facing_left &0ec2 20 6d 29 JSR &296d ; get_screen_colour_at_position &0ec5 29 08 AND #&08 &0ec7 d0 d8 BNE &0ea1 ; player_isn't_moving_onto_hole # Is the player stepping off a ladder? &0ec9 f0 ea BEQ &0eb5 ; player_can't_move_horizontally # If not, they can't move ; check_if_player_is_about_to_fall_through_hole &0ecb 8a TXA &0ecc 38 SEC &0ecd e5 1c SBC &1c ; player_direction # Consider a pixel one pixel to the side of the player &0ecf aa TAX &0ed0 a5 14 LDA &14 ; player_y &0ed2 38 SEC &0ed3 e9 10 SBC #&10 # and one pixel below their feet &0ed5 a8 TAY &0ed6 20 6d 29 JSR &296d ; get_screen_colour_at_position &0ed9 29 09 AND #&09 &0edb c9 01 CMP #&01 # Is the player moving onto a hole, not a ladder ? &0edd f0 46 BEQ &0f25 ; to_start_player_falling_through_hole # If so, make them fall through the hole ; consider_if_player_is_digging_or_filling &0edf a5 0a LDA &0a ; dig_pressed &0ee1 45 0b EOR &0b ; fill_pressed &0ee3 d0 43 BNE &0f28 ; to_player_pressed_dig_or_fill # If the player has pressed neither dig nor fill, &0ee5 a6 0c LDX &0c ; player_x &0ee7 a5 14 LDA &14 ; player_y &0ee9 38 SEC &0eea e9 07 SBC #&07 # Consider a pixel around their waist &0eec a8 TAY &0eed 20 6d 29 JSR &296d ; get_screen_colour_at_position &0ef0 c9 08 CMP #&08 # Is the player on a ladder? &0ef2 d0 18 BNE &0f0c ; player_didn't_press_up_or_down &0ef4 a5 09 LDA &09 ; up_pressed &0ef6 38 SEC &0ef7 e5 08 SBC &08 ; down_pressed &0ef9 f0 11 BEQ &0f0c ; player_didn't_press_up_or_down # If so, did they press up or down? &0efb 10 04 BPL &0f01 ; player_pressed_down ; player_pressed_up &0efd a9 05 LDA #&05 ; UP # If the player pressed up, set them climbing up &0eff 10 02 BPL &0f03 ; set_player_climbing ; player_pressed_down &0f01 a9 fb LDA #&fb ; DOWN # If the player pressed down, set them climbing down ; set_player_climbing &0f03 a9 05 LDA #&05 # Set player sprite climbing &0f05 85 24 STA &24 ; player_sprite &0f07 a9 01 LDA #&01 ; PLAYER_CLIMBING &0f09 85 2c STA &2c ; player_state &0f0b 60 RTS ; player_didn't_press_up_or_down &0f0c a5 1c LDA &1c ; player_direction &0f0e f0 12 BEQ &0f22 ; leave_with_zero # If the player is moving left or right, &0f10 a5 24 LDA &24 ; player_sprite &0f12 49 01 EOR #&01 # Toggle player's frame &0f14 85 24 STA &24 ; player_sprite &0f16 a5 0c LDA &0c ; player_x &0f18 18 CLC &0f19 65 1c ADC &1c ; player_direction # Move player left or right &0f1b 85 0c STA &0c ; player_x &0f1d a9 01 LDA #&01 &0f1f 20 d2 1b JSR &1bd2 ; play_sound # Play sound for running ; leave_with_zero &0f22 a9 00 LDA #&00 # Unused return value &0f24 60 RTS ; to_start_player_falling_through_hole &0f25 4c 43 1b JMP &1b43 ; start_player_falling_through_hole ; player_starting_to_dig_or_fill &0f28 4c 06 10 JMP &1006 ; player_starting_to_dig_or_fill ; handle_player_climbing # The player is on a ladder &0f2b a5 08 LDA &08 ; down_pressed &0f2d 38 SEC &0f2e e5 09 SBC &09 ; up_pressed &0f30 f0 17 BEQ &0f49 ; player_didn't_press_up_or_down &0f32 10 1b BPL &0f4f ; player_pressed_up ; player_pressed_down # If the player pressed down, &0f34 a5 14 LDA &14 ; player_y &0f36 38 SEC &0f37 e9 11 SBC #&11 # Consider a pixel two pixels beneath their feet &0f39 a8 TAY &0f3a a6 0c LDX &0c ; player_x &0f3c 20 6d 29 JSR &296d ; get_screen_colour_at_position &0f3f c9 08 CMP #&08 # Is this a ladder? &0f41 d0 06 BNE &0f49 ; player_didn't_press_up_or_down &0f43 a9 fb LDA #&fb ; DOWN # If so, set the player climbing down &0f45 85 1c STA &1c ; player_direction &0f47 30 19 BMI &0f62 ; ; player_was_able_to_move_up_or_down ; player_didn't_press_up_or_down &0f49 a9 00 LDA #&00 &0f4b 85 1c STA &1c ; player_direction &0f4d f0 25 BEQ &0f74 ; check_if_player_is_level_with_a_platform ; player_pressed_up # If the player pressed up, &0f4f a5 14 LDA &14 ; player_y &0f51 18 CLC &0f52 69 00 ADC #&00 # Consider a pixel level with their head &0f54 a8 TAY &0f55 a6 0c LDX &0c ; player_x &0f57 20 6d 29 JSR &296d ; get_screen_colour_at_position &0f5a 29 08 AND #&08 # Is this a ladder? &0f5c f0 eb BEQ &0f49 ; player_didn't_press_up_or_down &0f5e a9 05 LDA #&05 ; UP # If so, set the player climbing up &0f60 85 1c STA &1c ; player_direction ; player_was_able_to_move_up_or_down # If the player is climbing up or down, &0f62 a5 24 LDA &24 ; player_sprite &0f64 49 01 EOR #&01 # Toggle player's frame &0f66 85 24 STA &24 ; player_sprite &0f68 a5 14 LDA &14 ; player_y &0f6a 18 CLC &0f6b 65 1c ADC &1c ; player_direction # Move player up or down &0f6d 85 14 STA &14 ; player_y &0f6f a9 02 LDA #&02 &0f71 20 d2 1b JSR &1bd2 ; play_sound # Play sound for climbing ; check_if_player_is_level_with_a_platform &0f74 a5 14 LDA &14 ; player_y &0f76 38 SEC &0f77 e9 07 SBC #&07 &0f79 a2 23 LDX #&23 &0f7b 20 4c 1e JSR &1e4c ; get_a_modulo_x &0f7e d0 1d BNE &0f9d ; leave # Is the player level with a platform? If not, leave. ; turn_player_depending_on_pressed_keys &0f80 a5 06 LDA &06 ; left_pressed &0f82 38 SEC &0f83 e5 07 SBC &07 ; right_pressed &0f85 f0 16 BEQ &0f9d ; leave # Leave if the player didn't press left or right &0f87 10 08 BPL &0f91 ; player_pressed_right ; player_pressed_left &0f89 a9 fc LDA #&fc ; LEFT # If the player pressed left, set them facing left &0f8b 85 1c STA &1c ; player_direction &0f8d a9 01 LDA #&01 ; PLAYER_RUNNING_LEFT_FRAME_1 &0f8f d0 06 BNE &0f97 ; set_player_sprite &0f91 a9 04 LDA #&04 ; RIGHT # If the player pressed right, set them facing right &0f93 85 1c STA &1c ; player_direction &0f95 a9 03 LDA #&03 ; PLAYER_RUNNING_RIGHT_FRAME_1 ; set_player_sprite &0f97 85 24 STA &24 ; player_sprite &0f99 a9 00 LDA #&00 ; PLAYER_RUNNING # And set them back to running &0f9b 85 2c STA &2c ; player_state ; leave &0f9d 60 RTS ; handle_player_digging &0f9e a5 39 LDA &39 ; dig_or_fill_cooldown &0fa0 d0 2f BNE &0fd1 ; not_at_end_of_digging_or_filling # Both digging and filling take four turns &0fa2 a5 0a LDA &0a ; dig_pressed &0fa4 38 SEC &0fa5 e5 0b SBC &0b ; fill_pressed &0fa7 f0 d7 BEQ &0f80 ; turn_player_depending_on_pressed_keys &0fa9 8d db 22 STA &22db ; whether_player_pressed_dig_or_fill &0fac 10 0d BPL &0fbb ; player_pressed_fill ; player_pressed_dig # If the player pressed dig, not fill, &0fae a5 36 LDA &36 ; hole_sprite_minus_one &0fb0 c9 0c CMP #&0c ; COLOUR_1_HOLE_SECTION_THREE - 1 &0fb2 d0 01 BNE &0fb5 ; hole_isn't_completely_dug # and the hole isn't completely dug, ; leave &0fb4 60 RTS ; hole_isn't_completely_dug &0fb5 e6 39 INC &39 ; dig_or_fill_cooldown # start another round of digging ; leave_after_toggling_player_frame # (plotting occurs at end of round) &0fb7 20 ef 0f JSR &0fef ; toggle_player_frame &0fba 60 RTS ; player_pressed_fill # If the player pressed fill, not dig, &0fbb a5 36 LDA &36 ; hole_sprite_minus_one &0fbd c9 09 CMP #&09 ; COLOUR_1_HOLE_SECTION_ONE - 2 &0fbf f0 f3 BEQ &0fb4 ; leave # and the hole isn't completely filled, ; hole_isn't_completely_filled &0fc1 e6 39 INC &39 ; dig_or_fill_cooldown # start another round of filling &0fc3 20 ef 0f JSR &0fef ; toggle_player_frame # (plotting occurs now, at start of round) &0fc6 20 f6 0f JSR &0ff6 ; plot_hole # Plot the change &0fc9 a9 03 LDA #&03 &0fcb 20 d2 1b JSR &1bd2 ; play_sound # Play sound for filling &0fce c6 36 DEC &36 ; hole_sprite_minus_one # Make the hole shallower &0fd0 60 RTS ; not_at_end_of_digging_or_filling &0fd1 18 CLC &0fd2 69 01 ADC #&01 &0fd4 29 03 AND #&03 &0fd6 85 39 STA &39 ; dig_or_fill_cooldown &0fd8 c9 03 CMP #&03 &0fda d0 d8 BNE &0fb4 ; leave &0fdc ad db 22 LDA &22db ; whether_player_pressed_dig_or_fill &0fdf 10 d6 BPL &0fb7 ; leave_after_toggling_player_frame ; player_is_digging # If the player is digging, &0fe1 e6 36 INC &36 ; hole_sprite_minus_one # make the hole deeper &0fe3 20 ef 0f JSR &0fef ; toggle_player_frame &0fe6 20 f6 0f JSR &0ff6 ; plot_hole # Plot the change &0fe9 a9 03 LDA #&03 &0feb 20 d2 1b JSR &1bd2 ; play_sound # Play sound for digging &0fee 60 RTS ; toggle_player_frame &0fef a5 24 LDA &24 ; player_sprite &0ff1 49 01 EOR #&01 &0ff3 85 24 STA &24 ; player_sprite &0ff5 60 RTS ; plot_hole &0ff6 a5 34 LDA &34 ; hole_x &0ff8 38 SEC &0ff9 e9 03 SBC #&03 &0ffb aa TAX &0ffc a4 36 LDY &36 ; hole_sprite_minus_one &0ffe c8 INY &0fff 98 TYA &1000 a4 35 LDY &35 ; hole_y &1002 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &1005 60 RTS ; player_starting_to_dig_or_fill # If the player has just started to dig or fill, &1006 a9 b8 LDA #&b8 &1008 85 76 STA &76 ; digging_check_offsets_address_low &100a a9 22 LDA #&22 ; &22b8 = digging_check_offsets_table &100c 85 77 STA &77 ; digging_check_offsets_address_high &100e a5 0c LDA &0c ; player_x &1010 18 CLC &1011 69 0b ADC #&0b # Set the hole's location &1013 85 34 STA &34 ; hole_x &1015 a5 14 LDA &14 ; player_y &1017 38 SEC &1018 e9 10 SBC #&10 # just below their feet, &101a 85 35 STA &35 ; hole_y &101c a5 24 LDA &24 ; player_sprite &101e 29 02 AND #&02 &1020 d0 12 BNE &1034 ; player_is_digging_or_filling_to_the_right ; player_is_digging_or_filling_to_the_left &1022 a5 34 LDA &34 ; hole_x &1024 38 SEC &1025 e9 10 SBC #&10 # either to their left &1027 85 34 STA &34 ; hole_x &1029 18 CLC &102a a5 76 LDA &76 ; digging_check_offsets_address_low &102c 69 06 ADC #&06 &102e 85 76 STA &76 ; digging_check_offsets_address_low &1030 90 02 BCC &1034 &1032 e6 77 INC &77 ; digging_check_offsets_address_high ; player_is_digging_or_filling_to_the_right &1034 a5 34 LDA &34 ; hole_x &1036 38 SEC &1037 e9 04 SBC #&04 # or their right, depending on their direction &1039 c9 94 CMP #&94 &103b 90 01 BCC &103e ; hole_okay # Is the hole off the edge of the screen? ; leave &103d 60 RTS ; hole_okay &103e a6 34 LDX &34 ; hole_x &1040 20 66 1e JSR &1e66 ; check_if_monster_stops_player_digging # Check the player isn't digging too close to a monster &1043 e0 00 CPX #&00 &1045 f0 07 BEQ &104e ; no_monsters_near_hole &1047 c0 01 CPY #&01 # Y = 1 if player is one step away from monster in hole &1049 f0 f2 BEQ &103d ; leave # Y = 2 if player is standing next to monster in hole &104b 4c 93 1a JMP &1a93 ; player_is_filling_monster_in_old_hole # In the latter case, note the monster is being filled ; no_monsters_near_hole &104e a5 14 LDA &14 ; player_y &1050 38 SEC &1051 e9 10 SBC #&10 &1053 8d c4 22 STA &22c4 ; digging_check_y &1056 a0 05 LDY #&05 &1058 8c c5 22 STY &22c5 ; digging_check_number ; digging_check_loop # Check the player isn't digging too close to another &105b a5 0c LDA &0c ; player_x # hole (Y = 5 to 3) or a ladder (Y = 2 to 0) &105d 18 CLC &105e 71 76 ADC (&76),Y ; digging_check_offsets_address &1060 aa TAX &1061 ac c4 22 LDY &22c4 ; digging_check_y &1064 20 6d 29 JSR &296d ; get_screen_colour_at_position &1067 ac c5 22 LDY &22c5 ; digging_check_number &106a 39 c6 22 AND &22c6,Y ; digging_check_colours_table &106d d0 52 BNE &10c1 ; leave &106f 88 DEY &1070 8c c5 22 STY &22c5 ; digging_check_number &1073 c0 02 CPY #&02 &1075 d0 0a BNE &1081 ; skip_change &1077 a5 14 LDA &14 ; player_y # Some of the ladder checks check further down &1079 38 SEC &107a e9 0b SBC #&0b &107c 8d c4 22 STA &22c4 ; digging_check_y &107f b0 da BCS &105b ; digging_check_loop ; skip_change &1081 c0 ff CPY #&ff &1083 d0 d6 BNE &105b ; digging_check_loop &1085 a5 24 LDA &24 ; player_sprite # If all the checks were okay, &1087 29 02 AND #&02 # Set player sprite digging in appropriate direction &1089 18 CLC &108a 69 06 ADC #&06 &108c 85 24 STA &24 ; player_sprite &108e a9 02 LDA #&02 ; PLAYER_DIGGING &1090 85 2c STA &2c ; player_state &1092 a9 00 LDA #&00 &1094 85 39 STA &39 ; dig_or_fill_cooldown &1096 a5 34 LDA &34 ; hole_x &1098 38 SEC &1099 e9 03 SBC #&03 &109b aa TAX &109c a4 35 LDY &35 ; hole_y &109e 20 6d 29 JSR &296d ; get_screen_colour_at_position &10a1 29 01 AND #&01 # Determine whether there is already a hole here &10a3 85 36 STA &36 ; hole_sprite_minus_one &10a5 88 DEY &10a6 20 6d 29 JSR &296d ; get_screen_colour_at_position &10a9 29 01 AND #&01 &10ab 18 CLC &10ac 65 36 ADC &36 ; hole_sprite_minus_one &10ae 85 36 STA &36 ; hole_sprite_minus_one &10b0 98 TYA &10b1 38 SEC &10b2 e9 04 SBC #&04 &10b4 a8 TAY &10b5 20 6d 29 JSR &296d ; get_screen_colour_at_position &10b8 29 01 AND #&01 &10ba 18 CLC &10bb 65 36 ADC &36 ; hole_sprite_minus_one &10bd 69 09 ADC #&09 ; COLOUR_1_HOLE_SECTION_ONE - 2 &10bf 85 36 STA &36 ; hole_sprite_minus_one ; leave &10c1 60 RTS ; handle_player_falling &10c2 a5 14 LDA &14 ; player_y &10c4 38 SEC &10c5 e9 07 SBC #&07 &10c7 a2 23 LDX #&23 &10c9 20 4c 1e JSR &1e4c ; get_a_modulo_x &10cc f0 22 BEQ &10f0 ; falling_player_is_level_with_a_platform &10ce c9 07 CMP #&07 &10d0 d0 16 BNE &10e8 ; move_player_down # Has the player just cleared a hole? &10d2 a5 14 LDA &14 ; player_y &10d4 18 CLC &10d5 69 0c ADC #&0c &10d7 a8 TAY &10d8 a5 0c LDA &0c ; player_x &10da 4a LSR A &10db 4a LSR A &10dc 29 01 AND #&01 &10de 49 01 EOR #&01 &10e0 18 CLC &10e1 69 0e ADC #&0e ; COLOUR_5_BRICKWORK_WITH_COLOUR_7_MORTAR # If so, replace the dug brickwork &10e3 a6 0c LDX &0c ; player_x &10e5 20 fa 28 JSR &28fa ; plot_sprite_at_x_y ; move_player_down &10e8 a5 14 LDA &14 ; player_y &10ea 38 SEC &10eb e9 07 SBC #&07 &10ed 85 14 STA &14 ; player_y &10ef 60 RTS ; falling_player_is_level_with_a_platform # If the player's feet are level with a platform, &10f0 a5 14 LDA &14 ; player_y &10f2 38 SEC &10f3 e9 14 SBC #&14 &10f5 a8 TAY &10f6 a6 0c LDX &0c ; player_x &10f8 20 6d 29 JSR &296d ; get_screen_colour_at_position # Consider a pixel four pixels below the player's left &10fb 49 08 EOR #&08 &10fd 8d cd 22 STA &22cd ; falling_onto_hole_left_pixel_colour # (&0 = ladder, &c platform, &d hole) &1100 8a TXA &1101 18 CLC &1102 69 07 ADC #&07 # And a second below the player's right &1104 aa TAX &1105 20 6d 29 JSR &296d ; get_screen_colour_at_position &1108 49 08 EOR #&08 # (&0 = ladder, &c platform, &d hole) &110a 2d cd 22 AND &22cd ; falling_onto_hole_left_pixel_colour &110d 29 0d AND #&0d &110f c9 0d CMP #&0d &1111 d0 10 BNE &1123 ; player_lands_on_platform_or_ladder # Is the player aligned with a hole? ; player_falls_through_hole_in_platform # (either a full hole or a two dig hole will match) &1113 a5 14 LDA &14 ; player_y &1115 38 SEC &1116 e9 10 SBC #&10 &1118 a8 TAY &1119 a6 0c LDX &0c ; player_x &111b a9 9c LDA #&9c ; COLOUR_0_BLOCK | AND_SPRITE # If so, remove the dug brickwork beneath the player &111d 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &1120 4c e8 10 JMP &10e8 ; move_player_down # and make the player fall through the hole ; player_lands_on_platform_or_ladder &1123 a5 14 LDA &14 ; player_y &1125 38 SEC &1126 e9 10 SBC #&10 # Consider a pixel one pixels below the player's right &1128 a8 TAY &1129 a5 0c LDA &0c ; player_x &112b 18 CLC &112c 69 07 ADC #&07 &112e aa TAX &112f 20 6d 29 JSR &296d ; get_screen_colour_at_position &1132 8d ce 22 STA &22ce ; falling_onto_hole_right_pixel_inverse # (&8 = ladder, &4 platform, &5 hole) &1135 8a TXA &1136 38 SEC &1137 e9 07 SBC #&07 # and a second, below the player's left &1139 aa TAX &113a 20 6d 29 JSR &296d ; get_screen_colour_at_position &113d 8d cd 22 STA &22cd ; falling_onto_hole_left_pixel_colour # (&8 = ladder, &4 platform, &5 hole) &1140 49 08 EOR #&08 &1142 8d cf 22 STA &22cf ; falling_onto_hole_left_pixel_inverse # (&0 = ladder, &c platform, &d hole) &1145 ad ce 22 LDA &22ce ; falling_onto_hole_right_pixel_inverse &1148 49 08 EOR #&08 &114a 2d cf 22 AND &22cf ; falling_onto_hole_left_pixel_inverse &114d 29 0d AND #&0d &114f c9 0d CMP #&0d &1151 d0 08 BNE &115b ; player_lands_on_ladder_or_misaligned_hole ; player_lands_on_stage_one_hole # If player landed on a one dig hole, &1153 a9 0b LDA #&0b ; COLOUR_1_HOLE_SECTION_ONE &1155 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # fill it in &1158 4c 77 11 JMP &1177 ; set_player_running ; player_lands_on_ladder_or_misaligned_hole &115b ad cd 22 LDA &22cd ; falling_onto_hole_left_pixel_colour &115e 29 0d AND #&0d &1160 c9 05 CMP #&05 # If the player landed on the right edge of a hole, &1162 d0 06 BNE &116a ; player_didn't_land_on_right_edge_of_hole &1164 a9 00 LDA #&00 ; PLAYER_RUNNING_LEFT # set them facing left (towards the hole) &1166 85 37 STA &37 ; player_sprite_on_entering_hole &1168 f0 0d BEQ &1177 ; set_player_running ; player_didn't_land_on_right_edge_of_hole &116a ad ce 22 LDA &22ce ; falling_onto_hole_right_pixel_inverse &116d 29 0d AND #&0d &116f c9 05 CMP #&05 # If the player landed on the left edge of a hole, &1171 d0 04 BNE &1177 ; set_player_running &1173 a9 02 LDA #&02 ; PLAYER_RUNNING_RIGHT # set them facing right (towards the hole) &1175 85 37 STA &37 ; player_sprite_on_entering_hole ; set_player_running &1177 a5 37 LDA &37 ; player_sprite_on_entering_hole # Otherwise, set them facing the direction they ran &1179 85 24 STA &24 ; player_sprite # into the topmost hole, and set them running &117b a9 00 LDA #&00 : PLAYER_RUNNING &117d 85 2c STA &2c ; player_state &117f 85 1c STA &1c ; player_direction &1181 4c 08 21 JMP &2108 ; check_if_monsters_can_eat_player # but only if they didn't fall into a monster! ; play_stage &1184 ba TSX &1185 8e 38 23 STX &2338 ; stack_pointer_at_start_of_stage &1188 20 74 14 JSR &1474 ; initialise_monsters_and_player &118b 20 73 1b JSR &1b73 ; initialise_platforms_and_ladders ; main_game_loop &118e 20 f9 11 JSR &11f9 ; wait_for_vsync &1191 20 3b 14 JSR &143b ; plot_monsters_and_player &1194 58 CLI &1195 ad 45 23 LDA &2345 ; number_of_monsters_to_update_per_frame # Monsters includes the player here &1198 8d 46 23 STA &2346 ; monsters_still_to_update ; update_monsters_loop # Cycle through them, a fixed number per v-sync &119b 20 02 12 JSR &1202 ; handle_player_or_monster_movement &119e 20 1d 14 JSR &141d ; update_player_or_monster_screen_address &11a1 ce 46 23 DEC &2346 ; monsters_still_to_update &11a4 d0 f5 BNE &119b ; update_monsters_loop &11a6 ad 39 23 LDA &2339 ; player_flags &11a9 29 20 AND #&20 ; PLAYER_PAUSED &11ab d0 08 BNE &11b5 ; skip_oxygen_update &11ad ce 2c 23 DEC &232c ; actual_oxygen_low &11b0 d0 03 BNE &11b5 ; skip_oxygen_update &11b2 20 02 1a JSR &1a02 ; update_oxygen ; skip_oxygen_update &11b5 a9 7e LDA #&7e ; Acknowledge ESCAPE Condition &11b7 20 f4 ff JSR &fff4 ; OSBYTE &11ba 4c 8e 11 JMP &118e ; main_game_loop ; handle_player_movement &11bd a5 2c LDA &2c ; player_state &11bf c9 03 CMP #&03 ; PLAYER_FALLING &11c1 f0 0d BEQ &11d0 ; consider_player_movement &11c3 ae 2b 23 LDX &232b ; actual_oxygen_high &11c6 e0 0a CPX #&0a &11c8 b0 06 BCS &11d0 ; consider_player_movement # If the player has less than &0a00 actual oxygen, &11ca 20 49 1e JSR &1e49 ; get_random_number_within_range &11cd d0 01 BNE &11d0 ; consider_player_movement # make their movements increasingly erratic &11cf 60 RTS ; consider_player_movement &11d0 20 05 0e JSR &0e05 ; check_keys &11d3 a6 2c LDX &2c ; player_state # Update player depending on state &11d5 f0 10 BEQ &11e7 ; to_handle_player_running &11d7 ca DEX &11d8 f0 10 BEQ &11ea ; to_handle_player_climbing &11da ca DEX &11db f0 10 BEQ &11ed ; to_handle_player_digging &11dd ca DEX &11de f0 10 BEQ &11f0 ; to_handle_player_falling &11e0 ca DEX &11e1 f0 10 BEQ &11f3 ; to_handle_player_filling_monster &11e3 ca DEX &11e4 f0 10 BEQ &11f6 ; to_handle_player_filled_monster &11e6 60 RTS ; to_handle_player_running &11e7 4c 22 0e JMP &0e22 ; handle_player_running ; to_handle_player_climbing &11ea 4c 2b 0f JMP &0f2b ; handle_player_climbing ; to_handle_player_digging &11ed 4c 9e 0f JMP &0f9e ; handle_player_digging ; to_handle_player_falling &11f0 4c c2 10 JMP &10c2 ; handle_player_falling ; to_handle_player_filling_monster &11f3 4c 24 16 JMP &1624 ; handle_player_filling_monster ; to_handle_player_filled_monster &11f6 4c 70 18 JMP &1870 ; handle_player_filled_monster ; wait_for_vsync &11f9 78 SEI &11fa a9 02 LDA #&02 # Bit 1 is set by CA1 active edge, i.e. v-sync ; wait_for_vsync_loop &11fc 2c 4d fe BIT &fe4d ; Interrupt flag register &11ff f0 fb BEQ &11fc ; wait_for_vsync_loop &1201 60 RTS ; handle_player_or_monster_movement &1202 e6 38 INC &38 ; monster_number &1204 a5 38 LDA &38 ; monster_number &1206 29 07 AND #&07 &1208 85 38 STA &38 ; monster_number &120a aa TAX &120b bd 39 23 LDA &2339,X ; monsters_flags &120e 29 60 AND #&60 ; MONSTER_KILLED | MONSTER_PAUSED or PLAYER_PAUSED &1210 f0 01 BEQ &1213 ; player_or_monster_active &1212 60 RTS ; player_or_monster_active &1213 a5 38 LDA &38 ; monster_number &1215 f0 a6 BEQ &11bd ; handle_player_movement &1217 aa TAX # If this is a monster, &1218 b5 0c LDA &0c,X ; monsters_x &121a 8d d5 22 STA &22d5 ; check_x &121d b5 14 LDA &14,X ; monsters_y &121f 8d d6 22 STA &22d6 ; check_y &1222 a9 01 LDA #&01 ; PLAYER # check whether it is too near the player &1224 a2 07 LDX #&07 &1226 a0 0c LDY #&0c &1228 20 b6 1a JSR &1ab6 ; check_for_monsters_or_player_in_proximity &122b f0 06 BEQ &1233 ; monster_isn't_near_player ; kill_player_by_being_eaten &122d 20 a5 1e JSR &1ea5 ; plot_monster_eating_player # and eat them if it is. &1230 4c 57 1a JMP &1a57 ; kill_player ; monster_isn't_near_player &1233 a6 38 LDX &38 ; monster_number &1235 b5 2c LDA &2c,X ; monsters_state # Update monster depending on state &1237 aa TAX ; MONSTER_RUNNING &1238 f0 19 BEQ &1253 ; handle_monster_running &123a ca DEX ; MONSTER_CLIMBING &123b f0 0a BEQ &1247 ; to_handle_monster_climbing &123d ca DEX ; MONSTER_TRAPPED &123e f0 0a BEQ &124a ; to_handle_monster_trapped &1240 ca DEX ; MONSTER_FALLING &1241 f0 0a BEQ &124d ; to_handle_monster_falling &1243 ca DEX ; MONSTER_POINTS &1244 f0 0a BEQ &1250 ; to_handle_monster_points &1246 60 RTS # Do nothing if monster has been removed ; to_handle_monster_climbing &1247 4c 80 13 JMP &1380 ; handle_monster_climbing ; to_handle_monster_trapped &124a 4c 03 1c JMP &1c03 ; handle_monster_trapped ; to_handle_monster_falling &124d 4c 98 16 JMP &1698 ; handle_monster_falling ; to_handle_monster_points &1250 4c 87 18 JMP &1887 ; handle_monster_points ; handle_monster_running &1253 ad d6 22 LDA &22d6 ; check_y &1256 38 SEC &1257 e9 10 SBC #&10 &1259 a8 TAY &125a ad d5 22 LDA &22d5 ; check_x &125d 38 SEC &125e e9 04 SBC #&04 &1260 aa TAX &1261 20 6d 29 JSR &296d ; get_screen_colour_at_position &1264 c9 08 CMP #&08 # Is there a ladder below the monster? &1266 d0 28 BNE &1290 ; monster_isn't_about_to_climb_down &1268 ad d5 22 LDA &22d5 ; check_x &126b 18 CLC &126c 69 03 ADC #&03 &126e aa TAX &126f 20 6d 29 JSR &296d ; get_screen_colour_at_position &1272 c9 08 CMP #&08 # If so, is the monster aligned with it? &1274 d0 1a BNE &1290 ; monster_isn't_about_to_climb_down &1276 20 e0 21 JSR &21e0 ; determine_if_monster_is_hungry # If so, and the monster is feeling hungry, &1279 d0 15 BNE &1290 ; monster_isn't_about_to_climb_down &127b a6 38 LDX &38 ; monster_number &127d a5 14 LDA &14 ; player_y &127f d5 14 CMP &14,X ; monsters_y # and the player is below the monster, &1281 b0 0d BCS &1290 ; monster_isn't_about_to_climb_down &1283 a9 fb LDA #&fb ; DOWN # set the monster climbing down ; set_monster_direction &1285 a6 38 LDX &38 ; monster_number &1287 95 1c STA &1c,X ; monsters_direction &1289 a9 01 LDA #&01 ; MONSTER_CLIMBING &128b 95 2c STA &2c,X ; monsters_state &128d 4c 0f 14 JMP &140f ; update_monster_vertical_position ; monster_isn't_about_to_climb_down &1290 ad d5 22 LDA &22d5 ; check_x &1293 38 SEC &1294 e9 04 SBC #&04 &1296 aa TAX &1297 ad d6 22 LDA &22d6 ; check_y &129a 38 SEC &129b e9 01 SBC #&01 &129d a8 TAY &129e 20 6d 29 JSR &296d ; get_screen_colour_at_position &12a1 c9 08 CMP #&08 # Is there a ladder above the monster? &12a3 d0 1f BNE &12c4 ; monster_isn't_about_to_climb_up &12a5 ad d5 22 LDA &22d5 ; check_x &12a8 18 CLC &12a9 69 03 ADC #&03 &12ab aa TAX &12ac 20 6d 29 JSR &296d ; get_screen_colour_at_position &12af c9 08 CMP #&08 # If so, is the monster aligned with it? &12b1 d0 11 BNE &12c4 ; monster_isn't_about_to_climb_up &12b3 20 e0 21 JSR &21e0 ; determine_if_monster_is_hungry # If so, and the monster is feeling hungry, &12b6 d0 0c BNE &12c4 ; monster_isn't_about_to_climb_up &12b8 a6 38 LDX &38 ; monster_number &12ba b5 14 LDA &14,X ; monsters_y &12bc c5 14 CMP &14 ; player_y # and the player is above the monster, &12be b0 04 BCS &12c4 ; monster_isn't_about_to_climb_up &12c0 a9 05 LDA #&05 ; UP # set the monster climbing up &12c2 10 c1 BPL &1285 ; set_monster_direction ; monster_isn't_about_to_climb_up &12c4 ad d5 22 LDA &22d5 ; check_x &12c7 c9 9a CMP #&9a # If the monster is at the right of the screen, &12c9 90 04 BCC &12cf ; not_at_right_edge_of_screen &12cb a9 fe LDA #&fe ; LEFT # set it moving left &12cd 30 06 BMI &12d5 ; set_monster_moving_away_from_edge_of_screen ; not_at_right_edge_of_screen &12cf c9 0a CMP #&0a # If the monster is at the left of the screen &12d1 b0 06 BCS &12d9 ; not_at_left_edge_of_screen &12d3 a9 02 LDA #&02 ; RIGHT # set it moving right ; set_monster_moving_away_from_edge_of_screen &12d5 a6 38 LDX &38 ; monster_number &12d7 95 1c STA &1c,X ; monsters_direction ; not_at_left_edge_of_screen &12d9 a9 01 LDA #&01 &12db a6 38 LDX &38 ; monster_number &12dd b4 1c LDY &1c,X ; monsters_direction &12df 30 02 BMI &12e3 ; not_moving_right &12e1 a9 fe LDA #&fe ; not_moving_right &12e3 18 CLC &12e4 6d d5 22 ADC &22d5 ; check_x &12e7 aa TAX &12e8 ad d6 22 LDA &22d6 ; check_y &12eb 38 SEC &12ec e9 10 SBC #&10 &12ee a8 TAY &12ef 20 6d 29 JSR &296d ; get_screen_colour_at_position &12f2 29 0d AND #&0d &12f4 c9 05 CMP #&05 # Is the monster over a hole? &12f6 d0 21 BNE &1319 ; monster_isn't_over_hole &12f8 8a TXA &12f9 38 SEC &12fa e9 07 SBC #&07 &12fc a6 38 LDX &38 ; monster_number &12fe b4 1c LDY &1c,X ; monsters_direction &1300 30 03 BMI &1305 ; not_moving_right &1302 18 CLC &1303 69 0e ADC #&0e ; not_moving_right &1305 aa TAX &1306 ad d6 22 LDA &22d6 ; check_y &1309 38 SEC &130a e9 10 SBC #&10 &130c a8 TAY &130d 20 6d 29 JSR &296d ; get_screen_colour_at_position &1310 29 0d AND #&0d &1312 c9 05 CMP #&05 # If so, is the monster aligned with a hole? &1314 d0 03 BNE &1319 ; monster_isn't_over_hole &1316 4c 31 15 JMP &1531 ; monster_is_over_hole ; monster_isn't_over_hole &1319 ad d5 22 LDA &22d5 ; check_x &131c c9 0c CMP #&0c # If the monster isn't at the left &131e 90 3c BCC &135c ; update_monster_horizontal_position &1320 c9 98 CMP #&98 # or the right edge of the screen, &1322 b0 38 BCS &135c ; update_monster_horizontal_position &1324 a9 00 LDA #&00 ; MONSTERS # then see if it is near any of the other monsters &1326 a2 0c LDX #&0c &1328 a0 13 LDY #&13 &132a 20 b6 1a JSR &1ab6 ; check_for_monsters_or_player_in_proximity &132d d0 16 BNE &1345 ; monster_is_near_other_monster # If the monster is not near another monster, &132f 20 e0 21 JSR &21e0 ; determine_if_monster_is_hungry &1332 f0 28 BEQ &135c ; update_monster_horizontal_position # and they're not feeling hungry, &1334 a2 14 LDX #&14 &1336 20 49 1e JSR &1e49 ; get_random_number_within_range # then one in twenty frames &1339 d0 21 BNE &135c ; update_monster_horizontal_position &133b a6 38 LDX &38 ; monster_number &133d b5 1c LDA &1c,X ; monsters_direction &133f 49 fc EOR #&fc # change their direction &1341 95 1c STA &1c,X ; monsters_direction &1343 d0 17 BNE &135c ; update_monster_horizontal_position ; monster_is_near_other_monster # If the monster is near another monster, &1345 ad d6 22 LDA &22d6 ; check_y &1348 d5 14 CMP &14,X ; monsters_y &134a 90 10 BCC &135c ; update_monster_horizontal_position # either on the same platform or trapped in it, &134c ad d5 22 LDA &22d5 ; check_x &134f a0 02 LDY #&02 ; RIGHT # set the other monster moving away from it &1351 d5 0c CMP &0c,X ; monsters_x &1353 b0 02 BCS &1357 ; bounce_monster_off_other_monster &1355 a0 fe LDY #&fe ; LEFT ; bounce_monster_off_other_monster &1357 98 TYA &1358 a6 38 LDX &38 ; monster_number &135a 95 1c STA &1c,X ; monsters_direction ; update_monster_horizontal_position &135c a6 38 LDX &38 ; monster_number &135e ad d5 22 LDA &22d5 ; check_x # Update the monster's position &1361 18 CLC &1362 75 1c ADC &1c,X ; monsters_direction &1364 95 0c STA &0c,X ; monsters_x &1366 20 1d 16 JSR &161d ; toggle_monster_frame # and toggle their animation &1369 60 RTS ; generate_random_number &136a ad d7 22 LDA &22d7 ; rnd_1 &136d 29 48 AND #&48 &136f 69 38 ADC #&38 &1371 0a ASL A &1372 0a ASL A &1373 2e d9 22 ROL &22d9 ; rnd_3 &1376 2e d8 22 ROL &22d8 ; rnd_2 &1379 2e d7 22 ROL &22d7 ; rnd_1 &137c ad d7 22 LDA &22d7 ; rnd_1 &137f 60 RTS ; handle_monster_climbing &1380 ad d6 22 LDA &22d6 ; check_y &1383 18 CLC &1384 69 01 ADC #&01 &1386 a2 23 LDX #&23 &1388 20 4c 1e JSR &1e4c ; get_a_modulo_x &138b c9 08 CMP #&08 &138d d0 63 BNE &13f2 ; monster_isn't_level_with_platform # If the monster is level with a platform, &138f a6 38 LDX &38 ; monster_number &1391 b5 14 LDA &14,X ; monsters_y &1393 c5 14 CMP &14 ; player_y &1395 f0 35 BEQ &13cc ; move_monster_onto_platform # and the player isn't on that platform, ; monster_is_climbing &1397 a6 38 LDX &38 ; monster_number &1399 b5 1c LDA &1c,X ; monsters_direction &139b 10 15 BPL &13b2 ; monster_is_climbing_up ; monster_is_climbing_down &139d ad d5 22 LDA &22d5 ; check_x &13a0 38 SEC &13a1 e9 04 SBC #&04 &13a3 aa TAX &13a4 ad d6 22 LDA &22d6 ; check_y &13a7 38 SEC &13a8 e9 10 SBC #&10 &13aa a8 TAY &13ab 20 6d 29 JSR &296d ; get_screen_colour_at_position &13ae c9 08 CMP #&08 # Is there more ladder for the monster to climb? &13b0 d0 1a BNE &13cc ; move_monster_onto_platform ; monster_is_climbing_up # If so, keep the monster climbing &13b2 a6 38 LDX &38 ; monster_number &13b4 b5 1c LDA &1c,X ; monsters_direction &13b6 30 57 BMI &140f ; update_monster_vertical_position &13b8 f0 55 BEQ &140f ; update_monster_vertical_position &13ba ad d5 22 LDA &22d5 ; check_x &13bd 38 SEC &13be e9 04 SBC #&04 &13c0 aa TAX &13c1 ac d6 22 LDY &22d6 ; check_y &13c4 88 DEY &13c5 20 6d 29 JSR &296d ; get_screen_colour_at_position &13c8 c9 08 CMP #&08 &13ca f0 43 BEQ &140f ; update_monster_vertical_position ; move_monster_onto_platform # If the monster is on the same platform as the player, &13cc 20 e0 21 JSR &21e0 ; determine_if_monster_is_hungry # or has run out of ladder to climb, &13cf f0 13 BEQ &13e4 ; make_monster_head_towards_player # Is the monster hungry? If so, it heads towards player &13d1 20 6a 13 JSR &136a ; generate_random_number &13d4 29 04 AND #&04 # Otherwise, turn it left or right at random &13d6 38 SEC &13d7 e9 02 SBC #&02 &13d9 a6 38 LDX &38 ; monster_number ; set_monster_direction &13db 95 1c STA &1c,X ; monsters_direction &13dd a9 00 LDA #&00 ; MONSTER_RUNNING &13df 95 2c STA &2c,X ; monsters_state &13e1 4c 5c 13 JMP &135c ; update_monster_horizontal_position ; make_monster_head_towards_player &13e4 a6 38 LDX &38 ; monster_number &13e6 a9 02 LDA #&02 ; LEFT &13e8 b4 0c LDY &0c,X ; monsters_x &13ea c4 0c CPY &0c ; player_x &13ec 90 ed BCC &13db ; set_monster_direction &13ee a9 fe LDA #&fe ; RIGHT &13f0 d0 e9 BNE &13db ; set_monster_direction ; monster_isn't_level_with_platform # If the monster is midway up a ladder, &13f2 a9 00 LDA #&00 ; MONSTERS &13f4 a2 00 LDX #&00 &13f6 a0 14 LDY #&14 &13f8 20 b6 1a JSR &1ab6 ; check_for_monsters_or_player_in_proximity &13fb f0 12 BEQ &140f ; update_monster_vertical_position &13fd a0 05 LDY #&05 ; DOWN # If the monster is near another monster, &13ff ad d6 22 LDA &22d6 ; check_y &1402 d5 14 CMP &14,X ; monsters_y &1404 b0 02 BCS &1408 ; bounce_monster_off_other_monster &1406 a0 fb LDY #&fb ; UP # set the other monster moving away from it ; bounce_monster_off_other_monster &1408 a6 38 LDX &38 ; monster_number &140a 98 TYA &140b 95 1c STA &1c,X ; monsters_direction &140d d0 88 BNE &1397 ; monster_is_climbing ; update_monster_vertical_position &140f a6 38 LDX &38 ; monster_number &1411 ad d6 22 LDA &22d6 ; check_y # Update the monster's position &1414 18 CLC &1415 75 1c ADC &1c,X ; monsters_direction &1417 95 14 STA &14,X ; monsters_y &1419 20 1d 16 JSR &161d ; toggle_monster_frame # and toggle their animation &141c 60 RTS ; update_player_or_monster_screen_address &141d a6 38 LDX &38 ; monster_number &141f b4 14 LDY &14,X ; monsters_y &1421 b5 0c LDA &0c,X ; monsters_x &1423 18 CLC &1424 7d dd 22 ADC &22dd,X ; monsters_x_offset &1427 aa TAX &1428 20 c0 28 JSR &28c0 ; calculate_screen_address &142b a6 38 LDX &38 ; monster_number &142d a5 72 LDA &72 ; screen_address_low &142f 95 3a STA &3a,X ; monsters_screen_address_low &1431 a5 73 LDA &73 ; screen_address_high &1433 95 42 STA &42,X ; monsters_screen_address_high &1435 a9 01 LDA #&01 &1437 9d f9 22 STA &22f9,X ; monsters_plotted # Mark the monster or player as needing unplotting &143a 60 RTS ; plot_monsters_and_player &143b ae 36 23 LDX &2336 ; number_of_monsters_plus_one &143e ca DEX &143f 86 62 STX &62 ; monster_to_plot ; plot_monsters_and_player_loop &1441 a6 62 LDX &62 ; monster_to_plot &1443 bd f9 22 LDA &22f9,X ; monsters_plotted &1446 f0 27 BEQ &146f ; skip_unplotting_monster &1448 a9 00 LDA #&00 &144a 9d f9 22 STA &22f9,X ; monsters_plotted &144d b5 4a LDA &4a,X ; monsters_previous_screen_address_low &144f 85 72 STA &72 ; screen_address_low &1451 b5 52 LDA &52,X ; monsters_previous_screen_address_high &1453 85 73 STA &73 ; screen_address_high &1455 b5 5a LDA &5a,X ; monsters_previous_sprite &1457 20 07 29 JSR &2907 ; plot_sprite_at_screen_address # Unplot previous sprite &145a a6 62 LDX &62 ; monster_to_plot &145c b5 3a LDA &3a,X ; monsters_screen_address_low &145e 95 4a STA &4a,X ; monsters_previous_screen_address_low &1460 85 72 STA &72 ; screen_address_low &1462 b5 42 LDA &42,X ; monsters_screen_address_high &1464 95 52 STA &52,X monsters_previous_screen_address_high &1466 85 73 STA &73 ; screen_address_high &1468 b5 24 LDA &24,X ; monsters_sprite &146a 95 5a STA &5a,X ; monsters_previous_sprite &146c 20 07 29 JSR &2907 ; plot_sprite_at_screen_address # Plot new sprite ; skip_unplotting_monster &146f c6 62 DEC &62 ; monster_to_plot &1471 10 ce BPL &1441 ; plot_monsters_and_player_loop &1473 60 RTS ; initialise_monsters_and_player &1474 a2 07 LDX #&07 ; set_monster_flags_loop &1476 a9 40 LDA #&40 ; MONSTER_KILLED &1478 9d 39 23 STA &2339,X ; monsters_flags &147b a9 00 LDA #&00 &147d 9d 01 23 STA &2301,X ; monsters_holes_passed_through &1480 ca DEX &1481 10 f3 BPL &1476 ; set_monster_flags_loop &1483 a5 01 LDA &01 ; stage_number # Number of monsters = 3 + 2 * ((stage - 1) % 3) &1485 38 SEC # i.e. 3, 5, 7, 3, 5, 7, etc &1486 e9 01 SBC #&01 ; modulo_loop &1488 e9 03 SBC #&03 &148a b0 fc BCS &1488 ; modulo_loop &148c 69 03 ADC #&03 &148e 0a ASL A &148f 69 04 ADC #&04 &1491 8d 36 23 STA &2336 ; number_of_monsters_plus_one &1494 8d 37 23 STA &2337 ; number_of_monsters_still_alive_plus_one &1497 aa TAX &1498 ca DEX &1499 86 38 STX &38 ; monster_number ; position_monster &149b a6 38 LDX &38 ; monster_number &149d 20 6a 13 JSR &136a ; generate_random_number &14a0 29 1f AND #&1f # Put the monster somewhere in the middle half &14a2 0a ASL A &14a3 69 30 ADC #&30 &14a5 95 0c STA &0c,X ; monsters_x &14a7 8d d5 22 STA &22d5 ; check_x &14aa 20 6a 13 JSR &136a ; generate_random_number &14ad 29 03 AND #&03 # of one of the top four platforms &14af 18 CLC &14b0 69 01 ADC #&01 &14b2 a8 TAY &14b3 b9 31 23 LDA &2331,Y ; platform_heights &14b6 95 14 STA &14,X ; monsters_y &14b8 8d d6 22 STA &22d6 ; check_y &14bb a9 00 LDA #&00 ; MONSTERS # Check that the monster is not too close to another, &14bd a2 0c LDX #&0c &14bf a0 13 LDY #&13 &14c1 20 b6 1a JSR &1ab6 ; check_for_monsters_or_player_in_proximity &14c4 30 d5 BMI &149b ; position_monster # repositioning it if necessary &14c6 a6 38 LDX &38 ; monster_number &14c8 bd a4 22 LDA &22a4,X ; monsters_starting_type &14cb 95 63 STA &63,X ; monsters_type &14cd a8 TAY &14ce b9 2d 23 LDA &232d,Y ; monster_type_to_sprite &14d1 95 24 STA &24,X ; monsters_sprite &14d3 a9 7f LDA #&7f &14d5 95 5a STA &5a,X ; monsters_previous_sprite &14d7 a9 00 LDA #&00 ; MONSTER_RUNNING &14d9 95 2c STA &2c,X ; monsters_state &14db 9d f9 22 STA &22f9,X ; monsters_plotted &14de 9d 39 23 STA &2339,X ; monsters_flags &14e1 20 6a 13 JSR &136a ; generate_random_number &14e4 29 04 AND #&04 # Monsters starts moving left or right at random &14e6 38 SEC &14e7 e9 02 SBC #&02 &14e9 95 1c STA &1c,X ; monsters_direction &14eb c6 38 DEC &38 ; monster_number &14ed 10 ac BPL &149b ; position_monster # Repeat for any remaining monsters &14ef a9 50 LDA #&50 &14f1 85 0c STA &0c ; player_x # The player starts in the middle, &14f3 a9 2a LDA #&2a &14f5 85 14 STA &14 ; player_y # on the ground &14f7 a9 00 LDA #&00 &14f9 85 1c STA &1c ; player_direction &14fb ae 36 23 LDX &2336 ; number_of_monsters_plus_one &14fe ca DEX &14ff 86 38 STX &38 ; monster_number ; set_monster_screen_address_loop # Calculate screen addresses for monsters and player &1501 a6 38 LDX &38 ; monster_number &1503 20 1d 14 JSR &141d ; update_player_or_monster_screen_address &1506 c6 38 DEC &38 ; monster_number &1508 10 f7 BPL &1501 ; set_monster_screen_address_loop &150a e6 38 INC &38 ; monster_number &150c a9 00 LDA #&00 &150e 8d 28 23 STA &2328 ; oxygen_as_numbers_low &1511 85 1c STA &1c ; player_direction &1513 85 62 STA &62 ; monster_to_plot &1515 a9 30 LDA #&30 # Each stage has the same amount of actual oxygen &1517 8d 2c 23 STA &232c ; actual_oxygen_low &151a ad 44 23 LDA &2344 ; starting_oxygen_as_numbers_high # but the way it is scored is different on later ones &151d 8d 29 23 STA &2329 ; oxygen_as_numbers_high &1520 8d 2a 23 STA &232a ; oxygen_as_numbers_drain &1523 a9 78 LDA #&78 &1525 8d 2b 23 STA &232b ; actual_oxygen_high &1528 a9 70 LDA #&70 &152a 85 7a STA &7a ; oxygen_bar_screen_address_low &152c a9 7d LDA #&7d &152e 85 7b STA &7b ; oxygen_bar_screen_address_high &1530 60 RTS ; monster_is_over_hole &1531 8e e5 22 STX &22e5 ; hole_monster_x &1534 a5 2c LDA &2c ; player_state &1536 c9 02 CMP #&02 ; PLAYER_DIGGING &1538 d0 20 BNE &155a ; monster_isn't_over_most_just_dug_hole &153a a6 38 LDX &38 ; monster_number &153c b5 1c LDA &1c,X ; monsters_direction &153e 18 CLC &153f 6d d5 22 ADC &22d5 ; check_x # Allowing for the monster's movement, &1542 38 SEC &1543 e9 01 SBC #&01 &1545 c5 34 CMP &34 ; hole_x # is the monster over a hole that's just been dug? &1547 d0 11 BNE &155a ; monster_isn't_over_most_just_dug_hole &1549 ad d6 22 LDA &22d6 ; check_y &154c 38 SEC &154d e9 10 SBC #&10 &154f c5 35 CMP &35 ; hole_y &1551 d0 07 BNE &155a ; monster_isn't_over_most_just_dug_hole &1553 a9 04 LDA #&04 ; PLAYER_FILLING_MONSTER # If so, set the player filling a monster &1555 85 2c STA &2c ; player_state &1557 8e e7 22 STX &22e7 ; most_recently_filled_monster # and note this monster as the one to be filled ; monster_isn't_over_most_just_dug_hole &155a ad d6 22 LDA &22d6 ; check_y &155d 38 SEC &155e e9 17 SBC #&17 &1560 a8 TAY &1561 ae e5 22 LDX &22e5 ; hole_monster_x &1564 20 6d 29 JSR &296d ; get_screen_colour_at_position &1567 29 0d AND #&0d &1569 c9 05 CMP #&05 &156b d0 3d BNE &15aa ; monster_is_over_partial_hole &156d a6 38 LDX &38 ; monster_number # Is the monster over a fully dug hole? &156f a9 80 LDA #&80 ; MONSTER_FULLY_TRAPPED &1571 1d 39 23 ORA &2339,X ; monsters_flags # If so, mark it as having been fully trapped &1574 9d 39 23 STA &2339,X ; monsters_flags &1577 ad d5 22 LDA &22d5 ; check_x &157a 18 CLC &157b 75 1c ADC &1c,X ; monsters_direction # Apply the monster's horizontal movement &157d 95 0c STA &0c,X ; monsters_x &157f ad d6 22 LDA &22d6 ; check_y &1582 38 SEC &1583 e9 10 SBC #&10 # Put the monster in the hole &1585 95 14 STA &14,X ; monsters_y &1587 a8 TAY &1588 b5 24 LDA &24,X ; monsters_sprite &158a 49 02 EOR #&02 # Set the monster's sprite to be trapped &158c 95 24 STA &24,X ; monsters_sprite &158e b5 0c LDA &0c,X ; monsters_x &1590 38 SEC &1591 e9 03 SBC #&03 &1593 aa TAX &1594 a9 9c LDA #&9c ; COLOUR_0_BLOCK | AND_SPRITE # Remove the dug brickwork beneath the monster &1596 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &1599 a6 38 LDX &38 ; monster_number &159b a9 02 LDA #&02 ; MONSTER_TRAPPED # Mark the monster as trapped &159d 95 2c STA &2c,X ; monsters_state &159f a9 20 LDA #&20 &15a1 9d e8 22 STA &22e8,X ; monsters_escape_timer # 20+3 frames for monster to escape after climbing &15a4 a9 30 LDA #&30 &15a6 9d f0 22 STA &22f0,X ; monsters_trapped_timer # 24 frames before monster starts climbing out of hole &15a9 60 RTS ; monster_is_over_partial_hole # Is the monster in a partially dug hole? &15aa ad d6 22 LDA &22d6 ; check_y &15ad 38 SEC &15ae e9 14 SBC #&14 &15b0 a8 TAY &15b1 20 6d 29 JSR &296d ; get_screen_colour_at_position &15b4 29 0d AND #&0d &15b6 c9 05 CMP #&05 # Is the partial hole two digs deep? &15b8 08 PHP &15b9 68 PLA # Bit 1 is zero flag, set if comparison was true &15ba 29 02 AND #&02 &15bc 8d f8 22 STA &22f8 ; depth_of_partial_hole # 2 if two digs deep, 0 if one dig deep &15bf a6 38 LDX &38 ; monster_number &15c1 bd 39 23 LDA &2339,X ; monsters_flags &15c4 29 7f AND #&7f ; !MONSTER_FULLY_TRAPPED # Mark monster as not having been fully trapped &15c6 9d 39 23 STA &2339,X ; monsters_flags &15c9 b5 24 LDA &24,X ; monsters_sprite &15cb 49 01 EOR #&01 # Toggle the monster's frame &15cd 95 24 STA &24,X ; monsters_sprite &15cf b5 1c LDA &1c,X ; monsters_direction &15d1 18 CLC &15d2 6d d5 22 ADC &22d5 ; check_x # Apply the monster's horizontal movement &15d5 95 0c STA &0c,X ; monsters_x &15d7 ad f8 22 LDA &22f8 ; depth_of_partial_hole &15da 0a ASL A &15db 18 CLC &15dc 69 03 ADC #&03 &15de ed d6 22 SBC &22d6 ; check_y # Put the monster in the partial hole &15e1 49 ff EOR #&ff &15e3 95 14 STA &14,X ; monsters_y &15e5 ad d6 22 LDA &22d6 ; check_y &15e8 38 SEC &15e9 e9 10 SBC #&10 &15eb a8 TAY &15ec b5 0c LDA &0c,X ; monsters_x &15ee 38 SEC &15ef e9 03 SBC #&03 &15f1 aa TAX &15f2 ad f8 22 LDA &22f8 ; depth_of_partial_hole &15f5 4a LSR A &15f6 69 9d ADC #&9d ; COLOUR_15_INVERSE_OF_ONE_DIG_HOLE | AND_SPRITE &15f8 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Remove the dug part of the hole &15fb a6 38 LDX &38 ; monster_number &15fd a9 02 LDA #&02 ; MONSTER_TRAPPED # Mark the monster as trapped &15ff 95 2c STA &2c,X ; monsters_state &1601 a9 36 LDA #&36 # &36 = climbs out from topmost section of hole &1603 38 SEC &1604 ed f8 22 SBC &22f8 ; depth_of_partial_hole # &34 = climbs out from middle section of hole &1607 9d e8 22 STA &22e8,X ; monsters_escape_timer &160a ad f8 22 LDA &22f8 ; depth_of_partial_hole &160d 0a ASL A &160e 0a ASL A &160f 69 08 ADC #&08 &1611 9d f0 22 STA &22f0,X ; monsters_trapped_timer # 8 or 16 frames before monster starts climbing out &1614 a5 2c LDA &2c ; player_state &1616 c9 04 CMP #&04 ; PLAYER_FILLING_MONSTER &1618 d0 02 BNE &161c ; leave &161a e6 2c INC &2c ; player_state ; PLAYER_FILLED_MONSTER # Tidy up fill round ; leave &161c 60 RTS ; toggle_monster_frame &161d b5 24 LDA &24,X ; monsters_sprite &161f 49 01 EOR #&01 &1621 95 24 STA &24,X ; monsters_sprite &1623 60 RTS ; handle_player_filling_monster # The player is filling a hole containing a monster &1624 a5 39 LDA &39 ; dig_or_fill_cooldown &1626 d0 61 BNE &1689 ; not_at_end_of_filling &1628 20 05 0e JSR &0e05 ; check_keys # Unnecessary, as keys have just been checked &162b a5 0a LDA &0a ; dig_pressed &162d 38 SEC &162e e5 0b SBC &0b ; fill_pressed &1630 c9 01 CMP #&01 &1632 f0 03 BEQ &1637 ; player_pressed_fill &1634 4c 80 0f JMP &0f80 ; turn_player_depending_on_pressed_keys ; player_pressed_fill # If the player pressed fill, not dig &1637 e6 39 INC &39 ; dig_or_fill_cooldown &1639 20 ef 0f JSR &0fef ; toggle_player_frame &163c a9 03 LDA #&03 &163e 20 d2 1b JSR &1bd2 ; play_sound &1641 ae e7 22 LDX &22e7 ; most_recently_filled_monster # Consider the monster the player is filling &1644 bd f0 22 LDA &22f0,X ; monsters_trapped_timer &1647 f0 3f BEQ &1688 ; leave &1649 d6 14 DEC &14,X ; monsters_y # A single fill moves the monster down a pixel &164b de e8 22 DEC &22e8,X ; monsters_escape_timer &164e de e8 22 DEC &22e8,X ; monsters_escape_timer &1651 a9 30 LDA #&30 # and resets the clock on the monster being trapped &1653 9d f0 22 STA &22f0,X ; monsters_trapped_timer &1656 bd e8 22 LDA &22e8,X ; monsters_escape_timer &1659 c9 1a CMP #&1a # Three fills are required to bury the monster &165b d0 2b BNE &1688 ; leave &165d a9 05 LDA #&05 ; PLAYER_FILLED_MONSTER # Tidy up final fill round &165f 85 2c STA &2c ; player_state &1661 a9 03 LDA #&03 ; MONSTER_FALLING &1663 95 2c STA &2c,X ; monsters_state # Mark the monster as falling &1665 a9 02 LDA #&02 &1667 85 39 STA &39 ; dig_or_fill_cooldown &1669 a9 18 LDA #&18 ; MONSTER_LEAD | MONSTER_TAIL # A single falling monster performs both functions &166b 9d 39 23 STA &2339,X ; monsters_flags &166e a9 00 LDA #&00 &1670 9d 01 23 STA &2301,X ; monsters_holes_passed_through &1673 8d cd 25 STA &25cd ; additional_falling_monsters # Only one monster falling to begin with &1676 8d ce 25 STA &25ce ; killed_monster_y &1679 a9 00 LDA #&00 &167b a2 02 LDX #&02 &167d 20 d2 1b JSR &1bd2 ; play_sound # Silence channel 2 &1680 a9 07 LDA #&07 &1682 20 d2 1b JSR &1bd2 ; play_sound # Play sound for buried monster &1685 20 cc 1e JSR &1ecc ; toggle_paused_flag_on_all_but_most_recently_filled_monster ; leave &1688 60 RTS ; not_at_end_of_filling &1689 18 CLC &168a 69 01 ADC #&01 &168c 29 03 AND #&03 &168e 85 39 STA &39 ; dig_or_fill_cooldown &1690 c9 03 CMP #&03 &1692 d0 f4 BNE &1688 ; leave &1694 20 ef 0f JSR &0fef ; toggle_player_frame &1697 60 RTS ; handle_monster_falling &1698 a6 38 LDX &38 ; monster_number &169a b5 14 LDA &14,X ; monsters_y &169c 18 CLC &169d 69 1b ADC #&1b &169f a2 23 LDX #&23 &16a1 20 4c 1e JSR &1e4c ; get_a_modulo_x &16a4 a6 38 LDX &38 ; monster_number &16a6 c9 00 CMP #&00 &16a8 f0 41 BEQ &16eb ; monster_is_level_with_platform &16aa c9 0a CMP #&0a &16ac d0 33 BNE &16e1 ; monster_is_in_mid_air # Has the monster just cleared a hole? &16ae bd 39 23 LDA &2339,X ; monsters_flags &16b1 29 08 AND #&08 ; MONSTER_TAIL &16b3 f0 2c BEQ &16e1 ; monster_is_in_mid_air # If so, is there another monster following this one? &16b5 b5 14 LDA &14,X ; monsters_y &16b7 18 CLC &16b8 69 08 ADC #&08 &16ba a8 TAY &16bb b5 0c LDA &0c,X ; monsters_x &16bd 38 SEC &16be e9 03 SBC #&03 &16c0 aa TAX &16c1 4a LSR A &16c2 4a LSR A &16c3 29 01 AND #&01 &16c5 49 01 EOR #&01 &16c7 18 CLC &16c8 69 26 ADC #&26 ; COLOUR_4_BRICKWORK_WITH_COLOUR_6_MORTAR # If not, replot platform where the hole was &16ca 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &16cd a6 38 LDX &38 ; monster_number &16cf bd 01 23 LDA &2301,X ; monsters_holes_passed_through &16d2 d0 0d BNE &16e1 ; monster_is_in_mid_air # Is this the hole the player was filling? &16d4 a9 02 LDA #&02 ; PLAYER_DIGGING # If so, change the player's state to reflect this &16d6 85 2c STA &2c ; player_state &16d8 a9 01 LDA #&01 &16da 8d db 22 STA &22db ; whether_player_pressed_dig_or_fill # Unnecessarily mark the player as filling &16dd a9 09 LDA #&09 ; COLOUR_1_HOLE_SECTION_ONE - 2 &16df 85 36 STA &36 ; hole_sprite_minus_one # Mark the player's hole as filled ; monster_is_in_mid_air &16e1 a6 38 LDX &38 ; monster_number &16e3 b5 14 LDA &14,X ; monsters_y &16e5 38 SEC &16e6 e9 05 SBC #&05 # Make the monster fall; seven frames between platforms &16e8 95 14 STA &14,X ; monsters_y &16ea 60 RTS ; monster_is_level_with_platform # If the monster is level with a platform, &16eb ad 39 23 LDA &2339 ; player_flags &16ee 09 20 ORA #&20 ; PLAYER_PAUSED # Prevent player from moving until monster dies &16f0 8d 39 23 STA &2339 ; player_flags &16f3 fe 01 23 INC &2301,X ; monsters_holes_passed_through &16f6 bd 39 23 LDA &2339,X ; monsters_flags &16f9 29 10 AND #&10 ; MONSTER_LEAD &16fb d0 03 BNE &1700 ; monster_is_leading_monster &16fd 4c af 17 JMP &17af ; monster_isn't_leading_monster ; monster_is_leading_monster # If this is the first monster through the hole, &1700 b5 14 LDA &14,X ; monsters_y &1702 38 SEC &1703 e9 14 SBC #&14 # Consider a pixel four pixels below the monster &1705 a8 TAY &1706 b5 0c LDA &0c,X ; monsters_x &1708 38 SEC &1709 e9 04 SBC #&04 # on the monster's left &170b aa TAX &170c 20 6d 29 JSR &296d ; get_screen_colour_at_position &170f 49 08 EOR #&08 &1711 8d cd 22 STA &22cd ; falling_onto_hole_left_pixel_colour # (&0 = ladder, &c platform, &d hole) &1714 8a TXA &1715 18 CLC &1716 69 07 ADC #&07 # and a second, on the monster's right &1718 aa TAX &1719 20 6d 29 JSR &296d ; get_screen_colour_at_position &171c 49 08 EOR #&08 &171e 2d cd 22 AND &22cd ; falling_onto_hole_left_pixel_colour # (&0 = ladder, &c platform, &d hole) &1721 29 0d AND #&0d &1723 c9 0d CMP #&0d &1725 d0 16 BNE &173d ; monster_didn't_land_on_another_hole &1727 a6 38 LDX &38 ; monster_number # Is this either a fully dug or a two dig hole? &1729 b5 14 LDA &14,X ; monsters_y &172b 38 SEC &172c e9 11 SBC #&11 &172e a8 TAY &172f b5 0c LDA &0c,X ; monsters_x &1731 38 SEC &1732 e9 03 SBC #&03 &1734 aa TAX &1735 a9 9c LDA #&9c ; COLOUR_0_BLOCK | AND_SPRITE # If so, remove the dug brickwork beneath the monster &1737 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &173a 4c e1 16 JMP &16e1 ; monster_is_in_mid_air # and continue their fall ; monster_didn't_land_on_another_hole &173d a6 38 LDX &38 ; monster_number &173f b5 14 LDA &14,X ; monsters_y &1741 38 SEC &1742 e9 11 SBC #&11 # Consider a pixel one pixel below the monster &1744 a8 TAY &1745 b5 0c LDA &0c,X ; monsters_x &1747 18 CLC &1748 69 03 ADC #&03 # on the monster's right &174a aa TAX &174b 20 6d 29 JSR &296d ; get_screen_colour_at_position &174e 49 08 EOR #&08 &1750 8d ce 22 STA &22ce ; falling_onto_hole_right_pixel_inverse &1753 8a TXA &1754 38 SEC &1755 e9 07 SBC #&07 # and another, on the monster's left &1757 aa TAX &1758 20 6d 29 JSR &296d ; get_screen_colour_at_position &175b 49 08 EOR #&08 &175d 2d ce 22 AND &22ce ; falling_onto_hole_right_pixel_inverse &1760 29 0d AND #&0d &1762 c9 0d CMP #&0d &1764 d0 05 BNE &176b ; monster_landed_on_platform ; monster_landed_on_one_dig_hole # If the monster landed on a one dig hole, &1766 a9 0b LDA #&0b ; COLOUR_1_HOLE_SECTION_ONE &1768 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # fill it in ; monster_landed_on_platform &176b a9 00 LDA #&00 ; MONSTERS # Did the monster land on any other monster? &176d a2 01 LDX #&01 # (aligned with it horizontally) &176f a0 14 LDY #&14 &1771 20 b6 1a JSR &1ab6 ; check_for_monsters_or_player_in_proximity &1774 f0 43 BEQ &17b9 ; monster_didn't_hit_other_monster_in_hole &1776 b5 2c LDA &2c,X ; monsters_state &1778 c9 02 CMP #&02 ; MONSTER_TRAPPED # If so, was that monster trapped? &177a d0 3d BNE &17b9 ; monster_didn't_hit_other_monster_in_hole &177c bd e8 22 LDA &22e8,X ; monsters_escape_timer &177f c9 34 CMP #&34 # and not just about to escape? &1781 b0 36 BCS &17b9 ; monster_didn't_hit_other_monster_in_hole &1783 a9 03 LDA #&03 ; MONSTER_FALLING &1785 95 2c STA &2c,X ; monsters_state # If so, set the other monster falling &1787 a9 10 LDA #&10 ; MONSTER_LEAD &1789 9d 39 23 STA &2339,X ; monsters_flags # and give it the lead &178c a9 00 LDA #&00 &178e 9d 01 23 STA &2301,X ; monsters_holes_passed_through &1791 a4 38 LDY &38 ; monster_number &1793 b9 39 23 LDA &2339,Y ; monsters_flags &1796 29 ef AND #&ef ; !MONSTER_LEAD # removing the lead from the first monster &1798 99 39 23 STA &2339,Y ; monsters_flags &179b b9 14 00 LDA &0014,Y ; monsters_y &179e 38 SEC &179f e9 14 SBC #&14 &17a1 95 14 STA &14,X ; monsters_y &17a3 ee cd 25 INC &25cd ; additional_falling_monsters # Note that another monster is falling &17a6 a9 00 LDA #&00 &17a8 aa TAX &17a9 20 d2 1b JSR &1bd2 ; play_sound # Silence channel zero &17ac 4c e1 16 JMP &16e1 ; monster_is_in_mid_air # and keep continue the first monster's fall ; monster_isn't_leading_monster &17af b5 14 LDA &14,X ; monsters_y # If this isn't the first monster to fall, &17b1 cd ce 25 CMP &25ce ; killed_monster_y # has it reached the platform where the first died? &17b4 f0 64 BEQ &181a ; kill_monster # (the first monster may not have died yet) &17b6 4c e1 16 JMP &16e1 ; monster_is_in_mid_air # If not, keep the monster falling ; monster_didn't_hit_other_monster_in_hole &17b9 a9 00 LDA #&00 ; MONSTERS # Did the monster land on any other monster? &17bb a2 08 LDX #&08 # (running or partially trapped and misaligned) &17bd a0 08 LDY #&08 &17bf 20 b6 1a JSR &1ab6 ; check_for_monsters_or_player_in_proximity &17c2 f0 1c BEQ &17e0 ; monster_didn't_hit_other_monster &17c4 b5 2c LDA &2c,X ; monsters_state &17c6 c9 02 CMP #&02 ; MONSTER_TRAPPED # If the other monster is partially trapped, &17c8 d0 03 BNE &17cd ; hit_monster_wasn't_trapped # note this, so the platform can be later repaired &17ca ee 7f 27 INC &277f ; monster_hit_misaligned_partially_trapped_monster ; hit_monster_wasn't_trapped &17cd bd 39 23 LDA &2339,X ; monsters_flags &17d0 29 df AND #&df ; !MONSTER_PAUSED # Unpause the other monster so that it can die &17d2 9d 39 23 STA &2339,X ; monsters_flags &17d5 a9 05 LDA #&05 ; MONSTER_REMOVED &17d7 95 2c STA &2c,X ; monsters_state # Mark the other monster as removed &17d9 a9 7f LDA #&7f &17db 95 24 STA &24,X ; monsters_sprite # and set its sprite so that it won't be plotted &17dd 4c 1a 18 JMP &181a ; kill_monster ; monster_didn't_hit_other_monster # If the monster merely landed on a platform, &17e0 a6 38 LDX &38 ; monster_number &17e2 bd 01 23 LDA &2301,X ; monsters_holes_passed_through &17e5 d5 63 CMP &63,X ; monsters_type &17e7 b0 31 BCS &181a ; kill_monster # Did it fall far enough to kill it? ; monster_survived_holes &17e9 ad cd 25 LDA &25cd ; additional_falling_monsters &17ec d0 2c BNE &181a ; kill_monster # If not, are there other monsters also falling? &17ee a9 00 LDA #&00 &17f0 9d 01 23 STA &2301,X ; monsters_holes_passed_through # If not, the monster survives; reset it &17f3 8d 39 23 STA &2339 ; player_flags &17f6 20 cc 1e JSR &1ecc ; toggle_paused_flag_on_all_but_most_recently_filled_monster &17f9 20 61 1f JSR &1f61 ; silence_channels_two_and_three &17fc a6 38 LDX &38 ; monster_number &17fe 20 6a 13 JSR &136a ; generate_random_number &1801 29 04 AND #&04 # Set it running in a random direction &1803 38 SEC &1804 e9 02 SBC #&02 &1806 95 1c STA &1c,X ; monsters_direction &1808 d6 14 DEC &14,X ; monsters_y &180a b5 24 LDA &24,X ; monsters_sprite &180c 29 fd AND #&fd # Set its sprite back to the untrapped version &180e 95 24 STA &24,X ; monsters_sprite &1810 a9 00 LDA #&00 ; MONSTER_RUNNING &1812 95 2c STA &2c,X ; monsters_state &1814 a9 06 LDA #&06 &1816 20 d2 1b JSR &1bd2 ; play_sound # Play a sound for the monster surviving the fall &1819 60 RTS ; kill_monster # If the monster has died as a result of its fall, &181a a6 38 LDX &38 ; monster_number &181c b5 14 LDA &14,X ; monsters_y &181e 8d ce 25 STA &25ce ; killed_monster_y &1821 ce cd 25 DEC &25cd ; additional_falling_monsters # Are there further monsters to follow? &1824 10 41 BPL &1867 ; mark_monster_as_dead_and_unplotted &1826 20 61 1f JSR &1f61 ; silence_channels_two_and_three # If not, ; score_points_for_killed_monsters &1829 a9 00 LDA #&00 &182b 8d 21 23 STA &2321 ; points_value &182e a2 07 LDX #&07 ; score_points_for_killed_monsters_loop # calculate the score for all the monsters involved &1830 bd 39 23 LDA &2339,X ; monsters_flags &1833 29 60 AND #&60 ; MONSTER_KILLED | MONSTER_PAUSED &1835 d0 1d BNE &1854 ; consider_next_monster &1837 bd 01 23 LDA &2301,X ; monsters_holes_passed_through # Look up (holes passed through * 4) + monster type &183a 0a ASL A &183b 0a ASL A &183c 18 CLC &183d 75 63 ADC &63,X ; monsters_type &183f a8 TAY &1840 b9 09 23 LDA &2309,Y ; points_table # in the scoring table &1843 f8 SED &1844 18 CLC &1845 6d 21 23 ADC &2321 ; points_value &1848 8d 21 23 STA &2321 ; points_value # and add to the total score &184b d8 CLD &184c a9 00 LDA #&00 &184e 9d 01 23 STA &2301,X ; monsters_holes_passed_through &1851 ce 37 23 DEC &2337 ; number_of_monsters_still_alive_plus_one # One fewer monster left ; consider_next_monster &1854 ca DEX &1855 d0 d9 BNE &1830 ; score_points_for_killed_monsters_loop &1857 a6 38 LDX &38 ; monster_number # Set the last monster into a points display &1859 a9 04 LDA #&04 ; MONSTER_POINTS &185b 95 2c STA &2c,X ; monsters_state &185d a9 7f LDA #&7f &185f 95 24 STA &24,X ; monsters_sprite &1861 a9 08 LDA #&08 &1863 20 d2 1b JSR &1bd2 ; play_sound # Play a sound for killing it &1866 60 RTS ; mark_monster_as_dead_and_unplotted &1867 a9 05 LDA #&05 ; MONSTER_REMOVED &1869 95 2c STA &2c,X ; monsters_state &186b a9 7f LDA #&7f &186d 95 24 STA &24,X ; monsters_sprite &186f 60 RTS ; handle_player_filled_monster # Tidy up final fill round &1870 a5 39 LDA &39 ; dig_or_fill_cooldown &1872 d0 03 BNE &1877 ; not_at_end_of_fill &1874 4c 80 0f JMP &0f80 ; turn_player_depending_on_pressed_keys ; not_at_end_of_fill &1877 c9 02 CMP #&02 &1879 d0 03 BNE &187e ; skip_toggling_frame &187b 20 ef 0f JSR &0fef ; toggle_player_frame ; skip_toggling_frame &187e e6 39 INC &39 ; dig_or_fill_cooldown &1880 a5 39 LDA &39 ; dig_or_fill_cooldown &1882 29 03 AND #&03 &1884 85 39 STA &39 ; dig_or_fill_cooldown &1886 60 RTS ; handle_monster_points &1887 20 f9 11 JSR &11f9 ; wait_for_vsync &188a 20 3b 14 JSR &143b ; plot_monsters_and_player # Unnecessary replot &188d 58 CLI &188e ad 7f 27 LDA &277f ; monster_hit_misaligned_partially_trapped_monster &1891 f0 03 BEQ &1896 ; skip_platform_repair &1893 20 f2 21 JSR &21f2 ; repair_platform_for_squashed_partially_trapped_misaligned_monster ; skip_platform_repair &1896 a6 38 LDX &38 ; monster_number &1898 b5 0c LDA &0c,X ; monsters_x &189a 38 SEC &189b e9 09 SBC #&09 &189d ac 21 23 LDY &2321 ; points_value &18a0 c0 10 CPY #&10 &18a2 90 03 BCC &18a7 ; not_four_digits # If the player scored 1000 points or more, &18a4 18 CLC &18a5 69 02 ADC #&02 # change the position to allow for the extra digit ; not_four_digits &18a7 8d 22 23 STA &2322 ; points_x &18aa b4 14 LDY &14,X ; monsters_y &18ac 8c 23 23 STY &2323 ; points_y &18af aa TAX &18b0 ad 21 23 LDA &2321 ; points_value &18b3 20 30 19 JSR &1930 ; plot_number_as_sprite # Plot points &18b6 a9 00 LDA #&00 &18b8 20 30 19 JSR &1930 ; plot_number_as_sprite &18bb a2 32 LDX #&32 &18bd 20 71 1f JSR &1f71 ; delay_for_x # Pause for a while &18c0 ae 22 23 LDX &2322 ; points_x &18c3 ac 23 23 LDY &2323 ; points_y &18c6 ad 21 23 LDA &2321 ; points_value &18c9 20 30 19 JSR &1930 ; plot_number_as_sprite # Unplot points &18cc a9 00 LDA #&00 &18ce 20 30 19 JSR &1930 ; plot_number_as_sprite &18d1 a2 00 LDX #&00 &18d3 ac 21 23 LDY &2321 ; points_value &18d6 20 6e 19 JSR &196e ; increase_score # Increase the player's score accordingly &18d9 a2 07 LDX #&07 ; remove_flag_loop # Unpause all monsters &18db bd 39 23 LDA &2339,X ; monsters_flags &18de 29 df AND #&df ; !MONSTER_PAUSED &18e0 9d 39 23 STA &2339,X ; monsters_flags &18e3 b5 2c LDA &2c,X ; monsters_state &18e5 c9 04 CMP #&04 ; MONSTER_POINTS # Mark any monsters that are MONSTER_POINTS or &18e7 90 05 BCC &18ee ; monster_not_killed # MONSTER_removed as having been killed &18e9 a9 40 LDA #&40 ; MONSTER_KILLED &18eb 9d 39 23 STA &2339,X ; monsters_flags ; monster_not_killed &18ee ca DEX &18ef 10 ea BPL &18db ; remove_flag_loop &18f1 ad 37 23 LDA &2337 ; number_of_monsters_still_alive_plus_one &18f4 c9 01 CMP #&01 &18f6 f0 01 BEQ &18f9 ; finish_stage # If all the monsters are dead, finish the stage &18f8 60 RTS ; finish_stage &18f9 20 6f 1f JSR &1f6f ; delay_for_32 &18fc ae 28 23 LDX &2328 ; oxygen_as_numbers_low &18ff ac 29 23 LDY &2329 ; oxygen_as_numbers_high &1902 20 6e 19 JSR &196e ; increase_score # Score points for remaining oxygen &1905 ae 38 23 LDX &2338 ; stack_pointer_at_start_of_stage &1908 9a TXS # Reset stack pointer, meaning RTS will leave play_stage &1909 e6 01 INC &01 ; stage_number &190b a5 01 LDA &01 ; stage_number &190d c9 04 CMP #&04 # On stage 4 and afterwards, &190f d0 07 BNE &1918 ; not_stage_four &1911 a9 02 LDA #&02 : GREEN # the second monster is green &1913 8d a6 22 STA &22a6 ; monsters_starting_type + 2 &1916 d0 0e BNE &1926 ; increase_oxygen ; not_stage_four &1918 c9 07 CMP #&07 # On stage 7 and afterwards, &191a d0 13 BNE &192f ; not_stage_seven &191c a9 03 LDA #&03 ; WHITE # the third monster is white &191e 8d a7 22 STA &22a7 ; monsters_starting_type + 3 &1921 a9 03 LDA #&03 # and the game is 50% faster &1923 8d 45 23 STA &2345 ; number_of_monsters_to_update_per_frame ; increase_oxygen &1926 ad 44 23 LDA &2344 ; starting_oxygen_as_numbers_high # On stage 4 and stage 7, &1929 18 CLC &192a 69 10 ADC #&10 # the starting amount of oxygen increases by 1000 &192c 8d 44 23 STA &2344 ; starting_oxygen_as_numbers_high # but the oxygen drain increases by 10 too ; not_stage_seven &192f 60 RTS ; plot_number_as_sprite &1930 8d 24 23 STA &2324 ; number_value &1933 8e 25 23 STX &2325 ; number_x &1936 8c 26 23 STY &2326 ; number_y &1939 c9 00 CMP #&00 &193b f0 04 BEQ &1941 ; double_zero &193d c9 10 CMP #&10 &193f 90 0a BCC &194b ; single_digit ; double_zero &1941 4a LSR A &1942 4a LSR A &1943 4a LSR A &1944 4a LSR A &1945 18 CLC &1946 69 28 ADC #&28 ; DIGIT_0 &1948 20 fa 28 JSR &28fa ; plot_sprite_at_x_y ; single_digit &194b ad 25 23 LDA &2325 ; number_x &194e 18 CLC &194f 69 04 ADC #&04 &1951 aa TAX &1952 8e 25 23 STX &2325 ; number_x &1955 ac 26 23 LDY &2326 ; number_y &1958 ad 24 23 LDA &2324 ; number_value &195b 29 0f AND #&0f &195d 18 CLC &195e 69 28 ADC #&28 ; DIGIT_0 &1960 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &1963 ad 25 23 LDA &2325 ; number_x &1966 18 CLC &1967 69 04 ADC #&04 &1969 aa TAX &196a ac 26 23 LDY &2326 ; number_y &196d 60 RTS ; increase_score &196e f8 SED &196f 18 CLC &1970 8a TXA &1971 65 02 ADC &02 ; score_one &1973 85 02 STA &02 ; score_one &1975 98 TYA &1976 65 03 ADC &03 ; score_two &1978 85 03 STA &03 ; score_two &197a a9 00 LDA #&00 &197c 65 04 ADC &04 ; score_three &197e 85 04 STA &04 ; score_three &1980 d8 CLD &1981 20 a2 19 JSR &19a2 ; write_score_in_stage &1984 ad 92 25 LDA &2592 ; extra_life_gained &1987 d0 18 BNE &19a1 ; leave &1989 a5 03 LDA &03 ; score_two &198b c9 30 CMP #&30 # Gain an extra life when the player scores 3000 points &198d 90 12 BCC &19a1 ; leave &198f 20 be 1b JSR &1bbe ; plot_life_sprite &1992 a9 0a LDA #&0a &1994 20 d2 1b JSR &1bd2 ; play_sound # Play a sound for gaining an extra life &1997 20 6f 1f JSR &1f6f ; delay_for_32 &199a e6 00 INC &00 ; player_lives &199c a9 ff LDA #&ff &199e 8d 92 25 STA &2592 ; extra_life_gained &19a1 60 RTS ; write_score_in_stage &19a2 a9 20 LDA #&20 ; " " &19a4 8d 7c 27 STA &277c ; padding_character &19a7 a9 11 LDA #&11 # COLOUR 1 &19a9 20 ee ff JSR &ffee ; OSWRCH &19ac a9 01 LDA #&01 &19ae 20 ee ff JSR &ffee ; OSWRCH &19b1 a9 1f LDA #&1f # TAB(&07, &01) &19b3 20 ee ff JSR &ffee ; OSWRCH &19b6 a9 07 LDA #&07 &19b8 20 ee ff JSR &ffee ; OSWRCH &19bb a9 01 LDA #&01 &19bd 20 ee ff JSR &ffee ; OSWRCH ; write_score &19c0 a9 02 LDA #&02 # 3 bytes, 6 digits &19c2 85 78 STA &78 ; numbers_address_low &19c4 a9 00 LDA #&00 ; &0002 = score_one &19c6 85 79 STA &79 ; numbers_address_high &19c8 a0 02 LDY #&02 ; write_numbers &19ca a9 80 LDA #&80 &19cc 8d 27 23 STA &2327 ; using_padding_character ; write_numbers_loop &19cf b1 78 LDA (&78),Y ; numbers_address &19d1 4a LSR A &19d2 4a LSR A &19d3 4a LSR A &19d4 4a LSR A &19d5 20 ea 19 JSR &19ea ; write_digit &19d8 c0 00 CPY #&00 &19da d0 03 BNE &19df ; skip_stop_using_padding &19dc 8c 27 23 STY &2327 ; using_padding_character # Stop using padding character for second byte onwards ; skip_stop_using_padding &19df b1 78 LDA (&78),Y ; numbers_address &19e1 29 0f AND #&0f &19e3 20 ea 19 JSR &19ea ; write_digit &19e6 88 DEY &19e7 10 e6 BPL &19cf ; write_numbers_loop &19e9 60 RTS ; write_digit &19ea d0 0a BNE &19f6 ; use_digit &19ec 2c 27 23 BIT &2327 ; using_padding_character &19ef 10 05 BPL &19f6 ; use_digit &19f1 ad 7c 27 LDA &277c ; padding_character &19f4 d0 09 BNE &19ff ; use_padding_character ; use_digit &19f6 48 PHA &19f7 a9 00 LDA #&00 &19f9 8d 27 23 STA &2327 ; using_padding_character &19fc 68 PLA ; digit &19fd 09 30 ORA #&30 ; use_padding_character &19ff 4c ee ff JMP &ffee ; OSWRCH ; update_oxygen &1a02 a9 30 LDA #&30 &1a04 8d 2c 23 STA &232c ; actual_oxygen_low &1a07 ce 2b 23 DEC &232b ; actual_oxygen_high &1a0a ad 2b 23 LDA &232b ; actual_oxygen_high &1a0d c9 14 CMP #&14 &1a0f b0 0c BCS &1a1d ; update_oxygen_numbers # Is the player's oxygen in the red? &1a11 c9 10 CMP #&10 &1a13 90 1f BCC &1a34 ; update_oxygen_bar # If so, then four times &1a15 a9 09 LDA #&09 &1a17 20 d2 1b JSR &1bd2 ; play_sound # Play sound for low oxygen warning &1a1a 4c 34 1a JMP &1a34 ; update_oxygen_bar ; update_oxygen_numbers &1a1d f8 SED &1a1e 38 SEC &1a1f ad 28 23 LDA &2328 ; oxygen_as_numbers_low &1a22 ed 2a 23 SBC &232a ; oxygen_as_numbers_drain &1a25 8d 28 23 STA &2328 ; oxygen_as_numbers_low &1a28 ad 29 23 LDA &2329 ; oxygen_as_numbers_high &1a2b e9 00 SBC #&00 &1a2d 8d 29 23 STA &2329 ; oxygen_as_numbers_high &1a30 d8 CLD &1a31 20 68 1a JSR &1a68 ; plot_oxygen_numbers ; update_oxygen_bar &1a34 ad 2b 23 LDA &232b ; actual_oxygen_high # Every &0400 of actual oxygen &1a37 29 03 AND #&03 # (i.e. 80/120/160 in numbers) &1a39 d0 2c BNE &1a67 ; leave &1a3b a0 07 LDY #&07 &1a3d a9 f3 LDA #&f3 ; two pixels of colour 14 ; update_oxygen_bar_loop &1a3f 91 7a STA (&7a),Y ; oxygen_bar_screen_address # Remove two pixels of oxygen &1a41 88 DEY &1a42 10 fb BPL &1a3f ; update_oxygen_bar_loop &1a44 38 SEC &1a45 a5 7a LDA &7a ; oxygen_bar_screen_address_low &1a47 e9 08 SBC #&08 &1a49 85 7a STA &7a ; oxygen_bar_screen_address_low &1a4b b0 02 BCS &1a4f &1a4d c6 7b DEC &7b ; oxygen_bar_screen_address_high &1a4f ad 2b 23 LDA &232b ; actual_oxygen_high &1a52 d0 13 BNE &1a67 ; leave # If the player has run out of actual oxygen, kill them &1a54 20 59 21 JSR &2159 ; kill_player_by_asphyxiation ; kill_player &1a57 a2 64 LDX #&64 &1a59 20 71 1f JSR &1f71 ; delay_for_x &1a5c a9 01 LDA #&01 # Note that the player failed the stage &1a5e 85 05 STA &05 ; player_died &1a60 c6 00 DEC &00 ; player_lives &1a62 ae 38 23 LDX &2338 ; stack_pointer_at_start_of_stage &1a65 9a TXS # Reset stack pointer, meaning RTS will leave play_stage &1a66 60 RTS ; leave &1a67 60 RTS ; plot_oxygen_numbers &1a68 a9 11 LDA #&11 # COLOUR 0 &1a6a 20 ee ff JSR &ffee ; OSWRCH &1a6d a9 00 LDA #&00 &1a6f 20 ee ff JSR &ffee ; OSWRCH &1a72 a9 1f LDA #&1f # TAB(&08, &1e) &1a74 20 ee ff JSR &ffee ; OSWRCH &1a77 a9 08 LDA #&08 &1a79 20 ee ff JSR &ffee ; OSWRCH &1a7c a9 1e LDA #&1e &1a7e 20 ee ff JSR &ffee ; OSWRCH &1a81 a9 28 LDA #&28 &1a83 85 78 STA &78 ; numbers_address_low &1a85 a9 23 LDA #&23 ; &2328 = oxygen_as_numbers &1a87 85 79 STA &79 ; numbers_address_high &1a89 a9 20 LDA #&20 ; " " &1a8b 8d 7c 27 STA &277c ; padding_character &1a8e a0 01 LDY #&01 # 2 bytes, 4 digits &1a90 4c ca 19 JMP &19ca ; write_numbers ; player_is_filling_monster_in_old_hole &1a93 a9 05 LDA #&05 ; PLAYER_FILLED_MONSTER &1a95 85 2c STA &2c ; player_state &1a97 bd f0 22 LDA &22f0,X ; monsters_trapped_timer # If the monster in the hole isn't emerging, &1a9a f0 09 BEQ &1aa5 ; monster_is_emerging &1a9c bd e8 22 LDA &22e8,X ; monsters_escape_timer &1a9f c9 21 CMP #&21 &1aa1 b0 02 BCS &1aa5 ; monster_is_emerging &1aa3 c6 2c DEC &2c ; player_state ; PLAYER_FILLING_MONSTER # Set the player filling a monster ; monster_is_emerging &1aa5 a9 00 LDA #&00 &1aa7 85 39 STA &39 ; dig_or_fill_cooldown &1aa9 a5 24 LDA &24 ; player_sprite &1aab 29 02 AND #&02 &1aad 18 CLC &1aae 69 06 ADC #&06 ; PLAYER_DIGGING_LEFT &1ab0 85 24 STA &24 ; player_sprite &1ab2 8e e7 22 STX &22e7 ; most_recently_filled_monster # and note this monster as the one to be filled &1ab5 60 RTS ; check_for_monsters_or_player_in_proximity &1ab6 8e 41 23 STX &2341 ; check_x_proximity &1ab9 8c 42 23 STY &2342 ; check_y_proximity &1abc a2 ff LDX #&ff &1abe 8e 7b 27 STX &277b ; found_monster &1ac1 a4 38 LDY &38 ; monster_number &1ac3 c9 01 CMP #&01 # A = 1 to consider if player is in proximity &1ac5 f0 0a BEQ &1ad1 ; set_maximum_monster_to_check_plus_one # A = 0 to consider if any monsters are in proximity &1ac7 ad 36 23 LDA &2336 ; number_of_monsters_plus_one &1aca 8d 43 23 STA &2343 ; maximum_monster_to_check_plus_one &1acd a2 01 LDX #&01 &1acf d0 05 BNE &1ad6 ; check_for_monsters_or_player_in_proximity_loop ; set_maximum_monster_to_check_plus_one &1ad1 8d 43 23 STA &2343 ; maximum_monster_to_check_plus_one &1ad4 a2 00 LDX #&00 ; check_for_monsters_or_player_in_proximity_loop &1ad6 e4 38 CPX &38 ; monster_number &1ad8 f0 43 BEQ &1b1d ; check_next_monster &1ada bd 39 23 LDA &2339,X ; monsters_flags &1add 29 40 AND #&40 ; MONSTER_KILLED &1adf d0 3c BNE &1b1d ; check_next_monster # Don't consider monsters that have been killed &1ae1 ad d5 22 LDA &22d5 ; check_x &1ae4 18 CLC &1ae5 79 dd 22 ADC &22dd,Y ; monsters_x_offset &1ae8 8d cf 22 STA &22cf ; offset_check_x &1aeb b5 0c LDA &0c,X ; monsters_x &1aed 18 CLC &1aee 7d dd 22 ADC &22dd,X ; monsters_x_offset &1af1 38 SEC &1af2 ed cf 22 SBC &22cf ; offset_check_x &1af5 b0 04 BCS &1afb ; skip_x_inversion &1af7 49 ff EOR #&ff &1af9 69 01 ADC #&01 ; skip_x_inversion &1afb cd 41 23 CMP &2341 ; check_x_proximity &1afe b0 1d BCS &1b1d ; check_next_monster &1b00 b5 14 LDA &14,X ; monsters_y &1b02 38 SEC &1b03 ed d6 22 SBC &22d6 ; check_y &1b06 b0 04 BCS &1b0c ; skip_y_inversion &1b08 49 ff EOR #&ff &1b0a 69 01 ADC #&01 ; skip_y_inversion &1b0c cd 42 23 CMP &2342 ; check_y_proximity &1b0f b0 0c BCS &1b1d ; check_next_monster &1b11 8e 7b 27 STX &277b ; found_monster &1b14 b5 2c LDA &2c,X ; monsters_state &1b16 c9 02 CMP #&02 ; MONSTER_CLIMBING # Prioritise climbing monsters &1b18 d0 03 BNE &1b1d ; check_next_monster ; leave_with_minus_one &1b1a a9 ff LDA #&ff # Return minus one if a monster is in proximity &1b1c 60 RTS ; check_next_monster &1b1d e8 INX &1b1e ec 43 23 CPX &2343 ; maximum_monster_to_check_plus_one &1b21 d0 b3 BNE &1ad6 ; check_for_monsters_or_player_in_proximity_loop &1b23 ae 7b 27 LDX &277b ; found_monster &1b26 10 f2 BPL &1b1a ; leave_with_minus_one &1b28 a9 00 LDA #&00 # Return zero if no monster is in proximity &1b2a 60 RTS ; set_colour_x_to_y &1b2b a9 13 LDA #&13 # VDU 19, X, Y, 0, 0, 0 &1b2d 20 ee ff JSR &ffee ; OSWRCH &1b30 8a TXA &1b31 20 ee ff JSR &ffee ; OSWRCH &1b34 98 TYA &1b35 20 ee ff JSR &ffee ; OSWRCH &1b38 a9 00 LDA #&00 &1b3a 20 ee ff JSR &ffee ; OSWRCH &1b3d 20 ee ff JSR &ffee ; OSWRCH &1b40 4c ee ff JMP &ffee ; OSWRCH ; start_player_falling_through_hole &1b43 a5 0c LDA &0c ; player_x &1b45 18 CLC &1b46 65 1c ADC &1c ; player_direction # Move player over hole &1b48 85 0c STA &0c ; player_x &1b4a a5 24 LDA &24 ; player_sprite &1b4c 85 37 STA &37 ; player_sprite_on_entering_hole &1b4e a9 0a LDA #&0a ; PLAYER_FALLING # Set player sprite to be falling &1b50 85 24 STA &24 ; player_sprite &1b52 a5 14 LDA &14 ; player_y &1b54 38 SEC &1b55 e9 10 SBC #&10 &1b57 a8 TAY &1b58 a6 0c LDX &0c ; player_x &1b5a 8a TXA &1b5b 4a LSR A &1b5c 4a LSR A &1b5d 29 01 AND #&01 &1b5f 38 SEC &1b60 e9 10 SBC #&10 &1b62 49 ff EOR #&ff &1b64 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Remove the dug brickwork beneath the player &1b67 a5 14 LDA &14 ; player_y &1b69 38 SEC &1b6a e9 07 SBC #&07 # Move player into hole &1b6c 85 14 STA &14 ; player_y &1b6e a9 03 LDA #&03 ; PLAYER_FALLING &1b70 85 2c STA &2c ; player_state &1b72 60 RTS ; initialise_platforms_and_ladders &1b73 20 68 1a JSR &1a68 ; plot_oxygen_numbers &1b76 20 2f 1e JSR &1e2f ; plot_oxygen_bar &1b79 20 f7 1b JSR &1bf7 ; set_colours &1b7c 20 c6 1d JSR &1dc6 ; plot_platforms &1b7f 20 06 1d JSR &1d06 ; initialise_ladders &1b82 a2 04 LDX #&04 # Make platforms visible &1b84 a0 02 LDY #&02 &1b86 20 2b 1b JSR &1b2b ; set_colour_x_to_y &1b89 a2 19 LDX #&19 &1b8b 20 71 1f JSR &1f71 ; delay_for_x &1b8e a2 08 LDX #&08 # Make ladders visible &1b90 a0 05 LDY #&05 &1b92 20 2b 1b JSR &1b2b ; set_colour_x_to_y &1b95 a2 19 LDX #&19 &1b97 20 71 1f JSR &1f71 ; delay_for_x &1b9a a5 05 LDA &05 ; player_died &1b9c f0 11 BEQ &1baf ; skip_removing_life &1b9e ad 47 23 LDA &2347 ; x_position_of_next_life # If the player died, &1ba1 38 SEC &1ba2 e9 08 SBC #&08 &1ba4 8d 47 23 STA &2347 ; x_position_of_next_life &1ba7 aa TAX &1ba8 a0 fb LDY #&fb &1baa a9 35 LDA #&35 ; COLOUR_2_PLAYER_LIFE &1bac 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # unplot the last of their lives ; skip_removing_life &1baf a9 00 LDA #&00 &1bb1 85 05 STA &05 ; player_died &1bb3 20 f9 11 JSR &11f9 ; wait_for_vsync &1bb6 20 3b 14 JSR &143b ; plot_monsters_and_player &1bb9 58 CLI &1bba 20 6f 1f JSR &1f6f ; delay_for_32 &1bbd 60 RTS ; plot_life_sprite &1bbe a9 35 LDA #&35 ; COLOUR_2_PLAYER_LIFE &1bc0 ae 47 23 LDX &2347 ; x_position_of_next_life &1bc3 a0 fb LDY #&fb &1bc5 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &1bc8 ad 47 23 LDA &2347 ; x_position_of_next_life &1bcb 18 CLC &1bcc 69 08 ADC #&08 &1bce 8d 47 23 STA &2347 ; x_position_of_next_life &1bd1 60 RTS ; play_sound &1bd2 c9 00 CMP #&00 &1bd4 d0 10 BNE &1be6 ; not_sound_0 &1bd6 8a TXA &1bd7 18 CLC &1bd8 69 10 ADC #&10 # Flush channel; play sound immediately &1bda 8d 58 23 STA &2358 ; sound_0_channel &1bdd a2 58 LDX #&58 &1bdf a0 23 LDY #&23 ; &2358 = sound_0 &1be1 a9 07 LDA #&07 ; Generate a sound &1be3 4c f1 ff JMP &fff1 ; OSWORD ; not_sound_0 &1be6 0a ASL A &1be7 0a ASL A &1be8 0a ASL A &1be9 18 CLC &1bea 69 58 ADC #&58 &1bec aa TAX &1bed a9 00 LDA #&00 &1bef 69 23 ADC #&23 ; &2358 = sounds &1bf1 a8 TAY &1bf2 a9 07 LDA #&07 ; Generate a sound &1bf4 4c f1 ff JMP &fff1 ; OSWORD ; set_colours &1bf7 a2 0f LDX #&0f ; set_colours_loop &1bf9 bc 48 23 LDY &2348,X ; colour_table &1bfc 20 2b 1b JSR &1b2b ; set_colour_x_to_y &1bff ca DEX &1c00 10 f7 BPL &1bf9 ; set_colours_loop &1c02 60 RTS ; handle_monster_trapped &1c03 a6 38 LDX &38 ; monster_number &1c05 bd f0 22 LDA &22f0,X ; monsters_trapped_timer &1c08 f0 1d BEQ &1c27 ; monster_is_escaping_hole # If the monster is still trapped in the hole, &1c0a de f0 22 DEC &22f0,X ; monsters_trapped_timer # move it closer to starting to escaping &1c0d bd f0 22 LDA &22f0,X ; monsters_trapped_timer &1c10 d0 06 BNE &1c18 ; alternate_sound # If the monster is about to escape, silence channel 2 &1c12 a9 00 LDA #&00 &1c14 a2 02 LDX #&02 &1c16 d0 06 BNE &1c1e ; trapped_sound ; alternate_sound &1c18 29 01 AND #&01 # Otherwise, every two frames, &1c1a d0 07 BNE &1c23 ; skip_sound &1c1c a9 04 LDA #&04 ; trapped_sound &1c1e 20 d2 1b JSR &1bd2 ; play_sound # play a sound for the monster being trapped &1c21 a6 38 LDX &38 ; monster_number ; skip_sound &1c23 a9 00 LDA #&00 &1c25 f0 1a BEQ &1c41 ; update_sprite # and leave after toggling the monster's frame ; monster_is_escaping_hole # If the monster is escaping the hole, &1c27 fe e8 22 INC &22e8,X ; monsters_escape_timer # move it closer to escaping completely &1c2a bd e8 22 LDA &22e8,X ; monsters_escape_timer &1c2d 29 01 AND #&01 &1c2f d0 f2 BNE &1c23 ; skip_sound # Every two frames, &1c31 a9 05 LDA #&05 &1c33 20 d2 1b JSR &1bd2 ; play_sound # Play a sound for the monster climbing out of the hole &1c36 a6 38 LDX &38 ; monster_number &1c38 bd e8 22 LDA &22e8,X ; monsters_escape_timer &1c3b c9 34 CMP #&34 &1c3d b0 0c BCS &1c4b ; monster_is_filling_hole_as_it_climbs_out &1c3f a9 01 LDA #&01 # Move the monster a pixel upwards (escape_timer < &34) ; update_sprite &1c41 18 CLC &1c42 6d d6 22 ADC &22d6 ; check_y &1c45 95 14 STA &14,X ; monsters_y &1c47 20 1d 16 JSR &161d ; toggle_monster_frame # Toggle the monster's frame every frame &1c4a 60 RTS ; monster_is_filling_hole_as_it_climbs_out &1c4b d0 1c BNE &1c69 ; monster_is_climbing_out_of_middle_or_topmost_part_of_hole ; monster_is_climbing_out_of_bottommost_part_of_hole # escape_timer = &34 &1c4d b5 24 LDA &24,X ; monsters_sprite &1c4f 29 fd AND #&fd # Set the monster back to being uninverted &1c51 95 24 STA &24,X ; monsters_sprite &1c53 ad d6 22 LDA &22d6 ; check_y &1c56 38 SEC &1c57 e9 09 SBC #&09 &1c59 a8 TAY &1c5a a9 1f LDA #&1f ; COLOUR_4_HOLE_SECTION_THREE # Fill in the very bottom of the hole with solid green ; fill_hole_as_monster_climbs_out &1c5c 48 PHA &1c5d ad d5 22 LDA &22d5 ; check_x &1c60 38 SEC &1c61 e9 03 SBC #&03 &1c63 aa TAX &1c64 68 PLA ; sprite &1c65 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Plot part of the platform below the monster &1c68 60 RTS ; monster_is_climbing_out_of_middle_or_topmost_part_of_hole &1c69 c9 36 CMP #&36 &1c6b d0 17 BNE &1c84 ; ; monster_is_climbing_out_of_topmost_part_of_hole ; monster_is_climbing_out_of_middle_part_of_hole # escape_timer = &36 &1c6d 20 1d 16 JSR &161d ; toggle_monster_frame &1c70 ad d6 22 LDA &22d6 ; check_y &1c73 18 CLC &1c74 69 04 ADC #&04 &1c76 95 14 STA &14,X ; monsters_y &1c78 ad d6 22 LDA &22d6 ; check_y &1c7b 38 SEC &1c7c e9 09 SBC #&09 &1c7e a8 TAY &1c7f a9 20 LDA #&20 ; COLOUR_4_HOLE_SECTION_TWO # Fill in the middle part of the hole with solid green &1c81 4c 5c 1c JMP &1c5c ; fill_hole_as_monster_climbs_out ; monster_is_climbing_out_of_topmost_part_of_hole &1c84 20 1d 16 JSR &161d ; toggle_monster_frame # escape_timer = &38 &1c87 ad d6 22 LDA &22d6 ; check_y &1c8a 18 CLC &1c8b 69 03 ADC #&03 &1c8d 95 14 STA &14,X ; monsters_y &1c8f 38 SEC &1c90 e9 10 SBC #&10 &1c92 48 PHA &1c93 a8 TAY &1c94 a9 21 LDA #&21 ; COLOUR_4_HOLE_SECTION_ONE # Fill in the topmost part of the hole with solid green &1c96 20 5c 1c JSR &1c5c ; fill_hole_as_monster_climbs_out &1c99 68 PLA ; check_y - &0d &1c9a 48 PHA &1c9b a8 TAY &1c9c ad d5 22 LDA &22d5 ; check_x &1c9f 38 SEC &1ca0 e9 03 SBC #&03 &1ca2 48 PHA &1ca3 aa TAX &1ca4 a9 a4 LDA #&a4 ; COLOUR_14_BLOCK | AND_SPRITE &1ca6 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Remove any mortar remaining in undug part of platform &1ca9 68 PLA ; check_x - &03 &1caa aa TAX &1cab 68 PLA ; check_y - &0d &1cac a8 TAY &1cad 8a TXA &1cae 29 04 AND #&04 &1cb0 4a LSR A &1cb1 4a LSR A &1cb2 49 01 EOR #&01 &1cb4 69 22 ADC #&22 ; COLOUR_2_MORTAR &1cb6 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Replot mortar on repaired platform &1cb9 a6 38 LDX &38 ; monster_number &1cbb a9 00 LDA #&00 ; MONSTER_RUNNING &1cbd 95 2c STA &2c,X ; monsters_state # Set monster running &1cbf a9 00 LDA #&00 &1cc1 a2 00 LDX #&00 &1cc3 20 d2 1b JSR &1bd2 ; play_sound # Stop sound of monster climbing out &1cc6 a5 2c LDA &2c ; player_state &1cc8 c9 04 CMP #&04 ; PLAYER_FILLING_MONSTER | PLAYER_FILLED_MONSTER &1cca 90 19 BCC &1ce5 ; skip_resetting_player_dig_state # Was the player filling a monster? &1ccc a5 38 LDA &38 ; monster_number &1cce cd e7 22 CMP &22e7 ; most_recently_filled_monster &1cd1 d0 12 BNE &1ce5 ; skip_resetting_player_dig_state # If so, was it this monster? &1cd3 a9 02 LDA #&02 ; PLAYER_DIGGING &1cd5 85 2c STA &2c ; player_state # If so, set the player as digging an undug hole &1cd7 a5 24 LDA &24 ; player_sprite &1cd9 29 fe AND #&fe &1cdb 85 24 STA &24 ; player_sprite &1cdd a9 00 LDA #&00 &1cdf 85 39 STA &39 ; dig_or_fill_cooldown &1ce1 a9 09 LDA #&09 ; COLOUR_1_HOLE_SECTION_ONE - 2 &1ce3 85 36 STA &36 ; hole_sprite_minus_one ; skip_resetting_player_dig_state &1ce5 a5 01 LDA &01 ; stage_number &1ce7 c9 01 CMP #&01 &1ce9 f0 18 BEQ &1d03 ; skip_upgrading_monster # If this isn't the first stage, &1ceb a6 38 LDX &38 ; monster_number &1ced bd 39 23 LDA &2339,X ; monsters_flags # and the monster has MONSTER_FULLY_TRAPPED set, &1cf0 10 11 BPL &1d03 ; skip_upgrading_monster # (i.e. has climbed out of a fully dug hole) &1cf2 b5 63 LDA &63,X ; monsters_type &1cf4 c9 03 CMP #&03 ; WHITE &1cf6 f0 0b BEQ &1d03 ; skip_upgrading_monster # and the monster isn't already white, &1cf8 18 CLC &1cf9 69 01 ADC #&01 # then make the monster a hungrier type &1cfb 95 63 STA &63,X ; monsters_type &1cfd a8 TAY &1cfe b9 2d 23 LDA &232d,Y ; monster_type_to_sprite &1d01 95 24 STA &24,X ; monsters_sprite ; skip_upgrading_monster &1d03 4c 5c 13 JMP &135c ; update_monster_horizontal_position ; initialise_ladders &1d06 a2 08 LDX #&08 &1d08 20 49 1e JSR &1e49 ; get_random_number_within_range # Pick one of eight pre-defined ladder patterns &1d0b aa TAX &1d0c bc 0e 25 LDY &250e,X ; ladder_data_offset_table &1d0f 8c 2b 25 STY &252b ; ladder_data_offset &1d12 a0 00 LDY #&00 &1d14 8c 16 25 STY &2516 ; ladder_column ; consider_next_ladder &1d17 20 89 1d JSR &1d89 ; get_next_byte_of_ladder_data # If the top bit is not set, &1d1a 10 03 BPL &1d1f ; set_start_and_end_of_ladder # the first byte of ladder data defines the bottom &1d1c 4c b8 1d JMP &1db8 ; end_of_column_of_ladders # If the top bit is set, move to the next column ; set_start_and_end_of_ladder &1d1f 38 SEC &1d20 bd 1d 25 LDA &251d,X ; ladder_y_low_table &1d23 8d 17 25 STA &2517 ; ladder_coordinates + 1 &1d26 e9 06 SBC #&06 # Co-ordinates (1,5) and (2,6) are y of first byte - 6 &1d28 8d 1b 25 STA &251b ; ladder_coordinates + 5 &1d2b bd 23 25 LDA &2523,X ; ladder_y_high_table &1d2e 8d 18 25 STA &2518 ; ladder_coordinates + 2 &1d31 e9 00 SBC #&00 &1d33 8d 1c 25 STA &251c ; ladder_coordinates + 6 &1d36 20 89 1d JSR &1d89 ; get_next_byte_of_ladder_data # The second byte of ladder data defines the length &1d39 38 SEC &1d3a bd 1d 25 LDA &251d,X ; ladder_y_low_table &1d3d e9 44 SBC #&44 # Co-ordinates (3,4) are y of second byte - 44 &1d3f 8d 19 25 STA &2519 ; ladder_coordinates + 3 &1d42 bd 23 25 LDA &2523,X ; ladder_y_high_table &1d45 e9 00 SBC #&00 &1d47 8d 1a 25 STA &251a ; ladder_coordinates + 4 ; write_ladder_vdu_string &1d4a 20 94 1d JSR &1d94 ; get_next_byte_of_ladder_vdu_string # Write vdu string upto and including &19 &1d4d 20 ee ff JSR &ffee ; OSWRCH &1d50 c9 19 CMP #&19 &1d52 d0 f6 BNE &1d4a ; write_ladder_vdu_string &1d54 20 94 1d JSR &1d94 ; get_next_byte_of_ladder_vdu_string &1d57 8d 29 25 STA &2529 ; ladder_plot_and_coordinates_byte # The byte of vdu string after &19 is special &1d5a 29 57 AND #&57 &1d5c 20 ee ff JSR &ffee ; OSWRCH # Bits .4.1.421 encode the plot command, written here &1d5f 20 94 1d JSR &1d94 ; get_next_byte_of_ladder_vdu_string &1d62 20 ee ff JSR &ffee ; OSWRCH # Write low byte of x co-ordinate as specified in string &1d65 a2 02 LDX #&02 &1d67 8e 2a 25 STX &252a ; length_of_string_to_write &1d6a 4e 29 25 LSR &2529 ; ladder_plot_and_coordinates_byte # Bits 8.2.8... determine which co-ordinates to use ; write_coordinates_loop &1d6d 20 94 1d JSR &1d94 ; get_next_byte_of_ladder_vdu_string &1d70 0e 29 25 ASL &2529 ; ladder_plot_and_coordinates_byte # Consider &80, &20 and &08 of some_bits_of_ladder &1d73 0e 29 25 ASL &2529 ; ladder_plot_and_coordinates_byte &1d76 90 04 BCC &1d7c ; use_specified_coordinates &1d78 aa TAX # If the bit is set, use calculated co-ordinates &1d79 bd 16 25 LDA &2516,X ; ladder_coordinates # for high byte of x co-ordinate, and y co-ordinate ; use_specified_coordinates &1d7c 20 ee ff JSR &ffee ; OSWRCH # otherwise, use co-ordinates specified in string &1d7f ce 2a 25 DEC &252a ; length_of_string_to_write &1d82 ae 2a 25 LDX &252a ; length_of_string_to_write &1d85 10 e6 BPL &1d6d ; write_coordinates_loop &1d87 30 c1 BMI &1d4a ; write_ladder_vdu_string ; get_next_byte_of_ladder_data &1d89 ee 2b 25 INC &252b ; ladder_data_offset &1d8c ae 2b 25 LDX &252b ; ladder_data_offset &1d8f bd 2b 24 LDA &242b,X ; ladder_data &1d92 aa TAX &1d93 60 RTS ; get_next_byte_of_ladder_vdu_string &1d94 c8 INY &1d95 cc b8 23 CPY &23b8 ; ladder_vdu_string &1d98 f0 04 BEQ &1d9e ; reached_end_of_ladder_vdu_string &1d9a b9 b8 23 LDA &23b8,Y ; ladder_vdu_string &1d9d 60 RTS ; reached_end_of_ladder_vdu_string &1d9e 68 PLA # get_next_byte_of_ladder_vdu_string won't be returning &1d9f 68 PLA &1da0 20 89 1d JSR &1d89 ; get_next_byte_of_ladder_data # The third byte of ladder data sets the number of rungs ; plot_rungs_loop &1da3 8e 7d 27 STX &277d ; rungs_to_plot &1da6 a2 01 LDX #&01 &1da8 a0 25 LDY #&25 ; &2501 = rung_vdu_string &1daa 20 41 21 JSR &2141 ; write_string &1dad ae 7d 27 LDX &277d ; rungs_to_plot &1db0 ca DEX &1db1 d0 f0 BNE &1da3 ; plot_rungs_loop &1db3 a0 00 LDY #&00 &1db5 4c 17 1d JMP &1d17 ; consider_next_ladder ; end_of_column_of_ladders &1db8 ee 16 25 INC &2516 ; ladder_column &1dbb ad 16 25 LDA &2516 ; ladder_column &1dbe c9 05 CMP #&05 &1dc0 f0 03 BEQ &1dc5 ; leave &1dc2 4c 17 1d JMP &1d17 ; consider_next_ladder ; leave &1dc5 60 RTS ; plot_platforms &1dc6 a0 3d LDY #&3d &1dc8 8c 2d 25 STY &252d ; platform_y ; plot_platforms_vertical_loop &1dcb a2 00 LDX #&00 &1dcd 8e 2c 25 STX &252c ; platform_x ; plot_platforms_horizontal_loop &1dd0 a9 27 LDA #&27 ; COLOUR_4_BRICKWORK_WITH_COLOUR_6_MORTAR_OFFSET &1dd2 ac 2d 25 LDY &252d ; platform_y &1dd5 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &1dd8 ad 2c 25 LDA &252c ; platform_x &1ddb 18 CLC &1ddc 69 08 ADC #&08 &1dde 8d 2c 25 STA &252c ; platform_x &1de1 aa TAX &1de2 e0 a0 CPX #&a0 &1de4 d0 ea BNE &1dd0 ; plot_platforms_horizontal_loop &1de6 ad 2d 25 LDA &252d ; platform_y &1de9 18 CLC &1dea 69 23 ADC #&23 &1dec 8d 2d 25 STA &252d ; platform_y &1def a8 TAY &1df0 c0 ec CPY #&ec &1df2 d0 d7 BNE &1dcb ; plot_platforms_vertical_loop &1df4 60 RTS ; initialise_game &1df5 20 e8 20 JSR &20e8 ; move_sprite_data &1df8 ba TSX &1df9 8e 8a 25 STX &258a ; starting_stack_pointer &1dfc a9 04 LDA #&04 ; Define action of cursor editing keys &1dfe a2 01 LDX #&01 ; Cursor keys return ASCII values 135-139 &1e00 20 f4 ff JSR &fff4 ; OSBYTE ; start_new_game &1e03 20 df 1e JSR &1edf ; reset_game ; start_new_stage &1e06 20 84 11 JSR &1184 ; play_stage &1e09 20 36 1e JSR &1e36 ; silence_all_channels &1e0c 20 1c 1f JSR &1f1c ; play_level_complete_melody &1e0f 20 28 1e JSR &1e28 ; wipe_play_area &1e12 a5 05 LDA &05 ; player_died &1e14 f0 f0 BEQ &1e06 ; start_new_stage &1e16 a5 00 LDA &00 ; player_lives &1e18 d0 ec BNE &1e06 ; start_new_stage &1e1a 20 5f 1e JSR &1e5f ; plot_game_over &1e1d a2 64 LDX #&64 &1e1f 20 71 1f JSR &1f71 ; delay_for_x &1e22 20 98 1f JSR &1f98 ; check_for_high_score &1e25 4c 03 1e JMP &1e03 ; start_new_game ; wipe_play_area &1e28 a2 7a LDX #&7a &1e2a a0 25 LDY #&25 ; &257a = wipe_play_area_string &1e2c 4c 41 21 JMP &2141 ; write_string ; plot_oxygen_bar &1e2f a2 2e LDX #&2e &1e31 a0 25 LDY #&25 ; &252e = draw_oxygen_string &1e33 4c 41 21 JMP &2141 ; write_string ; silence_all_channels &1e36 a2 03 LDX #&03 &1e38 8e 89 25 STX &2589 ; channel_to_use ; silence_all_channels_loop &1e3b a9 00 LDA #&00 &1e3d 20 d2 1b JSR &1bd2 ; play_sound &1e40 ce 89 25 DEC &2589 ; channel_to_use &1e43 ae 89 25 LDX &2589 ; channel_to_use &1e46 10 f3 BPL &1e3b ; silence_all_channels &1e48 60 RTS ; get_random_number_within_range &1e49 20 6a 13 JSR &136a ; generate_random_number ; get_a_modulo_x &1e4c 8e 8b 25 STX &258b ; limit &1e4f e0 00 CPX #&00 &1e51 f0 0a BEQ &1e5d ; leave_with_zero &1e53 38 SEC ; reduction_loop &1e54 ed 8b 25 SBC &258b ; limit &1e57 b0 fb BCS &1e54 ; reduction_loop &1e59 6d 8b 25 ADC &258b ; limit &1e5c 60 RTS ; leave_with_zero &1e5d 8a TXA &1e5e 60 RTS ; plot_game_over &1e5f a2 95 LDX #&95 &1e61 a0 25 LDY #&25 ; &2595 = game_over_string &1e63 4c 41 21 JMP &2141 ; write_string ; check_if_monster_stops_player_digging &1e66 a6 34 LDX &34 ; hole_x &1e68 8e 7d 27 STX &277d ; digging_check_x &1e6b a0 02 LDY #&02 # Y = 2 for proposed hole, 1 for further away ; check_if_monster_stops_player_digging_loop &1e6d ae 36 23 LDX &2336 ; number_of_monsters_plus_one &1e70 bd 39 23 LDA &2339,X ; monsters_flags &1e73 29 40 AND #&40 ; MONSTER_KILLED &1e75 d0 13 BNE &1e8a ; consider_next_monster &1e77 b5 0c LDA &0c,X ; monsters_x &1e79 38 SEC &1e7a e9 01 SBC #&01 &1e7c cd 7d 27 CMP &277d ; digging_check_x &1e7f d0 09 BNE &1e8a ; consider_next_monster &1e81 a5 14 LDA &14 ; player_y &1e83 38 SEC &1e84 f5 14 SBC &14,X ; monsters_y &1e86 c9 13 CMP #&13 &1e88 90 1a BCC &1ea4 ; leave ; consider_next_monster &1e8a ca DEX &1e8b d0 e3 BNE &1e70 ; check_if_monster_stops_player_digging_loop &1e8d 88 DEY &1e8e f0 14 BEQ &1ea4 ; leave &1e90 a5 24 LDA &24 ; player_sprite # Do the same again, but offset eight pixels &1e92 29 02 AND #&02 # in the direction the player is facing &1e94 0a ASL A &1e95 0a ASL A &1e96 0a ASL A &1e97 38 SEC &1e98 e9 08 SBC #&08 &1e9a 18 CLC &1e9b 6d 7d 27 ADC &277d ; digging_check_x &1e9e 8d 7d 27 STA &277d ; digging_check_x &1ea1 4c 6d 1e JMP &1e6d ; check_if_monster_stops_player_digging_loop ; leave &1ea4 60 RTS ; plot_monster_eating_player &1ea5 a6 38 LDX &38 ; monster_number &1ea7 b5 63 LDA &63,X ; monsters_type &1ea9 18 CLC &1eaa 69 31 ADC #&31 ; RED_MONSTER_EATING_PLAYER - 1 # Set the monster's sprite to be eating the player &1eac 95 24 STA &24,X ; monsters_sprite &1eae 20 1d 14 JSR &141d ; update_player_or_monster_screen_address # Mark it as needing unplotting &1eb1 a6 38 LDX &38 ; monster_number &1eb3 a9 00 LDA #&00 # 0 = the player &1eb5 85 38 STA &38 ; monster_number &1eb7 20 1d 14 JSR &141d ; update_player_or_monster_screen_address # Mark the player as needing unplotting &1eba a9 7f LDA #&7f # Remove the player's sprite &1ebc 85 24 STA &24 ; player_sprite &1ebe 20 f9 11 JSR &11f9 ; wait_for_vsync &1ec1 20 3b 14 JSR &143b ; plot_monsters_and_player &1ec4 58 CLI &1ec5 20 36 1e JSR &1e36 ; silence_all_channels &1ec8 20 23 21 JSR &2123 ; play_death_sound &1ecb 60 RTS ; toggle_paused_flag_on_all_but_most_recently_filled_monster &1ecc a2 07 LDX #&07 &1ece ec e7 22 CPX &22e7 ; most_recently_filled_monster ; toggle_paused_flag_on_all_but_most_recently_filled_monster_loop &1ed1 f0 08 BEQ &1edb ; skip_monster &1ed3 bd 39 23 LDA &2339,X ; monsters_flags &1ed6 49 20 EOR #&20 ; MONSTER_PAUSED &1ed8 9d 39 23 STA &2339,X ; monsters_flags ; skip_monster &1edb ca DEX &1edc d0 f0 BNE &1ece ; toggle_paused_flag_on_all_but_most_recently_filled_monster_loop &1ede 60 RTS ; reset_game &1edf a2 07 LDX #&07 &1ee1 a9 01 LDA #&01 ; RED # All monsters start as red on stage one ; reset_monsters_starting_type_loop &1ee3 9d a4 22 STA &22a4,X ; monsters_starting_type &1ee6 ca DEX &1ee7 d0 fa BNE &1ee3 ; reset_monsters_starting_type_loop &1ee9 8e 92 25 STX &2592 ; extra_life_gained &1eec 8e a4 22 STX &22a4 ; player_starting_type # Player starts as PLAYER_RUNNING_LEFT &1eef 86 02 STX &02 ; score_one &1ef1 86 03 STX &03 ; score_two &1ef3 86 04 STX &04 ; score_three &1ef5 85 05 STA &05 ; player_died &1ef7 85 01 STA &01 ; stage_number &1ef9 a9 20 LDA #&20 &1efb 8d 44 23 STA &2344 ; starting_oxygen_as_numbers_high # Stage one starts with 2000 oxygen &1efe a9 02 LDA #&02 &1f00 8d 45 23 STA &2345 ; number_of_monsters_to_update_per_frame &1f03 a9 03 LDA #&03 # Player starts with three lives &1f05 85 00 STA &00 ; player_lives &1f07 a2 80 LDX #&80 &1f09 a0 27 LDY #&27 ; &2780 = setup_screen_string &1f0b 20 41 21 JSR &2141 ; write_string &1f0e a9 78 LDA #&78 &1f10 8d 47 23 STA &2347 ; x_position_of_next_life ; plot_lives_loop &1f13 aa TAX &1f14 20 be 1b JSR &1bbe ; plot_life_sprite &1f17 c9 90 CMP #&90 # Plotting routine is hard-coded for this &1f19 d0 f8 BNE &1f13 ; plot_lives_loop &1f1b 60 RTS ; play_level_complete_melody &1f1c a5 05 LDA &05 ; player_died &1f1e d0 40 BNE &1f60 ; leave # If the player didn't die, &1f20 ad 28 23 LDA &2328 ; oxygen_as_numbers_low &1f23 d0 05 BNE &1f2a ; player_didn't_asphyxiate &1f25 ad 29 23 LDA &2329 ; oxygen_as_numbers_high &1f28 f0 36 BEQ &1f60 ; leave ; player_didn't_asphyxiate &1f2a a2 00 LDX #&00 &1f2c 8e cc 25 STX &25cc ; melody_note ; play_melody_loop # play the stage completion melody &1f2f bd bc 25 LDA &25bc,X ; melody_table &1f32 8d b8 25 STA &25b8 ; melody_sound_pitch &1f35 a9 01 LDA #&01 &1f37 8d b4 25 STA &25b4 ; melody_sound_channel ; play_melody_note_loop # Play each note as chords on channels 1 to 3 &1f3a a2 b4 LDX #&b4 &1f3c a0 25 LDY #&25 ; &25b4 = melody_sound &1f3e a9 07 LDA #&07 ; Generate a sound &1f40 20 f1 ff JSR &fff1 ; OSWORD &1f43 ee b4 25 INC &25b4 ; melody_sound_channel &1f46 ad b8 25 LDA &25b8 ; melody_sound_pitch &1f49 18 CLC &1f4a 69 30 ADC #&30 &1f4c 8d b8 25 STA &25b8 ; melody_sound_pitch &1f4f ad b4 25 LDA &25b4 ; melody_sound_channel &1f52 c9 04 CMP #&04 &1f54 d0 e4 BNE &1f3a ; play_melody_note_loop &1f56 ee cc 25 INC &25cc ; melody_note &1f59 ae cc 25 LDX &25cc ; melody_note &1f5c e0 10 CPX #&10 &1f5e d0 cf BNE &1f2f ; play_melody_loop ; leave &1f60 60 RTS ; silence_channels_two_and_three &1f61 a9 00 LDA #&00 &1f63 a2 02 LDX #&02 &1f65 20 d2 1b JSR &1bd2 ; play_sound &1f68 a9 00 LDA #&00 &1f6a a2 03 LDX #&03 &1f6c 4c d2 1b JMP &1bd2 ; play_sound ; delay_for_32 &1f6f a2 32 LDX #&32 ; delay_for_x &1f71 8a TXA &1f72 0a ASL A &1f73 8d 91 25 STA &2591 ; desired_clock &1f76 20 8f 1f JSR &1f8f ; read_clock &1f79 ad 8c 25 LDA &258c ; clock_block &1f7c 18 CLC &1f7d 6d 91 25 ADC &2591 ; desired_clock &1f80 8d 91 25 STA &2591 ; desired_clock ; delay_loop &1f83 20 8f 1f JSR &1f8f ; read_clock &1f86 ad 8c 25 LDA &258c ; clock_block &1f89 cd 91 25 CMP &2591 ; desired_clock &1f8c d0 f5 BNE &1f83 ; delay_loop &1f8e 60 RTS ; read_clock &1f8f a9 01 LDA #&01 ; Read system clock &1f91 a2 8c LDX #&8c &1f93 a0 25 LDY #&25 ; &258c = clock_block &1f95 4c f1 ff JMP &fff1 ; OSWORD ; check_for_high_score &1f98 a2 07 LDX #&07 # Starting at the bottom of the high score table, ; check_for_high_score_loop &1f9a a5 04 LDA &04 ; score_three &1f9c dd df 25 CMP &25df,X ; high_scores_three # is the player's score greater to the score in rank X? &1f9f 90 15 BCC &1fb6 ; score_is_lower &1fa1 d0 10 BNE &1fb3 ; score_is_higher &1fa3 a5 03 LDA &03 ; score_two &1fa5 dd d7 25 CMP &25d7,X ; high_scores_two &1fa8 90 0c BCC &1fb6 ; score_is_lower &1faa d0 07 BNE &1fb3 ; score_is_higher &1fac a5 02 LDA &02 ; score_one &1fae dd cf 25 CMP &25cf,X ; high_scores_one &1fb1 90 03 BCC &1fb6 ; score_is_lower ; score_is_higher &1fb3 ca DEX &1fb4 10 e4 BPL &1f9a ; check_for_high_score ; score_is_lower # X contains the rank above the player's score &1fb6 e0 07 CPX #&07 &1fb8 d0 08 BNE &1fc2 ; new_high_score &1fba a9 ff LDA #&ff &1fbc 8d 9c 26 STA &269c ; position_in_high_scores &1fbf 4c 3f 20 JMP &203f ; display_high_scores # If the player didn't rank, just display the scores ; new_high_score &1fc2 e8 INX # X contains the player's rank &1fc3 8e 9c 26 STX &269c ; position_in_high_scores &1fc6 ad ee 25 LDA &25ee ; high_scores_name_address_low_table + 7 # Scores will be moved, but names are not &1fc9 8d f7 25 STA &25f7 ; input_osword_block &1fcc 85 7c STA &7c ; name_address_low &1fce ad f6 25 LDA &25f6 ; high_scores_name_address_high_table + 7 # The eighth (+7) slot is used for the new name &1fd1 8d f8 25 STA &25f8 ; input_osword_block + 1 &1fd4 85 7d STA &7d ; name_address_high &1fd6 a2 07 LDX #&07 &1fd8 ec 9c 26 CPX &269c ; position_in_high_scores &1fdb f0 24 BEQ &2001 ; skip_moving_scores_down # If the player isn't in rank 7, ; move_scores_down_loop # move the scores below them down a slot &1fdd bd ce 25 LDA &25ce,X ; high_scores_one - 1 &1fe0 9d cf 25 STA &25cf,X ; high_scores_one &1fe3 bd d6 25 LDA &25d6,X ; high_scores_two - 1 &1fe6 9d d7 25 STA &25d7,X ; high_scores_two &1fe9 bd de 25 LDA &25de,X ; high_scores_three - 1 &1fec 9d df 25 STA &25df,X ; high_scores_three &1fef bd e6 25 LDA &25e6,X ; high_scores_name_address_low_table -1 # Only pointers to the names are moved &1ff2 9d e7 25 STA &25e7,X ; high_scores_name_address_low_table &1ff5 bd ee 25 LDA &25ee,X ; high_scores_name_address_high_table - 1 &1ff8 9d ef 25 STA &25ef,X ; high_scores_name_address_high_table &1ffb ca DEX &1ffc ec 9c 26 CPX &269c ; position_in_high_scores &1fff d0 dc BNE &1fdd ; move_scores_down_loop ; skip_moving_scores_down &2001 a5 7c LDA &7c ; name_address_low # Insert the player's score and pointer to name &2003 9d e7 25 STA &25e7,X ; high_scores_name_address_low_table &2006 a5 7d LDA &7d ; name_address_high &2008 9d ef 25 STA &25ef,X ; high_scores_name_address_high_table &200b a5 02 LDA &02 ; score_one &200d 9d cf 25 STA &25cf,X ; high_scores_one &2010 a5 03 LDA &03 ; score_two &2012 9d d7 25 STA &25d7,X ; high_scores_two &2015 a5 04 LDA &04 ; score_three &2017 9d df 25 STA &25df,X ; high_scores_three &201a a2 9d LDX #&9d &201c a0 26 LDY #&26 ; &269d = congratulations_string &201e 20 41 21 JSR &2141 ; write_string &2021 a9 7e LDA #&7e ; Acknowledge ESCAPE Condition &2023 20 f4 ff JSR &fff4 ; OSBYTE &2026 a9 0f LDA #&0f ; Flush input buffer &2028 a2 01 LDX #&01 ; Flushes just the input buffer &202a 20 f4 ff JSR &fff4 ; OSBYTE &202d a2 f7 LDX #&f7 &202f a0 25 LDY #&25 ; &25f7 = input_osword_block &2031 a9 00 LDA #&00 ; Input line &2033 20 f1 ff JSR &fff1 ; OSWORD # Ask the player for their name &2036 a9 20 LDA #&20 ; pad_name_loop &2038 91 7c STA (&7c),Y ; name_address # and pad with spaces &203a c8 INY &203b c0 14 CPY #&14 &203d d0 f9 BNE &2038 ; pad_name_loop ; display_high_scores &203f a2 24 LDX #&24 &2041 a0 27 LDY #&27 ; &2724 = monster_scores_string &2043 20 41 21 JSR &2141 ; write_string &2046 a0 01 LDY #&01 &2048 8c ae 22 STY &22ae ; high_score_position ; display_high_scores_loop # For each high score, write &204b a9 20 LDA #&20 ; " " &204d 20 df 20 JSR &20df ; write_character_four_times # four spaces, &2050 ad ae 22 LDA &22ae ; high_score_position &2053 09 30 ORA #&30 &2055 20 ee ff JSR &ffee ; OSWRCH # rank, &2058 a9 2e LDA #&2e ; "." &205a 20 df 20 JSR &20df ; write_character_four_times # four "."s, &205d ae ae 22 LDX &22ae ; high_score_position &2060 bd ce 25 LDA &25ce,X ; high_scores_one - 1 &2063 85 02 STA &02 ; score_one &2065 bd d6 25 LDA &25d6,X ; high_scores_two - 1 &2068 85 03 STA &03 ; score_two &206a bd de 25 LDA &25de,X ; high_scores_three - 1 &206d 85 04 STA &04 ; score_three &206f a9 2e LDA #&2e ; "." &2071 8d 7c 27 STA &277c ; padding_character # score, padded with leading ".s", &2074 20 c0 19 JSR &19c0 ; write_score &2077 a9 2e LDA #&2e ; "." &2079 20 df 20 JSR &20df ; write_character_four_times # four "."s, &207c bd e6 25 LDA &25e6,X ; high_scores_name_address_low_table - 1 &207f 85 7c STA &7c ; name_address_low &2081 bd ee 25 LDA &25ee,X ; high_scores_name_address_high_table - 1 &2084 85 7d STA &7d ; name_address_high &2086 a0 00 LDY #&00 ; display_high_scores_name_loop &2088 b1 7c LDA (&7c),Y ; name_address &208a 20 ee ff JSR &ffee ; OSWRCH # name, &208d c8 INY &208e c0 14 CPY #&14 &2090 d0 f6 BNE &2088 ; display_high_scores_name_loop &2092 a9 0d LDA #&0d &2094 20 ee ff JSR &ffee ; OSWRCH &2097 a9 0a LDA #&0a &2099 20 ee ff JSR &ffee ; OSWRCH # and two new lines &209c 20 ee ff JSR &ffee ; OSWRCH &209f ee ae 22 INC &22ae ; high_score_position &20a2 ae ae 22 LDX &22ae ; high_score_position &20a5 e0 09 CPX #&09 &20a7 d0 a2 BNE &204b ; display_high_scores_loop &20a9 ae 9c 26 LDX &269c ; position_in_high_scores &20ac 30 16 BMI &20c4 ; skip_highlight # If the player ranked, &20ae a9 1f LDA #&1f &20b0 20 ee ff JSR &ffee ; OSWRCH # TAB(&00, (rank * 2) + 5) &20b3 a9 00 LDA #&00 &20b5 20 ee ff JSR &ffee ; OSWRCH &20b8 8a TXA &20b9 0a ASL A &20ba 69 05 ADC #&05 &20bc 20 ee ff JSR &ffee ; OSWRCH &20bf a9 88 LDA #&88 &20c1 20 ee ff JSR &ffee ; OSWRCH # Flashing text ; skip_highlight &20c4 a2 5a LDX #&5a &20c6 a0 27 LDY #&27 ; &275a = press_space_bar_string &20c8 20 41 21 JSR &2141 ; write_string &20cb a9 0f LDA #&0f ; Flush input buffer &20cd a2 01 LDX #&01 ; Flushes just the input buffer &20cf 20 f4 ff JSR &fff4 ; OSBYTE ; wait_for_space # Wait for SPACE to be pressed &20d2 a9 7e LDA #&7e ; Acknowledge ESCAPE Condition &20d4 20 f4 ff JSR &fff4 ; OSBYTE &20d7 20 e0 ff JSR &ffe0 ; OSRDCH &20da c9 20 CMP #&20 &20dc d0 f4 BNE &20d2 ; wait_for_space &20de 60 RTS ; write_character_four_times &20df a0 03 LDY #&03 ; write_character_four_times_loop &20e1 20 ee ff JSR &ffee ; OSWRCH &20e4 88 DEY &20e5 10 fa BPL &20e1 ; write_character_four_times_loop &20e7 60 RTS ; move_sprite_data # Move &3000-&33ff to &0400-&07ff &20e8 a0 30 LDY #&30 &20ea 84 79 STY &79 ; source_address_high &20ec a0 04 LDY #&04 &20ee 84 7b STY &7b ; target_address_high &20f0 a0 00 LDY #&00 &20f2 84 78 STY &78 ; source_address_low &20f4 84 7a STY &7a ; target_address_low ; move_sprite_data_loop &20f6 b1 78 LDA (&78),Y ; source_address &20f8 91 7a STA (&7a),Y ; target_address &20fa c8 INY &20fb d0 f9 BNE &20f6 ; move_memory_loop &20fd e6 79 INC &79 ; source_address_high &20ff e6 7b INC &7b ; target_address_high &2101 a5 7b LDA &7b ; target_address_high &2103 c9 08 CMP #&08 &2105 d0 ef BNE &20f6 ; move_sprite_data_loop &2107 60 RTS ; check_if_monsters_can_eat_player &2108 a5 0c LDA &0c ; player_x &210a 8d d5 22 STA &22d5 ; check_x &210d a5 14 LDA &14 ; player_y &210f 8d d6 22 STA &22d6 ; check_y &2112 a9 00 LDA #&00 ; MONSTERS &2114 a2 02 LDX #&02 &2116 a0 23 LDY #&23 &2118 20 b6 1a JSR &1ab6 ; check_for_monsters_or_player_in_proximity &211b f0 05 BEQ &2122 ; leave &211d 86 38 STX &38 ; monster_number &211f 4c 2d 12 JMP &122d ; kill_player_by_being_eaten # This never returns ; leave &2122 60 RTS ; play_death_sound &2123 a9 ff LDA #&ff &2125 8d b4 23 STA &23b4 ; sound_b_pitch &2128 a9 03 LDA #&03 &212a 8d b0 23 STA &23b0 ; sound_b_channel ; play_death_sound_loop # Play sound as a chord on channels 1 to 3 &212d a9 0b LDA #&0b &212f 20 d2 1b JSR &1bd2 ; play_sound &2132 ad b4 23 LDA &23b4 ; sound_b_pitch &2135 38 SEC &2136 e9 30 SBC #&30 &2138 8d b4 23 STA &23b4 ; sound_b_pitch &213b ce b0 23 DEC &23b0 ; sound_b_channel &213e d0 ed BNE &212d ; play_death_sound_loop &2140 60 RTS ; write_string &2141 86 7e STX &7e ; string_address_low &2143 84 7f STY &7f ; string_address_high &2145 a0 00 LDY #&00 &2147 b1 7e LDA (&7e),Y ; string_address &2149 8d 7e 27 STA &277e ; length_of_string &214c c8 INY ; write_string_loop &214d b1 7e LDA (&7e),Y ; string_address &214f 20 ee ff JSR &ffee ; OSWRCH &2152 c8 INY &2153 cc 7e 27 CPY &277e ; length_of_string &2156 d0 f5 BNE &214d ; write_string_loop &2158 60 RTS ; kill_player_by_asphyxiation &2159 20 36 1e JSR &1e36 ; silence_all_channels &215c a2 00 LDX #&00 &215e 86 38 STX &38 ; monster_number &2160 a5 2c LDA &2c ; player_state &2162 c9 03 CMP #&03 ; PLAYER_FALLING # If the player ran out of oxygen while falling, &2164 d0 10 BNE &2176 ; player_wasn't_falling &2166 20 f9 11 JSR &11f9 ; wait_for_vsync &2169 20 3b 14 JSR &143b ; plot_monsters_and_player &216c 58 CLI &216d 20 bd 11 JSR &11bd ; handle_player_movement # continue their fall until they come to a stop &2170 20 1d 14 JSR &141d ; update_player_or_monster_screen_address &2173 4c 59 21 JMP &2159 ; kill_player_by_asphyxiation ; player_wasn't_falling &2176 c9 01 CMP #&01 ; PLAYER_CLIMBING # If the player ran out of oxygen while climbing, &2178 d0 36 BNE &21b0 ; plot_asphyxiated_player_without_silence &217a a9 07 LDA #&07 &217c 20 d2 1b JSR &1bd2 ; play_sound # Play sound for player losing hold of ladder ; slide_down_ladder &217f a5 14 LDA &14 ; player_y &2181 38 SEC &2182 e9 11 SBC #&11 &2184 a8 TAY &2185 a6 0c LDX &0c ; player_x &2187 20 6d 29 JSR &296d ; get_screen_colour_at_position &218a 29 0c AND #&0c &218c c9 08 CMP #&08 &218e d0 19 BNE &21a9 ; plot_asphyxiated_player # While they remain on a ladder, &2190 a5 14 LDA &14 ; player_y &2192 38 SEC &2193 e9 05 SBC #&05 # move them down the ladder &2195 85 14 STA &14 ; player_y &2197 20 1d 14 JSR &141d ; update_player_or_monster_screen_address &219a 20 f9 11 JSR &11f9 ; wait_for_vsync &219d 20 3b 14 JSR &143b ; plot_monsters_and_player &21a0 58 CLI &21a1 a2 03 LDX #&03 &21a3 20 71 1f JSR &1f71 ; delay_for_x &21a6 4c 7f 21 JMP &217f ; slide_down_ladder ; plot_asphyxiated_player &21a9 a9 00 LDA #&00 &21ab a2 03 LDX #&03 &21ad 20 d2 1b JSR &1bd2 ; play_sound # Silence channel 3 ; plot_asphyxiated_player_without_silence &21b0 a5 24 LDA &24 ; player_sprite &21b2 a6 0c LDX &0c ; player_x &21b4 a4 14 LDY &14 ; player_y &21b6 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Remove player from screen &21b9 a5 14 LDA &14 ; player_y &21bb 38 SEC &21bc e9 08 SBC #&08 &21be 85 14 STA &14 ; player_y &21c0 a8 TAY &21c1 a5 0c LDA &0c ; player_x &21c3 38 SEC &21c4 e9 03 SBC #&03 &21c6 85 0c STA &0c ; player_x &21c8 aa TAX &21c9 a9 36 LDA #&36 ; ASPHYXIATED_PLAYER_FEET # Plot dead player's feet &21cb 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &21ce a5 0c LDA &0c ; player_x &21d0 18 CLC &21d1 69 08 ADC #&08 &21d3 aa TAX &21d4 a4 14 LDY &14 ; player_y &21d6 a9 37 LDA #&37 ; ASPHYXIATED_PLAYER_HEAD # Plot dead player's head &21d8 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &21db a9 08 LDA #&08 &21dd 4c d2 1b JMP &1bd2 ; play_sound # Play sound for player falling over dead ; determine_if_monster_is_hungry &21e0 ad 37 23 LDA &2337 ; number_of_monsters_still_alive_plus_one # Red monsters have a 1 in (number of monsters still &21e3 a6 38 LDX &38 ; monster_number # alive + 1) chance of being hungry, i.e. homing in on &21e5 b4 63 LDY &63,X ; monsters_type # player. Green monsters are twice as likely to be ; division_loop # hungry. White monsters are twice as likely again. &21e7 88 DEY &21e8 f0 04 BEQ &21ee ; use_as_range &21ea 4a LSR A &21eb d0 fa BNE &21e7 ; division_loop &21ed 60 RTS ; use_as_range &21ee aa TAX &21ef 4c 49 1e JMP &1e49 ; get_random_number_within_range ; repair_platform_for_squashed_partially_trapped_misaligned_monster &21f2 a6 38 LDX &38 ; monster_number &21f4 b5 14 LDA &14,X ; monsters_y &21f6 38 SEC &21f7 e9 11 SBC #&11 &21f9 48 PHA &21fa a8 TAY &21fb b5 0c LDA &0c,X ; monsters_x &21fd 38 SEC &21fe e9 03 SBC #&03 &2200 48 PHA &2201 aa TAX &2202 a9 9c LDA #&9c ; COLOUR_0_BLOCK | AND_SPRITE &2204 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Remove the platform, including any hole &2207 68 PLA ; monster_x &2208 aa TAX &2209 68 PLA ; monster_y &220a a8 TAY &220b 8a TXA &220c 29 04 AND #&04 &220e 49 04 EOR #&04 &2210 4a LSR A &2211 4a LSR A &2212 18 CLC &2213 69 26 ADC #&26 ; COLOUR_4_BRICKWORK_WITH_COLOUR_6_MORTAR &2215 20 fa 28 JSR &28fa ; plot_sprite_at_x_y # Replot brickwork &2218 ce 7f 27 DEC &277f ; monster_hit_misaligned_partially_trapped_monster &221b 60 RTS ; unused_routine_one # Similar to &21c4-&21f1 &221c e9 03 SBC #&03 # but using different locations for some variables &221e 8d ba 22 STA &22ba ; equivalent to player_x # Notably not in zero page &2221 aa TAX &2222 a9 36 LDA #&36 ; ASPHYXIATED_PLAYER_FEET # Plot dead player's feet &2224 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &2227 ad ba 22 LDA &22ba ; equivalent to player_x &222a 18 CLC &222b 69 08 ADC #&08 &222d aa TAX &222e ac c2 22 LDY &22c2 ; equivalent to player_y &2231 a9 37 LDA #&37 ; ASPHYXIATED_PLAYER_HEAD # Plot dead player's head &2233 20 fa 28 JSR &28fa ; plot_sprite_at_x_y &2236 a9 08 LDA #&08 &2238 4c 19 1c JMP &1c19 ; equivalent to play_sound # Different address for some, but not all functions ; unused_routine_two &223b ad 3b 23 LDA &233b ; equivalent to number_of_monsters_still_alive_plus_one &223e a6 38 LDX &38 ; monster_number &2240 b4 63 LDY &63,X ; monsters_type ; loop &2242 88 DEY &2243 f0 04 BEQ &2249 ; use_as_range &2245 4a LSR A &2246 d0 fa BNE &2242 ; loop &2248 60 RTS ; use_as_range &2249 aa TAX &224a 4c 93 1e JMP &1e93 ; equivalent to get_random_number_within_range ; unused &224d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &225d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &226d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &227d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &228d 00 00 00 00 00 00 00 00 00 00 00 00 ; unused &2299 01 01 01 01 01 01 01 06 7f 09 3e ; monsters_starting_type &22a4 00 01 02 01 01 01 01 01 : screen_colour &22ac 04 ; sprite_to_plot &22ad 28 ; screen_value ; high_score_position &22ae 03 ; screen_x &22af 30 ; screen_y &22b0 a6 ; key_to_check &22b1 ff ; keys_to_check &22b2 9e ; z &22b3 bd ; x &22b4 97 ; * &22b5 b7 ; ? &22b6 cd ; d &22b7 bc ; f ; digging_check_offsets_table &22b8 04 0c 10 12 15 04 ; right &22be 03 fb f7 f5 f2 03 ; left ; digging_check_y &22c4 ce ; digging_check_number &22c5 ff ; digging_check_colours_table &22c6 08 08 08 01 01 01 ; unused &22cc 01 ; falling_onto_hole_left_pixel_colour &22cd 0e ; falling_onto_hole_right_pixel_inverse &22ce 0c ; falling_onto_hole_left_pixel_inverse ; offset_check_x &22cf 60 ; bit_table &22d0 01 02 04 08 ; unused &22d4 08 ; check_x &22d5 64 ; check_y &22d6 b7 ; rnd_1 &22d7 7c ; rnd_2 &22d8 b8 ; rnd_3 &22d9 ca ; unused &22da 00 ; whether_player_pressed_dig_or_fill &22db 01 ; unused &22dc ff ; monsters_x_offset # Constant &22dd 00 fc fc fc fc fc fc fc ; hole_monster_x &22e5 67 ; unused &22e6 2b ; most_recently_filled_monster &22e7 03 ; monsters_escape_timer &22e8 03 1a 1a 1a 1a 1a 1a 1a ; monsters_trapped_timer &22f0 20 30 30 30 30 30 30 30 ; depth_of_partial_hole &22f8 02 ; monsters_plotted &22f9 00 00 00 00 01 01 01 01 ; monsters_holes_passed_through &2301 00 00 00 00 00 00 00 00 ; points_table ; R G W &2309 00 01 03 07 ; crushed &230d 00 01 03 07 ; 1 hole &2311 00 02 03 07 ; 2 holes &2315 00 03 05 07 ; 3 holes &2319 00 04 07 10 ; 4 holes &231a 00 08 15 20 ; 5 holes ; points_value &2321 01 ; points_x &2322 5b ; points_y &2323 b7 ; number_value &2324 00 ; number_x &2325 67 ; number_y &2326 b7 ; using_padding_character &2327 00 ; oxygen_as_numbers_low &2328 90 ; oxygen_as_numbers_high &2329 21 ; oxygen_as_numbers_drain &232a 30 ; actual_oxygen_high &232b 5d ; actual_oxygen_low &232c 2f ; monster_type_to_sprite ; R G W &232d 02 10 14 18 ; platform_heights &2331 4d 70 93 b6 d9 ; number_of_monsters_plus_one &2336 04 ; number_of_monsters_still_alive_plus_one &2337 01 ; stack_pointer_at_start_of_stage &2338 fb ; monsters_flags &2339 00 40 40 40 40 40 40 40 ; check_x_proximity &2341 07 ; check_y_proximity &2342 0c ; maximum_monster_to_check_plus_one &2343 01 ; starting_oxygen_as_numbers_high &2344 30 ; number_of_monsters_to_update_per_frame &2345 02 ; monsters_still_to_update &2346 02 ; x_position_of_next_life &2347 88 ; colour_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &2348 00 01 07 03 00 00 00 00 00 01 07 03 02 06 04 04 ; chan vol pitch dur ; sounds &2358 00 00 00 00 00 00 00 00 ; sound_0 # Silence (channel varies) &2360 11 00 02 00 80 00 01 00 ; sound_1 # Player running &2368 11 00 02 00 88 00 01 00 ; sound_2 # Player climbing &2370 11 00 02 00 74 00 01 00 ; sound_3 # Player digging or filling &2378 12 00 01 00 04 00 ff ff ; sound_4 # Monster trapped in hole &2380 10 00 01 00 00 00 ff ff ; sound_5 # Monster climbing out of hole &2388 10 00 04 00 07 00 1e 00 ; sound_6 # Monster survives fall &2390 13 00 03 00 80 00 ff ff ; sound_7 # Player falling off ladder from asphyxiation &2398 10 00 04 00 04 00 0a 00 ; sound_8 # Death of monster / player falling over dead &23a0 13 00 f1 ff e0 00 08 00 ; sound_9 # Low oxygen warning &23a8 13 00 04 00 c0 00 0a 00 ; sound_a # Extra life gained &23b0 03 00 03 00 ff 00 08 00 ; sound_b # Player eaten by monster (channel and pitch vary) ; ladder_vdu_string &23b8 73 ; # Remove platforms &23b9 12 00 80 ; GCOL 0, 128 &23bc 19 ac 58 00 01 02 ; MOVE (ladder_x + &58), (ladder y 12) &ac = &04 + &a8 &23c2 19 28 00 00 03 04 ; MOVE +&0000, +(ladder y 34) &28 = &00 + &28 &23c8 19 ff a0 00 01 02 ; FILL TRIANGLE (ladder-x + &a0), (ladder y 12) &ff = &57 + &a8 &23ce 19 7b 00 00 03 04 ; FILL TRIANGLE +&0000, +(ladder y 34) &7b = &53 + &28 ; # Unnecessarily remove any mortar immediately to right of ladder &23d4 12 02 0d ; GCOL 2 (AND), 14 &23d7 19 ac ac 00 01 02 ; MOVE (ladder_x + &ac), (ladder_y 12) &ac = &04 + &a8 &23dd 19 29 00 00 03 04 ; DRAW +&0000, +(ladder y 34) &29 = &01 + &28 ; # Unnecessarily replot mortar immediately to right of ladder (x5) &23e3 12 00 06 ; GCOL 0, 6 &2326 19 84 ac 00 5c 00 ; MOVE (ladder_x + &ac), &005c &84 = &04 + &80 &23ec 19 41 00 00 8c 00 ; PLOT FOREGROUND POINT +&0000, +&0000 &41 = &41 + &00 &23f2 19 41 00 00 8c 00 ; PLOT FOREGROUND POINT +&0000, +&0000 &41 = &41 + &00 &23f7 19 41 00 00 8c 00 ; PLOT FOREGROUND POINT +&0000, +&0000 &41 = &41 + &00 &23fe 19 41 00 00 8c 00 ; PLOT FOREGROUND POINT +&0000, +&0000 &41 = &41 + &00 &2404 19 41 00 00 8c 00 ; PLOT FOREGROUND POINT +&0000, +&0000 &41 = &41 + &00 ; # Plot sides &240a 12 00 08 ; GCOL 0, 8 &240d 19 ac 60 00 01 02 ; MOVE (ladder_x + &60), (ladder_y 12) &ac = &04 + &a8 &2413 19 29 00 00 03 04 ; DRAW +&0000, (ladder_y 34) &29 = &01 + &28 &2419 19 ac 98 00 01 02 ; MOVE (ladder_x + &98), (ladder_y 12) &ac = &04 + &a8 &241f 19 29 00 00 03 04 ; DRAW +&0000, (ladder_y 34) &29 = &01 + &28 &2425 19 ac 98 00 05 06 ; MOVE (ladder_x + &98), (ladder_y 56) &ac = &04 + &a8 ; ladder_data # Three bytes per section: start, length, rungs; &ff ends column ; ladder pattern 0 &242b 01 04 1e ff ; |-|---|-| &242f 00 02 10 03 02 10 ff ; |-|-|---| &2436 02 02 10 ff ; |---|-|-| &243a 00 03 17 04 01 09 ff ; |-|---|-| &2441 01 04 1e ff ; --|---|-- ; ladder pattern 1 &2445 00 01 09 02 03 17 ff ; |---|---| &244c 01 02 10 ff ; |---|-|-| &2450 00 02 10 03 02 10 ff ; |-|---|-| &2457 01 03 17 ff ; --|-|-|-| &245b 00 05 25 ff ; |---|---| ; ladder pattern 2 &245f 00 02 10 03 02 10 ff ; |---|-|-| &2466 01 03 17 ff ; |-|---|-- &246a 00 01 09 02 01 09 04 01 09 ff ; --|-|---| &2474 03 02 10 ff ; |-|-----| &2478 00 03 17 04 01 09 ff ; |---|---| ; ladder pattern 3 &247f 00 01 09 02 02 10 ff ; --|-----| &2486 02 03 17 ff ; |-|---|-| &248a 00 03 17 ff ; |-|-|-|-| &248e 02 02 10 ff ; ----|---| &2492 01 04 1e ff ; |---|---- ; ladder pattern 4 &2496 00 01 09 03 02 10 ff ; |---|---| &249d 00 02 10 ff ; |---|-|-- &24a1 00 05 25 ff ; ----|-|-| &24a5 02 02 10 ff ; --|-|---| &24a9 00 03 17 04 01 09 ff ; |-|-|---| ; ladder pattern 5 &24b0 00 03 17 04 01 09 ff ; |---|---| &24b7 02 02 10 ff ; --|-|-|-| &24bb 01 01 09 03 02 10 ff ; |-|---|-| &24c2 00 04 1e ff ; |---|-|-- &24c6 02 03 17 ff ; |-----|-- ; ladder pattern 6 &24ca 00 02 10 04 01 09 ff ; |---|-|-- &24d1 01 03 17 ff ; --|-|-|-| &24d5 00 01 09 03 02 10 ff ; --|---|-| &24dc 02 03 17 ff ; |-|------ &24e0 00 01 09 02 02 10 ff ; |---|---| ; ladder pattern 7 &24e7 01 02 10 ff ; --|---|-| &24eb 00 01 09 03 02 10 ff ; --|-|-|-| &24f2 00 04 1e ff ; |---|-|-- &24f6 02 03 17 ff ; |---|---| &24fa 00 02 10 03 02 10 ff ; --|-|---| ; rung_vdu_string &2501 0d &2502 19 00 c8 ff 14 00 ; MOVE -&0038, +&0014 &2508 19 01 38 00 00 00 ; DRAW +&0038, +&0000 ; ladder_data_offset_table &250e ff 19 33 53 6a 84 9e bb ; ladder_coordinates ; ladder_column &2516 05 &2517 88 &2518 01 &2519 d0 &251a 01 &251b 82 &251c 01 ; ladder_y_low_table &251d 70 fc 88 14 a0 2c ; ladder_y_high_table &2523 00 00 01 02 02 03 ; ladder_plot_and_coordinates_byte &2529 80 ; length_of_string_to_write &252a ff ; ladder_data_offset &252b 9e ; platform_x &252c a0 ; platform_y &252d ec ; draw_oxygen_string &252e 4c &252f 12 00 01 ; GCOL 0, 1 &2532 19 04 10 03 20 00 ; MOVE &0310, &0020 &2538 19 00 00 00 1c 00 ; MOVE +&0000, +&001c &253e 19 51 50 00 e4 ff ; FILL TRIANGLE +&0050, -&001c &2544 19 51 00 00 1c 00 ; FILL TRIANGLE +&0000, +&001c &254a 12 00 03 ; GCOL 0, 3 &254d 19 51 90 01 e4 ff ; FILL TRIANGLE +&0190, -&001c &2553 19 51 00 00 1c 00 ; FILL TRIANGLE +&0000, +&001c &2559 12 00 00 ; GCOL 0, 0 &255c 19 04 08 03 1c 00 ; MOVE &0308, &001c &2562 19 01 e8 01 00 00 ; DRAW +&01e8, +&0000 &2568 19 01 00 00 24 00 ; DRAW +&0000, +&0024 &256e 19 01 18 fe 00 00 ; DRAW -&01e8, +&0000 &2574 19 01 00 00 dc ff ; DRAW +&0000, -&0024 ; wipe_play_area_string &257a 0f &257b 18 00 00 6c 00 f8 04 a0 03 ; define graphics window &0000, &006c, &04f8, &03a0 &2584 12 00 80 ; GCOL 0, 128 + 0 &2587 10 ; CLG &2588 1a ; restore graphics window ; channel_to_use &2589 ff ; starting_stack_pointer &258a fd ; limit &258b 23 ; clock_block &258c fe bf 03 00 00 ; desired_clock &2591 fe ; extra_life_gained &2592 ff ; unused &2593 00 ; colour_of_floor_player_is_about_to_move_onto &2594 04 ; game_over_string &2595 1f &2596 11 02 ; COLOUR 2 &2598 11 80 ; COLOUR 128 &259a 1f 05 0e ; TAB(&05, &0e) &259d e0 e2 e4 e6 20 20 e8 ea e6 ec ; "Game Over" (top row of double height user defined characters) &25a7 1f 05 0f ; TAB(&05, &0f) &25aa e1 e3 e5 e7 20 20 e9 eb e7 ed ; "Game Over" (bottom row of double height user defined characters) ; chan vol pitch dur &25b4 01 00 f1 ff 00 00 05 00 ; melody_sound ; melody_table &25bc 00 10 1c 10 00 10 1c 10 00 10 1c 10 00 00 00 00 # Identical to the melody in Space Panic ; melody_note &25cc 0a ; additional_falling_monsters &25cd ff ; killed_monster_y &25ce b7 ; high_scores_one &25cf 00 00 00 00 00 00 00 00 ; high_scores_two &25d7 10 10 10 10 10 10 10 10 ; high_scores_three &25df 00 00 00 00 00 00 00 00 ; high_scores_name_address_low_table &25e7 fc 10 24 38 4c 60 74 88 ; high_scores_name_address_high_table &25ef 25 26 26 26 26 26 26 26 ; input_osword_block &25f7 88 26 ; &2688 = high_score_name_8 &25f9 13 ; maximum 19 characters &25fa 20 ff ; all printable characters ; high_score_names ; high_score_name_1 &25fc 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &260c 20 20 20 20 ; high_score_name_2 &2610 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &2620 20 20 20 20 ; high_score_name_3 &2624 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &2634 20 20 20 20 ; high_score_name_4 &2638 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &2648 20 20 20 20 ; high_score_name_5 &264c 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &265c 20 20 20 20 ; high_score_name_6 &2660 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &2670 20 20 20 20 ; high_score_name_7 &2674 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &2684 20 20 20 20 ; high_score_name_8 &2688 41 63 6f 72 6e 73 6f 66 74 20 20 20 20 20 20 20 ; "Acornsoft " &2698 20 20 20 20 ; position_in_high_scores &269c 00 ; congratulations_string &269d 86 &269e 16 07 ; MODE 7 &26a0 1f 07 03 ; TAB(&07, &03) &26a3 86 9d 84 8d 43 6f 6e 67 72 61 74 75 6c 61 74 69 ; CYAN, BACKGROUND, BLUE, DOUBLE, "Congratulations!! " &26b3 6f 6e 73 21 21 20 20 20 9c &26bc 1f 07 04 ; TAB(&07, &04) &26bf 86 9d 84 8d 43 6f 6e 67 72 61 74 75 6c 61 74 69 ; CYAN, BACKGROUND, BLUE, DOUBLE, "Congratulations!! " &26cf 6f 6e 73 21 21 20 20 20 9c &26d8 1f 03 07 ; TAB(&03, &07) &26db 82 59 6f 75 72 20 73 63 6f 72 65 20 69 73 20 69 ; GREEN, "Your score is in the Top Eight." &26eb 6e 20 74 68 65 20 54 6f 70 20 45 69 67 68 74 2e &26fc 1f 07 0a ; TAB(&07, &0a) &26fe 81 50 6c 65 61 73 65 20 65 6e 74 65 72 20 79 6f ; RED, "Please enter your name:" &270e 75 72 20 6e 61 6d 65 3a &2716 1f 07 0f ; TAB(&07, &0f) &2719 86 9d 84 ; CYAN, BACKGROUND, BLUE &271c 1f 1f 0f ; TAB(&1f, &0f) &271f 9c ; BACKGROUND OFF &2720 1f 0a 0f ; TAB(&0a, &0f) ; unused &2723 0f ; monster_scores_string &2724 36 &2725 16 07 ; MODE 7 &2727 17 00 0a 20 00 00 00 00 00 00 ; set CRTC register 10 to &20, disabling the cursor &2731 1f 0b 01 ; TAB(&0b, &01) &2735 81 8d 4d 6f 6e 73 74 65 72 20 53 63 6f 72 65 73 ; RED, DOUBLE, "Monster Scores" &2744 1f 0b 02 ; TAB(&0b, &02) &2747 81 8d 4d 6f 6e 73 74 65 72 20 53 63 6f 72 65 73 ; RED, DOUBLE, "Monster Scores" &2757 1f 00 05 ; TAB(&00, &05) ; press_space_bar_string &275a 21 &275b 1f 05 17 ; TAB(&05, &17) &275e 50 72 65 73 73 20 53 50 41 43 45 20 42 41 52 20 ; "Press SPACE BAR to play again." &276e 74 6f 20 70 6c 61 79 20 61 67 61 69 6e 0d 20 ; digging_check_x &277d 63 ; length_of_string &277e 0d ; monster_hit_misaligned_partially_trapped_monster &277f 00 ; setup_screen_string &2780 73 &2781 16 02 ; MODE 2 &2783 17 00 0a 20 00 00 00 00 00 00 ; set CRTC register 10 to &20, disabling the cursor &278d 13 0d 00 00 00 00 ; COLOUR 14, 0, 0, 0, 0 &2793 12 00 8d ; GCOL 0, 128 + 14 &2796 17 00 08 00 00 00 00 00 00 00 ; set CRTC register 8 = &00, normal sync, no blanking or cursor delay &27a0 19 04 00 00 00 00 ; MOVE &0000, &0000 &27a6 19 04 00 00 68 00 ; MOVE &0000, &0068 &27ac 19 57 f8 04 00 00 ; FILL TRIANGLE &04f8, &0000 &27b2 19 57 f8 04 68 00 ; FILL TRIANGLE &04f8, &0068 &27b8 19 04 00 00 a4 03 ; MOVE &0000, &03a4 &27be 19 04 00 00 fc 03 ; MOVE &0000, &03fc &27c4 19 57 f8 04 a4 03 ; FILL TRIANGLE &04f8, &03a4 &27ca 19 57 f8 04 fc 03 ; FILL TRIANGLE &04f8, &03fc &27d0 13 0d 06 00 00 00 ; COLOUR 14, 6, 0, 0, 0 &27d6 11 01 ; COLOUR 1 &27d8 11 8d ; COLOUR 128 + 14 &27da 1f 01 01 ; TAB(&01, &01) &27dd 53 43 4f 52 45 3a ; "SCORE:" &27e3 1f 0c 01 ; TAB(&0c, &01) &27e6 30 ; "0" &27e7 11 00 ; COLOUR 0 &27e9 1f 01 1e ; TAB(&01, &1e) &27ec 4f 58 59 47 45 4e 3a 00 ; "OXYGEN:" ; unused &27f4 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite_height_table &2800 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 07 07 07 07 07 &2810 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 07 07 07 07 &2820 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 &2830 07 07 0f 0f 0f 0f 07 07 ; unused &2838 00 00 00 00 00 00 00 00 # Would allow for a further eight sprites ; sprite_address_table &2840 c0 29 ; sprite &00 - PLAYER_RUNNING_LEFT &2842 00 2a ; sprite &01 - PLAYER_RUNNING_LEFT_FRAME_1 &2844 40 2a ; sprite &02 - PLAYER_RUNNING_RIGHT &2846 80 2a ; sprite &03 - PLAYER_RUNNING_RIGHT_FRAME_1 &2848 c0 2a ; sprite &04 - PLAYER_CLIMBING &284a 00 2b ; sprite &05 - PLAYER_CLIMBING_FRAME_1 &284c 40 2b ; sprite &06 - PLAYER_DIGGING_LEFT &284e 80 2b ; sprite &07 - PLAYER_DIGGING_LEFT_FRAME_1 &2850 c0 2b ; sprite &08 - PLAYER_DIGGING_RIGHT &2852 00 2c ; sprite &09 - PLAYER_DIGGING_RIGHT_FRAME_1 &2853 a0 2d ; sprite &0a - PLAYER_FALLING &2856 40 2c ; sprite &0b - COLOUR_1_HOLE_SECTION_ONE &2858 60 2c ; sprite &0c - COLOUR_1_HOLE_SECTION_TWO &285a 80 2c ; sprite &0d - COLOUR_1_HOLE_SECTION_THREE &285c e0 2d ; sprite &0e - COLOUR_5_BRICKWORK_WITH_COLOUR_7_MORTAR &285e 00 2e ; sprite &0f - COLOUR_5_BRICKWORK_WITH_COLOUR_7_MORTAR_OFFSET &2862 20 2d ; sprite &10 - RED_MONSTER &2862 60 2d ; sprite &11 - RED_MONSTER_FRAME_1 &2864 a0 2c ; sprite &12 - RED_MONSTER_TRAPPED &2866 e0 2c ; sprite &13 - RED_MONSTER_TRAPPED_FRAME_1 &2868 20 2e ; sprite &14 - GREEN_MONSTER &286a 00 06 ; sprite &15 - GREEN_MONSTER_FRAME_1 &286c 80 06 ; sprite &16 - GREEN_MONSTER_TRAPPED &286e c0 06 ; sprite &17 - GREEN_MONSTER_TRAPPED_FRAME_1 &2870 60 2e ; sprite &18 - WHITE_MONSTER &2872 40 06 ; sprite &19 - WHITE_MONSTER_FRAME_1 &2874 00 07 ; sprite &1a - WHITE_MONSTER_TRAPPED &2876 40 07 ; sprite &1b - WHITE_MONSTER_TRAPPED_FRAME_1 &2878 a0 2e ; sprite &1c - COLOUR_0_BLOCK &287a c0 2e ; sprite &1d - COLOUR_15_INVERSE_OF_ONE_DIG_HOLE &287c e0 2e ; sprite &1e - COLOUR_15_INVERSE_OF_TWO_DIG_HOLE &287e 00 2f ; sprite &1f - COLOUR_4_HOLE_SECTION_THREE &2880 20 2f ; sprite &20 - COLOUR_4_HOLE_SECTION_TWO &2882 40 2f ; sprite &21 - COLOUR_4_HOLE_SECTION_ONE &2884 60 2f ; sprite &22 - COLOUR_2_MORTAR &2886 80 2f ; sprite &23 - COLOUR_2_MORTAR_OFFSET &2888 a0 2f ; sprite &24 - COLOUR_14_BLOCK &288a a0 2f ; sprite &25 - COLOUR_14_BLOCK &288c c0 2f ; sprite &26 - COLOUR_4_BRICKWORK_WITH_COLOUR_6_MORTAR &288e e0 2f ; sprite &27 - COLOUR_4_BRICKWORK_WITH_COLOUR_6_MORTAR_OFFSET &2890 00 04 ; sprite &28 - DIGIT_0 &2892 20 04 ; sprite &29 - DIGIT_1 &2894 40 04 ; sprite &2a - DIGIT_2 &2896 60 04 ; sprite &2b - DIGIT_3 &2898 80 04 ; sprite &2c - DIGIT_4 &289a a0 04 ; sprite &2d - DIGIT_5 &289c c0 04 ; sprite &2e - DIGIT_6 &289e e0 04 ; sprite &2f - DIGIT_7 &28a0 00 05 ; sprite &30 - DIGIT_8 &28a2 20 05 ; sprite &31 - DIGIT_9 &28a4 40 05 ; sprite &32 - RED_MONSTER_EATING_PLAYER &28a6 80 05 ; sprite &33 - GREEN_MONSTER_EATING_PLAYER &28a8 c0 05 ; sprite &34 - WHITE_MONSTER_EATING_PLAYER &28aa 80 07 ; sprite &35 - COLOUR_2_PLAYER_LIFE &28ac c0 07 ; sprite &36 - ASPHYXIATED_PLAYER_FEET &28ae e0 07 ; sprite &37 - ASPHYXIATED_PLAYER_HEAD ; unused &28b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # Again, would allow for a further eight sprites ; calculate_screen_address &28c0 8a TXA &28c1 29 fe AND #&fe &28c3 0a ASL A &28c4 85 70 STA &70 ; x_low &28c6 a9 00 LDA #&00 &28c8 2a ROL A &28c9 06 70 ASL &70 ; x_low &28cb 2a ROL A &28cc 85 71 STA &71 ; x_high &28ce 98 TYA &28cf 49 ff EOR #&ff &28d1 29 07 AND #&07 &28d3 0a ASL A &28d4 85 72 STA &72 ; screen_address_low &28d6 98 TYA &28d7 49 ff EOR #&ff &28d9 29 f8 AND #&f8 &28db 4a LSR A &28dc 4a LSR A &28dd 85 73 STA &73 ; screen_address_high &28df 4a LSR A &28e0 4a LSR A &28e1 66 72 ROR &72 ; screen_address_low &28e3 18 CLC &28e4 65 73 ADC &73 ; screen_address_high &28e6 65 71 ADC &71 ; x_high &28e8 69 30 ADC #&30 &28ea 85 73 STA &73 ; screen_address_high &28ec a5 72 LDA &72 ; screen_address_low &28ee 18 CLC &28ef 65 70 ADC &70 ; x_low &28f1 85 72 STA &72 ; screen_address_low &28f3 a9 00 LDA #&00 &28f5 65 73 ADC &73 ; screen_address_high &28f7 85 73 STA &73 ; screen_address_high &28f9 60 RTS ; plot_sprite_at_x_y &28fa 8d ad 22 STA &22ad ; sprite_to_plot &28fd e0 a0 CPX #&a0 &28ff b0 6b BCS &296c ; leave # Don't plot anything beyond right edge of screen &2901 20 c0 28 JSR &28c0 ; calculate_screen_address &2904 ad ad 22 LDA &22ad ; sprite_to_plot ; plot_sprite_at_screen_address &2907 8d ad 22 STA &22ad ; sprite_to_plot &290a 29 80 AND #&80 &290c 4a LSR A w290d 4a LSR A &290e e9 51 SBC #&51 # &31 = AND (&??),Y, &51 = EOR (&??),Y &2910 49 ff EOR #&ff &2912 8d 32 29 STA &2932 ; eor_instruction # Self-modifying code &2915 ad ad 22 LDA &22ad ; sprite_to_plot &2918 29 7f AND #&7f &291a c9 38 CMP #&38 &291c b0 4e BCS &296c ; leave # Only sprites &00 - &37 are defined &291e a8 TAY &291f 0a ASL A &2920 aa TAX &2921 bd 40 28 LDA &2840,X ; sprite_address_table &2924 85 74 STA &74 ; sprite_address_low &2926 bd 41 28 LDA &2841,X ; sprite_address_table + 1 &2929 85 75 STA &75 ; sprite_address_high &292b be 00 28 LDX &2800,Y ; sprite_height_table ; plot_sprite_vertical_loop &292e a0 18 LDY #&18 # +6 pixels right; all sprites are 8 pixels wide ; plot_sprite_horizontal_loop &2930 b1 72 LDA (&72),Y ; screen_address ; eor_instruction &2932 51 74 EOR (&74),Y ; sprite_address # also AND (&74),Y ; sprite_address # AND if sprite & &80 is set &2934 91 72 STA (&72),Y ; screen_address &2936 98 TYA &2937 38 SEC &2938 e9 08 SBC #&08 # Move two pixels left &293a a8 TAY &293b 10 f3 BPL &2930 ; plot_sprite_horizontal_loop # until the left of the sprite is reached &293d ca DEX &293e 30 2c BMI &296c ; leave &2940 e6 74 INC &74 ; sprite_address_low # Move down a row of sprite data &2942 a4 74 LDY &74 ; sprite_address_low &2944 98 TYA &2945 29 07 AND #&07 &2947 d0 0b BNE &2954 ; same_group_of_sprite_data &2949 88 DEY &294a 98 TYA &294b 18 CLC &294c 69 19 ADC #&19 &294e 85 74 STA &74 ; sprite_address_low &2950 90 02 BCC &2954 &2952 e6 75 INC &75 ; sprite_address_high ; same_group_of_sprite_data &2954 e6 72 INC &72 ; screen_address_low # Move one pixel down &2956 a4 72 LDY &72 ; screen_address_low &2958 98 TYA &2959 29 07 AND #&07 &295b d0 d1 BNE &292e ; plot_sprite_vertical_loop &295d 88 DEY # moving to next group of eight lines if necessary &295e 98 TYA &295f 18 CLC &2960 69 79 ADC #&79 &2962 85 72 STA &72 ; screen_address_low &2964 a5 73 LDA &73 ; sprite_address_high &2966 69 02 ADC #&02 &2968 85 73 STA &73 ; sprite_address_high &296a 90 c2 BCC &292e ; plot_sprite_vertical_loop ; leave &296c 60 RTS ; get_screen_colour_at_position &296d 8a TXA &296e 48 PHA &296f 8e af 22 STX &22af ; screen_x &2972 8c b0 22 STY &22b0 ; screen_y &2975 20 c0 28 JSR &28c0 ; calculate_screen_address &2978 a0 00 LDY #&00 &297a b1 72 LDA (&72),Y ; screen_address # Get a byte of screen memory corresponding to position &297c 8c ac 22 STY &22ac ; screen_colour &297f 6e af 22 ROR &22af ; screen_x &2982 b0 01 BCS &2985 ; x_is_odd # If x is even, consider left pixel, otherwise right ; get_screen_colour_at_position_loop &2984 4a LSR A ; x_is_odd &2985 8d ae 22 STA &22ae ; screen_value &2988 39 d0 22 AND &22d0,Y ; bit_table &298b 0d ac 22 ORA &22ac ; screen_colour &298e 8d ac 22 STA &22ac ; screen_colour &2991 ad ae 22 LDA &22ae ; screen_value &2994 c8 INY &2995 c0 04 CPY #&04 &2997 d0 eb BNE &2984 ; get_screen_colour_at_position_loop &2999 68 PLA &299a aa TAX ; x # Restore original X and Y, leave with A = screen_colour &299b ad ac 22 LDA &22ac ; screen_colour &299e ac b0 22 LDY &22b0 ; screen_y &29a1 60 RTS ; unused &29a2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &29b2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite_data ; sprite &00 - PLAYER_RUNNING_LEFT &29c0 00 00 00 00 08 01 00 00 04 0c 0c 04 03 01 01 01 &29d0 08 0c 0c 08 03 02 02 02 00 00 00 00 00 02 04 00 &29e0 00 05 05 05 05 0f 00 00 05 0f 0f 00 00 00 00 00 &29f0 0a 0a 0a 0a 0f 0f 00 00 00 00 00 00 0a 0a 0a 0a ; sprite &01 - PLAYER_RUNNING_LEFT_FRAME_1 &2a00 00 00 00 00 08 01 00 00 04 0c 0c 04 03 01 01 01 &2a10 08 0c 0c 08 03 02 02 02 00 00 00 00 00 02 04 00 &2a20 00 00 00 00 00 00 00 05 05 0f 0f 0a 0a 0a 0a 0a &2a30 0a 0a 0f 0f 00 00 00 00 00 00 0f 0f 05 05 00 00 ; sprite &02 - PLAYER_RUNNING_RIGHT &2a40 00 00 00 00 00 01 08 00 04 0c 0c 04 03 01 01 01 &2a50 08 0c 0c 08 03 02 02 02 00 00 00 00 04 02 00 00 &2a60 00 00 00 00 05 05 05 05 05 05 05 05 0f 0f 00 00 &2a70 0a 0f 0f 00 00 00 00 00 00 0a 0a 0a 0a 0f 00 00 ; sprite &03 - PLAYER_RUNNING_RIGHT_FRAME_1 &2a80 00 00 00 00 00 01 08 00 04 0c 0c 04 03 01 01 01 &2a90 08 0c 0c 08 03 02 02 02 00 00 00 00 04 02 00 00 &2aa0 00 00 0f 0f 0a 0a 00 00 05 05 0f 0f 00 00 00 00 &2ab0 0a 0f 0f 05 05 05 05 05 00 00 00 00 00 00 00 0a ; sprite &04 - PLAYER_CLIMBING &2ac0 08 02 02 02 03 00 00 00 04 0c 0c 04 03 01 01 0f &2ad0 08 0c 0c 08 03 02 02 0f 00 00 04 01 03 00 00 00 &2ae0 00 00 05 00 00 00 00 00 0f 0a 0a 00 00 00 00 00 &2af0 0f 05 05 05 05 05 05 05 00 00 00 00 00 00 00 0a ; sprite &05 - PLAYER_CLIMBING_FRAME_1 &2b00 00 00 08 02 03 00 00 00 04 0c 0c 04 03 01 01 0f &2b10 08 0c 0c 08 03 02 02 0f 04 01 01 01 03 00 00 00 &2b20 00 00 00 00 00 00 00 05 0f 0a 0a 0a 0a 0a 0a 0a &2b30 0f 05 05 00 00 00 00 00 00 00 0a 00 00 00 00 00 ; sprite &06 - PLAYER_DIGGING_LEFT &2b40 00 00 00 00 00 00 00 00 0f 0f 0a 0a 0a 09 00 00 &2b50 04 0c 0c 04 01 03 01 01 08 0c 0c 08 02 02 02 02 &2b60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &2b70 05 05 05 05 05 05 05 0f 0a 0a 0a 0a 0a 0a 0a 0a ; sprite &07 - PLAYER_DIGGING_LEFT_FRAME_1 &2b80 00 00 00 00 00 00 00 00 00 04 04 00 00 00 00 00 &2b90 0c 0c 0c 0c 01 01 03 03 00 08 08 00 02 02 02 02 &2ba0 00 00 00 00 00 00 05 0f 01 08 0a 0a 0a 0a 0a 00 &2bb0 05 05 05 05 05 05 05 0f 0a 0a 0a 0f 0f 05 00 00 ; sprite &08 - PLAYER_DIGGING_RIGHT &2bc0 04 0c 0c 04 01 01 01 01 08 0c 0c 08 02 03 02 02 &2bd0 0f 0f 05 05 05 06 00 00 00 00 00 00 00 00 00 00 &2be0 05 05 05 05 05 05 05 05 0a 0a 0a 0a 0a 0a 0a 0f &2bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &09 - PLAYER_DIGGING_RIGHT_FRAME_1 &2c00 00 04 04 00 01 01 01 01 0c 0c 0c 0c 02 02 03 03 &2c10 00 08 08 00 00 00 00 00 00 00 00 00 00 00 00 00 &2c20 05 05 05 0f 0f 0a 00 00 0a 0a 0a 0a 0a 0a 0a 0f &2c30 02 04 05 05 05 05 05 00 00 00 00 00 00 00 0a 0f ; sprite &0b - COLOUR_1_HOLE_SECTION_ONE &2c40 03 01 00 00 00 00 00 00 03 03 03 00 00 00 00 00 &2c50 03 03 03 00 00 00 00 00 03 02 00 00 00 00 00 00 ; sprite &0c - COLOUR_1_HOLE_SECTION_TWO &2c60 00 02 03 03 03 01 00 00 00 00 00 03 03 03 01 00 &2c70 00 00 00 03 03 03 02 00 00 01 03 03 03 02 00 00 ; sprite &0d - COLOUR_1_HOLE_SECTION_THREE &2c80 00 00 00 00 00 02 03 03 00 00 00 00 00 00 02 03 &2c90 00 00 00 00 00 00 01 03 00 00 00 00 00 01 03 03 ; sprite &12 - RED_MONSTER_TRAPPED &2ca0 0f 05 05 05 00 00 01 03 00 00 00 0a 0a 0a 03 03 &2cb0 00 00 00 05 05 05 03 03 0f 0a 0a 0a 00 00 02 03 &2cc0 06 06 03 03 01 01 00 00 09 01 03 03 03 01 00 00 &2cd0 06 06 03 03 03 02 00 00 09 01 03 03 02 02 00 00 ; sprite &13 - RED_MONSTER_TRAPPED_FRAME_1 &2ce0 0f 05 05 05 05 05 00 00 00 00 00 00 00 0a 0a 0a &2cf0 00 00 00 00 00 05 05 05 0f 0a 0a 0a 0a 0a 00 00 &2d00 01 03 06 02 03 03 01 01 03 03 09 09 03 03 03 01 &2d10 03 03 06 02 03 03 03 02 02 03 09 09 03 03 02 02 ; sprite &10 - RED_MONSTER &2d20 00 00 00 00 0f 00 00 01 00 00 00 00 00 0a 03 03 &2d30 00 00 00 00 00 05 03 03 00 00 00 00 0f 00 00 02 &2d40 03 06 06 03 03 01 01 01 03 01 09 03 03 03 01 01 &2d50 03 06 06 03 03 03 02 02 03 01 09 03 03 02 02 02 ; sprite &11 - RED_MONSTER_FRAME_1 &2d60 00 00 00 00 05 0a 00 01 00 00 00 00 00 0a 03 03 &2d70 00 00 00 00 00 05 03 03 00 00 00 00 0a 05 00 02 &2d80 03 06 06 03 03 01 01 01 03 01 09 03 03 03 01 01 &2d90 03 06 06 03 03 03 02 02 03 01 09 03 03 02 02 02 ; sprite &0a - PLAYER_FALLING &2da0 08 02 02 02 03 00 00 00 04 0c 0c 04 03 01 01 0f &2db0 08 0c 0c 08 03 02 02 0f 04 01 01 01 03 00 00 00 &2dc0 00 00 00 00 00 00 00 05 0f 0a 0a 0a 0a 0a 0a 0a &2dd0 0f 05 05 05 05 05 05 05 00 00 00 00 00 00 00 0a ; sprite &0e - COLOUR_5_BRICKWORK_WITH_COLOUR_7_MORTAR &2de0 37 37 37 3f 33 33 33 33 33 33 33 3f 33 33 33 33 &2df0 33 33 33 3f 37 37 37 37 33 33 33 3f 33 33 33 33 ; sprite &0f - COLOUR_5_BRICKWORK_WITH_COLOUR_7_MORTAR_OFFSET &2e00 33 33 33 3f 37 37 37 37 33 33 33 3f 33 33 33 33 &2e10 37 37 37 3f 33 33 33 33 33 33 33 3f 33 33 33 33 ; sprite &14 - GREEN_MONSTER &2e20 00 00 00 00 10 10 30 20 00 00 20 20 20 30 30 10 &2e30 00 00 10 10 10 30 30 20 00 00 00 00 20 20 30 10 &2e40 30 24 24 30 10 00 00 01 30 10 18 30 30 20 02 02 &2e50 30 24 24 30 30 10 01 01 30 10 18 30 20 00 00 02 ; sprite &18 - WHITE_MONSTER &2e60 00 00 00 04 08 00 04 04 00 00 00 08 08 08 08 04 &2e70 00 00 00 04 04 04 04 08 00 00 00 08 04 00 08 08 &2e80 0c 09 09 09 0c 01 00 01 0d 05 05 07 0d 03 03 02 &2e90 0e 0b 0b 0b 0e 03 03 01 0c 04 04 06 0c 02 00 02 ; sprite &1c - COLOUR_0_BLOCK &2ea0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &2eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &1d - COLOUR_15_INVERSE_OF_ONE_DIG_HOLE &2ec0 00 aa ff ff ff ff ff ff 00 00 00 ff ff ff ff ff &2ed0 00 00 00 ff ff ff ff ff 00 55 ff ff ff ff ff ff ; sprite &1e - COLOUR_15_INVERSE_OF_TWO_DIG_HOLE &2ee0 00 00 00 00 00 aa ff ff 00 00 00 00 00 00 aa ff &2ef0 00 00 00 00 00 00 55 ff 00 00 00 00 00 55 ff ff ; sprite &1f - COLOUR_4_HOLE_SECTION_THREE &2f00 00 00 00 00 00 20 30 30 00 00 00 00 00 00 20 30 &2f10 00 00 00 00 00 00 10 30 00 00 00 00 00 10 30 30 ; sprite &20 - COLOUR_4_HOLE_SECTION_TWO &2f20 00 20 30 30 30 10 00 00 00 00 00 30 30 30 10 00 &2f30 00 00 00 30 30 30 20 00 00 10 30 30 30 20 00 00 ; sprite &21 - COLOUR_4_HOLE_SECTION_ONE &2f40 30 10 00 00 00 00 00 00 30 30 30 00 00 00 00 00 &2f50 30 30 30 00 00 00 00 00 30 20 00 00 00 00 00 00 ; sprite &22 - COLOUR_2_MORTAR &2f60 04 04 04 0c 00 00 00 00 00 00 00 0c 00 00 00 00 &2f70 00 00 00 0c 04 04 04 04 00 00 00 0c 00 00 00 00 ; sprite &23 - COLOUR_2_MORTAR_OFFSET &2f80 00 00 00 0c 04 04 04 04 00 00 00 0c 00 00 00 00 &2f90 04 04 04 0c 00 00 00 00 00 00 00 0c 00 00 00 00 ; sprite &24, &25 - COLOUR_14_BLOCK &2fa0 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 &2fb0 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 ; sprite &26 - COLOUR_4_BRICKWORK_WITH_COLOUR_6_MORTAR &2fc0 34 34 34 3c 30 30 30 30 30 30 30 3c 30 30 30 30 &2fd0 30 30 30 3c 34 34 34 34 30 30 30 3c 30 30 30 30 ; sprite &27 - COLOUR_4_BRICKWORK_WITH_COLOUR_6_MORTAR_OFFSET &2fe0 30 30 30 3c 34 34 34 34 30 30 30 3c 30 30 30 30 &2ff0 34 34 34 3c 30 30 30 30 30 30 30 3c 30 30 30 30 ; sprite &28 - DIGIT_0 &0400 0c 08 08 08 08 08 0c 00 08 08 08 08 08 08 08 00 # Further relocated from &3000-&33ff to &0400-&07ff &0410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &29 - DIGIT_1 &0420 04 0c 04 04 04 04 0c 00 00 00 00 00 00 00 08 00 &0430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &2a - DIGIT_2 &0440 0c 00 00 0c 08 08 0c 00 08 08 08 08 00 00 08 00 &0450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &2b - DIGIT_3 &0460 0c 00 00 0c 00 00 0c 00 08 08 08 08 08 08 08 00 &0470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &2c - DIGIT_4 &0480 08 08 08 0c 00 00 00 00 08 08 08 08 08 08 08 00 &0490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &2d - DIGIT_5 &04a0 0c 08 08 0c 00 00 0c 00 08 00 00 08 08 08 08 00 &04b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &2e - DIGIT_6 &04c0 08 08 08 0c 08 08 0c 00 00 00 00 08 08 08 08 00 &04d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &2f - DIGIT_7 &04e0 0c 00 00 00 00 00 00 00 08 08 08 08 08 08 08 00 &04f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &30 - DIGIT_8 &0500 0c 08 08 0c 08 08 0c 00 08 08 08 08 08 08 08 00 &0510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &31 - DIGIT_9 &0520 0c 08 08 0c 00 00 00 00 08 08 08 08 08 08 08 00 &0530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; sprite &32 - RED_MONSTER_EATING_PLAYER &0540 00 00 00 00 05 0a 00 03 00 00 00 01 01 0a 03 03 &0550 04 0c 0c 04 03 03 03 03 08 0c 0c 08 02 03 03 02 &0560 03 06 06 03 03 01 01 01 03 01 09 03 03 03 01 01 &0570 03 06 06 03 03 03 02 02 03 01 09 03 03 02 02 02 ; sprite &33 - GREEN_MONSTER_EATING_PLAYER &0580 00 00 00 00 10 10 30 20 00 00 20 21 21 21 30 01 &0590 04 0c 0c 04 03 03 03 03 08 0c 0c 08 02 03 03 21 &05a0 30 24 24 30 10 00 00 01 21 01 09 30 30 20 02 02 &05b0 03 03 06 30 30 10 01 01 12 10 18 30 20 00 00 02 ; sprite &34 - WHITE_MONSTER_EATING_PLAYER &05c0 00 00 00 04 08 00 04 04 00 00 01 09 09 08 09 01 &05d0 04 0c 0c 04 03 03 03 03 08 0c 0c 08 02 03 01 00 &05e0 0c 09 09 09 0c 01 00 01 09 01 01 07 0d 03 03 02 &05f0 03 03 03 0b 0e 03 03 01 0c 04 04 06 0c 02 00 02 ; sprite &15 - GREEN_MONSTER_FRAME_1 &0600 00 00 10 10 10 30 30 20 00 00 00 00 20 30 30 10 &0610 00 00 00 00 10 30 30 20 00 00 20 20 20 30 30 10 &0620 30 24 24 30 10 00 00 01 30 10 18 30 30 20 02 02 &0630 30 24 24 30 30 10 01 01 30 10 18 30 20 00 00 02 ; sprite &19 - WHITE_MONSTER_FRAME_1 &0640 00 00 00 00 04 00 04 04 00 00 00 0c 04 0c 08 04 &0650 00 00 00 0c 08 0c 04 08 00 00 00 00 08 00 08 08 &0660 0c 09 09 09 0c 01 00 01 0d 05 05 07 0d 03 03 02 &0670 0e 0b 0b 0b 0e 03 03 01 0c 04 04 06 0c 02 00 02 ; sprite &16 - GREEN_MONSTER_TRAPPED &0680 00 30 10 10 10 30 20 30 00 00 00 20 30 30 10 30 &0690 00 00 00 10 30 30 20 30 00 30 20 20 20 30 10 30 &06a0 24 24 30 10 00 00 01 00 10 18 30 30 20 02 02 00 &06b0 24 24 30 30 10 01 01 00 10 18 30 20 00 00 02 00 ; sprite &17 - GREEN_MONSTER_TRAPPED_FRAME_1 &06c0 00 30 10 10 10 10 30 20 00 00 00 20 30 30 30 10 &06d0 00 00 00 10 30 30 30 20 00 30 20 20 20 20 30 10 &06e0 30 24 20 30 10 00 00 01 30 18 18 30 30 20 02 02 &06f0 30 24 20 30 30 10 01 01 30 18 18 30 20 00 00 02 ; sprite &1a - WHITE_MONSTER_TRAPPED &0700 04 08 00 04 04 04 0c 09 08 08 08 08 00 04 0d 05 &0710 04 04 04 04 00 08 0e 0b 08 04 00 08 08 08 0c 04 &0720 09 09 0c 01 00 01 00 00 05 07 0d 03 03 02 00 00 &0730 0b 0b 0e 03 03 01 00 00 04 06 0c 02 00 02 00 00 ; sprite &1b - WHITE_MONSTER_TRAPPED_FRAME_1 &0740 04 08 00 00 04 04 04 0c 08 08 08 08 08 00 04 0d &0750 04 04 04 04 04 00 08 0e 08 04 00 00 08 08 08 0c &0760 09 08 08 0c 01 00 01 00 07 07 07 0d 03 03 02 00 &0770 0b 0a 0a 0e 03 03 01 00 06 06 06 0c 02 00 02 00 ; sprite &35 - COLOUR_2_PLAYER_LIFE &0780 00 00 00 00 00 04 08 00 04 0c 0c 04 0c 04 04 04 &0790 08 0c 0c 08 0c 08 08 08 00 00 00 00 04 08 00 00 &07a0 00 00 00 00 04 04 04 04 04 04 04 04 0c 0c 00 00 &07b0 08 0c 0c 00 00 00 00 00 00 08 08 08 08 0c 00 00 ; sprite &36 - ASPHYXIATED_PLAYER_FEET &07c0 00 00 00 0a 0a 0f 0f 0f 00 00 00 00 00 0f 0f 0f &07d0 00 00 00 00 00 0b 0b 0b 00 00 00 08 09 03 03 03 ; sprite &37 - ASPHYXIATED_PLAYER_HEAD &07e0 00 00 00 00 03 03 03 03 00 00 04 04 0c 0c 0c 0c &07f0 00 00 08 08 0c 0c 0c 0c 00 00 00 00 00 00 00 00