| ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; |
| ; Auto-generated by Regenerator 2000 v0.9.17 |
| ; https://github.com/ricardoquesada/regenerator2000 |
| ; |
| ; Exported from: vic20_omega_race_cart_generic_a000.regen2000proj |
| ; |
| ; Assemble with 64tass: |
| ; 64tass -o vic20_omega_race_cart_generic_a000.prg vic20_omega_race_cart_generic_a000.asm |
| ; |
| ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
|
| ; EXTERNAL LABELS |
| ; zpf_ = Zero Page Field |
| ; zpa_ = Zero Page Absolute Address |
| ; zpp_ = Zero Page Pointer |
| ; f_ = Field |
| ; a_ = Absolute Address |
| ; p_ = Pointer |
| ; e_ = External Jump |
| ; L_ = Other / User-defined |
|
| zp_score_cursor_x = $17 ; x-ref: $ACAF, $ACC4, $AD1E, $AD2D, $ADA7, $ADAC |
| zp_collision_type = $18 ; x-ref: $A5F6, $A610, $A617, $A61C, $A973, $A9AE, $A9C0, $A9CE, ... |
| zp_bullet_slots_free = $19 ; x-ref: $A346, $A472, $ADBD, $AE00, $AEAF |
| zp_marker_idx = $1a ; x-ref: $ABD0, $ABD2, $ABE1, $B17C, $B180, $B19C, $B1A3, $B1A7, ... |
| zp_collision_check_flag = $1b ; x-ref: $A63B, $AB07, $AB26, $AB28, $AB34, $AB36, $AE49, $AE93, ... |
| zp_temp_bcd_score = $1c ; x-ref: $ACB9, $ACCE, $ACE0, $ACF6, $AD04, $AD1A, $AD29, $AD3A, ... |
| zp_player_lives = $1f ; x-ref: $A05C, $A070, $AD66, $B10A, $B161, $B41A |
| zp_current_level = $20 ; x-ref: $A1B7, $A1BF, $A1D0, $A1DC, $A28D |
| zp_current_phase = $21 ; x-ref: $A1BB, $A1CC, $A1D2, $B376, $B38B |
| zp_irq_tick_counter = $22 ; x-ref: $A050, $A0CF, $A370 |
| zp_hiscore_lo = $23 ; x-ref: $A0A2, $A0AC, $A180, $ACCC |
| zp_hiscore_mid = $24 ; x-ref: $A09A, $A0B0, $A182 |
| zp_hiscore_hi = $25 ; x-ref: $A092, $A0B4, $A184 |
| zp_bullet_hit_mask = $26 ; x-ref: $A538, $A542, $AE4B, $AE9C, $AE9E |
| zp_playfield_color = $27 ; x-ref: $A177, $A415, $A45C, $B433, $B481, $B483, $B487 |
| zp_cur_entity_idx = $28 ; x-ref: $AFCC, $AFCE, $AFE5, $B01E, $B04C, $B074, $B17E, $B1A5 |
| zp_prev_heading = $29 ; x-ref: $A1F6, $A924, $A930, $A93F, $A94B, $A956 |
| zp_temp_frame_idx = $2a ; x-ref: $AB9B, $ABA1 |
| zp_player_wall_hits = $2b ; x-ref: $A583, $A59E, $A5DE, $AA7E |
| zp_ptr_gfx_str = $2c ; x-ref: $B2CC, $B2D2, $B2D7, $B2DC, $B2E1, $B2E8, $B2EA |
| zp_ptr_gfx_str_hi = $2d ; x-ref: $B2CE, $B2EE |
| zp_entity_type_to_slot = $002e ; x-ref: $A857, $A867, $B0F5 |
| zp_enemy1_slot_idx = $2f ; x-ref: $A114, $A338, $A69C, $A7BD, $A7F6 |
| zp_enemy3_slot_idx = $30 ; x-ref: $A301, $A6EF, $A7D0, $A811 |
| zp_enemy2_slot_idx = $31 ; x-ref: $A11C, $A336, $A6C6, $A7E3 |
| zp_fire_cooldown = $35 ; x-ref: $A1F2, $A46E, $A8DC, $A92C, $ADBB |
| zp_enemy_ai_speed_mask = $36 ; x-ref: $A256, $A778 |
| zp_frame_counter = $37 ; x-ref: $A03A, $A03C, $A040, $A342, $A496, $A519, $A70B, $A73C, ... |
| zp_enemy1_fire_timer = $38 ; x-ref: $A247, $A7C1 |
| zp_enemy3_fire_timer = $39 ; x-ref: $A24C, $A7D4 |
| zp_enemy2_fire_timer = $3a ; x-ref: $A251, $A7E7 |
| zp_firing_entity_slot = $3b ; x-ref: $A7CB, $A7DE, $A7F1, $A800, $A81B, $AF48 |
| zp_attract_delay_ctr = $3c ; x-ref: $ABF8, $ABFA, $ABFF, $AC06, $AC08, $AC11, $AFE3, $AFE7, ... |
| zp_max_enemy_count = $3d ; x-ref: $A060, $A074, $A1E8, $B0DA |
| zp_game_tick = $3e ; x-ref: $A042, $A1F8, $A6A0, $A6B9, $A6CA, $A6EB, $A7C7, $A7DA, ... |
| zp_entity_count = $40 ; x-ref: $A1EA, $A296, $A298, $A507, $A700, $A726, $A77C, $A889 |
| zp_snd_bass_dur = $41 ; x-ref: $A0DD, $A0EE, $B129 |
| zp_snd_alto_dur = $42 ; x-ref: $A087, $A0FC, $A10B, $A12B, $A21B, $B0E6 |
| zp_snd_soprano_dur = $43 ; x-ref: $A139, $A14A, $A603, $ADCF, $B15A, $B373 |
| zp_snd_noise_dur = $44 ; x-ref: $A158, $A169, $A48D, $A4B8, $B0D0, $B11F |
| zp_snd_bass_seq_idx = $45 ; x-ref: $A0D1, $A0E1, $A0E4, $A1FF, $B123 |
| zp_snd_alto_seq_idx = $46 ; x-ref: $A081, $A0F0, $A101, $A112, $A213, $A6C0, $B0E0 |
| zp_snd_soprano_seq_idx = $47 ; x-ref: $A12D, $A13D, $A140, $A201, $A5FD, $ADCB, $B154, $B36D |
| zp_snd_noise_seq_idx = $48 ; x-ref: $A14C, $A15C, $A15F, $A203, $A487, $B0CA, $B119 |
| zp_snd_bass_step = $49 ; x-ref: $A0E6, $A0E9, $B125 |
| zp_snd_alto_step = $4a ; x-ref: $A083, $A103, $A106, $A126, $A215, $B0E2 |
| zp_snd_soprano_step = $4b ; x-ref: $A142, $A145, $A5FF, $ADCD, $B156, $B36F |
| zp_snd_noise_step = $4c ; x-ref: $A161, $A164, $A489, $B0CC, $B11B |
| zp_snd_volume_state = $4d ; x-ref: $A068, $A08C, $A1FA, $B10E |
| zp_game_phase = $4e ; x-ref: $A056, $A064, $A06C, $A08E, $A1EE, $B110, $B114 |
| zp_enemy1_spawn_timer = $4f ; x-ref: $A25B, $A6A2, $A6BB |
| zp_enemy2_spawn_timer = $50 ; x-ref: $A260, $A6CC, $A6ED |
| zp_temp_entity_type = $51 ; x-ref: $A84F, $A85A, $A887, $A893 |
| zp_enemy1_mine_timer = $52 ; x-ref: $A265, $A7FA, $A80F |
| zp_enemy3_mine_timer = $53 ; x-ref: $A26A, $A815, $A828 |
| zp_extra_life_awarded = $54 ; x-ref: $A1B5, $AD71, $B147, $B15F |
| zp_difficulty_cap = $55 ; x-ref: $A1DA, $A242, $A6B3, $A6E5 |
| zp_enemy_rot_dir = $56 ; x-ref: $A273, $A27B, $A2E6, $A308 |
| zp_wave_vel_x = $57 ; x-ref: $A282, $A2D1, $A767 |
| zp_wave_vel_y = $5c ; x-ref: $A287, $A2D7, $A752, $A76D |
| zp_wide_boundary_flag = $61 ; x-ref: $A96F, $A97B, $A991, $A9D6, $A9E8, $AA37, $AA59 |
| zp_show_score_table = $62 ; x-ref: $A186, $B1EF, $B435 |
| zp_pos_x = $a3 ; x-ref: $A319, $A54C, $A5B2, $A5D4, $A5E6, $A642, $A667, $A66E, ... |
| zp_pos_y = $a4 ; x-ref: $A31E, $A551, $A5B7, $A5D9, $A5EE, $A647, $A681, $A688, ... |
| zp_ptr_bmp_col_lo = $a5 ; x-ref: $A402, $A413, $A421, $A42B, $A434, $AAC0, $AACA, $AB21, ... |
| zp_ptr_bmp_col_hi = $a6 ; x-ref: $A408, $A42F, $A439, $A43B, $AAC7, $AAD0 |
| zp_ptr_bmp_spill_lo = $a7 ; x-ref: $A404, $A417, $A423, $A454, $A45E, $AACE, $AB2F, $AB3B, ... |
| zp_ptr_bmp_spill_hi = $a8 ; x-ref: $A40C, $A458, $AAD4 |
| zp_ptr_glyph = $a9 ; x-ref: $AB0E, $AB4C, $ABAF |
| zp_ptr_glyph_hi = $aa ; x-ref: $AB9F, $ABA4, $ABA7, $ABAA, $ABB1, $ABB5 |
| zp_spr_row_mask = $ab ; x-ref: $AB1F, $AB24, $AB2B |
| zp_spr_spill_mask = $ac ; x-ref: $AB12, $AB1A, $AB32, $AB39, $AB52, $AB5A, $AB63 |
| zp_spr_bit_offset = $ad ; x-ref: $AAB1, $AB14, $AB54, $AB70, $AB85, $AF85 |
| zp_step_x = $ae ; x-ref: $A0C1, $A5C1, $A606, $AA77, $AA7C, $AA82, $AA8C, $AA95, ... |
| zp_step_y = $af ; x-ref: $A0C3, $A5C6, $A60B, $AA6D, $AA72, $AA97, $AAA1, $AAAA, ... |
| zp_joy_fire = $b0 ; x-ref: $A1F0, $A8D6, $A8E0, $A920, $A934, $A93B, $A947, $A952, ... |
| zp_player_angle = $b1 ; x-ref: $A2FA, $A479, $A8B7, $A8EA, $A8F7, $A8FE, $A913, $ADD2 |
| zp_joy_left = $b2 ; x-ref: $A1F4, $A47B, $A8F4, $A91E, $A937, $A94D |
| zp_pixel_mask = $b3 ; x-ref: $AF8A, $AF91, $AF98, $B28C, $B2AF, $B2DE, $B31B, $B325, ... |
| zp_loop_idx = $b4 ; x-ref: $A53E, $A540, $A55B, $A576, $A57C, $A57E, $A5BC, $A5E4, ... |
| zp_seg_len = $bd ; x-ref: $ABC9, $AC64, $AC93, $AECD, $AEFC, $AF03, $AF2C |
| zp_score_lo = $f7 ; x-ref: $A0A4, $A0AA, $A1AF, $ACB7, $B134, $B136 |
| zp_score_mid = $f8 ; x-ref: $A09C, $A0AE, $A1B1, $B13B, $B13D, $B14B |
| zp_score_hi = $f9 ; x-ref: $A094, $A0B2, $A1B3, $B13F, $B143 |
| SCREEN_MEMORY_PAGE = $0288 ; x-ref: $A015 |
| KEY_REPEAT = $028a ; x-ref: $A18A |
| MODIFIER_KEYS = $028d ; x-ref: $B421 |
| SHIFT_CBM_LOCK = $0291 ; x-ref: $A18F |
| IRQ_VECTOR_LO = $0314 ; x-ref: $A1A3 |
| IRQ_VECTOR_HI = $0315 ; x-ref: $A1A8 |
| entity_types = $033c ; x-ref: $A2A0, $A2AB, $A331, $A50E, $A580, $A707, $A72D, $A851, ... |
| entity_headings = $034f ; x-ref: $A2B5, $A2FC, $A5A9, $A5CB, $A712, $A8F9, $B05E |
| entity_x_coords = $0362 ; x-ref: $A2BB, $A30E, $A316, $A51E, $A524, $A5D1, $A5E8, $A63F, ... |
| entity_x_coord_1 = $0363 ; x-ref: $A313 |
| entity_y_coords = $0375 ; x-ref: $A2C4, $A2DD, $A31B, $A528, $A52E, $A5D6, $A5F0, $A644, ... |
| entity_old_x = $0388 ; x-ref: $A2BE, $A5AF, $A5EB |
| entity_old_y = $0395 ; x-ref: $A2C7, $A5B4, $A5F3 |
| entity_velocity_indices = $03a2 ; x-ref: $A2A3, $A2CD, $A32E, $A466, $A509, $A58C, $A62A, $A65F, ... |
| entity_anim_timers = $03b5 ; x-ref: $A2F2, $A744, $A764, $B04E, $B0EB, $B107 |
| entity_vx = $03c8 ; x-ref: $A2D4, $A33A, $A4A0, $A4A3, $A4BA, $A4CD, $A521, $A5BE, ... |
| BITMAP_COL0 = $1000 ; x-ref: $A429, $A42D, $AAD7 |
| BITMAP_COL1 = $10a0 ; x-ref: $AAD9 |
| BITMAP_COL2 = $1140 ; x-ref: $AADB |
| BITMAP_COL3 = $11e0 ; x-ref: $AADD |
| BITMAP_COL4 = $1280 ; x-ref: $AADF |
| BITMAP_COL5 = $1320 ; x-ref: $AAE1 |
| BITMAP_COL6 = $13c0 ; x-ref: $AAE3 |
| BITMAP_COL7 = $1460 ; x-ref: $AAE5 |
| BITMAP_COL8 = $1500 ; x-ref: $AAE7 |
| BITMAP_COL9 = $15a0 ; x-ref: $AAE9 |
| BITMAP_COL10 = $1640 ; x-ref: $AAEB |
| BITMAP_COL11 = $16e0 ; x-ref: $AAED |
| BITMAP_COL12 = $1780 ; x-ref: $AAEF |
| BITMAP_COL13 = $1820 ; x-ref: $AAF1 |
| BITMAP_COL14 = $18c0 ; x-ref: $AAF3 |
| BITMAP_COL15 = $1960 ; x-ref: $AAF5 |
| BITMAP_COL16 = $1a00 ; x-ref: $AAF7 |
| BITMAP_COL17 = $1aa0 ; x-ref: $AAF9 |
| BITMAP_COL18 = $1b40 ; x-ref: $AAFB |
| BITMAP_COL19 = $1be0 ; x-ref: $AAFD |
| entity_vy = $1d00 ; x-ref: $A2DA, $A33D, $A4AA, $A4AD, $A4D0, $A4E3, $A52B, $A5C3, ... |
| entity_sprite_frames = $1d13 ; x-ref: $A2B2, $A493, $A4B3, $A5C8, $A720, $A85F, $B061 |
| entity_y_center_deltas = $1d26 ; x-ref: $A2E3, $A75E, $A761 |
| entity_y_center_delta_1 = $1d27 ; x-ref: $A305 |
| ai_pursuit_vx = $1d33 ; x-ref: $A799, $AF4F |
| ai_pursuit_vy = $1d40 ; x-ref: $A7B7, $AF5E |
| bullet_vx = $1d4d ; x-ref: $ADD8, $AE66, $AF3B, $AF52 |
| bullet_vy = $1d55 ; x-ref: $ADE9, $AE74, $AF40, $AF61 |
| bullet_lifetimes = $1d5d ; x-ref: $A34C, $ADC3, $ADF8, $AE53, $AE60, $AEB3, $AF4A, $AF6F |
| bullet_x_coords = $1d65 ; x-ref: $A549, $ADE2, $AE6B, $AE70, $AF31, $AF5B |
| bullet_y_coords = $1d6d ; x-ref: $A54E, $ADF3, $AE79, $AE7E, $AF36, $AF6A |
| bullet_owners = $1d75 ; x-ref: $A560, $A56B, $ADFD, $AEAA, $AF74 |
| input_dispatch = $1d7d ; x-ref: $A17B, $A46B |
| input_dispatch_lo = $1d7e ; x-ref: $B3F9, $B409 |
| input_dispatch_hi = $1d7f ; x-ref: $B3FE, $B40E |
| enemy_speed_masks = $1d80 ; x-ref: $A21F, $A512, $A735 |
| enemy_speed_mask_type1 = $1d81 ; x-ref: $A225 |
| enemy_speed_mask_type2 = $1d82 ; x-ref: $A22B |
| enemy_speed_mask_type3 = $1d83 ; x-ref: $A231 |
| enemy_speed_mask_type4 = $1d84 ; x-ref: $A237 |
| enemy_speed_mask_type5 = $1d85 ; x-ref: $A23C |
| enemy_speed_mask_type6 = $1d86 ; x-ref: $A23F |
| SCREEN_RAM_R0C19 = $1e13 ; x-ref: $A400, $A406 |
| COLOR_RAM = $9600 ; x-ref: $A452, $A456 |
| COLOR_RAM_R0C3 = $9603 ; x-ref: $B298 |
| COLOR_RAM_R0C19 = $9613 ; x-ref: $A40A |
| COLOR_RAM_R1C21 = $962b ; x-ref: $B29B |
| COLOR_RAM_R2C16 = $963c ; x-ref: $B1CF |
| COLOR_RAM_R2C19 = $963f ; x-ref: $B29E |
| COLOR_RAM_R4C12 = $9664 ; x-ref: $B1D4 |
| COLOR_RAM_R4C15 = $9667 ; x-ref: $B2A1 |
| KERNAL_INITBAS = $e3a4 ; x-ref: $A01E |
| KERNAL_INITBASVEC = $e45b ; x-ref: $A01B |
| KERNAL_INITHW = $e518 ; x-ref: $A018 |
| KERNAL_INITMEM = $fd8d ; x-ref: $A00A |
| KERNAL_INITVIA = $fdf9 ; x-ref: $A010 |
| KERNAL_CRESTOR = $ff8a ; x-ref: $A00D |
| KERNAL_CSCNKEY = $ff9f ; x-ref: $B3D2 |
| KERNAL_CGETL = $ffe4 ; x-ref: $B3E3 |
|
| ; ENUMS |
| ; Enum: PetsciiShifted |
| PetsciiShifted = { |
| RAW_00: $00, |
| RAW_01: $01, |
| RAW_02: $02, |
| KEY_RUN_STOP: $03, |
| RAW_04: $04, |
| COLOR_WHITE: $05, |
| RAW_06: $06, |
| RAW_07: $07, |
| SHIFT_DISABLE: $08, |
| SHIFT_ENABLE: $09, |
| RAW_0A: $0a, |
| RAW_0B: $0b, |
| RAW_0C: $0c, |
| KEY_RETURN: $0d, |
| LOWER_CASE: $0e, |
| RAW_0F: $0f, |
| RAW_10: $10, |
| KEY_CRSR_DOWN: $11, |
| REVERSE_ON: $12, |
| KEY_HOME: $13, |
| KEY_DELETE: $14, |
| RAW_15: $15, |
| RAW_16: $16, |
| RAW_17: $17, |
| RAW_18: $18, |
| RAW_19: $19, |
| RAW_1A: $1a, |
| RAW_1B: $1b, |
| COLOR_RED: $1c, |
| KEY_CRSR_RIGHT: $1d, |
| COLOR_GREEN: $1e, |
| COLOR_BLUE: $1f, |
| KEY_SPACE: $20, |
| KEY_EXCLAMATION: $21, |
| KEY_QUOTE: $22, |
| KEY_HASH: $23, |
| KEY_DOLLAR: $24, |
| KEY_PERCENT: $25, |
| KEY_AMPERSAND: $26, |
| KEY_APOSTROPHE: $27, |
| KEY_PAREN_LEFT: $28, |
| KEY_PAREN_RIGHT: $29, |
| KEY_ASTERISK: $2a, |
| KEY_PLUS: $2b, |
| KEY_COMMA: $2c, |
| KEY_MINUS: $2d, |
| KEY_PERIOD: $2e, |
| KEY_SLASH: $2f, |
| KEY_0: $30, |
| KEY_1: $31, |
| KEY_2: $32, |
| KEY_3: $33, |
| KEY_4: $34, |
| KEY_5: $35, |
| KEY_6: $36, |
| KEY_7: $37, |
| KEY_8: $38, |
| KEY_9: $39, |
| KEY_COLON: $3a, |
| KEY_SEMICOLON: $3b, |
| KEY_LESS_THAN: $3c, |
| KEY_EQUAL: $3d, |
| KEY_GREATER_THAN: $3e, |
| KEY_QUESTION: $3f, |
| KEY_AT: $40, |
| KEY_a: $41, |
| KEY_b: $42, |
| KEY_c: $43, |
| KEY_d: $44, |
| KEY_e: $45, |
| KEY_f: $46, |
| KEY_g: $47, |
| KEY_h: $48, |
| KEY_i: $49, |
| KEY_j: $4a, |
| KEY_k: $4b, |
| KEY_l: $4c, |
| KEY_m: $4d, |
| KEY_n: $4e, |
| KEY_o: $4f, |
| KEY_p: $50, |
| KEY_q: $51, |
| KEY_r: $52, |
| KEY_s: $53, |
| KEY_t: $54, |
| KEY_u: $55, |
| KEY_v: $56, |
| KEY_w: $57, |
| KEY_x: $58, |
| KEY_y: $59, |
| KEY_z: $5a, |
| KEY_BRACKET_LEFT: $5b, |
| KEY_POUND: $5c, |
| KEY_BRACKET_RIGHT: $5d, |
| KEY_ARROW_UP: $5e, |
| KEY_ARROW_LEFT: $5f, |
| SHIFT_ASTERISK: $60, |
| KEY_A: $61, |
| KEY_B: $62, |
| KEY_C: $63, |
| KEY_D: $64, |
| KEY_E: $65, |
| KEY_F: $66, |
| KEY_G: $67, |
| KEY_H: $68, |
| KEY_I: $69, |
| KEY_J: $6a, |
| KEY_K: $6b, |
| KEY_L: $6c, |
| KEY_M: $6d, |
| KEY_N: $6e, |
| KEY_O: $6f, |
| KEY_P: $70, |
| KEY_Q: $71, |
| KEY_R: $72, |
| KEY_S: $73, |
| KEY_T: $74, |
| KEY_U: $75, |
| KEY_V: $76, |
| KEY_W: $77, |
| KEY_X: $78, |
| KEY_Y: $79, |
| KEY_Z: $7a, |
| SHIFT_PLUS: $7b, |
| CBM_ASTERISK: $7c, |
| SHIFT_MINUS: $7d, |
| SHIFT_ARROW_UP: $7e, |
| CBM_MINUS: $7f, |
| RAW_80: $80, |
| COLOR_ORANGE: $81, |
| RAW_82: $82, |
| RAW_83: $83, |
| RAW_84: $84, |
| KEY_F1: $85, |
| KEY_F3: $86, |
| KEY_F5: $87, |
| KEY_F7: $88, |
| KEY_F2: $89, |
| KEY_F4: $8a, |
| KEY_F6: $8b, |
| KEY_F8: $8c, |
| SHIFT_RETURN: $8d, |
| RAW_8E: $8e, |
| RAW_8F: $8f, |
| COLOR_BLACK: $90, |
| KEY_CRSR_UP: $91, |
| REVERSE_OFF: $92, |
| KEY_CLEAR: $93, |
| KEY_INSERT: $94, |
| COLOR_BROWN: $95, |
| COLOR_LIGHT_RED: $96, |
| COLOR_DARK_GRAY: $97, |
| COLOR_GRAY: $98, |
| COLOR_LIGHT_GREEN: $99, |
| COLOR_LIGHT_BLUE: $9a, |
| COLOR_LIGHT_GRAY: $9b, |
| COLOR_PURPLE: $9c, |
| KEY_CRSR_LEFT: $9d, |
| COLOR_YELLOW: $9e, |
| COLOR_CYAN: $9f, |
| SHIFT_SPACE: $a0, |
| CBM_K: $a1, |
| CBM_I: $a2, |
| CBM_T: $a3, |
| CBM_AT: $a4, |
| CBM_G: $a5, |
| CBM_PLUS: $a6, |
| CBM_M: $a7, |
| CBM_V: $a8, |
| SHIFT_POUND: $a9, |
| CBM_MINUS: $aa, |
| CBM_Q: $ab, |
| CBM_D: $ac, |
| CBM_Z: $ad, |
| CBM_S: $ae, |
| CBM_P: $af, |
| CBM_A: $b0, |
| CBM_E: $b1, |
| CBM_R: $b2, |
| CBM_W: $b3, |
| CBM_H: $b4, |
| CBM_J: $b5, |
| CBM_L: $b6, |
| CBM_Y: $b7, |
| CBM_U: $b8, |
| CBM_O: $b9, |
| SHIFT_AT: $ba, |
| CBM_F: $bb, |
| CBM_C: $bc, |
| CBM_X: $bd, |
| CBM_B: $be, |
| CBM_N: $bf, |
| ALT_SHIFT_ASTERISK: $c0, |
| ALT_KEY_A: $c1, |
| ALT_KEY_B: $c2, |
| ALT_KEY_C: $c3, |
| ALT_KEY_D: $c4, |
| ALT_KEY_E: $c5, |
| ALT_KEY_F: $c6, |
| ALT_KEY_G: $c7, |
| ALT_KEY_H: $c8, |
| ALT_KEY_I: $c9, |
| ALT_KEY_J: $ca, |
| ALT_KEY_K: $cb, |
| ALT_KEY_L: $cc, |
| ALT_KEY_M: $cd, |
| ALT_KEY_N: $ce, |
| ALT_KEY_O: $cf, |
| ALT_KEY_P: $d0, |
| ALT_KEY_Q: $d1, |
| ALT_KEY_R: $d2, |
| ALT_KEY_S: $d3, |
| ALT_KEY_T: $d4, |
| ALT_KEY_U: $d5, |
| ALT_KEY_V: $d6, |
| ALT_KEY_W: $d7, |
| ALT_KEY_X: $d8, |
| ALT_KEY_Y: $d9, |
| ALT_KEY_Z: $da, |
| ALT_SHIFT_PLUS: $db, |
| ALT_CBM_ASTERISK: $dc, |
| ALT_SHIFT_MINUS: $dd, |
| ALT_SHIFT_ARROW_UP: $de, |
| ALT_CBM_MINUS: $df, |
| ALT_SHIFT_SPACE: $e0, |
| ALT_CBM_K: $e1, |
| ALT_CBM_I: $e2, |
| ALT_CBM_T: $e3, |
| ALT_CBM_AT: $e4, |
| ALT_CBM_G: $e5, |
| ALT_CBM_PLUS: $e6, |
| ALT_CBM_M: $e7, |
| ALT_CBM_V: $e8, |
| ALT_SHIFT_POUND: $e9, |
| ALT_CBM_MINUS: $ea, |
| ALT_CBM_Q: $eb, |
| ALT_CBM_D: $ec, |
| ALT_CBM_Z: $ed, |
| ALT_CBM_S: $ee, |
| ALT_CBM_P: $ef, |
| ALT_CBM_A: $f0, |
| ALT_CBM_E: $f1, |
| ALT_CBM_R: $f2, |
| ALT_CBM_W: $f3, |
| ALT_CBM_H: $f4, |
| ALT_CBM_J: $f5, |
| ALT_CBM_L: $f6, |
| ALT_CBM_Y: $f7, |
| ALT_CBM_U: $f8, |
| ALT_CBM_O: $f9, |
| ALT_SHIFT_AT: $fa, |
| ALT_CBM_F: $fb, |
| ALT_CBM_C: $fc, |
| ALT_CBM_X: $fd, |
| ALT_CBM_B: $fe, |
| ALT_CBM_N: $ff |
| } |
| ; Enum: VicColors |
| VicColors = { |
| BLACK: $00, |
| WHITE: $01, |
| RED: $02, |
| CYAN: $03, |
| PURPLE: $04, |
| GREEN: $05, |
| BLUE: $06, |
| YELLOW: $07, |
| ORANGE: $08, |
| LIGHT_ORANGE: $09, |
| PINK: $0a, |
| LIGHT_CYAN: $0b, |
| LIGHT_PURPLE: $0c, |
| LIGHT_GREEN: $0d, |
| LIGHT_BLUE: $0e, |
| LIGHT_YELLOW: $0f |
| } |
|
| $A000 | | .wordcold_start; reset vector |
| $A002 | | .wordignore_nmi; "RESTORE" key vector |
| $A004 | | .byte$41, $30, $c3, $c2, $cd; "A0CBM" |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Cartridge cold-start entry point and main game loop for Omega Race. |
| ; Pointed to by the cold-start vector at $A000. |
| ; |
| ; Phase 1 ($A009-$A025): One-time hardware and game initialization. |
| ; - Clears decimal mode, restores KERNAL I/O vectors, resets the stack |
| ; pointer to $1FF, then calls sA175 to set up the IRQ handler and |
| ; load all game resources. |
| ; |
| ; Phase 2 ($A029-$A0CB): Main game loop. |
| ; - Outer loop (jA029): drives a full game cycle. |
| ; - Inner loop (bA037): per-frame update gated on the IRQ frame counter |
| ; (a22 >= 2) to synchronize with the raster interrupt. |
| ; - Branches on game-state flags (a4E, a4D, a1F, a3D) to handle active |
| ; play, level countdown, player death, and level transitions. |
| ; - Updates the 3-byte high score (a23/a24/a25) if the current score |
| ; beats (aF7/aF8/aF9) before starting the next level. |
| ; |
| ; Inputs: None (entry from KERNAL reset vector) |
| ; Outputs: None |
| ; Side Effects: Resets hardware state; runs all per-frame game subsystems; |
| ; manages level transitions and high-score updates. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A009 | d8 | cold_startcld; clear decimal mode — safe cartridge start ; x-ref: $A000 |
| $A00A | 20 8d fd | jsrKERNAL_INITMEM |
| $A00D | 20 8a ff | jsrKERNAL_CRESTOR; restore default KERNAL I/O vectors |
| $A010 | 20 f9 fd | jsrKERNAL_INITVIA |
| $A013 | a9 1e | lda#$1e |
| $A015 | 8d 88 02 | staSCREEN_MEMORY_PAGE |
| $A018 | 20 18 e5 | jsrKERNAL_INITHW |
| $A01B | 20 5b e4 | jsrKERNAL_INITBASVEC |
| $A01E | 20 a4 e3 | jsrKERNAL_INITBAS |
| $A021 | 78 | sei |
| $A022 | a2 ff | ldx#$ff |
| $A024 | 9a | txs; reset stack pointer to $FF (top of stack) |
| $A025 | 58 | cli |
| $A026 | 20 75 a1 | jsrinit_game_and_hardware; one-time init: IRQ setup, load resources |
| $A029 | 20 c8 b1 | j_A029jsrattract_mode; --- OUTER LOOP: full game cycle --- ; x-ref: $A0CB |
| $A02C | 20 ad a1 | jsrinit_new_game |
| $A02F | 20 be a1 | b_A02Fjsrinit_level; x-ref: $A06E |
| $A032 | a9 0f | j_A032lda#$0f; x-ref: $A07B |
| $A034 | 8d 0e 90 | sta$900e |
| $A037 | 20 6d a3 | b_A037jsrreset_frame_timer; --- INNER LOOP: per-frame update --- ; x-ref: $A062, $A06A, $A090 |
| $A03A | e6 37 | inczp_frame_counter; a37 = frame counter, wraps mod 8 |
| $A03C | a5 37 | ldazp_frame_counter |
| $A03E | 29 07 | and#$07 |
| $A040 | 85 37 | stazp_frame_counter |
| $A042 | e6 3e | inczp_game_tick |
| $A044 | 20 66 a4 | jsrupdate_player_physics; player/bullet physics update |
| $A047 | 20 9c a6 | jsrupdate_enemies; enemy AI / movement update |
| $A04A | 20 07 a5 | jsrapply_enemy_velocities; collision detection |
| $A04D | 20 35 a5 | jsrupdate_display_and_collisions; sprite / display update |
| $A050 | a5 22 | b_A050ldazp_irq_tick_counter; --- FRAME SYNC: spin until 2 IRQ ticks elapsed --- ; x-ref: $A054 |
| $A052 | c9 02 | cmp#$02; wait until a22 >= 2 (2 IRQ ticks = 1 frame) |
| $A054 | 90 fa | bccb_A050; spin-wait for frame gate |
| $A056 | a5 4e | ldazp_game_phase; a4E: game state (0=play, 1=countdown, $C8=new level, neg=game over) |
| $A058 | c9 01 | cmp#$01 |
| $A05A | f0 0c | beqb_A068; a4E==1: life/level countdown active |
| $A05C | a5 1f | ldazp_player_lives; a1F<0: player dead -> game-over path |
| $A05E | 30 32 | bmib_A092 |
| $A060 | a5 3d | ldazp_max_enemy_count; a3D!=0: enemies remain, keep looping |
| $A062 | d0 d3 | bneb_A037 |
| $A064 | a5 4e | ldazp_game_phase; a4E==0: level cleared -> level transition |
| $A066 | f0 16 | beqtrigger_level_transition |
| $A068 | c6 4d | b_A068deczp_snd_volume_state; a4D: life/countdown timer; decrement each pass ; x-ref: $A05A |
| $A06A | d0 cb | bneb_A037; countdown not done, keep looping |
| $A06C | a5 4e | ldazp_game_phase; a4E<0: new-level flag -> restart inner loop |
| $A06E | 30 bf | bmib_A02F |
| $A070 | a5 1f | ldazp_player_lives; a1F<0: game-over path |
| $A072 | 30 1e | bmib_A092 |
| $A074 | a5 3d | ldazp_max_enemy_count; a3D!=0: wave not cleared, keep going |
| $A076 | f0 06 | beqtrigger_level_transition |
| $A078 | 20 d2 a1 | jsrrestart_current_level; display score / wave-complete sequence |
| $A07B | 4c 32 a0 | jmpj_A032 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initiates the level transition delay. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Called when the wave is cleared. Sets up a 200-frame countdown |
| ; timer (a4D) and sets the level-advance flag (a4E to $C8). |
| ; Disables and re-enables IRQs during variable assignment. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| trigger_level_transition |
| $A07E | 78 | sei; disable IRQs for safe update ; x-ref: $A066, $A076 |
| $A07F | a9 26 | lda#$26; set animation/state variables |
| $A081 | 85 46 | stazp_snd_alto_seq_idx |
| $A083 | 85 4a | stazp_snd_alto_step |
| $A085 | a9 05 | lda#$05 |
| $A087 | 85 42 | stazp_snd_alto_dur |
| $A089 | 58 | cli; re-enable IRQs |
| $A08A | a9 c8 | lda#$c8; set 200-frame delay timer ($C8) |
| $A08C | 85 4d | stazp_snd_volume_state; store countdown timer |
| $A08E | 85 4e | stazp_game_phase; Set level-advance phase ($C8) |
| $A090 | d0 a5 | bneb_A037; return to inner loop to wait |
| $A092 | a5 25 | b_A092ldazp_hiscore_hi; --- HIGH SCORE CHECK (3-byte compare, big-endian) --- ; x-ref: $A05E, $A072 |
| $A094 | c5 f9 | cmpzp_score_hi; compare score high byte (a25) vs stored high score (aF9) |
| $A096 | 90 12 | bccb_A0AA |
| $A098 | d0 1c | bneb_A0B6 |
| $A09A | a5 24 | ldazp_hiscore_mid |
| $A09C | c5 f8 | cmpzp_score_mid |
| $A09E | 90 0a | bccb_A0AA |
| $A0A0 | d0 14 | bneb_A0B6 |
| $A0A2 | a5 23 | ldazp_hiscore_lo |
| $A0A4 | c5 f7 | cmpzp_score_lo |
| $A0A6 | 90 02 | bccb_A0AA |
| $A0A8 | d0 0c | bneb_A0B6 |
| $A0AA | a5 f7 | b_A0AAldazp_score_lo; current score > high score: copy to stored record ; x-ref: $A096, $A09E, $A0A6 |
| $A0AC | 85 23 | stazp_hiscore_lo; Update high score from current score |
| $A0AE | a5 f8 | ldazp_score_mid |
| $A0B0 | 85 24 | stazp_hiscore_mid |
| $A0B2 | a5 f9 | ldazp_score_hi |
| $A0B4 | 85 25 | stazp_hiscore_hi |
| $A0B6 | a9 00 | b_A0B6lda#$00; --- LEVEL TRANSITION: reset and start next wave --- ; x-ref: $A098, $A0A0, $A0A8 |
| $A0B8 | 8d 0e 90 | sta$900e |
| $A0BB | a2 94 | ldx#<wave_transition_graphic; X=$94, Y=$BE: next level init parameters |
| $A0BD | a0 be | ldy#>wave_transition_graphic |
| $A0BF | a9 06 | lda#$06 |
| $A0C1 | 85 ae | stazp_step_x |
| $A0C3 | 85 af | stazp_step_y |
| $A0C5 | 20 cc b2 | jsrdraw_graphic_string |
| $A0C8 | 20 bb b3 | jsrdelay_1_second |
| $A0CB | 4c 29 a0 | jmpj_A029; restart outer loop -> next wave begins |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Custom IRQ handler. Increments a frame synchronization counter and processes |
| ; background music and sound effects across 4 channels. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Increments irq_tick_counter (a22); updates VIC sound registers |
| ; ($900A-$900D); acknowledges VIA 2 timer interrupt. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A0CE | 78 | irq_handlersei; x-ref: $A1A1, $A1A6 |
| $A0CF | e6 22 | inczp_irq_tick_counter; Increment frame tick counter |
| $A0D1 | a4 45 | ldyzp_snd_bass_seq_idx |
| $A0D3 | f0 1b | beqb_A0F0 |
| $A0D5 | b9 d3 be | ldasnd_bass_freq_tbl,y |
| $A0D8 | 8d 0a 90 | sta$900a; Update Bass channel frequency |
| $A0DB | f0 13 | beqb_A0F0 |
| $A0DD | c6 41 | deczp_snd_bass_dur |
| $A0DF | d0 0f | bneb_A0F0 |
| $A0E1 | a4 45 | ldyzp_snd_bass_seq_idx |
| $A0E3 | c8 | iny |
| $A0E4 | 84 45 | styzp_snd_bass_seq_idx |
| $A0E6 | a4 49 | ldyzp_snd_bass_step |
| $A0E8 | c8 | iny |
| $A0E9 | 84 49 | styzp_snd_bass_step |
| $A0EB | b9 d5 be | ldasnd_bass_dur_tbl,y |
| $A0EE | 85 41 | stazp_snd_bass_dur |
| $A0F0 | a4 46 | b_A0F0ldyzp_snd_alto_seq_idx; x-ref: $A0D3, $A0DB, $A0DF |
| $A0F2 | f0 1c | beqb_A110 |
| $A0F4 | b9 d7 be | ldasnd_alto_freq_tbl,y |
| $A0F7 | 8d 0b 90 | sta$900b; Update Alto channel frequency |
| $A0FA | f0 14 | beqb_A110 |
| $A0FC | c6 42 | deczp_snd_alto_dur |
| $A0FE | d0 2d | bneb_A12D |
| $A100 | c8 | iny |
| $A101 | 84 46 | styzp_snd_alto_seq_idx |
| $A103 | a4 4a | ldyzp_snd_alto_step |
| $A105 | c8 | iny |
| $A106 | 84 4a | styzp_snd_alto_step |
| $A108 | b9 17 bf | ldasnd_alto_dur_tbl,y |
| $A10B | 85 42 | stazp_snd_alto_dur |
| $A10D | 4c 2d a1 | jmpb_A12D |
| $A110 | a9 01 | b_A110lda#$01; x-ref: $A0F2, $A0FA |
| $A112 | 85 46 | stazp_snd_alto_seq_idx |
| $A114 | a5 2f | ldazp_enemy1_slot_idx |
| $A116 | f0 04 | beqb_A11C |
| $A118 | a0 4a | ldy#$4a |
| $A11A | d0 0a | bneb_A126 |
| $A11C | a5 31 | b_A11Cldazp_enemy2_slot_idx; x-ref: $A116 |
| $A11E | f0 04 | beqb_A124 |
| $A120 | a0 41 | ldy#$41 |
| $A122 | d0 02 | bneb_A126 |
| $A124 | a0 01 | b_A124ldy#$01; x-ref: $A11E |
| $A126 | 84 4a | b_A126styzp_snd_alto_step; x-ref: $A11A, $A122 |
| $A128 | b9 17 bf | ldasnd_alto_dur_tbl,y |
| $A12B | 85 42 | stazp_snd_alto_dur |
| $A12D | a4 47 | b_A12Dldyzp_snd_soprano_seq_idx; x-ref: $A0FE, $A10D |
| $A12F | f0 1b | beqb_A14C |
| $A131 | b9 68 bf | ldasnd_soprano_freq_tbl,y |
| $A134 | 8d 0c 90 | sta$900c; Update Soprano channel frequency |
| $A137 | f0 13 | beqb_A14C |
| $A139 | c6 43 | deczp_snd_soprano_dur |
| $A13B | d0 0f | bneb_A14C |
| $A13D | a4 47 | ldyzp_snd_soprano_seq_idx |
| $A13F | c8 | iny |
| $A140 | 84 47 | styzp_snd_soprano_seq_idx |
| $A142 | a4 4b | ldyzp_snd_soprano_step |
| $A144 | c8 | iny |
| $A145 | 84 4b | styzp_snd_soprano_step |
| $A147 | b9 8d bf | ldasnd_soprano_dur_tbl,y |
| $A14A | 85 43 | stazp_snd_soprano_dur |
| $A14C | a4 48 | b_A14Cldyzp_snd_noise_seq_idx; x-ref: $A12F, $A137, $A13B |
| $A14E | f0 1b | beqb_A16B |
| $A150 | b9 b1 bf | ldasnd_noise_freq_tbl,y |
| $A153 | 8d 0d 90 | sta$900d; Update Noise channel frequency |
| $A156 | f0 13 | beqb_A16B |
| $A158 | c6 44 | deczp_snd_noise_dur |
| $A15A | d0 0f | bneb_A16B |
| $A15C | a4 48 | ldyzp_snd_noise_seq_idx |
| $A15E | c8 | iny |
| $A15F | 84 48 | styzp_snd_noise_seq_idx |
| $A161 | a4 4c | ldyzp_snd_noise_step |
| $A163 | c8 | iny |
| $A164 | 84 4c | styzp_snd_noise_step |
| $A166 | b9 ca bf | ldasnd_noise_dur_tbl,y |
| $A169 | 85 44 | stazp_snd_noise_dur |
| $A16B | 2c 24 91 | b_A16Bbit$9124; Acknowledge VIA 2 Timer 1 interrupt ; x-ref: $A14E, $A156, $A15A |
| $A16E | 68 | pla |
| $A16F | a8 | tay |
| $A170 | 68 | pla |
| $A171 | aa | tax |
| $A172 | 68 | pla |
| $A173 | 58 | cli |
| $A174 | 40 | rti |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes game variables, video hardware, and IRQ handler. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Zeroes scores, initializes VIC registers ($9000-$900F), |
| ; draws the playfield ($A400), and hooks the IRQ vector ($0314) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| init_game_and_hardware |
| $A175 | a9 01 | lda#VicColors.WHITE; init various zero-page variables ; x-ref: $A026 |
| $A177 | 85 27 | stazp_playfield_color |
| $A179 | a9 4c | lda#$4c; $4C = JMP opcode |
| $A17B | 8d 7d 1d | stainput_dispatch |
| $A17E | a9 00 | lda#$00 |
| $A180 | 85 23 | stazp_hiscore_lo; reset high score |
| $A182 | 85 24 | stazp_hiscore_mid |
| $A184 | 85 25 | stazp_hiscore_hi |
| $A186 | 85 62 | stazp_show_score_table |
| $A188 | a9 40 | lda#$40 |
| $A18A | 8d 8a 02 | staKEY_REPEAT |
| $A18D | a9 80 | lda#$80 |
| $A18F | 8d 91 02 | staSHIFT_CBM_LOCK |
| $A192 | a2 0f | ldx#$0f; X = 15 (for 16 VIC registers) |
| $A194 | bd 42 a4 | b_A194ldavic_registers,x; read VIC init values ; x-ref: $A19B |
| $A197 | 9d 00 90 | sta$9000,x; write to VIC chip registers ($9000-$900F) |
| $A19A | ca | dex |
| $A19B | 10 f7 | bplb_A194 |
| $A19D | 20 00 a4 | jsrinit_playfield; draw initial playfield / clear screen |
| $A1A0 | 78 | sei |
| $A1A1 | a9 ce | lda#<irq_handler; setup custom IRQ vector |
| $A1A3 | 8d 14 03 | staIRQ_VECTOR_LO |
| $A1A6 | a9 a0 | lda#>irq_handler |
| $A1A8 | 8d 15 03 | staIRQ_VECTOR_HI |
| $A1AB | 58 | cli |
| $A1AC | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes state for a new game session. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Resets the player score ($F7-$F9), level counter (a20), and |
| ; phase/difficulty counter (a21). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A1AD | a9 00 | init_new_gamelda#$00; reset player score byte 0 ; x-ref: $A02C, $B3C5 |
| $A1AF | 85 f7 | stazp_score_lo; Reset score to 0 |
| $A1B1 | 85 f8 | stazp_score_mid; reset player score byte 1 |
| $A1B3 | 85 f9 | stazp_score_hi; reset player score byte 2 |
| $A1B5 | 85 54 | stazp_extra_life_awarded; Clear extra life flag |
| $A1B7 | 85 20 | stazp_current_level; Reset level counter for new game |
| $A1B9 | a9 01 | lda#$01; set phase/difficulty to 1 |
| $A1BB | 85 21 | stazp_current_phase; Start at phase 1 |
| $A1BD | 60 | init_new_game_rtsrts; x-ref: $B3C8 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the game state for the start of a level/wave. |
| ; |
| ; Inputs: a20 (current level), a21 (current difficulty phase) |
| ; Outputs: None |
| ; Side Effects: Increments level counters, clears hardware sound registers, |
| ; looks up and initializes all enemy properties (types, |
| ; positions, velocities, animation frames) for the current wave, |
| ; and resets the player's position. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A1BE | 78 | init_levelsei; x-ref: $A02F |
| $A1BF | a5 20 | ldazp_current_level |
| $A1C1 | f0 0d | beqb_A1D0; if a20 is a multiple of 4, increment phase |
| $A1C3 | 29 03 | and#$03 |
| $A1C5 | d0 09 | bneb_A1D0 |
| $A1C7 | 20 67 b3 | jsrshow_phase_bonus_screen |
| $A1CA | 78 | sei |
| $A1CB | f8 | sed |
| $A1CC | e6 21 | inczp_current_phase; Advance phase every 4 levels (BCD increment) |
| $A1CE | d8 | cld |
| $A1CF | 58 | cli |
| $A1D0 | e6 20 | b_A1D0inczp_current_level; Advance to next level ; x-ref: $A1C1, $A1C5 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Restarts the current level/wave (e.g., after player death). |
| ; |
| ; Inputs: a20 (current level), a21 (current difficulty phase) |
| ; Outputs: None |
| ; Side Effects: Acts as an alternate entry point to init_level ($A1BE), skipping |
| ; the code that increments the level counters. It re-initializes |
| ; enemy positions and player state for the same wave. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| restart_current_level |
| $A1D2 | a5 21 | ldazp_current_phase; cap phase difficulty at 4 ; x-ref: $A078 |
| $A1D4 | c9 03 | cmp#$03 |
| $A1D6 | 90 02 | bccb_A1DA |
| $A1D8 | a9 04 | lda#$04 |
| $A1DA | 85 55 | b_A1DAstazp_difficulty_cap; x-ref: $A1D6 |
| $A1DC | a5 20 | ldazp_current_level; cap level difficulty at 4 |
| $A1DE | c9 03 | cmp#$03 |
| $A1E0 | 90 02 | bccb_A1E4 |
| $A1E2 | a9 04 | lda#$04 |
| $A1E4 | aa | b_A1E4tax; use level as table index ; x-ref: $A1E0 |
| $A1E5 | bd 73 a3 | ldaenemy_count_tbl,x; load number of enemies for this level |
| $A1E8 | 85 3d | stazp_max_enemy_count |
| $A1EA | 85 40 | stazp_entity_count |
| $A1EC | a9 00 | lda#$00; zero out game state variables |
| $A1EE | 85 4e | stazp_game_phase; Reset game_phase to 'play' |
| $A1F0 | 85 b0 | stazp_joy_fire |
| $A1F2 | 85 35 | stazp_fire_cooldown |
| $A1F4 | 85 b2 | stazp_joy_left |
| $A1F6 | 85 29 | stazp_prev_heading |
| $A1F8 | 85 3e | stazp_game_tick |
| $A1FA | 85 4d | stazp_snd_volume_state |
| $A1FC | 8d 0e 90 | sta$900e |
| $A1FF | 85 45 | stazp_snd_bass_seq_idx |
| $A201 | 85 47 | stazp_snd_soprano_seq_idx |
| $A203 | 85 48 | stazp_snd_noise_seq_idx |
| $A205 | 8d 0a 90 | sta$900a; clear VIC audio registers |
| $A208 | 8d 0b 90 | sta$900b |
| $A20B | 8d 0c 90 | sta$900c |
| $A20E | 8d 0d 90 | sta$900d |
| $A211 | a9 01 | lda#$01 |
| $A213 | 85 46 | stazp_snd_alto_seq_idx |
| $A215 | 85 4a | stazp_snd_alto_step |
| $A217 | a8 | tay |
| $A218 | b9 18 bf | ldasnd_alto_dur_tbl_offset1,y; initialize enemy types array |
| $A21B | 85 42 | stazp_snd_alto_dur |
| $A21D | a9 00 | lda#$00 |
| $A21F | 8d 80 1d | staenemy_speed_masks |
| $A222 | bd 77 a3 | ldawave_config_tbl_1,x |
| $A225 | 8d 81 1d | staenemy_speed_mask_type1 |
| $A228 | bd 7b a3 | ldawave_config_tbl_2,x |
| $A22B | 8d 82 1d | staenemy_speed_mask_type2 |
| $A22E | bd 7f a3 | ldawave_config_tbl_3,x |
| $A231 | 8d 83 1d | staenemy_speed_mask_type3 |
| $A234 | bd 83 a3 | ldawave_config_tbl_4,x |
| $A237 | 8d 84 1d | staenemy_speed_mask_type4 |
| $A23A | a9 ff | lda#$ff |
| $A23C | 8d 85 1d | staenemy_speed_mask_type5 |
| $A23F | 8d 86 1d | staenemy_speed_mask_type6 |
| $A242 | a6 55 | ldxzp_difficulty_cap |
| $A244 | bd 87 a3 | ldawave_config_tbl_5,x; initialize wave difficulty timers |
| $A247 | 85 38 | stazp_enemy1_fire_timer |
| $A249 | bd 8b a3 | ldawave_config_tbl_6,x |
| $A24C | 85 39 | stazp_enemy3_fire_timer |
| $A24E | bd 8f a3 | ldawave_config_tbl_7,x |
| $A251 | 85 3a | stazp_enemy2_fire_timer |
| $A253 | bd 93 a3 | ldawave_config_tbl_8,x |
| $A256 | 85 36 | stazp_enemy_ai_speed_mask |
| $A258 | bd 97 a3 | ldawave_config_tbl_9,x |
| $A25B | 85 4f | stazp_enemy1_spawn_timer |
| $A25D | bd 9b a3 | ldawave_config_tbl_10,x |
| $A260 | 85 50 | stazp_enemy2_spawn_timer |
| $A262 | bd 9f a3 | ldawave_config_tbl_11,x |
| $A265 | 85 52 | stazp_enemy1_mine_timer |
| $A267 | bd a3 a3 | ldawave_config_tbl_12,x |
| $A26A | 85 53 | stazp_enemy3_mine_timer |
| $A26C | ad 24 91 | lda$9124 |
| $A26F | 29 01 | and#$01 |
| $A271 | d0 06 | bneb_A279 |
| $A273 | 85 56 | stazp_enemy_rot_dir |
| $A275 | a0 03 | ldy#$03 |
| $A277 | d0 04 | bneb_A27D |
| $A279 | a0 05 | b_A279ldy#$05; x-ref: $A271 |
| $A27B | 85 56 | stazp_enemy_rot_dir |
| $A27D | a2 03 | b_A27Dldx#$03; x-ref: $A277 |
| $A27F | b9 f6 a3 | b_A27Fldavelocity_deltas_a,y; x-ref: $A28B |
| $A282 | 95 57 | stazp_wave_vel_x,x |
| $A284 | bd fc a3 | ldavelocity_deltas_b,x |
| $A287 | 95 5c | stazp_wave_vel_y,x |
| $A289 | 88 | dey |
| $A28A | ca | dex |
| $A28B | 10 f2 | bplb_A27F |
| $A28D | a5 20 | ldazp_current_level; Check if level >= 2 for extra enemies |
| $A28F | c9 02 | cmp#$02 |
| $A291 | b0 03 | bcsb_A296 |
| $A293 | a2 12 | ldx#$12 |
| $A295 | | .byte$2c; bit opcode |
| $A296 | a6 40 | b_A296ldxzp_entity_count; x-ref: $A291 |
| $A298 | e4 40 | b_A298cpxzp_entity_count; loop over all enemies ; x-ref: $A2F6 |
| $A29A | f0 0c | beqb_A2A8 |
| $A29C | 90 0a | bccb_A2A8 |
| $A29E | a9 ff | lda#$ff |
| $A2A0 | 9d 3c 03 | staentity_types,x |
| $A2A3 | 9d a2 03 | staentity_velocity_indices,x |
| $A2A6 | d0 4d | bneb_A2F5 |
| $A2A8 | bd a8 a3 | b_A2A8ldaenemy_init_sprite_frame_idx,x; setup enemy state arrays from ROM tables ; x-ref: $A29A, $A29C |
| $A2AB | 9d 3c 03 | staentity_types,x |
| $A2AE | a8 | tay |
| $A2AF | b9 2b a8 | ldasprite_frame_start_tbl,y |
| $A2B2 | 9d 13 1d | staentity_sprite_frames,x |
| $A2B5 | 9d 4f 03 | staentity_headings,x; setup enemy X/Y coords |
| $A2B8 | bd b5 a3 | ldaenemy_init_x_coord,x |
| $A2BB | 9d 62 03 | staentity_x_coords,x |
| $A2BE | 9d 88 03 | staentity_old_x,x |
| $A2C1 | bd c2 a3 | ldaenemy_init_y_coord,x |
| $A2C4 | 9d 75 03 | staentity_y_coords,x |
| $A2C7 | 9d 95 03 | staentity_old_y,x |
| $A2CA | bd cf a3 | ldaenemy_init_velocity_idx,x |
| $A2CD | 9d a2 03 | staentity_velocity_indices,x |
| $A2D0 | a8 | tay |
| $A2D1 | b9 57 00 | lda@w zp_wave_vel_x,y; setup enemy X/Y velocities |
| $A2D4 | 9d c8 03 | staentity_vx,x |
| $A2D7 | b9 5c 00 | lda@w zp_wave_vel_y,y |
| $A2DA | 9d 00 1d | staentity_vy,x |
| $A2DD | bd 75 03 | ldaentity_y_coords,x |
| $A2E0 | 38 | sec |
| $A2E1 | e9 64 | sbc#$64 |
| $A2E3 | 9d 26 1d | staentity_y_center_deltas,x |
| $A2E6 | a5 56 | ldazp_enemy_rot_dir |
| $A2E8 | d0 05 | bneb_A2EF |
| $A2EA | bd dc a3 | ldaenemy_init_data_1,x |
| $A2ED | d0 03 | bneb_A2F2 |
| $A2EF | bd e9 a3 | b_A2EFldaenemy_init_data_2,x; x-ref: $A2E8 |
| $A2F2 | 9d b5 03 | b_A2F2staentity_anim_timers,x; x-ref: $A2ED |
| $A2F5 | ca | b_A2F5dex; x-ref: $A2A6 |
| $A2F6 | 10 a0 | bplb_A298 |
| $A2F8 | a9 0c | lda#$0c |
| $A2FA | 85 b1 | stazp_player_angle |
| $A2FC | 8d 4f 03 | staentity_headings |
| $A2FF | a9 01 | lda#$01 |
| $A301 | 85 30 | stazp_enemy3_slot_idx |
| $A303 | a9 14 | lda#$14 |
| $A305 | 8d 27 1d | staentity_y_center_delta_1 |
| $A308 | a5 56 | ldazp_enemy_rot_dir |
| $A30A | d0 0a | bneb_A316 |
| $A30C | a9 8c | lda#$8c |
| $A30E | 8d 62 03 | staentity_x_coords |
| $A311 | a9 14 | lda#$14 |
| $A313 | 8d 63 03 | staentity_x_coord_1 |
| $A316 | ad 62 03 | b_A316ldaentity_x_coords; verify player spawn position is clear ; x-ref: $A30A |
| $A319 | 85 a3 | stazp_pos_x |
| $A31B | ad 75 03 | ldaentity_y_coords |
| $A31E | 85 a4 | stazp_pos_y |
| $A320 | 20 5d a6 | jsrcheck_entity_collision |
| $A323 | 8a | txa |
| $A324 | 30 0e | bmib_A334 |
| $A326 | f0 0c | beqb_A334 |
| $A328 | e0 0d | cpx#$0d |
| $A32A | 90 08 | bccb_A334 |
| $A32C | a9 ff | lda#$ff |
| $A32E | 9d a2 03 | staentity_velocity_indices,x |
| $A331 | 9d 3c 03 | staentity_types,x |
| $A334 | a9 00 | b_A334lda#$00; x-ref: $A324, $A326, $A32A |
| $A336 | 85 31 | stazp_enemy2_slot_idx |
| $A338 | 85 2f | stazp_enemy1_slot_idx |
| $A33A | 8d c8 03 | staentity_vx |
| $A33D | 8d 00 1d | staentity_vy |
| $A340 | a9 ff | lda#$ff |
| $A342 | 85 37 | stazp_frame_counter |
| $A344 | a9 04 | lda#$04 |
| $A346 | 85 19 | stazp_bullet_slots_free |
| $A348 | a9 00 | lda#$00 |
| $A34A | a2 07 | ldx#$07 |
| $A34C | 9d 5d 1d | b_A34Cstabullet_lifetimes,x; x-ref: $A350 |
| $A34F | ca | dex |
| $A350 | 10 fa | bplb_A34C |
| $A352 | 20 29 a4 | jsrclear_char_ram |
| $A355 | 20 52 a4 | jsrfill_color_ram |
| $A358 | 20 04 ac | jsrdraw_arena_border |
| $A35B | 20 ad ac | jsrdraw_player_score |
| $A35E | 20 c2 ac | jsrdraw_high_score |
| $A361 | 20 18 ad | jsrdraw_wave_indicator |
| $A364 | 20 4a ad | jsrdraw_lives_display |
| $A367 | 20 f6 ab | jsrerase_arena_border |
| $A36A | 20 ce ab | jsrdraw_markers |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Resets the IRQ frame tick counter. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Zeroes out a22 (the IRQ tick counter) with interrupts disabled |
| ; to prevent race conditions. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A36D | 78 | reset_frame_timersei; disable IRQs for safe modification ; x-ref: $A037 |
| $A36E | a9 00 | lda#$00; zero out the frame tick counter |
| $A370 | 85 22 | stazp_irq_tick_counter |
| $A372 | 58 | cli; re-enable IRQs |
| $A373 | 60 | enemy_count_tblrts; x-ref: $A1E5 |
| ; Table of number of enemies per level. |
| ; Note that level 0 uses the RTS opcode ($60) at $A373 as a space-saving trick. |
| $A374 | | .byte$06, $08, $0a |
| ; Wave configuration tables. Used to initialize game parameters based on difficulty phase. |
| $A377 | | wave_config_tbl_1.byte$0c, $01, $01, $01; x-ref: $A222 |
| $A37B | | wave_config_tbl_2.byte$00, $03, $01, $01; x-ref: $A228 |
| $A37F | | wave_config_tbl_3.byte$01, $07, $03, $03; x-ref: $A22E |
| $A383 | | wave_config_tbl_4.byte$01, $ff, $0f, $0f; x-ref: $A234 |
| $A387 | | wave_config_tbl_5.byte$07, $fe, $0f, $07; x-ref: $A244 |
| $A38B | | wave_config_tbl_6.byte$03, $1f, $0f, $07; x-ref: $A249 |
| $A38F | | wave_config_tbl_7.byte$07, $ff, $7f, $7f; x-ref: $A24E |
| $A393 | | wave_config_tbl_8.byte$7f, $07, $03, $01; x-ref: $A253 |
| $A397 | | wave_config_tbl_9.byte$00, $c8, $40, $20; x-ref: $A258 |
| $A39B | | wave_config_tbl_10.byte$14, $dc, $14, $14; x-ref: $A25D |
| $A39F | | wave_config_tbl_11.byte$0a, $ff, $ff, $c8; x-ref: $A262 |
| $A3A3 | | wave_config_tbl_12.byte$96, $ff, $ff, $ff, $ff; x-ref: $A267 |
| enemy_init_sprite_frame_idx |
| $A3A8 | | .byte$00, $02; x-ref: $A2A8 |
| $A3AA | | .fill11, $04 |
| $A3B5 | | enemy_init_x_coord.byte$14, $8c, $22, $40, $4c, $4a, $4f, $54; x-ref: $A2B8 |
| $A3BD | | .byte$63, $63, $6d, $70, $40 |
| $A3C2 | | enemy_init_y_coord.byte$28, $5a, $79, $81, $70, $86, $77, $86; x-ref: $A2C1 |
| $A3CA | | .byte$77, $86, $72, $8b, $6e |
| enemy_init_velocity_idx |
| $A3CF | | .byte$03, $01; x-ref: $A2CA |
| $A3D1 | | .fill11, $00 |
| $A3DC | | enemy_init_data_1.byte$00, $32, $0f, $35, $30, $44, $3a, $4e; x-ref: $A2EA |
| $A3E4 | | .byte$4e, $5d, $53, $6f, $22 |
| $A3E9 | | enemy_init_data_2.byte$00, $32, $6b, $55, $38, $50, $3c, $46; x-ref: $A2EF |
| $A3F1 | | .byte$28, $37, $19, $2f, $42 |
| $A3F6 | | velocity_deltas_a.byte$ff, $00, $01, $00, $ff, $00; x-ref: $A27F |
| $A3FC | | velocity_deltas_b.byte$00, $ff, $00, $01; x-ref: $A284 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the playfield by setting up a 20x10 grid of unique characters |
| ; and clearing the character definition area ($1000-$1CFF). |
| ; |
| ; Inputs: a27 (Color value for the playfield) |
| ; Outputs: None |
| ; Side Effects: Modifies Screen and Color RAM; clears RAM from $1000 to $1CFF |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A400 | a9 13 | init_playfieldlda#<SCREEN_RAM_R0C19; Pointer to Screen RAM ($1E13) ; x-ref: $A19D |
| $A402 | 85 a5 | stazp_ptr_bmp_col_lo |
| $A404 | 85 a7 | stazp_ptr_bmp_spill_lo |
| $A406 | a9 1e | lda#>SCREEN_RAM_R0C19 |
| $A408 | 85 a6 | stazp_ptr_bmp_col_hi |
| $A40A | a9 96 | lda#>COLOR_RAM_R0C19; Pointer to Color RAM ($9613) |
| $A40C | 85 a8 | stazp_ptr_bmp_spill_hi |
| $A40E | a2 c7 | ldx#$c7; Init counter for 200 tiles |
| $A410 | a0 b4 | b_A410ldy#$b4; x-ref: $A427 |
| $A412 | 8a | b_A412txa; x-ref: $A41F |
| $A413 | 91 a5 | sta(zp_ptr_bmp_col_lo),y; Store unique char code |
| $A415 | a5 27 | ldazp_playfield_color |
| $A417 | 91 a7 | sta(zp_ptr_bmp_spill_lo),y; Store color |
| $A419 | ca | dex |
| $A41A | 98 | tya |
| $A41B | 38 | sec |
| $A41C | e9 14 | sbc#$14; Move up one row (20 columns) |
| $A41E | a8 | tay |
| $A41F | b0 f1 | bcsb_A412 |
| $A421 | c6 a5 | deczp_ptr_bmp_col_lo |
| $A423 | c6 a7 | deczp_ptr_bmp_spill_lo |
| $A425 | e0 ff | cpx#$ff |
| $A427 | d0 e7 | bneb_A410 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Clears the custom character definition RAM ($1000-$1CFF) by zeroing all |
| ; 3,072 bytes. Called before drawing any new bitmap graphic into the character |
| ; set (title screens, phase bonus, level transitions). |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Zeroes $1000-$1CFF via pointer aA5/aA6 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A429 | a9 00 | clear_char_ramlda#<BITMAP_COL0; x-ref: $A352, $B1C8, $B1F6, $B20E, $B229, $B24C, $B266, $B367 |
| $A42B | 85 a5 | stazp_ptr_bmp_col_lo; set pointer low byte = $00 |
| $A42D | a9 10 | lda#>BITMAP_COL0; set pointer high byte = $10 (start at $1000) |
| $A42F | 85 a6 | stazp_ptr_bmp_col_hi |
| $A431 | a9 00 | lda#$00 |
| $A433 | a8 | tay |
| $A434 | 91 a5 | b_A434sta(zp_ptr_bmp_col_lo),y; write zero to (aA5),Y ; x-ref: $A437, $A43F |
| $A436 | c8 | iny |
| $A437 | d0 fb | bneb_A434 |
| $A439 | e6 a6 | inczp_ptr_bmp_col_hi; advance to next page |
| $A43B | a6 a6 | ldxzp_ptr_bmp_col_hi |
| $A43D | e0 1d | cpx#$1d; stop when high byte reaches $1D (past $1CFF) |
| $A43F | d0 f3 | bneb_A434; Clear up to $1CFF |
| $A441 | 60 | rts |
| $A442 | | vic_registers.byte$07, $1b, $94, $15, $00, $fc; x-ref: $A194 |
| $A448 | | .fill9, $00 |
| $A451 | | .byte$08 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Fills all 200 Color RAM cells ($9600-$96C7) with the value in a27. |
| ; Used to paint a uniform color across the 20x10 playfield character grid. |
| ; |
| ; Inputs: a27 (color value to fill) |
| ; Outputs: None |
| ; Side Effects: Overwrites $9600-$96C7 (Color RAM) via pointer aA7/aA8 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A452 | a9 00 | fill_color_ramlda#<COLOR_RAM; set pointer to Color RAM ($9600) ; x-ref: $A355, $B1F3, $B20B, $B22C, $B489 |
| $A454 | 85 a7 | stazp_ptr_bmp_spill_lo |
| $A456 | a9 96 | lda#>COLOR_RAM |
| $A458 | 85 a8 | stazp_ptr_bmp_spill_hi |
| $A45A | a0 c7 | ldy#$c7; Y = 199 — fill 200 cells |
| $A45C | a5 27 | ldazp_playfield_color; load fill color |
| $A45E | 91 a7 | b_A45Esta(zp_ptr_bmp_spill_lo),y; store color to (aA7),Y ; x-ref: $A463 |
| $A460 | 88 | dey; count down |
| $A461 | c0 ff | cpy#$ff |
| $A463 | d0 f9 | bneb_A45E |
| $A465 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Update player ship velocity, sprite frame, thruster state, and fire button. |
| ; |
| ; Each frame (called from main loop at $A044): |
| ; 1. Bail if player is inactive (f03A2 < 0). |
| ; 2. Read joystick via a1D7D; if fire cooldown (a35) is clear and a bullet |
| ; slot is free (a19 != 0), spawn a projectile via sADB9. |
| ; 3. Look up signed X/Y velocity deltas from 16-entry direction tables |
| ; (fA4E7 / fA4F7) indexed by the current heading (aB1, 0-15). |
| ; Deltas are applied every other frame (a37 odd = skip) for half-rate |
| ; physics accumulation. |
| ; 4. If the fire button (VIA1 $900D bit 7) is pressed, activate thruster: |
| ; set countdown timers a48/a4C=$18 and speed timer a44=$64, and write |
| ; the thrusting sprite frame to f1D13 (aB1 | $10). |
| ; 5. Clamp both X (f03C8) and Y (f1D00) velocities to the range -3..+3 |
| ; ($FD..$03). |
| ; |
| ; Inputs: aB1 = current heading (0-15), f03A2 = player alive flag, |
| ; a35 = fire cooldown, a19 = bullet slots free, |
| ; aB2 = direction flip bit, a900D = VIA1 joystick/fire port |
| ; Outputs: f03C8 = X velocity (clamped -3..+3), |
| ; f1D00 = Y velocity (clamped -3..+3), |
| ; f1D13 = sprite frame register |
| ; Side Effects: May spawn bullet (sADB9); sets thruster timers a44/a48/a4C. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_player_physics |
| $A466 | ad a2 03 | ldaentity_velocity_indices; f03A2 = player alive flag; negative = dead/inactive ; x-ref: $A044 |
| $A469 | 30 7b | bmir_A4E6; player inactive -> skip all updates |
| patch_input_dispatch_hi =*+$02 ; x-ref: $B166 |
| $A46B | 20 7d 1d | jsrinput_dispatch; read joystick, compute velocity delta from heading |
| $A46E | 24 35 | bitzp_fire_cooldown; a35 = fire cooldown; bit N set = cooldown active |
| $A470 | 10 07 | bplb_A479; skip if cooldown active (N set) |
| $A472 | a5 19 | ldazp_bullet_slots_free; a19 = bullet slots free; 0 = none available |
| $A474 | f0 03 | beqb_A479; no bullet slot free -> skip fire |
| $A476 | 20 b9 ad | jsrfire_bullet; spawn bullet: clear cooldown, fire projectile |
| $A479 | a5 b1 | b_A479ldazp_player_angle; aB1 = heading (0-15); aB2 bit 7 = direction flip ; x-ref: $A470, $A474 |
| $A47B | 24 b2 | bitzp_joy_left; aB2 bit 7: direction flip (0=right, 1=left) |
| $A47D | 10 34 | bplb_A4B3; ship not thrusting (aB2 N clear) -> sprite-only path |
| $A47F | 2c 0d 90 | bit$900d; VIA1 $900D bit 7: fire button (0=pressed) |
| $A482 | 30 0c | bmib_A490 |
| $A484 | 78 | sei; --- THRUSTER ACTIVATED: set animation timers --- |
| $A485 | a0 18 | ldy#$18 |
| $A487 | 84 48 | styzp_snd_noise_seq_idx |
| $A489 | 84 4c | styzp_snd_noise_step |
| $A48B | a0 64 | ldy#$64; a44 = speed timer ($64 = 100 frames) |
| $A48D | 84 44 | styzp_snd_noise_dur |
| $A48F | 58 | cli |
| $A490 | a8 | b_A490tay; Y = heading (0-15); set thrusting sprite frame: aB1 | $10 ; x-ref: $A482 |
| $A491 | 09 10 | ora#$10 |
| $A493 | 8d 13 1d | staentity_sprite_frames; write thrusting sprite frame to f1D13 |
| $A496 | a5 37 | ldazp_frame_counter; a37 bit 0: only accumulate velocity on even frames (half-rate) |
| $A498 | 29 01 | and#$01 |
| $A49A | d0 1e | bneb_A4BA; odd frame -> skip velocity accumulation |
| $A49C | 18 | clc |
| $A49D | b9 e7 a4 | ldax_velocity_delta_tbl,y; look up X velocity delta based on heading; X velocity delta table (16 directions) |
| $A4A0 | 6d c8 03 | adcentity_vx; accumulate X velocity |
| $A4A3 | 8d c8 03 | staentity_vx |
| $A4A6 | 18 | clc |
| $A4A7 | b9 f7 a4 | lday_velocity_delta_tbl,y; look up Y velocity delta based on heading; Y velocity delta table (16 directions) |
| $A4AA | 6d 00 1d | adcentity_vy; accumulate Y velocity |
| $A4AD | 8d 00 1d | staentity_vy |
| $A4B0 | 4c ba a4 | jmpb_A4BA |
| $A4B3 | 8d 13 1d | b_A4B3staentity_sprite_frames; ship not thrusting: set sprite frame without thruster ; x-ref: $A47D |
| $A4B6 | a9 01 | lda#$01 |
| $A4B8 | 85 44 | stazp_snd_noise_dur; set speed timer to 1 |
| $A4BA | ad c8 03 | b_A4BAldaentity_vx; --- CLAMP X VELOCITY (-3..+3) --- ; x-ref: $A49A, $A4B0 |
| $A4BD | 30 08 | bmib_A4C7; negative velocity? branch to neg clamp |
| $A4BF | c9 04 | cmp#$04; clamp positive to 3 (if >= 4) |
| $A4C1 | 90 0d | bccb_A4D0 |
| $A4C3 | a9 03 | lda#$03 |
| $A4C5 | d0 06 | bneb_A4CD |
| $A4C7 | c9 fd | b_A4C7cmp#$fd; clamp negative to -3 ($FD) (if < -3) ; x-ref: $A4BD |
| $A4C9 | b0 05 | bcsb_A4D0 |
| $A4CB | a9 fd | lda#$fd |
| $A4CD | 8d c8 03 | b_A4CDstaentity_vx; x-ref: $A4C5 |
| $A4D0 | ad 00 1d | b_A4D0ldaentity_vy; --- CLAMP Y VELOCITY (-3..+3) --- ; x-ref: $A4C1, $A4C9 |
| $A4D3 | 30 08 | bmib_A4DD; negative velocity? branch to neg clamp |
| $A4D5 | c9 04 | cmp#$04; clamp positive to 3 (if >= 4) |
| $A4D7 | 90 0d | bccr_A4E6 |
| $A4D9 | a9 03 | lda#$03 |
| $A4DB | d0 06 | bneb_A4E3 |
| $A4DD | c9 fd | b_A4DDcmp#$fd; clamp negative to -3 ($FD) (if < -3) ; x-ref: $A4D3 |
| $A4DF | b0 05 | bcsr_A4E6 |
| $A4E1 | a9 fd | lda#$fd |
| $A4E3 | 8d 00 1d | b_A4E3staentity_vy; x-ref: $A4DB |
| $A4E6 | 60 | r_A4E6rts; x-ref: $A469, $A4D7, $A4DF |
| $A4E7 | | x_velocity_delta_tbl.byte$02, $01, $01, $01, $00, $ff, $ff, $ff; X velocity delta table (16 directions) ; x-ref: $A49D |
| $A4EF | | .byte$fe, $ff, $ff, $ff, $00, $01, $01, $01 |
| $A4F7 | | y_velocity_delta_tbl.byte$00, $ff, $ff, $ff, $fe, $ff, $ff, $ff; Y velocity delta table (16 directions) ; x-ref: $A4A7 |
| $A4FF | | .byte$00, $01, $01, $01, $02, $01, $01, $01 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Applies velocity to enemy positions. |
| ; |
| ; Inputs: a40 (enemy count), a37 (frame counter), $03C8/$1D00 arrays (velocities) |
| ; Outputs: $0362/$0375 arrays (positions) |
| ; Side Effects: Updates coordinates of active enemies |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| apply_enemy_velocities |
| $A507 | a6 40 | ldxzp_entity_count; X = active enemy index ; x-ref: $A04A |
| $A509 | bd a2 03 | b_A509ldaentity_velocity_indices,x; check if enemy is active ; x-ref: $A532 |
| $A50C | 30 23 | bmib_A531 |
| $A50E | bd 3c 03 | ldaentity_types,x; get enemy type |
| $A511 | a8 | tay |
| $A512 | b9 80 1d | ldaenemy_speed_masks,y; check frame sync for type |
| $A515 | c9 ff | cmp#$ff |
| $A517 | f0 18 | beqb_A531 |
| $A519 | 25 37 | andzp_frame_counter |
| $A51B | d0 14 | bneb_A531 |
| $A51D | 18 | clc; apply X velocity to X position |
| $A51E | bd 62 03 | ldaentity_x_coords,x |
| $A521 | 7d c8 03 | adcentity_vx,x |
| $A524 | 9d 62 03 | staentity_x_coords,x |
| $A527 | 18 | clc; apply Y velocity to Y position |
| $A528 | bd 75 03 | ldaentity_y_coords,x |
| $A52B | 7d 00 1d | adcentity_vy,x |
| $A52E | 9d 75 03 | staentity_y_coords,x |
| $A531 | ca | b_A531dex; loop for all enemies ; x-ref: $A50C, $A517, $A51B |
| $A532 | 10 d5 | bplb_A509 |
| $A534 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates display states and handles all entity collisions. |
| ; |
| ; Inputs: a26 (bullet flags), bullet positions, player position, enemy positions |
| ; Outputs: Collision state (kills enemies or player), sprite display arrays |
| ; Side Effects: Calls collision detection, plays sound effects, removes killed entities |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_display_and_collisions |
| $A535 | 20 47 ae | jsrupdate_bullets; x-ref: $A04D |
| $A538 | a5 26 | ldazp_bullet_hit_mask |
| $A53A | f0 3e | beqb_A57A |
| $A53C | a9 07 | lda#$07; bullet loop from 7 to 0 |
| $A53E | 85 b4 | stazp_loop_idx |
| $A540 | a6 b4 | b_A540ldxzp_loop_idx; x-ref: $A578 |
| $A542 | a5 26 | ldazp_bullet_hit_mask |
| $A544 | 3d 93 ab | andbit_mask_tbl,x; check if bullet is active |
| $A547 | f0 2d | beqb_A576 |
| $A549 | bd 65 1d | ldabullet_x_coords,x; load bullet X |
| $A54C | 85 a3 | stazp_pos_x |
| $A54E | bd 6d 1d | ldabullet_y_coords,x; load bullet Y |
| $A551 | 85 a4 | stazp_pos_y |
| $A553 | 20 5d a6 | jsrcheck_entity_collision; check collision against enemies |
| $A556 | 8a | txa; X=FF if no collision |
| $A557 | c9 ff | cmp#$ff |
| $A559 | f0 1b | beqb_A576 |
| $A55B | a4 b4 | ldyzp_loop_idx |
| $A55D | 8a | txa |
| $A55E | d0 0b | bneb_A56B |
| $A560 | b9 75 1d | ldabullet_owners,y |
| $A563 | f0 15 | beqb_A57A |
| $A565 | 20 b6 b0 | jsrhandle_entity_hit; handle bullet hit enemy |
| $A568 | 4c 7a a5 | jmpb_A57A |
| $A56B | b9 75 1d | b_A56Bldabullet_owners,y; x-ref: $A55E |
| $A56E | d0 0a | bneb_A57A |
| $A570 | 20 b6 b0 | jsrhandle_entity_hit |
| $A573 | 4c 7a a5 | jmpb_A57A |
| $A576 | c6 b4 | b_A576deczp_loop_idx; x-ref: $A547, $A559 |
| $A578 | 10 c6 | bplb_A540 |
| $A57A | a9 12 | b_A57Alda#$12; enemy loop from 18 down to 0 ; x-ref: $A53A, $A563, $A568, $A56E, $A573 |
| $A57C | 85 b4 | stazp_loop_idx |
| $A57E | a4 b4 | j_A57Eldyzp_loop_idx; x-ref: $A627 |
| $A580 | b9 3c 03 | ldaentity_types,y |
| $A583 | 85 2b | stazp_player_wall_hits |
| $A585 | c9 ff | cmp#$ff |
| $A587 | d0 03 | bneb_A58C |
| $A589 | 4c 23 a6 | jmpj_A623 |
| $A58C | b9 a2 03 | b_A58Cldaentity_velocity_indices,y; x-ref: $A587 |
| $A58F | 10 0d | bplb_A59E |
| $A591 | c9 ff | cmp#$ff |
| $A593 | d0 03 | bneb_A598 |
| $A595 | 4c 23 a6 | jmpj_A623 |
| $A598 | 20 cc af | b_A598jsrdraw_enemy; x-ref: $A593 |
| $A59B | 4c 23 a6 | jmpj_A623 |
| $A59E | a5 2b | b_A59Eldazp_player_wall_hits; x-ref: $A58F |
| $A5A0 | c9 05 | cmp#$05 |
| $A5A2 | 90 05 | bccb_A5A9 |
| $A5A4 | 18 | clc |
| $A5A5 | 69 22 | adc#$22 |
| $A5A7 | d0 25 | bneb_A5CE |
| $A5A9 | b9 4f 03 | b_A5A9ldaentity_headings,y; x-ref: $A5A2 |
| $A5AC | 20 9b ab | jsrcalc_sprite_ptr |
| $A5AF | b9 88 03 | ldaentity_old_x,y |
| $A5B2 | 85 a3 | stazp_pos_x |
| $A5B4 | b9 95 03 | ldaentity_old_y,y |
| $A5B7 | 85 a4 | stazp_pos_y |
| $A5B9 | 20 41 ab | jsrerase_sprite |
| $A5BC | a4 b4 | ldyzp_loop_idx |
| $A5BE | b9 c8 03 | ldaentity_vx,y |
| $A5C1 | 85 ae | stazp_step_x |
| $A5C3 | b9 00 1d | ldaentity_vy,y |
| $A5C6 | 85 af | stazp_step_y |
| $A5C8 | b9 13 1d | ldaentity_sprite_frames,y |
| $A5CB | 99 4f 03 | staentity_headings,y |
| $A5CE | 20 9b ab | b_A5CEjsrcalc_sprite_ptr; x-ref: $A5A7 |
| $A5D1 | b9 62 03 | ldaentity_x_coords,y |
| $A5D4 | 85 a3 | stazp_pos_x |
| $A5D6 | b9 75 03 | ldaentity_y_coords,y |
| $A5D9 | 85 a4 | stazp_pos_y |
| $A5DB | 20 05 ab | jsrdraw_sprite_with_collision_check |
| $A5DE | a5 2b | ldazp_player_wall_hits |
| $A5E0 | c9 05 | cmp#$05 |
| $A5E2 | b0 3f | bcsj_A623 |
| $A5E4 | a4 b4 | ldyzp_loop_idx |
| $A5E6 | a5 a3 | ldazp_pos_x |
| $A5E8 | 99 62 03 | staentity_x_coords,y |
| $A5EB | 99 88 03 | staentity_old_x,y |
| $A5EE | a5 a4 | ldazp_pos_y |
| $A5F0 | 99 75 03 | staentity_y_coords,y |
| $A5F3 | 99 95 03 | staentity_old_y,y |
| $A5F6 | a5 18 | ldazp_collision_type |
| $A5F8 | f0 29 | beqj_A623 |
| $A5FA | 78 | sei |
| $A5FB | a9 21 | lda#$21 |
| $A5FD | 85 47 | stazp_snd_soprano_seq_idx |
| $A5FF | 85 4b | stazp_snd_soprano_step |
| $A601 | a9 03 | lda#$03 |
| $A603 | 85 43 | stazp_snd_soprano_dur |
| $A605 | 58 | cli |
| $A606 | a5 ae | ldazp_step_x |
| $A608 | 99 c8 03 | staentity_vx,y |
| $A60B | a5 af | ldazp_step_y |
| $A60D | 99 00 1d | staentity_vy,y |
| $A610 | a5 18 | ldazp_collision_type |
| $A612 | 30 05 | bmib_A619 |
| $A614 | 20 69 ac | jsrdraw_border_segment |
| $A617 | a5 18 | ldazp_collision_type |
| $A619 | 20 77 ac | b_A619jsrerase_border_segment; x-ref: $A612 |
| $A61C | a5 18 | ldazp_collision_type |
| $A61E | 10 03 | bplj_A623 |
| $A620 | 20 69 ac | jsrdraw_border_segment |
| $A623 | c6 b4 | j_A623deczp_loop_idx; x-ref: $A589, $A595, $A59B, $A5E2, $A5F8, $A61E |
| $A625 | 30 03 | bmib_A62A |
| $A627 | 4c 7e a5 | jmpj_A57E |
| $A62A | ad a2 03 | b_A62Aldaentity_velocity_indices; x-ref: $A625 |
| $A62D | 30 2a | bmib_A659 |
| $A62F | ad c8 03 | ldaentity_vx |
| $A632 | d0 07 | bneb_A63B |
| $A634 | ad 00 1d | ldaentity_vy |
| $A637 | d0 02 | bneb_A63B |
| $A639 | f0 04 | beqb_A63F |
| $A63B | a5 1b | b_A63Bldazp_collision_check_flag; x-ref: $A632, $A637 |
| $A63D | f0 1a | beqb_A659 |
| $A63F | ad 62 03 | b_A63Fldaentity_x_coords; load player X ; x-ref: $A639 |
| $A642 | 85 a3 | stazp_pos_x |
| $A644 | ad 75 03 | ldaentity_y_coords; load player Y |
| $A647 | 85 a4 | stazp_pos_y |
| $A649 | 20 5d a6 | jsrcheck_entity_collision; check player collision against enemies |
| $A64C | 8a | txa |
| $A64D | 30 0a | bmib_A659 |
| $A64F | f0 08 | beqb_A659 |
| $A651 | 20 b6 b0 | jsrhandle_entity_hit; handle player hit by enemy |
| $A654 | a2 00 | ldx#$00 |
| $A656 | 20 b6 b0 | jsrhandle_entity_hit |
| $A659 | 20 ce ab | b_A659jsrdraw_markers; x-ref: $A62D, $A63D, $A64D, $A64F |
| $A65C | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Checks whether a given X,Y position collides with any active entity. |
| ; Scans all 19 entity slots ($12 down to $00) using 8x8 pixel bounding-box |
| ; (AABB) collision detection. |
| ; |
| ; Inputs: $A3 = X coordinate to test, $A4 = Y coordinate to test |
| ; Outputs: X = index of colliding entity (0-$12), or $FF if no collision |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| check_entity_collision |
| $A65D | a2 12 | ldx#$12; start from last entity slot ; x-ref: $A320, $A553, $A649 |
| $A65F | bd a2 03 | b_A65Fldaentity_velocity_indices,x; check entity state ; x-ref: $A699 |
| $A662 | 30 34 | bmib_A698; skip if inactive (bit 7 set) |
| $A664 | bd 62 03 | ldaentity_x_coords,x; entity X position |
| $A667 | c5 a3 | cmpzp_pos_x; compare with test X |
| $A669 | b0 09 | bcsb_A674; entity.X >= test.X? check right edge |
| $A66B | 18 | clc |
| $A66C | 69 08 | adc#$08; entity.X + 8 (hitbox width) |
| $A66E | c5 a3 | cmpzp_pos_x; compare with test.X |
| $A670 | b0 0c | bcsb_A67E; overlap on X axis? check Y |
| $A672 | 90 24 | bccb_A698; no X overlap, skip |
| $A674 | a5 a3 | b_A674ldazp_pos_x; test.X ; x-ref: $A669 |
| $A676 | 18 | clc |
| $A677 | 69 08 | adc#$08; test.X + 8 (hitbox width) |
| $A679 | dd 62 03 | cmpentity_x_coords,x; test.X + 8 >= entity.X? overlap |
| $A67C | 90 1a | bccb_A698; no X overlap, skip |
| $A67E | bd 75 03 | b_A67Eldaentity_y_coords,x; entity Y position ; x-ref: $A670 |
| $A681 | c5 a4 | cmpzp_pos_y; compare with test Y |
| $A683 | b0 09 | bcsb_A68E; entity.Y >= test.Y? check bottom edge |
| $A685 | 18 | clc |
| $A686 | 69 08 | adc#$08; entity.Y + 8 (hitbox height) |
| $A688 | c5 a4 | cmpzp_pos_y; compare with test.Y |
| $A68A | b0 0f | bcsr_A69B; overlap on both axes = collision! |
| $A68C | 90 0a | bccb_A698; no Y overlap, skip |
| $A68E | a5 a4 | b_A68Eldazp_pos_y; test.Y ; x-ref: $A683 |
| $A690 | 18 | clc |
| $A691 | 69 08 | adc#$08; test.Y + 8 (hitbox height) |
| $A693 | dd 75 03 | cmpentity_y_coords,x; test.Y + 8 >= entity.Y? overlap |
| $A696 | b0 03 | bcsr_A69B; collision! return with X = entity index |
| $A698 | ca | b_A698dex; next entity ; x-ref: $A662, $A672, $A67C, $A68C |
| $A699 | 10 c4 | bplb_A65F; loop until X wraps to $FF |
| $A69B | 60 | r_A69Brts; return: X = entity index or $FF ; x-ref: $A68A, $A696 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates all enemy states, animations, movement, and spawning. |
| ; Handles spawning of enemy types 1 and 2 based on difficulty timers, |
| ; updates sprite frames for animation, calculates pursuit AI velocities |
| ; towards the player based on distance brackets, and handles enemy firing. |
| ; |
| ; Inputs: a37 (frame counter), a3E (timer), a40 (enemy count) |
| ; player position (f0362, f0375) |
| ; Outputs: Enemy states (zero page and $03xx/$1Dxx arrays) updated |
| ; Side Effects: Spawns new enemies, updates sprite pointers and positions |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A69C | a5 2f | update_enemiesldazp_enemy1_slot_idx; check if enemy 1 is active ; x-ref: $A047 |
| $A69E | d0 4f | bneb_A6EF |
| $A6A0 | a5 3e | ldazp_game_tick; load frame tick timer |
| $A6A2 | c5 4f | cmpzp_enemy1_spawn_timer |
| $A6A4 | d0 20 | bneb_A6C6 |
| $A6A6 | a0 03 | ldy#$03; search for active entity of type 3 |
| $A6A8 | 20 87 a8 | jsrfind_active_entity_by_type |
| $A6AB | 8a | txa |
| $A6AC | f0 18 | beqb_A6C6 |
| $A6AE | a0 01 | ldy#$01 |
| $A6B0 | 20 4f a8 | jsrspawn_entity_init; spawn enemy type 1 |
| $A6B3 | a6 55 | ldxzp_difficulty_cap |
| $A6B5 | bd 3f a8 | ldaspawn_delay_enemy1_tbl,x |
| $A6B8 | 18 | clc |
| $A6B9 | 65 3e | adczp_game_tick |
| $A6BB | 85 4f | stazp_enemy1_spawn_timer |
| $A6BD | 78 | sei; disable IRQs for spawning |
| $A6BE | a9 00 | lda#$00 |
| $A6C0 | 85 46 | stazp_snd_alto_seq_idx |
| $A6C2 | 58 | cli |
| $A6C3 | 4c ef a6 | jmpb_A6EF |
| $A6C6 | a5 31 | b_A6C6ldazp_enemy2_slot_idx; check if enemy 2 is active ; x-ref: $A6A4, $A6AC |
| $A6C8 | d0 25 | bneb_A6EF |
| $A6CA | a5 3e | ldazp_game_tick |
| $A6CC | c5 50 | cmpzp_enemy2_spawn_timer |
| $A6CE | d0 1f | bneb_A6EF |
| $A6D0 | a0 04 | ldy#$04 |
| $A6D2 | 20 87 a8 | jsrfind_active_entity_by_type |
| $A6D5 | 8a | txa |
| $A6D6 | d0 08 | bneb_A6E0 |
| $A6D8 | a0 02 | ldy#$02 |
| $A6DA | 20 87 a8 | jsrfind_active_entity_by_type |
| $A6DD | 8a | txa |
| $A6DE | f0 0f | beqb_A6EF |
| $A6E0 | a0 03 | b_A6E0ldy#$03; x-ref: $A6D6 |
| $A6E2 | 20 4f a8 | jsrspawn_entity_init |
| $A6E5 | a6 55 | ldxzp_difficulty_cap |
| $A6E7 | bd 3b a8 | ldaspawn_delay_enemy2_tbl,x |
| $A6EA | 18 | clc |
| $A6EB | 65 3e | adczp_game_tick |
| $A6ED | 85 50 | stazp_enemy2_spawn_timer |
| $A6EF | a5 30 | b_A6EFldazp_enemy3_slot_idx; check if enemy 3 is active ; x-ref: $A69E, $A6C3, $A6C8, $A6CE, $A6DE |
| $A6F1 | d0 0d | bneb_A700 |
| $A6F3 | a0 04 | ldy#$04 |
| $A6F5 | 20 87 a8 | jsrfind_active_entity_by_type |
| $A6F8 | 8a | txa |
| $A6F9 | f0 05 | beqb_A700 |
| $A6FB | a0 02 | ldy#$02 |
| $A6FD | 20 4f a8 | jsrspawn_entity_init |
| $A700 | a4 40 | b_A700ldyzp_entity_count; Y = active enemy count ; x-ref: $A6F1, $A6F9 |
| $A702 | b9 a2 03 | b_A702ldaentity_velocity_indices,y; get enemy state from array ; x-ref: $A724 |
| $A705 | 30 1c | bmib_A723 |
| $A707 | b9 3c 03 | ldaentity_types,y |
| $A70A | aa | tax |
| $A70B | a5 37 | ldazp_frame_counter |
| $A70D | 3d 35 a8 | andanim_speed_mask_tbl,x |
| $A710 | d0 11 | bneb_A723 |
| $A712 | b9 4f 03 | ldaentity_headings,y |
| $A715 | 18 | clc |
| $A716 | 69 01 | adc#$01 |
| $A718 | dd 30 a8 | cmpsprite_frame_limit_tbl,x |
| $A71B | 90 03 | bccb_A720 |
| $A71D | bd 2b a8 | ldasprite_frame_start_tbl,x |
| $A720 | 99 13 1d | b_A720staentity_sprite_frames,y; store calculated sprite frame ; x-ref: $A71B |
| $A723 | 88 | b_A723dey; x-ref: $A705, $A710 |
| $A724 | d0 dc | bneb_A702 |
| $A726 | a6 40 | ldxzp_entity_count |
| $A728 | bd a2 03 | b_A728ldaentity_velocity_indices,x; x-ref: $A774 |
| $A72B | 30 46 | bmib_A773 |
| $A72D | bd 3c 03 | ldaentity_types,x |
| $A730 | a8 | tay |
| $A731 | c9 01 | cmp#$01 |
| $A733 | f0 3e | beqb_A773 |
| $A735 | b9 80 1d | ldaenemy_speed_masks,y |
| $A738 | c9 ff | cmp#$ff |
| $A73A | f0 37 | beqb_A773 |
| $A73C | 25 37 | andzp_frame_counter |
| $A73E | d0 33 | bneb_A773 |
| $A740 | bd a2 03 | ldaentity_velocity_indices,x |
| $A743 | a8 | tay |
| $A744 | de b5 03 | decentity_anim_timers,x |
| $A747 | d0 1e | bneb_A767 |
| $A749 | c8 | iny |
| $A74A | 98 | tya |
| $A74B | 29 03 | and#$03 |
| $A74D | 9d a2 03 | staentity_velocity_indices,x |
| $A750 | a8 | tay |
| $A751 | 18 | clc |
| $A752 | b9 5c 00 | lda@w zp_wave_vel_y,y |
| $A755 | d0 03 | bneb_A75A |
| $A757 | a9 28 | lda#$28 |
| $A759 | | .byte$2c; bit opcode |
| $A75A | a9 00 | b_A75Alda#$00; x-ref: $A755 |
| $A75C | 69 28 | adc#$28 |
| $A75E | 7d 26 1d | adcentity_y_center_deltas,x |
| $A761 | 7d 26 1d | adcentity_y_center_deltas,x |
| $A764 | 9d b5 03 | staentity_anim_timers,x |
| $A767 | b9 57 00 | b_A767lda@w zp_wave_vel_x,y; x-ref: $A747 |
| $A76A | 9d c8 03 | staentity_vx,x |
| $A76D | b9 5c 00 | lda@w zp_wave_vel_y,y |
| $A770 | 9d 00 1d | staentity_vy,x |
| $A773 | ca | b_A773dex; x-ref: $A72B, $A733, $A73A, $A73E |
| $A774 | d0 b2 | bneb_A728 |
| $A776 | a5 37 | ldazp_frame_counter; load frame counter |
| $A778 | 25 36 | andzp_enemy_ai_speed_mask |
| $A77A | d0 41 | bneb_A7BD |
| $A77C | a4 40 | ldyzp_entity_count |
| $A77E | 38 | b_A77Esec; calculate X distance (enemy - player) ; x-ref: $A7BB |
| $A77F | b9 62 03 | ldaentity_x_coords,y |
| $A782 | ed 62 03 | sbcentity_x_coords |
| $A785 | 90 09 | bccb_A790 |
| $A787 | 20 9b a8 | jsrfind_distance_bracket; find distance bracket |
| $A78A | bd 47 a8 | ldapursuit_neg_velocity_tbl,x |
| $A78D | 4c 99 a7 | jmpj_A799 |
| $A790 | 20 23 aa | b_A790jsrnegate_a; x-ref: $A785 |
| $A793 | 20 9b a8 | jsrfind_distance_bracket |
| $A796 | bd 4b a8 | ldapursuit_pos_velocity_tbl,x |
| $A799 | 99 33 1d | j_A799staai_pursuit_vx,y; x-ref: $A78D |
| $A79C | 38 | sec; calculate Y distance (enemy - player) |
| $A79D | b9 75 03 | ldaentity_y_coords,y |
| $A7A0 | ed 75 03 | sbcentity_y_coords |
| $A7A3 | 90 09 | bccb_A7AE |
| $A7A5 | 20 9b a8 | jsrfind_distance_bracket; find distance bracket |
| $A7A8 | bd 47 a8 | ldapursuit_neg_velocity_tbl,x |
| $A7AB | 4c b7 a7 | jmpj_A7B7 |
| $A7AE | 20 23 aa | b_A7AEjsrnegate_a; x-ref: $A7A3 |
| $A7B1 | 20 9b a8 | jsrfind_distance_bracket |
| $A7B4 | bd 4b a8 | ldapursuit_pos_velocity_tbl,x |
| $A7B7 | 99 40 1d | j_A7B7staai_pursuit_vy,y; x-ref: $A7AB |
| $A7BA | 88 | dey |
| $A7BB | d0 c1 | bneb_A77E |
| $A7BD | a6 2f | b_A7BDldxzp_enemy1_slot_idx; check enemy 1 for firing/sound ; x-ref: $A77A |
| $A7BF | f0 0f | beqb_A7D0 |
| $A7C1 | a5 38 | ldazp_enemy1_fire_timer |
| $A7C3 | c9 ff | cmp#$ff |
| $A7C5 | f0 09 | beqb_A7D0 |
| $A7C7 | 25 3e | andzp_game_tick |
| $A7C9 | d0 05 | bneb_A7D0 |
| $A7CB | 86 3b | stxzp_firing_entity_slot |
| $A7CD | 20 46 af | jsrenemy_fire_bullet |
| $A7D0 | a6 30 | b_A7D0ldxzp_enemy3_slot_idx; x-ref: $A7BF, $A7C5, $A7C9 |
| $A7D2 | f0 0f | beqb_A7E3 |
| $A7D4 | a5 39 | ldazp_enemy3_fire_timer |
| $A7D6 | c9 ff | cmp#$ff |
| $A7D8 | f0 09 | beqb_A7E3 |
| $A7DA | 25 3e | andzp_game_tick |
| $A7DC | d0 05 | bneb_A7E3 |
| $A7DE | 86 3b | stxzp_firing_entity_slot |
| $A7E0 | 20 46 af | jsrenemy_fire_bullet |
| $A7E3 | a6 31 | b_A7E3ldxzp_enemy2_slot_idx; x-ref: $A7D2, $A7D8, $A7DC |
| $A7E5 | f0 0f | beqb_A7F6 |
| $A7E7 | a5 3a | ldazp_enemy2_fire_timer |
| $A7E9 | c9 ff | cmp#$ff |
| $A7EB | f0 09 | beqb_A7F6 |
| $A7ED | 25 3e | andzp_game_tick |
| $A7EF | d0 05 | bneb_A7F6 |
| $A7F1 | 86 3b | stxzp_firing_entity_slot |
| $A7F3 | 20 46 af | jsrenemy_fire_bullet |
| $A7F6 | a6 2f | b_A7F6ldxzp_enemy1_slot_idx; x-ref: $A7E5, $A7EB, $A7EF |
| $A7F8 | f0 17 | beqb_A811 |
| $A7FA | a5 52 | ldazp_enemy1_mine_timer |
| $A7FC | c5 3e | cmpzp_game_tick |
| $A7FE | d0 11 | bneb_A811 |
| $A800 | 86 3b | stxzp_firing_entity_slot |
| $A802 | 20 9d af | jsrspawn_enemy_mine |
| $A805 | 18 | clc |
| $A806 | ad 24 91 | lda$9124 |
| $A809 | 29 7f | and#$7f |
| $A80B | 09 40 | ora#$40 |
| $A80D | 65 3e | adczp_game_tick |
| $A80F | 85 52 | stazp_enemy1_mine_timer |
| $A811 | a6 30 | b_A811ldxzp_enemy3_slot_idx; x-ref: $A7F8, $A7FE |
| $A813 | f0 15 | beqr_A82A |
| $A815 | a5 53 | ldazp_enemy3_mine_timer |
| $A817 | c5 3e | cmpzp_game_tick |
| $A819 | d0 0f | bner_A82A |
| $A81B | 86 3b | stxzp_firing_entity_slot |
| $A81D | 20 9d af | jsrspawn_enemy_mine |
| $A820 | 18 | clc |
| $A821 | ad 24 91 | lda$9124 |
| $A824 | 09 c0 | ora#$c0 |
| $A826 | 65 3e | adczp_game_tick |
| $A828 | 85 53 | stazp_enemy3_mine_timer |
| $A82A | 60 | r_A82Arts; x-ref: $A813, $A819 |
| ; Initial sprite frame per entity type (5 entries, indexed by f033C) |
| sprite_frame_start_tbl |
| $A82B | | .byte$00, $20, $23, $24, $25; x-ref: $A2AF, $A71D, $A85C |
| ; Max sprite frame per entity type; wraps to sprite_frame_start_tbl |
| sprite_frame_limit_tbl |
| $A830 | | .byte$1f, $23, $25, $26, $27; x-ref: $A718 |
| ; ANDed with frame counter to control animation speed per type |
| $A835 | | anim_speed_mask_tbl.byte$00, $00, $01, $01, $03, $00; x-ref: $A70D |
| ; Spawn timer delay for enemy 2, indexed by difficulty (250,240,200,150) |
| spawn_delay_enemy2_tbl |
| $A83B | | .byte$fa, $f0, $c8, $96; x-ref: $A6E7 |
| ; Spawn timer delay for enemy 1, indexed by difficulty (255,245,205,155) |
| spawn_delay_enemy1_tbl |
| $A83F | | .byte$ff, $f5, $cd, $9b; x-ref: $A6B5 |
| ; Distance brackets for enemy AI pursuit (0,40,80,120) |
| distance_threshold_tbl |
| $A843 | | .byte$00, $28, $50, $78; x-ref: $A89D |
| ; Pursuit velocity when enemy is ahead of player (0,-2,-3,-3) |
| pursuit_neg_velocity_tbl |
| $A847 | | .byte$00, $fe, $fd, $fd; x-ref: $A78A, $A7A8 |
| ; Pursuit velocity when enemy is behind player (0,+2,+3,+3) |
| pursuit_pos_velocity_tbl |
| $A84B | | .byte$00, $02, $03, $03; x-ref: $A796, $A7B4 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes entity type, starting sprite frame, and tracking indices. |
| ; For type 1 entities, also initializes directional velocity. |
| ; |
| ; Inputs: Y = Entity type, X = Entity slot index |
| ; Outputs: None |
| ; Side Effects: Modifies entity arrays f033C, f1D13, f03C8, f1D00, and f002E |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A84F | 84 51 | spawn_entity_initstyzp_temp_entity_type; Save requested type ; x-ref: $A6B0, $A6E2, $A6FD |
| $A851 | bd 3c 03 | ldaentity_types,x; Load current type |
| $A854 | a8 | tay |
| $A855 | a9 00 | lda#$00 |
| $A857 | 99 2e 00 | sta@w zp_entity_type_to_slot,y; Clear tracking for old type |
| $A85A | a4 51 | ldyzp_temp_entity_type; Restore requested type |
| $A85C | b9 2b a8 | ldasprite_frame_start_tbl,y; Get start frame for type |
| $A85F | 9d 13 1d | staentity_sprite_frames,x; Set initial sprite frame |
| $A862 | 98 | tya |
| $A863 | 9d 3c 03 | staentity_types,x; Set new entity type |
| $A866 | 8a | txa |
| $A867 | 99 2e 00 | sta@w zp_entity_type_to_slot,y; Store slot index for this type |
| $A86A | c0 01 | cpy#$01; Check if type 1 |
| $A86C | d0 10 | bner_A87E; Skip velocity init if not type 1 |
| $A86E | bd a2 03 | ldaentity_velocity_indices,x; Load direction (0-3) from state |
| $A871 | a8 | tay |
| $A872 | b9 7f a8 | ldaspawn_x_velocity_tbl,y; Load X velocity for direction |
| $A875 | 9d c8 03 | staentity_vx,x; Set X velocity |
| $A878 | b9 83 a8 | ldaspawn_y_velocity_tbl,y; Load Y velocity for direction |
| $A87B | 9d 00 1d | staentity_vy,x; Set Y velocity |
| $A87E | 60 | r_A87Erts; x-ref: $A86C |
| ; Initial X velocity by spawn direction: ↘,↗,↖,↙ |
| $A87F | | spawn_x_velocity_tbl.byte$03, $03, $fd, $fd; x-ref: $A872 |
| ; Initial Y velocity by spawn direction: ↘,↗,↖,↙ |
| $A883 | | spawn_y_velocity_tbl.byte$03, $fd, $fd, $03; x-ref: $A878 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Searches the entity array for an active entity of a given type. |
| ; Scans from index a40 (entity count) down to 1. |
| ; |
| ; Inputs: Y = entity type to search for (1-4) |
| ; Outputs: X = index of matching entity (1-$12), or 0 if not found |
| ; Side Effects: $51 is overwritten with search type |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| find_active_entity_by_type |
| $A887 | 84 51 | styzp_temp_entity_type; save entity type to search for ; x-ref: $A6A8, $A6D2, $A6DA, $A6F5 |
| $A889 | a6 40 | ldxzp_entity_count; start from total entity count |
| $A88B | bd a2 03 | b_A88Bldaentity_velocity_indices,x; check entity state ; x-ref: $A898 |
| $A88E | 30 07 | bmib_A897; skip if inactive (bit 7 set) |
| $A890 | bd 3c 03 | ldaentity_types,x; load entity type |
| $A893 | c5 51 | cmpzp_temp_entity_type; matches requested type? |
| $A895 | f0 03 | beqr_A89A; yes, return with X = entity index |
| $A897 | ca | b_A897dex; next entity ; x-ref: $A88E |
| $A898 | d0 f1 | bneb_A88B; loop until X = 0 (not found) |
| $A89A | 60 | r_A89Arts; return: X = entity index or 0 ; x-ref: $A895 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Determines a distance bracket index (0-3) by comparing the distance value |
| ; in A against a threshold table. Used by enemy AI to select speed. |
| ; |
| ; Inputs: A = Absolute distance (X or Y) |
| ; Outputs: X = Bracket index (0-3) |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| find_distance_bracket |
| $A89B | a2 03 | ldx#$03; Start with highest bracket index (3) ; x-ref: $A787, $A793, $A7A5, $A7B1 |
| $A89D | dd 43 a8 | b_A89Dcmpdistance_threshold_tbl,x; Compare distance with threshold ; x-ref: $A8A3 |
| $A8A0 | b0 03 | bcsr_A8A5; If distance >= threshold, found bracket |
| $A8A2 | ca | dex; Else try next lower bracket |
| $A8A3 | d0 f8 | bneb_A89D; Loop until bracket 0 |
| $A8A5 | 60 | r_A8A5rts; x-ref: $A8A0 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Reads and processes joystick input from VIA hardware registers. |
| ; |
| ; Inputs: None |
| ; Outputs: aB0 (Fire pressed = $80) |
| ; aB1 (Right/Up state + player angle) |
| ; aB2 (Left pressed = $80) |
| ; Side Effects: Disables IRQs to safely read VIA2 Port B (Right direction), |
| ; then reads VIA1 Port A (Up/Down/Left/Fire) with a debounce loop. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A8A6 | 78 | read_joysticksei; x-ref: $B3D5, $B407, $B40C |
| $A8A7 | a2 7f | ldx#$7f |
| $A8A9 | 8e 22 91 | stx$9122; configure VIA2 DDRB |
| $A8AC | ad 20 91 | lda$9120 |
| $A8AF | a2 00 | ldx#$00 |
| $A8B1 | 29 80 | and#$80; read Joy Right (bit 7) |
| $A8B3 | d0 02 | bneb_A8B7 |
| $A8B5 | a2 ff | ldx#$ff |
| $A8B7 | 86 b1 | b_A8B7stxzp_player_angle; x-ref: $A8B3 |
| $A8B9 | a2 ff | ldx#$ff |
| $A8BB | 8e 22 91 | stx$9122 |
| $A8BE | a2 f7 | ldx#$f7 |
| $A8C0 | 8e 20 91 | stx$9120 |
| $A8C3 | 58 | cli |
| $A8C4 | ad 11 91 | b_A8C4lda$9111; read VIA1 Port A (Up/Down/Left/Fire) ; x-ref: $A8CA |
| $A8C7 | cd 11 91 | cmp$9111 |
| $A8CA | d0 f8 | bneb_A8C4; debounce loop |
| $A8CC | 29 3e | and#$3e |
| $A8CE | c9 1f | cmp#$1f; check if Fire (bit 5) is pressed |
| $A8D0 | b0 04 | bcsb_A8D6 |
| $A8D2 | a2 80 | ldx#$80 |
| $A8D4 | d0 0a | bneb_A8E0 |
| $A8D6 | 24 b0 | b_A8D6bitzp_joy_fire; x-ref: $A8D0 |
| $A8D8 | 10 04 | bplb_A8DE |
| $A8DA | a2 80 | ldx#$80 |
| $A8DC | 86 35 | stxzp_fire_cooldown |
| $A8DE | a2 00 | b_A8DEldx#$00; x-ref: $A8D8 |
| $A8E0 | 86 b0 | b_A8E0stxzp_joy_fire; store Fire button state ; x-ref: $A8D4 |
| $A8E2 | 29 1f | and#$1f |
| $A8E4 | c9 0f | cmp#$0f; check if Up (bit 4) is pressed |
| $A8E6 | b0 04 | bcsb_A8EC |
| $A8E8 | a2 01 | ldx#$01 |
| $A8EA | 86 b1 | stxzp_player_angle |
| $A8EC | a2 00 | b_A8ECldx#$00; x-ref: $A8E6 |
| $A8EE | 29 04 | and#$04; check if Left (bit 2) is pressed |
| $A8F0 | d0 02 | bneb_A8F4 |
| $A8F2 | a2 80 | ldx#$80 |
| $A8F4 | 86 b2 | b_A8F4stxzp_joy_left; x-ref: $A8F0 |
| $A8F6 | 18 | clc |
| $A8F7 | a5 b1 | ldazp_player_angle |
| $A8F9 | 6d 4f 03 | adcentity_headings; apply turning offset to player angle |
| $A8FC | 29 0f | and#$0f |
| $A8FE | 85 b1 | stazp_player_angle |
| $A900 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Reads analog paddle and fire button to update player angle and fire state. |
| ; Maps the 0-255 paddle value to a 0-15 angle index using thresholds. |
| ; Checks bit 4 of VIA1 Port A for the fire button. |
| ; |
| ; Inputs: $9008 (Paddle value), $9111 (VIA1 Port A) |
| ; Outputs: aB1 = Player angle (0-15), aB0 = Fire flag ($80 if pressed) |
| ; Side Effects: Updates state variables aB2, a29, a35 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $A901 | a2 10 | read_paddle_inputldx#$10; Start with highest angle index (16) ; x-ref: $B3DC, $B3F7, $B3FC |
| $A903 | ad 08 90 | lda$9008; Read analog paddle value |
| $A906 | dd 59 a9 | b_A906cmppaddle_angle_thresholds,x; Compare with threshold ; x-ref: $A90C |
| $A909 | b0 05 | bcsb_A910; If paddle >= threshold, found angle |
| $A90B | ca | dex; Else try next lower angle |
| $A90C | 10 f8 | bplb_A906 |
| $A90E | 30 05 | bmib_A915 |
| $A910 | 8a | b_A910txa; Use index as angle ; x-ref: $A909 |
| $A911 | 29 0f | and#$0f; Mask to 4 bits (0-15) |
| $A913 | 85 b1 | stazp_player_angle; Store player angle |
| $A915 | ad 11 91 | b_A915lda$9111; Read fire button (VIA1 Port A) ; x-ref: $A90E |
| $A918 | 29 10 | and#$10; Check bit 4 |
| $A91A | f0 1b | beqb_A937; Branch if button pressed (active low) |
| $A91C | a9 00 | lda#$00 |
| $A91E | 85 b2 | stazp_joy_left |
| $A920 | a5 b0 | ldazp_joy_fire |
| $A922 | f0 0a | beqb_A92E |
| $A924 | a5 29 | ldazp_prev_heading |
| $A926 | c5 37 | cmpzp_frame_counter |
| $A928 | f0 04 | beqb_A92E |
| $A92A | a9 80 | lda#$80 |
| $A92C | 85 35 | stazp_fire_cooldown |
| $A92E | a5 37 | b_A92Eldazp_frame_counter; x-ref: $A922, $A928 |
| $A930 | 85 29 | stazp_prev_heading |
| $A932 | a9 00 | lda#$00 |
| $A934 | 85 b0 | stazp_joy_fire |
| $A936 | 60 | rts |
| $A937 | a5 b2 | b_A937ldazp_joy_left; x-ref: $A91A |
| $A939 | 30 14 | bmir_A94F |
| $A93B | a5 b0 | ldazp_joy_fire |
| $A93D | f0 11 | beqb_A950 |
| $A93F | a5 29 | ldazp_prev_heading |
| $A941 | c5 37 | cmpzp_frame_counter |
| $A943 | d0 0a | bner_A94F |
| $A945 | a9 00 | lda#$00 |
| $A947 | 85 b0 | stazp_joy_fire |
| $A949 | a9 80 | lda#$80 |
| $A94B | 85 29 | stazp_prev_heading |
| $A94D | 85 b2 | stazp_joy_left |
| $A94F | 60 | r_A94Frts; x-ref: $A939, $A943 |
| $A950 | a9 80 | b_A950lda#$80; Set fire flag ($80) ; x-ref: $A93D |
| $A952 | 85 b0 | stazp_joy_fire |
| $A954 | a5 37 | ldazp_frame_counter |
| $A956 | 85 29 | stazp_prev_heading |
| $A958 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Analog Paddle to Player Angle Threshold Table |
| ; Because the original arcade game used a rotary controller, the VIC-20 port |
| ; supports the Commodore Paddle. This 17-byte table divides the 0-255 analog |
| ; paddle reading ($9008) into 16 evenly spaced intervals (0-15). The paddle |
| ; routine compares the analog reading against this table from top to bottom |
| ; to determine which of the 16 rotational angles the player's ship should face. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| paddle_angle_thresholds |
| $A959 | | .byte$00, $0f, $1e, $2d, $3c, $4b, $5a, $69; x-ref: $A906 |
| $A961 | | .byte$78, $87, $96, $a5, $b4, $c3, $d2, $e1 |
| $A969 | | .byte$f0 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Applies boundary collisions (outer screen walls and inner central box). |
| ; |
| ; Inputs: aA3, aA4 (X, Y position) |
| ; aAE, aAF (X, Y velocity) |
| ; Outputs: a18 (Collision flag: 0=none, >0 indicates which wall was hit) |
| ; Side Effects: Clamps the X/Y position to keep the entity in bounds. If a wall |
| ; or the central box is hit, the corresponding X or Y velocity |
| ; vector is negated (Two's Complement) to produce a bounce effect. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| check_boundary_collisions |
| $A96A | a9 80 | lda#$80; initialize wall hit flag ; x-ref: $AB7C, $AF7E |
| $A96C | | .byte$2c; bit opcode |
| check_boundary_collisions_narrow |
| $A96D | a9 00 | lda#$00; Set narrow boundary flag ($00) ; x-ref: $AB09, $AB47 |
| $A96F | 85 61 | stazp_wide_boundary_flag; Store in flag |
| $A971 | a9 00 | lda#$00; clear collision flag |
| $A973 | 85 18 | stazp_collision_type |
| $A975 | a5 a3 | ldazp_pos_x |
| $A977 | c9 f8 | cmp#$f8 |
| $A979 | b0 2a | bcsb_A9A5; check left outer screen boundary |
| $A97B | 24 61 | bitzp_wide_boundary_flag; N=1 ($80) -> use wide boundary zones (ship pixel); N=0 ($00) -> narrow (sprites) |
| $A97D | 10 06 | bplb_A985 |
| $A97F | c9 9d | cmp#$9d |
| $A981 | b0 34 | bcsb_A9B7; check right outer screen boundary |
| $A983 | 90 04 | bccb_A989 |
| $A985 | c9 97 | b_A985cmp#$97; x-ref: $A97D |
| $A987 | b0 2e | bcsb_A9B7 |
| $A989 | c9 79 | b_A989cmp#$79; check right side of inner box ; x-ref: $A983 |
| $A98B | b0 43 | bcsb_A9D0 |
| $A98D | c9 75 | cmp#$75 |
| $A98F | b0 38 | bcsb_A9C9 |
| $A991 | 24 61 | bitzp_wide_boundary_flag |
| $A993 | 10 04 | bplb_A999 |
| $A995 | c9 28 | cmp#$28 |
| $A997 | 90 37 | bccb_A9D0 |
| $A999 | c9 20 | b_A999cmp#$20; check left side of inner box ; x-ref: $A993 |
| $A99B | b0 2f | bcsb_A9CC |
| $A99D | c9 01 | cmp#$01 |
| $A99F | b0 2f | bcsb_A9D0 |
| $A9A1 | c9 01 | cmp#$01 |
| $A9A3 | b0 2b | bcsb_A9D0 |
| $A9A5 | a5 a4 | b_A9A5ldazp_pos_y; x-ref: $A979 |
| $A9A7 | a0 07 | ldy#$07 |
| $A9A9 | c9 50 | cmp#$50 |
| $A9AB | b0 01 | bcsb_A9AE |
| $A9AD | c8 | iny |
| $A9AE | 84 18 | b_A9AEstyzp_collision_type; x-ref: $A9AB |
| $A9B0 | a9 02 | lda#$02; clamp X to left edge |
| $A9B2 | 85 a3 | stazp_pos_x |
| $A9B4 | 4c 77 aa | jmpj_AA77; bounce (negate X velocity) |
| $A9B7 | a5 a4 | b_A9B7ldazp_pos_y; x-ref: $A981, $A987 |
| $A9B9 | a0 03 | ldy#$03 |
| $A9BB | c9 50 | cmp#$50 |
| $A9BD | 90 01 | bccb_A9C0 |
| $A9BF | c8 | iny |
| $A9C0 | 84 18 | b_A9C0styzp_collision_type; x-ref: $A9BD |
| $A9C2 | a9 95 | lda#$95; clamp X to right edge |
| $A9C4 | 85 a3 | stazp_pos_x |
| $A9C6 | 4c 77 aa | jmpj_AA77; bounce (negate X velocity) |
| $A9C9 | a9 fe | b_A9C9lda#$fe; x-ref: $A98F |
| $A9CB | | .byte$2c; bit opcode |
| $A9CC | a9 fc | b_A9CClda#$fc; x-ref: $A99B |
| $A9CE | 85 18 | stazp_collision_type |
| $A9D0 | a5 a4 | b_A9D0ldazp_pos_y; x-ref: $A98B, $A997, $A99F, $A9A3 |
| $A9D2 | c9 f8 | cmp#$f8 |
| $A9D4 | b0 22 | bcsb_A9F8; check top outer screen boundary |
| $A9D6 | 24 61 | bitzp_wide_boundary_flag |
| $A9D8 | 10 06 | bplb_A9E0 |
| $A9DA | c9 9d | cmp#$9d |
| $A9DC | b0 33 | bcsb_AA11 |
| $A9DE | 90 04 | bccb_A9E4 |
| $A9E0 | c9 97 | b_A9E0cmp#$97; x-ref: $A9D8 |
| $A9E2 | b0 2d | bcsb_AA11 |
| $A9E4 | c9 65 | b_A9E4cmp#$65; x-ref: $A9DE |
| $A9E6 | b0 22 | bcsb_AA0A |
| $A9E8 | 24 61 | bitzp_wide_boundary_flag |
| $A9EA | 10 04 | bplb_A9F0 |
| $A9EC | c9 3c | cmp#$3c |
| $A9EE | 90 1a | bccb_AA0A |
| $A9F0 | c9 34 | b_A9F0cmp#$34; x-ref: $A9EA |
| $A9F2 | b0 35 | bcsb_AA29 |
| $A9F4 | c9 01 | cmp#$01 |
| $A9F6 | b0 12 | bcsb_AA0A |
| $A9F8 | a5 a3 | b_A9F8ldazp_pos_x; x-ref: $A9D4 |
| $A9FA | a0 01 | ldy#$01 |
| $A9FC | c9 50 | cmp#$50 |
| $A9FE | 90 01 | bccb_AA01 |
| $AA00 | c8 | iny |
| $AA01 | 84 18 | b_AA01styzp_collision_type; x-ref: $A9FE |
| $AA03 | a9 02 | lda#$02; clamp Y to top edge |
| $AA05 | 85 a4 | stazp_pos_y |
| $AA07 | 4c 6d aa | jmpj_AA6D; bounce (negate Y velocity) |
| $AA0A | a9 00 | b_AA0Alda#$00; x-ref: $A9E6, $A9EE, $A9F6, $AA2B |
| $AA0C | 85 18 | stazp_collision_type |
| $AA0E | 4c ac aa | jmpcalc_bitmap_pointers |
| $AA11 | a5 a3 | b_AA11ldazp_pos_x; x-ref: $A9DC, $A9E2 |
| $AA13 | a0 05 | ldy#$05 |
| $AA15 | c9 50 | cmp#$50 |
| $AA17 | b0 01 | bcsb_AA1A |
| $AA19 | c8 | iny |
| $AA1A | 84 18 | b_AA1Astyzp_collision_type; hit bottom wall flag ; x-ref: $AA17 |
| $AA1C | a9 94 | lda#$94; clamp Y to bottom edge |
| $AA1E | 85 a4 | stazp_pos_y |
| $AA20 | 4c 6d aa | jmpj_AA6D; bounce (negate Y velocity) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Negates the accumulator using two's complement (A = -A). |
| ; Used for velocity bouncing and distance sign flipping. |
| ; |
| ; Inputs: A = signed 8-bit value |
| ; Outputs: A = negated value |
| ; Side Effects: Carry flag modified |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AA23 | 49 ff | negate_aeor#$ff; one's complement ; x-ref: $A790, $A7AE, $AA6F, $AA79 |
| $AA25 | 18 | clc |
| $AA26 | 69 01 | adc#$01; +1 = two's complement |
| $AA28 | 60 | rts |
| $AA29 | a5 18 | b_AA29ldazp_collision_type; handle inner box collisions ; x-ref: $A9F2 |
| $AA2B | 10 dd | bplb_AA0A |
| $AA2D | c9 fc | cmp#$fc |
| $AA2F | d0 12 | bneb_AA43 |
| $AA31 | a5 a3 | ldazp_pos_x |
| $AA33 | c9 25 | cmp#$25 |
| $AA35 | b0 18 | bcsb_AA4F |
| $AA37 | 24 61 | bitzp_wide_boundary_flag |
| $AA39 | 10 04 | bplb_AA3F |
| $AA3B | a9 25 | lda#$25 |
| $AA3D | d0 0c | bneb_AA4B |
| $AA3F | a9 20 | b_AA3Flda#$20; x-ref: $AA39 |
| $AA41 | d0 08 | bneb_AA4B |
| $AA43 | a5 a3 | b_AA43ldazp_pos_x; x-ref: $AA2F |
| $AA45 | c9 76 | cmp#$76 |
| $AA47 | 90 06 | bccb_AA4F |
| $AA49 | a9 79 | lda#$79 |
| $AA4B | 85 a3 | b_AA4Bstazp_pos_x; x-ref: $AA3D, $AA41 |
| $AA4D | d0 28 | bnej_AA77 |
| $AA4F | a5 a4 | b_AA4Fldazp_pos_y; x-ref: $AA35, $AA47 |
| $AA51 | c9 50 | cmp#$50 |
| $AA53 | b0 10 | bcsb_AA65 |
| $AA55 | a9 ff | lda#$ff |
| $AA57 | 85 18 | stazp_collision_type |
| $AA59 | 24 61 | bitzp_wide_boundary_flag |
| $AA5B | 10 04 | bplb_AA61 |
| $AA5D | a9 3c | lda#$3c |
| $AA5F | d0 0a | bneb_AA6B |
| $AA61 | a9 34 | b_AA61lda#$34; x-ref: $AA5B |
| $AA63 | d0 06 | bneb_AA6B |
| $AA65 | a9 fd | b_AA65lda#$fd; x-ref: $AA53 |
| $AA67 | 85 18 | stazp_collision_type |
| $AA69 | a9 65 | lda#$65 |
| $AA6B | 85 a4 | b_AA6Bstazp_pos_y; x-ref: $AA5F, $AA63 |
| $AA6D | a5 af | j_AA6Dldazp_step_y; negate Y velocity ; x-ref: $AA07, $AA20 |
| $AA6F | 20 23 aa | jsrnegate_a |
| $AA72 | 85 af | stazp_step_y |
| $AA74 | 4c 7e aa | jmpj_AA7E |
| $AA77 | a5 ae | j_AA77ldazp_step_x; negate X velocity ; x-ref: $A9B4, $A9C6, $AA4D |
| $AA79 | 20 23 aa | jsrnegate_a |
| $AA7C | 85 ae | stazp_step_x |
| $AA7E | a5 2b | j_AA7Eldazp_player_wall_hits; x-ref: $AA74 |
| $AA80 | d0 2a | bnecalc_bitmap_pointers |
| $AA82 | a5 ae | ldazp_step_x |
| $AA84 | f0 11 | beqb_AA97 |
| $AA86 | 30 09 | bmib_AA91 |
| $AA88 | c9 01 | cmp#$01 |
| $AA8A | f0 0b | beqb_AA97 |
| $AA8C | c6 ae | deczp_step_x |
| $AA8E | 4c 97 aa | jmpb_AA97 |
| $AA91 | c9 ff | b_AA91cmp#$ff; x-ref: $AA86 |
| $AA93 | f0 02 | beqb_AA97 |
| $AA95 | e6 ae | inczp_step_x |
| $AA97 | a5 af | b_AA97ldazp_step_y; x-ref: $AA84, $AA8A, $AA8E, $AA93 |
| $AA99 | f0 11 | beqcalc_bitmap_pointers |
| $AA9B | 30 09 | bmib_AAA6 |
| $AA9D | c9 01 | cmp#$01 |
| $AA9F | f0 0b | beqcalc_bitmap_pointers |
| $AAA1 | c6 af | deczp_step_y |
| $AAA3 | 4c ac aa | jmpcalc_bitmap_pointers |
| $AAA6 | c9 ff | b_AAA6cmp#$ff; x-ref: $AA9B |
| $AAA8 | f0 02 | beqcalc_bitmap_pointers |
| $AAAA | e6 af | inczp_step_y |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Calculates memory pointers for drawing to the custom VIC-20 bitmap. |
| ; |
| ; Inputs: aA3 (X coordinate), aA4 (Y coordinate) |
| ; Outputs: aAD (Bit shift offset: X % 8) |
| ; aA5/aA6 (Pointer to the byte containing the target pixel) |
| ; aA7/aA8 (Pointer to the adjacent column, 160 bytes ahead) |
| ; Side Effects: None. Omega Race implements a custom bitmap by arranging the |
| ; VIC-I character map into columns. This routine uses a lookup |
| ; table to find the base address of the column (X / 8), adds the |
| ; Y coordinate, and calculates pointers for rendering. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AAAC | 18 | calc_bitmap_pointersclc; x-ref: $AA0E, $AA80, $AA99, $AA9F, $AAA3, $AAA8, $AAFF, $AB41, ... |
| $AAAD | a5 a3 | ldazp_pos_x; load X coordinate |
| $AAAF | 29 07 | and#$07; extract bit offset (X % 8) |
| $AAB1 | 85 ad | stazp_spr_bit_offset; save bit offset |
| $AAB3 | a5 a3 | ldazp_pos_x |
| $AAB5 | 4a | lsra |
| $AAB6 | 4a | lsra |
| $AAB7 | 29 fe | and#$fe; calculate table index (X / 8) * 2 |
| $AAB9 | aa | tax |
| $AABA | 18 | clc |
| $AABB | bd d7 aa | ldabitmap_column_addresses_lo,x; load column base address low byte |
| $AABE | 65 a4 | adczp_pos_y; add Y coordinate to base address |
| $AAC0 | 85 a5 | stazp_ptr_bmp_col_lo; store pointer low |
| $AAC2 | bd d8 aa | ldabitmap_colum_addresses_hi,x; load column base address high byte |
| $AAC5 | 69 00 | adc#$00; add carry |
| $AAC7 | 85 a6 | stazp_ptr_bmp_col_hi; store pointer high |
| $AAC9 | 18 | clc |
| $AACA | a5 a5 | ldazp_ptr_bmp_col_lo |
| $AACC | 69 a0 | adc#$a0; add 160 (bytes per column) to low byte |
| $AACE | 85 a7 | stazp_ptr_bmp_spill_lo; store adjacent column pointer low |
| $AAD0 | a5 a6 | ldazp_ptr_bmp_col_hi |
| $AAD2 | 69 00 | adc#$00 |
| $AAD4 | 85 a8 | stazp_ptr_bmp_spill_hi; store adjacent column pointer high |
| $AAD6 | 60 | rts |
| bitmap_colum_addresses_hi =*+$01 ; x-ref: $AAC2 |
| bitmap_column_addresses_lo |
| $AAD7 | | .wordBITMAP_COL0, BITMAP_COL1, BITMAP_COL2, BITMAP_COL3, BITMAP_COL4; x-ref: $AABB |
| $AAE1 | | .wordBITMAP_COL5, BITMAP_COL6, BITMAP_COL7, BITMAP_COL8, BITMAP_COL9 |
| $AAEB | | .wordBITMAP_COL10, BITMAP_COL11, BITMAP_COL12, BITMAP_COL13, BITMAP_COL14 |
| $AAF5 | | .wordBITMAP_COL15, BITMAP_COL16, BITMAP_COL17, BITMAP_COL18, BITMAP_COL19 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Stamps an 8x8 sprite/glyph shape onto the custom bitmap using OR, and |
| ; accumulates pixel-overlap collision data into collision_check_flag. |
| ; The glyph shape (8 bytes) is read from (pA9),Y for rows Y=7..0. Each row |
| ; byte is right-shifted by aAD bits, producing a high-column mask (in A) and |
| ; a spill-column mask (in aAC). Both are OR-ed into the bitmap columns at |
| ; (aA5),Y and (aA7),Y. Before OR-ing, the old bitmap byte is AND-ed with the |
| ; new mask: any non-zero result means pixels were already set -> collision, |
| ; accumulated into collision_check_flag. |
| ; Does NOT clear collision_check_flag or run boundary checks on entry. |
| ; See draw_sprite_with_collision_check ($AB05) for the full-entry variant. |
| ; |
| ; Inputs: pA9/aAA = pointer to 8-byte glyph shape |
| ; aA5/aA6 = pointer to high bitmap column |
| ; aA7/aA8 = pointer to adjacent (spill) bitmap column |
| ; aAD = right-shift count (0..7, X sub-byte pixel offset) |
| ; collision_check_flag = running accumulator (caller-managed) |
| ; Outputs: Bitmap updated (sprite pixels OR-ed in) |
| ; collision_check_flag |= (old_bitmap AND sprite_mask) |
| ; Side Effects: Overwrites aAB, aAC (temporary shift registers) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| draw_sprite_or_collision |
| $AAFF | 20 ac aa | jsrcalc_bitmap_pointers; x-ref: $AD42, $AD8B, $ADA3, $B2FC, $B358, $B388, $B3A2 |
| $AB02 | 4c 0c ab | jmpj_AB0C |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Full-entry variant of draw_sprite_or_collision. Before stamping the sprite: |
| ; 1. Clears collision_check_flag to $00 (fresh collision test). |
| ; 2. Calls sA96D to check X-axis boundary collisions vs the playfield walls; |
| ; sA96D may clamp aA3 and set collision_type if a wall is hit. |
| ; Then falls through into the shared draw loop at jAB0C. |
| ; Use this entry when rendering a moving entity that needs both pixel-collision |
| ; detection (vs other sprites) and wall-boundary clamping. |
| ; |
| ; Inputs: aA3 = X coordinate, aA4 = Y coordinate |
| ; pA9/aAA = pointer to 8-byte glyph shape |
| ; aAD = right-shift count (0..7) |
| ; Outputs: Bitmap updated; collision_check_flag set if any overlap detected |
| ; collision_type set if a wall boundary was hit (via sA96D) |
| ; Side Effects: Clears then rebuilds collision_check_flag; may modify aA3 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| draw_sprite_with_collision_check |
| $AB05 | a9 00 | lda#$00; x-ref: $A5DB, $B00E, $B045 |
| $AB07 | 85 1b | stazp_collision_check_flag |
| $AB09 | 20 6d a9 | jsrcheck_boundary_collisions_narrow |
| $AB0C | a0 07 | j_AB0Cldy#$07; x-ref: $AB02 |
| $AB0E | b1 a9 | b_AB0Elda(zp_ptr_glyph),y; x-ref: $AB3E |
| $AB10 | a2 00 | ldx#$00 |
| $AB12 | 86 ac | stxzp_spr_spill_mask |
| $AB14 | a6 ad | ldxzp_spr_bit_offset |
| $AB16 | f0 07 | beqb_AB1F |
| $AB18 | 18 | b_AB18clc; x-ref: $AB1D |
| $AB19 | 4a | lsra |
| $AB1A | 66 ac | rorzp_spr_spill_mask |
| $AB1C | ca | dex |
| $AB1D | d0 f9 | bneb_AB18 |
| $AB1F | 85 ab | b_AB1Fstazp_spr_row_mask; x-ref: $AB16 |
| $AB21 | b1 a5 | lda(zp_ptr_bmp_col_lo),y |
| $AB23 | aa | tax |
| $AB24 | 25 ab | andzp_spr_row_mask |
| $AB26 | 05 1b | orazp_collision_check_flag |
| $AB28 | 85 1b | stazp_collision_check_flag |
| $AB2A | 8a | txa |
| $AB2B | 05 ab | orazp_spr_row_mask |
| $AB2D | 91 a5 | sta(zp_ptr_bmp_col_lo),y |
| $AB2F | b1 a7 | lda(zp_ptr_bmp_spill_lo),y |
| $AB31 | aa | tax |
| $AB32 | 25 ac | andzp_spr_spill_mask |
| $AB34 | 05 1b | orazp_collision_check_flag |
| $AB36 | 85 1b | stazp_collision_check_flag |
| $AB38 | 8a | txa |
| $AB39 | 05 ac | orazp_spr_spill_mask |
| $AB3B | 91 a7 | sta(zp_ptr_bmp_spill_lo),y |
| $AB3D | 88 | dey |
| $AB3E | 10 ce | bplb_AB0E |
| $AB40 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Erases an 8x8 sprite/glyph from the custom bitmap using AND-NOT masking. |
| ; The glyph shape (8 bytes) is read from (pA9),Y for rows Y=7..0. Each row |
| ; byte is inverted (EOR #$FF) to form a clear-mask (0=erase this pixel, |
| ; 1=leave alone), then right-shifted by aAD bits using SEC/ROR so that 1-bits |
| ; fill in from the left, preserving non-sprite pixels in the shift region. |
| ; The shifted masks are AND-ed into bitmap columns (aA5),Y and (aA7),Y, |
| ; clearing only the pixels that belong to this sprite without disturbing |
| ; any other content already on the bitmap. |
| ; Does NOT modify collision_check_flag. |
| ; See erase_sprite_with_boundary_check ($AB47) for the boundary variant. |
| ; |
| ; Inputs: pA9/aAA = pointer to 8-byte glyph shape |
| ; aA5/aA6 = pointer to high bitmap column |
| ; aA7/aA8 = pointer to adjacent (spill) bitmap column |
| ; aAD = right-shift count (0..7) |
| ; Outputs: Bitmap updated (sprite pixels cleared) |
| ; Side Effects: Overwrites aAC (temporary shift register) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AB41 | 20 ac aa | erase_spritejsrcalc_bitmap_pointers; x-ref: $A5B9, $AD5F, $ADB5, $B346 |
| $AB44 | 4c 4a ab | jmpj_AB4A |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Boundary-checking variant of erase_sprite. Before erasing, calls sA96D to |
| ; check X-axis boundary collisions vs the playfield walls; sA96D may clamp |
| ; aA3 and set collision_type if a wall is hit. Then falls through into the |
| ; shared erase loop at jAB4A. |
| ; Use this entry when erasing a moving entity whose position may be at or |
| ; beyond a screen boundary at the time of the erase. |
| ; |
| ; Inputs: aA3 = X coordinate, aA4 = Y coordinate |
| ; pA9/aAA = pointer to 8-byte glyph shape |
| ; aAD = right-shift count (0..7) |
| ; Outputs: Bitmap updated (sprite pixels cleared) |
| ; collision_type set if a wall boundary was hit (via sA96D) |
| ; Side Effects: May modify aA3 (clamped by sA96D); overwrites aAC |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| erase_sprite_with_boundary_check |
| $AB47 | 20 6d a9 | jsrcheck_boundary_collisions_narrow; x-ref: $B199, $B1C0 |
| $AB4A | a0 07 | j_AB4Aldy#$07; x-ref: $AB44 |
| $AB4C | b1 a9 | b_AB4Clda(zp_ptr_glyph),y; x-ref: $AB6A |
| $AB4E | 49 ff | eor#$ff |
| $AB50 | a2 ff | ldx#$ff |
| $AB52 | 86 ac | stxzp_spr_spill_mask |
| $AB54 | a6 ad | ldxzp_spr_bit_offset |
| $AB56 | f0 07 | beqb_AB5F |
| $AB58 | 38 | b_AB58sec; x-ref: $AB5D |
| $AB59 | 6a | rora |
| $AB5A | 66 ac | rorzp_spr_spill_mask |
| $AB5C | ca | dex |
| $AB5D | d0 f9 | bneb_AB58 |
| $AB5F | 31 a5 | b_AB5Fand(zp_ptr_bmp_col_lo),y; x-ref: $AB56 |
| $AB61 | 91 a5 | sta(zp_ptr_bmp_col_lo),y |
| $AB63 | a5 ac | ldazp_spr_spill_mask |
| $AB65 | 31 a7 | and(zp_ptr_bmp_spill_lo),y |
| $AB67 | 91 a7 | sta(zp_ptr_bmp_spill_lo),y |
| $AB69 | 88 | dey |
| $AB6A | 10 e0 | bplb_AB4C |
| $AB6C | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Sets a pixel in the custom bitmap at position (aA3, aA4). |
| ; |
| ; Inputs: aA3 = X coordinate, aA4 = Y coordinate |
| ; Outputs: Pixel set in bitmap memory |
| ; Side Effects: Modifies bitmap memory via (aA5) pointer |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AB6D | 20 ac aa | plot_pixeljsrcalc_bitmap_pointers; compute bitmap pointer for (aA3,aA4) ; x-ref: $ABB8, $ABDE |
| $AB70 | a6 ad | ldxzp_spr_bit_offset; bit offset (X % 8) |
| $AB72 | bd 93 ab | ldabit_mask_tbl,x; load bit mask for target pixel |
| $AB75 | a2 00 | ldx#$00 |
| $AB77 | 01 a5 | ora(zp_ptr_bmp_col_lo,x); OR pixel into bitmap byte |
| $AB79 | 81 a5 | sta(zp_ptr_bmp_col_lo,x); write back |
| $AB7B | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Clears a pixel after applying boundary collision checks. |
| ; Bounces velocity if a wall is hit, then clears the pixel. |
| ; |
| ; Inputs: aA3/aA4 = position, aAE/aAF = X/Y velocity |
| ; Outputs: Pixel cleared, position clamped, velocity bounced |
| ; Side Effects: Modifies bitmap memory, may negate velocity |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| clear_pixel_with_bounce |
| $AB7C | 20 6a a9 | jsrcheck_boundary_collisions; clamp position, bounce velocity ; x-ref: $AF05 |
| $AB7F | 4c 85 ab | jmpj_AB85 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Clears a pixel in the custom bitmap at position (aA3, aA4). |
| ; |
| ; Inputs: aA3 = X coordinate, aA4 = Y coordinate |
| ; Outputs: Pixel cleared in bitmap memory |
| ; Side Effects: Modifies bitmap memory via (aA5) pointer |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AB82 | 20 ac aa | clear_pixeljsrcalc_bitmap_pointers; x-ref: $AC53 |
| $AB85 | a6 ad | j_AB85ldxzp_spr_bit_offset; bit offset (X % 8) ; x-ref: $AB7F |
| $AB87 | bd 93 ab | ldabit_mask_tbl,x; load bit mask for target pixel |
| $AB8A | a2 00 | ldx#$00 |
| $AB8C | 49 ff | eor#$ff; invert mask |
| $AB8E | 21 a5 | and(zp_ptr_bmp_col_lo,x); AND to clear pixel |
| $AB90 | 81 a5 | sta(zp_ptr_bmp_col_lo,x); write back |
| $AB92 | 60 | rts |
| ; Bit mask lookup: index 0=$80, 1=$40, 2=$20 ... 7=$01 |
| $AB93 | | bit_mask_tbl.byte$80, $40, $20, $10, $08, $04, $02, $01; x-ref: $A544, $AB72, $AB87, $AE99, $AF87 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Converts a sprite/glyph frame index (in A) into a 16-bit pointer to the |
| ; corresponding 8x8 pixel shape in the ROM glyph table at $B496, and stores |
| ; the result in the Zero Page pointer pA9/aAA for use by the draw routine. |
| ; |
| ; Formula: pointer = $B496 + (A * 8) |
| ; |
| ; The index is multiplied by 8 (3 ASL+ROL pairs to propagate carry into the |
| ; high byte), then the base address $B496 is added. Always called immediately |
| ; before sAAFF, which reads (pA9),Y to stamp the 8 bytes into the bitmap. |
| ; |
| ; Inputs: A = sprite/glyph frame index (0-based) |
| ; Outputs: pA9/aAA = 16-bit pointer to the 8-byte shape in ROM |
| ; Side Effects: Overwrites a2A (temp copy of index) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AB9B | 85 2a | calc_sprite_ptrstazp_temp_frame_idx; save frame index; A = sprite/glyph frame index ; x-ref: $A5AC, $A5CE, $AD3F, $AD50, $AD6E, $ADA0, $ADB2, $B00B, ... |
| $AB9D | a9 00 | lda#$00; clear high byte of 16-bit product |
| $AB9F | 85 aa | stazp_ptr_glyph_hi |
| $ABA1 | a5 2a | ldazp_temp_frame_idx; A *= 2 (shift 1) |
| $ABA3 | 0a | asla |
| $ABA4 | 26 aa | rolzp_ptr_glyph_hi; A *= 4 (shift 2) |
| $ABA6 | 0a | asla |
| $ABA7 | 26 aa | rolzp_ptr_glyph_hi; A *= 8 (shift 3) — final byte offset = index * 8 |
| $ABA9 | 0a | asla |
| $ABAA | 26 aa | rolzp_ptr_glyph_hi |
| $ABAC | 18 | clc |
| $ABAD | 69 96 | adc#$96; store pointer low into pA9 |
| $ABAF | 85 a9 | stazp_ptr_glyph; load high byte of product |
| $ABB1 | a5 aa | ldazp_ptr_glyph_hi; add glyph table base high byte ($B4) + carry |
| $ABB3 | 69 b4 | adc#$b4; store pointer high into aAA; pA9/aAA now points to glyph shape |
| $ABB5 | 85 aa | stazp_ptr_glyph_hi |
| $ABB7 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws a line segment by plotting pixels and stepping by dx, dy. |
| ; Loops until the length counter reaches zero. |
| ; |
| ; Inputs: aA3/aA4 = Start X/Y, aAE/aAF = dx/dy, aBD = length |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ABB8 | 20 6d ab | draw_line_segmentjsrplot_pixel; x-ref: $ABCB, $AC73 |
| $ABBB | 18 | clc |
| $ABBC | a5 a3 | ldazp_pos_x |
| $ABBE | 65 ae | adczp_step_x |
| $ABC0 | 85 a3 | stazp_pos_x |
| $ABC2 | 18 | clc |
| $ABC3 | a5 a4 | ldazp_pos_y |
| $ABC5 | 65 af | adczp_step_y |
| $ABC7 | 85 a4 | stazp_pos_y |
| $ABC9 | c6 bd | deczp_seg_len |
| $ABCB | d0 eb | bnedraw_line_segment |
| $ABCD | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Plots 8 pixels at the corners and midpoints of the playfield area to act |
| ; as visual markers. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies character bitmap by setting 8 specific pixels. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ABCE | a0 07 | draw_markersldy#$07; Init loop counter for 8 dots ; x-ref: $A36A, $A659, $B22F, $B24F, $B269 |
| $ABD0 | 84 1a | styzp_marker_idx |
| $ABD2 | a4 1a | b_ABD2ldyzp_marker_idx; x-ref: $ABE3 |
| $ABD4 | b9 e6 ab | ldamarker_x_coords,y; Load X coordinate |
| $ABD7 | 85 a3 | stazp_pos_x |
| $ABD9 | b9 ee ab | ldamarker_y_coords,y; Load Y coordinate |
| $ABDC | 85 a4 | stazp_pos_y |
| $ABDE | 20 6d ab | jsrplot_pixel; Plot pixel |
| $ABE1 | c6 1a | deczp_marker_idx |
| $ABE3 | 10 ed | bplb_ABD2 |
| $ABE5 | 60 | rts |
| $ABE6 | | marker_x_coords.byte$00, $50, $9f, $00, $9f, $00, $50, $9f; x-ref: $ABD4 |
| $ABEE | | marker_y_coords.byte$00, $00, $00, $50, $50, $9f, $9f, $9f; x-ref: $ABD9 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Erases the arena border from the bitmap. Mirror of draw_arena_border — iterates |
| ; through 8 line segments, clearing pixels using erase_border_segment (sAC77). |
| ; Called during level init before the border is redrawn. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Clears border pixels from character bitmap ($1000-$1CFF) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ABF6 | a9 08 | erase_arena_borderlda#$08; init segment counter = 8 ; x-ref: $A367 |
| $ABF8 | 85 3c | stazp_attract_delay_ctr |
| $ABFA | a5 3c | b_ABFAldazp_attract_delay_ctr; loop — erase one border segment per pass ; x-ref: $AC01 |
| $ABFC | 20 77 ac | jsrerase_border_segment; erase segment at current counter index |
| $ABFF | c6 3c | deczp_attract_delay_ctr; decrement segment counter |
| $AC01 | d0 f7 | bneb_ABFA |
| $AC03 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws the playfield arena border onto the custom VIC-20 bitmap. Iterates |
| ; through 13 line segments, rendering each using parameters from the |
| ; border_segment_table (fACA0). |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Writes pixels to character bitmap ($1000-$1CFF) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AC04 | a9 08 | draw_arena_borderlda#$08; init segment counter = 8 (counts down to $FB) ; x-ref: $A358 |
| $AC06 | 85 3c | stazp_attract_delay_ctr |
| $AC08 | a5 3c | j_AC08ldazp_attract_delay_ctr; loop — draw one border segment per pass ; x-ref: $AC13 |
| $AC0A | c9 fb | cmp#$fb; stop when counter reaches $FB |
| $AC0C | f0 08 | beqr_AC16 |
| $AC0E | 20 69 ac | jsrdraw_border_segment; draw segment at current counter index |
| $AC11 | c6 3c | deczp_attract_delay_ctr; decrement segment counter |
| $AC13 | 4c 08 ac | jmpj_AC08 |
| $AC16 | 60 | r_AC16rts; x-ref: $AC0C |
| ; Flat array of 5-byte segment records for arena border drawing. |
| ; Each record defines one line segment (start pos, length, step direction): |
| ; +0: X start +1: Y start +2: pixel count +3: X step +4: Y step |
| ; Indexed via offsets from border_segment_tbl. |
| border_segment_params |
| $AC17 | | .byte$00; x-ref: $AC86 |
| border_segment_y_start |
| $AC18 | | .byte$00; x-ref: $AC8B |
| $AC19 | | border_segment_len.byte$4f; x-ref: $AC90 |
| $AC1A | | border_segment_dx.byte$01; x-ref: $AC95 |
| $AC1B | | border_segment_dy.byte$00, $50, $00, $4f, $01, $00, $00, $9f; x-ref: $AC9A |
| $AC23 | | .byte$4f, $01, $00, $50, $9f, $4f, $01, $00 |
| $AC2B | | .byte$28, $3c, $50, $01, $00, $28, $64, $50 |
| $AC33 | | .byte$01, $00, $00, $00, $4f, $00, $01, $00 |
| $AC3B | | .byte$50, $4f, $00, $01, $9f, $00, $4f, $00 |
| $AC43 | | .byte$01, $9f, $50, $4f, $00, $01, $28, $3c |
| $AC4B | | .byte$28, $00, $01, $78, $3c, $28, $00, $01 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Erases a line segment by clearing pixels and stepping by dx, dy. |
| ; Loops until the length counter reaches zero. |
| ; |
| ; Inputs: aA3/aA4 = Start X/Y, aAE/aAF = dx/dy, aBD = length |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AC53 | 20 82 ab | erase_line_segmentjsrclear_pixel; x-ref: $AC66, $AC81 |
| $AC56 | 18 | clc |
| $AC57 | a5 a3 | ldazp_pos_x |
| $AC59 | 65 ae | adczp_step_x |
| $AC5B | 85 a3 | stazp_pos_x |
| $AC5D | 18 | clc |
| $AC5E | a5 a4 | ldazp_pos_y |
| $AC60 | 65 af | adczp_step_y |
| $AC62 | 85 a4 | stazp_pos_y |
| $AC64 | c6 bd | deczp_seg_len |
| $AC66 | d0 eb | bneerase_line_segment |
| $AC68 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws a specific playfield border segment based on an index passed in A. |
| ; Uses border_segment_tbl to look up parameters and calls draw_line_segment. |
| ; |
| ; Inputs: A = Segment index |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap to draw the segment |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AC69 | 18 | draw_border_segmentclc; Clear carry for addition ; x-ref: $A614, $A620, $AC0E, $AE88, $AEBA |
| $AC6A | 69 04 | adc#$04; Add 4 to index (bias for table) |
| $AC6C | a8 | tay; Use as Y index |
| $AC6D | b9 a0 ac | ldaborder_segment_tbl,y; Get offset from table |
| $AC70 | 20 85 ac | jsrload_segment_params; Load segment parameters (X, Y, len, dx, dy) |
| $AC73 | 20 b8 ab | jsrdraw_line_segment; Draw the line segment |
| $AC76 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Erases a specific playfield border segment based on an index passed in A. |
| ; Uses border_segment_tbl to look up parameters and calls erase_line_segment. |
| ; |
| ; Inputs: A = Segment index |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap to clear the segment |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AC77 | 18 | erase_border_segmentclc; Clear carry for addition ; x-ref: $A619, $ABFC, $AE8D |
| $AC78 | 69 04 | adc#$04; Add 4 to index (bias for table) |
| $AC7A | a8 | tay; Use as Y index |
| $AC7B | b9 a0 ac | ldaborder_segment_tbl,y; Get offset from table |
| $AC7E | 20 85 ac | jsrload_segment_params; Load segment parameters (X, Y, len, dx, dy) |
| $AC81 | 20 53 ac | jsrerase_line_segment; Erase the line segment |
| $AC84 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Loads segment parameters (X, Y, length, dx, dy) from tables into Zero Page. |
| ; Indexed by Y register. |
| ; |
| ; Inputs: Y = Offset into parameter tables |
| ; Outputs: aA3 = X, aA4 = Y, aBD = length, aAE = dx, aAF = dy |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AC85 | a8 | load_segment_paramstay; Use offset in Y ; x-ref: $AC70, $AC7E |
| $AC86 | b9 17 ac | ldaborder_segment_params,y; Load X start |
| $AC89 | 85 a3 | stazp_pos_x |
| $AC8B | b9 18 ac | ldaborder_segment_y_start,y; Load Y start |
| $AC8E | 85 a4 | stazp_pos_y |
| $AC90 | b9 19 ac | ldaborder_segment_len,y; Load length |
| $AC93 | 85 bd | stazp_seg_len |
| $AC95 | b9 1a ac | ldaborder_segment_dx,y; Load dx (X step) |
| $AC98 | 85 ae | stazp_step_x |
| $AC9A | b9 1b ac | ldaborder_segment_dy,y; Load dy (Y step) |
| $AC9D | 85 af | stazp_step_y |
| $AC9F | 60 | rts |
| ; Offset index table into border_segment_params. Each byte is a byte-offset (Y index) |
| ; into the flat border_segment_params array, selecting a 5-byte segment record. |
| ; Indexed as: Y = segment_counter + 4; offset = border_segment_tbl[Y] |
| ; |
| ; Record layout at border_segment_params[offset] (5 bytes): |
| ; +0: X start (aA3) |
| ; +1: Y start (aA4) |
| ; +2: pixel count / length (aBD) |
| ; +3: X step per pixel (aAE) |
| ; +4: Y step per pixel (aAF) |
| ; |
| ; Entries (13 total for draw, 8 for erase): |
| ; $32 (50) -> top edge, left half X=0, Y=0, len=79, dx=1, dy=0 |
| ; $19 (25) -> top edge, right half |
| ; $37 (55) -> bottom edge, left half |
| ; $14 (20) -> bottom edge, right half |
| ; $00 (0) -> left edge, top half |
| ; $00 (0) -> left edge, top half (repeat) |
| ; $05 (5) -> left edge, bottom half |
| ; $28 (40) -> right edge, top half |
| ; $2D (45) -> right edge, bottom half |
| ; $0F (15) -> inner box top |
| ; $0A (10) -> inner box bottom |
| ; $23 (35) -> inner box left |
| ; $1E (30) -> inner box right |
| $ACA0 | | border_segment_tbl.byte$32, $19, $37, $14, $00, $00, $05, $28; x-ref: $AC6D, $AC7B |
| $ACA8 | | .byte$2d, $0f, $0a, $23, $1e |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws the current player score (aF7/aF8/aF9) onto the bitmap at X=$52, Y=$48. |
| ; Copies the 3-byte BCD score to a scratch buffer and calls render_bcd_digits |
| ; to draw each digit, advancing 4 pixels per digit. |
| ; |
| ; Inputs: aF7/aF8/aF9 (3-byte packed BCD current score) |
| ; Outputs: None |
| ; Side Effects: Writes digit graphics to bitmap |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ACAD | a9 52 | draw_player_scorelda#$52; X position = $52 ; x-ref: $A35B, $B0FC |
| $ACAF | 85 17 | stazp_score_cursor_x |
| $ACB1 | a9 48 | lda#$48; Y position = $48 |
| $ACB3 | 85 a4 | stazp_pos_y |
| $ACB5 | a2 02 | ldx#$02 |
| $ACB7 | b5 f7 | b_ACB7ldazp_score_lo,x; copy 3-byte BCD score to scratch buffer ; x-ref: $ACBC |
| $ACB9 | 95 1c | stazp_temp_bcd_score,x |
| $ACBB | ca | dex |
| $ACBC | 10 f9 | bplb_ACB7 |
| $ACBE | 20 d7 ac | jsrrender_bcd_digits; render digits |
| $ACC1 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws the current high score (stored in a23-a25) onto the bitmap. |
| ; Copies the 3-byte BCD score to a scratch buffer and calls render_bcd_digits. |
| ; |
| ; Inputs: a23/a24/a25 (3-byte packed BCD high score) |
| ; Outputs: None |
| ; Side Effects: Writes digit graphics to bitmap |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ACC2 | a9 52 | draw_high_scorelda#$52; X position = $52 ; x-ref: $A35E |
| $ACC4 | 85 17 | stazp_score_cursor_x; Store X cursor |
| $ACC6 | a9 5c | lda#$5c; Y position = $5C |
| $ACC8 | 85 a4 | stazp_pos_y; Store Y pos |
| $ACCA | a2 02 | ldx#$02; Init loop counter for 3 bytes |
| $ACCC | b5 23 | b_ACCCldazp_hiscore_lo,x; Copy BCD score byte to scratch ; x-ref: $ACD1 |
| $ACCE | 95 1c | stazp_temp_bcd_score,x; Store in scratch |
| $ACD0 | ca | dex |
| $ACD1 | 10 f9 | bplb_ACCC |
| $ACD3 | 20 d7 ac | jsrrender_bcd_digits; Render digits |
| $ACD6 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Renders the 3-byte packed BCD score in temp_bcd_score as digits. |
| ; Handles leading zero suppression. Once a non-zero digit is found, all |
| ; subsequent digits are rendered. |
| ; |
| ; Inputs: temp_bcd_score (3 bytes, packed BCD) |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap, advances score_cursor_x |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ACD7 | 20 a7 ad | render_bcd_digitsjsradvance_score_cursor; Initial spacing ; x-ref: $ACBE, $ACD3 |
| $ACDA | a2 02 | ldx#$02; Index 2 = most significant byte |
| $ACDC | 86 b4 | stxzp_loop_idx |
| $ACDE | a6 b4 | b_ACDEldxzp_loop_idx; Load BCD byte ; x-ref: $ACEC |
| $ACE0 | b5 1c | ldazp_temp_bcd_score,x |
| $ACE2 | d0 0c | bneb_ACF0; If not zero, start rendering |
| $ACE4 | 20 a7 ad | jsradvance_score_cursor; Skip spacing for blank digits |
| $ACE7 | 20 a7 ad | jsradvance_score_cursor |
| $ACEA | c6 b4 | deczp_loop_idx |
| $ACEC | 10 f0 | bplb_ACDE |
| $ACEE | 30 22 | bmib_AD12 |
| $ACF0 | 29 f0 | b_ACF0and#$f0; Extract high nibble ; x-ref: $ACE2 |
| $ACF2 | f0 0b | beqb_ACFF; If high nibble zero, skip it |
| $ACF4 | a6 b4 | b_ACF4ldxzp_loop_idx; x-ref: $AD10 |
| $ACF6 | b5 1c | ldazp_temp_bcd_score,x |
| $ACF8 | 4a | lsra; Shift right to get digit value |
| $ACF9 | 4a | lsra |
| $ACFA | 4a | lsra |
| $ACFB | 4a | lsra |
| $ACFC | 20 9d ad | jsrdraw_bcd_digit; Draw high nibble digit |
| $ACFF | 20 a7 ad | b_ACFFjsradvance_score_cursor; Advance cursor for next digit ; x-ref: $ACF2 |
| $AD02 | a6 b4 | ldxzp_loop_idx |
| $AD04 | b5 1c | ldazp_temp_bcd_score,x |
| $AD06 | 29 0f | and#$0f; Extract low nibble |
| $AD08 | 20 9d ad | jsrdraw_bcd_digit; Draw low nibble digit |
| $AD0B | 20 a7 ad | jsradvance_score_cursor |
| $AD0E | c6 b4 | deczp_loop_idx |
| $AD10 | 10 e2 | bplb_ACF4 |
| $AD12 | a9 00 | b_AD12lda#$00; If all were zero, draw a single '0' ; x-ref: $ACEE |
| $AD14 | 20 9d ad | jsrdraw_bcd_digit |
| $AD17 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws the current wave/level indicator as two columns of icons on the bitmap. |
| ; First column: up to 5 icons at X=$5A, Y=$40 (tens digit of wave). |
| ; Second column: up to 10 icons at X=$46, Y=$54 (units digit of wave). |
| ; Icon graphics are indexed from wave_icon_table (fB71E). |
| ; |
| ; Inputs: None (uses hardcoded positions and wave_icon_table) |
| ; Outputs: None |
| ; Side Effects: Writes icon graphics to bitmap |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AD18 | a9 04 | draw_wave_indicatorlda#$04; first column: 5 icons max ; x-ref: $A361 |
| $AD1A | 85 1c | stazp_temp_bcd_score |
| $AD1C | a9 5a | lda#$5a; X = $5A |
| $AD1E | 85 17 | stazp_score_cursor_x |
| $AD20 | a9 40 | lda#$40; Y = $40 |
| $AD22 | 85 a4 | stazp_pos_y |
| $AD24 | 20 37 ad | jsrdraw_wave_icons |
| $AD27 | a9 09 | lda#$09; second column: 10 icons max |
| $AD29 | 85 1c | stazp_temp_bcd_score |
| $AD2B | a9 46 | lda#$46; X = $46 |
| $AD2D | 85 17 | stazp_score_cursor_x |
| $AD2F | a9 54 | lda#$54; Y = $54 |
| $AD31 | 85 a4 | stazp_pos_y |
| $AD33 | 20 37 ad | jsrdraw_wave_icons |
| $AD36 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws a sequence of wave indicator icons from wave_icon_tbl. |
| ; Loops based on the value in temp_bcd_score (counts down to 0). |
| ; |
| ; Inputs: temp_bcd_score = Number of icons to draw - 1 |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap, advances score_cursor_x |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AD37 | 20 a7 ad | draw_wave_iconsjsradvance_score_cursor; Advance cursor for spacing ; x-ref: $AD24, $AD33, $AD47 |
| $AD3A | a4 1c | ldyzp_temp_bcd_score; Use remaining count as index |
| $AD3C | b9 1e b7 | ldawave_icon_tbl,y; Load icon index from table |
| $AD3F | 20 9b ab | jsrcalc_sprite_ptr; Compute sprite pointer |
| $AD42 | 20 ff aa | jsrdraw_sprite_or_collision; Draw the icon |
| $AD45 | c6 1c | deczp_temp_bcd_score; Decrement remaining count |
| $AD47 | 10 ee | bpldraw_wave_icons; Loop if not negative |
| $AD49 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws the player lives display onto the bitmap. Erases all 3 ship icon slots, |
| ; then redraws a filled ship icon for each remaining life (a1F). Uses a54 to |
| ; select a bonus ship position for the last icon drawn. |
| ; |
| ; Inputs: a1F (lives remaining), a54 (bonus ship flag) |
| ; Outputs: None |
| ; Side Effects: Writes ship icon graphics to bitmap at lives_icon_x/y_table positions |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AD4A | a2 02 | draw_lives_displayldx#$02; loop over 3 ship slots (X=2 down to 0) ; x-ref: $A364, $B163 |
| $AD4C | 86 b4 | stxzp_loop_idx |
| $AD4E | a9 29 | lda#$29; bitmap column = $29 |
| $AD50 | 20 9b ab | jsrcalc_sprite_ptr |
| $AD53 | a6 b4 | b_AD53ldxzp_loop_idx; x-ref: $AD64 |
| $AD55 | bd 93 ad | ldalives_icon_x_tbl,x; get X position for this slot |
| $AD58 | 85 a3 | stazp_pos_x |
| $AD5A | bd 98 ad | ldalives_icon_y_tbl,x; get Y position for this slot |
| $AD5D | 85 a4 | stazp_pos_y |
| $AD5F | 20 41 ab | jsrerase_sprite; erase ship icon |
| $AD62 | c6 b4 | deczp_loop_idx |
| $AD64 | 10 ed | bplb_AD53 |
| $AD66 | a6 1f | ldxzp_player_lives; lives remaining = 0 -> game over |
| $AD68 | f0 28 | beqr_AD92 |
| $AD6A | 86 b4 | stxzp_loop_idx |
| $AD6C | a9 00 | lda#$00 |
| $AD6E | 20 9b ab | jsrcalc_sprite_ptr |
| $AD71 | a5 54 | ldazp_extra_life_awarded; a54 = bonus ship flag |
| $AD73 | f0 0a | beqb_AD7F |
| $AD75 | a9 3d | lda#$3d; bonus ship at fixed position ($3D/$4C) |
| $AD77 | 85 a3 | stazp_pos_x |
| $AD79 | a9 4c | lda#$4c |
| $AD7B | 85 a4 | stazp_pos_y |
| $AD7D | d0 0c | bneb_AD8B |
| $AD7F | a6 b4 | b_AD7Fldxzp_loop_idx; x-ref: $AD73, $AD90 |
| $AD81 | bd 93 ad | ldalives_icon_x_tbl,x |
| $AD84 | 85 a3 | stazp_pos_x |
| $AD86 | bd 98 ad | ldalives_icon_y_tbl,x |
| $AD89 | 85 a4 | stazp_pos_y |
| $AD8B | 20 ff aa | b_AD8Bjsrdraw_sprite_or_collision; draw filled ship icon ; x-ref: $AD7D |
| $AD8E | c6 b4 | deczp_loop_idx |
| $AD90 | d0 ed | bneb_AD7F |
| $AD92 | 60 | r_AD92rts; x-ref: $AD68 |
| $AD93 | | lives_icon_x_tbl.byte$3d, $2b, $2b, $34, $34; x-ref: $AD55, $AD81 |
| $AD98 | | lives_icon_y_tbl.byte$4c, $44, $54, $44, $54; x-ref: $AD5A, $AD86 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Renders a single BCD digit (0-9) onto the bitmap. |
| ; Adds $47 to the digit value to get the sprite index. |
| ; |
| ; Inputs: A = Digit value (0-9) |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AD9D | 18 | draw_bcd_digitclc; Clear carry for addition ; x-ref: $ACFC, $AD08, $AD14 |
| $AD9E | 69 47 | adc#$47; Add $47 to get sprite index ('0' is at $47) |
| $ADA0 | 20 9b ab | jsrcalc_sprite_ptr; Compute sprite pointer |
| $ADA3 | 20 ff aa | jsrdraw_sprite_or_collision; Draw the digit |
| $ADA6 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Advances the score cursor X position by 4 pixels. |
| ; |
| ; Inputs: score_cursor_x |
| ; Outputs: score_cursor_x (incremented by 4) |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ADA7 | a5 17 | advance_score_cursorldazp_score_cursor_x; Load current X cursor ; x-ref: $ACD7, $ACE4, $ACE7, $ACFF, $AD0B, $AD37 |
| $ADA9 | 18 | clc; Clear carry for addition |
| $ADAA | 69 04 | adc#$04; Advance by 4 pixels |
| $ADAC | 85 17 | stazp_score_cursor_x; Store updated X cursor |
| $ADAE | 85 a3 | stazp_pos_x |
| $ADB0 | a9 5b | lda#$5b |
| $ADB2 | 20 9b ab | jsrcalc_sprite_ptr |
| $ADB5 | 20 41 ab | jsrerase_sprite |
| $ADB8 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes a new bullet slot when the player fires. |
| ; Scans for a free slot (0-3), looks up velocity and position offsets |
| ; based on the player's angle (aB1), and sets bullet lifetime. |
| ; |
| ; Inputs: aB1 = Player angle (0-15), player position |
| ; Outputs: None |
| ; Side Effects: Modifies bullet slot arrays, decrements bullet_slots_free |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $ADB9 | a9 00 | fire_bulletlda#$00; x-ref: $A476 |
| $ADBB | 85 35 | stazp_fire_cooldown |
| $ADBD | a5 19 | ldazp_bullet_slots_free |
| $ADBF | f0 45 | beqr_AE06 |
| $ADC1 | a2 03 | ldx#$03 |
| $ADC3 | bd 5d 1d | b_ADC3ldabullet_lifetimes,x; x-ref: $AE04 |
| $ADC6 | d0 3b | bneb_AE03 |
| $ADC8 | 78 | sei |
| $ADC9 | a9 01 | lda#$01 |
| $ADCB | 85 47 | stazp_snd_soprano_seq_idx |
| $ADCD | 85 4b | stazp_snd_soprano_step |
| $ADCF | 85 43 | stazp_snd_soprano_dur |
| $ADD1 | 58 | cli |
| $ADD2 | a4 b1 | ldyzp_player_angle |
| $ADD4 | 18 | clc |
| fADD7 =*+$02 |
| $ADD5 | b9 07 ae | ldabullet_dx_tbl,y; load X velocity from angle table |
| $ADD8 | 9d 4d 1d | stabullet_vx,x |
| $ADDB | 18 | clc |
| $ADDC | ad 62 03 | ldaentity_x_coords |
| $ADDF | 79 27 ae | adcbullet_spawn_dx_tbl,y; add X spawn offset; places bullet at ship nose |
| $ADE2 | 9d 65 1d | stabullet_x_coords,x |
| $ADE5 | 18 | clc |
| $ADE6 | b9 17 ae | ldabullet_dy_tbl,y; load Y velocity from angle table |
| $ADE9 | 9d 55 1d | stabullet_vy,x |
| $ADEC | 18 | clc |
| $ADED | ad 75 03 | ldaentity_y_coords |
| $ADF0 | 79 37 ae | adcbullet_spawn_dy_tbl,y; add Y spawn offset; places bullet at ship nose |
| $ADF3 | 9d 6d 1d | stabullet_y_coords,x |
| $ADF6 | a9 32 | lda#$32 |
| $ADF8 | 9d 5d 1d | stabullet_lifetimes,x |
| $ADFB | a9 00 | lda#$00 |
| $ADFD | 9d 75 1d | stabullet_owners,x |
| $AE00 | c6 19 | deczp_bullet_slots_free |
| $AE02 | 60 | rts |
| $AE03 | ca | b_AE03dex; x-ref: $ADC6 |
| $AE04 | 10 bd | bplb_ADC3 |
| $AE06 | 60 | r_AE06rts; x-ref: $ADBF |
| ; Signed X velocity delta per tick for a fired bullet, indexed by player angle (aB1, 0-15). |
| ; Values are 8-bit signed: $FD=-3, $FE=-2, $FF=-1, $00=0, $01=1, $02=2, $03=3. |
| ; Forms a cosine-like curve across 16 angles (0=right, 4=up, 8=left, 12=down). |
| ; Paired with bullet_dy_tbl (Y axis), bullet_spawn_dx_tbl/bullet_spawn_dy_tbl (spawn offset). |
| $AE07 | | bullet_dx_tbl.byte$03, $02, $02, $01, $00, $ff, $fe, $fe; x-ref: $ADD5 |
| $AE0F | | .byte$fd, $fd, $fe, $ff, $00, $01, $02, $02 |
| ; Signed Y velocity delta per tick for a fired bullet, indexed by player angle (aB1, 0-15). |
| ; Values are 8-bit signed: $FD=-3..$03=+3. Sine-like curve, 90 degrees offset from bullet_dx_tbl. |
| $AE17 | | bullet_dy_tbl.byte$00, $ff, $fe, $fe, $fd, $fe, $ff, $ff; x-ref: $ADE6 |
| $AE1F | | .byte$00, $01, $02, $02, $03, $02, $02, $01 |
| ; X spawn position offset (added to player X) for a new bullet, indexed by angle (aB1, 0-15). |
| ; Biases bullet starting position to appear at the ship's nose tip rather than its center. |
| $AE27 | | bullet_spawn_dx_tbl.byte$09, $09, $09, $05, $04, $03, $ff, $ff; x-ref: $ADDF |
| $AE2F | | .byte$ff, $ff, $ff, $03, $04, $05, $09, $09 |
| ; Y spawn position offset (added to player Y) for a new bullet, indexed by angle (aB1, 0-15). |
| ; Biases bullet starting position to appear at the ship's nose tip rather than its center. |
| $AE37 | | bullet_spawn_dy_tbl.byte$04, $03, $ff, $ff, $ff, $ff, $ff, $03; x-ref: $ADF0 |
| $AE3F | | .byte$04, $05, $09, $09, $09, $09, $09, $05 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Per-frame bullet update loop. Iterates over all 8 bullet slots (index 7..0) |
| ; and for each active bullet: |
| ; 1. Loads slot state into working registers via load_bullet_slot. |
| ; 2. Erases the old 3-pixel trail via erase_bullet_trail (steps back 3 pixels). |
| ; 3. Advances position: new_x = x + dx, new_y = y + dy; saves back to slot. |
| ; 4. Draws the new 3-pixel trail via draw_bullet_trail (steps forward 3 pixels). |
| ; 5. On wall hit (collision_type != 0): redraws/erases the impacted border segment. |
| ; 6. On pixel overlap (collision_check_flag != 0): ORs bullet's bit into a26 |
| ; (bullet-hit bitmask, consumed by update_display_and_collisions). |
| ; 7. Decrements f1D5D lifetime counter; when it reaches 0 the slot is freed. |
| ; |
| ; Inputs: f1D5D,x = bullet lifetime; f1D4D,x/f1D55,x = dx/dy velocity |
| ; f1D65,x/f1D6D,x = current x/y position; f1D75,x = slot owner flag |
| ; Outputs: a26 = bitmask of bullets that hit something this frame |
| ; f1D65,x/f1D6D,x updated to new positions |
| ; Side Effects: Bitmap modified (erase old trail, draw new trail); border segments |
| ; redrawn on wall collision; bullet_slots_free incremented on expiry |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AE47 | a9 00 | update_bulletslda#$00; clear bullet-hit bitmask and collision accumulator ; x-ref: $A535 |
| $AE49 | 85 1b | stazp_collision_check_flag |
| $AE4B | 85 26 | stazp_bullet_hit_mask |
| $AE4D | a9 07 | lda#$07 |
| $AE4F | 85 b4 | stazp_loop_idx |
| $AE51 | a6 b4 | j_AE51ldxzp_loop_idx; x-ref: $AEC7 |
| $AE53 | bd 5d 1d | ldabullet_lifetimes,x; slot counter: iterate 7..0 |
| $AE56 | f0 6b | beqb_AEC3; skip if slot is empty (lifetime = 0) |
| $AE58 | 20 31 af | jsrload_bullet_slot |
| $AE5B | 20 01 af | jsrerase_bullet_trail; erase old 3-pixel trail at previous position |
| $AE5E | a6 b4 | ldxzp_loop_idx |
| $AE60 | de 5d 1d | decbullet_lifetimes,x; decrement lifetime; 0 means bullet expires this tick |
| $AE63 | f0 43 | beqb_AEA8 |
| $AE65 | 18 | clc |
| $AE66 | bd 4d 1d | ldabullet_vx,x; advance x: new_x = x + dx |
| $AE69 | 85 ae | stazp_step_x |
| $AE6B | 7d 65 1d | adcbullet_x_coords,x |
| $AE6E | 85 a3 | stazp_pos_x |
| $AE70 | 9d 65 1d | stabullet_x_coords,x |
| $AE73 | 18 | clc |
| $AE74 | bd 55 1d | ldabullet_vy,x |
| $AE77 | 85 af | stazp_step_y |
| $AE79 | 7d 6d 1d | adcbullet_y_coords,x; advance y: new_y = y + dy |
| $AE7C | 85 a4 | stazp_pos_y |
| $AE7E | 9d 6d 1d | stabullet_y_coords,x |
| $AE81 | 20 cb ae | jsrdraw_bullet_trail; draw new 3-pixel trail; sets collision_type / collision_check_flag |
| $AE84 | a5 18 | ldazp_collision_type |
| $AE86 | f0 0b | beqb_AE93; wall hit? redraw impacted border segment |
| $AE88 | 20 69 ac | jsrdraw_border_segment |
| $AE8B | a5 18 | ldazp_collision_type |
| $AE8D | 20 77 ac | jsrerase_border_segment |
| $AE90 | 4c a0 ae | jmpj_AEA0 |
| $AE93 | a5 1b | b_AE93ldazp_collision_check_flag; x-ref: $AE86 |
| $AE95 | f0 2c | beqb_AEC3; pixel overlap hit — OR this bullet's bit into hit-bitmask |
| $AE97 | a4 b4 | ldyzp_loop_idx |
| $AE99 | b9 93 ab | ldabit_mask_tbl,y |
| $AE9C | 05 26 | orazp_bullet_hit_mask |
| $AE9E | 85 26 | stazp_bullet_hit_mask |
| $AEA0 | a6 b4 | j_AEA0ldxzp_loop_idx; x-ref: $AE90 |
| $AEA2 | 20 31 af | jsrload_bullet_slot |
| $AEA5 | 20 01 af | jsrerase_bullet_trail |
| $AEA8 | a6 b4 | b_AEA8ldxzp_loop_idx; x-ref: $AE63 |
| $AEAA | bd 75 1d | ldabullet_owners,x; slot owner flag: 0 = player bullet, free slot back to pool |
| $AEAD | d0 02 | bneb_AEB1 |
| $AEAF | e6 19 | inczp_bullet_slots_free |
| $AEB1 | a9 00 | b_AEB1lda#$00; x-ref: $AEAD |
| $AEB3 | 9d 5d 1d | stabullet_lifetimes,x |
| $AEB6 | a5 18 | ldazp_collision_type |
| $AEB8 | 10 03 | bplb_AEBD |
| $AEBA | 20 69 ac | jsrdraw_border_segment |
| $AEBD | a9 00 | b_AEBDlda#$00; x-ref: $AEB8 |
| $AEBF | 85 1b | stazp_collision_check_flag |
| $AEC1 | 85 18 | stazp_collision_type |
| $AEC3 | c6 b4 | b_AEC3deczp_loop_idx; x-ref: $AE56, $AE95 |
| $AEC5 | 30 03 | bmir_AECA |
| $AEC7 | 4c 51 ae | jmpj_AE51 |
| $AECA | 60 | r_AECArts; x-ref: $AEC5 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws a 3-pixel bullet trail forward from (aA3, aA4) in direction (aAE, aAF). |
| ; Plots 3 pixels, stepping +1 or -1 in x/y per pixel based on velocity sign. |
| ; Sets collision_check_flag if any pixel overlaps existing bitmap content. |
| ; Sets collision_type if a wall boundary is hit (via sAF7E). |
| ; |
| ; Inputs: aA3/aA4 = bullet X/Y position; aAE/aAF = X/Y velocity (sign used only) |
| ; Outputs: collision_check_flag, collision_type |
| ; Side Effects: Bitmap modified (3 pixels drawn) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AECB | a9 03 | draw_bullet_traillda#$03; x-ref: $AE81 |
| $AECD | 85 bd | stazp_seg_len |
| $AECF | a9 00 | lda#$00 |
| $AED1 | 85 1b | stazp_collision_check_flag |
| $AED3 | 20 7e af | b_AED3jsrplot_bullet_pixel; x-ref: $AEFE |
| $AED6 | a5 18 | ldazp_collision_type |
| $AED8 | 05 1b | orazp_collision_check_flag |
| $AEDA | d0 24 | bner_AF00 |
| $AEDC | a5 ae | ldazp_step_x |
| $AEDE | f0 0c | beqb_AEEC |
| $AEE0 | 30 03 | bmib_AEE5 |
| $AEE2 | a9 01 | lda#$01 |
| $AEE4 | | .byte$2c; bit opcode |
| $AEE5 | a9 ff | b_AEE5lda#$ff; x-ref: $AEE0 |
| $AEE7 | 18 | clc |
| $AEE8 | 65 a3 | adczp_pos_x |
| $AEEA | 85 a3 | stazp_pos_x |
| $AEEC | a5 af | b_AEECldazp_step_y; x-ref: $AEDE |
| $AEEE | f0 0c | beqb_AEFC |
| $AEF0 | 30 03 | bmib_AEF5 |
| $AEF2 | a9 01 | lda#$01 |
| $AEF4 | | .byte$2c; bit opcode |
| $AEF5 | a9 ff | b_AEF5lda#$ff; x-ref: $AEF0 |
| $AEF7 | 18 | clc |
| $AEF8 | 65 a4 | adczp_pos_y |
| $AEFA | 85 a4 | stazp_pos_y |
| $AEFC | c6 bd | b_AEFCdeczp_seg_len; x-ref: $AEEE |
| $AEFE | d0 d3 | bneb_AED3 |
| $AF00 | 60 | r_AF00rts; x-ref: $AEDA |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Erases a 3-pixel bullet trail backward from (aA3, aA4) in direction (aAE, aAF). |
| ; Steps -1 or +1 in x/y (opposite of velocity sign) and clears each pixel. |
| ; Uses clear_pixel_with_bounce; stops early on wall hit. |
| ; |
| ; Inputs: aA3/aA4 = bullet X/Y position; aAE/aAF = X/Y velocity (sign used only) |
| ; Outputs: None |
| ; Side Effects: Bitmap modified (3 pixels cleared); may set collision_type |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AF01 | a9 03 | erase_bullet_traillda#$03; x-ref: $AE5B, $AEA5 |
| $AF03 | 85 bd | stazp_seg_len |
| $AF05 | 20 7c ab | b_AF05jsrclear_pixel_with_bounce; x-ref: $AF2E |
| $AF08 | a5 18 | ldazp_collision_type |
| $AF0A | d0 24 | bner_AF30 |
| $AF0C | a5 ae | ldazp_step_x |
| $AF0E | f0 0c | beqb_AF1C |
| $AF10 | 30 03 | bmib_AF15 |
| $AF12 | a9 01 | lda#$01 |
| $AF14 | | .byte$2c; bit opcode |
| $AF15 | a9 ff | b_AF15lda#$ff; x-ref: $AF10 |
| $AF17 | 18 | clc |
| $AF18 | 65 a3 | adczp_pos_x |
| $AF1A | 85 a3 | stazp_pos_x |
| $AF1C | a5 af | b_AF1Cldazp_step_y; x-ref: $AF0E |
| $AF1E | f0 0c | beqb_AF2C |
| $AF20 | 30 03 | bmib_AF25 |
| $AF22 | a9 01 | lda#$01 |
| $AF24 | | .byte$2c; bit opcode |
| $AF25 | a9 ff | b_AF25lda#$ff; x-ref: $AF20 |
| $AF27 | 18 | clc |
| $AF28 | 65 a4 | adczp_pos_y |
| $AF2A | 85 a4 | stazp_pos_y |
| $AF2C | c6 bd | b_AF2Cdeczp_seg_len; x-ref: $AF1E |
| $AF2E | d0 d5 | bneb_AF05 |
| $AF30 | 60 | r_AF30rts; x-ref: $AF0A |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Loads bullet slot X (index in X reg) into working registers. |
| ; Copies position and velocity from parallel bullet arrays to shared ZP vars. |
| ; |
| ; Inputs: X = bullet slot index (0-7) |
| ; Outputs: aA3=x, aA4=y, aAE=dx, aAF=dy |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AF31 | bd 65 1d | load_bullet_slotldabullet_x_coords,x; x-ref: $AE58, $AEA2 |
| $AF34 | 85 a3 | stazp_pos_x |
| $AF36 | bd 6d 1d | ldabullet_y_coords,x |
| $AF39 | 85 a4 | stazp_pos_y |
| $AF3B | bd 4d 1d | ldabullet_vx,x |
| $AF3E | 85 ae | stazp_step_x |
| $AF40 | bd 55 1d | ldabullet_vy,x |
| $AF43 | 85 af | stazp_step_y |
| $AF45 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes a new bullet slot for an enemy. |
| ; Scans for a free slot among the upper slots (7 down to 4). |
| ; Inherits velocity from the firing enemy and sets position slightly ahead. |
| ; |
| ; Inputs: a3B = Index of the firing enemy |
| ; Outputs: None |
| ; Side Effects: Modifies bullet slot arrays, sets owner flag to 1 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AF46 | a0 07 | enemy_fire_bulletldy#$07; Start with highest bullet slot (7) ; x-ref: $A7CD, $A7E0, $A7F3 |
| $AF48 | a6 3b | ldxzp_firing_entity_slot; Load firing enemy index |
| $AF4A | b9 5d 1d | b_AF4Aldabullet_lifetimes,y; Check if slot is free ; x-ref: $AF7B |
| $AF4D | d0 29 | bneb_AF78; If active, try next slot |
| $AF4F | bd 33 1d | ldaai_pursuit_vx,x; Inherit enemy X velocity |
| $AF52 | 99 4d 1d | stabullet_vx,y |
| $AF55 | 18 | clc |
| $AF56 | 7d 62 03 | adcentity_x_coords,x; Add to enemy X position |
| $AF59 | 69 04 | adc#$04; Add offset of 4 pixels |
| $AF5B | 99 65 1d | stabullet_x_coords,y; Store as bullet X position |
| $AF5E | bd 40 1d | ldaai_pursuit_vy,x; Inherit enemy Y velocity |
| $AF61 | 99 55 1d | stabullet_vy,y |
| $AF64 | 18 | clc |
| $AF65 | 7d 75 03 | adcentity_y_coords,x; Add to enemy Y position |
| $AF68 | 69 04 | adc#$04; Add offset of 4 pixels |
| $AF6A | 99 6d 1d | stabullet_y_coords,y; Store as bullet Y position |
| $AF6D | a9 23 | lda#$23; Set lifetime to 35 frames |
| $AF6F | 99 5d 1d | stabullet_lifetimes,y |
| $AF72 | a9 01 | lda#$01; Set owner flag to 1 (enemy) |
| $AF74 | 99 75 1d | stabullet_owners,y |
| $AF77 | 60 | rts |
| $AF78 | 88 | b_AF78dey; Move to next slot ; x-ref: $AF4D |
| $AF79 | c0 03 | cpy#$03; Stop after checking slot 4 |
| $AF7B | d0 cd | bneb_AF4A |
| $AF7D | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Plots a single pixel of a bullet trail onto the bitmap. |
| ; Checks for boundary collisions and pixel overlaps (collisions with other entities). |
| ; |
| ; Inputs: aA5 = Pointer to bitmap byte, aAD = bit offset (0-7) |
| ; collision_check_flag = accumulator |
| ; Outputs: collision_check_flag (updated), collision_type (from boundary check) |
| ; Side Effects: Modifies the bitmap |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AF7E | 20 6a a9 | plot_bullet_pixeljsrcheck_boundary_collisions; Check collisions with walls ; x-ref: $AED3 |
| $AF81 | a5 18 | ldazp_collision_type; Check if wall hit |
| $AF83 | d0 17 | bner_AF9C; Return if wall hit |
| $AF85 | a6 ad | ldxzp_spr_bit_offset; X = bit offset (0-7) |
| $AF87 | bd 93 ab | ldabit_mask_tbl,x; Get bit mask for pixel |
| $AF8A | 85 b3 | stazp_pixel_mask; Store mask |
| $AF8C | a2 00 | ldx#$00; Offset 0 |
| $AF8E | a1 a5 | lda(zp_ptr_bmp_col_lo,x); Read bitmap byte |
| $AF90 | a8 | tay; Save original byte in Y |
| $AF91 | 25 b3 | andzp_pixel_mask; Check if pixel already set |
| $AF93 | 05 1b | orazp_collision_check_flag; Update collision flag |
| $AF95 | 85 1b | stazp_collision_check_flag |
| $AF97 | 98 | tya; Restore original byte |
| $AF98 | 05 b3 | orazp_pixel_mask; Set pixel bit |
| $AF9A | 81 a5 | sta(zp_ptr_bmp_col_lo,x); Write back to bitmap |
| $AF9C | 60 | r_AF9Crts; x-ref: $AF83 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Spawns a new mine/drone at the position of the current enemy (X). |
| ; Scans for a free slot among the upper slots (18 down to 13). |
| ; Sets type to 5 or 6 based on a random timer check. |
| ; |
| ; Inputs: X = Index of parent enemy |
| ; Outputs: None |
| ; Side Effects: Modifies entity slot arrays (13-18) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AF9D | a0 12 | spawn_enemy_mineldy#$12; Start with highest candidate slot (18) ; x-ref: $A802, $A81D |
| $AF9F | b9 3c 03 | b_AF9Fldaentity_types,y; Check if slot is free (negative type) ; x-ref: $AFA7 |
| $AFA2 | 30 07 | bmib_AFAB; Branch if free slot found |
| $AFA4 | 88 | dey; Else try next lower slot |
| $AFA5 | c0 0d | cpy#$0d; Stop after checking slot 13 |
| $AFA7 | b0 f6 | bcsb_AF9F |
| $AFA9 | 90 20 | bccr_AFCB |
| $AFAB | bd 62 03 | b_AFABldaentity_x_coords,x; Copy X position from parent enemy ; x-ref: $AFA2 |
| $AFAE | 99 62 03 | staentity_x_coords,y |
| $AFB1 | bd 75 03 | ldaentity_y_coords,x; Copy Y position from parent enemy |
| $AFB4 | 99 75 03 | staentity_y_coords,y |
| $AFB7 | a9 00 | lda#$00; Set state to active (0) |
| $AFB9 | 99 a2 03 | staentity_velocity_indices,y |
| $AFBC | ad 24 91 | lda$9124; Read random-ish value from timer |
| $AFBF | 29 03 | and#$03; Mask to 2 bits |
| $AFC1 | d0 03 | bneb_AFC6; Branch if not 0 |
| $AFC3 | a9 05 | lda#$05; Set type 5 (rare) |
| $AFC5 | | .byte$2c; bit opcode |
| $AFC6 | a9 06 | b_AFC6lda#$06; Set type 6 (common) ; x-ref: $AFC1 |
| $AFC8 | 99 3c 03 | staentity_types,y; Store entity type |
| $AFCB | 60 | r_AFCBrts; x-ref: $AFA9 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the visual display of an enemy entity. |
| ; Runs every 8 frames. Handles normal (3x3 body) and exploding (4 wings) states. |
| ; Animates by toggling bit 0 of the state. |
| ; |
| ; Inputs: Y = Entity slot index |
| ; Outputs: None |
| ; Side Effects: Modifies the bitmap, updates entity state and timer |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $AFCC | 84 28 | draw_enemystyzp_cur_entity_idx; Scratch: current enemy entity slot index, preserved across draw sub-calls ; x-ref: $A598 |
| $AFCE | a6 28 | ldxzp_cur_entity_idx |
| $AFD0 | a5 37 | ldazp_frame_counter; Load frame counter |
| $AFD2 | 29 07 | and#$07; Check lower 3 bits |
| $AFD4 | f0 01 | beqb_AFD7; Only run every 8 frames |
| $AFD6 | 60 | rts |
| $AFD7 | bd a2 03 | b_AFD7ldaentity_velocity_indices,x; Load entity state ; x-ref: $AFD4 |
| $AFDA | c9 82 | cmp#$82; Check if state >= $82 (exploding) |
| $AFDC | b0 39 | bcsb_B017 |
| $AFDE | 20 a1 b1 | jsrerase_enemy_body; Erase normal body |
| $AFE1 | a0 08 | ldy#$08 |
| $AFE3 | 84 3c | styzp_attract_delay_ctr |
| $AFE5 | a6 28 | b_AFE5ldxzp_cur_entity_idx; x-ref: $B013 |
| $AFE7 | a4 3c | ldyzp_attract_delay_ctr |
| $AFE9 | b9 8a b0 | ldaenemy_body_dx_tbl,y; load X offset for body pixel [a3C] |
| $AFEC | 18 | clc |
| $AFED | 7d 62 03 | adcentity_x_coords,x |
| $AFF0 | 85 a3 | stazp_pos_x |
| $AFF2 | b9 93 b0 | ldaenemy_body_dy_tbl,y; load Y offset for body pixel [a3C] |
| $AFF5 | 18 | clc |
| $AFF6 | 7d 75 03 | adcentity_y_coords,x |
| $AFF9 | 85 a4 | stazp_pos_y |
| $AFFB | bd a2 03 | ldaentity_velocity_indices,x |
| $AFFE | 29 01 | and#$01 |
| $B000 | f0 02 | beqb_B004 |
| $B002 | a9 09 | lda#$09 |
| $B004 | 18 | b_B004clc; x-ref: $B000 |
| $B005 | 65 3c | adczp_attract_delay_ctr |
| $B007 | a8 | tay |
| $B008 | b9 a4 b0 | ldaf_B0A4,y |
| $B00B | 20 9b ab | jsrcalc_sprite_ptr |
| $B00E | 20 05 ab | jsrdraw_sprite_with_collision_check; Draw body pixel |
| $B011 | c6 3c | deczp_attract_delay_ctr |
| $B013 | 10 d0 | bplb_AFE5 |
| $B015 | 30 35 | bmib_B04C |
| $B017 | 20 7a b1 | b_B017jsrerase_enemy_wings; Erase wings ; x-ref: $AFDC |
| $B01A | a0 03 | ldy#$03 |
| $B01C | 84 3c | styzp_attract_delay_ctr |
| $B01E | a6 28 | b_B01Eldxzp_cur_entity_idx; x-ref: $B04A |
| $B020 | a4 3c | ldyzp_attract_delay_ctr |
| $B022 | b9 82 b0 | ldaenemy_wing_dx_tbl,y; load X offset for wing pixel [a3C] |
| $B025 | 18 | clc |
| $B026 | 7d 62 03 | adcentity_x_coords,x |
| $B029 | 85 a3 | stazp_pos_x |
| $B02B | b9 86 b0 | ldaenemy_wing_dy_tbl,y; load Y offset for wing pixel [a3C] |
| $B02E | 18 | clc |
| $B02F | 7d 75 03 | adcentity_y_coords,x |
| $B032 | 85 a4 | stazp_pos_y |
| $B034 | bd a2 03 | ldaentity_velocity_indices,x |
| $B037 | 29 01 | and#$01 |
| $B039 | 0a | asla |
| $B03A | 0a | asla |
| $B03B | 18 | clc |
| $B03C | 65 3c | adczp_attract_delay_ctr |
| $B03E | a8 | tay |
| $B03F | b9 9c b0 | ldaf_B09C,y |
| $B042 | 20 9b ab | jsrcalc_sprite_ptr |
| $B045 | 20 05 ab | jsrdraw_sprite_with_collision_check; Draw wing pixel |
| $B048 | c6 3c | deczp_attract_delay_ctr |
| $B04A | 10 d2 | bplb_B01E |
| $B04C | a6 28 | b_B04Cldxzp_cur_entity_idx; x-ref: $B015 |
| $B04E | de b5 03 | decentity_anim_timers,x; Decrement animation timer |
| $B051 | 30 09 | bmib_B05C; Branch if timer expired |
| $B053 | bd a2 03 | ldaentity_velocity_indices,x |
| $B056 | 49 01 | eor#$01; Toggle bit 0 for animation |
| $B058 | 9d a2 03 | staentity_velocity_indices,x |
| $B05B | 60 | rts |
| $B05C | a9 2a | b_B05Clda#$2a; x-ref: $B051 |
| $B05E | 9d 4f 03 | staentity_headings,x |
| $B061 | 9d 13 1d | staentity_sprite_frames,x |
| $B064 | bd a2 03 | ldaentity_velocity_indices,x |
| $B067 | c9 82 | cmp#$82 |
| $B069 | b0 06 | bcsb_B071 |
| $B06B | 20 a1 b1 | jsrerase_enemy_body |
| $B06E | 4c 74 b0 | jmpj_B074 |
| $B071 | 20 7a b1 | b_B071jsrerase_enemy_wings; x-ref: $B069 |
| $B074 | a4 28 | j_B074ldyzp_cur_entity_idx; x-ref: $B06E |
| $B076 | b9 3c 03 | ldaentity_types,y |
| $B079 | a9 ff | lda#$ff |
| $B07B | 99 a2 03 | staentity_velocity_indices,y |
| $B07E | 99 3c 03 | staentity_types,y |
| $B081 | 60 | rts |
| ; Signed X pixel offsets (relative to enemy center) for the 4 wing-tip pixels. |
| ; Indexed 0-3. Values: $FC=-4, $04=+4. |
| ; Layout (X,Y pairs with enemy_wing_dy_tbl): |
| ; 0: (-4,-4) top-left |
| ; 1: (+4,-4) top-right |
| ; 2: (-4,+4) bottom-left |
| ; 3: (+4,+4) bottom-right |
| ; Forms a 4-corner diamond shape at ±4 pixels. Used when enemy state >= $82. |
| $B082 | | enemy_wing_dx_tbl.byte$fc, $04, $fc, $04; x-ref: $B022, $B186 |
| ; Signed Y pixel offsets (relative to enemy center) for the 4 wing-tip pixels. |
| ; Indexed 0-3. Values: $FC=-4, $04=+4. |
| ; Paired with enemy_wing_dx_tbl. See that table for full (X,Y) layout. |
| $B086 | | enemy_wing_dy_tbl.byte$fc, $fc, $04, $04; x-ref: $B02B, $B18F |
| ; Signed X pixel offsets (relative to enemy center) for the 9-pixel enemy body. |
| ; Indexed 0-8. Values: $F8=-8, $00=0, $08=+8. |
| ; Layout (X,Y pairs with enemy_body_dy_tbl) — a 3x3 grid spaced 8 pixels apart: |
| ; 0: (-8,-8) 1: (0,-8) 2: (+8,-8) <- top row |
| ; 3: (-8, 0) 4: (0, 0) 5: (+8, 0) <- middle row |
| ; 6: (-8,+8) 7: (0,+8) 8: (+8,+8) <- bottom row |
| ; Used for the main enemy body (state < $82). |
| $B08A | | enemy_body_dx_tbl.byte$f8, $00, $08, $f8, $00, $08, $f8, $00; x-ref: $AFE9, $B1AD |
| $B092 | | .byte$08 |
| ; Signed Y pixel offsets (relative to enemy center) for the 9-pixel enemy body. |
| ; Indexed 0-8. Values: $F8=-8, $00=0, $08=+8. |
| ; Paired with enemy_body_dx_tbl. See that table for full 3x3 grid layout. |
| $B093 | | enemy_body_dy_tbl.byte$f8, $f8, $f8, $00, $00, $00, $08, $08; x-ref: $AFF2, $B1B6 |
| $B09B | | .byte$08 |
| | .encode |
| | .enc"screen" |
| $B09C | | f_B09C.text"-./01234"; x-ref: $B03F |
| $B0A4 | | f_B0A4.text"56789:;<=>?`abcdef"; x-ref: $B008 |
| | .endencode |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles a collision hit on entity slot X. Dispatches on entity type (f033C,x): |
| ; |
| ; Y = 0 -> Player ship was hit: |
| ; - Sets f03A2,x=$80 (inactive/exploding), f03B5,x=$06 (anim frames) |
| ; - Decrements player_lives, sets respawn timer a4D=$3C |
| ; - Triggers death audio/visual effect via SEI-protected register writes |
| ; - Sets bit 0 of a4E (death flag) |
| ; |
| ; Y = 5 -> Large enemy hit: |
| ; - Triggers fanfare sound (a48=1, a4C=1, a44=7) |
| ; - Falls through to score/explosion logic |
| ; |
| ; Y < 5 -> Standard enemy hit: |
| ; - Decrements a3D (remaining enemies on wave) |
| ; - Triggers hit sound (a46=a4A=$0A) |
| ; |
| ; Y > 5 -> Obstacle hit: |
| ; - Triggers alternate sound (a46=a4A=$17) |
| ; |
| ; (Y != 0 common epilogue): |
| ; - Sets f03B5,x=$02 (explosion timer), f03A2,x=$82 (exploding state) |
| ; - Clears f002E,y (per-type counter for this entity kind) |
| ; - Calls add_score(Y) and redraws player score HUD |
| ; |
| ; Inputs: X = entity slot index (0-$12) |
| ; f033C,x = entity type / hit classification (0=player, 1-9=enemy types) |
| ; Outputs: player_lives decremented (if player hit); aF7/aF8/aF9 score updated |
| ; Side Effects: Entity state set to exploding; audio registers written under SEI |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B0B6 | a9 00 | handle_entity_hitlda#$00; clear entity collision state and pixel-overlap flag ; x-ref: $A565, $A570, $A651, $A656 |
| $B0B8 | 9d c8 03 | staentity_vx,x |
| $B0BB | 9d 00 1d | staentity_vy,x |
| $B0BE | bd 3c 03 | ldaentity_types,x |
| $B0C1 | a8 | tay |
| $B0C2 | f0 3c | beqb_B100; Y = entity type: 0=player, else enemy/obstacle |
| $B0C4 | c9 05 | cmp#$05; Y=5 -> large enemy: fanfare sound |
| $B0C6 | d0 0c | bneb_B0D4 |
| $B0C8 | a9 01 | lda#$01 |
| $B0CA | 85 48 | stazp_snd_noise_seq_idx |
| $B0CC | 85 4c | stazp_snd_noise_step |
| $B0CE | a9 07 | lda#$07 |
| $B0D0 | 85 44 | stazp_snd_noise_dur |
| $B0D2 | d0 15 | bneb_B0E9 |
| $B0D4 | 90 04 | b_B0D4bccb_B0DA; Y < 5: decrement remaining enemy count ; x-ref: $B0C6 |
| $B0D6 | a9 17 | lda#$17 |
| $B0D8 | d0 05 | bneb_B0DF |
| $B0DA | c6 3d | b_B0DAdeczp_max_enemy_count; x-ref: $B0D4 |
| $B0DC | 78 | sei |
| $B0DD | a9 0a | lda#$0a |
| $B0DF | 78 | b_B0DFsei; x-ref: $B0D8 |
| $B0E0 | 85 46 | stazp_snd_alto_seq_idx |
| $B0E2 | 85 4a | stazp_snd_alto_step |
| $B0E4 | a9 01 | lda#$01 |
| $B0E6 | 85 42 | stazp_snd_alto_dur |
| $B0E8 | 58 | cli |
| $B0E9 | a9 02 | b_B0E9lda#$02; x-ref: $B0D2 |
| $B0EB | 9d b5 03 | staentity_anim_timers,x |
| $B0EE | a9 82 | lda#$82 |
| $B0F0 | 9d a2 03 | staentity_velocity_indices,x; set entity to exploding state (still visible) |
| $B0F3 | a9 00 | lda#$00 |
| $B0F5 | 99 2e 00 | sta@w zp_entity_type_to_slot,y |
| $B0F8 | 98 | tya |
| $B0F9 | 20 2d b1 | jsradd_score; award score for this entity type (Y = type index) |
| $B0FC | 20 ad ac | jsrdraw_player_score |
| $B0FF | 60 | rts |
| $B100 | a9 80 | b_B100lda#$80; --- player ship hit branch --- ; x-ref: $B0C2 |
| $B102 | 9d a2 03 | staentity_velocity_indices,x |
| $B105 | a9 06 | lda#$06 |
| $B107 | 9d b5 03 | staentity_anim_timers,x |
| $B10A | c6 1f | deczp_player_lives; decrement lives |
| $B10C | a9 3c | lda#$3c |
| $B10E | 85 4d | stazp_snd_volume_state; invincibility/respawn timer ($3C = 60 frames) |
| $B110 | a5 4e | ldazp_game_phase |
| $B112 | 09 01 | ora#$01 |
| $B114 | 85 4e | stazp_game_phase; Set death-countdown phase (bit 0) |
| $B116 | 78 | sei |
| $B117 | a9 0c | lda#$0c |
| $B119 | 85 48 | stazp_snd_noise_seq_idx |
| $B11B | 85 4c | stazp_snd_noise_step |
| $B11D | a9 04 | lda#$04 |
| $B11F | 85 44 | stazp_snd_noise_dur |
| $B121 | a9 01 | lda#$01 |
| $B123 | 85 45 | stazp_snd_bass_seq_idx |
| $B125 | 85 49 | stazp_snd_bass_step |
| $B127 | a9 0c | lda#$0c |
| $B129 | 85 41 | stazp_snd_bass_dur |
| $B12B | 58 | cli |
| $B12C | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Adds a BCD score value to the player's 3-byte score (aF7/aF8/aF9). |
| ; The A register is an index into the score table at fB16A; each entry is a |
| ; 2-byte packed BCD value. After adding, checks if the score has crossed the |
| ; extra-life threshold ($4000). If so, and if the bonus life flag (a54) is |
| ; clear, grants an extra life, triggers the fanfare, and updates the HUD. |
| ; |
| ; Inputs: A = score table index (0-7) |
| ; Outputs: aF7/aF8/aF9 = updated 3-byte packed BCD score |
| ; Side Effects: May increment player_lives and call draw_lives_display; |
| ; sets a54=1 to prevent awarding more than one extra life |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B12D | 78 | add_scoresei; disable IRQs before score update ; x-ref: $B0F9, $B3B7 |
| $B12E | 0a | asla; A*2 = byte offset into 2-byte BCD table entries |
| $B12F | a8 | tay; index into table |
| $B130 | f8 | sed; enable BCD (Decimal) mode for BCD addition |
| $B131 | b9 6a b1 | ldascore_table_lo,y; load score low byte from table |
| $B134 | 65 f7 | adczp_score_lo; add to score byte 0 (ones/tens) |
| $B136 | 85 f7 | stazp_score_lo; store score byte 0 |
| $B138 | b9 6b b1 | ldascore_table_hi,y; load score high byte from table |
| $B13B | 65 f8 | adczp_score_mid; add to score byte 1 (hundreds/thousands) |
| $B13D | 85 f8 | stazp_score_mid; store score byte 1 |
| $B13F | a5 f9 | ldazp_score_hi; propagate carry into score byte 2 (ten-thousands) |
| $B141 | 69 00 | adc#$00 |
| $B143 | 85 f9 | stazp_score_hi; store score byte 2 |
| $B145 | d8 | cld; exit BCD mode |
| $B146 | 58 | cli; re-enable IRQs |
| $B147 | a5 54 | ldazp_extra_life_awarded; check if extra life already awarded |
| $B149 | d0 1e | bner_B169; yes — skip extra-life check |
| $B14B | a5 f8 | ldazp_score_mid; check score high byte >= $40 (i.e. score >= 4000) |
| $B14D | c9 40 | cmp#$40 |
| $B14F | 90 18 | bccr_B169; score < 4000 — no extra life yet |
| $B151 | 78 | sei; disable IRQs to safely update sprite/sound registers |
| $B152 | a9 11 | lda#$11 |
| $B154 | 85 47 | stazp_snd_soprano_seq_idx |
| $B156 | 85 4b | stazp_snd_soprano_step |
| $B158 | a9 03 | lda#$03 |
| $B15A | 85 43 | stazp_snd_soprano_dur |
| $B15C | 58 | cli |
| $B15D | a9 01 | lda#$01 |
| $B15F | 85 54 | stazp_extra_life_awarded; Set flag: extra life already granted |
| $B161 | e6 1f | inczp_player_lives; grant extra life |
| $B163 | 20 4a ad | jsrdraw_lives_display; update lives HUD display |
| $B166 | 8d 6d a4 | stapatch_input_dispatch_hi |
| $B169 | 60 | r_B169rts; x-ref: $B149, $B14F |
| score_table_hi =*+$01 ; x-ref: $B138 |
| ; 2-byte packed BCD score values indexed by enemy type / kill event |
| ; [0] $0000 = 0 pts (no score) |
| ; [1] $0250 = 250 pts |
| ; [2] $0150 = 150 pts |
| ; [3] $0150 = 150 pts |
| ; [4] $0100 = 100 pts |
| ; [5] $0050 = 50 pts |
| ; [6] $0035 = 35 pts |
| ; [7] $0500 = 500 pts (bonus) |
| $B16A | | score_table_lo.word$0000, $0250, $0150, $0150, $0100; x-ref: $B131 |
| $B174 | | .word$0050, $0035, $0500 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Erases the 4-pixel enemy wing-tip pattern from the bitmap. Iterates indices 3..0, |
| ; computing each pixel position as: |
| ; X = f0362[a28] + enemy_wing_dx_tbl[i] |
| ; Y = f0375[a28] + enemy_wing_dy_tbl[i] |
| ; and calling erase_sprite_with_boundary_check for each. |
| ; Used when entity state (f03A2) >= $82 (exploding / wing-tip visible state). |
| ; For the normal body state, erase_enemy_body is used instead. |
| ; |
| ; Inputs: a28 = entity slot index |
| ; Outputs: None |
| ; Side Effects: Clears 4 pixels from the bitmap at the enemy's wing-tip positions |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B17A | a0 03 | erase_enemy_wingsldy#$03; x-ref: $B017, $B071 |
| $B17C | 84 1a | styzp_marker_idx |
| $B17E | a6 28 | b_B17Eldxzp_cur_entity_idx; x-ref: $B19E |
| $B180 | a4 1a | ldyzp_marker_idx |
| $B182 | bd 62 03 | ldaentity_x_coords,x |
| $B185 | 18 | clc |
| $B186 | 79 82 b0 | adcenemy_wing_dx_tbl,y |
| $B189 | 85 a3 | stazp_pos_x |
| $B18B | bd 75 03 | ldaentity_y_coords,x |
| $B18E | 18 | clc |
| $B18F | 79 86 b0 | adcenemy_wing_dy_tbl,y |
| $B192 | 85 a4 | stazp_pos_y |
| $B194 | a9 29 | lda#$29 |
| $B196 | 20 9b ab | jsrcalc_sprite_ptr |
| $B199 | 20 47 ab | jsrerase_sprite_with_boundary_check |
| $B19C | c6 1a | deczp_marker_idx |
| $B19E | 10 de | bplb_B17E |
| $B1A0 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Erases the 9-pixel enemy body from the bitmap. Iterates indices 8..0, |
| ; computing each pixel position as: |
| ; X = f0362[a28] + enemy_body_dx_tbl[i] |
| ; Y = f0375[a28] + enemy_body_dy_tbl[i] |
| ; and calling erase_sprite_with_boundary_check for each. |
| ; This is the erase counterpart to the draw loop in sAFCC. |
| ; Only called when entity state (f03A2) < $82 (body-visible, not exploding). |
| ; For the exploding (wing-tip) state, sB17A is used instead. |
| ; |
| ; Inputs: a28 = entity slot index |
| ; Outputs: None |
| ; Side Effects: Clears 9 pixels from the bitmap at the enemy's 3x3 body positions |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B1A1 | a0 08 | erase_enemy_bodyldy#$08; loop 8..0 over 9 body pixels ; x-ref: $AFDE, $B06B |
| $B1A3 | 84 1a | styzp_marker_idx |
| $B1A5 | a6 28 | b_B1A5ldxzp_cur_entity_idx; x-ref: $B1C5 |
| $B1A7 | a4 1a | ldyzp_marker_idx |
| $B1A9 | bd 62 03 | ldaentity_x_coords,x |
| $B1AC | 18 | clc |
| $B1AD | 79 8a b0 | adcenemy_body_dx_tbl,y |
| $B1B0 | 85 a3 | stazp_pos_x |
| $B1B2 | bd 75 03 | ldaentity_y_coords,x |
| $B1B5 | 18 | clc |
| $B1B6 | 79 93 b0 | adcenemy_body_dy_tbl,y; pixel Y = entity_y + body_dy[i] |
| $B1B9 | 85 a4 | stazp_pos_y |
| $B1BB | a9 29 | lda#$29; glyph $29 = single-pixel dot shape |
| $B1BD | 20 9b ab | jsrcalc_sprite_ptr |
| $B1C0 | 20 47 ab | jsrerase_sprite_with_boundary_check |
| $B1C3 | c6 1a | deczp_marker_idx |
| $B1C5 | 10 de | bplb_B1A5 |
| $B1C7 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Title screen / Attract mode sequence. |
| ; |
| ; Inputs: None |
| ; Outputs: Returns when the player presses Start (aB0 flag goes negative) |
| ; Side Effects: Clears screen, displays cycling title screens and graphics, |
| ; sets colors, waits for user input. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B1C8 | 20 29 a4 | attract_modejsrclear_char_ram; clear screen / display RAM ; x-ref: $A029, $B287 |
| $B1CB | a0 28 | ldy#$28; setup title screen colors |
| $B1CD | a9 02 | b_B1CDlda#VicColors.RED; x-ref: $B1D8 |
| $B1CF | 99 3c 96 | staCOLOR_RAM_R2C16,y |
| $B1D2 | a9 07 | lda#VicColors.YELLOW |
| $B1D4 | 99 64 96 | staCOLOR_RAM_R4C12,y |
| $B1D7 | 88 | dey |
| $B1D8 | 10 f3 | bplb_B1CD |
| $B1DA | a2 86 | ldx#<gfx_attract_slide_1; gfx_attract_slide_1 ($BB86): OMEGA RACE title logo + copyright text |
| $B1DC | a0 bb | ldy#>gfx_attract_slide_1 |
| $B1DE | a9 01 | lda#$01 |
| $B1E0 | 85 ae | stazp_step_x |
| $B1E2 | 85 af | stazp_step_y |
| $B1E4 | 20 cc b2 | jsrdraw_graphic_string; draw title logo with red/yellow gradient |
| $B1E7 | 20 b4 b2 | jsrattract_mode_delay; wait for delay |
| $B1EA | 24 b0 | bitzp_joy_fire; check if start button pressed |
| $B1EC | 10 01 | bplb_B1EF |
| $B1EE | 60 | rts |
| $B1EF | a5 62 | b_B1EFldazp_show_score_table; x-ref: $B1EC |
| $B1F1 | f0 18 | beqb_B20B |
| $B1F3 | 20 52 a4 | jsrfill_color_ram |
| $B1F6 | 20 29 a4 | jsrclear_char_ram; clear screen for next graphic |
| $B1F9 | a2 28 | ldx#<gfx_attract_slide_2; gfx_attract_slide_2 ($B728): scoring table (enemy types + point values) |
| $B1FB | a0 b7 | ldy#>gfx_attract_slide_2 |
| $B1FD | a9 02 | lda#$02 |
| $B1FF | 85 ae | stazp_step_x |
| $B201 | a9 ff | lda#$ff |
| $B203 | 85 af | stazp_step_y |
| $B205 | 20 cc b2 | jsrdraw_graphic_string; draw scoring table (conditional: only when a62 != 0) |
| $B208 | 20 b4 b2 | jsrattract_mode_delay |
| $B20B | 20 52 a4 | b_B20Bjsrfill_color_ram; x-ref: $B1F1 |
| $B20E | 20 29 a4 | jsrclear_char_ram |
| $B211 | a2 10 | ldx#<gfx_attract_slide_3; gfx_attract_slide_3 ($BC10): copyright/logo screen |
| $B213 | a0 bc | ldy#>gfx_attract_slide_3 |
| $B215 | a9 01 | lda#$01 |
| $B217 | 85 ae | stazp_step_x |
| $B219 | 85 af | stazp_step_y |
| $B21B | 20 cc b2 | jsrdraw_graphic_string; draw copyright/logo screen |
| $B21E | 24 b0 | bitzp_joy_fire |
| $B220 | 30 64 | bmir_B286 |
| $B222 | 20 8a b2 | jsrattract_color_cycle |
| $B225 | 24 b0 | bitzp_joy_fire |
| $B227 | 30 5d | bmir_B286 |
| $B229 | 20 29 a4 | jsrclear_char_ram |
| $B22C | 20 52 a4 | jsrfill_color_ram |
| $B22F | 20 ce ab | jsrdraw_markers |
| $B232 | a2 67 | ldx#<gfx_story_slide_1; gfx_story_slide_1 ($BC67): 'In the year 2003, the Omegan System...' |
| $B234 | a0 bc | ldy#>gfx_story_slide_1 |
| $B236 | a9 01 | lda#$01 |
| $B238 | 85 ae | stazp_step_x |
| $B23A | a9 ff | lda#$ff |
| $B23C | 85 af | stazp_step_y |
| $B23E | 20 cc b2 | jsrdraw_graphic_string; draw story slide 1: 'In the year 2003...' (instant display, no typing delay) |
| $B241 | 24 b0 | bitzp_joy_fire |
| $B243 | 30 41 | bmir_B286 |
| $B245 | 20 b4 b2 | jsrattract_mode_delay |
| $B248 | 24 b0 | bitzp_joy_fire |
| $B24A | 30 3a | bmir_B286 |
| $B24C | 20 29 a4 | jsrclear_char_ram |
| $B24F | 20 ce ab | jsrdraw_markers |
| $B252 | a2 a8 | ldx#<attract_story_slide_2; next story slide ($BDA8) |
| $B254 | a0 bd | ldy#>attract_story_slide_2 |
| $B256 | a9 01 | lda#$01 |
| $B258 | 85 ae | stazp_step_x |
| $B25A | 85 af | stazp_step_y |
| $B25C | 20 cc b2 | jsrdraw_graphic_string; draw story slide 2 |
| $B25F | 20 23 b3 | jsrattract_ship_animation |
| $B262 | 24 b0 | bitzp_joy_fire |
| $B264 | 30 20 | bmir_B286 |
| $B266 | 20 29 a4 | jsrclear_char_ram |
| $B269 | 20 ce ab | jsrdraw_markers |
| $B26C | a2 0a | ldx#<attract_story_slide_3 |
| $B26E | a0 be | ldy#>attract_story_slide_3 |
| $B270 | a9 01 | lda#$01 |
| $B272 | 85 ae | stazp_step_x |
| $B274 | a9 ff | lda#$ff |
| $B276 | 85 af | stazp_step_y |
| $B278 | 20 cc b2 | jsrdraw_graphic_string |
| $B27B | 24 b0 | bitzp_joy_fire |
| $B27D | 30 07 | bmir_B286 |
| $B27F | 20 b4 b2 | jsrattract_mode_delay |
| $B282 | 24 b0 | bitzp_joy_fire |
| $B284 | 10 01 | bplb_B287 |
| $B286 | 60 | r_B286rts; x-ref: $B220, $B227, $B243, $B24A, $B264, $B27D |
| $B287 | 4c c8 b1 | b_B287jmpattract_mode; x-ref: $B284 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Attract mode color cycling animation. Loops $19 (25) times, each iteration |
| ; incrementing aAE and writing (aAE & $07) to 4 fixed color RAM positions |
| ; ($9603, $962B, $963F, $9667), cycling through VIC-20's 8 colors (0-7). |
| ; After each color update, calls the attract_mode_delay inner loop (sB2B8) |
| ; to pace the animation. Aborts early if the start button is pressed (aB0 < 0). |
| ; Called once from attract_mode after displaying the copyright/logo screen. |
| ; |
| ; Inputs: None (aAE used as internal counter, initialized to 0) |
| ; Outputs: None |
| ; Side Effects: Writes to color RAM at $9603, $962B, $963F, $9667; |
| ; returns immediately if aB0 bit 7 set (start pressed) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B28A | a9 19 | attract_color_cyclelda#$19; loop counter: 25 iterations ; x-ref: $B222 |
| $B28C | 85 b3 | stazp_pixel_mask |
| $B28E | a9 00 | lda#$00 |
| $B290 | 85 ae | stazp_step_x |
| $B292 | e6 ae | b_B292inczp_step_x; advance color index each frame ; x-ref: $B2B1 |
| $B294 | a5 ae | ldazp_step_x |
| $B296 | 29 07 | and#$07; mask to 3 bits: cycles colors 0-7 |
| $B298 | 8d 03 96 | staCOLOR_RAM_R0C3; write color to 4 logo positions in color RAM |
| $B29B | 8d 2b 96 | staCOLOR_RAM_R1C21 |
| $B29E | 8d 3f 96 | staCOLOR_RAM_R2C19 |
| $B2A1 | 8d 67 96 | staCOLOR_RAM_R4C15 |
| $B2A4 | a9 06 | lda#$06 |
| $B2A6 | 85 1a | stazp_marker_idx |
| $B2A8 | 20 b8 b2 | jsrattract_mode_delay_inner; pace animation with delay; also polls for start button |
| $B2AB | 24 b0 | bitzp_joy_fire; abort if start pressed (bit 7 of aB0) |
| $B2AD | 30 04 | bmir_B2B3 |
| $B2AF | c6 b3 | deczp_pixel_mask |
| $B2B1 | d0 df | bneb_B292 |
| $B2B3 | 60 | r_B2B3rts; x-ref: $B2AD |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Delay loop used during the attract mode sequence. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Delays execution for a few seconds by looping 40 x 256 times. |
| ; Continually polls for user input (via scan_input_for_start) and |
| ; aborts the delay instantly if the start button is pressed. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B2B4 | a9 28 | attract_mode_delaylda#$28; setup outer loop counter (40) ; x-ref: $B1E7, $B208, $B245, $B27F |
| $B2B6 | 85 1a | stazp_marker_idx |
| attract_mode_delay_inner |
| $B2B8 | a9 ff | lda#$ff; Setup inner loop counter (255) ; x-ref: $B2A8, $B2C9 |
| $B2BA | 85 3c | stazp_attract_delay_ctr |
| $B2BC | 20 d2 b3 | b_B2BCjsrscan_input_for_start; Poll joysticks and keyboard ; x-ref: $B2C5 |
| $B2BF | 24 b0 | bitzp_joy_fire; Check if start button pressed |
| $B2C1 | 30 08 | bmir_B2CB; Abort delay if pressed |
| $B2C3 | c6 3c | deczp_attract_delay_ctr; Decrement inner counter |
| $B2C5 | d0 f5 | bneb_B2BC |
| $B2C7 | c6 1a | deczp_marker_idx; Decrement outer counter |
| $B2C9 | d0 ed | bneattract_mode_delay_inner |
| $B2CB | 60 | r_B2CBrts; x-ref: $B2C1 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draws a sequence of characters/graphics to the screen with a typing effect. |
| ; |
| ; Inputs: X (pointer low), Y (pointer high) to graphic data structure |
| ; aAE (delay outer loop), aAF (delay inner loop) |
| ; Outputs: None |
| ; Side Effects: Draws to screen RAM. Can be aborted instantly if the user |
| ; presses the start button (aB0 flag). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B2CC | 86 2c | draw_graphic_stringstxzp_ptr_gfx_str; store pointer low ; x-ref: $A0C5, $B1E4, $B205, $B21B, $B23E, $B25C, $B278, $B3AF |
| $B2CE | 84 2d | styzp_ptr_gfx_str_hi; store pointer high |
| $B2D0 | a0 00 | b_B2D0ldy#$00; x-ref: $B2EC, $B2F0 |
| $B2D2 | b1 2c | lda(zp_ptr_gfx_str),y; read base X coordinate |
| $B2D4 | 85 a3 | stazp_pos_x |
| $B2D6 | c8 | iny |
| $B2D7 | b1 2c | lda(zp_ptr_gfx_str),y; read base Y coordinate |
| $B2D9 | 85 a4 | stazp_pos_y |
| $B2DB | c8 | iny |
| $B2DC | b1 2c | lda(zp_ptr_gfx_str),y; read X-coordinate step |
| $B2DE | 85 b3 | stazp_pixel_mask |
| $B2E0 | c8 | j_B2E0iny; x-ref: $B31F |
| $B2E1 | b1 2c | lda(zp_ptr_gfx_str),y; read next character |
| $B2E3 | d0 0e | bneb_B2F3; if 00, end of segment |
| $B2E5 | c8 | iny |
| $B2E6 | 98 | tya |
| $B2E7 | 18 | clc |
| $B2E8 | 65 2c | adczp_ptr_gfx_str |
| $B2EA | 85 2c | stazp_ptr_gfx_str |
| $B2EC | 90 e2 | bccb_B2D0 |
| $B2EE | e6 2d | inczp_ptr_gfx_str_hi |
| $B2F0 | 4c d0 b2 | jmpb_B2D0 |
| $B2F3 | c9 ff | b_B2F3cmp#$ff; if FF, end of all data ; x-ref: $B2E3 |
| $B2F5 | f0 2b | beqr_B322 |
| $B2F7 | 84 b4 | styzp_loop_idx |
| $B2F9 | 20 9b ab | jsrcalc_sprite_ptr |
| $B2FC | 20 ff aa | jsrdraw_sprite_or_collision; draw character to screen |
| $B2FF | a5 ae | ldazp_step_x |
| $B301 | 85 1a | stazp_marker_idx |
| $B303 | a5 af | b_B303ldazp_step_y; x-ref: $B314 |
| $B305 | 85 3c | stazp_attract_delay_ctr |
| $B307 | 20 d2 b3 | b_B307jsrscan_input_for_start; x-ref: $B310 |
| $B30A | 24 b0 | bitzp_joy_fire; abort if start pressed |
| $B30C | 30 14 | bmir_B322 |
| $B30E | c6 3c | deczp_attract_delay_ctr |
| $B310 | d0 f5 | bneb_B307 |
| $B312 | c6 1a | deczp_marker_idx |
| $B314 | d0 ed | bneb_B303 |
| $B316 | a4 b4 | ldyzp_loop_idx |
| $B318 | a5 a3 | ldazp_pos_x |
| $B31A | 18 | clc |
| $B31B | 65 b3 | adczp_pixel_mask; advance X by step |
| $B31D | 85 a3 | stazp_pos_x |
| $B31F | 4c e0 b2 | jmpj_B2E0 |
| $B322 | 60 | r_B322rts; x-ref: $B2F5, $B30C |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Attract mode ship animation. Cycles through sprite frames $20, $21, $22 |
| ; at a fixed position (X=$10, Y=$90) for 100 frames, with a small inter-frame |
| ; delay (~$FF * $20 iterations). Each frame: |
| ; 1. Erases previous sprite frame at (aA3, aA4). |
| ; 2. Advances sprite index aB3 ($20->$21->$22->$20 wrap at $23). |
| ; 3. Calls calc_sprite_ptr and draw_sprite_or_collision. |
| ; 4. Polls scan_input_for_start; exits immediately if start is pressed. |
| ; Called from attract_mode after story slide 2, before the next slide. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Bitmap updated (animated sprite drawn); aborts if aB0 bit 7 set |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| attract_ship_animation |
| $B323 | a9 20 | lda#$20; start sprite index: frame 0 of 3-frame animation ; x-ref: $B25F |
| $B325 | 85 b3 | stazp_pixel_mask |
| $B327 | 20 9b ab | jsrcalc_sprite_ptr |
| $B32A | a9 10 | lda#$10; animation position: X=$10, Y=$90 |
| $B32C | 85 a3 | stazp_pos_x |
| $B32E | a9 90 | lda#$90 |
| $B330 | 85 a4 | stazp_pos_y |
| $B332 | a9 64 | lda#$64 |
| $B334 | 85 b4 | stazp_loop_idx; outer loop: 100 animation frames |
| $B336 | a9 ff | b_B336lda#$ff; inter-frame delay: ~$FF * $20 iterations ; x-ref: $B364 |
| $B338 | 85 1a | stazp_marker_idx |
| $B33A | a9 20 | b_B33Alda#$20; x-ref: $B344 |
| $B33C | 85 3c | stazp_attract_delay_ctr |
| $B33E | c6 3c | b_B33Edeczp_attract_delay_ctr; x-ref: $B340 |
| $B340 | d0 fc | bneb_B33E |
| $B342 | c6 1a | deczp_marker_idx |
| $B344 | d0 f4 | bneb_B33A |
| $B346 | 20 41 ab | jsrerase_sprite; erase previous frame |
| $B349 | e6 b3 | inczp_pixel_mask |
| $B34B | a5 b3 | ldazp_pixel_mask |
| $B34D | c9 23 | cmp#$23; wrap sprite index: $20, $21, $22 -> back to $20 |
| $B34F | d0 04 | bneb_B355 |
| $B351 | a9 20 | lda#$20 |
| $B353 | 85 b3 | stazp_pixel_mask |
| $B355 | 20 9b ab | b_B355jsrcalc_sprite_ptr; x-ref: $B34F |
| $B358 | 20 ff aa | jsrdraw_sprite_or_collision |
| $B35B | 20 d2 b3 | jsrscan_input_for_start; draw next animation frame |
| $B35E | 24 b0 | bitzp_joy_fire; abort animation if start pressed |
| $B360 | 30 04 | bmir_B366 |
| $B362 | c6 b4 | deczp_loop_idx |
| $B364 | d0 d0 | bneb_B336 |
| $B366 | 60 | r_B366rts; x-ref: $B360 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Phase advancement bonus screen. Called every 4th level before incrementing |
| ; the difficulty phase (a21). Clears the screen, plays a sound fanfare, draws |
| ; the current phase graphic indexed by a21, displays a congratulatory string, |
| ; waits ~1 second, then awards 7 bonus points to the player score. |
| ; |
| ; Inputs: a21 (current difficulty phase, selects which graphic to draw) |
| ; Outputs: None |
| ; Side Effects: Clears screen; triggers sound; draws phase graphic and text; |
| ; delays ~1 second; adds 7 points to player score (sB12D). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| show_phase_bonus_screen |
| $B367 | 20 29 a4 | jsrclear_char_ram; clear screen ; x-ref: $A1C7 |
| $B36A | 78 | sei |
| $B36B | a9 11 | lda#$11; trigger sound fanfare (channel indices/durations) |
| $B36D | 85 47 | stazp_snd_soprano_seq_idx |
| $B36F | 85 4b | stazp_snd_soprano_step |
| $B371 | a9 03 | lda#$03 |
| $B373 | 85 43 | stazp_snd_soprano_dur |
| $B375 | 58 | cli |
| $B376 | a5 21 | ldazp_current_phase; get low nibble of phase as sprite index |
| $B378 | 29 0f | and#$0f |
| $B37A | 18 | clc |
| $B37B | 69 d4 | adc#$d4; offset into graphic table ($D4 base) |
| $B37D | 20 9b ab | jsrcalc_sprite_ptr; compute bitmap address for phase graphic |
| $B380 | a9 80 | lda#$80; X position = $80, Y = $1C for primary graphic |
| $B382 | 85 a3 | stazp_pos_x |
| $B384 | a9 1c | lda#$1c |
| $B386 | 85 a4 | stazp_pos_y |
| $B388 | 20 ff aa | jsrdraw_sprite_or_collision; draw primary phase graphic |
| $B38B | a5 21 | ldazp_current_phase |
| $B38D | 29 f0 | and#$f0; check high nibble — draw second graphic if nonzero |
| $B38F | f0 14 | beqb_B3A5 |
| $B391 | 4a | lsra |
| $B392 | 4a | lsra |
| $B393 | 4a | lsra |
| $B394 | 4a | lsra |
| $B395 | 69 d4 | adc#$d4 |
| $B397 | 20 9b ab | jsrcalc_sprite_ptr |
| $B39A | a9 78 | lda#$78; X position = $78 for secondary graphic |
| $B39C | 85 a3 | stazp_pos_x |
| $B39E | a9 1c | lda#$1c |
| $B3A0 | 85 a4 | stazp_pos_y |
| $B3A2 | 20 ff aa | jsrdraw_sprite_or_collision; draw secondary phase graphic |
| $B3A5 | a2 a1 | b_B3A5ldx#<phase_bonus_congrats_text; x-ref: $B38F |
| $B3A7 | a0 be | ldy#>phase_bonus_congrats_text |
| $B3A9 | a9 01 | lda#$01 |
| $B3AB | 85 ae | stazp_step_x |
| $B3AD | 85 af | stazp_step_y |
| $B3AF | 20 cc b2 | jsrdraw_graphic_string; draw congratulatory text string |
| $B3B2 | 20 bb b3 | jsrdelay_1_second; wait ~1 second |
| $B3B5 | a9 07 | lda#$07; award 7 bonus points |
| $B3B7 | 20 2d b1 | jsradd_score |
| $B3BA | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Delay loop for approximately 1 second. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Wastes exactly 1 million CPU cycles (~1 second at 1MHz) using |
| ; nested loops and dummy writes to ROM addresses. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B3BB | a9 ff | delay_1_secondlda#$ff; setup outer loop counter (256) ; x-ref: $A0C8, $B3B2 |
| $B3BD | 85 1a | stazp_marker_idx |
| $B3BF | a9 ff | b_B3BFlda#$ff; setup inner loop counter (256) ; x-ref: $B3CF |
| $B3C1 | 85 3c | stazp_attract_delay_ctr |
| $B3C3 | c6 3c | b_B3C3deczp_attract_delay_ctr; 5 cycles ; x-ref: $B3CB |
| $B3C5 | 8d ad a1 | stainit_new_game; 4 cycles (dummy ROM write) |
| $B3C8 | 8d bd a1 | stainit_new_game_rts; 4 cycles (dummy ROM write) |
| $B3CB | d0 f6 | bneb_B3C3; 3 cycles (branch taken) = 16 cycles loop |
| $B3CD | c6 1a | deczp_marker_idx |
| $B3CF | d0 ee | bneb_B3BF |
| $B3D1 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Scans joysticks and keyboard for a "Game Start" input during attract mode. |
| ; |
| ; Inputs: None |
| ; Outputs: Sets aB0 to $80 if start is triggered. |
| ; Side Effects: Calls KERNAL keyboard and custom joystick scan routines. |
| ; Depending on the input (F-keys or joystick buttons), it configures |
| ; the selected game mode and player sprite pointers. Also contains a |
| ; hidden cheat/easter-egg check for modifier keys. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B3D2 | 20 9f ff | scan_input_for_startjsrKERNAL_CSCNKEY; scan keyboard via KERNAL ; x-ref: $B2BC, $B307, $B35B |
| $B3D5 | 20 a6 a8 | jsrread_joystick; scan joystick 1 |
| $B3D8 | a5 b0 | ldazp_joy_fire; check if joystick 1 triggered start |
| $B3DA | d0 2b | bneoption_joystick |
| $B3DC | 20 01 a9 | jsrread_paddle_input; scan joystick 2 |
| $B3DF | a5 b0 | ldazp_joy_fire; check if joystick 2 triggered start |
| $B3E1 | d0 14 | bneb_B3F7 |
| $B3E3 | 20 e4 ff | jsrKERNAL_CGETL; get character from keyboard buffer |
| $B3E6 | aa | tax |
| $B3E7 | c9 85 | cmp#PetsciiShifted.KEY_F1; check for F1 |
| $B3E9 | f0 1c | beqoption_joystick |
| $B3EB | c9 89 | cmp#PetsciiShifted.KEY_F2; check for F2 |
| $B3ED | f0 18 | beqoption_joystick |
| $B3EF | c9 86 | cmp#PetsciiShifted.KEY_F3; check for F3 |
| $B3F1 | f0 04 | beqb_B3F7 |
| $B3F3 | c9 8a | cmp#PetsciiShifted.KEY_F4; check for F4 |
| $B3F5 | d0 2a | bneb_B421 |
| $B3F7 | a9 01 | b_B3F7lda#<read_paddle_input; configure game mode A ; x-ref: $B3E1, $B3F1 |
| $B3F9 | 8d 7e 1d | stainput_dispatch_lo |
| $B3FC | a9 a9 | lda#>read_paddle_input |
| $B3FE | 8d 7f 1d | stainput_dispatch_hi |
| $B401 | e0 8a | cpx#$8a |
| $B403 | f0 13 | beqb_B418 |
| $B405 | d0 0e | bneb_B415 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Configures the game for Joystick 1 control and sets the number of lives. |
| ; Called when the player presses F1, F2, or the joystick button during attract mode. |
| ; |
| ; Inputs: X = PETSCII key code (if started via keyboard) |
| ; Outputs: player_lives = 2 or 4 (based on F-key pressed) |
| ; joy_fire = $80 (signals start to abort attract mode) |
| ; input_dispatch vector points to read_joystick |
| ; Side Effects: Patches the input_dispatch vector with the handler routine |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B407 | a9 a6 | option_joysticklda#<read_joystick; configure game mode B ; x-ref: $B3DA, $B3E9, $B3ED |
| $B409 | 8d 7e 1d | stainput_dispatch_lo; Patch input vector LSB |
| $B40C | a9 a8 | lda#>read_joystick |
| $B40E | 8d 7f 1d | stainput_dispatch_hi; Patch input vector MSB |
| $B411 | e0 89 | cpx#$89; Check if F2 was pressed |
| $B413 | f0 03 | beqb_B418; If F2, jump to give 4 lives |
| $B415 | a9 02 | b_B415lda#$02; Else, give 2 lives ; x-ref: $B405 |
| $B417 | | .byte$2c; BIT trick to skip next instruction |
| $B418 | a9 04 | b_B418lda#$04; Give 4 lives (F2 or F4) ; x-ref: $B403, $B413 |
| $B41A | 85 1f | stazp_player_lives; Store selected number of lives |
| $B41C | a9 80 | lda#$80; Set game start flag ($80) |
| $B41E | 85 b0 | stazp_joy_fire; Write to joy_fire to abort attract mode |
| $B420 | 60 | rts |
| $B421 | ae 8d 02 | b_B421ldxMODIFIER_KEYS; Read KERNAL modifier key flag (Shift/C=) ; x-ref: $B3F5 |
| $B424 | e0 07 | cpx#$07; Check if Shift + C= + Ctrl are held down |
| $B426 | f0 04 | beqb_B42C; If yes, activate secret mode |
| $B428 | 20 38 b4 | jsrhandle_display_settings_key; Else, process normal F-keys |
| $B42B | 60 | rts |
| $B42C | a9 08 | b_B42Clda#VicColors.ORANGE; Load color value (Black) ; x-ref: $B426 |
| $B42E | 8d 0f 90 | sta$900f; Update VIC border/background color |
| $B431 | a9 01 | lda#VicColors.WHITE; Load flag/color value |
| $B433 | 85 27 | stazp_playfield_color; Set playfield color |
| $B435 | 85 62 | stazp_show_score_table; Enable special feature |
| $B437 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles keyboard shortcuts to adjust display settings. |
| ; $1D (CRSR RIGHT): Shift screen right |
| ; $11 (CRSR DOWN) : Shift screen down |
| ; $8C : Toggle interlace mode |
| ; $87 : Cycle background color |
| ; $88 : Cycle border color |
| ; |
| ; Inputs: A = PETSCII key code |
| ; Outputs: None |
| ; Side Effects: Modifies VIC registers $9000, $9001, $900F, and color RAM |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| handle_display_settings_key |
| $B438 | aa | tax; X = key code ; x-ref: $B428 |
| $B439 | a9 01 | lda#$01 |
| $B43B | e0 1d | cpx#$1d; Check for CRSR RIGHT |
| $B43D | d0 0c | bneb_B44B |
| $B43F | 18 | clc |
| $B440 | 6d 00 90 | adc$9000; Add 1 to horizontal origin |
| $B443 | 29 8f | and#$8f |
| $B445 | 09 01 | ora#$01 |
| $B447 | 8d 00 90 | sta$9000 |
| $B44A | 60 | rts |
| $B44B | e0 11 | b_B44Bcpx#$11; Check for CRSR DOWN ; x-ref: $B43D |
| $B44D | d0 0c | bneb_B45B |
| $B44F | 18 | clc |
| $B450 | 6d 01 90 | adc$9001; Add 1 to vertical origin |
| $B453 | 29 3f | and#$3f |
| $B455 | 09 01 | ora#$01 |
| $B457 | 8d 01 90 | sta$9001 |
| $B45A | 60 | rts |
| $B45B | e0 8c | b_B45Bcpx#$8c; Check for key $8C ; x-ref: $B44D |
| $B45D | d0 09 | bneb_B468 |
| $B45F | ad 00 90 | lda$9000 |
| $B462 | 49 80 | eor#$80; Toggle interlace bit |
| $B464 | 8d 00 90 | sta$9000 |
| $B467 | 60 | rts |
| $B468 | e0 87 | b_B468cpx#$87; Check for key $87 ; x-ref: $B45D |
| $B46A | d0 11 | bneb_B47D |
| $B46C | ad 0f 90 | lda$900f |
| $B46F | 18 | clc |
| $B470 | 69 10 | adc#$10; Cycle background color |
| $B472 | 29 77 | and#$77 |
| $B474 | 18 | clc |
| $B475 | 69 01 | adc#$01 |
| $B477 | 09 08 | ora#$08 |
| $B479 | 8d 0f 90 | sta$900f |
| $B47C | 60 | rts |
| $B47D | e0 88 | b_B47Dcpx#$88; Check for key $88 ; x-ref: $B46A |
| $B47F | d0 0b | bner_B48C |
| $B481 | e6 27 | inczp_playfield_color; Cycle border color |
| $B483 | a5 27 | ldazp_playfield_color |
| $B485 | 29 07 | and#$07 |
| $B487 | 85 27 | stazp_playfield_color |
| $B489 | 20 52 a4 | jsrfill_color_ram; Update color RAM |
| $B48C | 60 | r_B48Crts; x-ref: $B47F |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Ignores NMI interrupts (likely triggered by the RESTORE key) by restoring |
| ; registers and returning immediately. |
| ; |
| ; Inputs: None (assumes Y, X, A are pushed on stack by KERNAL) |
| ; Outputs: Restores Y, X, A registers |
| ; Side Effects: Reads $9111 (VIA 1 Port A) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $B48D | 2c 11 91 | ignore_nmibit$9111; dummy read of VIA 1 Port A ; x-ref: $A002 |
| $B490 | 68 | pla; pull Y |
| $B491 | a8 | tay |
| $B492 | 68 | pla; pull X |
| $B493 | aa | tax |
| $B494 | 68 | pla; pull A |
| $B495 | 40 | rti; return from interrupt |
| ; ROM table of 8x8 pixel glyph shapes (8 bytes each). |
| ; Indexed by frame number via calc_sprite_ptr: addr = $B496 + (index * 8). |
| ; Contains all game sprites (player ship, enemy ships, bullets, icons) and |
| ; the large logo tiles used in attract mode screens. |
| $B496 | | sprite_glyph_table.byte$c0, $30, $2c, $23, $2c, $30, $c0, $00 |
| $B49E | | .byte$00, $00, $ff, $22, $24, $18, $10, $20 |
| $B4A6 | | .byte$01, $0e, $32, $c2, $24, $14, $08, $08 |
| $B4AE | | .byte$04, $0c, $14, $24, $64, $9c, $04, $04 |
| $B4B6 | | .byte$10, $10, $28, $28, $44, $7c, $82, $82 |
| $B4BE | | .byte$20, $30, $28, $24, $26, $39, $20, $20 |
| $B4C6 | | .byte$80, $60, $5c, $23, $24, $28, $10, $10 |
| $B4CE | | .byte$00, $00, $ff, $44, $24, $18, $08, $04 |
| $B4D6 | | .byte$03, $0c, $34, $c4, $34, $0c, $03, $00 |
| $B4DE | | .byte$04, $08, $18, $24, $44, $ff, $00, $00 |
| $B4E6 | | .byte$10, $10, $28, $24, $23, $5c, $60, $80 |
| $B4EE | | .byte$20, $20, $39, $26, $24, $28, $30, $20 |
| $B4F6 | | .byte$82, $82, $7c, $44, $28, $28, $10, $10 |
| $B4FE | | .byte$04, $04, $9c, $64, $24, $14, $0c, $04 |
| $B506 | | .byte$08, $08, $14, $24, $c4, $3a, $06, $01 |
| $B50E | | .byte$20, $10, $18, $24, $22, $ff, $00, $00 |
| $B516 | | .byte$c0, $30, $6c, $e3, $6c, $30, $c0, $00 |
| $B51E | | .byte$00, $00, $ff, $22, $64, $78, $10, $20 |
| $B526 | | .byte$01, $0e, $32, $c2, $24, $74, $68, $08 |
| $B52E | | .byte$04, $0c, $14, $24, $64, $bc, $34, $04 |
| $B536 | | .byte$10, $10, $28, $28, $44, $7c, $ba, $92 |
| $B53E | | .byte$20, $30, $28, $24, $26, $3d, $2c, $20 |
| $B546 | | .byte$80, $60, $5c, $23, $24, $2e, $16, $10 |
| $B54E | | .byte$00, $00, $ff, $44, $26, $1e, $08, $04 |
| $B556 | | .byte$03, $0c, $36, $c7, $36, $0c, $03, $00 |
| $B55E | | .byte$04, $08, $1e, $26, $44, $ff, $00, $00 |
| $B566 | | .byte$10, $16, $2e, $24, $23, $5c, $60, $80 |
| $B56E | | .byte$20, $2c, $3d, $26, $24, $28, $30, $20 |
| $B576 | | .byte$92, $ba, $7c, $44, $28, $28, $10, $10 |
| $B57E | | .byte$04, $34, $bc, $64, $24, $14, $0c, $04 |
| $B586 | | .byte$08, $68, $74, $24, $c4, $3a, $06, $01 |
| $B58E | | .byte$20, $10, $78, $64, $22, $ff, $00, $00 |
| $B596 | | .byte$00, $82, $54, $38, $6c, $10, $10, $10 |
| $B59E | | .byte$00, $04, $98, $78, $7c, $08, $04, $00 |
| $B5A6 | | .byte$10, $10, $10, $28, $7c, $28, $44, $00 |
| $B5AE | | .byte$18, $66, $42, $99, $bd, $42, $66, $18 |
| $B5B6 | | .byte$24, $3c, $c3, $5a, $7e, $c3, $3c, $24 |
| $B5BE | | .byte$18, $66, $42, $81, $81, $42, $66, $18 |
| $B5C6 | | .byte$24, $3c, $c3, $42, $42, $c3, $3c, $24 |
| $B5CE | | .byte$10, $28, $44, $fe, $44, $28, $10, $00 |
| $B5D6 | | .byte$10, $28, $44, $fe, $00, $00, $00, $00 |
| $B5DE | | .fill8, $ff |
| $B5E6 | | .fill8, $00 |
| $B5EE | | .byte$04, $04, $08, $10, $20, $40, $40, $00 |
| $B5F6 | | .byte$7c, $82, $ba, $a2, $a2, $ba, $82, $7c |
| $B5FE | | .byte$00, $00, $00, $01, $09, $05, $00, $1c |
| $B606 | | .byte$00, $00, $00, $00, $20, $40, $00, $70 |
| $B60E | | .byte$00, $05, $09, $00, $00, $00, $00, $00 |
| $B616 | | .byte$00, $40, $20, $00, $00, $00, $00, $00 |
| $B61E | | .byte$09, $49, $25, $10, $c0, $20, $00, $e0 |
| $B626 | | .byte$20, $24, $48, $10, $06, $08, $00, $0e |
| $B62E | | .byte$00, $20, $c0, $10, $25, $49, $09, $01 |
| $B636 | | .byte$00, $08, $06, $10, $48, $24, $20, $00 |
| $B63E | | .byte$00, $00, $00, $00, $00, $00, $02, $01 |
| $B646 | | .byte$00, $00, $00, $00, $10, $92, $54, $55 |
| $B64E | | .byte$00, $00, $00, $00, $00, $00, $80, $00 |
| $B656 | | .byte$00, $06, $00, $0f, $00, $06, $00, $01 |
| $B65E | | .byte$92, $54, $00, $c7, $00, $54, $92, $55 |
| $B666 | | .byte$00, $c0, $00, $e0, $00, $c0, $00, $00 |
| $B66E | | .byte$02, $00, $00, $00, $00, $00, $00, $00 |
| $B676 | | .byte$54, $92, $10, $00, $00, $00, $00, $00 |
| $B67E | | .byte$80, $00, $00, $00, $00, $00, $00, $00 |
| $B686 | | .byte$02, $02, $21, $11, $08, $04, $00, $60 |
| $B68E | | .byte$10, $10, $11, $11, $82, $00, $00, $00 |
| $B696 | | .byte$80, $80, $08, $10, $20, $40, $00, $0c |
| $B69E | | .byte$18, $00, $00, $f0, $00, $00, $18, $60 |
| $B6A6 | | .fill8, $00 |
| $B6AE | | .byte$30, $00, $00, $1e, $00, $00, $30, $0c |
| $B6B6 | | .byte$00, $04, $08, $11, $21, $02, $02, $00 |
| $B6BE | | .byte$00, $00, $82, $11, $11, $10, $10, $10 |
| $B6C6 | | .byte$00, $40, $20, $10, $08, $80, $80, $00 |
| $B6CE | | .byte$e0, $a0, $a0, $a0, $e0, $00, $00, $00 |
| $B6D6 | | .byte$40, $c0, $40, $40, $e0, $00, $00, $00 |
| $B6DE | | .byte$e0, $20, $60, $80, $e0, $00, $00, $00 |
| $B6E6 | | .byte$e0, $20, $40, $20, $e0, $00, $00, $00 |
| $B6EE | | .byte$a0, $a0, $e0, $20, $20, $00, $00, $00 |
| $B6F6 | | .byte$e0, $80, $c0, $20, $c0, $00, $00, $00 |
| $B6FE | | .byte$60, $80, $e0, $a0, $e0, $00, $00, $00 |
| $B706 | | .byte$e0, $20, $40, $80, $80, $00, $00, $00 |
| $B70E | | .byte$e0, $a0, $e0, $a0, $e0, $00, $00, $00 |
| $B716 | | .byte$e0, $a0, $e0, $20, $20, $00, $00, $00 |
| $B71E | | wave_icon_tbl.byte$65, $72, $6f, $63, $73, $2a, $68, $67; x-ref: $AD3C |
| $B726 | | .byte$69, $68 |
| ; draw_graphic_string data: scoring table screen. |
| ; Drawn conditionally (only when a62 != 0). Ends with $FF. |
| $B728 | | gfx_attract_slide_2.byte$18, $10, $08, $93, $86, $80, $7d, $93; x-ref: $B1F9, $B1FB |
| $B730 | | .byte$82, $8f, $90, $86, $8c, $8b, $7d, $7f |
| $B738 | | .byte$96, $00, $24, $38, $08, $7e, $8b, $81 |
| $B740 | | .byte$96, $7d, $83, $86, $8b, $88, $82, $89 |
| $B748 | | .byte$00, $4b, $4e, $04, $77, $69, $6b, $00 |
| $B750 | | .byte$24, $68, $08, $82, $8f, $86, $80, $7d |
| $B758 | | .byte$80, $8c, $91, $91, $8c, $8b, $00, $40 |
| $B760 | | .byte$88, $08, $d7, $2b, $dc, $d6, $ff, $00 |
| $B768 | | .byte$00, $00, $00, $00, $00, $00, $f0, $f0 |
| $B770 | | .byte$f0, $f0, $f0, $00, $00, $00, $ff, $9b |
| $B778 | | .byte$b3, $9b, $bb, $b1, $ff, $00, $ff, $89 |
| $B780 | | .byte$bd, $99, $bd, $b9, $ff, $00, $ff, $91 |
| $B788 | | .byte$b7, $91, $bd, $b1, $ff, $00, $ff, $91 |
| $B790 | | .byte$bd, $9d, $bd, $bd, $ff |
| $B795 | | .fill9, $00 |
| $B79E | | .byte$40, $a0, $e0, $a0, $a0, $00, $00, $00 |
| $B7A6 | | .byte$c0, $a0, $c0, $a0, $c0, $00, $00, $00 |
| $B7AE | | .byte$60, $80, $80, $80, $60, $00, $00, $00 |
| $B7B6 | | .byte$c0, $a0, $a0, $a0, $c0, $00, $00, $00 |
| $B7BE | | .byte$e0, $80, $c0, $80, $e0, $00, $00, $00 |
| $B7C6 | | .byte$e0, $80, $c0, $80, $80, $00, $00, $00 |
| $B7CE | | .byte$60, $80, $80, $a0, $60, $00, $00, $00 |
| $B7D6 | | .byte$a0, $a0, $e0, $a0, $a0, $00, $00, $00 |
| $B7DE | | .byte$e0, $40, $40, $40, $e0, $00, $00, $00 |
| $B7E6 | | .byte$e0, $40, $40, $40, $80, $00, $00, $00 |
| $B7EE | | .byte$a0, $a0, $c0, $a0, $a0, $00, $00, $00 |
| $B7F6 | | .byte$80, $80, $80, $80, $e0, $00, $00, $00 |
| $B7FE | | .byte$a0, $e0, $a0, $a0, $a0, $00, $00, $00 |
| $B806 | | .byte$c0, $a0, $a0, $a0, $a0, $00, $00, $00 |
| $B80E | | .byte$40, $a0, $a0, $a0, $40, $00, $00, $00 |
| $B816 | | .byte$c0, $a0, $c0, $80, $80, $00, $00, $00 |
| $B81E | | .byte$40, $a0, $a0, $a0, $60, $00 |
| ; ROM table of 8x8 pixel shapes for the small text font (8 bytes each). |
| ; Contains glyphs for digits 0-9 and uppercase/lowercase letters used |
| ; in the attract mode text slides (story text, copyright lines, etc.). |
| $B824 | | small_font_glyphs.byte$00, $00, $c0, $a0, $c0, $a0, $a0, $00 |
| $B82C | | .byte$00, $00, $e0, $80, $e0, $20, $e0, $00 |
| $B834 | | .byte$00, $00, $e0, $40, $40, $40, $40, $00 |
| $B83C | | .byte$00, $00, $a0, $a0, $a0, $a0, $e0, $00 |
| $B844 | | .byte$00, $00, $a0, $a0, $a0, $a0, $40, $00 |
| $B84C | | .byte$00, $00, $a0, $a0, $a0, $e0, $a0, $00 |
| $B854 | | .byte$00, $00, $a0, $a0, $40, $a0, $a0, $00 |
| $B85C | | .byte$00, $00, $a0, $a0, $40, $40, $40, $00 |
| $B864 | | .byte$00, $00, $e0, $20, $40, $80, $e0, $00 |
| $B86C | | .byte$00, $00, $00, $00, $00, $40, $40, $80 |
| $B874 | | .byte$00, $00, $00, $00, $00, $00, $40 |
| $B87B | | .fill11, $00 |
| $B886 | | .byte$30, $48, $84, $fc, $84, $84, $84, $00 |
| $B88E | | .byte$f8, $84, $84, $f8, $84, $84, $f8, $00 |
| $B896 | | .byte$fc, $80, $80, $80, $80, $80, $fc, $00 |
| $B89E | | .byte$f8, $84, $84, $84, $84, $84, $f8, $00 |
| $B8A6 | | .byte$fc, $80, $80, $f8, $80, $80, $fc, $00 |
| $B8AE | | .byte$fc, $80, $80, $f8, $80, $80, $80, $00 |
| $B8B6 | | .byte$fc, $80, $8c, $84, $84, $84, $fc, $00 |
| $B8BE | | .byte$84, $84, $84, $fc, $84, $84, $84, $00 |
| $B8C6 | | .byte$70, $20, $20, $20, $20, $20, $70, $00 |
| $B8CE | | .byte$08, $08, $08, $08, $08, $88, $78, $00 |
| $B8D6 | | .byte$88, $90, $e0, $a0, $90, $88, $88, $00 |
| $B8DE | | .byte$80, $80, $80, $80, $80, $80, $fc, $00 |
| $B8E6 | | .byte$84, $cc, $b4, $84, $84, $84, $84, $00 |
| $B8EE | | .byte$84, $c4, $a4, $94, $8c, $84, $84, $00 |
| $B8F6 | | .byte$fc, $84, $84, $84, $84, $84, $fc, $00 |
| $B8FE | | .byte$fc, $84, $84, $fc, $80, $80, $80, $00 |
| $B906 | | .byte$fc, $84, $84, $84, $94, $88, $f4, $00 |
| $B90E | | .byte$fc, $84, $84, $fc, $a0, $90, $88, $00 |
| $B916 | | .byte$fc, $80, $80, $fc, $04, $04, $fc, $00 |
| $B91E | | .byte$7c, $10, $10, $10, $10, $10, $10, $00 |
| $B926 | | .byte$84, $84, $84, $84, $84, $84, $fc, $00 |
| $B92E | | .byte$44, $44, $44, $44, $28, $28, $10, $00 |
| $B936 | | .byte$84, $84, $84, $84, $b4, $cc, $84, $00 |
| $B93E | | .byte$44, $44, $28, $10, $28, $44, $44, $00 |
| $B946 | | .byte$44, $44, $28, $10, $10, $10, $10, $00 |
| $B94E | | .byte$fc, $04, $08, $10, $20, $40, $fc, $00 |
| $B956 | | .byte$00, $00, $00, $00, $10, $10, $20, $00 |
| $B95E | | .byte$00, $00, $00, $00, $00, $10, $10, $00 |
| $B966 | | .byte$00, $00, $00, $01, $03, $07, $0f, $1e |
| $B96E | | .byte$07, $1f, $7f, $f8, $e0, $c1, $07, $1f |
| $B976 | | .byte$ff, $ff, $ff, $00, $00, $fc, $ff, $ff |
| $B97E | | .byte$00, $c0, $f0, $fc, $3e, $1f, $07, $c3 |
| $B986 | | .byte$00, $00, $00, $00, $00, $00, $80, $ff |
| $B98E | | .byte$00, $00, $00, $00, $00, $00, $00, $ff |
| $B996 | | .byte$1c, $3c, $38, $71, $71, $e3, $e3, $e7 |
| $B99E | | .byte$3e, $78, $f1, $e7, $cf, $9e, $9c, $38 |
| $B9A6 | | .byte$03, $00, $fc, $ff, $ff, $03, $01, $00 |
| $B9AE | | .byte$e1, $f1, $78, $3c, $9c, $ce, $ce, $e7 |
| $B9B6 | | .byte$ff, $ff, $00, $00, $7f, $7f, $7f, $70 |
| $B9BE | | .byte$ff, $ff, $00, $00, $e1, $f1, $f9, $3c |
| $B9C6 | | .byte$ff, $ff, $00, $00, $ff, $ff, $ff, $00 |
| $B9CE | | .byte$ff, $ff, $00, $00, $03, $0f, $1f, $3e |
| $B9D6 | | .byte$ff, $ff, $00, $00, $e0, $e0, $e0, $00 |
| $B9DE | | .byte$ff, $ff, $00, $00, $e0, $e0, $e0, $70 |
| $B9E6 | | .byte$ff, $ff, $00, $00, $1f, $1f, $1f, $00 |
| $B9EE | | .byte$ff, $ff, $00, $00, $f0, $f8, $fc, $1c |
| $B9F6 | | .byte$ff, $ff, $00, $00, $1c, $1c, $1c, $0e |
| $B9FE | | .byte$ff, $ff, $00, $00, $03, $0f, $1f, $3e |
| $BA06 | | .byte$ff, $ff, $00, $00, $df, $df, $df |
| $BA0D | | .fill8, $00 |
| $BA15 | | .byte$f0, $e0, $e0, $00, $00, $80, $00, $00 |
| $BA1D | | .byte$00, $e7, $e7, $e7, $e7, $e7, $e7, $e3 |
| $BA25 | | .byte$e3, $38, $38, $38, $38, $38, $38, $9c |
| $BA2D | | .byte$9e, $00, $00, $00, $00, $00, $00, $01 |
| $BA35 | | .byte$03, $e7, $e7, $e7, $e7, $e7, $e7, $ce |
| $BA3D | | .byte$ce, $70, $73, $73, $73, $73, $73, $73 |
| $BA45 | | .byte$73, $1c, $9d, $9d, $9d, $9d, $9d, $9d |
| $BA4D | | .byte$9d, $00, $ff, $ff, $ff, $c0, $c0, $ff |
| $BA55 | | .byte$ff, $38, $79, $71, $79, $38, $3e, $1f |
| $BA5D | | .byte$0f, $00, $e1, $e3, $e3, $03, $27, $e7 |
| $BA65 | | .byte$e7, $70, $f0, $b8, $b8, $b8, $1c, $fc |
| $BA6D | | .byte$fc, $00, $1f, $1f, $1f, $1c, $1c, $1c |
| $BA75 | | .byte$1c, $1c, $f8, $f0, $f8, $38, $1c, $1c |
| $BA7D | | .byte$1c, $0e, $3e, $77, $77, $77, $e3, $ff |
| $BA85 | | .byte$ff, $38, $70, $70, $70, $38, $be, $9f |
| $BA8D | | .byte$8f, $00, $1f, $1f, $1f, $1c, $1c, $df |
| $BA95 | | .byte$df, $00, $fc, $f8, $f8, $00, $00, $e0 |
| $BA9D | | .byte$c0, $71, $71, $38, $3c, $1c, $1e, $0f |
| $BAA5 | | .byte$07, $cf, $e7, $f1, $78, $3e, $1f, $07 |
| $BAAD | | .byte$c1, $ff, $ff, $fc, $00, $03, $ff, $ff |
| $BAB5 | | .byte$fc, $9c, $3c, $78, $f1, $e1, $c3, $07 |
| $BABD | | .byte$1f, $73, $00, $00, $ff, $ff, $ff, $00 |
| $BAC5 | | .byte$00, $9d, $00, $00, $ff, $ff, $ff, $00 |
| $BACD | | .byte$00, $ff, $00, $00, $ff, $ff, $ff, $00 |
| $BAD5 | | .byte$00, $03, $00, $00, $ff, $ff, $ff, $00 |
| $BADD | | .byte$00, $cf, $00, $00, $ff, $ff, $ff, $00 |
| $BAE5 | | .byte$00, $fe, $00, $00, $ff, $ff, $ff, $00 |
| $BAED | | .byte$00, $1c, $00, $00, $ff, $ff, $ff, $00 |
| $BAF5 | | .byte$00, $1d, $00, $00, $ff, $ff, $ff, $00 |
| $BAFD | | .byte$00, $c3, $00, $00, $ff, $ff, $ff, $00 |
| $BB05 | | .byte$00, $df, $00, $00, $ff, $fe, $fe, $00 |
| $BB0D | | .byte$00, $c0, $00, $00, $00, $00, $00, $00 |
| $BB15 | | .byte$00, $03, $01, $00, $00, $00, $00, $00 |
| $BB1D | | .byte$00, $e0, $f8, $7f, $1f, $07, $00, $00 |
| $BB25 | | .byte$00, $00, $00, $ff, $ff, $ff, $00, $00 |
| $BB2D | | .byte$00, $3e, $fc, $f0, $c0, $00, $00, $00 |
| $BB35 | | .byte$00, $78, $84, $84, $84, $84, $84, $78 |
| $BB3D | | .byte$00, $10, $30, $10, $10, $10, $10, $38 |
| $BB45 | | .byte$00, $38, $44, $04, $08, $10, $20, $7c |
| $BB4D | | .byte$00, $38, $44, $04, $08, $04, $44, $38 |
| $BB55 | | .byte$00, $44, $44, $44, $7c, $04, $04, $04 |
| $BB5D | | .byte$00, $7c, $40, $78, $04, $04, $44, $38 |
| $BB65 | | .byte$00, $3c, $40, $78, $44, $44, $44, $7c |
| $BB6D | | .byte$00, $7c, $04, $08, $10, $20, $40, $40 |
| $BB75 | | .byte$00, $7c, $44, $44, $7c, $44, $44, $7c |
| $BB7D | | .byte$00, $7c, $44, $44, $7c, $04, $04, $04 |
| $BB85 | | .byte$00 |
| ; draw_graphic_string data: OMEGA RACE title logo (glyphs $9A-$D3 = large 5-row |
| ; logo tiles spanning Y=62-94) followed by copyright text rows at Y=126/138. |
| ; Drawn with a red/yellow Color RAM gradient pre-set by attract_mode. |
| ; Terminates with $FF at $BC0F. |
| $BB86 | | gfx_attract_slide_1.byte$09, $3e, $08, $9a, $9b, $9c, $9d, $9e; x-ref: $B1DA, $B1DC |
| $BB8E | | .fill11, $9f |
| $BB99 | | .byte$af, $00, $09, $46, $08, $a0, $a1, $a2 |
| $BBA1 | | .byte$a3, $a4, $a5, $a6, $a7, $a8, $a9, $aa |
| $BBA9 | | .byte$ab, $ac, $ad, $ae, $a6, $b0, $00, $09 |
| $BBB1 | | .byte$4e, $08, $b1, $b2, $b3, $b4, $b5, $b6 |
| $BBB9 | | .byte$b7, $b8, $b9, $ba, $bb, $bc, $bd, $be |
| $BBC1 | | .byte$bf, $c0, $00, $09, $56, $08 |
| | .encode |
| | .enc"none" |
| $BBC7 | | .text$c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8, $c9, $ca, $cb, $cc, $c7, $cd, $ce, $cf |
| | .endencode |
| $BBD7 | | .byte$00, $09, $5e, $08, $d0, $d1, $d2, $d3 |
| $BBDF | | .byte$00, $20, $7e, $04 |
| $BBE3 | | .byte$2c, $60; (c) |
| $BBE5 | | .byte$48, $50, $4f, $49, $60; 1982 |
| | .encode |
| | .enc"none" |
| $BBEA | | .text"commodore`ltd|" |
| | .endencode |
| $BBF8 | | .byte$00, $20, $8a, $04 |
| $BBFC | | .byte$2c; (c) |
| $BBFD | | .byte$60; space |
| $BBFE | | .byte$48, $50, $4f, $48; 1981 |
| $BC02 | | .byte$60; space |
| | .encode |
| | .enc"none" |
| $BC03 | | .text"bally`midway" |
| | .endencode |
| $BC0F | | .byte$ff |
| ; draw_graphic_string data: title/logo copyright screen. |
| ; Contains 5 segments (rows of glyph tiles) and ends with $FF at $BC66. |
| $BC10 | | gfx_attract_slide_3.byte$18, $08, $08, $5c, $7d, $87, $8c, $96; x-ref: $B211, $B213 |
| $BC18 | | .byte$90, $91, $86, $80, $88, $00, $18, $20 |
| $BC20 | | .byte$08, $5d, $7d, $8d, $7e, $81, $81, $89 |
| $BC28 | | .byte$82, $7d, $00, $18, $38, $08, $5e, $7d |
| $BC30 | | .byte$90, $80, $8f, $82, $82, $8b, $7d, $80 |
| $BC38 | | .byte$8c, $89, $8c, $8f, $00, $18, $50, $08 |
| $BC40 | | .byte$5f, $7d, $90, $85, $86, $8d, $7d, $80 |
| $BC48 | | .byte$8c, $89, $8c, $8f, $00, $1c, $70, $08 |
| $BC50 | | .byte$7f, $8c, $8b, $92, $90, $7d, $90, $85 |
| $BC58 | | .byte$86, $8d, $7d, $7e, $91, $00, $34, $88 |
| $BC60 | | .byte$08, $d8, $d4, $d4, $d4, $d4, $ff |
| ; draw_graphic_string data: attract story slide 1. |
| ; 'In the year 2003, the Omegan System developed a method of training its...' |
| ; Segment header: X=$0A, Y=$18, step=$04, then small-font glyph indices. |
| ; Character values use the small text font table at small_font_glyphs ($B824). |
| ; Drawn with aAF=$FF (instant display, no typing delay). |
| $BC67 | | gfx_story_slide_1.byte$0a, $18, $04; x-ref: $B232, $B234 |
| | .encode |
| | .enc"none" |
| $BC6A | | .text"in`the`year`" |
| | .endencode |
| $BC76 | | .byte$49, $47, $47, $4a; 2003 |
| | .encode |
| | .enc"none" |
| $BC7A | | .text"{`the`omegan`system" |
| | .endencode |
| $BC8D | | .byte$00, $0c, $20, $04 |
| | .encode |
| | .enc"none" |
| $BC91 | | .text"developed`a`method`of`training`its" |
| | .endencode |
| $BCB3 | | .byte$00, $14, $28, $04 |
| | .encode |
| | .enc"none" |
| $BCB7 | | .text"warriors`to`protect`their`star" |
| | .endencode |
| $BCD5 | | .byte$00, $0e, $30, $04 |
| | .encode |
| | .enc"none" |
| $BCD9 | | .text"colonies|`over`the`city`of`komar{" |
| | .endencode |
| $BCFA | | .byte$00, $0e, $38, $04 |
| | .encode |
| | .enc"none" |
| $BCFE | | .text"android`controlled`fighters`raced" |
| | .endencode |
| $BD1F | | .byte$00, $1a, $40, $04 |
| | .encode |
| | .enc"none" |
| $BD23 | | .text"to`engage`and`destroy`these" |
| | .endencode |
| $BD3E | | .byte$00, $30, $48, $04 |
| | .encode |
| | .enc"none" |
| $BD42 | | .text"omegan`warriors|" |
| | .endencode |
| $BD52 | | .byte$00, $04, $70, $04 |
| | .encode |
| | .enc"none" |
| $BD56 | | .text"points`were`awarded`for`the`ability`to" |
| | .endencode |
| $BD7C | | .byte$00, $02, $78, $04 |
| | .encode |
| | .enc"none" |
| $BD80 | | .text"neutralize`this`droid`force`as`follows|" |
| | .endencode |
| $BDA7 | | .byte$ff |
| attract_story_slide_2 |
| $BDA8 | | .byte$10, $10, $08, $28, $00, $10, $30, $08; x-ref: $B252, $B254 |
| $BDB0 | | .byte$27, $00, $10, $50, $08, $25, $00, $10 |
| $BDB8 | | .byte$70, $08, $23, $00, $10, $90, $08, $20 |
| $BDC0 | | .byte$00, $50, $10, $08, $d7, $d9, $d4, $7d |
| $BDC8 | | .byte$8d, $8c, $86, $8b, $91, $90, $00, $50 |
| $BDD0 | | .byte$30, $08, $d9, $d4, $d4, $7d, $8d, $8c |
| $BDD8 | | .byte$86, $8b, $91, $90, $00, $48, $50, $08 |
| $BDE0 | | .byte$d5, $d4, $d4, $d4, $7d, $8d, $8c, $86 |
| $BDE8 | | .byte$8b, $91, $90, $00, $48, $70, $08, $d5 |
| $BDF0 | | .byte$d9, $d4, $d4, $7d, $8d, $8c, $86, $8b |
| $BDF8 | | .byte$91, $90, $00, $48, $90, $08, $d6, $d9 |
| $BE00 | | .byte$d4, $d4, $7d, $8d, $8c, $86, $8b, $91 |
| $BE08 | | .byte$90, $ff |
| attract_story_slide_3 |
| $BE0A | | .byte$06, $20, $04; x-ref: $B26C, $B26E |
| | .encode |
| | .enc"none" |
| $BE0D | | .text"the`omegan`method`is`so`successful`it" |
| | .endencode |
| $BE32 | | .byte$00, $0c, $28, $04 |
| | .encode |
| | .enc"none" |
| $BE36 | | .text"commands`fear`and`respect`from`all" |
| | .endencode |
| $BE58 | | .byte$00, $18, $30, $04 |
| | .encode |
| | .enc"none" |
| $BE5C | | .text"throughout`the`galaxies|`the" |
| | .endencode |
| $BE78 | | .byte$00, $22, $38, $04 |
| | .encode |
| | .enc"none" |
| $BE7C | | .text"method`is`code`named|||" |
| | .endencode |
| $BE93 | | .byte$ff |
| wave_transition_graphic |
| $BE94 | | .byte$2d, $30, $08, $84, $7e, $8a, $82, $7d; x-ref: $A0BB, $A0BD |
| $BE9C | | .byte$8c, $93, $82, $8f, $ff |
| phase_bonus_congrats_text |
| $BEA1 | | .byte$18, $1c, $08, $81, $8f, $8c, $86, $81; x-ref: $B3A5, $B3A7 |
| $BEA9 | | .byte$7d, $83, $8c, $8f, $80, $82, $00, $28 |
| $BEB1 | | .byte$4c, $08, $82, $89, $86, $8a, $86, $8b |
| $BEB9 | | .byte$7e, $91, $82, $81, $00, $08, $7c, $08 |
| $BEC1 | | .byte$d9, $99, $d4, $d4, $d4, $7d, $7f, $8c |
| $BEC9 | | .byte$8b, $92, $90, $7d, $8d, $8c, $86, $8b |
| $BED1 | | .byte$91, $90 |
| $BED3 | | snd_bass_freq_tbl.byte$ff, $8c; x-ref: $A0D5 |
| $BED5 | | snd_bass_dur_tbl.byte$00, $5a; x-ref: $A0EB |
| $BED7 | | snd_alto_freq_tbl.byte$00, $af, $08, $b3, $08, $af, $08, $a0; x-ref: $A0F4 |
| $BEDF | | .byte$08, $00, $fa, $f5, $f0, $eb, $e6, $dc |
| $BEE7 | | .byte$d7, $c8, $be, $b4, $aa, $96, $00, $b4 |
| $BEEF | | .byte$be, $c8, $cd, $d2, $d7, $dc, $e1, $e6 |
| $BEF7 | | .byte$eb, $f0, $f5, $fa, $ff, $00, $d9, $d4 |
| $BEFF | | .byte$d9, $db, $df, $cf, $01, $d9, $d4, $d9 |
| $BF07 | | .byte$db, $df, $cf, $01, $d9, $d4, $d9, $db |
| $BF0F | | .byte$df, $cf, $01, $d9, $db, $d9, $db, $d4 |
| $BF17 | | snd_alto_dur_tbl.byte$00; x-ref: $A108, $A128 |
| snd_alto_dur_tbl_offset1 |
| $BF18 | | .byte$12, $06, $12, $06, $12, $06, $12, $06; x-ref: $A218 |
| $BF20 | | .byte$00, $01, $01, $02, $03, $03, $02, $02 |
| $BF28 | | .byte$02, $02, $02, $01, $01, $00, $01, $01 |
| $BF30 | | .byte$01, $01, $01, $01, $02, $02, $02, $02 |
| $BF38 | | .byte$02, $02, $03, $09, $00, $05, $06, $06 |
| $BF40 | | .byte$08, $21, $14, $05, $06, $06, $06, $08 |
| $BF48 | | .byte$21, $14, $05, $06, $06, $06, $08, $21 |
| $BF50 | | .byte$14, $05, $06, $06, $06, $0a, $2d, $00 |
| $BF58 | | .byte$09, $03, $09, $03, $09, $03, $09, $03 |
| $BF60 | | .byte$00, $04, $02, $04, $02, $04, $02, $04 |
| $BF68 | | snd_soprano_freq_tbl.byte$02, $ff, $fa, $f5, $f0, $eb, $e6, $e1; x-ref: $A131 |
| $BF70 | | .byte$dc, $d7, $d2, $c8, $be, $b4, $af, $aa |
| $BF78 | | .byte$00, $ee, $01, $ee, $01, $ee, $01, $ee |
| $BF80 | | .byte$01, $ee, $01, $ee, $01, $ee, $01, $ee |
| $BF88 | | .byte$00, $be, $c1, $be, $01 |
| $BF8D | | snd_soprano_dur_tbl.byte$00; x-ref: $A147 |
| $BF8E | | .fill15, $01 |
| $BF9D | | .byte$00 |
| $BF9E | | .fill15, $03 |
| $BFAD | | .byte$00, $02, $02, $02 |
| $BFB1 | | snd_noise_freq_tbl.byte$04, $b4, $be, $c3, $c8, $cd, $d2, $d7; x-ref: $A150 |
| $BFB9 | | .byte$dc, $e1, $e6, $00, $cd, $01, $c8, $01 |
| $BFC1 | | .byte$c3, $01, $be, $01, $b4, $01, $8c, $00 |
| $BFC9 | | .byte$c8 |
| $BFCA | | snd_noise_dur_tbl.byte$00, $08, $08, $08, $08, $08, $08, $08; x-ref: $A166 |
| $BFD2 | | .byte$07, $07, $07, $00, $0f, $01, $0f, $01 |
| $BFDA | | .byte$0f, $01, $0f, $01, $0f, $01, $0f, $00 |
| $BFE2 | | .byte$64, $03, $31, $82, $0f, $01, $0f, $01 |
| $BFEA | | .byte$0f, $00, $64 |
| $BFED | | .fill19, $aa |