Super Invaders disassembly ========================== Super Invaders was written by Geoff Crammond, and was published by Acornsoft for the BBC Micro in 1982. It is a clone of Taito's 1978 Space Invaders. The following disassembly was created by reverse engineering binary images, 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. Interesting pokes ================= &204c = &04 (optionally &1f42 = &90) make a TERRIFYING EXPERIENCE even more terrifying &1cb0 = &60 infinite lives Game disassembly ================ ; INVADER2 ; 00000E00 00001CF5 2200 &0e00 0d # Start of BASIC program &0e01 ff # End of BASIC program ; plot_or_unplot_sprite &0e02 a9 00 LDA #&00 # &00 to use EOR plotting, checking for collision &0e04 4c 09 0e JMP &0e09 ; set_plotting_mode ; plot_sprite &0e07 a9 40 LDA #&40 # &40 to use OR plotting, checking for collision ; set_plotting_mode &0e09 85 81 STA &81 ; plotting_mode ; check_for_collision &0e0b 8e fe 0c STX &0cfe ; tmp_x &0e0e 8c ff 0c STY &0cff ; tmp_y &0e11 a5 79 LDA &79 ; sprite &0e13 0a ASL A &0e14 0a ASL A &0e15 65 76 ADC &76 ; sprite_x_fraction &0e17 0a ASL A &0e18 a8 TAY &0e19 b9 f8 2b LDA &2bf8,Y ; sprite_addresses_table - 8 &0e1c 85 8c STA &8c ; sprite_offsets_address_low &0e1e b9 f9 2b LDA &2bf9,Y ; sprite_addresses_table - 8 + 1 &0e21 85 8d STA &8d ; sprite_offsets_address_high &0e23 a0 00 LDY #&00 &0e25 84 86 STY &86 ; collision &0e27 b1 8c LDA (&8c),Y ; sprite_offsets_address # Get byte of sprite data for number of bytes to plot &0e29 85 72 STA &72 ; unused # Unused variable &0e2b 69 01 ADC #&01 &0e2d 65 8c ADC &8c ; sprite_offsets_address_low &0e2f 85 8e STA &8e ; sprite_data_address_low &0e31 a5 8d LDA &8d ; sprite_offsets_address_high &0e33 69 00 ADC #&00 &0e35 85 8f STA &8f ; sprite_data_address_high &0e37 a0 01 LDY #&01 &0e39 84 75 STY &75 ; data_offset &0e3b a6 71 LDX &71 ; sprite_y &0e3d b1 8c LDA (&8c),Y ; sprite_offsets_address # Get first byte of offset data &0e3f 0a ASL A &0e40 0a ASL A ; plot_sprite_row_loop &0e41 85 74 STA &74 ; screen_offset &0e43 a4 70 LDY &70 ; sprite_x &0e45 bd 00 2d LDA &2d00,X ; row_addresses_low_table &0e48 79 00 2f ADC &2f00,Y ; column_offsets_low_table &0e4b 85 82 STA &82 ; screen_address_low &0e4d bd 00 2e LDA &2e00,X ; row_addresses_high_table &0e50 79 50 2f ADC &2f50,Y ; column_offsets_high_table &0e53 85 83 STA &83 ; screen_address_high ; plot_sprite_column_loop &0e55 a4 75 LDY &75 ; data_offset &0e57 b1 8e LDA (&8e),Y ; sprite_data_address # Get byte of sprite data &0e59 85 85 STA &85 ; sprite_byte &0e5b a4 81 LDY &81 ; plotting_mode &0e5d 30 1e BMI &0e7d ; is_checking_for_collision &0e5f d0 29 BNE &0e8a ; is_plotting ; is_plotting_or_unplotting # Plotting mode &00 EORs sprite data to screen &0e61 a4 74 LDY &74 ; screen_offset &0e63 31 82 AND (&82),Y ; screen_address # (sprite AND screen), i.e. check if sprite plotted &0e65 45 85 EOR &85 ; sprite_byte &0e67 d0 09 BNE &0e72 ; collision_when_plotting_or_unplotting # Treat as collision if anything else plotted &0e69 a5 85 LDA &85 ; sprite_byte &0e6b 51 82 EOR (&82),Y ; screen_address # Otherwise unplot sprite &0e6d 91 82 STA (&82),Y ; screen_address &0e6f 4c 98 0e JMP &0e98 ; next_column ; collision_when_plotting_or_unplotting # If there is a collision, &0e72 11 82 ORA (&82),Y ; screen_address &0e74 45 85 EOR &85 ; sprite_byte # ((sprite AND screen) OR screen) EOR sprite &0e76 91 82 STA (&82),Y ; screen_address # i.e. keep only bits set in screen but not sprite &0e78 e6 86 INC &86 ; collision &0e7a 4c 98 0e JMP &0e98 ; next_column ; is_checking_for_collision # Plotting mode &ff checks for collision &0e7d a4 74 LDY &74 ; screen_offset &0e7f 31 82 AND (&82),Y ; screen_address # (sprite AND screen), i.e. check if sprite plotted &0e81 45 85 EOR &85 ; sprite_byte &0e83 f0 13 BEQ &0e98 ; next_column # Treat as collision if anything else plotted &0e85 e6 86 INC &86 ; collision &0e87 4c 98 0e JMP &0e98 ; next_column ; is_plotting # Plotting mode &40 ORs sprite data to screen &0e8a a4 74 LDY &74 ; screen_offset &0e8c 31 82 AND (&82),Y ; screen_address # (sprite AND screen), i.e. check if sprite plotted &0e8e f0 02 BEQ &0e92 ; no_collision_when_plotting &0e90 e6 86 INC &86 ; collision # Treat as collision if anything else plotted ; no_collision_when_plotting &0e92 a5 85 LDA &85 ; sprite_byte &0e94 11 82 ORA (&82),Y ; screen_address # Plot sprite &0e96 91 82 STA (&82),Y ; screen_address ; next_column &0e98 e6 75 INC &75 ; data_offset &0e9a a4 75 LDY &75 ; data_offset &0e9c b1 8c LDA (&8c),Y ; sprite_offsets_address # Get byte of offset data &0e9e 0a ASL A # Top bit set to stay on current row &0e9f 85 74 STA &74 ; screen_offset &0ea1 b0 b2 BCS &0e55 ; plot_sprite_column_loop # Top bit clear to move to next row &0ea3 e8 INX # Move down a row &0ea4 0a ASL A &0ea5 90 9a BCC &0e41 ; plot_sprite_row_loop # Second top bit set indicates end of sprite &0ea7 ae fe 0c LDX &0cfe ; tmp_x &0eaa ac ff 0c LDY &0cff ; tmp-y &0ead 60 RTS ; update_movers &0eae a2 00 LDX #&00 ; update_movers_loop &0eb0 86 8d STX &8d ; mover_offset &0eb2 bd 00 0c LDA &0c00,X ; movers_flags &0eb5 85 80 STA &80 ; mover_flags &0eb7 a9 06 LDA #&06 ; MOVER_FLAG_MOVED | MOVER_FLAG_ABSENT &0eb9 24 80 BIT &80 ; mover_flags &0ebb 70 0b BVS &0ec8 ; to_leave # MOVER_FLAG_END &0ebd f0 0c BEQ &0ecb ; update_mover # Update mover only if both flags clear ; update_next_mover &0ebf a5 8d LDA &8d ; mover_offset &0ec1 18 CLC &0ec2 69 10 ADC #&10 # Next mover &0ec4 aa TAX &0ec5 4c b0 0e JMP &0eb0 ; update_movers_loop ; to_leave &0ec8 4c 4c 10 JMP &104c ; leave ; update_mover &0ecb a5 73 LDA &73 ; all_movers_need_updating &0ecd 10 0c BPL &0edb ; skip_flag_check &0ecf a5 80 LDA &80 ; mover_flags &0ed1 29 08 AND #&08 ; MOVER_FLAG_NEEDS_UPDATE &0ed3 f0 ea BEQ &0ebf ; update_next_mover &0ed5 a5 80 LDA &80 ; mover_flags &0ed7 29 f7 AND #&f7 ; !MOVER_FLAG_NEEDS_UPDATE &0ed9 85 80 STA &80 ; mover_flags ; skip_flag_check &0edb bd 0c 0c LDA &0c0c,X ; movers_plotted # Positive if mover plotted &0ede 10 03 BPL &0ee3 ; move_mover &0ee0 4c db 0f JMP &0fdb ; skip_moving_mover ; move_mover &0ee3 bd 05 0c LDA &0c05,X ; movers_energy_y &0ee6 18 CLC &0ee7 7d 06 0c ADC &0c06,X ; movers_speed_y &0eea c9 20 CMP #&20 &0eec 9d 05 0c STA &0c05,X ; movers_energy_y &0eef 90 40 BCC &0f31 ; skip_vertical_movement ; move_mover_vertically &0ef1 85 8c STA &8c ; delta &0ef3 29 1f AND #&1f &0ef5 9d 05 0c STA &0c05,X ; movers_energy_y &0ef8 a5 8c LDA &8c ; delta &0efa 4a LSR A &0efb 4a LSR A &0efc 4a LSR A &0efd 4a LSR A &0efe 4a LSR A &0eff 85 8c STA &8c ; delta &0f01 a5 80 LDA &80 ; mover_flags &0f03 30 0f BMI &0f14 ; move_mover_up # If MOVER_FLAG_UP set, move mover up, otherwise down ; move_mover_down &0f05 bd 08 0c LDA &0c08,X ; movers_new_y &0f08 18 CLC &0f09 65 8c ADC &8c ; delta &0f0b c9 f8 CMP #&f8 &0f0d 85 8f STA &8f ; y &0f0f 90 16 BCC &0f27 ; mover_still_vertically_on_screen &0f11 4c 20 0f JMP &0f20 ; remove_mover_at_vertical_edge_of_screen ; move_mover_up &0f14 bd 08 0c LDA &0c08,X ; movers_new_y &0f17 38 SEC &0f18 e5 8c SBC &8c ; delta &0f1a c9 10 CMP #&10 &0f1c 85 8f STA &8f ; y &0f1e b0 07 BCS &0f27 ; mover_still_vertically_on_screen ; remove_mover_at_vertical_edge_of_screen &0f20 a9 14 LDA #&14 ; SPRITE_MISSILE_REMOVER &0f22 9d 0b 0c STA &0c0b,X ; movers_sprite &0f25 a5 8f LDA &8f ; y ; mover_still_vertically_on_screen &0f27 9d 08 0c STA &0c08,X ; movers_new_y &0f2a a5 80 LDA &80 ; mover_flags &0f2c 09 04 ORA #&04 ; MOVER_FLAG_MOVED &0f2e 9d 00 0c STA &0c00,X ; movers_flags ; skip_vertical_movement &0f31 bd 03 0c LDA &0c03,X ; movers_energy_x &0f34 18 CLC &0f35 7d 04 0c ADC &0c04,X ; movers_speed_x &0f38 c9 20 CMP #&20 &0f3a 9d 03 0c STA &0c03,X ; movers_energy_x &0f3d b0 03 BCS &0f42 ; move_mover_vertically &0f3f 4c 1e 10 JMP &101e ; skip_horizontal_movement ; move_mover_vertically &0f42 85 8c STA &8c ; delta &0f44 29 1f AND #&1f &0f46 9d 03 0c STA &0c03,X ; movers_energy_x &0f49 a5 8c LDA &8c ; delta &0f4b 4a LSR A &0f4c 4a LSR A &0f4d 4a LSR A &0f4e 4a LSR A &0f4f 4a LSR A &0f50 85 8c STA &8c ; delta &0f52 29 03 AND #&03 &0f54 85 8e STA &8e ; x &0f56 a5 80 LDA &80 ; mover_flags &0f58 4a LSR A &0f59 b0 1a BCS &0f75 ; move_mover_left # If MOVER_FLAG_LEFT set, move mover left, otherwise right ; move_mover_right &0f5b bd 02 0c LDA &0c02,X ; movers_new_x_fraction &0f5e 65 8c ADC &8c ; delta &0f60 85 8c STA &8c ; delta &0f62 29 03 AND #&03 &0f64 9d 02 0c STA &0c02,X ; movers_new_x_fraction &0f67 a5 8c LDA &8c ; delta &0f69 4a LSR A &0f6a 4a LSR A &0f6b 18 CLC &0f6c 7d 0a 0c ADC &0c0a,X ; movers_new_x &0f6f 9d 0a 0c STA &0c0a,X ; movers_new_x &0f72 4c 90 0f JMP &0f90 ; consider_mover_type ; move_mover_left &0f75 bd 02 0c LDA &0c02,X ; movers_new_x_fraction &0f78 e5 8e SBC &8e ; x &0f7a 29 03 AND #&03 &0f7c 9d 02 0c STA &0c02,X ; movers_new_x_fraction &0f7f bd 0a 0c LDA &0c0a,X ; movers_new_x &0f82 b0 02 BCS &0f86 ; skip_underflow &0f84 e9 00 SBC #&00 ; skip_underflow &0f86 46 8c LSR &8c ; delta &0f88 46 8c LSR &8c ; delta &0f8a 38 SEC &0f8b e5 8c SBC &8c ; delta &0f8d 9d 0a 0c STA &0c0a,X ; movers_new_x ; consider_mover_type &0f90 e0 30 CPX #&30 ; MOVER_BOMB_TWO &0f92 d0 1a BNE &0fae ; not_bomb &0f94 e0 20 CPX #&20 ; MOVER_BOMB_ONE &0f96 d0 16 BNE &0fae ; not_bomb # Bug: always branches (although bombs home towards &0f98 c9 01 CMP #&01 # player, and player is always within the screen) &0f9a d0 07 BNE &0fa3 ; not_at_left_edge # If the bomb were at the left edge of the screen, ; at_left_edge &0f9c a9 00 LDA #&00 # Clear MOVER_FLAG_LEFT to set it moving right &0f9e 85 80 STA &80 ; mover_flags &0fa0 4c db 0f JMP &0fdb ; not_ufo ; not_at_left_edge &0fa3 c9 4c CMP #&4c &0fa5 90 34 BCC &0fdb ; not_ufo # If the bomb were at the right edge of the screen, ; at_right_edge &0fa7 a9 01 LDA #&01 ; MOVER_FLAG_LEFT # Set MOVER_FLAG_LEFT to set it moving left &0fa9 85 80 STA &80 ; mover_flags &0fab 4c db 0f JMP &0fdb ; not_ufo ; not_bomb &0fae e0 40 CPX #&40 ; MOVER_UFO &0fb0 d0 29 BNE &0fdb ; not_ufo ; is_ufo &0fb2 c9 01 CMP #&01 &0fb4 90 16 BCC &0fcc ; remove_ufo_at_left_of_screen &0fb6 c9 4a CMP #&4a &0fb8 90 21 BCC &0fdb ; skip_removing_ufo ; remove_ufo_at_right_of_screen &0fba a0 00 LDY #&00 &0fbc 8c e8 39 STY &39e8 ; screen_memory + 3 * &280 + &4d * 8 # Unplot part of UFO, triggering collision &0fbf a9 09 LDA #&09 &0fc1 20 5f 12 JSR &125f ; play_sound # Stop UFO sound &0fc4 a9 40 LDA #&40 # &40 to indicate UFO departed to right &0fc6 8d f2 05 STA &05f2 ; ufo_departure_direction # Set to non-zero to add to side walls &0fc9 4c db 0f JMP &0fdb ; skip_moving_mover ; remove_ufo_at_left_of_screen &0fcc a0 00 LDY #&00 &0fce 8c 90 37 STY &3790 ; screen_memory + 3 * &280 + 2 * 8 # Unplot part of UFO, triggering collision &0fd1 a9 09 LDA #&09 &0fd3 20 5f 12 JSR &125f ; play_sound # Stop UFO sound &0fd6 a9 80 LDA #&80 # &80 to indicate UFO departed to left &0fd8 8d f2 05 STA &05f2 ; ufo_departure_direction # Set to non-zero to add to side walls ; skip_removing_ufo ; not_ufo ; skip_moving_mover &0fdb a5 80 LDA &80 ; mover_flags &0fdd 09 04 ORA #&04 ; MOVER_FLAG_MOVED &0fdf 9d 00 0c STA &0c00,X ; movers_flags &0fe2 e0 00 CPX #&00 ; MOVER_PLAYER &0fe4 d0 38 BNE &101e ; not_player ; is_player &0fe6 ad 0a 0c LDA &0c0a ; movers_new_x + &00 (player) &0fe9 cd bc 0c CMP &0cbc ; ground_left_edge_x &0fec b0 0e BCS &0ffc ; not_beyond_left_edge # Is the player beyond the left edge of the ground? ; beyond_left_edge &0fee ad bc 0c LDA &0cbc ; ground_left_edge_x &0ff1 8d 0a 0c STA &0c0a ; movers_new_x + &00 (player) # If so, limit player to ground &0ff4 a9 00 LDA #&00 &0ff6 8d 02 0c STA &0c02 ; movers_new_x_fraction + &00 (player) &0ff9 4c 1e 10 JMP &101e ; not_beyond_right_edge ; not_beyond_left_edge &0ffc ad 0a 0c LDA &0c0a ; movers_new_x + &00 (player) &0fff cd bd 0c CMP &0cbd ; ground_right_edge_x &1002 90 1a BCC &101e ; not_beyond_right_edge # Is the player beyond the right edge of the ground? &1004 f0 0e BEQ &1014 ; check_right_edge_fraction ; beyond_right_edge &1006 ad bd 0c LDA &0cbd ; ground_right_edge_x &1009 8d 0a 0c STA &0c0a ; movers_new_x + &00 (player) # If so, limit player to ground &100c a9 01 LDA #&01 &100e 8d 02 0c STA &0c02 ; movers_new_x_fraction + &00 (player) &1011 4c 1e 10 JMP &101e ; not_beyond_right_edge ; check_right_edge_fraction &1014 a9 01 LDA #&01 &1016 cd 02 0c CMP &0c02 ; movers_new_x_fraction + &00 (player) &1019 b0 03 BCS &101e ; not_beyond_right_edge &101b 8d 02 0c STA &0c02 ; movers_new_x_fraction + &00 (player) ; not_beyond_right_edge ; not_player &101e bd 00 0c LDA &0c00,X ; movers_flags &1021 29 04 AND #&04 ; MOVER_FLAG_MOVED &1023 d0 03 BNE &1028 ; add_mover_to_stack_for_replotting_enemies &1025 4c bf 0e JMP &0ebf ; update_next_mover ; add_mover_to_stack_for_replotting_enemies &1028 8a TXA &1029 18 CLC &102a 69 0c ADC #&0c ; IS_MOVER &102c e0 00 CPX #&00 ; MOVER_PLAYER &102e d0 07 BNE &1037 ; not_player ; is_player &1030 e6 7d INC &7d ; stack_for_replotting_player_offset # Add player to player replot stack &1032 a6 7d LDX &7d ; stack_for_replotting_player_offset &1034 4c 46 10 JMP &1046 ; add_to_order ; not_player &1037 e0 40 CPX #&40 ; MOVER_UFO &1039 f0 07 BEQ &1042 ; is_ufo ; is_missile_or_bomb &103b e6 7c INC &7c ; stack_for_replotting_enemies_offset # Add missiles and bombs to enemy replot stack &103d a6 7c LDX &7c ; stack_for_replotting_enemies_offset &103f 4c 46 10 JMP &1046 ; add_to_order ; is_ufo &1042 e6 7e INC &7e ; stack_for_replotting_ufo_offset # Add UFO to UFO replot stack &1044 a6 7e LDX &7e ; stack_for_replotting_ufo_offset ; add_to_order &1046 9d 00 0c STA &0c00,X ; stack_for_replotting_enemies - &51 &1049 4c bf 0e JMP &0ebf ; update_next_mover ; leave &104c 60 RTS ; replot_enemy_or_mover &104d a6 7f LDX &7f ; stack_offset &104f bd 00 0c LDA &0c00,X ; stack_for_replotting_enemies - &51 # Also player and UFO stacks &1052 f0 40 BEQ &1094 ; to_leave # Leave if nothing on stack &1054 c6 7f DEC &7f ; stack_offset &1056 85 88 STA &88 ; enemy_position_or_mover_offset &1058 29 0f AND #&0f &105a 49 0c EOR #&0c ; IS_MOVER &105c 85 77 STA &77 ; updating_enemy # Set to non-zero if enemy, zero if mover &105e d0 37 BNE &1097 ; is_enemy ; is_mover &1060 a5 88 LDA &88 ; enemy_position_or_mover_offset &1062 29 70 AND #&70 &1064 aa TAX &1065 86 78 STX &78 ; mover_offset &1067 bd 00 0c LDA &0c00,X ; movers_flags &106a 29 fb AND #&fb ; !MOVER_FLAG_MOVED &106c 9d 00 0c STA &0c00,X ; movers_flags &106f 29 02 AND #&02 ; MOVER_FLAG_ABSENT &1071 d0 21 BNE &1094 ; to_leave &1073 bd 01 0c LDA &0c01,X ; movers_x_fraction &1076 85 76 STA &76 ; sprite_x_fraction &1078 bd 07 0c LDA &0c07,X ; movers_y &107b 85 71 STA &71 ; sprite_y &107d bd 09 0c LDA &0c09,X ; movers_x &1080 85 70 STA &70 ; sprite_x &1082 bd 0b 0c LDA &0c0b,X ; movers_sprite &1085 85 79 STA &79 ; sprite &1087 bd 0c 0c LDA &0c0c,X ; movers_plotted # Positive if mover plotted &108a f0 37 BEQ &10c3 ; unplot_sprite_and_consider_collision &108c a9 00 LDA #&00 # Set to positive to indicate mover plotted &108e 9d 0c 0c STA &0c0c,X ; movers_plotted &1091 4c 15 11 JMP &1115 ; plot_sprite_and_consider_collision ; to_leave &1094 4c 76 11 JMP &1176 ; leave ; is_enemy &1097 a5 8a LDA &8a ; wave_x_fraction &1099 85 76 STA &76 ; sprite_x_fraction &109b a5 88 LDA &88 ; enemy_position_or_mover_offset &109d 8d b8 0c STA &0cb8 ; last_replotted_enemy_position &10a0 29 7f AND #&7f &10a2 a8 TAY &10a3 84 78 STY &78 ; row_and_column &10a5 b9 00 05 LDA &0500,Y ; enemies_type - &30 # Negative if enemy has been destroyed &10a8 30 ea BMI &1094 ; to_leave &10aa 85 79 STA &79 ; sprite &10ac 98 TYA &10ad 29 70 AND #&70 &10af aa TAX &10b0 86 7b STX &7b ; row &10b2 bd 0e 05 LDA &050e,X ; enemy_rows_previous_y - &30 &10b5 85 71 STA &71 ; sprite_y &10b7 a5 88 LDA &88 ; enemy_position_or_mover_offset &10b9 29 0f AND #&0f &10bb a8 TAY &10bc b9 10 05 LDA &0510,Y ; enemy_columns_previous_x &10bf 85 70 STA &70 ; sprite_x &10c1 84 7a STY &7a ; column ; unplot_sprite_and_consider_collision &10c3 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot enemy or mover &10c6 a4 77 LDY &77 ; updating_enemy # Non-zero if enemy, zero if mover &10c8 d0 24 BNE &10ee ; replot_enemy ; consider_replotting_mover &10ca a6 78 LDX &78 ; row_and_column &10cc a5 86 LDA &86 ; collision &10ce f0 03 BEQ &10d3 ; replot_mover &10d0 4c 40 11 JMP &1140 ; remove_mover ; replot_mover &10d3 bd 02 0c LDA &0c02,X ; movers_new_x_fraction &10d6 85 76 STA &76 ; sprite_x_fraction &10d8 9d 01 0c STA &0c01,X ; movers_x_fraction &10db bd 08 0c LDA &0c08,X ; movers_new_y &10de 85 71 STA &71 ; sprite_y &10e0 9d 07 0c STA &0c07,X ; movers_y &10e3 bd 0a 0c LDA &0c0a,X ; movers_new_x &10e6 85 70 STA &70 ; sprite_x &10e8 9d 09 0c STA &0c09,X ; movers_x &10eb 4c 15 11 JMP &1115 ; plot_sprite_and_consider_collision # Plot mover ; replot_enemy &10ee a6 7b LDX &7b ; row &10f0 bd 0f 05 LDA &050f,X ; enemy_rows_y - &30 &10f3 85 71 STA &71 ; sprite_y &10f5 cd f3 0c CMP &0cf3 ; wave_lowest_y &10f8 90 03 BCC &10fd ; not_lowest_y &10fa 8d f3 0c STA &0cf3 ; wave_lowest_y ; not_lowest_y &10fd c9 e5 CMP #&e5 &10ff d0 05 BNE &1106 ; not_at_ground &1101 a9 40 LDA #&40 &1103 8d ed 05 STA &05ed ; enemy_reached_ground # Set to non-zero to indicate enemy reached ground ; not_at_ground &1106 a4 7a LDY &7a ; column &1108 b9 20 05 LDA &0520,Y ; enemy_columns_x &110b 85 70 STA &70 ; sprite_x &110d a5 8a LDA &8a ; wave_x_fraction &110f 49 02 EOR #&02 &1111 29 02 AND #&02 &1113 85 76 STA &76 ; sprite_x_fraction ; plot_sprite_and_consider_collision &1115 20 07 0e JSR &0e07 ; plot_sprite # Plot enemy or mover &1118 a5 86 LDA &86 ; collision &111a f0 5a BEQ &1176 ; leave &111c a4 77 LDY &77 ; updating_enemy # Non-zero if enemy, zero if mover &111e d0 4d BNE &116d ; add_collision ; is_mover_collision &1120 a6 78 LDX &78 ; mover_offset &1122 a5 88 LDA &88 ; enemy_position_or_mover_offset &1124 29 30 AND #&30 &1126 f0 10 BEQ &1138 ; keep_existing_sprite ; is_bomb_or_missile &1128 bd 07 0c LDA &0c07,X ; movers_y &112b c9 d5 CMP #&d5 # Has the bomb or missile hit a shield? &112d b0 09 BCS &1138 ; keep_existing_sprite &112f c9 c3 CMP #&c3 &1131 90 05 BCC &1138 ; keep_existing_sprite &1133 a9 0f LDA #&0f ; SPRITE_DAMAGE # If so, use damage sprite &1135 4c 3b 11 JMP &113b ; use_sprite ; keep_existing_sprite &1138 bd 0b 0c LDA &0c0b,X ; movers_sprite ; use_sprite &113b 85 79 STA &79 ; sprite &113d 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot mover at end of life ; remove_mover &1140 bd 00 0c LDA &0c00,X ; movers_flags &1143 09 02 ORA #&02 ; MOVER_FLAG_ABSENT # Set to indicate mover has been removed &1145 9d 00 0c STA &0c00,X ; movers_flags &1148 a5 88 LDA &88 ; enemy_position_or_mover_offset &114a 29 30 AND #&30 &114c d0 0c BNE &115a ; is_bomb_or_missile ; is_player_or_ufo &114e e0 40 CPX #&40 ; MOVER_UFO &1150 d0 24 BNE &1176 ; leave ; is_ufo &1152 a9 09 LDA #&09 &1154 20 5f 12 JSR &125f ; play_sound # Stop UFO sound &1157 4c 76 11 JMP &1176 ; leave ; is_bomb_or_missile &115a 49 10 EOR #&10 &115c d0 0f BNE &116d ; add_collision ; is_missile &115e a5 71 LDA &71 ; sprite_y &1160 8d bb 0c STA &0cbb ; missile_collision_y &1163 a5 70 LDA &70 ; sprite_x &1165 8d ba 0c STA &0cba ; missile_collision_x &1168 a5 76 LDA &76 ; sprite_x_fraction &116a 8d b9 0c STA &0cb9 ; missile_collision_x_fraction ; add_collision &116d e6 87 INC &87 ; collisions_count &116f a5 88 LDA &88 ; enemy_position_or_mover_offset &1171 a6 87 LDX &87 ; collisions_count &1173 9d 80 05 STA &0580,X ; collisions_list ; leave &1176 60 RTS ; update_wave &1177 a5 7c LDA &7c ; stack_for_replotting_enemies_offset &1179 c9 51 CMP #&51 ; &0c51 = stack_for_replotting_enemies &117b d0 5d BNE &11da ; leave # Leave unless the entire wave has finished movement &117d a9 00 LDA #&00 &117f 85 74 STA &74 ; new_direction &1181 ad e6 0c LDA &0ce6 ; wave_movement_cooldown &1184 d0 54 BNE &11da ; leave # Is it time for the wave to move again? &1186 ad 02 05 LDA &0502 ; wave_movement_maximum_cooldown &1189 8d e6 0c STA &0ce6 ; wave_movement_cooldown ; store_previous_columns_x &118c a2 00 LDX #&00 ; store_previous_columns_x_loop &118e bd 20 05 LDA &0520,X ; enemy_columns_x &1191 9d 10 05 STA &0510,X ; enemy_columns_previous_x &1194 e8 INX &1195 e0 0b CPX #&0b &1197 d0 f5 BNE &118e ; store_previous_columns_x_loop ; store_previous_rows_y &1199 a2 00 LDX #&00 ; store_previous_rows_y_loop &119b bd 3f 05 LDA &053f,X ; enemy_rows_y &119e 9d 3e 05 STA &053e,X ; enemy_rows_previous_y &11a1 8a TXA &11a2 18 CLC &11a3 69 10 ADC #&10 # Move up a row &11a5 aa TAX &11a6 e0 50 CPX #&50 &11a8 d0 f1 BNE &119b ; store_previous_rows_y_loop ; recalculate_stack_for_replotting_enemies &11aa a2 2f LDX #&2f ; recalculate_stack_for_replotting_loop &11ac e8 INX &11ad a9 00 LDA #&00 &11af 85 84 STA &84 ; column_has_enemies # Set to zero to indicate no enemies in column &11b1 8a TXA &11b2 a8 TAY ; recalculate_stack_for_replotting_row_loop &11b3 b9 00 05 LDA &0500,Y ; enemies_type - &30 # Negative if enemy has been destroyed &11b6 30 10 BMI &11c8 ; consider_next_enemy &11b8 a9 80 LDA #&80 &11ba 85 84 STA &84 ; column_has_enemies # Set to negative to indicate enemy in column &11bc 86 85 STX &85 ; tmp_x &11be e6 7c INC &7c ; stack_for_replotting_enemies_offset &11c0 a6 7c LDX &7c ; stack_for_replotting_enemies_offset &11c2 98 TYA &11c3 9d 00 0c STA &0c00,X ; stack_for_replotting_enemies - &51 # Add enemy to enemy replot stack &11c6 a6 85 LDX &85 ; tmp_x ; consider_next_enemy &11c8 98 TYA &11c9 18 CLC &11ca 69 10 ADC #&10 # Move up a row &11cc a8 TAY &11cd 10 e4 BPL &11b3 ; recalculate_stack_for_replotting_row_loop &11cf a5 84 LDA &84 ; column_has_enemies # Negative if column contains any enemies &11d1 30 0a BMI &11dd ; has_enemies ; consider_next_column &11d3 e0 3a CPX #&3a # Is this the rightmost column? &11d5 f0 53 BEQ &122a ; finished_moving_wave &11d7 4c ac 11 JMP &11ac ; recalculate_stack_for_replotting_loop ; leave &11da 4c 5e 12 JMP &125e ; leave ; has_enemies &11dd ad 03 05 LDA &0503 ; previous_wave_direction &11e0 cd 04 05 CMP &0504 ; wave_direction # &80 if moving left, &40 if moving right &11e3 f0 0b BEQ &11f0 ; skip_two_step_turn &11e5 ac f3 0c LDY &0cf3 ; wave_lowest_y &11e8 c0 bd CPY #&bd &11ea b0 04 BCS &11f0 ; skip_two_step_turn &11ec a0 01 LDY #&01 &11ee 84 74 STY &74 ; new_direction ; skip_two_step_turn &11f0 8d 04 05 STA &0504 ; wave_direction # &80 if moving left, &40 if moving right &11f3 8a TXA &11f4 29 0f AND #&0f # Extract column &11f6 a8 TAY &11f7 ad 04 05 LDA &0504 ; wave_direction # &80 if moving left, &40 if moving right &11fa 30 17 BMI &1213 ; move_column_left ; move_column_right &11fc b9 20 05 LDA &0520,Y ; enemy_columns_x &11ff 18 CLC &1200 69 01 ADC #&01 &1202 99 20 05 STA &0520,Y ; enemy_columns_x &1205 86 8b STX &8b ; wave_bottom_right_position &1207 cd bf 0c CMP &0cbf ; screen_right_edge_x # Has the wave reached the right edge of the screen? &120a d0 1b BNE &1227 ; finished_moving_column &120c a9 80 LDA #&80 # Set to &80 to start moving left &120e 85 74 STA &74 ; new_direction &1210 4c 27 12 JMP &1227 ; finished_moving_column ; move_column_left &1213 b9 20 05 LDA &0520,Y ; enemy_columns_x &1216 38 SEC &1217 e9 01 SBC #&01 &1219 99 20 05 STA &0520,Y ; enemy_columns_x &121c 86 8b STX &8b ; wave_bottom_right_position &121e cd be 0c CMP &0cbe ; screen_left_edge_x # Has the wave reached the left edge of the screen? &1221 d0 04 BNE &1227 ; finished_moving_column &1223 a9 40 LDA #&40 # Set to &40 to start moving right &1225 85 74 STA &74 ; new_direction ; finished_moving_column &1227 4c d3 11 JMP &11d3 ; consider_next_column ; finished_moving_wave &122a a5 8a LDA &8a ; wave_x_fraction &122c 49 02 EOR #&02 &122e 29 02 AND #&02 &1230 85 8a STA &8a ; wave_x_fraction &1232 ac e9 0c LDY &0ce9 ; enemy_movement_sound_cooldown &1235 d0 03 BNE &123a ; skip_sound &1237 20 5f 12 JSR &125f ; play_sound # Play sound for moving enemies ; skip_sound &123a a5 74 LDA &74 ; new_direction # Non-zero if wave is turning &123c f0 20 BEQ &125e ; leave &123e c9 01 CMP #&01 &1240 f0 03 BEQ &1245 ; is_two_step_turn &1242 8d 03 05 STA &0503 ; previous_wave_direction ; is_two_step_turn &1245 a2 00 LDX #&00 ; move_enemy_rows_down_loop &1247 bd 3f 05 LDA &053f,X ; enemy_rows_y &124a 18 CLC &124b 69 0a ADC #&0a # Move down 10 pixels &124d 9d 3f 05 STA &053f,X ; enemy_rows_y &1250 8a TXA &1251 18 CLC &1252 69 10 ADC #&10 # Move up a row &1254 aa TAX &1255 e0 50 CPX #&50 &1257 d0 ee BNE &1247 ; move_enemy_rows_down_loop &1259 a9 00 LDA #&00 &125b 8d f3 0c STA &0cf3 ; wave_lowest_y # Will be recalculated ; leave &125e 60 RTS ; play_sound &125f 8e fe 0c STX &0cfe ; tmp_x &1262 8c ff 0c STY &0cff ; tmp_y &1265 0a ASL A &1266 0a ASL A &1267 0a ASL A &1268 18 CLC &1269 69 a0 ADC #&a0 ; &2fa0 = sound_data &126b aa TAX &126c a0 2f LDY #&2f &126e a9 07 LDA #&07 ; Generate a sound &1270 20 f1 ff JSR &fff1 ; OSWORD &1273 ae fe 0c LDX &0cfe ; tmp_x &1276 ac ff 0c LDY &0cff ; tmp_y &1279 60 RTS ; initialise_game &127a a9 90 LDA #&90 ; &0c90 = stack_for_replotting_ufo &127c 85 7e STA &7e ; stack_for_replotting_ufo_offset &127e a9 8d LDA #&8d ; &0c8d = stack_for_replotting_player &1280 85 7d STA &7d ; stack_for_replotting_player_offset &1282 a9 51 LDA #&51 ; &0c51 = stack_for_replotting_enemies &1284 85 7c STA &7c ; stack_for_replotting_enemies_offset &1286 a9 00 LDA #&00 &1288 8d 8d 0c STA &0c8d ; stack_for_replotting_player # Set to zero to mark base of player stack &128b 8d 51 0c STA &0c51 ; stack_for_replotting_enemies # Set to zero to mark base of main stack &128e 8d 90 0c STA &0c90 ; stack_for_replotting_ufo # Set to zero to mark base of UFO stack &1291 8d fa 05 STA &05fa ; score &1294 8d fb 05 STA &05fb ; score + 1 &1297 8d f9 05 STA &05f9 ; score_needs_updating # Set to positive to indicate score needs updating &129a a9 40 LDA #&40 &129c 8d f5 0c STA &0cf5 ; level_tally_x &129f a9 09 LDA #&09 &12a1 8d f8 05 STA &05f8 ; number_x # Update score &12a4 a9 12 LDA #&12 &12a6 8d dc 0c STA &0cdc ; difficulties_wave_speeds + 2 &12a9 a9 12 LDA #&12 &12ab 8d db 0c STA &0cdb ; difficulties_wave_speeds + 1 &12ae a9 18 LDA #&18 &12b0 8d da 0c STA &0cda ; difficulties_wave_speeds &12b3 a9 4f LDA #&4f &12b5 8d d9 0c STA &0cd9 ; difficulties_minimum_initial_wave_height + 2 &12b8 a9 4f LDA #&4f &12ba 8d d8 0c STA &0cd8 ; difficulties_minimum_initial_wave_height + 1 &12bd a9 4f LDA #&4f &12bf 8d d7 0c STA &0cd7 ; difficulties_minimum_initial_wave_height &12c2 a9 05 LDA #&05 &12c4 8d bc 0c STA &0cbc ; ground_left_edge_x &12c7 a9 47 LDA #&47 &12c9 8d bd 0c STA &0cbd ; ground_right_edge_x &12cc a9 00 LDA #&00 &12ce 8d be 0c STA &0cbe ; screen_left_edge_x &12d1 a9 4c LDA #&4c &12d3 8d bf 0c STA &0cbf ; screen_right_edge_x &12d6 a9 00 LDA #&00 &12d8 8d ef 05 STA &05ef ; lives &12db 8d ed 05 STA &05ed ; enemy_reached_ground &12de 8d f4 0c STA &0cf4 ; extra_lives_gained &12e1 8d fd 0c STA &0cfd ; unused # Unused variable &12e4 8d f2 05 STA &05f2 ; ufo_departure_direction # Set to zero to suppress addition to side walls &12e7 20 1d 1b JSR &1b1d ; check_for_high_score &12ea 20 fb 1e JSR &1efb ; initialise_cooldowns &12ed 20 19 1f JSR &1f19 ; initialise_wave_alien_types &12f0 20 f0 16 JSR &16f0 ; initialise_movers &12f3 20 6b 20 JSR &206b ; set_default_palette &12f6 20 d1 1d JSR &1dd1 ; initialise_mover_speeds &12f9 20 c7 1c JSR &1cc7 ; initialise_player &12fc 20 0c 13 JSR &130c ; initialise_wave &12ff 20 db 16 JSR &16db ; initialise_stack_for_replotting_enemies &1302 20 84 17 JSR &1784 ; plot_shields &1305 20 e8 18 JSR &18e8 ; plot_ground &1308 20 89 1a JSR &1a89 ; consider_updating_score &130b 60 RTS ; initialise_wave &130c a9 00 LDA #&00 &130e 85 8a STA &8a ; wave_x_fraction &1310 a9 0a LDA #&0a &1312 85 8b STA &8b ; wave_bottom_right_position &1314 ac f7 0c LDY &0cf7 ; difficulty &1317 b9 d9 0c LDA &0cd9,Y ; difficulties_wave_speeds - 1 &131a 8d 02 05 STA &0502 ; wave_movement_maximum_cooldown &131d 8d e6 0c STA &0ce6 ; wave_movement_cooldown &1320 a9 40 LDA #&40 &1322 8d 04 05 STA &0504 ; wave_direction # Set to &40 to start wave moving right &1325 8d 03 05 STA &0503 ; previous_wave_direction &1328 a2 00 LDX #&00 &132a ad be 0c LDA &0cbe ; screen_left_edge_x &132d 38 SEC &132e e9 05 SBC #&05 ; initialise_enemy_columns_previous_x_loop &1330 18 CLC &1331 69 05 ADC #&05 # Enemies are 20 pixels apart horizontally &1333 9d 10 05 STA &0510,X ; enemy_columns_previous_x &1336 9d 20 05 STA &0520,X ; enemy_columns_x &1339 e8 INX &133a e0 0b CPX #&0b &133c d0 f2 BNE &1330 ; initialise_enemy_columns_previous_x_loop &133e a2 00 LDX #&00 ; initialise_enemies_type_loop &1340 ad 0b 05 LDA &050b ; wave_alien_types + 4 &1343 9d 30 05 STA &0530,X ; enemies_type &1346 ad 0a 05 LDA &050a ; wave_alien_types + 3 &1349 9d 40 05 STA &0540,X ; enemies_type + &10 &134c ad 09 05 LDA &0509 ; wave_alien_types + 2 &134f 9d 50 05 STA &0550,X ; enemies_type + &20 &1352 ad 08 05 LDA &0508 ; wave_alien_types + 1 &1355 9d 60 05 STA &0560,X ; enemies_type + &30 &1358 ad 07 05 LDA &0507 ; wave_alien_types &135b 9d 70 05 STA &0570,X ; enemies_type + &40 &135e e8 INX &135f e0 0b CPX #&0b &1361 d0 dd BNE &1340 ; initialise_enemies_type_loop &1363 a2 00 LDX #&00 &1365 ac 06 05 LDY &0506 ; initial_wave_height ; initialise_enemy_rows_y_loop &1368 98 TYA &1369 18 CLC &136a 69 14 ADC #&14 # Enemies are 20 pixels apart vertically &136c 9d 3e 05 STA &053e,X ; enemy_rows_previous_y &136f 9d 3f 05 STA &053f,X ; enemy_rows_y &1372 a8 TAY &1373 8d f3 0c STA &0cf3 ; wave_lowest_y &1376 8a TXA &1377 18 CLC &1378 69 10 ADC #&10 # Move up a row &137a aa TAX &137b e0 50 CPX #&50 &137d d0 e9 BNE &1368 ; initialise_enemy_rows_y_loop &137f a0 0a LDY #&0a ; initialise_enemies_in_column_loop &1381 a9 40 LDA #&40 # Columns have five enemies &1383 99 e0 05 STA &05e0,Y ; enemies_in_column &1386 88 DEY &1387 10 f8 BPL &1381 ; initialise_enemies_in_column_loop &1389 a9 37 LDA #&37 ; 55 &138b 8d 05 05 STA &0505 ; enemies_remaining &138e ad eb 05 LDA &05eb ; rnd_state &1391 29 07 AND #&07 &1393 18 CLC &1394 69 28 ADC #&28 &1396 8d 4f 0c STA &0c4f ; enemies_remaining_for_next_ufo &1399 60 RTS ; process_collisions &139a a2 00 LDX #&00 &139c 86 77 STX &77 ; collision_to_consider &139e 8e f5 05 STX &05f5 ; missile_collision_processed # Set to zero to indicate collision not processed ; process_collisions_loop &13a1 a6 77 LDX &77 ; collision_to_consider &13a3 e8 INX &13a4 e4 87 CPX &87 ; collisions_count &13a6 f0 05 BEQ &13ad ; process_collision &13a8 90 03 BCC &13ad ; process_collision &13aa 4c 45 16 JMP &1645 ; clear_collusions_list ; process_collision &13ad 86 77 STX &77 ; collision_to_consider &13af bd 80 05 LDA &0580,X ; collisions_list &13b2 85 88 STA &88 ; collision_position_or_mover_offset &13b4 29 0f AND #&0f &13b6 49 0c EOR #&0c ; IS_MOVER &13b8 f0 03 BEQ &13bd ; process_mover_collision &13ba 4c fa 14 JMP &14fa ; process_enemy_collision ; process_mover_collision &13bd a5 88 LDA &88 ; collision_position_or_mover_offset &13bf 29 20 AND #&20 &13c1 f0 03 BEQ &13c6 ; process_missile_collision &13c3 4c 42 15 JMP &1542 ; process_bomb_collision ; process_missile_collision &13c6 ad f5 05 LDA &05f5 ; missile_collision_processed # Non-zero if bomb hit missile &13c9 d0 d6 BNE &13a1 ; process_collisions_loop &13cb ad bb 0c LDA &0cbb ; missile_collision_y &13ce c9 20 CMP #&20 &13d0 b0 07 BCS &13d9 ; check_if_missile_hit_enemy &13d2 c9 14 CMP #&14 &13d4 90 cb BCC &13a1 ; process_collisions_loop &13d6 4c f4 14 JMP &14f4 ; missile_hit_ufo ; check_if_missile_hit_enemy &13d9 a5 8b LDA &8b ; wave_bottom_right_position &13db 29 0f AND #&0f &13dd aa TAX &13de 86 74 STX &74 ; rightmost_column &13e0 bd 20 05 LDA &0520,X ; enemy_columns_x &13e3 18 CLC &13e4 69 03 ADC #&03 # A = rightmost x of rightmost column &13e6 cd ba 0c CMP &0cba ; missile_collision_x &13e9 b0 03 BCS &13ee ; determine_column_of_collision &13eb 4c a1 13 JMP &13a1 ; process_collisions_loop # Didn't hit enemy if missile right of rightmost enemy ; determine_column_of_collision &13ee 38 SEC &13ef ed ba 0c SBC &0cba ; missile_collision_x &13f2 a0 00 LDY #&00 &13f4 38 SEC ; determine_column_of_collision_loop &13f5 e9 05 SBC #&05 # Move left a column &13f7 30 04 BMI &13fd ; set_columns_from_right &13f9 c8 INY &13fa 4c f5 13 JMP &13f5 ; determine_column_of_collision_loop ; set_columns_from_right &13fd 84 75 STY &75 ; columns_from_right &13ff c9 fb CMP #&fb ; &100 - 5 &1401 d0 07 BNE &140a ; not_aligned &1403 ad 04 05 LDA &0504 ; wave_direction # &80 if moving left, &40 if moving right &1406 30 02 BMI &140a ; not_aligned &1408 e6 74 INC &74 ; rightmost_column ; not_aligned &140a a5 74 LDA &74 ; rightmost_column &140c 38 SEC &140d e5 75 SBC &75 ; set_columns_from_right &140f 30 90 BMI &13a1 ; process_collisions_loop # Didn't hit enemy if missile left of leftmost column &1411 c9 0b CMP #&0b &1413 b0 8c BCS &13a1 ; process_collisions_loop # Didn't hit enemy if missile right of rightmost column &1415 aa TAX &1416 85 75 STA &75 ; column &1418 a0 00 LDY #&00 ; determine_row_of_collision_loop &141a bd 30 05 LDA &0530,X ; enemies_type # Negative if enemy has been destroyed &141d 10 12 BPL &1431 ; check_row ; consider_next_row &141f 98 TYA &1420 18 CLC &1421 69 10 ADC #&10 # Move up a row &1423 c9 50 CMP #&50 &1425 f0 07 BEQ &142e ; to_process_collisions_loop # Didn't hit enemy if missile above topmost row &1427 a8 TAY &1428 65 75 ADC &75 ; column &142a aa TAX &142b 4c 1a 14 JMP &141a ; determine_row_of_collision_loop ; to_process_collisions_loop &142e 4c a1 13 JMP &13a1 ; process_collisions_loop ; check_row &1431 b9 3f 05 LDA &053f,Y ; enemy_rows_y &1434 38 SEC &1435 e9 0b SBC #&0b &1437 cd bb 0c CMP &0cbb ; missile_collision_y &143a b0 f2 BCS &142e ; to_process_collisions_loop # Didn't hit enemy if missile below bottommost row &143c 18 CLC &143d 69 15 ADC #&15 &143f cd bb 0c CMP &0cbb ; missile_collision_y &1442 90 db BCC &141f ; consider_next_row ; missile_hit_enemy &1444 bd 30 05 LDA &0530,X ; enemies_type &1447 85 79 STA &79 ; sprite &1449 20 70 1a JSR &1a70 ; add_to_score # Score for destroying enemy, depending on enemy type &144c a9 80 LDA #&80 &144e 9d 30 05 STA &0530,X ; enemies_type # Set to negative to indicate enemy not present &1451 8a TXA &1452 86 8d STX &8d ; exploding_enemy_position &1454 29 0f AND #&0f &1456 aa TAX &1457 86 8c STX &8c ; exploding_enemy_column &1459 ad b8 0c LDA &0cb8 ; last_replotted_enemy_position &145c 29 0f AND #&0f &145e c5 8c CMP &8c ; enemy_row &1460 90 25 BCC &1487 ; is_in_new_position &1462 d0 14 BNE &1478 ; is_in_previous_position &1464 a5 8d LDA &8d ; exploding_enemy_position &1466 29 f0 AND #&f0 &1468 18 CLC &1469 69 30 ADC #&30 &146b 85 8d STA &8d ; exploding_enemy_row &146d ad b8 0c LDA &0cb8 ; last_replotted_enemy_position &1470 29 f0 AND #&f0 &1472 c5 8d CMP &8d ; exploding_enemy_row &1474 90 11 BCC &1487 ; is_in_new_position &1476 f0 0f BEQ &1487 ; is_in_new_position ; is_in_previous_position &1478 bd 10 05 LDA &0510,X ; enemy_columns_previous_x &147b 85 70 STA &70 ; sprite_x &147d b9 3e 05 LDA &053e,Y ; enemy_rows_previous_y &1480 85 71 STA &71 ; sprite_y &1482 a5 8a LDA &8a ; wave_x_fraction &1484 4c 97 14 JMP &1497 ; check_if_bottom_enemy_in_column ; is_in_new_position &1487 bd 20 05 LDA &0520,X ; enemy_columns_x &148a 85 70 STA &70 ; sprite_x &148c b9 3f 05 LDA &053f,Y ; enemy_rows_y &148f 85 71 STA &71 ; sprite_y &1491 a5 8a LDA &8a ; wave_x_fraction &1493 49 02 EOR #&02 &1495 29 02 AND #&02 ; check_if_bottom_enemy_in_column &1497 85 76 STA &76 ; sprite_x_fraction &1499 98 TYA &149a dd e0 05 CMP &05e0,X ; enemies_in_column &149d d0 16 BNE &14b5 ; explode_enemy ; is_bottom_enemy_in_column &149f bd e0 05 LDA &05e0,X ; enemies_in_column &14a2 38 SEC &14a3 e9 10 SBC #&10 &14a5 9d e0 05 STA &05e0,X ; enemies_in_column &14a8 30 0b BMI &14b5 ; explode_enemy &14aa 8a TXA &14ab 18 CLC &14ac 7d e0 05 ADC &05e0,X ; enemies_in_column &14af a8 TAY &14b0 b9 30 05 LDA &0530,Y ; enemies_type # Negative if enemy has been destroyed &14b3 30 ea BMI &149f ; is_bottom_enemy_in_column ; explode_enemy &14b5 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot destroyed enemy &14b8 ad e1 0c LDA &0ce1 ; missile_explosion_cooldown &14bb 10 1a BPL &14d7 ; skip_adding_explosion &14bd a9 00 LDA #&00 &14bf 85 76 STA &76 ; sprite_x_fraction &14c1 a9 0e LDA #&0e ; SPRITE_MISSILE_ENEMY_EXPLOSION &14c3 85 79 STA &79 ; sprite &14c5 20 07 0e JSR &0e07 ; plot_sprite # Plot missile explosion &14c8 a5 70 LDA &70 ; sprite_x &14ca 8d f0 05 STA &05f0 ; missile_explosion_x &14cd a5 71 LDA &71 ; sprite_y &14cf 8d f1 05 STA &05f1 ; missile_explosion_y &14d2 a9 02 LDA #&02 &14d4 8d e1 0c STA &0ce1 ; missile_explosion_cooldown ; skip_adding_explosion &14d7 a9 01 LDA #&01 &14d9 20 5f 12 JSR &125f ; play_sound # Play sound for destroying enemy &14dc ce 05 05 DEC &0505 ; enemies_remaining &14df d0 05 BNE &14e6 ; not_last_enemy &14e1 a9 ff LDA #&ff &14e3 8d e6 0c STA &0ce6 ; wave_movement_cooldown # Set to &ff to stop movement ; not_last_enemy &14e6 ad 05 05 LDA &0505 ; enemies_remaining &14e9 cd 02 05 CMP &0502 ; wave_movement_maximum_cooldown &14ec b0 03 BCS &14f1 ; skip_increasing_wave_speed &14ee 8d 02 05 STA &0502 ; wave_movement_maximum_cooldown # Increase speed of wave as enemies destroyed ; skip_increasing_wave_speed &14f1 4c a1 13 JMP &13a1 ; process_collisions_loop ; missile_hit_ufo &14f4 20 ba 19 JSR &19ba ; explode_ufo &14f7 4c a1 13 JMP &13a1 ; process_collisions_loop ; process_enemy_collision &14fa a6 88 LDX &88 ; collision_position_or_mover_offset &14fc bd 00 05 LDA &0500,X ; enemies_type - &30 # Negative if enemy has been destroyed &14ff 30 3e BMI &153f ; to_process_collisions_loop &1501 a5 88 LDA &88 ; collision_position_or_mover_offset &1503 29 70 AND #&70 &1505 aa TAX &1506 bd 0f 05 LDA &050f,X ; enemy_rows_y - &30 &1509 85 71 STA &71 ; sprite_y &150b a5 88 LDA &88 ; collision_position_or_mover_offset &150d 29 0f AND #&0f &150f a8 TAY &1510 b9 20 05 LDA &0520,Y ; enemy_columns_x &1513 85 70 STA &70 ; sprite_x &1515 85 78 STA &78 ; previous_sprite_x &1517 ad 04 05 LDA &0504 ; wave_direction # &80 if moving left, &40 if moving right &151a 30 02 BMI &151e ; skip_increment &151c e6 70 INC &70 ; sprite_x ; skip_increment &151e a9 00 LDA #&00 &1520 85 76 STA &76 ; sprite_x_fraction &1522 a9 0d LDA #&0d ; SPRITE_SHIELD &1524 85 79 STA &79 ; sprite &1526 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Clear path of alien by unplotting any shield &1529 a6 88 LDX &88 ; collision_position_or_mover_offset &152b bd 00 05 LDA &0500,X ; enemies_type - &30 &152e 85 79 STA &79 ; sprite &1530 a5 8a LDA &8a ; wave_x_fraction &1532 49 02 EOR #&02 &1534 29 02 AND #&02 &1536 85 76 STA &76 ; sprite_x_fraction &1538 a5 78 LDA &78 ; previous_sprite_x &153a 85 70 STA &70 ; sprite_x &153c 20 07 0e JSR &0e07 ; plot_sprite # Replot alien ; to_process_collisions_loop &153f 4c a1 13 JMP &13a1 ; process_collisions_loop ; process_bomb_collision &1542 a5 88 LDA &88 ; collision_position_or_mover_offset &1544 29 30 AND #&30 &1546 aa TAX &1547 bd 07 0c LDA &0c07,X ; movers_y &154a c9 eb CMP #&eb &154c 90 03 BCC &1551 ; bomb_hit_missile_or_shield &154e 4c e5 15 JMP &15e5 ; bomb_hit_ground_or_player ; bomb_hit_missile_or_shield &1551 cd bb 0c CMP &0cbb ; missile_collision_y &1554 90 07 BCC &155d ; check_y &1556 38 SEC &1557 ed bb 0c SBC &0cbb ; missile_collision_y &155a 4c 64 15 JMP &1564 ; check_y_delta ; check_y &155d ad bb 0c LDA &0cbb ; missile_collision_y &1560 38 SEC &1561 fd 07 0c SBC &0c07,X ; movers_y ; check_y_delta &1564 c9 05 CMP #&05 &1566 b0 49 BCS &15b1 ; not_missile &1568 ad ba 0c LDA &0cba ; missile_collision_x &156b dd 09 0c CMP &0c09,X ; movers_x &156e f0 11 BEQ &1581 ; check_x_fraction &1570 38 SEC &1571 e9 01 SBC #&01 &1573 dd 09 0c CMP &0c09,X ; movers_x &1576 d0 39 BNE &15b1 ; not_missile &1578 ad b9 0c LDA &0cb9 ; missile_collision_x_fraction &157b 18 CLC &157c 69 04 ADC #&04 &157e 4c 84 15 JMP &1584 ; check_x_fraction_plus ; check_x_fraction &1581 ad b9 0c LDA &0cb9 ; missile_collision_x_fraction ; check_x_fraction_plus &1584 38 SEC &1585 fd 01 0c SBC &0c01,X ; movers_x_fraction &1588 90 27 BCC &15b1 ; not_missile &158a c9 03 CMP #&03 &158c b0 23 BCS &15b1 ; not_missile ; bomb_hit_missile &158e bd 01 0c LDA &0c01,X ; movers_x_fraction &1591 85 76 STA &76 ; sprite_x_fraction &1593 bd 09 0c LDA &0c09,X ; movers_x &1596 85 70 STA &70 ; sprite_x &1598 bd 07 0c LDA &0c07,X ; movers_y &159b 85 71 STA &71 ; sprite_y &159d a9 12 LDA #&12 ; SPRITE_MISSILE_BOMB_EXPLOSION &159f 85 79 STA &79 ; sprite &15a1 9d 0b 0c STA &0c0b,X ; movers_sprite &15a4 a9 06 LDA #&06 &15a6 9d c2 0c STA &0cc2,X ; bomb_explosions_cooldown - &02 &15a9 20 07 0e JSR &0e07 ; plot_sprite # Plot explosion for bomb hit by missile &15ac a9 01 LDA #&01 &15ae 8d f5 05 STA &05f5 ; missile_collision_processed # Set to non-zero to indicate collision processed ; not_missile &15b1 bd 07 0c LDA &0c07,X ; movers_y &15b4 c9 e1 CMP #&e1 &15b6 90 2a BCC &15e2 ; to_process_collisions_loop ; check_for_bomb_hitting_player &15b8 ad 09 0c LDA &0c09 ; movers_x + &00 (player) &15bb 85 70 STA &70 ; sprite_x &15bd ad 07 0c LDA &0c07 ; movers_y + &00 (player) &15c0 85 71 STA &71 ; sprite_y &15c2 ad 01 0c LDA &0c01 ; movers_x_fraction + &00 (player) &15c5 85 76 STA &76 ; sprite_x_fraction &15c7 ad 0b 0c LDA &0c0b ; movers_sprite + &00 (player) &15ca 85 79 STA &79 ; sprite &15cc a9 ff LDA #&ff # &ff to check for collision without plotting sprite &15ce 85 81 STA &81 ; plotting_mode &15d0 20 0b 0e JSR &0e0b ; check_for_collision &15d3 a5 86 LDA &86 ; collision &15d5 f0 18 BEQ &15ef ; add_bomb_explosion &15d7 ad 00 0c LDA &0c00 ; movers_flags + &00 (player) &15da 09 02 ORA #&02 ; MOVER_FLAG_ABSENT # Set to indicate player has been killed &15dc 8d 00 0c STA &0c00 ; movers_flags + &00 (player) &15df 4c ef 15 JMP &15ef ; add_bomb_explosion ; to_process_collisions_loop &15e2 4c a1 13 JMP &13a1 ; process_collisions_loop ; bomb_hit_ground_or_player &15e5 bd 08 0c LDA &0c08,X ; movers_new_y &15e8 c9 f8 CMP #&f8 &15ea b0 f6 BCS &15e2 ; to_process_collisions_loop &15ec 4c b8 15 JMP &15b8 ; check_for_bomb_hitting_player ; add_bomb_explosion &15ef bd 07 0c LDA &0c07,X ; movers_y &15f2 c9 eb CMP #&eb &15f4 90 ec BCC &15e2 ; to_process_collisions_loop &15f6 bd 09 0c LDA &0c09,X ; movers_x &15f9 cd bc 0c CMP &0cbc ; ground_left_edge_x &15fc b0 06 BCS &1604 ; check_right_edge &15fe ad bc 0c LDA &0cbc ; ground_left_edge_x &1601 4c 11 16 JMP &1611 ; replot_ground ; check_right_edge &1604 cd bd 0c CMP &0cbd ; ground_right_edge_x &1607 90 08 BCC &1611 ; replot_ground &1609 f0 06 BEQ &1611 ; replot_ground &160b ad bd 0c LDA &0cbd ; ground_right_edge_x &160e 18 CLC &160f 69 01 ADC #&01 ; replot_ground &1611 85 70 STA &70 ; sprite_x &1613 a9 ef LDA #&ef &1615 85 71 STA &71 ; sprite_y &1617 a9 00 LDA #&00 &1619 85 76 STA &76 ; sprite_x_fraction &161b a9 10 LDA #&10 ; SPRITE_GROUND &161d 85 79 STA &79 ; sprite &161f 20 07 0e JSR &0e07 ; plot_sprite # Plot ground &1622 bd 01 0c LDA &0c01,X ; movers_x_fraction &1625 85 76 STA &76 ; sprite_x_fraction &1627 a9 e7 LDA #&e7 &1629 85 71 STA &71 ; sprite_y &162b 9d 07 0c STA &0c07,X ; movers_y &162e a9 11 LDA #&11 ; SPRITE_BOMB_GROUND_EXPLOSION &1630 9d 0b 0c STA &0c0b,X ; movers_sprite &1633 85 79 STA &79 ; sprite &1635 bd 09 0c LDA &0c09,X ; movers_x &1638 85 70 STA &70 ; sprite_x &163a a9 03 LDA #&03 &163c 9d c2 0c STA &0cc2,X ; bomb_explosions_cooldown - &20 &163f 20 07 0e JSR &0e07 ; plot_sprite # Plot bomb explosion &1642 4c a1 13 JMP &13a1 ; process_collisions_loop ; clear_collusions_list &1645 a9 00 LDA #&00 &1647 85 87 STA &87 ; collisions_count &1649 60 RTS ; update_and_replot_game &164a a9 00 LDA #&00 &164c 85 87 STA &87 ; collisions_count &164e 85 73 STA &73 ; all_movers_need_updating # Set to positive to update all movers &1650 8d b8 0c STA &0cb8 ; last_replotted_enemy_position &1653 20 77 11 JSR &1177 ; update_wave &1656 20 89 1f JSR &1f89 ; update_game &1659 78 SEI &165a ad 60 fe LDA &fe60 ; User VIA port B input/output register # Top bit (PB7) is set by User VIA Timer 1 timeout &165d 10 0f BPL &166e ; skip_vsync # Negative at bottom of second frame &165f ad 65 fe LDA &fe65 ; User VIA timer 1 counter MSB &1662 c9 05 CMP #&05 &1664 b0 08 BCS &166e ; skip_waiting_for_vsync # Branch if a v-sync is not due soon &1666 c9 01 CMP #&01 &1668 90 04 BCC &166e ; skip_waiting_for_vsync # Branch if a v-sync is due very soon &166a 58 CLI &166b 20 9a 20 JSR &209a ; wait_for_vsync ; skip_waiting_for_vsync &166e 58 CLI &166f 4c 75 16 JMP &1675 ; consider_next_replot ; update_and_replot_game_loop &1672 20 89 1f JSR &1f89 ; update_game ; consider_next_replot &1675 a6 7c LDX &7c ; stack_for_replotting_enemies_offset &1677 bd 00 0c LDA &0c00,X ; stack_for_replotting_enemies - &51 &167a f0 0d BEQ &1689 ; replot_player # Zero if nothing on stack &167c 29 0f AND #&0f &167e 49 0c EOR #&0c ; IS_MOVER &1680 f0 2f BEQ &16b1 ; replot_enemy_or_mover &1682 ad 05 05 LDA &0505 ; enemies_remaining &1685 c9 02 CMP #&02 &1687 90 28 BCC &16b1 ; replot_enemy_or_mover ; replot_player &1689 a5 7d LDA &7d ; stack_for_replotting_player_offset &168b 85 7f STA &7f ; stack_offset &168d 20 4d 10 JSR &104d ; replot_enemy_or_mover # Replot player &1690 a5 7f LDA &7f ; stack_offset &1692 85 7d STA &7d ; stack_for_replotting_player_offset &1694 ad 65 fe LDA &fe65 ; User VIA timer 1 counter MSB # Use timer to replot enemies without flicker &1697 c9 40 CMP #&40 &1699 b0 16 BCS &16b1 ; replot_enemy_or_mover # Branch if raster is above wave in first frame &169b c9 0a CMP #&0a &169d 90 12 BCC &16b1 ; replot_enemy_or_mover # Branch if raster has left screen in second frame &169f a5 7e LDA &7e ; stack_for_replotting_ufo_offset ; consider_replotting_ufo &16a1 c9 90 CMP #&90 # &90 if UFO doesn't need updating &16a3 f0 0c BEQ &16b1 ; replot_enemy_or_mover ; replot_ufo &16a5 85 7f STA &7f ; stack_offset &16a7 20 4d 10 JSR &104d ; replot_enemy_or_mover # Replot UFO &16aa a5 7f LDA &7f ; stack_offset &16ac 85 7e STA &7e ; stack_for_replotting_ufo_offset &16ae 4c a1 16 JMP &16a1 ; consider_replotting_ufo ; replot_enemy_or_mover &16b1 a5 7c LDA &7c ; stack_for_replotting_enemies_offset &16b3 85 7f STA &7f ; stack_offset &16b5 20 4d 10 JSR &104d ; replot_enemy_or_mover # Replot next enemy or mover &16b8 a5 7f LDA &7f ; stack_offset &16ba 85 7c STA &7c ; stack_for_replotting_enemies_offset &16bc a5 77 LDA &77 ; updating_enemy # Non-zero if enemy, zero if mover &16be f0 07 BEQ &16c7 ; skip_collision_check &16c0 a5 87 LDA &87 ; collisions_count &16c2 f0 03 BEQ &16c7 ; skip_collision_check &16c4 20 9a 13 JSR &139a ; process_collisions ; skip_collision_check &16c7 a5 7c LDA &7c ; stack_for_replotting_enemies_offset &16c9 c9 51 CMP #&51 ; &0c51 = stack_for_replotting_enemies # &51 if enemy stack is empty &16cb d0 a5 BNE &1672 ; update_and_replot_game_loop &16cd a5 7d LDA &7d ; stack_for_replotting_player_offset &16cf c9 8d CMP #&8d ; &0c8d = stack_for_replotting_player # &8d if player stack is empty &16d1 d0 b6 BNE &1689 ; replot_player &16d3 a5 87 LDA &87 ; collisions_count &16d5 f0 03 BEQ &16da ; leave &16d7 20 9a 13 JSR &139a ; process_collisions ; leave &16da 60 RTS ; initialise_stack_for_replotting_enemies &16db 18 CLC &16dc a2 30 LDX #&30 ; initialise_stack_for_replotting_column_loop &16de 8a TXA ; initialise_stack_for_replotting_row_loop &16df e6 7c INC &7c ; stack_for_replotting_enemies_offset &16e1 a4 7c LDY &7c ; stack_for_replotting_enemies_offset &16e3 99 00 0c STA &0c00,Y ; stack_for_replotting_enemies - &51 &16e6 69 10 ADC #&10 # Move up a row &16e8 10 f5 BPL &16df ; initialise_stack_for_replotting_row_loop &16ea e8 INX # Move right a column &16eb e0 3b CPX #&3b &16ed d0 ef BNE &16de ; initialise_stack_for_replotting_column_loop &16ef 60 RTS ; initialise_movers &16f0 a2 00 LDX #&00 ; initialise_movers_loop &16f2 a9 02 LDA #&02 ; MOVER_FLAG_ABSENT &16f4 9d 00 0c STA &0c00,X ; movers_flags &16f7 a9 00 LDA #&00 &16f9 9d 01 0c STA &0c01,X ; movers_x_fraction &16fc 9d 02 0c STA &0c02,X ; movers_new_x_fraction &16ff 9d 03 0c STA &0c03,X ; movers_energy_x &1702 9d 04 0c STA &0c04,X ; movers_speed_x &1705 9d 05 0c STA &0c05,X ; movers_energy_y &1708 9d 06 0c STA &0c06,X ; movers_speed_y &170b 9d 0d 0c STA &0c0d,X ; movers_unused # Unused variables &170e 8a TXA &170f 18 CLC &1710 69 10 ADC #&10 # Next mover &1712 aa TAX &1713 c9 50 CMP #&50 &1715 d0 db BNE &16f2 ; initialise_movers_loop &1717 a9 40 LDA #&40 ; MOVER_FLAG_END &1719 9d 00 0c STA &0c00,X ; movers_flags # X = &40 here, so UFO &171c a9 e5 LDA #&e5 &171e 8d 07 0c STA &0c07 ; movers_y + &00 (player) &1721 8d 08 0c STA &0c08 ; movers_new_y + &00 (player) &1724 a9 0a LDA #&0a ; SPRITE_PLAYER &1726 8d 0b 0c STA &0c0b ; movers_sprite + &00 (player) &1729 a9 82 LDA #&82 &172b 8d 10 0c STA &0c10 ; movers_flags + &10 (missile) &172e a9 13 LDA #&13 ; SPRITE_UFO &1730 8d 4b 0c STA &0c4b ; movers_sprite + &40 (ufo) &1733 a9 16 LDA #&16 &1735 8d 47 0c STA &0c47 ; movers_y + &40 (ufo) &1738 8d 48 0c STA &0c48 ; movers_new_y + &40 (ufo) &173b 60 RTS ; add_missile &173c ad 64 fe LDA &fe64 ; User VIA timer 1 counter LSB &173f 8d f7 05 STA &05f7 ; rnd_state_from_via &1742 ad 0a 0c LDA &0c0a ; movers_new_x + &00 (player) &1745 8d 1a 0c STA &0c1a ; movers_new_x + &10 (missile) &1748 8d 19 0c STA &0c19 ; movers_x + &10 (missile) &174b ad 08 0c LDA &0c08 ; movers_new_y + &00 (player) &174e 38 SEC &174f e9 05 SBC #&05 &1751 8d 18 0c STA &0c18 ; movers_new_y + &10 (missile) &1754 8d 17 0c STA &0c17 ; movers_y + &10 (missile) &1757 a9 80 LDA #&80 &1759 8d 1c 0c STA &0c1c ; movers_plotted + &10 (missile) # Set to negative to indicate missile not plotted &175c ad 02 0c LDA &0c02 ; movers_new_x_fraction + &00 (player) &175f 18 CLC &1760 69 03 ADC #&03 &1762 c9 04 CMP #&04 &1764 90 08 BCC &176e ; skip_overflow &1766 ee 1a 0c INC &0c1a ; movers_new_x + &10 (missile) &1769 ee 19 0c INC &0c19 ; movers_x + &10 (missile) &176c 29 03 AND #&03 ; skip_overflow &176e 8d 12 0c STA &0c12 ; movers_new_x_fraction + &10 (missile) &1771 8d 11 0c STA &0c11 ; movers_x_fraction + &10 (missile) &1774 a9 80 LDA #&80 ; MOVER_FLAG_UP &1776 8d 10 0c STA &0c10 ; movers_flags + &10 (missile) &1779 a9 0c LDA #&0c ; SPRITE_MISSILE &177b 8d 1b 0c STA &0c1b ; movers_sprite + &10 (missile) &177e a9 06 LDA #&06 &1780 20 5f 12 JSR &125f ; play_sound # Play sound for firing missile &1783 60 RTS ; plot_shields &1784 a9 0d LDA #&0d ; SPRITE_SHIELD &1786 85 79 STA &79 ; sprite &1788 a9 08 LDA #&08 &178a 85 77 STA &77 ; shield_x ; plot_shields_loop # For each of four shields, &178c 85 70 STA &70 ; sprite_x &178e a9 02 LDA #&02 &1790 85 76 STA &76 ; sprite_x_fraction &1792 a9 c7 LDA #&c7 &1794 85 71 STA &71 ; sprite_y &1796 20 07 0e JSR &0e07 ; plot_sprite # Plot top and right of shield &1799 a9 00 LDA #&00 &179b 85 76 STA &76 ; sprite_x_fraction &179d a9 cd LDA #&cd &179f 85 71 STA &71 ; sprite_y &17a1 20 07 0e JSR &0e07 ; plot_sprite # Plot bottom left of shield &17a4 a5 70 LDA &70 ; sprite_x &17a6 18 CLC &17a7 69 03 ADC #&03 &17a9 85 70 STA &70 ; sprite_x1 &17ab 20 07 0e JSR &0e07 ; plot_sprite # Plot bottom middle of shield &17ae a5 77 LDA &77 ; shield_x &17b0 18 CLC &17b1 69 13 ADC #&13 &17b3 85 77 STA &77 ; shield_x &17b5 c9 46 CMP #&46 &17b7 90 d3 BCC &178c ; plot_shields_loop &17b9 60 RTS ; consider_dropping_bombs &17ba a2 00 LDX #&00 ; consider_dropping_bombs_loop # For each of two bombs, &17bc 86 77 STX &77 ; bomb_offset &17be bd 20 0c LDA &0c20,X ; movers_flags + &20 (bomb) &17c1 29 02 AND #&02 ; MOVER_FLAG_ABSENT &17c3 d0 0c BNE &17d1 ; not_present # Is there a bomb in this slot? ; consider_next_bomb &17c5 8a TXA &17c6 18 CLC &17c7 69 10 ADC #&10 # Next bomb &17c9 aa TAX &17ca e0 20 CPX #&20 &17cc d0 ee BNE &17bc ; consider_dropping_bombs_loop &17ce 4c c9 18 JMP &18c9 ; leave ; not_present &17d1 bd e2 0c LDA &0ce2,X ; bomb_explosions_cooldown &17d4 f0 07 BEQ &17dd ; unplot_bomb_explosion &17d6 c9 ff CMP #&ff &17d8 d0 eb BNE &17c5 ; consider_next_bomb # Is the bomb exploding? &17da 4c f7 17 JMP &17f7 ; skip_unplotting_bomb_explosion ; unplot_bomb_explosion &17dd de e2 0c DEC &0ce2,X ; bomb_explosions_cooldown &17e0 bd 21 0c LDA &0c21,X ; movers_x_fraction + &20 (bomb) &17e3 85 76 STA &76 ; sprite_x_fraction &17e5 bd 29 0c LDA &0c29,X ; movers_x + &20 (bomb) &17e8 85 70 STA &70 ; sprite_x &17ea bd 27 0c LDA &0c27,X ; movers_y + &20 (bomb) &17ed 85 71 STA &71 ; sprite_y &17ef bd 2b 0c LDA &0c2b,X ; movers_sprite + &20 (bomb) &17f2 85 79 STA &79 ; sprite &17f4 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot bomb explosion ; skip_unplotting_bomb_explosion &17f7 ad e8 0c LDA &0ce8 ; end_of_level_cooldown # &ff except at end of level &17fa c9 ff CMP #&ff &17fc d0 c7 BNE &17c5 ; consider_next_bomb &17fe ad e5 0c LDA &0ce5 ; new_bomb_cooldown &1801 d0 c2 BNE &17c5 ; consider_next_bomb # Is it too early to drop another bomb? &1803 a5 82 LDA &82 ; screen_address_low &1805 4a LSR A &1806 4a LSR A &1807 4a LSR A &1808 18 CLC &1809 6d eb 05 ADC &05eb ; rnd_state &180c 6d 09 0c ADC &0c09 ; movers_x + &00 (player) &180f 6d 17 0c ADC &0c17 ; movers_y + &10 (missile) &1812 6d f7 05 ADC &05f7 ; rnd_state_from_via &1815 e0 00 CPX #&00 # Is this the first bomb slot? &1817 d0 02 BNE &181b ; skip_inversion &1819 49 ff EOR #&ff ; skip_inversion &181b 29 0f AND #&0f &181d 18 CLC &181e 69 01 ADC #&01 &1820 85 74 STA &74 ; bomb_rnd # Random number between 1 and 16 for column &1822 8d eb 05 STA &05eb ; rnd_state (initial_bomb_rnd) &1825 a0 00 LDY #&00 &1827 a9 80 LDA #&80 &1829 85 75 STA &75 ; bomb_column ; find_column_for_bomb_loop &182b b9 e0 05 LDA &05e0,Y ; enemies_in_column # Negative if no enemies in column &182e 30 17 BMI &1847 ; consider_next_column &1830 c6 74 DEC &74 ; bomb_rnd &1832 f0 3f BEQ &1873 ; drop_bomb_from_column_Y # Use the random column if it has enemies &1834 84 78 STY &78 ; bomb_fallback_column &1836 a5 75 LDA &75 ; bomb_column &1838 10 0d BPL &1847 ; consider_next_column # If a suitable column hasn't been found, &183a b9 20 05 LDA &0520,Y ; enemy_columns_x &183d 18 CLC &183e 69 03 ADC #&03 &1840 cd 0a 0c CMP &0c0a ; movers_new_x + &00 (player) &1843 90 02 BCC &1847 ; consider_next_column # Use a column as close to the player as possible &1845 84 75 STY &75 ; bomb_column ; consider_next_column &1847 c8 INY &1848 c0 0b CPY #&0b &184a d0 df BNE &182b ; find_column_for_bomb_loop &184c a5 74 LDA &74 ; bomb_rnd # If the random number didn't correspond to an occupied column, &184e cd eb 05 CMP &05eb ; rnd_state (initial_bomb_rnd) &1851 d0 08 BNE &185b ; not_end_of_level # Branches if any enemies remain &1853 a9 fe LDA #&fe # Start end of level cooldown &1855 8d e8 0c STA &0ce8 ; end_of_level_cooldown &1858 4c c9 18 JMP &18c9 ; leave ; not_end_of_level &185b ad f7 0c LDA &0cf7 ; difficulty &185e c9 02 CMP #&02 &1860 b0 0b BCS &186d ; drop_bomb # If this is a MILD ENCOUNTER, &1862 a5 74 LDA &74 ; bomb_rnd &1864 0a ASL A # (initial bomb_rnd - columns with enemies) * 2 &1865 cd eb 05 CMP &05eb ; rnd_state (initial_bomb_rnd) &1868 b0 03 BCS &186d ; drop_bomb # Drop bomb if initial bomb_rnd >= 2 * columns with enemies &186a 4c c5 17 JMP &17c5 ; consider_next_bomb # i.e. fewer bombs when more columns containing enemies ; drop_bomb &186d a4 75 LDY &75 ; bomb_column &186f 10 02 BPL &1873 ; drop_bomb_from_column_Y &1871 a4 78 LDY &78 ; bomb_fallback_column ; drop_bomb_from_column_Y &1873 b9 e0 05 LDA &05e0,Y ; enemies_in_column &1876 85 74 STA &74 ; bomb_row &1878 a9 0b LDA #&0b ; SPRITE_BOMB &187a 9d 2b 0c STA &0c2b,X ; movers_sprite + &20 (bomb) &187d a9 00 LDA #&00 &187f 9d 20 0c STA &0c20,X ; movers_flags + &20 (bomb) &1882 b9 20 05 LDA &0520,Y ; enemy_columns_x &1885 e0 00 CPX #&00 &1887 d0 03 BNE &188c ; not_first_bomb &1889 18 CLC &188a 69 01 ADC #&01 # Offset second bomb slightly to avoid overplotting ; not_first_bomb &188c 9d 29 0c STA &0c29,X ; movers_x + &20 (bomb) &188f 9d 2a 0c STA &0c2a,X ; movers_new_x + &20 (bomb) &1892 a4 74 LDY &74 ; bomb_row &1894 b9 3f 05 LDA &053f,Y ; enemy_rows_y &1897 18 CLC &1898 69 0a ADC #&0a &189a 9d 27 0c STA &0c27,X ; movers_y + &20 (bomb) &189d 9d 28 0c STA &0c28,X ; movers_new_y + &20 (bomb) &18a0 c9 b3 CMP #&b3 &18a2 a9 30 LDA #&30 &18a4 b0 02 BCS &18a8 ; set_bomb_speed &18a6 a9 40 LDA #&40 # Bombs fall faster if dropped from above a certain level ; set_bomb_speed &18a8 9d 26 0c STA &0c26,X ; movers_speed_y + &20 (bomb) &18ab ad eb 05 LDA &05eb ; rnd_state &18ae 29 03 AND #&03 &18b0 9d 21 0c STA &0c21,X ; movers_x_fraction + &20 (bomb) &18b3 9d 22 0c STA &0c22,X ; movers_new_x_fraction + &20 (bomb) &18b6 a9 80 LDA #&80 &18b8 9d 2c 0c STA &0c2c,X ; movers_plotted + &20 (bomb) # Set to negative to indicate bomb not plotted &18bb ad fc 0c LDA &0cfc ; bombing_maximum_cooldown &18be 8d e5 0c STA &0ce5 ; new_bomb_cooldown &18c1 a9 00 LDA #&00 &18c3 9d 24 0c STA &0c24,X ; movers_speed_x + &20 (bomb) &18c6 4c c5 17 JMP &17c5 ; consider_next_bomb ; leave &18c9 60 RTS ; update_missile_explosion &18ca ad e1 0c LDA &0ce1 ; missile_explosion_cooldown &18cd d0 18 BNE &18e7 ; leave # Is it time to remove the missile explosion? &18cf ce e1 0c DEC &0ce1 ; missile_explosion_cooldown &18d2 ad f0 05 LDA &05f0 ; missile_explosion_x &18d5 85 70 STA &70 ; sprite_x &18d7 ad f1 05 LDA &05f1 ; missile_explosion_y &18da 85 71 STA &71 ; sprite_y &18dc a9 00 LDA #&00 &18de 85 76 STA &76 ; sprite_x_fraction &18e0 a9 0e LDA #&0e ; SPRITE_MISSILE_ENEMY_EXPLOSION &18e2 85 79 STA &79 ; sprite &18e4 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot missile explosion ; leave &18e7 60 RTS ; plot_ground &18e8 a9 10 LDA #&10 ; SPRITE_GROUND &18ea 85 79 STA &79 ; sprite &18ec a9 00 LDA #&00 &18ee 85 76 STA &76 ; sprite_x_fraction &18f0 a9 ef LDA #&ef &18f2 85 71 STA &71 ; sprite_y &18f4 a2 05 LDX #&05 ; plot_ground_loop &18f6 86 70 STX &70 ; sprite_x &18f8 20 07 0e JSR &0e07 ; plot_sprite # Plot ground &18fb a5 70 LDA &70 ; sprite_x &18fd 18 CLC &18fe 69 03 ADC #&03 &1900 aa TAX &1901 e0 48 CPX #&48 &1903 90 f1 BCC &18f6 ; plot_ground_loop &1905 a9 48 LDA #&48 &1907 85 70 STA &70 ; sprite_x &1909 20 07 0e JSR &0e07 ; plot_sprite # Plot right edge of ground &190c 60 RTS ; update_ufo &190d ad 40 0c LDA &0c40 ; movers_flags + &40 (ufo) &1910 29 02 AND #&02 ; MOVER_FLAG_ABSENT &1912 d0 03 BNE &1917 ; not_present &1914 4c b9 19 JMP &19b9 ; leave ; not_present &1917 ad e3 0c LDA &0ce3 ; ufo_score_cooldown # Positive if UFO score displayed &191a 10 6f BPL &198b ; consider_unplotting_ufo_score &191c ad 05 05 LDA &0505 ; enemies_remaining &191f cd 4f 0c CMP &0c4f ; enemies_remaining_for_next_ufo &1922 90 03 BCC &1927 ; consider_adding_ufo # Add new UFO after certain number of enemies destroyed &1924 4c b9 19 JMP &19b9 ; leave ; consider_adding_ufo &1927 ad e7 0c LDA &0ce7 ; new_ufo_cooldown &192a f0 13 BEQ &193f ; add_ufo &192c c9 ff CMP #&ff &192e d0 0c BNE &193c ; to_leave &1930 a5 82 LDA &82 ; screen_address_low # Used as random number &1932 8d e7 0c STA &0ce7 ; new_ufo_cooldown &1935 c9 ff CMP #&ff &1937 d0 03 BNE &193c ; to_leave &1939 ce e7 0c DEC &0ce7 ; new_ufo_cooldown ; to_leave &193c 4c b9 19 JMP &19b9 ; leave ; add_ufo &193f ce e7 0c DEC &0ce7 ; new_ufo_cooldown &1942 a9 80 LDA #&80 &1944 8d 4c 0c STA &0c4c ; movers_plotted + &40 (ufo) # Set to negative to indicate UFO not plotted &1947 a5 8a LDA &8a ; wave_x_fraction # Used as random direction for new UFO &1949 f0 10 BEQ &195b ; add_ufo_from_left ; add_ufo_from_right &194b a9 4a LDA #&4a &194d 8d 4a 0c STA &0c4a ; movers_new_x + &40 (ufo) &1950 8d 49 0c STA &0c49 ; movers_x + &40 (ufo) &1953 a9 01 LDA #&01 ; MOVER_FLAG_LEFT # Set MOVER_FLAG_LEFT to set new UFO moving left &1955 8d 40 0c STA &0c40 ; movers_flags + &40 (ufo) &1958 4c 68 19 JMP &1968 ; set_ufo_x_fraction ; add_ufo_from_left &195b a9 01 LDA #&01 &195d 8d 4a 0c STA &0c4a ; movers_new_x + &40 (ufo) &1960 8d 49 0c STA &0c49 ; movers_x + &40 (ufo) &1963 a9 00 LDA #&00 # Clear MOVER_FLAG_LEFT to set new UFO moving right &1965 8d 40 0c STA &0c40 ; movers_flags + &40 (ufo) ; set_ufo_x_fraction &1968 a9 00 LDA #&00 &196a 8d 42 0c STA &0c42 ; movers_new_x_fraction + &40 (ufo) &196d 8d 41 0c STA &0c41 ; movers_x_fraction + &40 (ufo) &1970 a9 08 LDA #&08 ; SOUND_UFO &1972 20 5f 12 JSR &125f ; play_sound # Play sound for new UFO &1975 ad eb 05 LDA &05eb ; rnd_state &1978 29 07 AND #&07 &197a 18 CLC &197b 6d 4f 0c ADC &0c4f ; enemies_remaining_for_next_ufo # Next UFO after 10 - 17 more enemies destroyed &197e 38 SEC &197f e9 11 SBC #&11 &1981 10 02 BPL &1985 ; skip_floor &1983 a9 00 LDA #&00 ; skip_floor &1985 8d 4f 0c STA &0c4f ; enemies_remaining_for_next_ufo &1988 4c b9 19 JMP &19b9 ; leave ; consider_unplotting_ufo_score &198b d0 2c BNE &19b9 ; leave # Is it time to unplot the UFO score? ; unplot_ufo_score &198d ad 49 0c LDA &0c49 ; movers_x + &40 (ufo) &1990 85 70 STA &70 ; sprite_x &1992 a9 15 LDA #&15 &1994 85 71 STA &71 ; sprite_y &1996 a9 00 LDA #&00 &1998 85 76 STA &76 ; sprite_x_fraction &199a a9 0e LDA #&0e ; SPRITE_MISSILE_ENEMY_EXPLOSION &199c 85 79 STA &79 ; sprite &199e 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot UFO explosion &19a1 a9 17 LDA #&17 &19a3 85 71 STA &71 ; sprite_y &19a5 a9 0d LDA #&0d ; SPRITE_SHIELD &19a7 85 79 STA &79 ; sprite &19a9 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot UFO score &19ac a5 70 LDA &70 ; sprite_x &19ae 18 CLC &19af 69 03 ADC #&03 &19b1 85 70 STA &70 ; sprite_x &19b3 20 02 0e JSR &0e02 ; plot_or_unplot_sprite &19b6 ce e3 0c DEC &0ce3 ; ufo_score_cooldown # Set to &ff to reset ; leave &19b9 60 RTS ; explode_ufo &19ba a9 00 LDA #&00 &19bc 8d f2 05 STA &05f2 ; ufo_departure_direction # Set to zero to suppress addition to side walls &19bf a9 05 LDA #&05 ; write text at graphics cursor &19c1 20 e3 ff JSR &ffe3 ; OSASCI &19c4 ad 40 0c LDA &0c40 ; movers_flags + &40 (ufo) &19c7 09 02 ORA #&02 ; MOVER_FLAG_ABSENT # Set to indicate UFO has been destroyed &19c9 8d 40 0c STA &0c40 ; movers_flags + &40 (ufo) &19cc ad 47 0c LDA &0c47 ; movers_y + &40 (ufo) &19cf 85 71 STA &71 ; sprite_y &19d1 ad 4b 0c LDA &0c4b ; movers_sprite + &40 (ufo) &19d4 85 79 STA &79 ; sprite &19d6 ad 41 0c LDA &0c41 ; movers_x_fraction + &40 (ufo) &19d9 85 76 STA &76 ; sprite_x_fraction &19db ad 49 0c LDA &0c49 ; movers_x + &40 (ufo) &19de 85 70 STA &70 ; sprite_x &19e0 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot UFO &19e3 a9 15 LDA #&15 &19e5 85 71 STA &71 ; sprite_y &19e7 a9 00 LDA #&00 &19e9 85 76 STA &76 ; sprite_x_fraction &19eb a9 0e LDA #&0e ; SPRITE_MISSILE_ENEMY_EXPLOSION &19ed 85 79 STA &79 ; sprite &19ef 20 07 0e JSR &0e07 ; plot_sprite # Plot UFO explosion &19f2 a9 09 LDA #&09 &19f4 20 5f 12 JSR &125f ; play_sound # Stop UFO sound &19f7 a9 07 LDA #&07 &19f9 20 5f 12 JSR &125f ; play_sound # Play sound for destroying UFO &19fc a9 19 LDA #&19 ; plot # MOVE sprite_x * 16, &03a0 &19fe 20 e3 ff JSR &ffe3 ; OSASCI &1a01 a9 04 LDA #&04 ; move absolute &1a03 20 e3 ff JSR &ffe3 ; OSASCI &1a06 18 CLC &1a07 a5 70 LDA &70 ; sprite_x &1a09 0a ASL A &1a0a 0a ASL A &1a0b 0a ASL A &1a0c 0a ASL A &1a0d 20 e3 ff JSR &ffe3 ; OSASCI &1a10 a5 70 LDA &70 ; sprite_x &1a12 4a LSR A &1a13 4a LSR A &1a14 4a LSR A &1a15 4a LSR A &1a16 20 e3 ff JSR &ffe3 ; OSASCI &1a19 a9 a0 LDA #&a0 &1a1b 20 e3 ff JSR &ffe3 ; OSASCI &1a1e a9 03 LDA #&03 &1a20 20 e3 ff JSR &ffe3 ; OSASCI &1a23 ad ba 0c LDA &0cba ; missile_collision_x &1a26 38 SEC &1a27 ed 49 0c SBC &0c49 ; movers_x + &40 (ufo) &1a2a c9 01 CMP #&01 &1a2c f0 23 BEQ &1a51 ; score_300_for_hitting_ufo &1a2e 29 01 AND #&01 &1a30 f0 0d BEQ &1a3f ; score_150_for_hitting_ufo ; score_50_for_hitting_ufo &1a32 a9 20 LDA #&20 ; " " &1a34 20 e3 ff JSR &ffe3 ; OSASCI &1a37 a9 05 LDA #&05 # Score 50 for destroying UFO &1a39 20 70 1a JSR &1a70 ; add_to_score &1a3c 4c 49 1a JMP &1a49 ; write_five ; score_150_for_hitting_ufo &1a3f a9 31 LDA #&31 ; "1" &1a41 20 e3 ff JSR &ffe3 ; OSASCI &1a44 a9 15 LDA #&15 # Score 150 for destroying UFO &1a46 20 70 1a JSR &1a70 ; add_to_score ; write_five &1a49 a9 35 LDA #&35 ; "5" &1a4b 20 e3 ff JSR &ffe3 ; OSASCI &1a4e 4c 60 1a JMP &1a60 ; write_zero ; score_300_for_hitting_ufo &1a51 a9 33 LDA #&33 ; "3" &1a53 20 e3 ff JSR &ffe3 ; OSASCI &1a56 a9 30 LDA #&30 ; "0" &1a58 20 e3 ff JSR &ffe3 ; OSASCI &1a5b a9 30 LDA #&30 # Score 300 for destroying UFO &1a5d 20 70 1a JSR &1a70 ; add_to_score ; write_zero &1a60 a9 30 LDA #&30 ; "0 &1a62 20 e3 ff JSR &ffe3 ; OSASCI &1a65 a9 1e LDA #&1e &1a67 8d e3 0c STA &0ce3 ; ufo_score_cooldown &1a6a a9 04 LDA #&04 ; write text at text cursor &1a6c 20 e3 ff JSR &ffe3 ; OSASCI &1a6f 60 RTS ; add_to_score &1a70 f8 SED &1a71 18 CLC &1a72 6d fa 05 ADC &05fa ; score &1a75 8d fa 05 STA &05fa ; score &1a78 90 08 BCC &1a82 ; skip_overflow &1a7a ad fb 05 LDA &05fb ; score + 1 &1a7d 69 00 ADC #&00 &1a7f 8d fb 05 STA &05fb ; score + 1 ; skip_overflow &1a82 d8 CLD &1a83 a9 00 LDA #&00 &1a85 8d f9 05 STA &05f9 ; score_needs_updating # Set to positive to indicate score needs updating &1a88 60 RTS ; consider_updating_score &1a89 ad f9 05 LDA &05f9 ; score_needs_updating # Positive if score needs updating &1a8c 10 03 BPL &1a91 ; needs_updating &1a8e 4c 17 1b JMP &1b17 ; set_score_as_updated ; needs_updating &1a91 a9 09 LDA #&09 &1a93 cd f8 05 CMP &05f8 ; number_x &1a96 f0 0e BEQ &1aa6 ; update_score ; update_high_score &1a98 ae f7 0c LDX &0cf7 ; difficulty &1a9b bd cc 0c LDA &0ccc,X ; high_scores_high &1a9e a8 TAY &1a9f bd c9 0c LDA &0cc9,X ; high_scores_low &1aa2 aa TAX &1aa3 4c db 1a JMP &1adb ; write_number_in_XY # Write high score ; update_score &1aa6 ac fb 05 LDY &05fb ; score + 1 &1aa9 ae fa 05 LDX &05fa ; score &1aac c0 05 CPY #&05 # Extra life at 5000 points &1aae d0 08 BNE &1ab8 ; check_for_second_extra_life &1ab0 ad f4 0c LDA &0cf4 ; extra_lives_gained &1ab3 d0 03 BNE &1ab8 ; check_for_second_extra_life &1ab5 4c c3 1a JMP &1ac3 ; gain_extra_life ; check_for_second_extra_life &1ab8 c0 15 CPY #&15 # Extra life at 15000 points &1aba d0 1f BNE &1adb ; write_number_in_XY &1abc ad f4 0c LDA &0cf4 ; extra_lives_gained &1abf c9 01 CMP #&01 &1ac1 d0 18 BNE &1adb ; write_number_in_XY ; gain_extra_life &1ac3 ee f4 0c INC &0cf4 ; extra_lives_gained &1ac6 a9 40 LDA #&40 # Non-zero to gain life &1ac8 20 92 1c JSR &1c92 ; gain_or_lose_life &1acb a9 0a LDA #&0a &1acd 20 5f 12 JSR &125f ; play_sound # Play sound for extra life &1ad0 a9 0c LDA #&0c &1ad2 8d e9 0c STA &0ce9 ; enemy_movement_sound_cooldown &1ad5 ae fa 05 LDX &05fa ; score &1ad8 ac fb 05 LDY &05fb ; score + 1 ; write_number_in_XY &1adb 86 74 STX &74 ; number_low &1add 84 75 STY &75 ; number_high &1adf a9 1f LDA #&1f # TAB(number_x, &01) &1ae1 20 e3 ff JSR &ffe3 ; OSASCI &1ae4 ad f8 05 LDA &05f8 ; number_x &1ae7 20 e3 ff JSR &ffe3 ; OSASCI &1aea a9 01 LDA #&01 &1aec 20 e3 ff JSR &ffe3 ; OSASCI &1aef a5 75 LDA &75 ; number_high &1af1 4a LSR A &1af2 4a LSR A &1af3 4a LSR A &1af4 4a LSR A &1af5 09 30 ORA #&30 ; "0" &1af7 20 e3 ff JSR &ffe3 ; OSASCI &1afa a5 75 LDA &75 ; number_high &1afc 29 0f AND #&0f &1afe 09 30 ORA #&30 ; "0" &1b00 20 e3 ff JSR &ffe3 ; OSASCI &1b03 a5 74 LDA &74 ; number_low &1b05 4a LSR A &1b06 4a LSR A &1b07 4a LSR A &1b08 4a LSR A &1b09 09 30 ORA #&30 ; "0" &1b0b 20 e3 ff JSR &ffe3 ; OSASCI &1b0e a5 74 LDA &74 ; number_low &1b10 29 0f AND #&0f &1b12 09 30 ORA #&30 ; "0" &1b14 20 e3 ff JSR &ffe3 ; OSASCI ; set_score_as_updated &1b17 a9 80 LDA #&80 &1b19 8d f9 05 STA &05f9 ; score_needs_updating # Set to negative to indicate score updated &1b1c 60 RTS ; check_for_high_score &1b1d ad fb 05 LDA &05fb ; score + 1 &1b20 ae f7 0c LDX &0cf7 ; difficulty &1b23 dd cc 0c CMP &0ccc,X ; high_scores_high &1b26 90 19 BCC &1b41 ; update_high_score &1b28 f0 0c BEQ &1b36 ; check_low &1b2a 9d cc 0c STA &0ccc,X ; high_scores_high &1b2d ad fa 05 LDA &05fa ; score &1b30 9d c9 0c STA &0cc9,X ; high_scores_low &1b33 4c 41 1b JMP &1b41 ; update_high_score ; check_low &1b36 ad fa 05 LDA &05fa ; score &1b39 dd c9 0c CMP &0cc9,X ; high_scores_low &1b3c 90 03 BCC &1b41 ; update_high_score &1b3e 9d c9 0c STA &0cc9,X ; high_scores_low ; update_high_score &1b41 a9 00 LDA #&00 &1b43 8d f9 05 STA &05f9 ; score_needs_updating # Set to positive to indicate score needs updating &1b46 a9 21 LDA #&21 &1b48 8d f8 05 STA &05f8 ; number_x # Update high score &1b4b 20 89 1a JSR &1a89 ; consider_updating_score &1b4e a9 09 LDA #&09 &1b50 8d f8 05 STA &05f8 ; number_x # Update score &1b53 60 RTS ; check_for_player_movement &1b54 ad 04 0c LDA &0c04 ; movers_energy_x + &00 (player) &1b57 18 CLC &1b58 69 20 ADC #&20 &1b5a c9 20 CMP #&20 &1b5c b0 02 BCS &1b60 ; skip_floor &1b5e a9 20 LDA #&20 # Player always has enough energy to move once ; skip_floor &1b60 85 74 STA &74 ; player_energy &1b62 a9 00 LDA #&00 &1b64 8d 04 0c STA &0c04 ; movers_energy_x + &00 (player) &1b67 ad d4 0c LDA &0cd4 ; input_method # Zero for keyboard, one or two for joystick &1b6a f0 10 BEQ &1b7c ; skip_checking_joystick_movement &1b6c 09 01 ORA #&01 &1b6e aa TAX &1b6f a9 80 LDA #&80 ; Read I/O device or buffer status &1b71 20 f4 ff JSR &fff4 ; OSBYTE &1b74 c0 32 CPY #&32 &1b76 90 0b BCC &1b83 ; is_moving_right &1b78 c0 c8 CPY #&c8 &1b7a b0 1b BCS &1b97 ; is_moving_left ; skip_checking_joystick_movement &1b7c a2 bd LDX #&bd ; X &1b7e 20 56 20 JSR &2056 ; check_for_keypress &1b81 d0 0d BNE &1b90 ; right_not_pressed ; is_moving_right &1b83 a2 00 LDX #&00 # Clear MOVER_FLAG_LEFT to set player moving right &1b85 8e 00 0c STX &0c00 ; movers_flags + &00 (player) &1b88 a5 74 LDA &74 ; player_energy &1b8a 8d 04 0c STA &0c04 ; movers_energy_x + &00 (player) &1b8d 4c a1 1b JMP &1ba1 ; left_not_pressed ; right_not_pressed &1b90 a2 9e LDX #&9e ; Z &1b92 20 56 20 JSR &2056 ; check_for_keypress &1b95 d0 0a BNE &1ba1 ; left_not_pressed ; is_moving_left &1b97 a2 01 LDX #&01 ; MOVER_FLAG_LEFT # Set MOVER_FLAG_LEFT to set player moving left &1b99 8e 00 0c STX &0c00 ; movers_flags + &00 (player) &1b9c a5 74 LDA &74 ; player_energy &1b9e 8d 04 0c STA &0c04 ; movers_energy_x + &00 (player) # Set energy to move player on next mover update ; left_not_pressed &1ba1 a9 60 LDA #&60 ; 3 * &20 # Set maximum player speed &1ba3 cd 04 0c CMP &0c04 ; movers_energy_x + &00 (player) &1ba6 b0 03 BCS &1bab ; skip_ceiling &1ba8 8d 04 0c STA &0c04 ; movers_energy_x + &00 (player) ; skip_ceiling &1bab ad 10 0c LDA &0c10 ; movers_flags + &10 (missile) &1bae 29 02 AND #&02 ; MOVER_FLAG_ABSENT &1bb0 f0 25 BEQ &1bd7 ; skip_checking_for_fire &1bb2 ad d4 0c LDA &0cd4 ; input_method # Zero for keyboard, one or two for joystick &1bb5 f0 08 BEQ &1bbf ; skip_checking_joystick_fire &1bb7 20 60 20 JSR &2060 ; check_for_joystick_fire &1bba cd d4 0c CMP &0cd4 ; input_method &1bbd f0 07 BEQ &1bc6 ; is_firing ; skip_checking_joystick_fire &1bbf a2 b6 LDX #&b6 ; RETURN &1bc1 20 56 20 JSR &2056 ; check_for_keypress &1bc4 d0 1b BNE &1be1 ; leave ; is_firing &1bc6 ad e4 0c LDA &0ce4 ; new_missile_cooldown &1bc9 d0 16 BNE &1be1 ; leave &1bcb 20 3c 17 JSR &173c ; add_missile &1bce ad f4 05 LDA &05f4 ; new_missile_maximum_cooldown # Set delay between firing &1bd1 8d e4 0c STA &0ce4 ; new_missile_cooldown &1bd4 4c e1 1b JMP &1be1 ; leave ; skip_checking_for_fire &1bd7 a9 02 LDA #&02 # Set minimum delay between explosion and new missile &1bd9 cd e4 0c CMP &0ce4 ; new_missile_cooldown &1bdc 90 03 BCC &1be1 ; leave &1bde 8d e4 0c STA &0ce4 ; new_missile_cooldown ; leave &1be1 60 RTS ; increase_wave_difficulty &1be2 ad 08 05 LDA &0508 ; wave_alien_types + 1 &1be5 c9 02 CMP #&02 ; SPRITE_ALIEN_TWO &1be7 d0 05 BNE &1bee ; not_green &1be9 a0 02 LDY #&02 ; G # Set colour 2 to green &1beb 4c f4 1b JMP &1bf4 ; set_colour_two ; not_green &1bee c9 05 CMP #&05 ; SPRITE_ALIEN_FIVE &1bf0 d0 07 BNE &1bf9 ; skip_setting_colour &1bf2 a0 09 LDY #&09 ; R/C # Set colour 2 to flashing red/cyan ; set_colour_two &1bf4 a2 02 LDX #&02 &1bf6 20 81 20 JSR &2081 ; set_colour ; skip_setting_colour &1bf9 ad 08 05 LDA &0508 ; wave_alien_types + 1 &1bfc c9 06 CMP #&06 ; SPRITE_ALIEN_SIX &1bfe 90 09 BCC &1c09 ; change_wave_alien_types &1c00 20 19 1f JSR &1f19 ; initialise_wave_alien_types &1c03 20 6b 20 JSR &206b ; set_default_palette &1c06 4c 37 1c JMP &1c37 ; increase_wave_speed ; change_wave_alien_types &1c09 ad 08 05 LDA &0508 ; wave_alien_types + 1 &1c0c cd 07 05 CMP &0507 ; wave_alien_types &1c0f f0 0c BEQ &1c1d ; change_rows_two_and_four ; change_rows_one_three_and_five &1c11 ee 07 05 INC &0507 ; wave_alien_types &1c14 ee 09 05 INC &0509 ; wave_alien_types + 2 &1c17 ee 0b 05 INC &050b ; wave_alien_types + 4 &1c1a 4c 23 1c JMP &1c23 ; lower_wave_height ; change_rows_two_and_four &1c1d ee 08 05 INC &0508 ; wave_alien_types + 1 &1c20 ee 0a 05 INC &050a ; wave_alien_types + 3 ; lower_wave_height &1c23 ac f7 0c LDY &0cf7 ; difficulty &1c26 ad 06 05 LDA &0506 ; initial_wave_height &1c29 18 CLC &1c2a 69 0a ADC #&0a &1c2c d9 d6 0c CMP &0cd6,Y ; difficulties_minimum_initial_wave_height - 1 &1c2f 90 03 BCC &1c34 ; skip_height_floor &1c31 b9 d6 0c LDA &0cd6,Y ; difficulties_minimum_initial_wave_height - 1 ; skip_height_floor &1c34 8d 06 05 STA &0506 ; initial_wave_height ; increase_wave_speed &1c37 ae f7 0c LDX &0cf7 ; difficulty &1c3a de d9 0c DEC &0cd9,X ; difficulties_wave_speeds - 1 &1c3d a9 0e LDA #&0e &1c3f dd d9 0c CMP &0cd9,X ; difficulties_wave_speeds - 1 &1c42 90 03 BCC &1c47 ; skip_speed_floor &1c44 9d d9 0c STA &0cd9,X ; difficulties_wave_speeds - 1 ; skip_speed_floor &1c47 60 RTS ; delay &1c48 85 74 STA &74 ; delay_high ; delay_outer_loop &1c4a 85 75 STA &75 ; delay_middle ; delay_loop &1c4c 85 84 STA &84 ; delay_low ; delay_inner_loop &1c4e c6 84 DEC &84 ; delay_low &1c50 d0 fc BNE &1c4e ; delay_inner_loop &1c52 c6 75 DEC &75 ; delay_middle &1c54 d0 f6 BNE &1c4c ; delay_loop &1c56 c6 74 DEC &74 ; delay_high &1c58 d0 f0 BNE &1c4a ; delay_outer_loop &1c5a 60 RTS ; animate_dying_player &1c5b ad 07 0c LDA &0c07 ; movers_y + &00 (player) &1c5e 85 71 STA &71 ; sprite_y &1c60 a9 09 LDA #&09 &1c62 85 77 STA &77 ; count &1c64 ad 09 0c LDA &0c09 ; movers_x + &00 (player) &1c67 85 70 STA &70 ; sprite_x &1c69 ad 01 0c LDA &0c01 ; movers_x_fraction + &00 (player) &1c6c 85 76 STA &76 ; sprite_x_fraction &1c6e ad 0b 0c LDA &0c0b ; movers_sprite + &00 (player) &1c71 85 79 STA &79 ; sprite &1c73 a9 03 LDA #&03 &1c75 20 5f 12 JSR &125f ; play_sound # Play sound for player dying &1c78 a9 04 LDA #&04 &1c7a 20 5f 12 JSR &125f ; play_sound # Play sound for player dying ; animate_dead_player_loop &1c7d 20 07 0e JSR &0e07 ; plot_sprite # Plot dying player &1c80 a9 12 LDA #&12 &1c82 20 48 1c JSR &1c48 ; delay &1c85 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot dying player &1c88 a9 20 LDA #&20 &1c8a 20 48 1c JSR &1c48 ; delay &1c8d c6 77 DEC &77 ; count &1c8f d0 ec BNE &1c7d ; animate_dead_player_loop &1c91 60 RTS ; gain_or_lose_life &1c92 85 77 STA &77 ; gain_or_lose # Zero to lose a life, non-zero to gain a life &1c94 ad 0b 0c LDA &0c0b ; movers_sprite + &00 (player) &1c97 85 79 STA &79 ; sprite &1c99 a9 00 LDA #&00 &1c9b 85 76 STA &76 ; sprite_x_fraction &1c9d a9 f4 LDA #&f4 &1c9f 85 71 STA &71 ; sprite_y &1ca1 ae ef 05 LDX &05ef ; lives &1ca4 a9 0a LDA #&0a ; calculate_x_position_loop &1ca6 18 CLC &1ca7 69 06 ADC #&06 &1ca9 ca DEX &1caa d0 fa BNE &1ca6 ; calculate_x_position_loop &1cac a6 77 LDX &77 ; gain_or_lose &1cae d0 0b BNE &1cbb ; gain_life ; lose_life &1cb0 ce ef 05 DEC &05ef ; lives &1cb3 85 70 STA &70 ; sprite_x &1cb5 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot lost life &1cb8 4c c6 1c JMP &1cc6 ; leave ; gain_life &1cbb 18 CLC &1cbc 69 06 ADC #&06 &1cbe 85 70 STA &70 ; sprite_x &1cc0 ee ef 05 INC &05ef ; lives &1cc3 20 07 0e JSR &0e07 ; plot_sprite # Plot gained life &1cc6 60 RTS ; initialise_player &1cc7 ad bc 0c LDA &0cbc ; ground_left_edge_x &1cca 8d 0a 0c STA &0c0a ; movers_new_x + &00 (player) # Player starts at left of ground &1ccd 8d 09 0c STA &0c09 ; movers_x + &00 (player) &1cd0 85 70 STA &70 ; sprite_x &1cd2 ad 08 0c LDA &0c08 ; movers_new_y + &00 (player) &1cd5 85 71 STA &71 ; sprite_y &1cd7 a9 00 LDA #&00 &1cd9 8d 02 0c STA &0c02 ; movers_new_x_fraction + &00 (player) &1cdc 8d 01 0c STA &0c01 ; movers_x_fraction + &00 (player) &1cdf 85 76 STA &76 ; sprite_x_fraction &1ce1 8d f7 05 STA &05f7 ; rnd_state_from_via &1ce4 8d 00 0c STA &0c00 ; movers_flags + &00 (player) &1ce7 ad 0b 0c LDA &0c0b ; movers_sprite + &00 (player) &1cea 85 79 STA &79 ; sprite &1cec 20 07 0e JSR &0e07 ; plot_sprite # Plot initial player &1cef a9 00 LDA #&00 &1cf1 8d 0c 0c STA &0c0c ; movers_plotted + &00 (player) # Set to positive to indicate player plotted &1cf4 60 RTS ; entry_point &1cf5 a9 01 LDA #&01 &1cf7 8d f7 0c STA &0cf7 ; difficulty &1cfa a9 81 LDA #&81 ; Read machine type &1cfc a0 ff LDY #&ff &1cfe a2 00 LDX #&00 &1d00 20 f4 ff JSR &fff4 ; OSBYTE &1d03 8e f6 0c STX &0cf6 ; machine_type &1d06 a9 16 LDA #&16 # Change to MODE 1 &1d08 20 ee ff JSR &ffee ; OSWRCH &1d0b a9 01 LDA #&01 &1d0d 20 ee ff JSR &ffee ; OSWRCH &1d10 a9 17 LDA #&17 # Disable cursor &1d12 20 ee ff JSR &ffee ; OSWRCH &1d15 a9 00 LDA #&00 &1d17 20 ee ff JSR &ffee ; OSWRCH &1d1a a9 0a LDA #&0a &1d1c 20 ee ff JSR &ffee ; OSWRCH &1d1f a9 20 LDA #&20 &1d21 20 ee ff JSR &ffee ; OSWRCH &1d24 a9 00 LDA #&00 &1d26 a2 06 LDX #&06 ; write_nulls_loop &1d28 20 ee ff JSR &ffee ; OSWRCH &1d2b ca DEX &1d2c d0 fa BNE &1d28 ; write_nulls_loop &1d2e a2 06 LDX #&06 &1d30 a9 00 LDA #&00 &1d32 8d d4 0c STA &0cd4 ; input_method # Set to zero to use keyboard ; initialise_high_scores_loop &1d35 9d c9 0c STA &0cc9,X ; high_scores_low &1d38 ca DEX &1d39 d0 fa BNE &1d35 ; initialise_high_scores_loop &1d3b a9 2c LDA #&2c ; &2cc0 = envelope_data &1d3d 8d fd 2c STA &2cfd ; envelope_address_high &1d40 a9 c0 LDA #&c0 &1d42 8d fc 2c STA &2cfc ; envelope_address_low &1d45 20 aa 1e JSR &1eaa ; define_envelope &1d48 20 aa 1e JSR &1eaa ; define_envelope &1d4b 20 aa 1e JSR &1eaa ; define_envelope &1d4e 20 6b 20 JSR &206b ; set_default_palette &1d51 20 e6 1d JSR &1de6 ; scoring_and_keys_screens &1d54 20 9a 20 JSR &209a ; wait_for_vsync ; new_game &1d57 20 7a 12 JSR &127a ; initialise_game &1d5a a9 40 LDA #&40 # Non-zero to gain life &1d5c 20 92 1c JSR &1c92 ; gain_or_lose_life &1d5f a9 40 LDA #&40 # Non-zero to gain life &1d61 20 92 1c JSR &1c92 ; gain_or_lose_life &1d64 a9 46 LDA #&46 &1d66 20 48 1c JSR &1c48 ; delay ; new_life ; main_game_loop &1d69 20 4a 16 JSR &164a ; update_and_replot_game &1d6c 20 ca 18 JSR &18ca ; update_missile_explosion &1d6f 20 ba 17 JSR &17ba ; consider_dropping_bombs &1d72 20 0d 19 JSR &190d ; update_ufo &1d75 20 89 1a JSR &1a89 ; consider_updating_score &1d78 20 bf 20 JSR &20bf ; consider_adding_to_side_walls &1d7b ad 00 0c LDA &0c00 ; movers_flags + &00 (player) &1d7e 29 02 AND #&02 ; MOVER_FLAG_ABSENT # Set if player has been hit by bomb &1d80 d0 1f BNE &1da1 ; player_hit &1d82 ad ed 05 LDA &05ed ; enemy_reached_ground # Non-zero if enemy reached ground &1d85 d0 2d BNE &1db4 ; end_of_game_after_animating_dying_player &1d87 ad e8 0c LDA &0ce8 ; end_of_level_cooldown &1d8a d0 dd BNE &1d69 ; main_game_loop ; next_level &1d8c ce e8 0c DEC &0ce8 ; end_of_level_cooldown # Set to &ff to reset &1d8f 20 a4 21 JSR &21a4 ; plot_level_tally &1d92 20 e2 1b JSR &1be2 ; increase_wave_difficulty &1d95 20 0c 13 JSR &130c ; initialise_wave &1d98 20 db 16 JSR &16db ; initialise_stack_for_replotting_enemies &1d9b 20 84 17 JSR &1784 ; plot_shields &1d9e 4c 69 1d JMP &1d69 ; main_game_loop ; player_hit &1da1 20 5b 1c JSR &1c5b ; animate_dying_player &1da4 ad ef 05 LDA &05ef ; lives &1da7 f0 0e BEQ &1db7 ; end_of_game &1da9 a9 00 LDA #&00 # Zero to lose life &1dab 20 92 1c JSR &1c92 ; gain_or_lose_life &1dae 20 c7 1c JSR &1cc7 ; initialise_player &1db1 4c 69 1d JMP &1d69 ; new_life ; end_of_game_after_animating_dying_player &1db4 20 5b 1c JSR &1c5b ; animate_dying_player ; end_of_game &1db7 a9 09 LDA #&09 &1db9 20 5f 12 JSR &125f ; play_sound # Play sound for removing UFO &1dbc a9 5a LDA #&5a &1dbe 20 48 1c JSR &1c48 ; delay &1dc1 20 1d 1b JSR &1b1d ; check_for_high_score &1dc4 20 99 1e JSR &1e99 ; write_restart_text_and_wait_for_space_or_fire &1dc7 20 05 20 JSR &2005 ; select_difficulty_screen &1dca 20 86 1e JSR &1e86 ; clear_screen_and_write_score &1dcd 4c 57 1d JMP &1d57 ; new_game &1dd0 60 RTS ; initialise_mover_speeds &1dd1 a9 a0 LDA #&a0 &1dd3 8d 16 0c STA &0c16 ; movers_speed_y + &10 (missile) &1dd6 a9 0c LDA #&0c &1dd8 8d f4 05 STA &05f4 ; new_missile_maximum_cooldown &1ddb a9 40 LDA #&40 &1ddd 8d 44 0c STA &0c44 ; movers_speed_x + &40 (ufo) &1de0 a9 12 LDA #&12 &1de2 8d fc 0c STA &0cfc ; bombing_maximum_cooldown &1de5 60 RTS ; scoring_and_keys_screens &1de6 a9 0c LDA #&0c ; CLS &1de8 20 e3 ff JSR &ffe3 ; OSASCI &1deb ad fb 2c LDA &2cfb ; scoring_text_address_high &1dee 85 78 STA &78 ; text_address_high &1df0 ad fa 2c LDA &2cfa ; scoring_text_address_low &1df3 85 77 STA &77 ; text_address_low &1df5 20 c7 1e JSR &1ec7 ; write_text_loop # Write scoring information &1df8 a9 12 LDA #&12 &1dfa 85 70 STA &70 ; sprite_x &1dfc a9 02 LDA #&02 &1dfe 85 76 STA &76 ; sprite_x_fraction &1e00 a9 01 LDA #&01 ; SPRITE_ALIEN_ONE &1e02 85 79 STA &79 ; sprite &1e04 a9 40 LDA #&40 &1e06 85 71 STA &71 ; sprite_y &1e08 20 07 0e JSR &0e07 ; plot_sprite # Plot alien in scoring screen &1e0b e6 79 INC &79 ; sprite ; &02 ; SPRITE_ALIEN_TWO &1e0d a9 60 LDA #&60 &1e0f 85 71 STA &71 ; sprite_y &1e11 20 07 0e JSR &0e07 ; plot_sprite # Plot alien in scoring screen &1e14 e6 79 INC &79 ; sprite ; &03 ; SPRITE_ALIEN_THREE &1e16 a9 80 LDA #&80 &1e18 85 71 STA &71 ; sprite_y &1e1a 20 07 0e JSR &0e07 ; plot_sprite # Plot alien in scoring screen &1e1d a9 08 LDA #&08 &1e1f 85 70 STA &70 ; sprite_x &1e21 a9 a0 LDA #&a0 &1e23 85 71 STA &71 ; sprite_y &1e25 a9 13 LDA #&13 ; SPRITE_UFO &1e27 85 79 STA &79 ; sprite &1e29 20 07 0e JSR &0e07 ; plot_sprite # Plot UFO in scoring screen &1e2c 20 64 1e JSR &1e64 ; wait_for_space_or_fire &1e2f a9 0c LDA #&0c ; CLS &1e31 20 e3 ff JSR &ffe3 ; OSASCI &1e34 20 c7 1e JSR &1ec7 ; write_text_loop # Write key information &1e37 20 64 1e JSR &1e64 ; wait_for_space_or_fire &1e3a a5 78 LDA &78 ; text_address_high &1e3c 8d f1 0c STA &0cf1 ; difficulty_text_address_high &1e3f a5 77 LDA &77 ; text_address_low &1e41 8d f0 0c STA &0cf0 ; difficulty_text_address_low &1e44 20 05 20 JSR &2005 ; select_difficulty_screen &1e47 a5 78 LDA &78 ; text_address_high &1e49 8d fb 0c STA &0cfb ; score_text_address_high &1e4c a5 77 LDA &77 ; text_address_low &1e4e 8d fa 0c STA &0cfa ; score_text_address_low &1e51 a9 0c LDA #&0c ; CLS &1e53 20 e3 ff JSR &ffe3 ; OSASCI &1e56 20 c7 1e JSR &1ec7 ; write_text_loop &1e59 a5 78 LDA &78 ; text_address_high &1e5b 8d f9 0c STA &0cf9 ; restart_text_address_high &1e5e a5 77 LDA &77 ; text_address_low &1e60 8d f8 0c STA &0cf8 ; restart_text_address_low &1e63 60 RTS ; wait_for_space_or_fire &1e64 a9 00 LDA #&00 &1e66 8d f3 05 STA &05f3 ; suppress_space_or_fire_autorepeat # Set to zero to suppress SPACE or fire ; wait_for_space_or_fire_loop &1e69 a2 9d LDX #&9d ; SPACE &1e6b 20 56 20 JSR &2056 ; check_for_keypress &1e6e f0 10 BEQ &1e80 ; space_pressed &1e70 20 60 20 JSR &2060 ; check_for_joystick_fire # Returns non-zero if joystick fire button pressed &1e73 d0 08 BNE &1e7d ; set_input_method &1e75 a9 01 LDA #&01 &1e77 8d f3 05 STA &05f3 ; suppress_space_or_fire_autorepeat # Set to non-zero to allow SPACE or fire &1e7a 4c 69 1e JMP &1e69 ; wait_for_space_or_fire_loop ; set_input_method &1e7d 8d d4 0c STA &0cd4 ; input_method # Set to one or two to use joystick ; space_pressed &1e80 ad f3 05 LDA &05f3 ; suppress_space_or_fire_autorepeat # Zero if SPACE or fire suppressed &1e83 f0 e4 BEQ &1e69 ; wait_for_space_or_fire_loop &1e85 60 RTS ; clear_screen_and_write_score &1e86 ad fb 0c LDA &0cfb ; score_text_address_high &1e89 85 78 STA &78 ; text_address_high &1e8b ad fa 0c LDA &0cfa ; score_text_address_low &1e8e 85 77 STA &77 ; text_address_low &1e90 a9 0c LDA #&0c ; CLS &1e92 20 e3 ff JSR &ffe3 ; OSASCI &1e95 20 c7 1e JSR &1ec7 ; write_text_loop # Write score and high score &1e98 60 RTS ; write_restart_text_and_wait_for_space_or_fire &1e99 ad f9 0c LDA &0cf9 ; restart_text_address_high &1e9c 85 78 STA &78 ; text_address_high &1e9e ad f8 0c LDA &0cf8 ; restart_text_address_low &1ea1 85 77 STA &77 ; text_address_low &1ea3 20 c7 1e JSR &1ec7 ; write_text_loop # Write restart &1ea6 20 64 1e JSR &1e64 ; wait_for_space_or_fire &1ea9 60 RTS ; define_envelope &1eaa ae fc 2c LDX &2cfc ; envelope_address_low &1ead ac fd 2c LDY &2cfd ; envelope_address_high &1eb0 a9 08 LDA #&08 ; Define a sound envelope &1eb2 20 f1 ff JSR &fff1 ; OSWORD &1eb5 18 CLC &1eb6 ad fc 2c LDA &2cfc ; envelope_address_low &1eb9 69 0e ADC #&0e &1ebb 8d fc 2c STA &2cfc ; envelope_address_low &1ebe ad fd 2c LDA &2cfd ; envelope_address_high &1ec1 69 00 ADC #&00 &1ec3 8d fd 2c STA &2cfd ; envelope_address_high &1ec6 60 RTS ; write_text &1ec7 a0 00 LDY #&00 ; write_text_loop &1ec9 b1 77 LDA (&77),Y ; text_address &1ecb aa TAX &1ecc a5 77 LDA &77 ; text_address_low &1ece 18 CLC &1ecf 69 01 ADC #&01 &1ed1 85 77 STA &77 ; text_address_low &1ed3 90 02 BCC &1ed7 ; skip_page &1ed5 e6 78 INC &78 ; text_address_high ; skip_page &1ed7 e0 ff CPX #&ff &1ed9 f0 07 BEQ &1ee2 ; leave &1edb 8a TXA &1edc 20 ee ff JSR &ffee ; OSWRCH &1edf 4c c9 1e JMP &1ec9 ; write_text_loop ; leave &1ee2 60 RTS ; update_cooldowns # Acts on &0ce1 - &0ce9 and &0cf2 &1ee3 a2 12 LDX #&12 # ; update_cooldowns_loop # &0ce1 missile_explosion_cooldown &1ee5 bd e0 0c LDA &0ce0,X ; cooldowns - 1 # &0ce2 bomb_explosions_cooldown &1ee8 f0 07 BEQ &1ef1 ; consider_next_cooldown # &0ce3 bomb_explosions_cooldown + 1 &1eea c9 ff CMP #&ff # &0ce4 new_missile_cooldown &1eec f0 03 BEQ &1ef1 ; consider_next_cooldown # &0ce5 new_bomb_cooldown &1eee de e0 0c DEC &0ce0,X ; cooldowns - 1 # &0ce6 wave_movement_cooldown ; consider_next_cooldown # &0ce7 new_ufo_cooldown &1ef1 ca DEX # &0ce8 end_of_level_cooldown &1ef2 e0 0a CPX #&0a # &0ce9 enemy_movement_sound_cooldown &1ef4 b0 fb BCS &1ef1 ; consider_next_cooldown # &1ef6 e0 00 CPX #&00 # &0cf2 unused_cooldown &1ef8 d0 eb BNE &1ee5 ; update_cooldowns_loop &1efa 60 RTS ; initialise_cooldowns &1efb a2 08 LDX #&08 ; initialise_cooldowns_loop &1efd a9 ff LDA #&ff &1eff 9d e0 0c STA &0ce0,X ; cooldowns - 1 &1f02 ca DEX &1f03 d0 f8 BNE &1efd ; initialise_cooldowns_loop &1f05 8d f2 0c STA &0cf2 ; unused_cooldown # Unused variable &1f08 a9 00 LDA #&00 &1f0a 8d e4 0c STA &0ce4 ; new_missile_cooldown &1f0d 8d e5 0c STA &0ce5 ; new_bomb_cooldown &1f10 8d e9 0c STA &0ce9 ; enemy_movement_sound_cooldown &1f13 a9 01 LDA #&01 &1f15 8d ee 05 STA &05ee ; flagged_movers_need_updating # Set to non-zero to indicate flagged movers updated &1f18 60 RTS ; initialise_wave_alien_types &1f19 a9 01 LDA #&01 ; SPRITE_ALIEN_ONE &1f1b 8d 07 05 STA &0507 ; wave_alien_types &1f1e 8d 08 05 STA &0508 ; wave_alien_types + 1 &1f21 a9 02 LDA #&02 ; SPRITE_ALIEN_TWO &1f23 8d 09 05 STA &0509 ; wave_alien_types + 2 &1f26 8d 0a 05 STA &050a ; wave_alien_types + 3 &1f29 a9 03 LDA #&03 ; SPRITE_ALIEN_THREE &1f2b 8d 0b 05 STA &050b ; wave_alien_types + 4 &1f2e ae f7 0c LDX &0cf7 ; difficulty &1f31 a9 13 LDA #&13 &1f33 e0 04 CPX #&04 # Unused difficulty level 4 would start wave lower &1f35 90 02 BCC &1f39 ; set_initial_wave_height # Always branches &1f37 a9 27 LDA #&27 ; set_initial_wave_height &1f39 8d 06 05 STA &0506 ; initial_wave_height &1f3c 60 RTS ; move_bombs_towards_player &1f3d ad f7 0c LDA &0cf7 ; difficulty &1f40 c9 03 CMP #&03 &1f42 d0 44 BNE &1f88 ; leave # Is this a TERRIFYING EXPERIENCE? &1f44 a2 00 LDX #&00 ; move_bombs_towards_player_loop &1f46 bd 27 0c LDA &0c27,X ; movers_y + &20 (bomb) &1f49 38 SEC &1f4a e9 04 SBC #&04 &1f4c cd f3 0c CMP &0cf3 ; wave_lowest_y &1f4f 90 2e BCC &1f7f ; consider_next_bomb &1f51 bd 29 0c LDA &0c29,X ; movers_x + &20 (bomb) &1f54 cd 09 0c CMP &0c09 ; movers_x + &00 (player) &1f57 90 0f BCC &1f68 ; is_left_of_player &1f59 f0 24 BEQ &1f7f ; consider_next_bomb ; is_right_of_player &1f5b 38 SEC &1f5c e9 01 SBC #&01 &1f5e f0 1f BEQ &1f7f ; consider_next_bomb &1f60 bd 20 0c LDA &0c20,X ; movers_flags + &20 (bomb) &1f63 09 01 ORA #&01 ; MOVER_FLAG_LEFT # Set MOVER_FLAG_LEFT to set bomb moving left &1f65 4c 6d 1f JMP &1f6d ; set_flags ; is_left_of_player &1f68 bd 20 0c LDA &0c20,X ; movers_flags + &20 (bomb) &1f6b 29 fe AND #&fe ; !MOVER_FLAG_LEFT # Clear MOVER_FLAG_LEFT to set bomb moving right ; set_flags &1f6d 9d 20 0c STA &0c20,X ; movers_flags + &20 (bomb) &1f70 a9 20 LDA #&20 &1f72 9d 24 0c STA &0c24,X ; movers_energy_x + &00 (bomb) # Set energy to move bomb on next mover update &1f75 a9 10 LDA #&10 &1f77 9d 26 0c STA &0c26,X ; movers_speed_y + &20 (bomb) # Bombs fall slower &1f7a a9 23 LDA #&23 &1f7c 8d fc 0c STA &0cfc ; bombing_maximum_cooldown # Bombs fall less often ; consider_next_bomb &1f7f 8a TXA &1f80 18 CLC &1f81 69 10 ADC #&10 # Next bomb &1f83 aa TAX &1f84 e0 20 CPX #&20 &1f86 d0 be BNE &1f46 ; move_bombs_towards_player_loop ; leave &1f88 60 RTS ; update_game ; wait_for_timer_reset &1f89 78 SEI &1f8a ad 65 fe LDA &fe65 ; User VIA timer 1 counter MSB &1f8d c9 01 CMP #&01 &1f8f 90 f8 BCC &1f89 ; wait_for_timer_reset # If a v-sync is due very soon, wait for it to reset timer &1f91 ae 60 fe LDX &fe60 ; User VIA port B input/output register # Top bit PB7 is set by User VIA Timer 1 timeout &1f94 58 CLI &1f95 c9 0a CMP #&0a &1f97 90 08 BCC &1fa1 ; update_game_after_second_frame # Branch if raster has left screen in second frame &1f99 c9 58 CMP #&58 &1f9b 90 45 BCC &1fe2 ; update_game_after_first_frame # Branch if raster has left screen in first frame &1f9d 8a TXA &1f9e 4c a4 1f JMP &1fa4 ; update_game_in_first_frame ; update_game_after_second_frame &1fa1 8a TXA &1fa2 49 80 EOR #&80 ; update_game_in_first_frame &1fa4 cd d6 0c CMP &0cd6 ; previous_frame_state &1fa7 f0 5b BEQ &2004 ; leave &1fa9 8d d6 0c STA &0cd6 ; previous_frame_state # Alternates between &7f and &ff &1fac 20 54 1b JSR &1b54 ; check_for_player_movement &1faf 20 3d 1f JSR &1f3d ; move_bombs_towards_player &1fb2 20 e3 1e JSR &1ee3 ; update_cooldowns &1fb5 ad 05 05 LDA &0505 ; enemies_remaining &1fb8 c9 02 CMP #&02 &1fba b0 03 BCS &1fbf ; not_last_enemy_in_first_frame &1fbc 20 77 11 JSR &1177 ; update_wave ; not_last_enemy_in_first_frame &1fbf 20 ae 0e JSR &0eae ; update_movers &1fc2 a9 00 LDA #&00 &1fc4 8d ee 05 STA &05ee ; flagged_movers_need_updating # Set to zero to indicate flagged movers need updating &1fc7 ad 10 0c LDA &0c10 ; movers_flags + &10 (missile) &1fca 09 08 ORA #&08 ; MOVER_FLAG_NEEDS_UPDATE &1fcc 8d 10 0c STA &0c10 ; movers_flags + &10 (missile) &1fcf ad 20 0c LDA &0c20 ; movers_flags + &20 (bomb) &1fd2 09 08 ORA #&08 ; MOVER_FLAG_NEEDS_UPDATE &1fd4 8d 20 0c STA &0c20 ; movers_flags + &20 (bomb) &1fd7 ad 30 0c LDA &0c30 ; movers_flags + &20 (bomb) + &10 &1fda 09 08 ORA #&08 ; MOVER_FLAG_NEEDS_UPDATE &1fdc 8d 30 0c STA &0c30 ; movers_flags + &20 (bomb) + &10 &1fdf 4c 04 20 JMP &2004 ; leave ; update_game_after_first_frame &1fe2 ad ee 05 LDA &05ee ; flagged_movers_need_updating # Zero if flagged movers need updating &1fe5 d0 1d BNE &2004 ; leave &1fe7 20 e3 1e JSR &1ee3 ; update_cooldowns &1fea ad 05 05 LDA &0505 ; enemies_remaining &1fed c9 02 CMP #&02 &1fef b0 03 BCS &1ff4 ; not_last_enemy_after_first_frame &1ff1 20 77 11 JSR &1177 ; update_wave ; not_last_enemy_after_first_frame &1ff4 a9 01 LDA #&01 &1ff6 8d ee 05 STA &05ee ; flagged_movers_need_updating # Set to non-zero to indicate flagged movers updated &1ff9 a9 80 LDA #&80 &1ffb 85 73 STA &73 ; all_movers_need_updating # Set to negative to update only flagged movers &1ffd 20 ae 0e JSR &0eae ; update_movers &2000 a9 00 LDA #&00 &2002 85 73 STA &73 ; all_movers_need_updating # Set to positive to update all movers ; leave &2004 60 RTS ; select_difficulty_screen &2005 a9 0c LDA #&0c &2007 20 e3 ff JSR &ffe3 ; OSASCI &200a ad f1 0c LDA &0cf1 ; difficulty_text_address_high &200d 85 78 STA &78 ; text_address_high &200f ad f0 0c LDA &0cf0 ; difficulty_text_address_low &2012 85 77 STA &77 ; text_address_low &2014 20 c7 1e JSR &1ec7 ; write_text_loop # Write difficulties text &2017 a9 00 LDA #&00 &2019 8d f3 05 STA &05f3 ; suppress_space_or_fire_autorepeat # Set to zero to suppress SPACE or fire &201c 4c 24 20 JMP &2024 ; select_difficulty_screen_loop ; set_suppress_space_or_fire_autorepeat &201f a9 01 LDA #&01 &2021 8d f3 05 STA &05f3 ; suppress_space_or_fire_autorepeat # Set to non-zero to allow SPACE or fire ; select_difficulty_screen_loop &2024 20 60 20 JSR &2060 ; check_for_joystick_fire # Returns non-zero if joystick fire button pressed &2027 f0 03 BEQ &202c ; fire_not_pressed &2029 4c 50 20 JMP &2050 ; check_if_suppress_space_or_fire_autorepeat ; fire_not_pressed &202c a2 cf LDX #&cf ; 1 &202e 20 56 20 JSR &2056 ; check_for_keypress &2031 d0 05 BNE &2038 ; one_not_pressed &2033 a9 01 LDA #&01 &2035 4c 4d 20 JMP &204d ; set_difficulty ; one_not_pressed &2038 a2 ce LDX #&ce ; 2 &203a 20 56 20 JSR &2056 ; check_for_keypress &203d d0 05 BNE &2044 ; two_not_pressed &203f a9 02 LDA #&02 &2041 4c 4d 20 JMP &204d ; set_difficulty ; two_not_pressed &2044 a2 ee LDX #&ee ; 3 &2046 20 56 20 JSR &2056 ; check_for_keypress &2049 d0 d4 BNE &201f ; set_suppress_space_or_fire_autorepeat &204b a9 03 LDA #&03 ; set_difficulty &204d 8d f7 0c STA &0cf7 ; difficulty ; check_if_suppress_space_or_fire_autorepeat &2050 ad f3 05 LDA &05f3 ; suppress_space_or_fire_autorepeat # Zero if SPACE or fire suppressed &2053 f0 cf BEQ &2024 ; select_difficulty_screen_loop &2055 60 RTS ; check_for_keypress &2056 a9 81 LDA #&81 ; Scan for a particular key &2058 a0 ff LDY #&ff &205a 20 f4 ff JSR &fff4 ; OSBYTE &205d e0 ff CPX #&ff # Leave with equal set if key pressed &205f 60 RTS ; check_for_joystick_fire &2060 a2 00 LDX #&00 ; joystick buttons &2062 a9 80 LDA #&80 ; Read I/O device or buffer status &2064 20 f4 ff JSR &fff4 ; OSBYTE &2067 8a TXA &2068 29 03 AND #&03 &206a 60 RTS # Leave with non-zero if joystick fire button pressed ; set_default_palette &206b a2 01 LDX #&01 # Set colour 1 to blue &206d a0 04 LDY #&04 &206f 20 81 20 JSR &2081 ; set_colour &2072 a2 02 LDX #&02 # Set colour 2 to red &2074 a0 01 LDY #&01 &2076 20 81 20 JSR &2081 ; set_colour &2079 a2 03 LDX #&03 # Set colour 3 to yellow &207b a0 03 LDY #&03 &207d 20 81 20 JSR &2081 ; set_colour &2080 60 RTS ; set_colour # Called with X = logical colour, Y = physical colour &2081 a9 13 LDA #&13 &2083 20 ee ff JSR &ffee ; OSWRCH &2086 8a TXA &2087 20 ee ff JSR &ffee ; OSWRCH &208a 98 TYA &208b 20 ee ff JSR &ffee ; OSWRCH &208e a9 00 LDA #&00 &2090 20 ee ff JSR &ffee ; OSWRCH &2093 20 ee ff JSR &ffee ; OSWRCH &2096 20 ee ff JSR &ffee ; OSWRCH &2099 60 RTS ; wait_for_vsync &209a ad f6 0c LDA &0cf6 ; machine_type &209d f0 08 BEQ &20a7 ; is_os_0.10 &209f a9 13 LDA #&13 ; Wait for vertical retrace &20a1 20 f4 ff JSR &fff4 ; OSBYTE &20a4 4c af 20 JMP &20af ; set_timer ; is_os_0.10 &20a7 ad 24 02 LDA &0224 ; net_vector_low ; wait_for_vsync_on_os_0.10_loop &20aa cd 24 02 CMP &0224 ; net_vector_low &20ad f0 fb BEQ &20aa ; wait_for_vsync_on_os_0.10_loop ; set_timer &20af a9 c0 LDA #&c0 # Set User VIA Timer 1 to one-shot interrupt on PB7 &20b1 8d 6b fe STA &fe6b ; User VIA auxiliary control register &20b4 a9 3e LDA #&3e ; &9c3e = 39998 # Set timer to timeout after 0.039998 seconds &20b6 8d 64 fe STA &fe64 ; User VIA timer 1 counter LSB # i.e. approximately 25 times a second / two v-syncs &20b9 a9 9c LDA #&9c &20bb 8d 65 fe STA &fe65 ; User VIA timer 1 counter MSB &20be 60 RTS ; consider_adding_to_side_walls &20bf ad f7 0c LDA &0cf7 ; difficulty &20c2 c9 02 CMP #&02 # No side walls if this is a MILD ENCOUNTER &20c4 90 62 BCC &2128 ; skip_adding_to_side_walls &20c6 ad f2 05 LDA &05f2 ; ufo_departure_direction # Non-zero if UFO has departed without being destroyed &20c9 f0 62 BEQ &212d ; to_leave &20cb ad 09 0c LDA &0c09 ; movers_x + &00 (player) &20ce cd bd 0c CMP &0cbd ; ground_right_edge_x &20d1 f0 5a BEQ &212d ; to_leave &20d3 18 CLC &20d4 69 01 ADC #&01 &20d6 cd bd 0c CMP &0cbd ; ground_right_edge_x &20d9 d0 07 BNE &20e2 ; check_enemies_not_at_right_edge &20db ad 01 0c LDA &0c01 ; movers_x_fraction + &00 (player) &20de c9 02 CMP #&02 &20e0 b0 4b BCS &212d ; to_leave ; check_enemies_not_at_right_edge &20e2 a2 0b LDX #&0b ; find_rightmost_column_loop &20e4 ca DEX &20e5 30 46 BMI &212d ; to_leave &20e7 bd e0 05 LDA &05e0,X ; enemies_in_column &20ea 30 f8 BMI &20e4 ; find_rightmost_column_loop &20ec bd 20 05 LDA &0520,X ; enemy_columns_x &20ef 18 CLC &20f0 69 01 ADC #&01 &20f2 cd bf 0c CMP &0cbf ; screen_right_edge_x &20f5 90 39 BCC &2130 ; consider_adding_to_left_wall &20f7 4c 2d 21 JMP &212d ; to_leave ; add_to_right_wall &20fa ad bd 0c LDA &0cbd ; ground_right_edge_x &20fd 18 CLC &20fe 69 03 ADC #&03 &2100 20 92 21 JSR &2192 ; unplot_edge_of_ground # Unplot right edge of ground &2103 ad bd 0c LDA &0cbd ; ground_right_edge_x &2106 38 SEC &2107 e9 01 SBC #&01 &2109 8d bd 0c STA &0cbd ; ground_right_edge_x &210c ad bf 0c LDA &0cbf ; screen_right_edge_x &210f 18 CLC &2110 69 03 ADC #&03 &2112 20 74 21 JSR &2174 ; plot_wall # Plot right wall &2115 ad bf 0c LDA &0cbf ; screen_right_edge_x &2118 38 SEC &2119 e9 01 SBC #&01 &211b 8d bf 0c STA &0cbf ; screen_right_edge_x &211e a9 05 LDA #&05 &2120 20 5f 12 JSR &125f ; play_sound # Play sound for adding to side walls &2123 a9 05 LDA #&05 &2125 8d e9 0c STA &0ce9 ; enemy_movement_sound_cooldown ; skip_adding_to_side_walls &2128 a9 00 LDA #&00 &212a 8d f2 05 STA &05f2 ; ufo_departure_direction # Set to zero to suppress further addition to side walls ; to_leave &212d 4c 73 21 JMP &2173 ; leave ; check_left_wall &2130 ad 09 0c LDA &0c09 ; movers_x + &00 (player) &2133 cd bc 0c CMP &0cbc ; ground_left_edge_x &2136 f0 3b BEQ &2173 ; leave ; check_enemies_not_at_left_edge &2138 a2 ff LDX #&ff ; find_leftmost_column_loop &213a e8 INX &213b e0 0b CPX #&0b &213d b0 34 BCS &2173 ; leave &213f bd e0 05 LDA &05e0,X ; enemies_in_column &2142 30 f6 BMI &213a ; find_leftmost_column_loop &2144 ad be 0c LDA &0cbe ; screen_left_edge_x &2147 18 CLC &2148 69 01 ADC #&01 &214a dd 20 05 CMP &0520,X ; enemy_columns_x &214d b0 24 BCS &2173 ; leave ; add_to_left_wall &214f ad bc 0c LDA &0cbc ; ground_left_edge_x &2152 38 SEC &2153 e9 02 SBC #&02 &2155 20 92 21 JSR &2192 ; unplot_edge_of_ground # Unplot left edge of ground &2158 ad bc 0c LDA &0cbc ; ground_left_edge_x &215b 18 CLC &215c 69 01 ADC #&01 &215e 8d bc 0c STA &0cbc ; ground_left_edge_x &2161 ad be 0c LDA &0cbe ; screen_left_edge_x &2164 20 74 21 JSR &2174 ; plot_wall # Plot left wall &2167 ad be 0c LDA &0cbe ; screen_left_edge_x &216a 18 CLC &216b 69 01 ADC #&01 &216d 8d be 0c STA &0cbe ; screen_left_edge_x &2170 4c fa 20 JMP &20fa ; add_to_right_wall ; leave &2173 60 RTS ; plot_wall &2174 85 70 STA &70 ; sprite_x &2176 a9 15 LDA #&15 ; SPRITE_WALL &2178 85 79 STA &79 ; sprite &217a a9 00 LDA #&00 &217c 85 76 STA &76 ; sprite_x_fraction &217e a9 31 LDA #&31 &2180 85 71 STA &71 ; sprite_y &2182 a2 0e LDX #&0e ; plot_wall_loop &2184 18 CLC &2185 a5 71 LDA &71 ; sprite_y &2187 69 0a ADC #&0a &2189 85 71 STA &71 ; sprite_y &218b 20 07 0e JSR &0e07 ; plot_sprite # Plot side wall &218e ca DEX &218f d0 f3 BNE &2184 ; plot_wall_loop &2191 60 RTS ; unplot_edge_of_ground &2192 85 70 STA &70 ; sprite_x &2194 a9 10 LDA #&10 ; SPRITE_GROUND &2196 85 79 STA &79 ; sprite &2198 a9 00 LDA #&00 &219a 85 76 STA &76 ; sprite_x_fraction &219c a9 ef LDA #&ef &219e 85 71 STA &71 ; sprite_y &21a0 20 02 0e JSR &0e02 ; plot_or_unplot_sprite # Unplot edge of ground &21a3 60 RTS ; plot_level_tally &21a4 ce f5 0c DEC &0cf5 ; level_tally_x &21a7 ad f5 0c LDA &0cf5 ; level_tally_x &21aa c9 2c CMP #&2c &21ac 90 11 BCC &21bf ; leave &21ae 85 70 STA &70 ; sprite_x &21b0 a9 f6 LDA #&f6 &21b2 85 71 STA &71 ; sprite_y &21b4 a9 00 LDA #&00 &21b6 85 76 STA &76 ; sprite_x_fraction &21b8 a9 0c LDA #&0c ; SPRITE_MISSILE &21ba 85 79 STA &79 ; sprite &21bc 20 07 0e JSR &0e07 ; plot_sprite # Plot level tally ; leave &21bf ea NOP &21c0 60 RTS ; unused &21c1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &21d1 00 00 00 ; scoring_text &21d4 1f 0f 08 ; TAB(&0f, &08) &21d7 73 63 6f 72 65 73 20 31 30 20 70 6f 69 6e 74 73 ; "scores 10 points" &21e7 1f 0f 0c ; TAB(&0f, &0c) &21ea 73 63 6f 72 65 73 20 32 30 20 70 6f 69 6e 74 73 ; "scores 20 points" &21fa 1f 0f 10 ; TAB(&0f, &10) &21fd 73 63 6f 72 65 73 20 33 30 20 70 6f 69 6e 74 73 ; "scores 30 points" &220d 1f 0a 14 ; TAB(&0a, &14) &2210 3f 20 73 63 6f 72 65 73 20 6d 6f 73 74 20 66 6f ; "? scores most for central hit" &2220 72 20 63 65 6e 74 72 61 6c 20 68 69 74 &222d 1f 07 1e ; TAB(&07, &1e) &2230 50 72 65 73 73 20 73 70 61 63 65 20 62 61 72 20 ; "Press space bar to continue" &2240 74 6f 20 63 6f 6e 74 69 6e 75 65 &224b ff ; end of string ; key_text &224c 1f 0b 06 ; TAB(&0b, &06) &224f 45 78 74 72 61 20 64 65 66 65 6e 64 65 72 20 61 ; "Extra defender at" &225f 74 &2260 1f 09 08 ; TAB(&09, &08) &2263 35 30 30 30 20 61 6e 64 20 31 35 30 30 30 20 70 ; "5000 and 15000 points." &2273 6f 69 6e 74 73 2e &2279 1f 03 0c ; TAB(&03, &0c) &227c 4b 45 59 53 3a ; "KEYS:" &2281 1f 0c 0e ; TAB(&0c, &0e) &2284 27 5a 27 20 74 6f 20 6d 6f 76 65 20 6c 65 66 74 ; "'Z' to move left" &2294 1f 0c 10 ; TAB(&0c, &10) &2297 27 58 27 20 74 6f 20 6d 6f 76 65 20 72 69 67 68 ; "'X' to move right" &22a7 74 &22a8 1f 07 12 ; TAB(&07, &12) &22ab 27 52 45 54 55 52 4e 27 20 74 6f 20 66 69 72 65 ; "'RETURN' to fire missiles" &22bb 20 6d 69 73 73 69 6c 65 73 &22c4 1f 03 18 ; TAB(&03, &18) &22c7 50 72 65 73 73 20 46 49 52 45 20 62 75 74 74 6f ; "Press FIRE button to select joystick" &22d7 6e 20 74 6f 20 73 65 6c 65 63 74 20 6a 6f 79 73 &22e7 74 69 63 6b &22eb 1f 07 1b ; TAB(&07, &1b) &22ee 6f 72 ; "or" &22f0 1f 07 1e ; TAB(&07, &1e) &22f3 50 72 65 73 73 20 73 70 61 63 65 20 62 61 72 20 ; "Press space bar to continue" &2303 74 6f 20 63 6f 6e 74 69 6e 75 65 &230e ff ; end of string ; select_difficulty_text &230f 1f 0a 09 ; TAB(&0a, &09) &2312 50 72 65 73 73 20 27 31 27 20 66 6f 72 20 61 ; "Press '1' for a" &2321 1f 0f 0b ; TAB(&0f, &0b) &2324 4d 49 4c 44 20 45 4e 43 4f 55 4e 54 45 52 ; "MILD ENCOUNTER" &2332 1f 0a 0f ; TAB(&0a, &0f) &2335 50 72 65 73 73 20 27 32 27 20 66 6f 72 20 61 6e ; "Press '2' for an" &2345 1f 0f 11 ; TAB(&0f, &11) &2348 55 4e 43 4f 4d 46 4f 52 54 41 42 4c 45 20 53 49 ; "UNCOMFORTABLE SITUATION" &2358 54 55 41 54 49 4f 4e &235f 1f 0a 15 ; TAB(&0a, &15) &2362 50 72 65 73 73 20 27 33 27 20 66 6f 72 20 61 ; "Press '3' for a" &2371 1f 0f 17 ; TAB(&0f, &17) &2374 54 45 52 52 49 46 59 49 4e 47 20 45 58 50 45 52 ; "TERRIFYING EXPERIENCE" &2384 49 45 4e 43 45 &2389 ff ; end of string ; score_text &238a 1f 02 01 ; TAB(&02, &01) &238d 53 63 6f 72 65 20 20 30 30 30 30 30 ; "Score 00000" &2399 1f 15 01 ; TAB(&15, &01) &239c 48 69 67 68 20 53 63 6f 72 65 20 20 30 30 30 30 ; "High Score 00000" &23ac 30 &23ad ff ; end of string ; restart_text &23ae 1f 05 04 ; TAB(&05, &04) &23b1 50 72 65 73 73 20 74 68 65 20 73 70 61 63 65 20 ; "Press the space bar to restart" &23c1 62 61 72 20 74 6f 20 72 65 73 74 61 72 74 &23cf ff ; end of string ; sprite data ; sprite_15_zero (SPRITE_WALL) &23d0 0a &23d1 00 00 00 00 00 00 00 00 00 00 &23db 40 &23dc 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ; sprite_14_three (SPRITE_MISSILE_REMOVER) &23e6 0a &23e7 02 88 02 88 02 88 02 88 02 88 &23f1 40 &23f2 11 88 11 88 11 cc 11 cc 11 88 ; sprite_14_two (SPRITE_MISSILE_REMOVER) &23fc 0a &23fd 02 88 02 88 02 88 02 88 02 88 &2407 40 &2408 33 00 33 00 33 88 33 88 33 00 ; sprite_14_one (SPRITE_MISSILE_REMOVER) &2412 0a &2413 02 88 02 88 02 88 02 88 02 88 &241d 40 &241e 66 00 66 00 77 00 77 00 66 00 ; sprite_14_zero (SPRITE_MISSILE_REMOVER) &2428 05 &2429 02 02 02 02 02 &242e 40 &242f cc cc ee ee cc ; sprite_13_three (SPRITE_UFO) &2434 01 &2435 00 &2436 40 &2437 ff ; sprite_13_two (SPRITE_UFO) &2438 22 &2439 04 8c 04 8c 02 88 8c 90 00 84 88 8c 90 94 00 84 &2449 88 8c 90 94 00 84 88 8c 90 94 02 88 8c 90 04 8c &2459 04 8c &245b 40 &245c 11 88 27 ae 11 6f df 88 01 ef ef ef ef 88 23 ef &246c ef ef ef cc 01 ef ef ef ef 88 11 6f df 88 27 ae &247c 11 88 ; sprite_13_one (SPRITE_UFO) &247e 01 &247f 00 &2480 40 &2481 ff ; sprite_13_zero (SPRITE_UFO) &2482 1d &2483 04 02 88 8c 02 88 8c 00 84 88 8c 90 00 84 88 8c &2493 90 00 84 88 8c 90 02 88 8c 02 88 8c 04 &24a0 40 &24a1 66 11 5f 08 67 ef ce 67 ef ef ef ee ef ef ef ef &24b1 ef 67 ef ef ef ee 67 ef ce 11 5f 08 66 ; sprite_12_three (SPRITE_MISSILE_BOMB_EXPLOSION) &24be 10 &24bf 02 88 04 8c 02 88 00 84 88 02 88 00 88 8c 02 88 &24cf 40 &24d0 11 00 11 00 00 44 00 99 00 00 44 00 55 00 00 88 ; sprite_12_two (SPRITE_MISSILE_BOMB_EXPLOSION) &24e0 10 &24e1 02 88 04 8c 02 88 00 84 88 02 88 00 88 8c 02 88 &24f1 40 &24f2 22 00 22 00 00 88 11 22 00 00 88 00 aa 00 11 00 ; sprite_12_one (SPRITE_MISSILE_BOMB_EXPLOSION) &2502 10 &2503 02 88 04 8c 02 88 00 84 88 02 88 00 88 8c 02 88 &2513 40 &2514 44 00 44 00 11 00 22 44 00 11 00 11 44 00 22 00 ; sprite_12_zero (SPRITE_MISSILE_BOMB_EXPLOSION) &2524 09 &2525 02 04 02 00 84 02 00 88 02 &252e 40 &252f 88 88 22 44 88 22 22 88 44 ; sprite_11_three (SPRITE_BOMB_GROUND_EXPLOSION) &2538 0e &2539 00 84 02 88 02 88 02 88 02 88 02 88 02 88 &2547 40 &2548 00 22 00 22 11 00 00 44 11 00 00 00 00 88 ; sprite_11_two (SPRITE_BOMB_GROUND_EXPLOSION) &2556 0e &2557 00 84 02 88 02 88 02 88 02 88 02 88 02 88 &2565 40 &2566 00 44 00 44 22 00 00 88 22 00 00 00 11 00 ; sprite_11_one (SPRITE_BOMB_GROUND_EXPLOSION) &2574 0e &2575 00 84 02 88 02 88 02 88 02 88 02 88 02 88 &2583 40 &2584 00 88 00 88 44 00 11 00 44 00 00 00 22 00 ; sprite_11_zero (SPRITE_BOMB_GROUND_EXPLOSION) &2592 07 &2593 00 02 02 02 02 02 02 &259a 40 &259b 11 11 88 22 88 00 44 ; sprite_10_three (SPRITE_GROUND) &25a2 08 &25a3 00 84 88 8c 00 84 88 8c &25ab 40 &25ac 01 0f 0f 0e 01 0f 0f 0e ; sprite_10_two (SPRITE_GROUND) &25b4 08 &25b5 00 84 88 8c 00 84 88 8c &25bd 40 &25be 03 0f 0f 0c 03 0f 0f 0c ; sprite_10_one (SPRITE_GROUND) &25c6 08 &25c7 00 84 88 8c 00 84 88 8c &25cf 40 &25d0 07 0f 0f 08 07 0f 0f 08 ; sprite_10_zero (SPRITE_GROUND) &25d8 06 &25d9 00 84 88 00 84 88 &25df 40 &25e0 0f 0f 0f 0f 0f 0f ; sprite_0f_three (SPRITE_DAMAGE) &25e6 1a &25e7 02 88 00 84 88 00 84 88 00 84 88 00 84 88 00 84 &25f7 88 00 84 88 00 84 88 00 84 88 &2601 40 &2602 11 88 00 33 cc 00 77 ee 00 77 cc 00 33 ee 00 77 &2612 cc 00 33 ee 00 77 cc 00 22 88 ; sprite_0f_two (SPRITE_DAMAGE) &261c 1a &261d 02 88 00 84 88 00 84 88 00 84 88 00 84 88 00 84 &262d 88 00 84 88 00 84 88 00 84 88 &2637 40 &2638 33 00 00 77 88 00 ff cc 00 ff 88 00 77 cc 00 ff &2648 88 00 77 cc 00 ff 88 00 55 00 ; sprite_0f_one (SPRITE_DAMAGE) &2652 1a &2653 02 88 00 84 88 00 84 88 00 84 88 00 84 88 00 84 &2663 88 00 84 88 00 84 88 00 84 88 &266d 40 &266e 66 00 00 ff 00 11 ff 88 11 ff 00 00 ff 88 11 ff &267e 00 00 ff 88 11 ff 00 00 aa 00 ; sprite_0f_zero (SPRITE_DAMAGE) &2688 11 &2689 02 00 84 00 84 00 84 00 84 00 84 00 84 00 84 00 &2699 84 &269a 40 &269b cc 11 ee 33 ff 33 ee 11 ff 33 ee 11 ff 33 ee 11 &26ab 44 ; sprite_0e_zero (SPRITE_MISSILE_ENEMY_EXPLOSION) &26ac 15 &26ad 00 88 02 8c 02 8c 00 88 02 8c 00 84 8c 00 8c 00 &26bd 84 88 02 8c 02 &26c2 40 &26c3 11 11 01 22 40 08 22 44 80 04 44 22 11 10 80 02 &26d3 01 22 88 22 01 ; sprite_0d_zero (SPRITE_SHIELD) # Also used for unplotting areas &26d8 1e &26d9 00 84 88 00 84 88 00 84 88 00 84 88 00 84 88 00 &26e9 84 88 00 84 88 00 84 88 00 84 88 00 84 88 &26f7 40 &26f8 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff &2708 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ; sprite_0d_two (SPRITE_SHIELD) &2716 2c &2717 04 8c 90 02 88 8c 90 94 02 88 8c 90 94 00 84 88 &2727 8c 90 94 98 00 84 88 8c 90 94 98 00 84 88 8c 90 &2737 94 98 0c 0c 0c 0c 0c 0c 0c 0c 0c 0c &2743 40 &2744 ff ff ff 33 ff ff ff cc ff ff ff ff ff 33 ff ff &2754 ff ff ff cc ff ff ff ff ff ff ff ff ff ff ff ff &2764 ff ff ff ff ff ff ff ff ff ff ff ff ; sprite_0c_three (SPRITE_MISSILE) &2700 05 &2701 02 02 02 02 02 &2706 40 &2707 11 11 11 11 11 ; sprite_0c_two (SPRITE_MISSILE) &277e 05 &277f 02 02 02 02 02 &2784 40 &2785 22 22 22 22 22 ; sprite_0c_one (SPRITE_MISSILE) &2788 05 &2789 02 02 02 02 02 &278e 40 &278f 44 44 44 44 44 ; sprite_0c_zero (SPRITE_MISSILE) &2794 05 &2795 02 02 02 02 02 &279a 40 &279b 88 88 88 88 88 ; sprite_0b_three (SPRITE_BOMB) &27a0 0a &27a1 02 88 02 88 02 88 02 88 02 88 &27ab 40 &27ac 00 88 00 88 11 cc 11 cc 00 88 ; sprite_0b_two (SPRITE_BOMB) &27b6 0a &27b7 02 88 02 88 02 88 02 88 02 88 &27c1 40 &27c2 11 00 11 00 33 88 33 88 11 00 ; sprite_0b_one (SPRITE_BOMB) &27cc 0a &27cd 02 88 02 88 02 88 02 88 02 88 &27d7 40 &27d8 22 00 22 00 77 00 77 00 22 00 ; sprite_0b_zero (SPRITE_BOMB) &27e2 05 &27e3 02 02 02 02 02 &27e8 40 &27e9 44 44 ee ee 44 ; sprite_0a_three (SPRITE_PLAYER) &27ee 1e &27ef 04 04 04 04 02 88 8c 02 88 8c 90 00 84 88 8c 90 &27ff 00 84 88 8c 90 00 84 88 8c 90 02 88 8c 90 &280d 40 &280e 22 22 77 77 67 ef ef 8f 0f 0f 88 01 0f 0f 0f 4c &281e 11 0f 0f 0f 4c 11 0f 0f 0f 0c bf bf bf 88 ; sprite_0a_two (SPRITE_PLAYER) &282c 1e &282d 04 04 04 04 02 88 8c 00 84 88 8c 00 84 88 8c 90 &283d 00 84 88 8c 90 00 84 88 8c 90 00 84 88 8c &284b 40 &284c 44 44 ee ee ef ef ee 01 0f 0f 0f 23 0f 0f 0f 88 &285c 23 0f 0f 0f 88 23 0f 0f 0f 88 01 ef ef ef ; sprite_0a_one (SPRITE_PLAYER) &286a 1e &286b 04 04 02 88 02 88 00 84 88 8c 00 84 88 8c 00 84 &287b 88 8c 00 84 88 8c 00 84 88 8c 00 84 88 8c &2889 40 &288a 88 88 11 cc 11 cc 01 ef ef cc 23 0f 0f 2e 47 0f &289a 0f 0f 47 0f 0f 1f 07 0f 0f 1f 33 bf bf ae ; sprite_0a_zero (SPRITE_PLAYER) &28a8 1e &28a9 02 02 02 88 02 88 00 84 88 8c 00 84 88 8c 00 84 &28b9 88 8c 00 84 88 8c 00 84 88 8c 00 84 88 8c &28c7 40 &28c8 11 11 33 88 33 88 23 ef ef 88 47 0f 0f 4c 8f 0f &28d8 0f 2e 0f 0f 0f 0e 8f 0f 0f 2e 67 ef ef cc ; sprite_07_two (SPRITE_ALIEN_SEVEN) &28e6 14 &28e7 02 88 02 88 02 88 02 88 02 88 02 88 02 88 02 88 &28f7 02 88 02 88 &28fb 40 &28fc 10 80 30 c0 f0 f0 80 10 a2 54 80 10 80 10 f0 f0 &290c 30 c0 c0 30 ; sprite_07_zero (SPRITE_ALIEN_SEVEN) &2910 14 &2911 02 88 02 88 02 88 02 88 02 88 02 88 02 88 02 88 &2921 02 88 02 88 &2925 40 &2926 10 80 30 c0 f0 f0 80 10 80 10 a2 54 80 10 f0 f0 &2936 30 c0 60 60 ; sprite_06_two (SPRITE_ALIEN_SIX) &293a 1a &293b 02 88 00 84 88 8c 00 84 88 8c 00 84 88 8c 02 88 &294b 02 88 02 88 00 84 88 04 00 84 &2955 40 &2956 88 22 11 ee 77 88 11 66 55 88 11 66 55 88 ff ff &2966 77 dd ff aa 11 ff 44 88 11 ff ; sprite_06_zero (SPRITE_ALIEN_SIX) &2970 1a &2971 02 88 00 84 88 8c 00 84 88 8c 00 84 88 8c 02 88 &2981 02 88 02 88 02 88 8c 02 04 8c &298b 40 &298c 44 11 11 ee 77 88 11 aa 66 88 11 aa 66 88 ff ff &299c bb ee 55 ff 22 ff 88 11 ff 88 ; sprite_05_two (SPRITE_ALIEN_FIVE) &29a6 1c &29a7 00 84 88 8c 02 88 02 88 02 88 02 88 00 84 88 8c &29b7 00 84 88 8c 00 84 88 8c 02 88 02 88 &29c3 40 &29c4 01 03 0c 08 2f 4f 07 0e 07 0e 0f 0f 01 0f 0f 08 &29d4 01 77 ee 08 01 22 44 08 08 01 07 0e ; sprite_05_zero (SPRITE_ALIEN_FIVE) &29e0 1a &29e1 02 88 02 88 00 84 88 8c 02 88 02 88 02 88 02 88 &29f1 00 84 88 8c 00 84 88 8c 02 88 &29fb 40 &29fc 03 0c 2f 4f 01 07 0e 08 07 0e 07 0e 0f 0f 0f 0f &2a0c 01 0e 07 08 01 08 01 08 0f 0f ; sprite_04_two (SPRITE_ALIEN_FOUR) &2a16 1b &2a17 00 02 88 00 84 88 8c 00 84 88 8c 00 8c 00 84 88 &2a27 8c 02 88 00 84 88 8c 02 88 02 88 &2a32 40 &2a33 00 c0 30 10 80 10 80 20 c0 30 40 20 40 10 10 80 &2a43 80 f0 f0 10 d0 b0 80 f0 f0 40 20 ; sprite_04_zero (SPRITE_ALIEN_FOUR) &2a4e 18 &2a4f 02 88 02 88 00 8c 00 8c 00 8c 00 84 88 8c 02 88 &2a5f 00 84 88 8c 02 88 02 88 &2a67 40 &2a68 60 60 c0 30 10 80 10 80 10 80 10 10 80 80 f0 f0 &2a78 10 d0 b0 80 f0 f0 20 40 ; sprite_03_two (SPRITE_ALIEN_THREE) &2a80 1a &2a81 02 88 02 88 02 88 02 88 02 88 8c 02 88 8c 00 84 &2a91 88 8c 00 84 88 00 84 88 00 88 &2a9b 40 &2a9c 33 cc 77 ee cc 33 ff ff 77 ee 4c 9b 99 04 01 22 &2aac 04 44 22 04 44 02 44 04 22 44 ; sprite_03_zero (SPRITE_ALIEN_THREE) &2ab6 1a &2ab7 02 88 02 88 02 88 02 88 00 84 88 00 84 88 00 84 &2ac7 88 8c 02 88 8c 02 88 8c 02 8c &2ad1 40 &2ad2 33 cc 77 ee cc 33 ff ff 23 77 ee 02 99 9d 22 02 &2ae2 44 08 22 02 44 02 22 04 22 44 ; sprite_01_two (SPRITE_ALIEN_ONE) &2aec 24 &2aed 00 8c 00 8c 00 84 88 8c 00 84 88 8c 00 84 88 8c &2afd 00 84 88 8c 00 84 88 8c 00 84 88 8c 00 84 88 8c &2b0d 00 84 88 8c &2b11 40 &2b12 c0 30 20 40 20 f0 f0 40 10 10 80 80 20 dc e6 40 &2b22 70 f0 f0 e0 70 f0 f0 e0 60 44 22 60 30 f0 f0 c0 &2b32 10 f0 f0 80 ; sprite_01_zero (SPRITE_ALIEN_ONE) &2b36 26 &2b37 00 84 88 8c 00 8c 00 84 88 8c 00 84 88 8c 00 84 &2b47 88 8c 00 84 88 8c 00 84 88 8c 00 84 88 8c 00 84 &2b57 88 8c 00 84 88 8c &2b5d 40 &2b5e 10 80 10 80 20 40 20 f0 f0 40 10 10 80 80 20 76 &2b6e b3 40 70 f0 f0 e0 70 f0 f0 e0 60 44 22 60 30 99 &2b7e 99 c0 10 f0 f0 80 ; sprite_02_two (SPRITE_ALIEN_TWO) &2b84 1e &2b85 00 84 88 8c 00 84 88 8c 00 84 88 8c 00 84 88 8c &2b95 00 84 88 8c 02 88 02 88 02 88 02 88 02 88 &2ba3 40 &2ba4 04 03 0c 02 04 07 0e 02 04 0f 0f 02 02 6f 6f 04 &2bb4 01 6f 6f 08 0f 0f 0f 0f 04 02 04 02 0e 07 ; sprite_02_zero (SPRITE_ALIEN_TWO) &2bc2 1e &2bc3 02 88 02 88 02 88 02 88 02 88 00 84 88 8c 00 84 &2bd3 88 8c 00 84 88 8c 00 84 88 8c 00 84 88 8c &2be1 40 &2be2 03 0c 07 0e 0f 0f 09 09 09 09 01 0f 0f 08 02 0f &2bf2 0f 04 04 04 02 02 04 04 02 02 04 0e 07 02 ; sprite_addresses_table ; zero one two three &2c00 36 2b ff ff ec 2a ff ff ; &2b36, &2aec : sprite_01 (SPRITE_ALIEN_ONE) &2c08 c2 2b ff ff 84 2b ff ff ; &2bc2, &2b84 : sprite_02 (SPRITE_ALIEN_TWO) &2c10 b6 2a ff ff 80 2a ff ff ; &2ab6, &2a80 : sprite_03 (SPRITE_ALIEN_THREE) &2c18 4e 2a ff ff 16 2a ff ff ; &2a4e, &2a16 : sprite_04 (SPRITE_ALIEN_FOUR) &2c20 e0 29 ff ff a6 29 ff ff ; &29e0, &29a6 : sprite_05 (SPRITE_ALIEN_FIVE) &2c28 70 29 ff ff 3a 29 ff ff ; &2970, &293a : sprite_06 (SPRITE_ALIEN_SIX) &2c30 10 29 ff ff e6 28 ff ff ; &2910, &28e6 : sprite_07 (SPRITE_ALIEN_SEVEN) &2c38 ff ff ff ff ff ff ff ff ; : sprite_08 (unused) &2c40 00 00 00 00 00 00 00 00 ; : sprite_09 (unused) &2c48 a8 28 6a 28 2c 28 ee 27 ; &28a8, &286a, &282c, &27ee : sprite_0a (SPRITE_PLAYER) &2c50 e2 27 cc 27 b6 27 a0 27 ; &27e2, &27cc, &27b6, &27a0 : sprite_0b (SPRITE_BOMB) &2c58 94 27 88 27 7c 27 70 27 ; &2794, &2788, &277c, &2770 : sprite_0c (SPRITE_MISSILE) &2c60 d8 26 00 00 16 27 00 00 ; &26d8, &0000, &2716, &0000 : sprite_0d (SPRITE_SHIELD) &2c68 ac 26 00 00 00 00 00 00 ; &26ac, &0000, &0000, &0000 : sprite_0e (SPRITE_MISSILE_ENEMY_EXPLOSION) &2c70 88 26 52 26 1c 26 e6 25 ; &2688, &2652, &261c, &25e6 : sprite_0f (SPRITE_DAMAGE) &2c78 d8 25 c6 25 b4 25 a2 25 ; &25d8, &25c6, &25b4, &25a2 : sprite_10 (SPRITE_GROUND) &2c80 92 25 74 25 56 25 38 25 ; &2592, &2574, &2556, &2538 : sprite_11 (SPRITE_BOMB_GROUND_EXPLOSION) &2c88 24 25 02 25 e0 24 be 24 ; &2524, &2502, &24e0, &24be : sprite_12 (SPRITE_MISSILE_BOMB_EXPLOSION) &2c90 82 24 7e 24 38 24 34 24 ; &2482, &247e, &2438, &2434 : sprite_13 (SPRITE_UFO) &2c98 28 24 12 24 fc 23 e6 23 ; &2428, &2412, &23fc, &23e6 : sprite_14 (SPRITE_MISSILE_REMOVER) &2ca0 d0 23 ff ff ff ff ff ff ; &23d0 : sprite_15 (SPRITE_WALL) &2ca8 ff ff ff ff ff ff ff ff ; : sprite_16 (unused) &2cb0 ff ff ff ff ff ff ff ff ; : sprite_17 (unused) &2cb8 ff ff ff ff ff ff ff ff ; : sprite_18 (unused) ; envelope_data &2cc0 01 01 d8 fb ff 02 05 0a 7f 00 ff fe 78 78 # Firing missile &2cce 03 01 02 02 02 14 14 14 00 00 00 ff 6e 6e # Player dying &2cdc 04 01 0a f6 f6 08 04 04 00 00 00 ff 50 50 # UFO ; unused &2cea 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; scoring_text_address &2cfa d4 21 ; &21d4 = scoring_text ; envelope_address_low &2cfc 00 ; envelope_address_high &2cfd 00 ; unused &2cfe 00 2c ; row_addresses_low_table &2d00 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d10 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d20 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d30 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d40 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d50 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d60 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d70 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d80 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2d90 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2da0 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2db0 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2dc0 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2dd0 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2de0 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 &2df0 00 01 02 03 04 05 06 07 80 81 82 83 84 85 86 87 ; row_addresses_high_table &2e00 30 30 30 30 30 30 30 30 32 32 32 32 32 32 32 32 &2e10 35 35 35 35 35 35 35 35 37 37 37 37 37 37 37 37 &2e20 3a 3a 3a 3a 3a 3a 3a 3a 3c 3c 3c 3c 3c 3c 3c 3c &2e30 3f 3f 3f 3f 3f 3f 3f 3f 41 41 41 41 41 41 41 41 &2e40 44 44 44 44 44 44 44 44 46 46 46 46 46 46 46 46 &2e50 49 49 49 49 49 49 49 49 4b 4b 4b 4b 4b 4b 4b 4b &2e60 4e 4e 4e 4e 4e 4e 4e 4e 50 50 50 50 50 50 50 50 &2e70 53 53 53 53 53 53 53 53 55 55 55 55 55 55 55 55 &2e80 58 58 58 58 58 58 58 58 5a 5a 5a 5a 5a 5a 5a 5a &2e90 5d 5d 5d 5d 5d 5d 5d 5d 5f 5f 5f 5f 5f 5f 5f 5f &2ea0 62 62 62 62 62 62 62 62 64 64 64 64 64 64 64 64 &2eb0 67 67 67 67 67 67 67 67 69 69 69 69 69 69 69 69 &2ec0 6c 6c 6c 6c 6c 6c 6c 6c 6e 6e 6e 6e 6e 6e 6e 6e &2ed0 71 71 71 71 71 71 71 71 73 73 73 73 73 73 73 73 &2ee0 76 76 76 76 76 76 76 76 78 78 78 78 78 78 78 78 &2ef0 7b 7b 7b 7b 7b 7b 7b 7b 7d 7d 7d 7d 7d 7d 7d 7d ; column_offsets_low_table &2f00 00 08 10 18 20 28 30 38 40 48 50 58 60 68 70 78 &2f10 80 88 90 98 a0 a8 b0 b8 c0 c8 d0 d8 e0 e8 f0 f8 &2f20 00 08 10 18 20 28 30 38 40 48 50 58 60 68 70 78 &2f30 80 88 90 98 a0 a8 b0 b8 c0 c8 d0 d8 e0 e8 f0 f8 &2f40 00 08 10 18 20 28 30 38 40 48 50 58 60 68 70 78 ; column_offsets_high_table &2f50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &2f60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &2f70 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 &2f80 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 &2f90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ; sound_data ; chan vol pitch dur &2fa0 12 00 f4 ff 04 00 02 00 ; &00 # Moving enemies &2fa8 10 00 f6 ff 04 00 04 00 ; &01 # Destroying enemy &2fb0 12 00 f4 ff 00 00 02 00 ; &02 # Moving enemies &2fb8 11 01 03 00 32 00 28 00 ; &03 # Player dying &2fc0 12 01 03 00 3c 00 28 00 ; &04 # Player dying &2fc8 12 00 f3 ff dc 00 02 00 ; &05 # Adding to side walls &2fd0 11 00 01 00 96 00 02 00 ; &06 # Firing missile &2fd8 10 00 f1 ff 05 00 0f 00 ; &07 # Destroying UFO &2fe0 13 00 04 00 46 00 ff 00 ; &08 # New UFO &2fe8 13 00 04 00 46 00 00 00 ; &09 # Removing UFO &2ff0 12 00 f1 ff 96 00 05 00 ; &0a # Extra life &2ff8 00 00 00 00 00 00 00 00 ; &0b # (unused)