| ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; |
| ; Auto-generated by Regenerator 2000 v0.9.17 |
| ; https://github.com/ricardoquesada/regenerator2000 |
| ; |
| ; Exported from: c64_burnin_rubber.regen2000proj |
| ; |
| ; Assemble with 64tass: |
| ; 64tass -o c64_burnin_rubber.prg c64_burnin_rubber.asm |
| ; |
| ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
|
| ; EXTERNAL LABELS |
| ; zpa_ = Zero Page Absolute Address |
| ; f_ = Field |
| ; a_ = Absolute Address |
| ; p_ = Pointer |
| ; e_ = External Jump |
| ; L_ = Other / User-defined |
| ; (ext) = External File Label |
|
| zpa_01 = $01 ; x-ref: $1809, $180D, $1812, $1816 |
| zp_p_tmp_lo = $49 ; x-ref: $130B, $1315, $131A, $1326, $132B, $1347, $134C, $135A, ... |
| zp_p_tmp_hi = $4a ; x-ref: $130F, $131C, $1320, $132F, $1336, $133B, $134E, $1352, ... |
| zp_rnd_car_type_byte = $8c ; x-ref: $4A14 |
| zp_rnd_direction_byte = $8d ; x-ref: $4AEB |
| zp_rnd_speed_byte = $8e ; x-ref: $4AF2, $4D9E |
| zp_rnd_pos_byte = $8f ; x-ref: $4A4D, $4A5A, $4A67, $4A74, $4A81, $4AAD |
| zp_key_scan = $c5 ; x-ref: $3FD8, $5239, $523F, $5245, $5270, $530A, $534C, $5400, ... |
| zp_joy_state = $f5 ; x-ref: $11D6, $11E4, $17A6, $17AD, $1A00, $1D83, $4410, $49ED, ... |
| IRQ_VEC_LO = $0314 ; IRQ ; x-ref: $1298 |
| IRQ_VEC_HI = $0315 ; IRQ ; x-ref: $1293 |
| p_03D9 = $03d9 ; x-ref: $4DC3, $4DC7 |
| SCREEN_RAM = $0400 ; x-ref: $1057, $1132, $1B10, $1B14, $3C2D, $3C31, $4D4F, $4D53 |
| SCREEN_RAM_R0C3 = $0403 ; x-ref: $16FA |
| SCREEN_RAM_R0C14 = $040e ; x-ref: $1703 |
| SCREEN_RAM_R0C25 = $0419 ; x-ref: $1FB6, $1FC6, $1FD6, $1FE2 |
| SCREEN_RAM_R0C26 = $041a ; x-ref: $1FB1, $1FC1, $1FD1, $1FDD |
| SCREEN_RAM_R0C32 = $0420 ; x-ref: $16B6 |
| SCREEN_RAM_R0C33 = $0421 ; x-ref: $16BF |
| SCREEN_RAM_R0C38 = $0426 ; x-ref: $16C8 |
| SCREEN_RAM_R0C39 = $0427 ; x-ref: $16D1 |
| SCREEN_RAM_R1C0 = $0428 ; x-ref: $135C, $1399, $1B8E, $50D5 |
| SCREEN_RAM_R2C0 = $0450 ; x-ref: $4AA5, $4AA9 |
| SCREEN_RAM_R3C11 = $0483 ; x-ref: $1413 |
| SCREEN_RAM_R4C0 = $04a0 ; x-ref: $1B65 |
| SCREEN_RAM_R5C8 = $04d0 ; x-ref: $111E |
| SCREEN_RAM_R5C10 = $04d2 ; x-ref: $1428 |
| SCREEN_RAM_R5C23 = $04df ; x-ref: $143B |
| SCREEN_RAM_R5C24 = $04e0 ; x-ref: $1444 |
| SCREEN_RAM_R6C16 = $0500 ; x-ref: $105D, $1121, $1138, $1717, $503D, $5069 |
| SCREEN_RAM_R6C23 = $0507 ; x-ref: $5050 |
| SCREEN_RAM_R7C12 = $0524 ; x-ref: $1452 |
| SCREEN_RAM_R9C11 = $0573 ; x-ref: $1498 |
| SCREEN_RAM_R9C12 = $0574 ; x-ref: $146E, $1481 |
| SCREEN_RAM_R9C13 = $0575 ; x-ref: $148A |
| SCREEN_RAM_R9C16 = $0578 ; x-ref: $1B6B, $4615 |
| SCREEN_RAM_R9C23 = $057f ; x-ref: $18C0 |
| SCREEN_RAM_R9C26 = $0582 ; x-ref: $18CF |
| SCREEN_RAM_R9C27 = $0583 ; x-ref: $18D2 |
| SCREEN_RAM_R11C3 = $05bb ; x-ref: $1E01 |
| SCREEN_RAM_R11C17 = $05c9 ; x-ref: $14AD |
| SCREEN_RAM_R11C19 = $05cb ; x-ref: $1DD8, $1E2B |
| SCREEN_RAM_R11C20 = $05cc ; x-ref: $1DE1, $1E34 |
| SCREEN_RAM_R12C32 = $0600 ; x-ref: $1063, $1124, $113E, $171D |
| SCREEN_RAM_R13C16 = $0618 ; x-ref: $1CA0, $1F11, $4685 |
| SCREEN_RAM_R13C20 = $061c ; x-ref: $1CC8 |
| SCREEN_RAM_R14C33 = $0651 ; x-ref: $5307, $5349 |
| SCREEN_RAM_R14C34 = $0652 ; x-ref: $5302, $5344 |
| SCREEN_RAM_R15C16 = $0668 ; x-ref: $1CA6, $1F30, $4695 |
| SCREEN_RAM_R15C20 = $066c ; x-ref: $1CD1 |
| SCREEN_RAM_R15C32 = $0678 ; x-ref: $1B71 |
| SCREEN_RAM_R16C11 = $068b ; x-ref: $14C5 |
| SCREEN_RAM_R16C23 = $0697 ; x-ref: $154E |
| SCREEN_RAM_R16C32 = $06a0 ; x-ref: $1127 |
| SCREEN_RAM_R17C16 = $06b8 ; x-ref: $1CAC, $1F4F, $46A5 |
| SCREEN_RAM_R17C20 = $06bc ; x-ref: $1CDA |
| SCREEN_RAM_R18C14 = $06de ; x-ref: $1567 |
| SCREEN_RAM_R18C32 = $06f0 ; x-ref: $1069, $1144, $1723, $1B77 |
| SCREEN_RAM_R19C16 = $0708 ; x-ref: $1CB2, $1F6E, $46B5 |
| SCREEN_RAM_R19C20 = $070c ; x-ref: $1CE3 |
| SCREEN_RAM_R20C39 = $0747 ; x-ref: $1505, $493D |
| SCREEN_RAM_R21C0 = $0748 ; x-ref: $4931 |
| SCREEN_RAM_R21C1 = $0749 ; x-ref: $4937 |
| SCREEN_RAM_R21C11 = $0753 ; x-ref: $490E |
| SCREEN_RAM_R21C14 = $0756 ; x-ref: $536A |
| SCREEN_RAM_R21C16 = $0758 ; x-ref: $1CB8, $1F89, $46C1 |
| SCREEN_RAM_R21C20 = $075c ; x-ref: $1CEC |
| SCREEN_RAM_R22C0 = $0770 ; x-ref: $4925, $4934 |
| SCREEN_RAM_R22C1 = $0771 ; x-ref: $492B, $493A |
| SCREEN_RAM_R22C2 = $0772 ; x-ref: $44C8 |
| SCREEN_RAM_R22C3 = $0773 ; x-ref: $44CF |
| SCREEN_RAM_R22C10 = $077a ; x-ref: $44DE |
| SCREEN_RAM_R22C11 = $077b ; x-ref: $4908, $4911 |
| SCREEN_RAM_R23C0 = $0798 ; x-ref: $4919, $4928 |
| SCREEN_RAM_R23C1 = $0799 ; x-ref: $491F, $492E |
| SCREEN_RAM_R23C2 = $079a ; x-ref: $451D |
| SCREEN_RAM_R23C3 = $079b ; x-ref: $44B8 |
| SCREEN_RAM_R23C6 = $079e ; x-ref: $4522 |
| SCREEN_RAM_R23C7 = $079f ; x-ref: $44F2 |
| SCREEN_RAM_R23C8 = $07a0 ; x-ref: $44F7 |
| SCREEN_RAM_R23C9 = $07a1 ; x-ref: $44FC |
| SCREEN_RAM_R23C10 = $07a2 ; x-ref: $44E3 |
| SCREEN_RAM_R23C11 = $07a3 ; x-ref: $4902, $490B |
| SCREEN_RAM_R24C0 = $07c0 ; x-ref: $491C |
| SCREEN_RAM_R24C1 = $07c1 ; x-ref: $4922 |
| SCREEN_RAM_R24C2 = $07c2 ; x-ref: $44ED |
| SCREEN_RAM_R24C3 = $07c3 ; x-ref: $44D4 |
| SCREEN_RAM_R24C10 = $07ca ; x-ref: $44E8 |
| SCREEN_RAM_R24C11 = $07cb ; x-ref: $4905 |
| sprite_ptr_0 = $07f8 ; x-ref: $104E, $10E4, $15EC, $1752, $1A2A, $1A87, $1A96, $1AAD, ... |
| sprite_ptr_1 = $07f9 ; x-ref: $10E9, $13BA, $49CD, $49D4, $49D9, $49DF, $49E4, $4A1F, ... |
| sprite_ptr_2 = $07fa ; x-ref: $10EE, $13C0 |
| sprite_ptr_3 = $07fb ; x-ref: $10F3 |
| sprite_ptr_4 = $07fc ; x-ref: $10F8 |
| sprite_ptr_5 = $07fd ; x-ref: $10FD, $3CCD, $45E0 |
| sprite_ptr_6 = $07fe ; x-ref: $1102 |
| sprite_ptr_7 = $07ff ; x-ref: $1164, $46F3 |
| level_nr = $0800 ; x-ref: $1202, $125A, $1303, $1574, $1577, $1FA7, $4878, $4F04, ... |
| level_block_idx = $0801 ; x-ref: $1207, $1306, $1378, $137B, $1583, $4898, $48B5 |
| level_tile_y_offset = $0802 ; x-ref: $120C, $1340, $136D, $1375, $1588, $4875 |
| season_nr = $0803 ; x-ref: $1211, $135F, $139C, $1542, $158B, $158E, $1597, $1726, ... |
| player_speed = $0804 ; x-ref: $1216, $1235, $1778, $3BE3, $3C02, $3E13, $3E1D, $3E42, ... |
| player_is_jumping = $0805 ; x-ref: $1230, $12C0, $1761, $182D, $1A08, $1A17, $1A3A, $1AD9, ... |
| jump_anim_frame = $0806 ; x-ref: $1A1C, $1AEB, $1AEE |
| player_x_offset = $0807 ; x-ref: $1247 |
| player_y_offset = $0808 ; x-ref: $124A, $4404, $440C |
| jump_timer_base = $0810 ; x-ref: $1A1F, $1A45, $1AFB |
| jump_frame_timer = $0811 ; x-ref: $1A25, $1A40, $1A4B |
| crashed_cars_tens = $0820 ; x-ref: $121C, $1435, $145F, $147B, $16A3, $179C, $1885, $4E39 |
| crashed_cars_ones = $0821 ; x-ref: $1226, $143E, $1464, $1484, $16A6, $16B9, $185B, $4E27, ... |
| lives_tens = $0822 ; x-ref: $16C2, $480F, $4812, $481B, $486B, $4985 |
| lives_ones = $0823 ; x-ref: $122B, $16CB, $3FC7, $4800, $4803, $480C, $4861, $4979, ... |
| score_7digits = $0825 ; x-ref: $15AB, $15B7, $15BE, $15CB, $15D7, $15DE, $16F4, $17E2, ... |
| scroll_row_counter = $0827 ; x-ref: $4940, $4948, $4952, $498C |
| crashed_cars_bonus_10k = $0830 ; x-ref: $1852, $1866, $1872, $1879, $1890, $189C, $18A3, $18B1, ... |
| crashed_cars_bonus_1k = $0831 ; x-ref: $1855, $18FE |
| crashed_cars_bonus_100 = $0832 ; x-ref: $1858, $18DD |
| name_entry_substate = $0857 ; x-ref: $1BAE, $1C28, $1C40, $1C54, $1C68, $1C7C, $1CF7, $1D0F, ... |
| highscore_timer_tens = $0858 ; x-ref: $1D5F, $1DBF, $1DC5, $1DC8, $1DD2, $1E25, $46C9 |
| highscore_timer_ones = $0859 ; x-ref: $1D64, $1DAD, $1DB3, $1DBC, $1DCD, $1DDB, $1E2E, $46CE |
| scroll_switch_timer_2 = $085a |
| pickup_mode_active = $085e ; x-ref: $124F, $46EC, $4709, $4712, $471F, $4728 |
| pickup_display_timer = $085f ; x-ref: $470E, $4718 |
| active_row = $0860 ; x-ref: $1D69, $1E48, $1E65, $1E6F, $1E72, $1E78, $1E82, $1E85, ... |
| active_col = $0861 ; x-ref: $1D6E, $1E43, $1E8B, $1E95, $1E98, $1E9B, $1EA1, $1EAB, ... |
| game_over_delay_ctr = $08c0 ; x-ref: $4624, $4631 |
| collision_rel_x = $08d3 ; x-ref: $39B4, $39BD, $3A03, $3B2F, $3B47, $3B7B |
| collision_rel_y = $08d4 ; x-ref: $39E1, $39EA, $3A08, $3A27, $3B80, $3B9F, $3EF4 |
| joy_poll_timeout = $08da ; x-ref: $51E3, $51F7 |
| score_digits = $08e0 ; x-ref: $123A, $176B, $3E24, $3E2A, $3E33, $3E53, $3E59, $3E62, ... |
| speed_tens_digit = $08e1 ; x-ref: $1242, $1773, $44AC |
| speed_hundreds_digit = $08e2 ; x-ref: $123D, $176E, $445C, $44A7 |
| busy_wait_delay_ctr = $08ff ; x-ref: $48E2, $48EF |
| f_0900 = $0900 ; x-ref: $1263, $3BD8, $3BF6, $4C68, $4C74, $4C83, $4CB1, $4CCB, ... |
| f_0904 = $0904 ; x-ref: $4AEF, $4C21, $4D6E, $4D83, $4D8A, $4D92 |
| f_0908 = $0908 ; x-ref: $4AF6, $4C19, $4DA2 |
| tbl_enemy_sprite_state = $090c ; x-ref: $3A52, $3C73, $3D07, $3D4C, $4B00, $4B0C, $4C02, $5230 |
| tbl_enemy_sprite_direction = $0910 ; x-ref: $3A0F, $3A14, $3A1C, $3A21, $3A2E, $3A33, $3A3B, $3A40, ... |
| tbl_enemy_sprite_step_count = $0914 ; x-ref: $3A82, $3AA6, $3BCA, $3D21, $3D52, $3D6E, $3D8A, $4B06 |
| f_0918 = $0918 ; x-ref: $4B09 |
| tbl_enemy_sprite_lifetime = $0920 ; x-ref: $3AB2, $3ABA, $3AC6, $3ACE, $3BF0, $3D3F, $4B0F |
| tbl_enemy_sprite_active = $0924 ; x-ref: $3A43, $3A48, $3A5A, $3A5D, $3BBD, $3C6C, $3D02, $3D49, ... |
| tbl_enemy_car_state = $0928 ; x-ref: $177D, $3982, $3996, $3B07, $3C80, $3EEE, $4554, $49C6, ... |
| tbl_enemy_car_state_1 = $0929 ; x-ref: $1780 |
| tbl_enemy_car_state_2 = $092a ; x-ref: $1783 |
| tbl_enemy_car_state_3 = $092b ; x-ref: $1786 |
| tbl_enemy_car_type = $092c ; x-ref: $3A64, $3A68, $3A89, $3A8D, $3AA9, $3ABD, $3BC3, $3C88, ... |
| tbl_npc_damage_timer = $0930 ; x-ref: $3C94, $45CD, $4E66 |
| tbl_enemy_car_fresh_flag = $0934 ; x-ref: $4EF1, $4F25, $4FA9 |
| tbl_score_sprite_active = $0980 ; x-ref: $1789, $3C99, $3CD2, $45D2, $45E5, $4E9A, $4EAC |
| tbl_score_sprite_active_1 = $0981 ; x-ref: $178C |
| tbl_score_sprite_active_2 = $0982 ; x-ref: $178F |
| f_0983 = $0983 ; x-ref: $3CAC, $4E3D, $4EA5 |
| scroll_row_snapshot = $0986 ; x-ref: $1252, $4943, $494C, $4956, $498F |
| dist_substep = $0987 ; x-ref: $1255, $4961, $4967, $4970 |
| col_quadrant = $0988 ; x-ref: $3B87, $3B94, $3BA6, $3BB3, $3DB6, $3E08, $3EA0 |
| col_step_px = $0989 ; x-ref: $3BD0, $3DC1, $3DDE |
| col_active = $098a ; x-ref: $1792, $17A0, $17CE, $3BC0, $3DB0, $3DDA, $3DF7 |
| col_frames_left = $098b ; x-ref: $3C0F, $3DD2, $3DEF |
| f_0A00 = $0a00 ; x-ref: $125D, $500C, $50AF, $51AC |
| buf_a_pending_cars_lo = $0a22 ; x-ref: $5116, $5181 |
| buf_a_pending_cars_hi = $0a23 ; x-ref: $5111, $517C |
| f_0B00 = $0b00 ; x-ref: $1266, $5012, $50B5, $51B2 |
| f_0C00 = $0c00 ; x-ref: $1260, $5025, $5096, $518B |
| buf_c_pending_cars_lo = $0c22 ; x-ref: $5123, $51A2 |
| buf_c_pending_cars_hi = $0c23 ; x-ref: $511E, $519D |
| f_0D00 = $0d00 ; x-ref: $1269, $502B, $509C, $5191 |
| number_of_players = $0f00 ; x-ref: $3FE7, $3FEF, $5003, $507B, $50BE, $5100 |
| current_player_nr = $0f01 ; x-ref: $3FE4, $3FF4, $501C, $504A, $508E, $50A7, $50C8, $510A, ... |
| hi_score_7digits = $0f50 ; x-ref: $1198, $16FD, $17DF, $17F4 |
| COLOR_RAM = $d800 ; x-ref: $1073, $1E3F, $4637 |
| COLOR_RAM_R1C0 = $d828 ; x-ref: $1365, $13A2, $172C, $1B7C, $1B93 |
| COLOR_RAM_R2C0 = $d850 ; x-ref: $1078 |
| COLOR_RAM_R3C0 = $d878 ; x-ref: $107B |
| COLOR_RAM_R3C11 = $d883 ; x-ref: $1418 |
| COLOR_RAM_R5C0 = $d8c8 ; x-ref: $1080 |
| COLOR_RAM_R5C10 = $d8d2 ; x-ref: $142D |
| COLOR_RAM_R6C0 = $d8f0 ; x-ref: $114E |
| COLOR_RAM_R6C16 = $d900 ; x-ref: $172F, $1B7F, $5042, $5072 |
| COLOR_RAM_R7C12 = $d924 ; x-ref: $1457 |
| COLOR_RAM_R8C0 = $d940 ; x-ref: $1083 |
| COLOR_RAM_R9C11 = $d973 ; x-ref: $149D |
| COLOR_RAM_R9C12 = $d974 ; x-ref: $1473 |
| COLOR_RAM_R9C16 = $d978 ; x-ref: $461A |
| COLOR_RAM_R9C23 = $d97f ; x-ref: $18C5 |
| COLOR_RAM_R9C26 = $d982 ; x-ref: $18D7 |
| COLOR_RAM_R9C27 = $d983 ; x-ref: $18DA |
| COLOR_RAM_R11C0 = $d9b8 ; x-ref: $1086 |
| COLOR_RAM_R11C3 = $d9bb ; x-ref: $1E06 |
| COLOR_RAM_R11C17 = $d9c9 ; x-ref: $14B2 |
| COLOR_RAM_R11C19 = $d9cb ; x-ref: $1E39 |
| COLOR_RAM_R11C20 = $d9cc ; x-ref: $1E3C |
| COLOR_RAM_R12C16 = $d9f0 ; x-ref: $1151 |
| COLOR_RAM_R12C32 = $da00 ; x-ref: $1732, $1B82 |
| COLOR_RAM_R14C0 = $da30 ; x-ref: $1089 |
| COLOR_RAM_R16C11 = $da8b ; x-ref: $14CA |
| COLOR_RAM_R16C23 = $da97 ; x-ref: $1553 |
| COLOR_RAM_R17C0 = $daa8 ; x-ref: $108E |
| COLOR_RAM_R17C24 = $dac0 ; x-ref: $1154 |
| COLOR_RAM_R18C14 = $dade ; x-ref: $156C |
| COLOR_RAM_R18C32 = $daf0 ; x-ref: $1735 |
| COLOR_RAM_R19C0 = $daf8 ; x-ref: $1091 |
| COLOR_RAM_R19C8 = $db00 ; x-ref: $1B85 |
| COLOR_RAM_R21C0 = $db48 ; x-ref: $1094 |
| COLOR_RAM_R21C14 = $db56 ; x-ref: $536F |
| COLOR_RAM_R22C2 = $db72 ; x-ref: $4503 |
| COLOR_RAM_R23C0 = $db98 ; x-ref: $1099 |
| COLOR_RAM_R23C2 = $db9a ; x-ref: $4506 |
| COLOR_RAM_R23C3 = $db9b ; x-ref: $44BD |
| COLOR_RAM_R24C2 = $dbc2 ; x-ref: $4509 |
| f_DBFF = $dbff ; x-ref: $56E6 |
| e_E097 = $e097 ; x-ref: $4A0F, $4A24, $4A8D |
| e_EA7E = $ea7e ; x-ref: $573E |
| KERNAL_RESET_VECTOR = $fce2 ; x-ref: $8000 |
| sfx_voice_1_state = $7080 ; x-ref: $1279, $539D, $53B2, $53DA, $53F5 |
| sfx_voice_1_freq_lo = $7081 ; x-ref: $127C, $53A2, $53C5, $53EA |
| sfx_voice_1_freq_mod = $7082 ; x-ref: $127F, $53B6, $53C9, $53CE, $53E2, $53E5 |
| f_7400 = $7400 ; x-ref: $11AE, $1B9D, $1C71, $1C8D, $1CC2 |
| f_7408 = $7408 ; x-ref: $1BBB, $1C5D, $1C74, $1CCB |
| f_7410 = $7410 ; x-ref: $1BD6, $1C49, $1C60, $1CD4 |
| f_7418 = $7418 ; x-ref: $1BF1, $1C35, $1C4C, $1CDD |
| f_7420 = $7420 ; x-ref: $1C0C, $1C38, $1CE6 |
| f_7430 = $7430 ; x-ref: $11A9, $1C92, $1C9D, $1D40, $1F0E, $4682 |
| f_7438 = $7438 ; x-ref: $1CA3, $1D2C, $1D43, $1F2D, $4692 |
| f_7440 = $7440 ; x-ref: $1CA9, $1D18, $1D2F, $1F4C, $46A2 |
| f_7448 = $7448 ; x-ref: $1CAF, $1D04, $1D1B, $1F6B, $46B2 |
| f_7450 = $7450 ; x-ref: $1CB5, $1D07, $1F86, $46BE |
|
| ; ENUMS |
| ; Enum: VicIIColors |
| VicIIColors = { |
| BLACK: $00, |
| WHITE: $01, |
| RED: $02, |
| CYAN: $03, |
| PURPLE: $04, |
| GREEN: $05, |
| BLUE: $06, |
| YELLOW: $07, |
| ORANGE: $08, |
| BROWN: $09, |
| LIGHT_RED: $0a, |
| DARK_GREY: $0b, |
| GREY: $0c, |
| LIGHT_GREEN: $0d, |
| LIGHT_BLUE: $0e, |
| LIGHT_GREY: $0f |
| } |
|
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the VIC-II video chip settings for the game. |
| ; Clears sprite coordinates, enables multi-color mode for character display, |
| ; sets up global border and background colors, and configures sprite sizes, |
| ; priorities, and multi-color settings. Also sets the character memory pointer. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies VIC-II registers ($D000-$D026) and Sprite 0 pointer ($07F8) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1000 | a2 00 | init_vic_videoldx#$00; x-ref: $1803 |
| $1002 | 8a | txa |
| $1003 | 9d 00 d0 | b_1003sta$d000,x; Clear sprite coordinates ($D000-$D010) ; x-ref: $1009 Sprite 0 X Pos |
| $1006 | e8 | inx |
| $1007 | e0 11 | cpx#$11 |
| $1009 | d0 f8 | bneb_1003 |
| $100B | 8d 17 d0 | sta$d017; Sprites Expand 2x Vertical (Y) |
| $100E | 8d 1b d0 | sta$d01b; Sprite to Background Display Priority |
| $1011 | 8d 1d d0 | sta$d01d; Sprites Expand 2x Horizontal (X) |
| $1014 | a9 ff | lda#$ff |
| $1016 | 8d 15 d0 | sta$d015; Sprite display Enable |
| $1019 | 8d 1c d0 | sta$d01c; Sprites Multi-Color Mode Select |
| $101C | a9 00 | lda#$00 |
| $101E | 8d 20 d0 | sta$d020; Border Color |
| $1021 | a9 0b | lda#$0b |
| $1023 | 8d 21 d0 | sta$d021; Background Color 0 |
| $1026 | a9 00 | lda#$00 |
| $1028 | 8d 22 d0 | sta$d022; Background Color 1, Multi-Color Register 0 |
| $102B | a9 06 | lda#$06 |
| $102D | 8d 23 d0 | sta$d023; Background Color 2, Multi-Color Register 1 |
| $1030 | a9 00 | lda#$00 |
| $1032 | 8d 25 d0 | sta$d025; Sprite Multi-Color Register 0 |
| $1035 | a9 02 | lda#$02 |
| $1037 | 8d 26 d0 | sta$d026; Sprite Multi-Color Register 1 |
| $103A | ad 16 d0 | lda$d016; VIC Control Register 2 |
| $103D | 09 10 | ora#$10 |
| $103F | 8d 16 d0 | sta$d016; VIC Control Register 2 |
| $1042 | ad 18 d0 | lda$d018; VIC Memory Control Register |
| $1045 | 29 f0 | and#$f0 |
| $1047 | 09 08 | ora#$08; Set character memory to $2000 |
| $1049 | 8d 18 d0 | sta$d018; VIC Memory Control Register |
| $104C | a9 c0 | lda#$c0 |
| $104E | 8d f8 07 | stasprite_ptr_0; Sprite 0 pointer points to $3000 |
| $1051 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the screen display, background colors, and title/game sprites. |
| ; This routine runs at startup to paint the initial screen layout to Screen RAM |
| ; ($0400) and Color RAM ($D800). It establishes the sprite positions and does a |
| ; fade-in effect by shifting bits into the sprite enable register ($D015) before |
| ; switching to a second screen layout ($2800). |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies Screen RAM ($0400), Color RAM ($D800), and all Sprite |
| ; registers in ($D000-$D015). Loops through wait delays. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| init_screen_and_sprites |
| $1052 | a2 00 | ldx#$00; x-ref: $1806 |
| $1054 | bd 00 24 | b_1054ldaf_2400,x; Copy layout 1 ($2400) to Screen RAM ($0400) ; x-ref: $106D |
| $1057 | 9d 00 04 | staSCREEN_RAM,x |
| $105A | bd 00 25 | ldaf_2500,x |
| $105D | 9d 00 05 | staSCREEN_RAM_R6C16,x |
| $1060 | bd 00 26 | ldaf_2600,x |
| $1063 | 9d 00 06 | staSCREEN_RAM_R12C32,x |
| $1066 | bd f0 26 | ldaf_26F0,x |
| $1069 | 9d f0 06 | staSCREEN_RAM_R18C32,x |
| $106C | e8 | inx |
| $106D | d0 e5 | bneb_1054 |
| $106F | a2 00 | ldx#$00 |
| $1071 | a9 04 | b_1071lda#VicIIColors.PURPLE; x-ref: $109F |
| $1073 | 9d 00 d8 | staCOLOR_RAM,x; Color Memory ($D800) Setup |
| $1076 | a9 0f | lda#VicIIColors.LIGHT_GREY |
| $1078 | 9d 50 d8 | staCOLOR_RAM_R2C0,x |
| $107B | 9d 78 d8 | staCOLOR_RAM_R3C0,x |
| $107E | a9 03 | lda#VicIIColors.CYAN |
| $1080 | 9d c8 d8 | staCOLOR_RAM_R5C0,x |
| $1083 | 9d 40 d9 | staCOLOR_RAM_R8C0,x |
| $1086 | 9d b8 d9 | staCOLOR_RAM_R11C0,x |
| $1089 | 9d 30 da | staCOLOR_RAM_R14C0,x |
| $108C | a9 01 | lda#VicIIColors.WHITE |
| $108E | 9d a8 da | staCOLOR_RAM_R17C0,x |
| $1091 | 9d f8 da | staCOLOR_RAM_R19C0,x |
| $1094 | 9d 48 db | staCOLOR_RAM_R21C0,x |
| $1097 | a9 04 | lda#VicIIColors.PURPLE |
| $1099 | 9d 98 db | staCOLOR_RAM_R23C0,x |
| $109C | e8 | inx |
| $109D | e0 50 | cpx#$50 |
| $109F | d0 d0 | bneb_1071 |
| $10A1 | a9 00 | lda#$00 |
| $10A3 | 20 ca 11 | jsrenable_sprites_and_update_hud |
| $10A6 | a9 38 | lda#$38 |
| $10A8 | 8d 00 d0 | sta$d000; Setup Sprites 0-7 X/Y Coordinates; Sprite 0 X Pos |
| $10AB | 8d 02 d0 | sta$d002; Sprite 1 X Pos |
| $10AE | 8d 04 d0 | sta$d004; Sprite 2 X Pos |
| $10B1 | 8d 06 d0 | sta$d006; Sprite 3 X Pos |
| $10B4 | a9 d0 | lda#$d0 |
| $10B6 | 8d 08 d0 | sta$d008; Sprite 4 X Pos |
| $10B9 | 8d 0a d0 | sta$d00a; Sprite 5 X Pos |
| $10BC | 8d 0c d0 | sta$d00c; Sprite 6 X Pos |
| $10BF | 8d 0e d0 | sta$d00e; Sprite 7 X Pos |
| $10C2 | a9 5a | lda#$5a |
| $10C4 | 8d 01 d0 | sta$d001; Sprite 0 Y Pos |
| $10C7 | 8d 09 d0 | sta$d009; Sprite 4 Y Pos |
| $10CA | a9 72 | lda#$72 |
| $10CC | 8d 03 d0 | sta$d003; Sprite 1 Y Pos |
| $10CF | 8d 0b d0 | sta$d00b; Sprite 5 Y Pos |
| $10D2 | a9 8a | lda#$8a |
| $10D4 | 8d 05 d0 | sta$d005; Sprite 2 Y Pos |
| $10D7 | 8d 0d d0 | sta$d00d; Sprite 6 Y Pos |
| $10DA | a9 a2 | lda#$a2 |
| $10DC | 8d 07 d0 | sta$d007; Sprite 3 Y Pos |
| $10DF | 8d 0f d0 | sta$d00f; Sprite 7 Y Pos |
| $10E2 | a9 c2 | lda#$c2 |
| $10E4 | 8d f8 07 | stasprite_ptr_0; Setup Sprites 0-7 Pointers |
| $10E7 | a9 c4 | lda#$c4 |
| $10E9 | 8d f9 07 | stasprite_ptr_1 |
| $10EC | a9 c6 | lda#$c6 |
| $10EE | 8d fa 07 | stasprite_ptr_2 |
| $10F1 | a9 c8 | lda#$c8 |
| $10F3 | 8d fb 07 | stasprite_ptr_3 |
| $10F6 | a9 ca | lda#$ca |
| $10F8 | 8d fc 07 | stasprite_ptr_4 |
| $10FB | a9 cc | lda#$cc |
| $10FD | 8d fd 07 | stasprite_ptr_5 |
| $1100 | a9 ce | lda#$ce |
| $1102 | 8d fe 07 | stasprite_ptr_6 |
| $1105 | a9 d0 | lda#$d0 |
| $1107 | 20 64 11 | jsrinit_sprite_colors |
| $110A | 20 d0 11 | j_110Ajsrdelay_with_fire_check; x-ref: $1117 |
| $110D | ad 15 d0 | lda$d015; Sprite display Enable |
| $1110 | 0a | asla; Slide/Fade in Sprite Enable bits |
| $1111 | 18 | clc |
| $1112 | 69 01 | adc#$01 |
| $1114 | 8d 15 d0 | sta$d015; Sprite display Enable |
| $1117 | 4c 0a 11 | jmpj_110A |
| $111A | a2 00 | j_111Aldx#$00; x-ref: $11EB |
| $111C | a9 20 | lda#$20 |
| $111E | 9d d0 04 | b_111EstaSCREEN_RAM_R5C8,x; x-ref: $112B |
| $1121 | 9d 00 05 | staSCREEN_RAM_R6C16,x |
| $1124 | 9d 00 06 | staSCREEN_RAM_R12C32,x |
| $1127 | 9d a0 06 | staSCREEN_RAM_R16C32,x |
| $112A | e8 | inx |
| $112B | d0 f1 | bneb_111E |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the title screen by copying layout data to Screen RAM, setting |
| ; Color RAM, disabling sprites, and jumping to the title screen menu. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies Screen RAM ($0400-$07E7), Color RAM ($D8F0-$DBBF), and |
| ; $D015 (Sprite display enable). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $112D | a2 00 | init_title_screenldx#$00; Initialize copy index |
| $112F | bd 00 28 | b_112Fldainstructions_screen_1,x; Copy layout data to Screen RAM ; x-ref: $1158 |
| $1132 | 9d 00 04 | staSCREEN_RAM,x |
| $1135 | bd 00 29 | ldainstructions_screen_2,x |
| $1138 | 9d 00 05 | staSCREEN_RAM_R6C16,x |
| $113B | bd 00 2a | ldainstructions_screen_3,x |
| $113E | 9d 00 06 | staSCREEN_RAM_R12C32,x |
| $1141 | bd f0 2a | ldainstructions_screen_4,x |
| $1144 | 9d f0 06 | staSCREEN_RAM_R18C32,x |
| $1147 | a9 00 | lda#$00; Disable all sprites |
| $1149 | 8d 15 d0 | sta$d015; Sprite display Enable |
| $114C | a9 07 | lda#VicIIColors.YELLOW; Set color to yellow ($07) |
| $114E | 9d f0 d8 | staCOLOR_RAM_R6C0,x; Apply yellow to specific Color RAM areas |
| $1151 | 9d f0 d9 | staCOLOR_RAM_R12C16,x |
| $1154 | 9d c0 da | staCOLOR_RAM_R17C24,x |
| $1157 | e8 | inx |
| $1158 | d0 d5 | bneb_112F |
| $115A | a9 10 | lda#$10; Set A to $10 for menu init |
| $115C | 4c cb 3f | jmptitle_screen_menu; Jump to title screen menu |
| ; dead code |
| $115F | | .byte$d0, $f9, $4c, $8e, $11 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes colors for all 8 hardware sprites and sets sprite pointer 7. |
| ; |
| ; Inputs: A = Value for sprite pointer 7 |
| ; Outputs: None |
| ; Side Effects: Modifies VIC-II sprite color registers ($D027-$D02E) and sprite pointer 7. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1164 | 8d ff 07 | init_sprite_colorsstasprite_ptr_7; Set sprite pointer 7 ; x-ref: $1107 |
| $1167 | a9 01 | lda#$01; Set Sprite 0 and 1 colors to white ($01) |
| $1169 | 8d 27 d0 | sta$d027; Sprite 0 Color |
| $116C | 8d 28 d0 | sta$d028; Sprite 1 Color |
| $116F | a9 07 | lda#$07; Set Sprite 3 color to yellow ($07) |
| $1171 | 8d 2a d0 | sta$d02a; Sprite 3 Color |
| $1174 | a9 0e | lda#$0e; Set Sprite 4 and 5 colors to light blue ($0E) |
| $1176 | 8d 2b d0 | sta$d02b; Sprite 4 Color |
| $1179 | a9 0e | lda#$0e |
| $117B | 8d 2c d0 | sta$d02c; Sprite 5 Color |
| $117E | a9 04 | lda#$04; Set Sprite 2 color to purple ($04) |
| $1180 | 8d 29 d0 | sta$d029; Sprite 2 Color |
| $1183 | a9 05 | lda#$05; Set Sprite 6 color to green ($05) |
| $1185 | 8d 2d d0 | sta$d02d; Sprite 6 Color |
| $1188 | a9 0d | lda#$0d; Set Sprite 7 color to light green ($0D) |
| $118A | 8d 2e d0 | sta$d02e; Sprite 7 Color |
| $118D | 60 | rts |
| $118E | 20 00 12 | j_118Ejsrinit_game_vars; x-ref: $3FEA, $3FF7 |
| $1191 | 20 0c 17 | jsrinit_level_screen |
| $1194 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the game state, memory buffers, and SID audio filters. |
| ; This routine sets up several 256-byte pages ($0800-$0DFF), clears object/sprite |
| ; buffers, and resets various variables at the start of $0800. It also initializes |
| ; the SID chip's filter and volume settings initially calling `$1195` then jumping |
| ; to `$1200` to complete the rest of the work. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies memory regions $0800-$0DFF, $0F50-$0F56, $7400-$7457, |
| ; and SID registers $D415-$D418. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1195 | a2 00 | init_game_stateldx#$00; x-ref: $1800 |
| $1197 | 8a | txa |
| $1198 | 9d 50 0f | b_1198stahi_score_7digits,x; x-ref: $119E |
| $119B | e8 | inx |
| $119C | e0 07 | cpx#$07 |
| $119E | d0 f8 | bneb_1198 |
| $11A0 | a9 4f | lda#$4f |
| $11A2 | 8d 18 d4 | sta$d418; SID Mode/Volume; Select Filter Mode and Volume |
| $11A5 | a2 00 | ldx#$00 |
| $11A7 | a9 20 | b_11A7lda#$20; x-ref: $11B4 |
| $11A9 | 9d 30 74 | staf_7430,x |
| $11AC | a9 00 | lda#$00 |
| $11AE | 9d 00 74 | staf_7400,x |
| $11B1 | e8 | inx |
| $11B2 | e0 28 | cpx#$28 |
| $11B4 | d0 f1 | bneb_11A7 |
| $11B6 | a9 06 | lda#$06 |
| $11B8 | 8d 17 d4 | sta$d417; SID Resonance/Voice Input; Filter Resonance Control / Voice Input Control |
| $11BB | 4c 00 12 | jmpinit_game_vars |
| $11BE | | .fill11, $00 |
| $11C9 | | .byte$8d |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the sprite display enable mask and tail-calls the HUD update routine. |
| ; |
| ; Inputs: A = Sprite enable bitmask |
| ; Outputs: None |
| ; Side Effects: Modifies $D015 (Sprite display enable) and updates HUD display. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| enable_sprites_and_update_hud |
| $11CA | 8d 15 d0 | sta$d015; Set sprite display enable mask ; x-ref: $10A3 Sprite display Enable |
| $11CD | 4c b0 16 | jmpupdate_hud_display; Tail call to update HUD |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Performs a delay loop while polling the fire button. If the fire button is |
| ; pressed during the delay, it waits for release, unwinds the stack, and aborts. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: May discard stack return address and jump to j111A on fire press. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| delay_with_fire_check |
| $11D0 | a2 00 | ldx#$00; Initialize X delay counter ; x-ref: $110A |
| $11D2 | a0 00 | b_11D2ldy#$00; Initialize Y delay counter ; x-ref: $11DF |
| $11D4 | a9 10 | b_11D4lda#$10; Bit mask for fire button ; x-ref: $11DC |
| $11D6 | 2c f5 00 | bit@w zp_joy_state; Check joystick state |
| $11D9 | f0 07 | beqb_11E2; If pressed (0), branch to wait-for-release loop |
| $11DB | 88 | dey |
| $11DC | d0 f6 | bneb_11D4 |
| $11DE | ca | dex |
| $11DF | d0 f1 | bneb_11D2 |
| $11E1 | 60 | rts |
| $11E2 | a9 10 | b_11E2lda#$10; Wait loop: mask for fire button ; x-ref: $11D9, $11E7 |
| $11E4 | 2c f5 00 | bit@w zp_joy_state |
| $11E7 | f0 f9 | beqb_11E2; Loop until fire button is released (non-zero) |
| $11E9 | 68 | pla; Discard return address (low byte) |
| $11EA | 68 | pla; Discard return address (high byte) |
| $11EB | 4c 1a 11 | jmpj_111A; Abort current call chain |
| $11EE | | .byte$00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Convenience routine to initialize the HUD and trigger a screen scroll down. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Calls init_hud and scroll_screen_down routines. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| init_hud_and_scroll_screen_down |
| $11F0 | 20 b0 44 | jsrinit_hud; Initialize Heads Up Display ; x-ref: $1300 |
| $11F3 | 20 00 15 | jsrscroll_screen_down; Scroll the screen down one row |
| $11F6 | 60 | rts |
| $11F7 | | .fill9, $00 |
| level_nr_self_modifiying =*+$01 ; x-ref: $3FD1, $5311, $5314, $531D |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes game variables and duplicates memory pages. |
| ; This routine resets various state variables in the $0800-$09FF range, zeroes |
| ; out specific arrays, and then creates two copies of the $0800-$09FF memory pages |
| ; at $0A00-$0BFF and $0C00-$0DFF. It finally resets the SID filter cutoff frequency. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies memory $0800-$0DFF, $7080-$7082, and SID $D415-$D416. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1200 | a9 00 | init_game_varslda#$00; x-ref: $118E, $11BB |
| $1202 | 8d 00 08 | stalevel_nr |
| $1205 | a9 00 | lda#$00 |
| $1207 | 8d 01 08 | stalevel_block_idx |
| $120A | a9 18 | lda#24 |
| $120C | 8d 02 08 | stalevel_tile_y_offset |
| $120F | a9 00 | lda#$00 |
| $1211 | 8d 03 08 | staseason_nr |
| $1214 | a9 80 | lda#$80 |
| $1216 | 8d 04 08 | staplayer_speed |
| $1219 | a9 00 | lda#$00 |
| $121B | aa | tax; Clear $0820-$084E |
| $121C | 9d 20 08 | b_121Cstacrashed_cars_tens,x; x-ref: $1222 |
| $121F | e8 | inx |
| $1220 | e0 2f | cpx#$2f |
| $1222 | d0 f8 | bneb_121C |
| $1224 | a9 00 | lda#$00 |
| $1226 | 8d 21 08 | stacrashed_cars_ones |
| $1229 | a9 03 | lda#$03 |
| $122B | 8d 23 08 | stalives_ones |
| $122E | a9 00 | lda#$00 |
| $1230 | 8d 05 08 | staplayer_is_jumping |
| $1233 | a9 50 | lda#$50 |
| $1235 | 8d 04 08 | staplayer_speed |
| $1238 | a9 00 | lda#$00 |
| $123A | 8d e0 08 | stascore_digits |
| $123D | 8d e2 08 | staspeed_hundreds_digit |
| $1240 | a9 08 | lda#$08 |
| $1242 | 8d e1 08 | staspeed_tens_digit |
| $1245 | a9 00 | lda#$00 |
| $1247 | 8d 07 08 | staplayer_x_offset |
| $124A | 8d 08 08 | staplayer_y_offset |
| $124D | a9 00 | lda#$00 |
| $124F | 8d 5e 08 | stapickup_mode_active |
| $1252 | 8d 86 09 | stascroll_row_snapshot |
| $1255 | 8d 87 09 | stadist_substep |
| $1258 | a2 00 | ldx#$00 |
| $125A | bd 00 08 | b_125Aldalevel_nr,x; Copy $0800-$08FF to $0A00 and $0C00 ; x-ref: $126D |
| $125D | 9d 00 0a | staf_0A00,x |
| $1260 | 9d 00 0c | staf_0C00,x |
| $1263 | bd 00 09 | ldaf_0900,x; Copy $0900-$09FF to $0B00 and $0D00 |
| $1266 | 9d 00 0b | staf_0B00,x |
| $1269 | 9d 00 0d | staf_0D00,x |
| $126C | e8 | inx |
| $126D | d0 eb | bneb_125A |
| $126F | a9 00 | lda#$00 |
| $1271 | 8d 15 d4 | sta$d415; Filter Cutoff Frequency: Low-Nybble |
| $1274 | a9 00 | lda#$00 |
| $1276 | 8d 16 d4 | sta$d416; Filter Cutoff Frequency: High-Byte |
| $1279 | 8d 80 70 | stasfx_voice_1_state |
| $127C | 8d 81 70 | stasfx_voice_1_freq_lo |
| $127F | 8d 82 70 | stasfx_voice_1_freq_mod |
| $1282 | 60 | rts |
| $1283 | | .fill13, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; MAIN ENTRY POINT |
| ; This code was in the tape loader. |
| ; Moved to the "main" binary to have a single-load game |
| $1290 | 78 | startsei |
| $1291 | a9 53 | lda#>irq_handler_music |
| $1293 | 8d 15 03 | staIRQ_VEC_HI; IRQ |
| $1296 | a9 98 | lda#<irq_handler_music |
| $1298 | 8d 14 03 | staIRQ_VEC_LO; IRQ |
| $129B | 58 | cli |
| $129C | 4c 00 18 | jmpmain |
| $129F | | .fill33, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Silences SID Voice 1. |
| ; However, if the player is jumping, it pops 4 bytes from the stack to bypass |
| ; both this routine and its caller (reset_voice1_state) and returns directly |
| ; to the caller of reset_voice1_state (e.g., play_crash_sfx). |
| ; This prevents crash sounds from playing while jumping. |
| ; |
| ; Inputs: player_is_jumping |
| ; Outputs: None |
| ; Side Effects: Silences Voice 1 or manipulates stack to bail early. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| silence_voice1_or_bail_if_jumping |
| $12C0 | ad 05 08 | ldaplayer_is_jumping; x-ref: $3E73 |
| $12C3 | f0 05 | beqb_12CA |
| $12C5 | 68 | pla |
| $12C6 | 68 | pla |
| $12C7 | 68 | pla |
| $12C8 | 68 | pla |
| $12C9 | 60 | rts |
| $12CA | a9 00 | b_12CAlda#$00; x-ref: $12C3 |
| $12CC | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| $12CF | 60 | rts |
| $12D0 | | .fill32, $00 |
| ; Cartridge cold-start entry point (referenced by vector at $8002) |
| cartridge_reset_entry |
| $12F0 | 58 | cli; x-ref: $8002 |
| $12F1 | a2 fb | ldx#$fb |
| $12F3 | 9a | txs |
| $12F4 | 4c 03 18 | jmpgame_init_and_loop |
| $12F7 | | .fill9, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Scrolls the playfield down and fetches the next row of map tile data. |
| ; First, it shifts Screen RAM down by one row to create a scrolling effect. |
| ; Then, it computes a pointer to the level map array ($4000) based on the current |
| ; scroll position to grab a 1024-byte map tile ID. Because tile data is located |
| ; at $8010 and stretches underneath the BASIC ROM ($A000-$BFFF), the caller must |
| ; bank out BASIC first. It finally copies 40 bytes of the tile row into Screen RAM |
| ; at $0428 (row 1, leaving the UI row intact) and updates Color RAM. |
| ; |
| ; Inputs: $0800 (level nr), $0801 (Map Block Column), $0802 (Tile Y offset) |
| ; Outputs: None |
| ; Side Effects: Modifies Screen RAM ($0428+), Color RAM, and pointers at $49/$4A. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| scroll_and_draw_map_row |
| $1300 | 20 f0 11 | jsrinit_hud_and_scroll_screen_down; Scroll screen downward ; x-ref: $180F |
| $1303 | ae 00 08 | ldxlevel_nr |
| $1306 | ac 01 08 | ldylevel_block_idx |
| $1309 | a9 00 | lda#<level_tile_tbl |
| $130B | 85 49 | stazp_p_tmp_lo |
| $130D | a9 40 | lda#>level_tile_tbl |
| $130F | 85 4a | stazp_p_tmp_hi |
| $1311 | e0 00 | j_1311cpx#$00; x-ref: $1323 |
| $1313 | f0 11 | beqb_1326 |
| $1315 | a5 49 | ldazp_p_tmp_lo |
| $1317 | 18 | clc |
| $1318 | 69 20 | adc#$20 |
| $131A | 85 49 | stazp_p_tmp_lo |
| $131C | a5 4a | ldazp_p_tmp_hi |
| $131E | 69 00 | adc#$00 |
| $1320 | 85 4a | stazp_p_tmp_hi |
| $1322 | ca | dex |
| $1323 | 4c 11 13 | jmpj_1311 |
| $1326 | b1 49 | b_1326lda(zp_p_tmp_lo),y; x-ref: $1313 |
| $1328 | aa | tax |
| $1329 | a9 10 | lda#<level_tile_definition_tbl |
| $132B | 85 49 | stazp_p_tmp_lo |
| $132D | a9 80 | lda#>level_tile_definition_tbl |
| $132F | 85 4a | stazp_p_tmp_hi |
| $1331 | ca | j_1331dex; x-ref: $133D |
| $1332 | e0 00 | cpx#$00 |
| $1334 | f0 0a | beqb_1340 |
| $1336 | a5 4a | ldazp_p_tmp_hi |
| $1338 | 18 | clc |
| $1339 | 69 04 | adc#$04 |
| $133B | 85 4a | stazp_p_tmp_hi |
| $133D | 4c 31 13 | jmpj_1331 |
| $1340 | ae 02 08 | b_1340ldxlevel_tile_y_offset; x-ref: $1334 |
| $1343 | e0 00 | j_1343cpx#$00; x-ref: $1355 |
| $1345 | f0 11 | beqb_1358 |
| $1347 | a5 49 | ldazp_p_tmp_lo |
| $1349 | 18 | clc |
| $134A | 69 28 | adc#$28 |
| $134C | 85 49 | stazp_p_tmp_lo |
| $134E | a5 4a | ldazp_p_tmp_hi |
| $1350 | 69 00 | adc#$00 |
| $1352 | 85 4a | stazp_p_tmp_hi |
| $1354 | ca | dex |
| $1355 | 4c 43 13 | jmpj_1343 |
| $1358 | a0 00 | b_1358ldy#$00; x-ref: $1345 |
| $135A | b1 49 | b_135Alda(zp_p_tmp_lo),y; x-ref: $136B |
| $135C | 99 28 04 | staSCREEN_RAM_R1C0,y |
| $135F | ae 03 08 | ldxseason_nr |
| $1362 | bd 7c 16 | ldatbl_text_color_seasons,x; One byte per season (0=Summer, 1=Autumn, 2=Winter, 3=Spring) |
| $1365 | 99 28 d8 | staCOLOR_RAM_R1C0,y |
| $1368 | c8 | iny |
| $1369 | c0 28 | cpy#$28 |
| $136B | d0 ed | bneb_135A |
| $136D | ce 02 08 | declevel_tile_y_offset |
| $1370 | 30 01 | bmib_1373 |
| $1372 | 60 | rts |
| $1373 | a9 18 | b_1373lda#24; x-ref: $1370 |
| $1375 | 8d 02 08 | stalevel_tile_y_offset |
| $1378 | ee 01 08 | inclevel_block_idx |
| $137B | ad 01 08 | ldalevel_block_idx |
| $137E | c9 20 | cmp#$20 |
| $1380 | f0 01 | beqb_1383 |
| $1382 | 60 | rts |
| $1383 | ea | b_1383nop; x-ref: $1380 |
| $1384 | ea | nop |
| $1385 | ea | nop |
| $1386 | a2 00 | ldx#$00 |
| $1388 | 20 00 15 | b_1388jsrscroll_screen_down; x-ref: $13B2 |
| $138B | 8a | txa |
| $138C | 48 | pha |
| $138D | a9 10 | lda#<level_tile_definition_tbl |
| $138F | 85 49 | stazp_p_tmp_lo |
| $1391 | a9 80 | lda#>level_tile_definition_tbl |
| $1393 | 85 4a | stazp_p_tmp_hi |
| $1395 | a0 00 | ldy#$00 |
| $1397 | b1 49 | b_1397lda(zp_p_tmp_lo),y; x-ref: $13A8 |
| $1399 | 99 28 04 | staSCREEN_RAM_R1C0,y |
| $139C | ae 03 08 | ldxseason_nr |
| $139F | bd 7c 16 | ldatbl_text_color_seasons,x; One byte per season (0=Summer, 1=Autumn, 2=Winter, 3=Spring) |
| $13A2 | 99 28 d8 | staCOLOR_RAM_R1C0,y |
| $13A5 | c8 | iny |
| $13A6 | c0 28 | cpy#$28 |
| $13A8 | d0 ed | bneb_1397 |
| $13AA | 20 56 47 | jsrtick_gameplay_systems |
| $13AD | 68 | pla |
| $13AE | aa | tax |
| $13AF | e8 | inx |
| $13B0 | e0 19 | cpx#$19 |
| $13B2 | d0 d4 | bneb_1388 |
| $13B4 | 20 f0 45 | jsradd_car_x_subpixels |
| $13B7 | bd 74 16 | ldatbl_level_complete_sprite1_ptr,x |
| $13BA | 8d f9 07 | stasprite_ptr_1 |
| $13BD | bd 70 16 | ldatbl_level_complete_sprite2_ptr,x |
| $13C0 | 8d fa 07 | stasprite_ptr_2 |
| $13C3 | bd 78 16 | ldatbl_level_complete_sprite1_color,x |
| $13C6 | 8d 28 d0 | sta$d028; Sprite 1 Color |
| $13C9 | 20 e7 15 | jsrreset_hero_sprite_and_color |
| $13CC | a9 90 | lda#$90 |
| $13CE | 8d 03 d0 | sta$d003; Sprite 1 Y Pos |
| $13D1 | 8d 05 d0 | sta$d005; Sprite 2 Y Pos |
| $13D4 | a9 60 | lda#$60 |
| $13D6 | 8d 02 d0 | sta$d002; Sprite 1 X Pos |
| $13D9 | a9 75 | lda#$75 |
| $13DB | 8d 04 d0 | sta$d004; Sprite 2 X Pos |
| $13DE | ad 00 d0 | j_13DElda$d000; x-ref: $13ED Sprite 0 X Pos |
| $13E1 | c9 8a | cmp#$8a |
| $13E3 | f0 11 | beqb_13F6 |
| $13E5 | 90 09 | bccb_13F0 |
| $13E7 | ce 00 d0 | dec$d000; Sprite 0 X Pos |
| $13EA | 20 e0 14 | j_13EAjsrdelay_short; x-ref: $13F3 |
| $13ED | 4c de 13 | jmpj_13DE |
| $13F0 | ee 00 d0 | b_13F0inc$d000; x-ref: $13E5 Sprite 0 X Pos |
| $13F3 | 4c ea 13 | jmpj_13EA |
| $13F6 | ad 01 d0 | b_13F6lda$d001; x-ref: $13E3, $1405 Sprite 0 Y Pos |
| $13F9 | c9 90 | cmp#$90 |
| $13FB | f0 11 | beqb_140E |
| $13FD | 90 09 | bccb_1408 |
| $13FF | ce 01 d0 | dec$d001; Sprite 0 Y Pos |
| $1402 | 20 e0 14 | j_1402jsrdelay_short; x-ref: $140B |
| $1405 | 4c f6 13 | jmpb_13F6 |
| $1408 | ee 01 d0 | b_1408inc$d001; x-ref: $13FD Sprite 0 Y Pos |
| $140B | 4c 02 14 | jmpj_1402 |
| $140E | a2 00 | b_140Eldx#$00; x-ref: $13FB |
| $1410 | bd 00 16 | b_1410ldatxt_congratulations_pt1,x; x-ref: $141E |
| $1413 | 9d 83 04 | staSCREEN_RAM_R3C11,x |
| $1416 | a9 07 | lda#VicIIColors.YELLOW |
| $1418 | 9d 83 d8 | staCOLOR_RAM_R3C11,x |
| $141B | e8 | inx |
| $141C | e0 12 | cpx#$12 |
| $141E | d0 f0 | bneb_1410 |
| $1420 | 20 f0 14 | jsrdelay_long |
| $1423 | a2 00 | ldx#$00 |
| $1425 | bd 12 16 | b_1425ldatxt_you_crash_cars,x; x-ref: $1433 |
| $1428 | 9d d2 04 | staSCREEN_RAM_R5C10,x |
| $142B | a9 07 | lda#VicIIColors.YELLOW |
| $142D | 9d d2 d8 | staCOLOR_RAM_R5C10,x |
| $1430 | e8 | inx |
| $1431 | e0 14 | cpx#$14 |
| $1433 | d0 f0 | bneb_1425 |
| $1435 | ad 20 08 | ldacrashed_cars_tens |
| $1438 | 18 | clc |
| $1439 | 69 30 | adc#$30 |
| $143B | 8d df 04 | staSCREEN_RAM_R5C23 |
| $143E | ad 21 08 | ldacrashed_cars_ones |
| $1441 | 18 | clc |
| $1442 | 69 30 | adc#$30 |
| $1444 | 8d e0 04 | staSCREEN_RAM_R5C24 |
| $1447 | 20 f0 14 | jsrdelay_long |
| $144A | 20 f0 14 | jsrdelay_long |
| $144D | a2 00 | ldx#$00 |
| $144F | bd 26 16 | b_144Fldatxt_bonus_pts_are,x; x-ref: $145D |
| $1452 | 9d 24 05 | staSCREEN_RAM_R7C12,x |
| $1455 | a9 03 | lda#VicIIColors.CYAN |
| $1457 | 9d 24 d9 | staCOLOR_RAM_R7C12,x |
| $145A | e8 | inx |
| $145B | e0 10 | cpx#$10 |
| $145D | d0 f0 | bneb_144F |
| $145F | ad 20 08 | ldacrashed_cars_tens |
| $1462 | d0 05 | bneb_1469 |
| $1464 | ad 21 08 | ldacrashed_cars_ones |
| $1467 | f0 2a | beqb_1493 |
| $1469 | a2 00 | b_1469ldx#$00; x-ref: $1462 |
| $146B | bd 36 16 | b_146Bldatxt_multiplier_500,x; x-ref: $1479 |
| $146E | 9d 74 05 | staSCREEN_RAM_R9C12,x |
| $1471 | a9 04 | lda#VicIIColors.PURPLE |
| $1473 | 9d 74 d9 | staCOLOR_RAM_R9C12,x |
| $1476 | e8 | inx |
| $1477 | e0 0a | cpx#$0a |
| $1479 | d0 f0 | bneb_146B |
| $147B | ad 20 08 | ldacrashed_cars_tens |
| $147E | 18 | clc |
| $147F | 69 30 | adc#$30 |
| $1481 | 8d 74 05 | staSCREEN_RAM_R9C12 |
| $1484 | ad 21 08 | ldacrashed_cars_ones |
| $1487 | 18 | clc |
| $1488 | 69 30 | adc#$30 |
| $148A | 8d 75 05 | staSCREEN_RAM_R9C13 |
| $148D | 4c 50 18 | jmpcalc_and_display_crashed_cars_bonus |
| ; dead code |
| $1490 | | .byte$4c, $ba, $14 |
| $1493 | a2 00 | b_1493ldx#$00; x-ref: $1467 |
| $1495 | bd 40 16 | b_1495ldatxt_extra_bonus_points,x; x-ref: $14A3 |
| $1498 | 9d 73 05 | staSCREEN_RAM_R9C11,x |
| $149B | a9 03 | lda#VicIIColors.CYAN |
| $149D | 9d 73 d9 | staCOLOR_RAM_R9C11,x |
| $14A0 | e8 | inx |
| $14A1 | e0 12 | cpx#$12 |
| $14A3 | d0 f0 | bneb_1495 |
| $14A5 | 20 f0 14 | jsrdelay_long |
| $14A8 | a2 00 | ldx#$00 |
| $14AA | bd 52 16 | b_14AAldatxt_50000,x; x-ref: $14B8 |
| $14AD | 9d c9 05 | staSCREEN_RAM_R11C17,x |
| $14B0 | a9 04 | lda#VicIIColors.PURPLE |
| $14B2 | 9d c9 d9 | staCOLOR_RAM_R11C17,x |
| $14B5 | e8 | inx |
| $14B6 | e0 05 | cpx#$05 |
| $14B8 | d0 f0 | bneb_14AA |
| $14BA | 20 a7 15 | jsrincrement_score_by_50000 |
| $14BD | 20 f0 14 | j_14BDjsrdelay_long; x-ref: $1943 |
| $14C0 | a2 00 | ldx#$00 |
| $14C2 | bd 57 16 | b_14C2ldatxt_next_way_is,x; x-ref: $14D0 |
| $14C5 | 9d 8b 06 | staSCREEN_RAM_R16C11,x |
| $14C8 | a9 07 | lda#VicIIColors.YELLOW |
| $14CA | 9d 8b da | staCOLOR_RAM_R16C11,x |
| $14CD | e8 | inx |
| $14CE | e0 0b | cpx#$0b |
| $14D0 | d0 f0 | bneb_14C2 |
| $14D2 | 4c 42 15 | jmpshow_next_season_screen |
| $14D5 | | .fill11, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Short busy-wait delay (~13 ms). Runs a nested loop with X=10 outer iterations |
| ; and Y=256 inner iterations. Shares the loop body with delay_long. |
| ; |
| ; Inputs: None |
| ; Outputs: X=0, Y=0 |
| ; Side Effects: None (burns CPU time) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $14E0 | a2 0a | delay_shortldx#$0a; 10 outer iterations ; x-ref: $13EA, $1402 |
| $14E2 | a0 00 | delay_outer_loopldy#$00; 256 inner iterations (Y wraps $00->$FF) ; x-ref: $14E8, $14F8 |
| $14E4 | 88 | delay_inner_loopdey; x-ref: $14E5, $14F5 |
| $14E5 | d0 fd | bnedelay_inner_loop |
| $14E7 | ca | dex |
| $14E8 | d0 f8 | bnedelay_outer_loop |
| $14EA | 60 | rts |
| $14EB | | .byte$00, $00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Long busy-wait delay (~328 ms). X=$00 wraps to 256 outer iterations, each |
| ; with 256 inner Y iterations. Falls through into delay_short's loop body. |
| ; Used for dramatic pauses during level transitions and score displays. |
| ; |
| ; Inputs: None |
| ; Outputs: X=0, Y=0 |
| ; Side Effects: None (burns CPU time) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $14F0 | a2 00 | delay_longldx#$00; X=$00 wraps to 256 outer iterations ; x-ref: $1420, $1447, $144A, $14A5, $14BD, $155C, $155F, $159E |
| $14F2 | a0 00 | ldy#$00 |
| $14F4 | 88 | dey |
| $14F5 | d0 ed | bnedelay_inner_loop |
| $14F7 | ca | dex |
| $14F8 | d0 e8 | bnedelay_outer_loop |
| $14FA | 60 | rts |
| $14FB | | .byte$00, $00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Shifts a large portion of Screen RAM down by one row (40 bytes) to create the |
| ; scrolling effect. It initializes a zero-page pointer ($49/$4A) to the end of |
| ; the scrolling region ($0747) and copies memory to pointer + 40 ($28). |
| ; It iterates backwards until it reaches the HUD boundary at $0427, leaving row 0 |
| ; (the HUD) intact. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies Screen RAM ($0428-$076F) and zero-page pointers $49/$4A. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1500 | 20 00 49 | scroll_screen_downjsrshift_colour_row_pipeline; shift colour pipeline; A=$07 on return ; x-ref: $11F3, $1388 |
| $1503 | 85 4a | stazp_p_tmp_hi |
| $1505 | a9 47 | lda#<SCREEN_RAM_R20C39 |
| $1507 | 85 49 | stazp_p_tmp_lo; Set pointer to $0747 |
| $1509 | a0 00 | b_1509ldy#$00; x-ref: $1522, $1528 |
| $150B | b1 49 | lda(zp_p_tmp_lo),y |
| $150D | a0 28 | ldy#$28 |
| $150F | 91 49 | sta(zp_p_tmp_lo),y; Copy byte down one row (40 bytes offset) |
| $1511 | a5 49 | ldazp_p_tmp_lo |
| $1513 | 38 | sec |
| $1514 | e9 01 | sbc#$01 |
| $1516 | 85 49 | stazp_p_tmp_lo; Decrement pointer ($49) |
| $1518 | a5 4a | ldazp_p_tmp_hi |
| $151A | e9 00 | sbc#$00 |
| $151C | 85 4a | stazp_p_tmp_hi; Decrement pointer MSB ($4A) if needed |
| $151E | a5 49 | ldazp_p_tmp_lo |
| $1520 | c9 27 | cmp#$27 |
| $1522 | d0 e5 | bneb_1509 |
| $1524 | a5 4a | ldazp_p_tmp_hi |
| $1526 | c9 04 | cmp#$04 |
| $1528 | d0 df | bneb_1509; Loop until pointer reaches boundary ($0427) |
| $152A | 58 | cli |
| $152B | 60 | rts |
| ; dead code |
| $152C | | .byte$4c, $58, $60, $4a, $e9, $00, $85, $4a |
| $1534 | | .byte$a5, $49, $c9, $27, $d0, $cf, $a5, $4a |
| $153C | | .byte$c9, $04, $d0, $c9, $58, $60 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Level transition screen: displays the upcoming season name and "GOOD LUCK!" |
| ; message. If all 32 levels (ways) are completed, awards a BONUS 10000 score. |
| ; Otherwise, advances season_nr (mod 4), resets level state, plays a countdown |
| ; delay animation, and re-enters the main game flow for the next level. |
| ; |
| ; Inputs: season_nr ($0803), a0800 ($0800) level counter |
| ; Outputs: season_nr (incremented mod 4), a0800 (incremented), level state reset |
| ; Side Effects: Writes to Screen/Color RAM, busy-wait delays, may award bonus |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| show_next_season_screen |
| $1542 | ad 03 08 | ldaseason_nr; Load season index (0-3) ; x-ref: $14D2 |
| $1545 | 0a | asla; season_nr * 8 = offset into txt_seasons |
| $1546 | 0a | asla |
| $1547 | 0a | asla |
| $1548 | aa | tax |
| $1549 | a0 00 | ldy#$00 |
| $154B | bd 80 16 | b_154Bldatxt_seasons,x; Copy 8-char season name to screen ; x-ref: $155A |
| $154E | 99 97 06 | staSCREEN_RAM_R16C23,y; Screen RAM row 16, col 23 |
| $1551 | a9 07 | lda#VicIIColors.YELLOW; Yellow text |
| $1553 | 99 97 da | staCOLOR_RAM_R16C23,y |
| $1556 | e8 | inx |
| $1557 | c8 | iny |
| $1558 | c0 08 | cpy#$08 |
| $155A | d0 ef | bneb_154B |
| $155C | 20 f0 14 | jsrdelay_long |
| $155F | 20 f0 14 | jsrdelay_long |
| $1562 | a2 00 | ldx#$00 |
| $1564 | bd 62 16 | b_1564ldatxt_good_luck,x; x-ref: $1572 |
| $1567 | 9d de 06 | staSCREEN_RAM_R18C14,x |
| $156A | a9 07 | lda#VicIIColors.YELLOW |
| $156C | 9d de da | staCOLOR_RAM_R18C14,x |
| $156F | e8 | inx |
| $1570 | e0 0c | cpx#$0c |
| $1572 | d0 f0 | bneb_1564 |
| $1574 | ee 00 08 | inclevel_nr; Increment level counter |
| $1577 | ad 00 08 | ldalevel_nr |
| $157A | c9 20 | cmp#32; All 32 levels done? |
| $157C | d0 03 | bneb_1581 |
| $157E | 4c 60 53 | jmpaward_bonus_score; Yes: award BONUS 10000 |
| $1581 | a9 00 | b_1581lda#$00; x-ref: $157C, $5395 |
| $1583 | 8d 01 08 | stalevel_block_idx |
| $1586 | a9 18 | lda#24 |
| $1588 | 8d 02 08 | stalevel_tile_y_offset |
| $158B | ee 03 08 | incseason_nr; Advance to next season |
| $158E | ad 03 08 | ldaseason_nr |
| $1591 | c9 04 | cmp#$04; Wrap season 4 -> 0 |
| $1593 | d0 05 | bneb_159A |
| $1595 | a9 00 | lda#$00 |
| $1597 | 8d 03 08 | staseason_nr |
| $159A | a2 15 | b_159Aldx#$15; Countdown delay: 21 iterations ; x-ref: $1593 |
| $159C | 8a | b_159Ctxa; x-ref: $15E2 |
| $159D | 48 | pha |
| $159E | 20 f0 14 | jsrdelay_long |
| $15A1 | 68 | pla |
| $15A2 | aa | tax |
| $15A3 | ca | dex |
| $15A4 | 4c e2 15 | jmpj_15E2 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Increments the player's score by 50000 points. |
| ; This routine calls an internal loop 5 times (controlled by Y register). In each |
| ; loop, it increments the ten-thousand digit (index 2 of the $0825 score array) by 1. |
| ; Overflows are handled seamlessly via a cascading BCD-like carry lookup. After |
| ; adding 5 to the ten-thousand position, it refreshes the HUD to display the new score. |
| ; |
| ; Inputs: None (relies on $0825 array) |
| ; Outputs: None |
| ; Side Effects: Modifies the Score array and calls update_hud_display. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| increment_score_by_50000 |
| $15A7 | a0 00 | ldy#$00; x-ref: $14BA, $5377, $537A |
| $15A9 | a2 02 | b_15A9ldx#$02; x-ref: $15C4 |
| $15AB | bd 25 08 | j_15ABldascore_7digits,x; x-ref: $15BB |
| $15AE | 18 | clc |
| $15AF | 69 01 | adc#$01 |
| $15B1 | c9 0a | cmp#$0a |
| $15B3 | d0 09 | bneb_15BE |
| $15B5 | a9 00 | lda#$00 |
| $15B7 | 9d 25 08 | stascore_7digits,x |
| $15BA | ca | dex |
| $15BB | 4c ab 15 | jmpj_15AB |
| $15BE | 9d 25 08 | b_15BEstascore_7digits,x; x-ref: $15B3 |
| $15C1 | c8 | iny |
| $15C2 | c0 05 | cpy#$05 |
| $15C4 | d0 e3 | bneb_15A9 |
| $15C6 | 4c b0 16 | jmpupdate_hud_display |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Increments the player's 7-digit score uniformly. |
| ; Because the score is stored as an array of 7 individual digits (0-9) at $0825, |
| ; this routine performs a manual base-10 addition. It starts at the least |
| ; significant digit (index 6, $082B), adds 1, and carries over any overflow (10) |
| ; to the next significant digit. |
| ; |
| ; Inputs: Score array at $0825-$082B |
| ; Outputs: Modified Score array |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $15C9 | a2 06 | increment_scoreldx#$06; Start at least significant digit (index 6) ; x-ref: $181B, $4759 |
| $15CB | bd 25 08 | j_15CBldascore_7digits,x; x-ref: $15DB |
| $15CE | 18 | clc |
| $15CF | 69 01 | adc#$01; Add 1 to the current digit |
| $15D1 | c9 0a | cmp#$0a; Check for base-10 overflow |
| $15D3 | d0 09 | bneb_15DE |
| $15D5 | a9 00 | lda#$00 |
| $15D7 | 9d 25 08 | stascore_7digits,x |
| $15DA | ca | dex; Move to next most significant digit (carry) |
| $15DB | 4c cb 15 | jmpj_15CB |
| $15DE | 9d 25 08 | b_15DEstascore_7digits,x; x-ref: $15D3 |
| $15E1 | 60 | rts |
| $15E2 | d0 b8 | j_15E2bneb_159C; Loop until X=0, then fall through to j16A1 ; x-ref: $15A4 |
| $15E4 | 4c a1 16 | jmpreset_crashed_cars_and_switch_player |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Resets the player (hero) sprite's frame to 0 ($C0), sets Sprite 2's color, |
| ; and clears the sprite expansion flags for both X and Y. |
| ; |
| ; Inputs: A = Color for Sprite 2 |
| ; Outputs: None |
| ; Side Effects: Modifies Sprite 2 Color ($D029), Player sprite pointer, and Sprite Expand flags ($D017, $D01D) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| reset_hero_sprite_and_color |
| $15E7 | 8d 29 d0 | sta$d029; Set Sprite 2 Color ; x-ref: $13C9 Sprite 2 Color |
| $15EA | a9 c0 | lda#$c0; Hero sprite frame #0 |
| $15EC | 8d f8 07 | stasprite_ptr_0; Set hero sprite pointer |
| $15EF | a9 00 | lda#$00; Clear expand flags |
| $15F1 | 8d 17 d0 | sta$d017; Sprites Expand 2x Vertical (Y) |
| $15F4 | 8d 1d d0 | sta$d01d; Sprites Expand 2x Horizontal (X) |
| $15F7 | 60 | rts |
| $15F8 | | .byte$20, $08, $8d, $21, $08, $60, $00, $00 |
| | .encode |
| | .enc"screen" |
| txt_congratulations_pt1 |
| $1600 | | .text"CONGRATULATIONS !!"; x-ref: $1410 |
| $1612 | | txt_you_crash_cars.text" YOU CRASH CARS"; x-ref: $1425 |
| $1626 | | txt_bonus_pts_are.text"BONUS POINTS ARE"; x-ref: $144F |
| $1636 | | txt_multiplier_500.text" X 500 ="; x-ref: $146B |
| txt_extra_bonus_points |
| $1640 | | .text"EXTRA BONUS POINTS"; x-ref: $1495 |
| $1652 | | txt_50000.text"50000"; x-ref: $14AA |
| $1657 | | txt_next_way_is.text"NEXT WAY IS"; x-ref: $14C2 |
| $1662 | | txt_good_luck.text"GOOD LUCK!.."; x-ref: $1564 |
| | .endencode |
| $166E | | .byte$00, $00 |
| tbl_level_complete_sprite2_ptr |
| $1670 | | .byte$d5, $d6, $d8, $d7; x-ref: $13BD |
| tbl_level_complete_sprite1_ptr |
| $1674 | | .byte$d9, $dc, $da, $db; x-ref: $13B7 |
| tbl_level_complete_sprite1_color |
| $1678 | | .byte$0d, $01, $0a, $01; x-ref: $13C3 |
| tbl_text_color_seasons |
| $167C | | .byteVicIIColors.LIGHT_GREEN; One byte per season (0=Summer, 1=Autumn, 2=Winter, 3=Spring) ; x-ref: $1362, $139F, $1729, $506F |
| $167D | | .byteVicIIColors.GREY; grey |
| $167E | | .byteVicIIColors.LIGHT_GREY; light grey |
| $167F | | .byteVicIIColors.BROWN; brown |
| | .encode |
| | .enc"screen" |
| $1680 | | txt_seasons.text"SUMMER AUTUMN WINTER SPRING "; x-ref: $154B |
| | .endencode |
| $16A0 | | .byte$00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Resets the crashed cars counter to zero, then jumps to the active player |
| ; state switch logic. Typically called at the end of a season or game over. |
| ; |
| ; Inputs: None |
| ; Outputs: crashed_cars_tens, crashed_cars_ones cleared |
| ; Side Effects: Jumps to switch_active_player_state |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| reset_crashed_cars_and_switch_player |
| $16A1 | a9 00 | lda#$00; Zero crashed_cars count; jump to 2-player state switch (end of season) ; x-ref: $15E4 |
| $16A3 | 8d 20 08 | stacrashed_cars_tens |
| $16A6 | 8d 21 08 | stacrashed_cars_ones |
| $16A9 | 4c be 50 | jmpswitch_active_player_state |
| $16AC | | .byte$00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the HUD text on the top row of the screen ($0400). |
| ; Converts numeric gameplay variables such as the current score, high score, and |
| ; other state values into screencodes (by adding $30) and writes them directly |
| ; to Screen RAM. |
| ; |
| ; Inputs: Numeric values at $0821, $0822, $0823, $0825-$082B (Score), and $0F50-$0F56 (High Score) |
| ; Outputs: None |
| ; Side Effects: Modifies Screen RAM ($0403-$0427) to update visible UI numbers. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $16B0 | 20 40 49 | update_hud_displayjsradvance_distance_counter; x-ref: $11CD, $15C6, $1818, $1940, $1D4E, $4745, $4756, $47D6 |
| $16B3 | 18 | clc |
| $16B4 | 69 30 | adc#$30; A = crashed_cars_tens digit (returned by advance_distance_counter) |
| $16B6 | 8d 20 04 | staSCREEN_RAM_R0C32 |
| $16B9 | ad 21 08 | ldacrashed_cars_ones; hud_crashed_ones: screen col 33 ($0421) |
| $16BC | 18 | clc |
| $16BD | 69 30 | adc#$30 |
| $16BF | 8d 21 04 | staSCREEN_RAM_R0C33 |
| $16C2 | ad 22 08 | ldalives_tens; hud_lives_tens: screen col 38 ($0426) |
| $16C5 | 18 | clc; hud_lives_ones: screen col 39 ($0427) |
| $16C6 | 69 30 | adc#$30 |
| $16C8 | 8d 26 04 | staSCREEN_RAM_R0C38 |
| $16CB | ad 23 08 | ldalives_ones |
| $16CE | 18 | clc |
| $16CF | 69 30 | adc#$30 |
| $16D1 | 8d 27 04 | staSCREEN_RAM_R0C39 |
| $16D4 | 20 a7 1f | jsrwrite_level_nr_to_hud; write level number digits to hud_level_tens/ones ($0419/$041A) |
| $16D7 | 4c f2 16 | jmphud_write_score_and_hiscore |
| ; dead code |
| $16DA | | .byte$09, $18, $69, $31, $8d, $1a, $04, $4c |
| $16E2 | | .byte$f2, $16, $a9, $31, $8d, $19, $04, $ad |
| $16EA | | .byte$00, $08, $18, $69, $27, $8d, $1a, $04 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Writes the 7-digit current score and the 7-digit high score to the HUD |
| ; area of screen RAM ($0403 and $040E respectively). Converts raw decimal |
| ; digits into screencodes by adding $30. |
| ; |
| ; Inputs: score_7digits, hi_score_7digits |
| ; Outputs: Screen RAM ($0403-$0409, $040E-$0414) |
| ; Side Effects: Updates visible score values on HUD |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| hud_write_score_and_hiscore |
| $16F2 | a2 00 | ldx#$00; write all 7 score digits to $0403-$0409; all 7 hi-score digits to $040E-$0414 ; x-ref: $16D7 |
| $16F4 | bd 25 08 | b_16F4ldascore_7digits,x; Read current score digit ; x-ref: $1709 |
| $16F7 | 18 | clc |
| $16F8 | 69 30 | adc#$30; Convert Score to Screencode |
| $16FA | 9d 03 04 | staSCREEN_RAM_R0C3,x; Write to HUD score area |
| $16FD | bd 50 0f | ldahi_score_7digits,x; Read high score digit |
| $1700 | 18 | clc |
| $1701 | 69 30 | adc#$30; Convert High Score to Screencode |
| $1703 | 9d 0e 04 | staSCREEN_RAM_R0C14,x; Write to HUD high score area |
| $1706 | e8 | inx |
| $1707 | e0 07 | cpx#$07 |
| $1709 | d0 e9 | bneb_16F4 |
| $170B | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the screen and VIC-II state at the start of each level. |
| ; Called on every level start (including 2-player turn swaps). |
| ; |
| ; Phase 1: restore_game_vars, then copy 3 screen pages from tile data under BASIC |
| ; ROM ($8110/$8210/$8300) and HUD row from $8038 to screen RAM; |
| ; apply season text color to all 4 color RAM pages. |
| ; Phase 2: Zero-fill NPC sprite X regs ($D002..$D00D); place player sprite at |
| ; X=$A8, Y=$B0; set player sprite frame ($C0) and color (4=purple); |
| ; enable all 8 sprites; clear jump flag and multicolor mode. |
| ; Phase 3: Reset score digits, speed, all NPC car/sprite state flags, and |
| ; score popup slots; clear collision flag. |
| ; Tail-calls reset_score_sprite_colors to finish. |
| ; |
| ; Inputs: season_nr, level_nr, current_player_nr |
| ; Outputs: Screen RAM ($0400-$07FF), Color RAM ($D800-$DBFF), VIC-II sprite regs |
| ; Side Effects: Clears all enemy/sprite/collision state; resets player speed to $50 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $170C | 20 00 50 | init_level_screenjsrrestore_game_vars; x-ref: $1191, $50A2, $50BB, $5197, $51B8 |
| $170F | a2 00 | ldx#$00 |
| $1711 | 20 d2 50 | b_1711jsrcopy_hud_text_row; x-ref: $1739 |
| $1714 | bd 10 81 | ldaf_8110,x |
| $1717 | 9d 00 05 | staSCREEN_RAM_R6C16,x |
| $171A | bd 10 82 | ldaf_8210,x |
| $171D | 9d 00 06 | staSCREEN_RAM_R12C32,x |
| $1720 | bd 00 83 | ldaf_8300,x |
| $1723 | 9d f0 06 | staSCREEN_RAM_R18C32,x |
| $1726 | ac 03 08 | ldyseason_nr |
| $1729 | b9 7c 16 | ldatbl_text_color_seasons,y; One byte per season (0=Summer, 1=Autumn, 2=Winter, 3=Spring) |
| $172C | 9d 28 d8 | staCOLOR_RAM_R1C0,x |
| $172F | 9d 00 d9 | staCOLOR_RAM_R6C16,x |
| $1732 | 9d 00 da | staCOLOR_RAM_R12C32,x |
| $1735 | 9d f0 da | staCOLOR_RAM_R18C32,x |
| $1738 | e8 | inx |
| $1739 | d0 d6 | bneb_1711 |
| $173B | a2 00 | ldx#$00; zero-fill VIC-II sprite X regs for NPC sprites 1-7 ($D002..$D00D) |
| $173D | 8a | txa |
| $173E | 9d 02 d0 | b_173Esta$d002,x; x-ref: $1744 Sprite 1 X Pos |
| $1741 | e8 | inx |
| $1742 | e0 0e | cpx#$0e |
| $1744 | d0 f8 | bneb_173E |
| $1746 | a9 a8 | lda#$a8; position player sprite at $A8 (center road) |
| $1748 | 8d 00 d0 | sta$d000; Sprite 0 X Pos |
| $174B | a9 b0 | lda#$b0; set player sprite Y pos to $B0; draw player name row |
| $174D | 20 35 50 | jsrset_player_y_and_draw_player_row |
| $1750 | a9 c0 | lda#$c0; player car sprite frame $C0 |
| $1752 | 8d f8 07 | stasprite_ptr_0 |
| $1755 | a9 04 | lda#$04 |
| $1757 | 8d 27 d0 | sta$d027; Sprite 0 Color |
| $175A | a9 ff | lda#$ff |
| $175C | 8d 15 d0 | sta$d015; Sprite display Enable |
| $175F | a9 00 | lda#$00 |
| $1761 | 8d 05 08 | staplayer_is_jumping |
| $1764 | a9 1f | lda#$1f; set score_digits[0] (hundreds) = 0, score_digits[1..2] = 0/8 |
| $1766 | 8d 1c d0 | sta$d01c; Sprites Multi-Color Mode Select |
| $1769 | a9 00 | lda#$00 |
| $176B | 8d e0 08 | stascore_digits |
| $176E | 8d e2 08 | staspeed_hundreds_digit |
| $1771 | a9 08 | lda#$08 |
| $1773 | 8d e1 08 | staspeed_tens_digit |
| $1776 | a9 50 | lda#$50 |
| $1778 | 8d 04 08 | staplayer_speed |
| $177B | a9 00 | lda#$00 |
| $177D | 8d 28 09 | statbl_enemy_car_state |
| $1780 | 8d 29 09 | statbl_enemy_car_state_1 |
| $1783 | 8d 2a 09 | statbl_enemy_car_state_2 |
| $1786 | 8d 2b 09 | statbl_enemy_car_state_3 |
| $1789 | 8d 80 09 | statbl_score_sprite_active |
| $178C | 8d 81 09 | statbl_score_sprite_active_1 |
| $178F | 8d 82 09 | statbl_score_sprite_active_2 |
| $1792 | 8d 8a 09 | stacol_active |
| $1795 | 4c f0 3c | jmpreset_score_sprite_colors |
| $1798 | | .byte$00 |
| $1799 | 20 dd 17 | j_1799jsrupdate_hiscore_if_beaten; x-ref: $4992 |
| $179C | ad 20 08 | ldacrashed_cars_tens |
| $179F | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles horizontal movement for the player car (Sprite 0). |
| ; Checks the game state flag at $098A. If active, reads the parsed input state |
| ; at zero page $00F5. Bit 2 ($04) corresponds to Left, Bit 3 ($08) to Right. |
| ; If left is pressed, Sprite 0's X position ($D000) is moved left by 6 pixels, |
| ; clamping at 0. If right is pressed, it is moved right by 6 pixels, clamping |
| ; at $FF (255). |
| ; |
| ; Inputs: State flag $098A, Parsed Input state at $00F5 |
| ; Outputs: None |
| ; Side Effects: Modifies Sprite 0 X position ($D000) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| handle_player_movement |
| $17A0 | ad 8a 09 | ldacol_active; x-ref: $181E, $475C |
| $17A3 | f0 01 | beqb_17A6 |
| $17A5 | 60 | r_17A5rts; x-ref: $17B2 |
| $17A6 | ad f5 00 | b_17A6lda@w zp_joy_state; Check input state array at $00F5 ; x-ref: $17A3 |
| $17A9 | 29 04 | and#$04; Check Bit 2 (Left) |
| $17AB | f0 15 | beqb_17C2 |
| $17AD | ad f5 00 | lda@w zp_joy_state |
| $17B0 | 29 08 | and#$08; Check Bit 3 (Right) |
| $17B2 | d0 f1 | bner_17A5 |
| $17B4 | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $17B7 | 18 | clc |
| $17B8 | 69 06 | adc#$06; Move Right 6 pixels |
| $17BA | 90 02 | bccb_17BE |
| $17BC | a9 ff | lda#$ff; Clamp to max string edge ($FF) |
| $17BE | 8d 00 d0 | b_17BEsta$d000; x-ref: $17BA, $17C8, $17CC Sprite 0 X Pos |
| $17C1 | 60 | rts |
| $17C2 | ad 00 d0 | b_17C2lda$d000; x-ref: $17AB Sprite 0 X Pos |
| $17C5 | 38 | sec |
| $17C6 | e9 06 | sbc#$06; Move Left 6 pixels |
| $17C8 | b0 f4 | bcsb_17BE |
| $17CA | a9 00 | lda#$00; Clamp to left edge ($00) |
| $17CC | f0 f0 | beqb_17BE |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Checks if there is an active collision. If no collision is active, |
| ; it proceeds to handle player acceleration logic. |
| ; |
| ; Inputs: col_active |
| ; Outputs: None |
| ; Side Effects: May branch to handle_acceleration |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| check_acceleration_conditions |
| $17CE | ad 8a 09 | ldacol_active; x-ref: $1832 |
| $17D1 | f0 01 | beqb_17D4 |
| $17D3 | 60 | rts |
| $17D4 | 4c 10 44 | b_17D4jmphandle_acceleration; Proceed to acceleration logic ; x-ref: $17D1 |
| $17D7 | | .byte$00, $00, $00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Compares the player's current score with the high score. |
| ; If the current score is higher, it overwrites the high score. |
| ; |
| ; Inputs: score_7digits ($0825), hi_score_7digits ($0F50) |
| ; Outputs: hi_score_7digits updated if score was higher |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_hiscore_if_beaten |
| $17DD | a2 00 | ldx#$00; x-ref: $1799 |
| $17DF | bd 50 0f | b_17DFldahi_score_7digits,x; Load high score digit ; x-ref: $17EC |
| $17E2 | dd 25 08 | cmpscore_7digits,x; Compare with current score digit |
| $17E5 | 30 08 | bmib_17EF; If score is higher, branch to update |
| $17E7 | d0 05 | bner_17EE; If high score is higher, return |
| $17E9 | e8 | inx |
| $17EA | e0 07 | cpx#$07 |
| $17EC | d0 f1 | bneb_17DF |
| $17EE | 60 | r_17EErts; x-ref: $17E7 |
| $17EF | a2 00 | b_17EFldx#$00; Reset index for copy ; x-ref: $17E5 |
| $17F1 | bd 25 08 | b_17F1ldascore_7digits,x; x-ref: $17FA |
| $17F4 | 9d 50 0f | stahi_score_7digits,x; Copy score digit to high score |
| $17F7 | e8 | inx |
| $17F8 | e0 07 | cpx#$07 |
| $17FA | d0 f5 | bneb_17F1 |
| $17FC | 60 | rts |
| $17FD | | .byte$00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the game and enters the main game loop. |
| ; |
| ; On entry, runs one-time init (game state, VIC-II, screen/sprites), then |
| ; enters the per-frame loop. Each iteration briefly banks out BASIC ROM so |
| ; scroll_and_draw_map_row can read tile data stored under it ($8010+), then |
| ; banks BASIC back in and calls every per-frame update in sequence before |
| ; jumping to apply recoil and looping back. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies 6510 I/O Port ($01), updates game state and screen |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1800 | 20 95 11 | mainjsrinit_game_state; One-time init: zero game state variables and load level data ; x-ref: $129C |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Entry point for initializing the game loop. Sets up VIC-II video registers, |
| ; screen, and sprites, then falls through into the main loop. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Initializes VIC-II hardware state, draws initial screen |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1803 | 20 00 10 | game_init_and_loopjsrinit_vic_video; Set up VIC-II registers (border, background, multicolor, raster IRQ) ; x-ref: $12F4, $5107, $511B, $5128 |
| $1806 | 20 52 10 | jsrinit_screen_and_sprites; Draw initial playfield screen and position all sprites |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; The core per-frame game loop body. Banks out BASIC to draw the map row, |
| ; updates HUD, processes player movement/jumping, checks collisions, updates |
| ; NPC cars, and manages game timing. |
| ; |
| ; Inputs: Current game state, joystick input |
| ; Outputs: None |
| ; Side Effects: Modifies game state, updates screen, manages sprite positions |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1809 | a5 01 | main_loopldazpa_01; 6510 IO Port ; x-ref: $4FB9 |
| $180B | 29 fe | and#$fe; Bank out Basic ROM |
| $180D | 85 01 | stazpa_01 |
| $180F | 20 00 13 | jsrscroll_and_draw_map_row; Scroll screen down and draw next tile row (BASIC banked out for tile data at $8010) |
| $1812 | a5 01 | ldazpa_01 |
| $1814 | 09 01 | ora#$01; Bank Basic ROM back in |
| $1816 | 85 01 | stazpa_01 |
| $1818 | 20 b0 16 | jsrupdate_hud_display; Refresh score, lives, and speed indicator on the HUD row |
| $181B | 20 c9 15 | jsrincrement_score; Add time-based score increment each frame |
| $181E | 20 a0 17 | jsrhandle_player_movement; Read joystick and update player car X/Y position and speed |
| $1821 | 20 00 1a | jsrcheck_jump_input; Detect fire button press to initiate a jump over another car |
| $1824 | 20 3a 1a | jsrupdate_jump_animation; Advance jump arc frame counter and update sprite pointer |
| $1827 | 20 00 1b | jsrcheck_background_collision; Check player sprite vs road/wall tile for collision response |
| $182A | 20 00 44 | jsrapply_y_offset; Apply current vertical scroll offset to all sprite Y positions |
| $182D | ad 05 08 | ldaplayer_is_jumping; Skip acceleration check while player is airborne |
| $1830 | d0 03 | bneb_1835 |
| $1832 | 20 ce 17 | jsrcheck_acceleration_conditions; Adjust player speed based on current road tile type |
| $1835 | 20 00 46 | b_1835jsrdelay_frame_by_speed; Busy-wait loop to throttle frame rate to the player's current speed ; x-ref: $1830 |
| $1838 | 20 12 47 | jsrupdate_pickup_timer; Count down timers for on-road pickup items |
| $183B | 20 d4 3a | jsrprocess_entities_and_input; Handle NPC car AI logic and process any remaining player input side-effects |
| $183E | 20 00 3d | jsrupdate_moving_sprites; Move all active NPC car sprites one step along their path |
| $1841 | 20 55 4e | jsrupdate_explosion_animations; Advance crash/explosion sprite animation frames |
| $1844 | 20 a0 49 | jsrupdate_sprite_animations; Update all other sprite animation states (player car, debris, etc.) |
| $1847 | 20 00 3b | jsrdetect_player_car_collision; Check for player-vs-NPC car collisions and trigger responses |
| $184A | 20 f0 3a | jsrupdate_enemies_and_check_jump; Update enemy AI states and check if player has jumped onto a car |
| $184D | 4c cd 4e | jmpmain_loop_apply_recoil; Apply X-axis recoil to player, then loop back to main_loop |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Converts the number of crashed cars into a score bonus and displays it. |
| ; |
| ; The crashed-car count (a 2-digit value in crashed_cars_tens/ones) is |
| ; multiplied by 100 and added to score_7digits via repeated BCD-style |
| ; addition (5 inner loops: ones->+1, tens->+10, then the computed |
| ; 100/1k/10k partial sums are each added digit-by-digit with carry). |
| ; Afterwards the 3-digit bonus number is written to screen RAM ($057F-$0583) |
| ; and its color (purple=4) to color RAM ($D97F-$D983), skipping leading zeros. |
| ; Finally update_hud_display is called and control falls to the shared |
| ; epilogue that shows a delay and the next-season screen. |
| ; |
| ; Inputs: crashed_cars_tens ($0820), crashed_cars_ones ($0821), |
| ; crashed_cars_bonus_10k/1k/100 ($0830-$0832) |
| ; Outputs: score_7digits ($0825-$082B) updated with bonus |
| ; Side Effects: Writes bonus digits to screen RAM $057F-$0583, |
| ; writes color 4 to color RAM $D97F-$D983, |
| ; calls update_hud_display, then jumps to show next-season screen. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| calc_and_display_crashed_cars_bonus |
| $1850 | a9 00 | lda#$00; Zero out the 3-digit bonus accumulator (10k, 1k, 100) ; x-ref: $148D |
| $1852 | 8d 30 08 | stacrashed_cars_bonus_10k |
| $1855 | 8d 31 08 | stacrashed_cars_bonus_1k |
| $1858 | 8d 32 08 | stacrashed_cars_bonus_100 |
| $185B | ac 21 08 | ldycrashed_cars_ones; Phase 1: Y = crashed_cars_ones; loop Y times adding +1 to bonus accumulator |
| $185E | f0 25 | j_185Ebeqb_1885; x-ref: $1882 |
| $1860 | 98 | tya |
| $1861 | 48 | pha |
| $1862 | a0 05 | ldy#$05 |
| $1864 | a2 02 | b_1864ldx#$02; 5 reps per car (adds 1 to the 3-digit bonus, carries through digits) ; x-ref: $187D |
| $1866 | bd 30 08 | j_1866ldacrashed_cars_bonus_10k,x; X walks digits from MSB [2] to LSB [0]; add 1, propagate carry if digit wraps past 9 ; x-ref: $1876 |
| $1869 | 18 | clc |
| $186A | 69 01 | adc#$01 |
| $186C | c9 0a | cmp#$0a; Digit wrapped past 9: zero it and carry to the next higher digit |
| $186E | d0 09 | bneb_1879 |
| $1870 | a9 00 | lda#$00 |
| $1872 | 9d 30 08 | stacrashed_cars_bonus_10k,x |
| $1875 | ca | dex |
| $1876 | 4c 66 18 | jmpj_1866 |
| $1879 | 9d 30 08 | b_1879stacrashed_cars_bonus_10k,x; x-ref: $186E |
| $187C | 88 | dey |
| $187D | d0 e5 | bneb_1864 |
| $187F | 68 | pla |
| $1880 | a8 | tay |
| $1881 | 88 | dey |
| $1882 | 4c 5e 18 | jmpj_185E |
| $1885 | ac 20 08 | b_1885ldycrashed_cars_tens; Phase 2: Y = crashed_cars_tens; loop Y times adding +10 to bonus accumulator ; x-ref: $185E |
| $1888 | f0 25 | j_1888beqb_18AF; x-ref: $18AC |
| $188A | 98 | tya |
| $188B | 48 | pha |
| $188C | a0 05 | ldy#$05 |
| $188E | a2 01 | b_188Eldx#$01; 5 reps per car (adds 10 to the bonus; only upper 2 digits affected) ; x-ref: $18A7 |
| $1890 | bd 30 08 | j_1890ldacrashed_cars_bonus_10k,x; x-ref: $18A0 |
| $1893 | 18 | clc |
| $1894 | 69 01 | adc#$01 |
| $1896 | c9 0a | cmp#$0a |
| $1898 | d0 09 | bneb_18A3 |
| $189A | a9 00 | lda#$00 |
| $189C | 9d 30 08 | stacrashed_cars_bonus_10k,x |
| $189F | ca | dex |
| $18A0 | 4c 90 18 | jmpj_1890 |
| $18A3 | 9d 30 08 | b_18A3stacrashed_cars_bonus_10k,x; x-ref: $1898 |
| $18A6 | 88 | dey |
| $18A7 | d0 e5 | bneb_188E |
| $18A9 | 68 | pla |
| $18AA | a8 | tay |
| $18AB | 88 | dey |
| $18AC | 4c 88 18 | jmpj_1888 |
| $18AF | a2 00 | b_18AFldx#$00; Skip leading zeros: scan from MSB until a non-zero digit is found ; x-ref: $1888 |
| $18B1 | bd 30 08 | j_18B1ldacrashed_cars_bonus_10k,x; x-ref: $18B7 |
| $18B4 | d0 04 | bneb_18BA |
| $18B6 | e8 | inx |
| $18B7 | 4c b1 18 | jmpj_18B1 |
| $18BA | bd 30 08 | b_18BAldacrashed_cars_bonus_10k,x; Convert digit to PETSCII (+$30) and write to screen RAM $057F+x ; x-ref: $18B4, $18CB |
| $18BD | 18 | clc |
| $18BE | 69 30 | adc#$30 |
| $18C0 | 9d 7f 05 | staSCREEN_RAM_R9C23,x |
| $18C3 | a9 04 | lda#VicIIColors.PURPLE; Set color 4 (purple) for bonus digit in color RAM $D97F+x |
| $18C5 | 9d 7f d9 | staCOLOR_RAM_R9C23,x |
| $18C8 | e8 | inx |
| $18C9 | e0 03 | cpx#$03 |
| $18CB | d0 ed | bneb_18BA |
| $18CD | a9 30 | lda#$30; Fill trailing screen RAM positions $0582-$0583 with '0' ($30) |
| $18CF | 8d 82 05 | staSCREEN_RAM_R9C26 |
| $18D2 | 8d 83 05 | staSCREEN_RAM_R9C27 |
| $18D5 | a9 04 | lda#VicIIColors.PURPLE; Set color 4 (purple) for trailing positions in color RAM $D982-$D983 |
| $18D7 | 8d 82 d9 | staCOLOR_RAM_R9C26 |
| $18DA | 8d 83 d9 | staCOLOR_RAM_R9C27 |
| $18DD | ac 32 08 | ldycrashed_cars_bonus_100 |
| $18E0 | f0 1c | j_18E0beqb_18FE; x-ref: $18FB |
| $18E2 | a2 04 | ldx#$04 |
| $18E4 | bd 25 08 | j_18E4ldascore_7digits,x; x-ref: $18F4 |
| $18E7 | 18 | clc |
| $18E8 | 69 01 | adc#$01 |
| $18EA | c9 0a | cmp#$0a |
| $18EC | d0 09 | bneb_18F7 |
| $18EE | a9 00 | lda#$00 |
| $18F0 | 9d 25 08 | stascore_7digits,x |
| $18F3 | ca | dex |
| $18F4 | 4c e4 18 | jmpj_18E4 |
| $18F7 | 9d 25 08 | b_18F7stascore_7digits,x; x-ref: $18EC |
| $18FA | 88 | dey |
| $18FB | 4c e0 18 | jmpj_18E0 |
| $18FE | ac 31 08 | b_18FEldycrashed_cars_bonus_1k; Phase 4: Y = crashed_cars_bonus_1k; add 1,000 per unit to score_7digits ; x-ref: $18E0 |
| $1901 | f0 1c | j_1901beqb_191F; x-ref: $191C |
| $1903 | a2 03 | ldx#$03 |
| $1905 | bd 25 08 | j_1905ldascore_7digits,x; x-ref: $1915 |
| $1908 | 18 | clc |
| $1909 | 69 01 | adc#$01 |
| $190B | c9 0a | cmp#$0a |
| $190D | d0 09 | bneb_1918 |
| $190F | a9 00 | lda#$00 |
| $1911 | 9d 25 08 | stascore_7digits,x |
| $1914 | ca | dex |
| $1915 | 4c 05 19 | jmpj_1905 |
| $1918 | 9d 25 08 | b_1918stascore_7digits,x; x-ref: $190D |
| $191B | 88 | dey |
| $191C | 4c 01 19 | jmpj_1901 |
| $191F | ac 30 08 | b_191Fldycrashed_cars_bonus_10k; Phase 5: Y = crashed_cars_bonus_10k; add 10,000 per unit to score_7digits ; x-ref: $1901 |
| $1922 | f0 1c | j_1922beqb_1940; x-ref: $193D |
| $1924 | a2 02 | ldx#$02 |
| $1926 | bd 25 08 | j_1926ldascore_7digits,x; x-ref: $1936 |
| $1929 | 18 | clc |
| $192A | 69 01 | adc#$01 |
| $192C | c9 0a | cmp#$0a |
| $192E | d0 09 | bneb_1939 |
| $1930 | a9 00 | lda#$00 |
| $1932 | 9d 25 08 | stascore_7digits,x |
| $1935 | ca | dex |
| $1936 | 4c 26 19 | jmpj_1926 |
| $1939 | 9d 25 08 | b_1939stascore_7digits,x; x-ref: $192E |
| $193C | 88 | dey |
| $193D | 4c 22 19 | jmpj_1922 |
| $1940 | 20 b0 16 | b_1940jsrupdate_hud_display; Refresh HUD with updated score, then jump to next-season screen epilogue ; x-ref: $1922 |
| $1943 | 4c bd 14 | jmpj_14BD |
| $1946 | | .fill186, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Checks if the Fire button is pressed to initiate a car jump. |
| ; Reads the parsed input state at $00F5 (Bit 4 = Fire button). If the jump |
| ; action is requested and the car is not already jumping (jump state $0805 is 0), |
| ; it initializes the jump animation state machine, sets the initial sprite |
| ; pointer for the jump, and slightly shifts the car's X position. |
| ; |
| ; Inputs: Parsed input state at $00F5, jump state at $0805 |
| ; Outputs: None |
| ; Side Effects: Modifies $0805 (jump active), $0806 (jump frame), |
| ; and Sprite 0 X position ($D000). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1A00 | ad f5 00 | check_jump_inputlda@w zp_joy_state; Read input state ; x-ref: $1821, $3AD7, $3AF3, $475F |
| $1A03 | 29 10 | and#$10; Check Bit 4 (Fire button) |
| $1A05 | f0 01 | beqb_1A08 |
| $1A07 | 60 | r_1A07rts; x-ref: $1A0B |
| $1A08 | ad 05 08 | b_1A08ldaplayer_is_jumping; Check if already jumping ($0805 != 0) ; x-ref: $1A05 |
| $1A0B | d0 fa | bner_1A07 |
| $1A0D | 20 4b 47 | jsris_speed_above_100_else_return |
| $1A10 | 4a | lsra |
| $1A11 | 4a | lsra |
| $1A12 | 20 f8 1a | jsrset_jump_timer_base |
| $1A15 | a9 01 | lda#$01; Set jump active flag |
| $1A17 | 8d 05 08 | staplayer_is_jumping |
| $1A1A | a9 01 | lda#$01; Reset jump animation frame |
| $1A1C | 8d 06 08 | stajump_anim_frame |
| $1A1F | ad 10 08 | ldajump_timer_base |
| $1A22 | 4a | lsra |
| $1A23 | 4a | lsra |
| $1A24 | 4a | lsra |
| $1A25 | 8d 11 08 | stajump_frame_timer |
| $1A28 | a9 d4 | lda#$d4; Set Sprite 0 pointer for jump start |
| $1A2A | 8d f8 07 | stasprite_ptr_0 |
| $1A2D | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $1A30 | 18 | clc |
| $1A31 | 69 04 | adc#$04 |
| $1A33 | 8d 00 d0 | sta$d000; Sprite 0 X Pos |
| $1A36 | ea | nop |
| $1A37 | ea | nop |
| $1A38 | ea | nop |
| $1A39 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Processes the jump animation state machine for Sprite 0. |
| ; This routine runs continuously in the game loop. If $0805 indicates a jump is |
| ; active, it decrements the frame timer $0811. Once the timer elapses, it |
| ; advances the animation frame $0806 and uses a switch statement ($1A51) to update |
| ; the sprite pointer, sizes, and position to create a jumping arc. |
| ; When the animation reaches the end (frame 9), it resets $0805 to 0. |
| ; |
| ; Inputs: Jump state at $0805, animation frame $0806, timer $0811 |
| ; Outputs: None |
| ; Side Effects: Modifies Sprite 0 X position ($D000), Sprite Pointer ($07F8), |
| ; and Sprite Expansion bits ($D017, $D01D). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_jump_animation |
| $1A3A | ad 05 08 | ldaplayer_is_jumping; Check jump active flag ; x-ref: $1824, $4762 |
| $1A3D | d0 01 | bneb_1A40 |
| $1A3F | 60 | r_1A3Frts; x-ref: $1A43 |
| $1A40 | ce 11 08 | b_1A40decjump_frame_timer; Decrement jump frame timer ; x-ref: $1A3D |
| $1A43 | d0 fa | bner_1A3F |
| $1A45 | ad 10 08 | ldajump_timer_base |
| $1A48 | 4a | lsra |
| $1A49 | 4a | lsra |
| $1A4A | 4a | lsra |
| $1A4B | 8d 11 08 | stajump_frame_timer |
| $1A4E | 20 eb 1a | jsrincrement_jump_frame; Increment animation frame (in A) |
| $1A51 | c9 09 | cmp#$09 |
| $1A53 | f0 2d | beqb_1A82 |
| $1A55 | c9 08 | cmp#$08 |
| $1A57 | f0 26 | beqb_1A7F |
| $1A59 | c9 07 | cmp#$07 |
| $1A5B | f0 1f | beqb_1A7C |
| $1A5D | c9 06 | cmp#$06 |
| $1A5F | f0 18 | beqb_1A79 |
| $1A61 | c9 05 | cmp#$05 |
| $1A63 | f0 11 | beqb_1A76 |
| $1A65 | c9 04 | cmp#$04 |
| $1A67 | f0 0a | beqb_1A73 |
| $1A69 | c9 03 | cmp#$03 |
| $1A6B | f0 03 | beqb_1A70 |
| $1A6D | 4c 85 1a | jmpjump_anim_frame_1_2 |
| $1A70 | 4c 94 1a | b_1A70jmpjump_anim_expand_sprite; x-ref: $1A6B |
| $1A73 | 4c ab 1a | b_1A73jmpjump_anim_frame_4_5; x-ref: $1A67 |
| $1A76 | 4c ab 1a | b_1A76jmpjump_anim_frame_4_5; x-ref: $1A63 |
| $1A79 | 4c f2 1a | b_1A79jmpjump_anim_frame_0; x-ref: $1A5F |
| $1A7C | 4c b1 1a | b_1A7Cjmpjump_anim_shrink_sprite; x-ref: $1A5B |
| $1A7F | 4c c8 1a | b_1A7Fjmpjump_anim_frame_6_or_8; x-ref: $1A57 |
| $1A82 | 4c d7 1a | b_1A82jmpjump_anim_terminate; x-ref: $1A53 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Jump Animation Frame 1 & 2 Handler. |
| ; Sets the player car sprite pointer to the ascending graphic. |
| ; X position is processed but effectively unchanged (SBC #$00). |
| ; |
| ; Inputs: None |
| ; Outputs: Sprite 0 Pointer updated |
| ; Side Effects: Updates Sprite 0 graphic. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1A85 | a9 d3 | jump_anim_frame_1_2lda#$d3; Animation Frame 1 & 2: Draw ascending sprite ; x-ref: $1A6D |
| $1A87 | 8d f8 07 | stasprite_ptr_0 |
| $1A8A | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $1A8D | 38 | sec |
| $1A8E | e9 00 | sbc#$00 |
| $1A90 | 8d 00 d0 | sta$d000; Sprite 0 X Pos |
| $1A93 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Jump Animation Frame 3 Handler (Apex). |
| ; Expands the player sprite 2x horizontally and vertically to simulate maximum |
| ; height. Adjusts the X position left by 12 pixels to keep the car visually centered. |
| ; |
| ; Inputs: Sprite 0 X position ($D000) |
| ; Outputs: Sprite 0 X position ($D000), Sprite Expansion registers ($D017, $D01D) |
| ; Side Effects: Enlarges Sprite 0. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| jump_anim_expand_sprite |
| $1A94 | a9 d2 | lda#$d2; Animation Frame 3: Max height, expand sprite ; x-ref: $1A70 |
| $1A96 | 8d f8 07 | stasprite_ptr_0 |
| $1A99 | a9 01 | lda#$01 |
| $1A9B | 8d 17 d0 | sta$d017; Sprites Expand 2x Vertical (Y) |
| $1A9E | 8d 1d d0 | sta$d01d; Sprites Expand 2x Horizontal (X) |
| $1AA1 | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $1AA4 | 38 | sec |
| $1AA5 | e9 0c | sbc#$0c; Compensate for center shift on expansion |
| $1AA7 | 8d 00 d0 | sta$d000; Sprite 0 X Pos |
| $1AAA | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Jump Animation Frame 4 & 5 Handler. |
| ; Updates the player sprite to the descending graphic while still expanded. |
| ; |
| ; Inputs: None |
| ; Outputs: Sprite 0 Pointer updated |
| ; Side Effects: Updates Sprite 0 graphic. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1AAB | a9 d4 | jump_anim_frame_4_5lda#$d4; Animation Frame 4 & 5: Expanded descending ; x-ref: $1A73, $1A76 |
| $1AAD | 8d f8 07 | stasprite_ptr_0 |
| $1AB0 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Jump Animation Frame 7 Handler. |
| ; Shrinks the player sprite back to normal 1x size as it nears the ground. |
| ; Adjusts the X position right by 12 pixels to compensate for the center shift. |
| ; |
| ; Inputs: Sprite 0 X position ($D000) |
| ; Outputs: Sprite 0 X position ($D000), Sprite Expansion registers ($D017, $D01D) |
| ; Side Effects: Restores Sprite 0 to normal size. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| jump_anim_shrink_sprite |
| $1AB1 | a9 00 | lda#$00; Animation Frame 7: Shrink sprite back ; x-ref: $1A7C |
| $1AB3 | 8d 17 d0 | sta$d017; Sprites Expand 2x Vertical (Y) |
| $1AB6 | 8d 1d d0 | sta$d01d; Sprites Expand 2x Horizontal (X) |
| $1AB9 | a9 d3 | lda#$d3 |
| $1ABB | 8d f8 07 | stasprite_ptr_0 |
| $1ABE | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $1AC1 | 18 | clc |
| $1AC2 | 69 0c | adc#$0c; Compensate for center shift on shrink |
| $1AC4 | 8d 00 d0 | sta$d000; Sprite 0 X Pos |
| $1AC7 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Jump Animation Frame 6 & 8 Handler. |
| ; Updates the player sprite to the descending graphic. |
| ; X position is processed but effectively unchanged (ADC #$00). |
| ; |
| ; Inputs: None |
| ; Outputs: Sprite 0 Pointer updated |
| ; Side Effects: Updates Sprite 0 graphic. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| jump_anim_frame_6_or_8 |
| $1AC8 | a9 d4 | lda#$d4; x-ref: $1A7F |
| $1ACA | 8d f8 07 | stasprite_ptr_0 |
| $1ACD | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $1AD0 | 18 | clc |
| $1AD1 | 69 00 | adc#$00 |
| $1AD3 | 8d 00 d0 | sta$d000; Sprite 0 X Pos |
| $1AD6 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Jump Animation Termination Handler. |
| ; Ends the jump sequence by resetting the jumping flag, silencing the jump sound |
| ; effect on SID Voice 1, and shifting the car left by 4 pixels. |
| ; |
| ; Inputs: Sprite 0 X position ($D000) |
| ; Outputs: player_is_jumping flag ($0805), Sprite 0 X position ($D000) |
| ; Side Effects: Stops jump sound, restores normal gameplay state. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1AD7 | a9 00 | jump_anim_terminatelda#$00; Animation Frame 9 (End): Reset sequence ; x-ref: $1A82 |
| $1AD9 | 8d 05 08 | staplayer_is_jumping |
| $1ADC | a9 c0 | lda#$c0 |
| $1ADE | 20 30 4c | jsrrestore_player_sprite_stop_sound; Stop SID Voice 1 jump sound |
| $1AE1 | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $1AE4 | 38 | sec |
| $1AE5 | e9 04 | sbc#$04 |
| $1AE7 | 8d 00 d0 | sta$d000; Sprite 0 X Pos |
| $1AEA | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Advances the jump animation frame counter and returns the new frame number. |
| ; |
| ; Inputs: jump_anim_frame |
| ; Outputs: A register (new frame number), jump_anim_frame |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1AEB | ee 06 08 | increment_jump_frameincjump_anim_frame; x-ref: $1A4E |
| $1AEE | ad 06 08 | ldajump_anim_frame |
| $1AF1 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Jump Animation Frame 0 (and 6) Handler. |
| ; Sets the player car sprite pointer to the neutral graphic. |
| ; |
| ; Inputs: None |
| ; Outputs: Sprite 0 Pointer updated |
| ; Side Effects: Updates Sprite 0 graphic. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1AF2 | a9 d2 | jump_anim_frame_0lda#$d2; x-ref: $1A79 |
| $1AF4 | 8d f8 07 | stasprite_ptr_0 |
| $1AF7 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Calculates and sets the base timer for the jump animation based on the car's |
| ; current speed/momentum. Adds 15 to the input accumulator value. |
| ; |
| ; Inputs: A register (base delay) |
| ; Outputs: jump_timer_base ($0807) |
| ; Side Effects: Adjusts the animation speed. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1AF8 | 18 | set_jump_timer_baseclc; x-ref: $1A12 |
| $1AF9 | 69 0f | adc#$0f |
| $1AFB | 8d 10 08 | stajump_timer_base |
| $1AFE | 60 | rts |
| $1AFF | 00 | .byte$00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Checks if the player's car has collided with physical background obstacles. |
| ; First, checks if the car is actively jumping (ignores collision if jump state |
| ; is non-zero). If on the ground, transforms Sprite 0's X and Y pixel positions |
| ; into 40x25 character grid coordinates (column and row). It then calculates |
| ; a pointer into Screen RAM ($0400) relative to the car's current position. |
| ; Finally, tests the four corners surrounding the car's footprint by fetching |
| ; the characters and calling $46DE to see if they are a fatal obstacle tile. |
| ; |
| ; Inputs: Jump State at $0805, Sprite 0 X/Y Positions ($D000, $D001) |
| ; Outputs: None (Direct exit/jump on collision via $46DE) |
| ; Side Effects: Can initiate crash sequence, mutates temp pointers $49 and $4A. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| check_background_collision |
| $1B00 | ad 05 08 | ldaplayer_is_jumping; Ignore collision if jumping ; x-ref: $1827, $4765 |
| $1B03 | f0 01 | beqb_1B06 |
| $1B05 | 60 | rts |
| $1B06 | ad 00 d0 | b_1B06lda$d000; Convert Pixel X to Char Column (divide by 8) ; x-ref: $1B03 Sprite 0 X Pos |
| $1B09 | 38 | sec |
| $1B0A | e9 10 | sbc#$10 |
| $1B0C | 4a | lsra |
| $1B0D | 4a | lsra |
| $1B0E | 4a | lsra |
| $1B0F | a8 | tay |
| $1B10 | a9 04 | lda#>SCREEN_RAM |
| $1B12 | 85 4a | stazp_p_tmp_hi |
| $1B14 | a9 00 | lda#<SCREEN_RAM |
| $1B16 | 85 49 | stazp_p_tmp_lo |
| $1B18 | ad 01 d0 | lda$d001; Convert Pixel Y to Char Row (divide by 8); Sprite 0 Y Pos |
| $1B1B | 38 | sec |
| $1B1C | e9 2e | sbc#$2e |
| $1B1E | 4a | lsra |
| $1B1F | 4a | lsra |
| $1B20 | 4a | lsra |
| $1B21 | aa | tax |
| $1B22 | f0 11 | j_1B22beqb_1B35; Calculate pointer offset down Screen RAM ; x-ref: $1B32 |
| $1B24 | a5 49 | ldazp_p_tmp_lo |
| $1B26 | 18 | clc |
| $1B27 | 69 28 | adc#$28 |
| $1B29 | 85 49 | stazp_p_tmp_lo |
| $1B2B | a5 4a | ldazp_p_tmp_hi |
| $1B2D | 69 00 | adc#$00 |
| $1B2F | 85 4a | stazp_p_tmp_hi |
| $1B31 | ca | dex |
| $1B32 | 4c 22 1b | jmpj_1B22 |
| $1B35 | b1 49 | b_1B35lda(zp_p_tmp_lo),y; Check Top-Left Character ; x-ref: $1B22 |
| $1B37 | ea | nop |
| $1B38 | 20 de 46 | jsrcheck_tile_is_obstacle |
| $1B3B | c8 | iny; Check Top-Right Character |
| $1B3C | b1 49 | lda(zp_p_tmp_lo),y |
| $1B3E | ea | nop |
| $1B3F | 20 de 46 | jsrcheck_tile_is_obstacle |
| $1B42 | 98 | tya; Move to Bottom-Left Character |
| $1B43 | 18 | clc |
| $1B44 | 69 27 | adc#$27 |
| $1B46 | a8 | tay |
| $1B47 | b1 49 | lda(zp_p_tmp_lo),y |
| $1B49 | ea | nop |
| $1B4A | 20 de 46 | jsrcheck_tile_is_obstacle |
| $1B4D | c8 | iny; Check Bottom-Right Character |
| $1B4E | b1 49 | lda(zp_p_tmp_lo),y |
| $1B50 | ea | nop |
| $1B51 | 20 de 46 | jsrcheck_tile_is_obstacle |
| $1B54 | 60 | rts |
| $1B55 | 4c 00 48 | j_1B55jmpplayer_death_handler; x-ref: $46E9 |
| $1B58 | | .byte$ad, $23, $08, $d0, $f7 |
| $1B5D | 20 10 46 | j_1B5Djsrshow_game_over_and_wait; x-ref: $4870 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; High Score Entry Screen |
| ; |
| ; Displays the high score screen, determines if the player's score qualifies |
| ; for the top 5, shifts the table to insert it, and lets the player enter |
| ; their 3-letter initials using a joystick-controlled letter grid. |
| ; A countdown timer auto-confirms when it reaches 00. |
| ; |
| ; Inputs: score_7digits ($2428) - player's current score (7 BCD digits) |
| ; joy_state ($F5) - joystick state for grid navigation |
| ; High score table at $7400-$7457 (5 entries: scores + names) |
| ; Outputs: state_cleanup_index ($0857) - ranking position (1-5), or 0 |
| ; High score table updated with new entry if qualified |
| ; Side Effects: Writes to Screen RAM ($0400+) and Color RAM ($D800+) |
| ; Calls update_hud_display. Runs a timed input loop. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| high_score_entry_screen |
| $1B60 | a2 00 | ldx#$00; X = loop counter 0..255 |
| $1B62 | bd 28 2c | b_1B62ldaenter_high_score_screen_1,x; copy letter grid row 1 to screen ; x-ref: $1B89 |
| $1B65 | 9d a0 04 | staSCREEN_RAM_R4C0,x |
| $1B68 | bd 00 2d | ldaenter_high_score_screen_2,x; copy letter grid row 2 to screen |
| $1B6B | 9d 78 05 | staSCREEN_RAM_R9C16,x |
| $1B6E | bd 00 2e | ldaenter_high_score_screen_3,x; copy letter grid row 3 to screen |
| $1B71 | 9d 78 06 | staSCREEN_RAM_R15C32,x |
| $1B74 | bd 78 2e | ldaenter_high_score_screen_4,x; copy letter grid row 4 to screen |
| $1B77 | 9d f0 06 | staSCREEN_RAM_R18C32,x |
| $1B7A | a9 07 | lda#VicIIColors.YELLOW; yellow |
| $1B7C | 9d 28 d8 | staCOLOR_RAM_R1C0,x; color 4 pages of Color RAM |
| $1B7F | 9d 00 d9 | staCOLOR_RAM_R6C16,x |
| $1B82 | 9d 00 da | staCOLOR_RAM_R12C32,x |
| $1B85 | 9d 00 db | staCOLOR_RAM_R19C8,x |
| $1B88 | e8 | inx |
| $1B89 | d0 d7 | bneb_1B62 |
| $1B8B | bd 28 24 | b_1B8Bldaf_2428,x; copy title/header to top of screen ; x-ref: $1B99 |
| $1B8E | 9d 28 04 | staSCREEN_RAM_R1C0,x |
| $1B91 | a9 0a | lda#VicIIColors.LIGHT_RED; light red |
| $1B93 | 9d 28 d8 | staCOLOR_RAM_R1C0,x |
| $1B96 | e8 | inx |
| $1B97 | e0 78 | cpx#$78 |
| $1B99 | d0 f0 | bneb_1B8B |
| ; --- Compare score against top 5 entries (7 BCD digits each) --- |
| $1B9B | a2 00 | check_1st_placeldx#$00 |
| $1B9D | bd 00 74 | b_1B9Dldaf_7400,x; 1st place score at $7400 ; x-ref: $1BAA |
| $1BA0 | dd 25 08 | cmpscore_7digits,x |
| $1BA3 | 30 0f | bmiis_1st_place; score < 1st? rank = 1 |
| $1BA5 | d0 12 | bnecheck_2nd_place; score > 1st? check 2nd |
| $1BA7 | e8 | inx |
| $1BA8 | e0 07 | cpx#$07 |
| $1BAA | d0 f1 | bneb_1B9D |
| $1BAC | a9 02 | lda#$02; score == 1st → rank 2 (below tie) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Stores the calculated ranking and proceeds to insert the score. |
| ; |
| ; Inputs: A = Rank (1-5, or 0 if not ranked) |
| ; Outputs: name_entry_substate = Rank |
| ; Side Effects: Jumps to insert_score_in_table |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| store_rank_and_insert |
| $1BAE | 8d 57 08 | staname_entry_substate; store ranking (0-5) ; x-ref: $1BB6, $1BCC, $1BD1, $1BE7, $1BEC, $1C02, $1C07, $1C1D, ... |
| $1BB1 | 4c 28 1c | jmpinsert_score_in_table |
| $1BB4 | a9 01 | is_1st_placelda#$01; Set rank to 1 ; x-ref: $1BA3 |
| $1BB6 | 4c ae 1b | jmpstore_rank_and_insert |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Compares the player's score against the 2nd place leaderboard score. |
| ; |
| ; Inputs: score_7digits = Player score, $7408 = 2nd place score |
| ; Outputs: A = Rank (2 if higher, 3 if equal, otherwise checks 3rd place) |
| ; Side Effects: Jumps to store_rank_and_insert or falls through to check_3rd_place |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1BB9 | a2 00 | check_2nd_placeldx#$00; x-ref: $1BA5 |
| $1BBB | bd 08 74 | check_2nd_loopldaf_7408,x; Load 2nd place digit ; x-ref: $1BC8 |
| $1BBE | dd 25 08 | cmpscore_7digits,x; Compare with player's score digit |
| $1BC1 | 30 0c | bmiis_2nd_place; Leaderboard digit < player digit -> player is 2nd |
| $1BC3 | d0 0f | bnecheck_3rd_place; Leaderboard digit > player digit -> check 3rd |
| $1BC5 | e8 | inx |
| $1BC6 | e0 07 | cpx#$07 |
| $1BC8 | d0 f1 | bnecheck_2nd_loop |
| $1BCA | a9 03 | lda#$03; Scores equal -> player becomes 3rd |
| $1BCC | 4c ae 1b | jmpstore_rank_and_insert |
| $1BCF | a9 02 | is_2nd_placelda#$02; Set rank to 2 ; x-ref: $1BC1 |
| $1BD1 | 4c ae 1b | jmpstore_rank_and_insert |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Compares the player's score against the 3rd place leaderboard score. |
| ; |
| ; Inputs: score_7digits = Player score, $7410 = 3rd place score |
| ; Outputs: A = Rank (3 if higher, 4 if equal, otherwise checks 4th place) |
| ; Side Effects: Jumps to store_rank_and_insert or falls through to check_4th_place |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1BD4 | a2 00 | check_3rd_placeldx#$00; x-ref: $1BC3 |
| $1BD6 | bd 10 74 | check_3rd_loopldaf_7410,x; Load 3rd place digit ; x-ref: $1BE3 |
| $1BD9 | dd 25 08 | cmpscore_7digits,x; Compare with player's score digit |
| $1BDC | 30 0c | bmiis_3rd_place; Leaderboard digit < player digit -> player is 3rd |
| $1BDE | d0 0f | bnecheck_4th_place; Leaderboard digit > player digit -> check 4th |
| $1BE0 | e8 | inx |
| $1BE1 | e0 07 | cpx#$07 |
| $1BE3 | d0 f1 | bnecheck_3rd_loop |
| $1BE5 | a9 04 | lda#$04; Scores equal -> player becomes 4th |
| $1BE7 | 4c ae 1b | jmpstore_rank_and_insert; shift 2nd→3rd |
| $1BEA | a9 03 | is_3rd_placelda#$03; Set rank to 3 ; x-ref: $1BDC |
| $1BEC | 4c ae 1b | jmpstore_rank_and_insert |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Compares the player's score against the 4th place leaderboard score. |
| ; |
| ; Inputs: score_7digits = Player score, $7418 = 4th place score |
| ; Outputs: A = Rank (4 if higher, 5 if equal, otherwise checks 5th place) |
| ; Side Effects: Jumps to store_rank_and_insert or falls through to check_5th_place |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1BEF | a2 00 | check_4th_placeldx#$00; x-ref: $1BDE |
| $1BF1 | bd 18 74 | check_4th_loopldaf_7418,x; Load 4th place digit ; x-ref: $1BFE |
| $1BF4 | dd 25 08 | cmpscore_7digits,x; Compare with player's score digit |
| $1BF7 | 30 0c | bmiis_4th_place; Leaderboard digit < player digit -> player is 4th |
| $1BF9 | d0 0f | bnecheck_5th_place; Leaderboard digit > player digit -> check 5th |
| $1BFB | e8 | inx |
| $1BFC | e0 07 | cpx#$07 |
| $1BFE | d0 f1 | bnecheck_4th_loop |
| $1C00 | a9 05 | lda#$05; Scores equal -> player becomes 5th |
| $1C02 | 4c ae 1b | jmpstore_rank_and_insert |
| $1C05 | a9 04 | is_4th_placelda#$04; Set rank to 4 ; x-ref: $1BF7 |
| $1C07 | 4c ae 1b | jmpstore_rank_and_insert |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Compares the player's score against the 5th place leaderboard score. |
| ; |
| ; Inputs: score_7digits = Player score, $7420 = 5th place score |
| ; Outputs: A = Rank (5 if higher, 0 if equal or lower) |
| ; Side Effects: Jumps to store_rank_and_insert |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1C0A | a2 00 | check_5th_placeldx#$00; x-ref: $1BF9 |
| $1C0C | bd 20 74 | check_5th_loopldaf_7420,x; Load 5th place digit ; x-ref: $1C19 |
| $1C0F | dd 25 08 | cmpscore_7digits,x; Compare with player's score digit |
| $1C12 | 30 0c | bmiis_5th_place; Leaderboard digit < player digit -> player is 5th |
| $1C14 | d0 0f | bnescore_too_low; Leaderboard digit > player digit -> score too low |
| $1C16 | e8 | inx |
| $1C17 | e0 07 | cpx#$07 |
| $1C19 | d0 f1 | bnecheck_5th_loop |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles the case where the player's score did not qualify for the top 5. |
| ; |
| ; Inputs: None |
| ; Outputs: A = 0 (Rank 0) |
| ; Side Effects: Jumps to store_rank_and_insert |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1C1B | a9 00 | score_not_rankedlda#$00; Rank 0 = not in top 5 ; x-ref: $1C25 |
| $1C1D | 4c ae 1b | jmpstore_rank_and_insert |
| $1C20 | a9 05 | is_5th_placelda#$05; Set rank to 5 ; x-ref: $1C12 |
| $1C22 | 4c ae 1b | jmpstore_rank_and_insert |
| $1C25 | 4c 1b 1c | score_too_lowjmpscore_not_ranked; Jump to unranked handler ; x-ref: $1C14 |
| ; --- Shift table entries down and insert new score --- |
| insert_score_in_table |
| $1C28 | ad 57 08 | ldaname_entry_substate; x-ref: $1BB1 |
| $1C2B | f0 4f | beqb_1C7C; rank 0 = not ranked, skip insertion |
| $1C2D | c9 05 | cmp#$05 |
| $1C2F | f0 4b | b_1C2Fbeqb_1C7C; x-ref: $1C45, $1C59, $1C6D |
| $1C31 | 20 f7 1c | jsrshift_name_entries_down; shift name entries down |
| $1C34 | ea | nop |
| $1C35 | bd 18 74 | b_1C35ldaf_7418,x; shift 5th→6th (discard) ; x-ref: $1C3E |
| $1C38 | 9d 20 74 | staf_7420,x; beq score_not_ranked (rank 0) |
| $1C3B | e8 | inx |
| $1C3C | e0 08 | cpx#$08 |
| $1C3E | d0 f5 | bneb_1C35 |
| $1C40 | ad 57 08 | ldaname_entry_substate |
| $1C43 | c9 04 | cmp#$04 |
| $1C45 | f0 e8 | beqb_1C2F |
| $1C47 | a2 00 | ldx#$00 |
| $1C49 | bd 10 74 | b_1C49ldaf_7410,x; x-ref: $1C52 |
| $1C4C | 9d 18 74 | staf_7418,x |
| $1C4F | e8 | inx |
| $1C50 | e0 08 | cpx#$08 |
| $1C52 | d0 f5 | bneb_1C49 |
| $1C54 | ad 57 08 | ldaname_entry_substate |
| $1C57 | c9 03 | cmp#$03 |
| $1C59 | f0 d4 | beqb_1C2F |
| $1C5B | a2 00 | ldx#$00; shift 3rd→4th |
| $1C5D | bd 08 74 | b_1C5Dldaf_7408,x; x-ref: $1C66 |
| $1C60 | 9d 10 74 | staf_7410,x |
| $1C63 | e8 | inx |
| $1C64 | e0 08 | cpx#$08 |
| $1C66 | d0 f5 | bneb_1C5D |
| $1C68 | ad 57 08 | ldaname_entry_substate |
| $1C6B | c9 02 | cmp#$02 |
| $1C6D | f0 c0 | beqb_1C2F |
| $1C6F | a2 00 | ldx#$00; shift 2nd→3rd |
| $1C71 | bd 00 74 | b_1C71ldaf_7400,x; x-ref: $1C7A |
| $1C74 | 9d 08 74 | staf_7408,x |
| $1C77 | e8 | inx |
| $1C78 | e0 08 | cpx#$08 |
| $1C7A | d0 f5 | bneb_1C71 |
| $1C7C | ad 57 08 | b_1C7Cldaname_entry_substate; x-ref: $1C2B, $1C2F |
| $1C7F | f0 1a | beqdisplay_high_score_table |
| $1C81 | 38 | sec |
| $1C82 | e9 01 | sbc#$01 |
| $1C84 | 0a | asla |
| $1C85 | 0a | asla |
| $1C86 | 0a | asla |
| $1C87 | a8 | tay |
| $1C88 | a2 00 | ldx#$00 |
| $1C8A | bd 25 08 | b_1C8Aldascore_7digits,x; x-ref: $1C99 |
| $1C8D | 99 00 74 | staf_7400,y |
| $1C90 | a9 20 | lda#$20 |
| $1C92 | 99 30 74 | staf_7430,y |
| $1C95 | c8 | iny |
| $1C96 | e8 | inx; copy 7 score digits to table |
| $1C97 | e0 07 | cpx#$07 |
| $1C99 | d0 ef | bneb_1C8A |
| ; --- Render all 5 entries: names to screen --- |
| display_high_score_table |
| $1C9B | a2 00 | ldx#$00; x-ref: $1C7F |
| $1C9D | bd 30 74 | b_1C9Dldaf_7430,x; name entry 1 (3 chars) ; x-ref: $1CBE |
| $1CA0 | 9d 18 06 | staSCREEN_RAM_R13C16,x |
| $1CA3 | bd 38 74 | ldaf_7438,x |
| $1CA6 | 9d 68 06 | staSCREEN_RAM_R15C16,x |
| $1CA9 | bd 40 74 | ldaf_7440,x |
| $1CAC | 9d b8 06 | staSCREEN_RAM_R17C16,x; name entry 4 |
| $1CAF | bd 48 74 | ldaf_7448,x; inner delay loop (256 ticks) |
| $1CB2 | 9d 08 07 | staSCREEN_RAM_R19C16,x |
| $1CB5 | bd 50 74 | ldaf_7450,x; delay loop outer: 256 * 256 iterations for pacing |
| $1CB8 | 9d 58 07 | staSCREEN_RAM_R21C16,x |
| $1CBB | e8 | inx; ones digit: SBC #1; underflow ($FF) means carry to tens |
| $1CBC | e0 03 | cpx#$03 |
| $1CBE | d0 dd | bneb_1C9D |
| $1CC0 | a2 00 | ldx#$00 |
| ; --- Render score digits (+$30 = screen code '0') --- |
| display_scores_as_digits |
| $1CC2 | bd 00 74 | ldaf_7400,x; x-ref: $1CF2 |
| $1CC5 | 18 | clc |
| $1CC6 | 69 30 | adc#$30; if both digits zero: timer expired, auto-confirm |
| $1CC8 | 9d 1c 06 | staSCREEN_RAM_R13C20,x |
| $1CCB | bd 08 74 | ldaf_7408,x |
| $1CCE | 18 | clc |
| $1CCF | 69 30 | adc#$30 |
| $1CD1 | 9d 6c 06 | staSCREEN_RAM_R15C20,x |
| $1CD4 | bd 10 74 | ldaf_7410,x |
| $1CD7 | 18 | clc |
| $1CD8 | 69 30 | adc#$30 |
| $1CDA | 9d bc 06 | staSCREEN_RAM_R17C20,x |
| $1CDD | bd 18 74 | ldaf_7418,x |
| $1CE0 | 18 | clc |
| $1CE1 | 69 30 | adc#$30 |
| $1CE3 | 9d 0c 07 | staSCREEN_RAM_R19C20,x |
| $1CE6 | bd 20 74 | ldaf_7420,x |
| $1CE9 | 18 | clc |
| $1CEA | 69 30 | adc#$30 |
| $1CEC | 9d 5c 07 | staSCREEN_RAM_R21C20,x |
| $1CEF | e8 | inx |
| $1CF0 | e0 07 | cpx#$07 |
| $1CF2 | d0 ce | bnedisplay_scores_as_digits |
| $1CF4 | 4c 4e 1d | jmpafter_table_update |
| ; --- Shift 3-char name entries down in the name table ($7430) --- |
| shift_name_entries_down |
| $1CF7 | ad 57 08 | ldaname_entry_substate; x-ref: $1C31 |
| $1CFA | c9 05 | cmp#$05 |
| $1CFC | f0 7e | beqb_1D7C |
| $1CFE | c9 00 | cmp#$00 |
| $1D00 | f0 7a | beqb_1D7C |
| $1D02 | a2 00 | ldx#$00 |
| $1D04 | bd 48 74 | b_1D04ldaf_7448,x; shift 5th name → 6th (discard) ; x-ref: $1D0D |
| $1D07 | 9d 50 74 | staf_7450,x |
| $1D0A | e8 | inx |
| $1D0B | e0 03 | cpx#$03 |
| $1D0D | d0 f5 | bneb_1D04 |
| $1D0F | ad 57 08 | ldaname_entry_substate |
| $1D12 | c9 04 | cmp#$04 |
| $1D14 | f0 35 | beqb_1D4B |
| $1D16 | a2 00 | ldx#$00 |
| $1D18 | bd 40 74 | b_1D18ldaf_7440,x; shift 4th → 5th ; x-ref: $1D21 |
| $1D1B | 9d 48 74 | staf_7448,x |
| $1D1E | e8 | inx |
| $1D1F | e0 03 | cpx#$03 |
| $1D21 | d0 f5 | bneb_1D18 |
| $1D23 | ad 57 08 | ldaname_entry_substate |
| $1D26 | c9 03 | cmp#$03 |
| $1D28 | f0 21 | beqb_1D4B |
| $1D2A | a2 00 | ldx#$00 |
| $1D2C | bd 38 74 | b_1D2Cldaf_7438,x; shift 3rd → 4th ; x-ref: $1D35 |
| $1D2F | 9d 40 74 | staf_7440,x |
| $1D32 | e8 | inx |
| $1D33 | e0 03 | cpx#$03 |
| $1D35 | d0 f5 | bneb_1D2C |
| $1D37 | ad 57 08 | ldaname_entry_substate |
| $1D3A | c9 02 | cmp#$02 |
| $1D3C | f0 0d | beqb_1D4B |
| $1D3E | a2 00 | ldx#$00 |
| $1D40 | bd 30 74 | b_1D40ldaf_7430,x; shift 2nd → 3rd ; x-ref: $1D49 |
| $1D43 | 9d 38 74 | staf_7438,x |
| $1D46 | e8 | inx |
| $1D47 | e0 03 | cpx#$03 |
| $1D49 | d0 f5 | bneb_1D40 |
| $1D4B | a2 00 | b_1D4Bldx#$00; x-ref: $1D14, $1D28, $1D3C |
| $1D4D | 60 | rts |
| ; --- Check if player qualified; if so, enter initials --- |
| $1D4E | 20 b0 16 | after_table_updatejsrupdate_hud_display; copy message to screen ; x-ref: $1CF4 |
| $1D51 | ad 57 08 | ldaname_entry_substate |
| $1D54 | d0 03 | bneb_1D59; color = cyan |
| $1D56 | 4c fc 1d | b_1D56jmpshow_not_in_top_5_message; x-ref: $1D5B |
| $1D59 | c9 00 | b_1D59cmp#$00; x-ref: $1D54 |
| $1D5B | f0 f9 | beqb_1D56; read screen char at cursor → store as 1st initial in table and screen |
| $1D5D | a9 09 | lda#$09; countdown timer tens digit = 9 |
| $1D5F | 8d 58 08 | stahighscore_timer_tens |
| $1D62 | a9 09 | lda#$09 |
| $1D64 | 8d 59 08 | stahighscore_timer_ones; countdown timer ones digit = 9 |
| $1D67 | a9 05 | lda#$05 |
| $1D69 | 8d 60 08 | staactive_row |
| $1D6C | a9 06 | lda#$06 |
| $1D6E | 8d 61 08 | staactive_col; starting grid column = 6 |
| $1D71 | a2 00 | ldx#$00 |
| ; High Score input loop: display cursor, read joystick |
| $1D73 | 20 25 1e | highscore_input_loopjsrdraw_highscore_timer_and_cursor; x-ref: $1DE7 |
| $1D76 | 20 b7 1e | jsrhighlight_cursor_cell |
| $1D79 | ea | nop |
| $1D7A | ea | nop |
| $1D7B | ea | nop |
| $1D7C | ea | b_1D7Cnop; x-ref: $1CFC, $1D00 |
| $1D7D | ea | nop |
| $1D7E | ea | nop |
| $1D7F | ea | nop |
| $1D80 | ea | nop |
| $1D81 | ea | nop |
| $1D82 | ea | nop |
| $1D83 | ad f5 00 | lda@w zp_joy_state; read joystick port |
| $1D86 | 29 1f | and#$1f; mask direction + fire bits |
| $1D88 | c9 1e | cmp#$1e; $1E = up |
| $1D8A | f0 60 | beqhighscore_joy_up |
| $1D8C | c9 1d | cmp#$1d; $1D = down |
| $1D8E | f0 5f | beqhighscore_joy_down |
| $1D90 | c9 1b | cmp#$1b; $1B = left |
| $1D92 | f0 5e | beqhighscore_joy_left |
| $1D94 | c9 17 | cmp#$17; $17 = right |
| $1D96 | f0 5d | beqhighscore_joy_right |
| $1D98 | c9 0f | cmp#$0f; $0F = fire button |
| $1D9A | f0 5c | beqhighscore_joy_fire |
| ; --- Decrement countdown timer; end entry when expired --- |
| $1D9C | 20 25 1e | decrement_timerjsrdraw_highscore_timer_and_cursor; display timer, then delay ; x-ref: $1E6C, $1E7F, $1E92, $1EA8, $1F97, $4688, $4698, $46A8, ... |
| $1D9F | 8a | txa |
| $1DA0 | 48 | pha |
| $1DA1 | a2 00 | ldx#$00 |
| $1DA3 | a0 00 | b_1DA3ldy#$00; x-ref: $1DA9 |
| $1DA5 | 88 | b_1DA5dey; x-ref: $1DA6 |
| $1DA6 | d0 fd | bneb_1DA5 |
| $1DA8 | ca | dex |
| $1DA9 | d0 f8 | bneb_1DA3 |
| $1DAB | 68 | pla |
| $1DAC | aa | tax |
| $1DAD | ad 59 08 | ldahighscore_timer_ones; advance name letter index, then rejoin timer tick |
| $1DB0 | 38 | sec; ones digit -= 1 |
| $1DB1 | e9 01 | sbc#$01 |
| $1DB3 | 8d 59 08 | stahighscore_timer_ones |
| $1DB6 | c9 ff | cmp#$ff; underflow? wrap to 9 |
| $1DB8 | d0 0e | bneb_1DC8 |
| $1DBA | a9 09 | lda#$09; reset ones to 9 |
| $1DBC | 8d 59 08 | stahighscore_timer_ones |
| $1DBF | ad 58 08 | ldahighscore_timer_tens; tens digit -= 1 |
| $1DC2 | 38 | sec |
| $1DC3 | e9 01 | sbc#$01 |
| $1DC5 | 8d 58 08 | stahighscore_timer_tens |
| $1DC8 | ad 58 08 | b_1DC8ldahighscore_timer_tens; x-ref: $1DB8, $46D1 |
| $1DCB | d0 1a | bneb_1DE7 |
| $1DCD | ad 59 08 | ldahighscore_timer_ones |
| $1DD0 | d0 15 | bneb_1DE7 |
| $1DD2 | ad 58 08 | ldahighscore_timer_tens |
| $1DD5 | 18 | clc |
| $1DD6 | 69 30 | adc#$30 |
| $1DD8 | 8d cb 05 | staSCREEN_RAM_R11C19 |
| $1DDB | ad 59 08 | ldahighscore_timer_ones |
| $1DDE | 18 | clc |
| $1DDF | 69 30 | adc#$30 |
| $1DE1 | 8d cc 05 | staSCREEN_RAM_R11C20 |
| $1DE4 | 4c 0e 1e | jmpj_1E0E |
| $1DE7 | 4c 73 1d | b_1DE7jmphighscore_input_loop; x-ref: $1DCB, $1DD0 |
| $1DEA | | .byte$71, $1d |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Highscore Joystick Dispatch Trampolines |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Jumps to the respective cursor movement or fire handler |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1DEC | 4c 65 1e | highscore_joy_upjmphighscore_move_up; Dispatch up ; x-ref: $1D8A |
| $1DEF | 4c 78 1e | highscore_joy_downjmphighscore_move_down; Dispatch down ; x-ref: $1D8E |
| $1DF2 | 4c 8b 1e | highscore_joy_leftjmphighscore_move_left; Dispatch left ; x-ref: $1D92 |
| $1DF5 | 4c a1 1e | highscore_joy_rightjmphighscore_move_right; Dispatch right ; x-ref: $1D96 |
| $1DF8 | 4c be 3f | highscore_joy_firejmphighscore_fire_pressed; Dispatch fire ; x-ref: $1D9A |
| $1DFB | ea | .byte$ea |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Display "Not In Top 5" Message |
| ; |
| ; Inputs: None |
| ; Outputs: Screen RAM and Color RAM |
| ; Side Effects: Copies the text to the screen and sets its color to cyan |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| show_not_in_top_5_message |
| $1DFC | a2 00 | ldx#$00; x-ref: $1D56 |
| $1DFE | bd d0 2f | b_1DFEldatxt_you_arent_in_the_five_best_scores,x; Read character from message ; x-ref: $1E0C |
| $1E01 | 9d bb 05 | staSCREEN_RAM_R11C3,x; Write to screen RAM |
| $1E04 | a9 03 | lda#VicIIColors.CYAN; Cyan color |
| $1E06 | 9d bb d9 | staCOLOR_RAM_R11C3,x; Write to color RAM |
| $1E09 | e8 | inx |
| $1E0A | e0 22 | cpx#$22 |
| $1E0C | d0 f0 | bneb_1DFE |
| $1E0E | 4c e1 51 | j_1E0Ejmppoll_joy_for_scroll_switch; x-ref: $1DE4 |
| ; dead code |
| $1E11 | | .byte$5a, $08, $a2, $00, $a0, $00, $88, $d0 |
| $1E19 | | .byte$fd, $ca, $d0, $f8, $ce, $5a, $08, $d0 |
| $1E21 | | .byte$f1, $4c, $00, $51 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Draw Highscore Timer And Cursor |
| ; |
| ; Inputs: highscore_timer_tens, highscore_timer_ones, active_row, active_col |
| ; Outputs: Screen RAM and Color RAM |
| ; Side Effects: Updates the timer display digits, colors them cyan, and colors the active cursor letter red |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| draw_highscore_timer_and_cursor |
| $1E25 | ad 58 08 | ldahighscore_timer_tens; Load tens digit ; x-ref: $1D73, $1D9C |
| $1E28 | 18 | clc |
| $1E29 | 69 30 | adc#$30; Convert to screencode |
| $1E2B | 8d cb 05 | staSCREEN_RAM_R11C19 |
| $1E2E | ad 59 08 | ldahighscore_timer_ones; Load ones digit |
| $1E31 | 18 | clc |
| $1E32 | 69 30 | adc#$30; Convert to screencode |
| $1E34 | 8d cc 05 | staSCREEN_RAM_R11C20 |
| $1E37 | a9 03 | lda#VicIIColors.CYAN; Cyan color |
| $1E39 | 8d cb d9 | staCOLOR_RAM_R11C19 |
| $1E3C | 8d cc d9 | staCOLOR_RAM_R11C20 |
| $1E3F | a9 d8 | lda#>COLOR_RAM; Color RAM high byte ($D8) |
| $1E41 | 85 4a | stazp_p_tmp_hi |
| $1E43 | ad 61 08 | ldaactive_col; Cursor column |
| $1E46 | 85 49 | stazp_p_tmp_lo |
| $1E48 | ac 60 08 | ldyactive_row; Cursor row |
| $1E4B | f0 11 | j_1E4Bbeqb_1E5E; move cursor left (min col = 6) ; x-ref: $1E5B |
| $1E4D | a5 49 | ldazp_p_tmp_lo |
| $1E4F | 18 | clc; Add 40 for each row |
| $1E50 | 69 28 | adc#$28 |
| $1E52 | 85 49 | stazp_p_tmp_lo |
| $1E54 | a5 4a | ldazp_p_tmp_hi |
| $1E56 | 69 00 | adc#$00 |
| $1E58 | 85 4a | stazp_p_tmp_hi |
| $1E5A | 88 | dey |
| $1E5B | 4c 4b 1e | jmpj_1E4B |
| $1E5E | a9 02 | b_1E5Elda#$02; Red color ; x-ref: $1E4B |
| $1E60 | a0 00 | ldy#$00 |
| $1E62 | 91 49 | sta(zp_p_tmp_lo),y; Set letter color to red |
| $1E64 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Highscore Move Cursor Up |
| ; |
| ; Inputs: active_row |
| ; Outputs: active_row |
| ; Side Effects: Decreases row by 2, capped at min row 5 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1E65 | ad 60 08 | highscore_move_upldaactive_row; x-ref: $1DEC |
| $1E68 | c9 05 | cmp#$05; Min row 5 |
| $1E6A | d0 03 | bneb_1E6F |
| $1E6C | 4c 9c 1d | j_1E6Cjmpdecrement_timer; x-ref: $1E75 |
| $1E6F | ce 60 08 | b_1E6Fdecactive_row; Move up 2 cells ; x-ref: $1E6A |
| $1E72 | ce 60 08 | decactive_row |
| $1E75 | 4c 6c 1e | jmpj_1E6C |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Highscore Move Cursor Down |
| ; |
| ; Inputs: active_row |
| ; Outputs: active_row |
| ; Side Effects: Increases row by 2, capped at max row 9 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1E78 | ad 60 08 | highscore_move_downldaactive_row; x-ref: $1DEF |
| $1E7B | c9 09 | cmp#$09; Max row 9 |
| $1E7D | d0 03 | bneb_1E82 |
| $1E7F | 4c 9c 1d | j_1E7Fjmpdecrement_timer; x-ref: $1E88 |
| $1E82 | ee 60 08 | b_1E82incactive_row; Move down 2 cells ; x-ref: $1E7D |
| $1E85 | ee 60 08 | incactive_row |
| $1E88 | 4c 7f 1e | jmpj_1E7F |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Highscore Move Cursor Left |
| ; |
| ; Inputs: active_col |
| ; Outputs: active_col |
| ; Side Effects: Decreases column by 3, capped at min col 6 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1E8B | ad 61 08 | highscore_move_leftldaactive_col; x-ref: $1DF2 |
| $1E8E | c9 06 | cmp#$06; Min col 6 |
| $1E90 | d0 03 | bneb_1E95 |
| $1E92 | 4c 9c 1d | j_1E92jmpdecrement_timer; x-ref: $1E9E |
| $1E95 | ce 61 08 | b_1E95decactive_col; Move left 3 cells ; x-ref: $1E90 |
| $1E98 | ce 61 08 | decactive_col |
| $1E9B | ce 61 08 | decactive_col |
| $1E9E | 4c 92 1e | jmpj_1E92 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Highscore Move Cursor Right |
| ; |
| ; Inputs: active_col |
| ; Outputs: active_col |
| ; Side Effects: Increases column by 3, capped at max col 33 ($21) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $1EA1 | ad 61 08 | highscore_move_rightldaactive_col; x-ref: $1DF5 |
| $1EA4 | c9 21 | cmp#$21; Max col $21 (33) |
| $1EA6 | d0 03 | bneb_1EAB |
| $1EA8 | 4c 9c 1d | j_1EA8jmpdecrement_timer; x-ref: $1EB4 |
| $1EAB | ee 61 08 | b_1EABincactive_col; Move right 3 cells ; x-ref: $1EA6 |
| $1EAE | ee 61 08 | incactive_col |
| $1EB1 | ee 61 08 | incactive_col |
| $1EB4 | 4c a8 1e | jmpj_1EA8 |
| ; --- Set Color RAM at (active_row, active_col) to yellow --- |
| highlight_cursor_cell |
| $1EB7 | a9 d8 | lda#$d8; $D8 = high byte of Color RAM ($D800) ; x-ref: $1D76 |
| $1EB9 | 85 4a | stazp_p_tmp_hi |
| $1EBB | ad 61 08 | ldaactive_col |
| $1EBE | 85 49 | stazp_p_tmp_lo |
| $1EC0 | ac 60 08 | ldyactive_row |
| $1EC3 | f0 11 | j_1EC3beqb_1ED6; x-ref: $1ED3 |
| $1EC5 | a5 49 | ldazp_p_tmp_lo |
| $1EC7 | 18 | clc |
| $1EC8 | 69 28 | adc#$28 |
| $1ECA | 85 49 | stazp_p_tmp_lo |
| $1ECC | a5 4a | ldazp_p_tmp_hi |
| $1ECE | 69 00 | adc#$00 |
| $1ED0 | 85 4a | stazp_p_tmp_hi |
| $1ED2 | 88 | dey |
| $1ED3 | 4c c3 1e | jmpj_1EC3 |
| $1ED6 | a9 07 | b_1ED6lda#$07; yellow ; x-ref: $1EC3 |
| $1ED8 | a0 00 | ldy#$00 |
| $1EDA | 91 49 | sta(zp_p_tmp_lo),y |
| $1EDC | 60 | rts |
| $1EDD | 4c 59 46 | j_1EDDjmpj_4659; x-ref: $4656 |
| ; dead code |
| $1EE0 | | .byte$00, $d0, $06, $a5, $4a, $c9, $00, $00 |
| $1EE8 | | .byte$fe, $a5, $49, $c9, $00, $d0, $06, $a5 |
| $1EF0 | | .byte$4a, $c9, $00, $00, $fe |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handle Name Letter Selection |
| ; |
| ; Inputs: X (letter index 0-2), name_entry_substate (rank), p_tmp (points to Color RAM cell) |
| ; Outputs: Screen RAM, Highscore Buffer |
| ; Side Effects: Converts color RAM pointer to screen RAM pointer, reads the selected character, and saves it to the respective rank's highscore name buffer and display location. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| handle_name_letter_selection |
| $1EF5 | e0 03 | cpx#$03; Check if 3 letters entered ; x-ref: $4675 |
| $1EF7 | d0 03 | bneb_1EFC |
| $1EF9 | 4c c7 46 | jmpterminate_name_entry |
| $1EFC | ad 57 08 | b_1EFCldaname_entry_substate; Load player rank (1-5) ; x-ref: $1EF7 |
| $1EFF | c9 01 | cmp#$01; Rank 1? |
| $1F01 | d0 1b | bneb_1F1E |
| $1F03 | a5 4a | ldazp_p_tmp_hi |
| $1F05 | 38 | sec |
| $1F06 | e9 d4 | sbc#$d4; Subtract $D4 to point to Screen RAM ($0400 page) |
| $1F08 | 85 4a | stazp_p_tmp_hi |
| $1F0A | a0 00 | ldy#$00 |
| $1F0C | b1 49 | lda(zp_p_tmp_lo),y; Read selected char from Screen RAM |
| $1F0E | 9d 30 74 | staf_7430,x; Store in Rank 1 name buffer |
| $1F11 | 9d 18 06 | staSCREEN_RAM_R13C16,x; Write to screen display |
| $1F14 | a5 4a | ldazp_p_tmp_hi |
| $1F16 | 18 | clc |
| $1F17 | 69 d4 | adc#$d4; Restore pointer to Color RAM |
| $1F19 | 85 4a | stazp_p_tmp_hi |
| $1F1B | 4c 96 1f | jmpj_1F96 |
| $1F1E | c9 02 | b_1F1Ecmp#$02; x-ref: $1F01 |
| $1F20 | d0 1b | bneb_1F3D |
| $1F22 | a5 4a | ldazp_p_tmp_hi |
| $1F24 | 38 | sec |
| $1F25 | e9 d4 | sbc#$d4 |
| $1F27 | 85 4a | stazp_p_tmp_hi |
| $1F29 | a0 00 | ldy#$00 |
| $1F2B | b1 49 | lda(zp_p_tmp_lo),y |
| $1F2D | 9d 38 74 | staf_7438,x |
| $1F30 | 9d 68 06 | staSCREEN_RAM_R15C16,x |
| $1F33 | a5 4a | ldazp_p_tmp_hi |
| $1F35 | 18 | clc |
| $1F36 | 69 d4 | adc#$d4 |
| $1F38 | 85 4a | stazp_p_tmp_hi |
| $1F3A | 4c 96 1f | jmpj_1F96 |
| $1F3D | c9 03 | b_1F3Dcmp#$03; x-ref: $1F20 |
| $1F3F | d0 1b | bneb_1F5C |
| $1F41 | a5 4a | ldazp_p_tmp_hi |
| $1F43 | 38 | sec |
| $1F44 | e9 d4 | sbc#$d4 |
| $1F46 | 85 4a | stazp_p_tmp_hi |
| $1F48 | a0 00 | ldy#$00 |
| $1F4A | b1 49 | lda(zp_p_tmp_lo),y |
| $1F4C | 9d 40 74 | staf_7440,x |
| $1F4F | 9d b8 06 | staSCREEN_RAM_R17C16,x |
| $1F52 | a5 4a | ldazp_p_tmp_hi |
| $1F54 | 18 | clc |
| $1F55 | 69 d4 | adc#$d4 |
| $1F57 | 85 4a | stazp_p_tmp_hi |
| $1F59 | 4c 96 1f | jmpj_1F96 |
| $1F5C | c9 04 | b_1F5Ccmp#$04; x-ref: $1F3F |
| $1F5E | d0 1b | bneb_1F7B |
| $1F60 | a5 4a | ldazp_p_tmp_hi |
| $1F62 | 38 | sec |
| $1F63 | e9 d4 | sbc#$d4 |
| $1F65 | 85 4a | stazp_p_tmp_hi |
| $1F67 | a0 00 | ldy#$00 |
| $1F69 | b1 49 | lda(zp_p_tmp_lo),y |
| $1F6B | 9d 48 74 | staf_7448,x |
| $1F6E | 9d 08 07 | staSCREEN_RAM_R19C16,x |
| $1F71 | a5 4a | ldazp_p_tmp_hi |
| $1F73 | 18 | clc |
| $1F74 | 69 d4 | adc#$d4 |
| $1F76 | 85 4a | stazp_p_tmp_hi |
| $1F78 | 4c 96 1f | jmpj_1F96 |
| $1F7B | a5 4a | b_1F7Bldazp_p_tmp_hi; x-ref: $1F5E |
| $1F7D | 38 | sec |
| $1F7E | e9 d4 | sbc#$d4 |
| $1F80 | 85 4a | stazp_p_tmp_hi |
| $1F82 | a0 00 | ldy#$00 |
| $1F84 | b1 49 | lda(zp_p_tmp_lo),y |
| $1F86 | 9d 50 74 | staf_7450,x |
| $1F89 | 9d 58 07 | staSCREEN_RAM_R21C16,x |
| $1F8C | a5 4a | ldazp_p_tmp_hi |
| $1F8E | 18 | clc |
| $1F8F | 69 d4 | adc#$d4 |
| $1F91 | 85 4a | stazp_p_tmp_hi |
| $1F93 | 4c 96 1f | jmpj_1F96 |
| $1F96 | e8 | j_1F96inx; x-ref: $1F1B, $1F3A, $1F59, $1F78, $1F93 |
| $1F97 | 4c 9c 1d | jmpdecrement_timer |
| ; Dead code |
| $1F9A | | .byte$00, $88, $d0, $fd, $ca, $d0, $f8, $ce |
| $1FA2 | | .byte$c0, $08, $d0, $f1, $60 |
| ; converts level_nr (0-based) to 2-digit screencodes for HUD |
| ; level 0-8 → '01'-'09'; level 9-18 → '10'-'19'; level 19-28 → '20'-'28'; level 29+ → '30'+ |
| write_level_nr_to_hud |
| $1FA7 | ad 00 08 | ldalevel_nr; x-ref: $16D4 |
| $1FAA | c9 1d | cmp#$1d |
| $1FAC | 30 0c | bmib_1FBA |
| $1FAE | 18 | clc |
| $1FAF | 69 13 | adc#$13 |
| $1FB1 | 8d 1a 04 | staSCREEN_RAM_R0C26 |
| $1FB4 | a9 33 | lda#$33 |
| $1FB6 | 8d 19 04 | staSCREEN_RAM_R0C25 |
| $1FB9 | 60 | rts |
| $1FBA | c9 13 | b_1FBAcmp#$13; x-ref: $1FAC |
| $1FBC | 30 0c | bmib_1FCA |
| $1FBE | 18 | clc |
| $1FBF | 69 1d | adc#$1d |
| $1FC1 | 8d 1a 04 | staSCREEN_RAM_R0C26 |
| $1FC4 | a9 32 | lda#$32 |
| $1FC6 | 8d 19 04 | staSCREEN_RAM_R0C25 |
| $1FC9 | 60 | rts |
| $1FCA | c9 09 | b_1FCAcmp#$09; x-ref: $1FBC |
| $1FCC | 30 0c | bmib_1FDA |
| $1FCE | 18 | clc |
| $1FCF | 69 27 | adc#$27 |
| $1FD1 | 8d 1a 04 | staSCREEN_RAM_R0C26 |
| $1FD4 | a9 31 | lda#$31 |
| $1FD6 | 8d 19 04 | staSCREEN_RAM_R0C25 |
| $1FD9 | 60 | rts |
| $1FDA | 18 | b_1FDAclc; x-ref: $1FCC |
| $1FDB | 69 31 | adc#$31 |
| $1FDD | 8d 1a 04 | staSCREEN_RAM_R0C26 |
| $1FE0 | a9 30 | lda#$30 |
| $1FE2 | 8d 19 04 | staSCREEN_RAM_R0C25 |
| $1FE5 | 60 | rts |
| $1FE6 | | .byte$e8, $4c, $9c, $1d, $14, $20, $13, $03 |
| $1FEE | | .byte$0f, $12, $05, $13, $00, $00, $00, $00 |
| $1FF6 | | .byte$00 |
| | .encode |
| | .enc"screen" |
| $1FF7 | | txt_game_over.text"GAME OVER"; x-ref: $4612 |
| | .endencode |
| $2000 | | .binary"c64_burnin_rubber_2000.html" |
| | .encode |
| | .enc"screen" |
| $2400 | | f_2400.text"SC:0000000 HI:0000000 RO:00 CAR:00 LI:00"; x-ref: $1054 |
| $2428 | | f_2428.text" "; x-ref: $1B8B |
| $2450 | | .text" ", $67, $69, $6b, $6d, $6f, $71, $73, $75, $77, $79, $73, $75, " ", $6f, $71, $6b, $6d, $67, $69, $67, $69, $7b, $7d, $6f, $71, " " |
| $2478 | | .text" ", $68, $6a, $6c, $6e, $70, $72, $74, $76, $78, $7a, $74, $76, " ", $70, $72, $6c, $6e, $68, $6a, $68, $6a, $7c, $7e, $70, $72, " " |
| $24A0 | | .text" " |
| $24C8 | | .text" 500 PTS 300 PTS " |
| $24F0 | | .text" " |
| $2500 | | f_2500.text" "; x-ref: $105A |
| $2528 | | .text" 500 PTS" |
| $2550 | | .text" 200 PTS " |
| $2578 | | .text" " |
| $25A0 | | .text" 300 PTS" |
| $25C8 | | .text" 200 PTS " |
| $25F0 | | .text" " |
| $2600 | | f_2600.text" "; x-ref: $1060 |
| $2628 | | .text" 300 PTS 200 " |
| $2650 | | .text"PTS " |
| $2678 | | .text" " |
| $26A0 | | .text" 32 ROUNDS ARE AVAILABLE" |
| $26C8 | | .text" " |
| $26F0 | | f_26F0.text" TRY TO SEE MORE! "; x-ref: $1066 |
| $2718 | | .text" " |
| $2740 | | .text" P USE JOYSTICK OR KEYS ""J""" |
| $2768 | | .text" L # " |
| $2790 | | .text" . " |
| $27B8 | | .text" ", $7f, " COLOSOFTWARE 1983 " |
| $27E0 | | .text" " |
| instructions_screen_1 |
| $2800 | | .text"SC:0000000 HI:0000000 RO:00 CAR:00 LI:00"; x-ref: $112F |
| $2828 | | .text" " |
| $2850 | | .text" ", $67, $69, $6b, $6d, $6f, $71, $73, $75, $77, $79, $73, $75, " ", $6f, $71, $6b, $6d, $67, $69, $67, $69, $7b, $7d, $6f, $71, " " |
| $2878 | | .text" ", $68, $6a, $6c, $6e, $70, $72, $74, $76, $78, $7a, $74, $76, " ", $70, $72, $6c, $6e, $68, $6a, $68, $6a, $7c, $7e, $70, $72, " " |
| $28A0 | | .text" " |
| $28C8 | | .text" SCORING POINTS FOR " |
| $28F0 | | .text" " |
| instructions_screen_2 |
| $2900 | | .text" .1 CRASH"; x-ref: $1135 |
| $2928 | | .text"ING CARS. " |
| $2950 | | .text" .2 LANDI" |
| $2978 | | .text"NG ON CARS. " |
| $29A0 | | .text" .3 BONUS" |
| $29C8 | | .text" POINTS AT THE END OF EA" |
| $29F0 | | .text"CH ROUND. " |
| instructions_screen_3 |
| $2A00 | | .text" "; x-ref: $113B |
| $2A28 | | .text" F7 TO CHANGE ROUND: RO =" |
| $2A50 | | .text" " |
| $2A78 | | .text" BONUS LIVE EVERY 70000 POI" |
| $2AA0 | | .text"NTS " |
| $2AC8 | | .text" PLAYER CAN JUMP ONLY WIT" |
| instructions_screen_4 |
| $2AF0 | | .text"H MORE THAN 100 MPH "; x-ref: $1141 |
| $2B18 | | .text" " |
| $2B40 | | .text" PRESS FIRE BUTTON OR ""J"" TO " |
| $2B68 | | .text"JUMP DURING THE GAME " |
| $2B90 | | .text" " |
| $2BB8 | | .text" F1 1 PLAYER F3 2 PLAYER" |
| $2BE0 | | .text"S " |
| $2C00 | | unused_monitor_cmd.text".T0400,07FF,2C00 " |
| enter_high_score_screen_1 |
| $2C28 | | .text" "; x-ref: $1B62 |
| $2C50 | | .text" A B C D E F G H I J " |
| $2C78 | | .text" " |
| $2CA0 | | .text" K L M N O P Q R S T " |
| $2CC8 | | .text" " |
| $2CF0 | | .text" U V W X" |
| enter_high_score_screen_2 |
| $2D00 | | .text" Y Z . RUB END "; x-ref: $1B68 |
| $2D28 | | .text" " |
| $2D50 | | .text" " |
| $2D78 | | .text" 1- " |
| $2DA0 | | .text" " |
| $2DC8 | | .text" 2- " |
| $2DF0 | | .text" " |
| enter_high_score_screen_3 |
| $2E00 | | .text" "; x-ref: $1B6E |
| $2E28 | | .text" 3- " |
| $2E50 | | .text" " |
| enter_high_score_screen_4 |
| $2E78 | | .text" 4- "; x-ref: $1B74 |
| $2EA0 | | .text" " |
| $2EC8 | | .text" 5- " |
| $2EF0 | | .text" " |
| $2F18 | | .text" " |
| $2F40 | | .text" " |
| $2F68 | | .text" " |
| $2F90 | | .text" " |
| $2FB8 | | .text" " |
| txt_you_arent_in_the_five_best_scores |
| $2FD0 | | .text"YOU AREN""T IN THE FIVE BEST SCORESY Z "; x-ref: $1DFE |
| $2FF8 | | .text"EST SC X" |
| | .endencode |
| $3000 | | .binary"c64_burnin_rubber_3000.html" |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Detects collisions between NPC cars (enemy slots 0..2 vs 1..3). |
| ; If two active cars are within 16x16 pixels, calculates a bounce response, |
| ; setting new directions, step counts, and lifetimes based on car types. |
| ; |
| ; Inputs: tbl_enemy_car_state, Sprite X/Y regs ($D002/$D003), f092C, tbl_sprite_step_count_0 |
| ; Outputs: tbl_enemy_sprite_direction, tbl_enemy_sprite_active, tbl_enemy_sprite_step_count, tbl_enemy_sprite_lifetime |
| ; Side Effects: Calls $5230 and updates tbl_enemy_sprite_state if both cars were collision-inactive. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| detect_npc_car_collision |
| $3980 | a0 00 | ldy#$00; Outer loop: Y = car index 0..2 (must be active, state=1) ; x-ref: $3AE4 |
| $3982 | b9 28 09 | b_3982ldatbl_enemy_car_state,y; x-ref: $398C |
| $3985 | c9 01 | cmp#$01; car_state = 1 → this NPC is active (outer loop car) |
| $3987 | f0 06 | beqb_398F |
| $3989 | c8 | b_3989iny; Inner loop: X = next active car (Y+1..3), forming pairs (0,1)(0,2)(0,3)(1,2)(1,3)(2,3) ; x-ref: $3994 |
| $398A | c0 03 | cpy#$03 |
| $398C | d0 f4 | bneb_3982 |
| $398E | 60 | rts |
| $398F | 98 | b_398Ftya; x-ref: $3987 |
| $3990 | aa | tax |
| $3991 | e8 | b_3991inx; x-ref: $399B, $39CF, $39FC, $3AD1 |
| $3992 | e0 04 | cpx#$04 |
| $3994 | f0 f3 | beqb_3989 |
| $3996 | bd 28 09 | ldatbl_enemy_car_state,x |
| $3999 | c9 01 | cmp#$01; car_state = 1 → candidate for collision pair (inner loop car) |
| $399B | d0 f4 | bneb_3991 |
| $399D | 8a | txa |
| $399E | 48 | pha |
| $399F | 0a | asla; X slot → sprite register offset (slot*2); $D002+offset = sprite X pos reg |
| $39A0 | aa | tax |
| $39A1 | 98 | tya |
| $39A2 | 48 | pha |
| $39A3 | 0a | asla; Y slot → sprite register offset (slot*2) |
| $39A4 | a8 | tay |
| $39A5 | b9 02 d0 | lda$d002,y; load sprite X pos of car Y; Sprite 1 X Pos |
| $39A8 | dd 02 d0 | cmp$d002,x; compare against sprite X pos of car X; Sprite 1 X Pos |
| $39AB | 90 0e | bccb_39BB |
| $39AD | 38 | sec |
| $39AE | fd 02 d0 | sbc$d002,x; Sprite 1 X Pos |
| $39B1 | 48 | pha |
| $39B2 | a9 01 | lda#$01 |
| $39B4 | 8d d3 08 | stacollision_rel_x; collision_rel_x = 1: car Y is to the right of car X |
| $39B7 | 68 | pla |
| $39B8 | 4c c7 39 | jmpj_39C7 |
| $39BB | a9 00 | b_39BBlda#$00; x-ref: $39AB |
| $39BD | 8d d3 08 | stacollision_rel_x; collision_rel_x = 0: car Y is to the left of car X |
| $39C0 | bd 02 d0 | lda$d002,x; Sprite 1 X Pos |
| $39C3 | 38 | sec |
| $39C4 | f9 02 d0 | sbc$d002,y; Sprite 1 X Pos |
| $39C7 | c9 10 | j_39C7cmp#$10; horizontal gap ≥ 16px → cars not overlapping, skip pair ; x-ref: $39B8 |
| $39C9 | 90 07 | bccb_39D2 |
| $39CB | 68 | pla |
| $39CC | a8 | tay |
| $39CD | 68 | pla |
| $39CE | aa | tax |
| $39CF | 4c 91 39 | jmpb_3991 |
| $39D2 | b9 03 d0 | b_39D2lda$d003,y; load sprite Y pos of car Y ; x-ref: $39C9 Sprite 1 Y Pos |
| $39D5 | dd 03 d0 | cmp$d003,x; compare against sprite Y pos of car X; Sprite 1 Y Pos |
| $39D8 | 90 0e | bccb_39E8 |
| $39DA | 38 | sec |
| $39DB | fd 03 d0 | sbc$d003,x; Sprite 1 Y Pos |
| $39DE | 48 | pha |
| $39DF | a9 01 | lda#$01 |
| $39E1 | 8d d4 08 | stacollision_rel_y; collision_rel_y = 1: car Y is below car X |
| $39E4 | 68 | pla |
| $39E5 | 4c f4 39 | jmpj_39F4 |
| $39E8 | a9 00 | b_39E8lda#$00; x-ref: $39D8 |
| $39EA | 8d d4 08 | stacollision_rel_y; collision_rel_y = 0: car Y is above car X |
| $39ED | bd 03 d0 | lda$d003,x; Sprite 1 Y Pos |
| $39F0 | 38 | sec |
| $39F1 | f9 03 d0 | sbc$d003,y; Sprite 1 Y Pos |
| $39F4 | c9 10 | j_39F4cmp#$10; vertical gap ≥ 16px → cars not overlapping, skip pair ; x-ref: $39E5 |
| $39F6 | 90 07 | bccb_39FF |
| $39F8 | 68 | pla |
| $39F9 | a8 | tay |
| $39FA | 68 | pla |
| $39FB | aa | tax |
| $39FC | 4c 91 39 | jmpb_3991 |
| $39FF | 68 | b_39FFpla; x-ref: $39F6 |
| $3A00 | a8 | tay |
| $3A01 | 68 | pla |
| $3A02 | aa | tax |
| ; Direction encoding: 1=up-left 2=up-right 3=down-left 4=down-right |
| $3A03 | ad d3 08 | ldacollision_rel_x |
| $3A06 | d0 1f | bneb_3A27 |
| $3A08 | ad d4 08 | ldacollision_rel_y |
| $3A0B | d0 0d | bneb_3A1A |
| $3A0D | a9 01 | lda#$01; rel_x=0, rel_y=0: Y bounces up-left (dir 1) |
| $3A0F | 99 10 09 | statbl_enemy_sprite_direction,y |
| $3A12 | a9 04 | lda#$04; rel_x=0, rel_y=0: X bounces down-right (dir 4) |
| $3A14 | 9d 10 09 | statbl_enemy_sprite_direction,x |
| $3A17 | 4c 43 3a | jmpj_3A43 |
| $3A1A | a9 03 | b_3A1Alda#$03; rel_x=0, rel_y=1: Y bounces down-left (dir 3) ; x-ref: $3A0B |
| $3A1C | 99 10 09 | statbl_enemy_sprite_direction,y |
| $3A1F | a9 02 | lda#$02; rel_x=0, rel_y=1: X bounces up-right (dir 2) |
| $3A21 | 9d 10 09 | statbl_enemy_sprite_direction,x |
| $3A24 | 4c 43 3a | jmpj_3A43 |
| $3A27 | ad d4 08 | b_3A27ldacollision_rel_y; x-ref: $3A06 |
| $3A2A | d0 0d | bneb_3A39 |
| $3A2C | a9 02 | lda#$02; rel_x=1, rel_y=0: Y bounces up-right (dir 2) |
| $3A2E | 99 10 09 | statbl_enemy_sprite_direction,y |
| $3A31 | a9 03 | lda#$03; rel_x=1, rel_y=0: X bounces down-left (dir 3) |
| $3A33 | 9d 10 09 | statbl_enemy_sprite_direction,x |
| $3A36 | 4c 43 3a | jmpj_3A43 |
| $3A39 | a9 04 | b_3A39lda#$04; rel_x=1, rel_y=1: Y bounces down-right (dir 4) ; x-ref: $3A2A |
| $3A3B | 99 10 09 | statbl_enemy_sprite_direction,y |
| $3A3E | a9 01 | lda#$01; rel_x=1, rel_y=1: X bounces up-left (dir 1) |
| $3A40 | 9d 10 09 | statbl_enemy_sprite_direction,x |
| $3A43 | bd 24 09 | j_3A43ldatbl_enemy_sprite_active,x; Both debris sprites inactive: trigger full collision (activate + play crash SFX); JSR sets tbl_enemy_sprite_state[x]=1 and returns A=1 ; x-ref: $3A17, $3A24, $3A36 |
| $3A46 | d0 10 | bneb_3A58 |
| $3A48 | b9 24 09 | ldatbl_enemy_sprite_active,y; check if car Y debris sprite already active |
| $3A4B | d0 0b | bneb_3A58 |
| $3A4D | a9 01 | lda#$01 |
| $3A4F | 20 30 52 | jsrset_collision_state_and_play_sfx; both inactive: activate collision (A=1) + play SFX |
| $3A52 | 99 0c 09 | statbl_enemy_sprite_state,y; store JSR return value (A=1) into car Y's sprite state |
| $3A55 | 4c 60 3a | jmpj_3A60 |
| $3A58 | a9 01 | b_3A58lda#$01; At least one already active: just re-arm both (no SFX replay) ; x-ref: $3A46, $3A4B |
| $3A5A | 9d 24 09 | statbl_enemy_sprite_active,x; at least one already active: mark both active (re-collision) |
| $3A5D | 99 24 09 | statbl_enemy_sprite_active,y; mark car Y active too |
| $3A60 | 8a | j_3A60txa; x-ref: $3A55 |
| $3A61 | 48 | pha |
| $3A62 | 98 | tya |
| $3A63 | 48 | pha |
| $3A64 | bd 2c 09 | ldatbl_enemy_car_type,x; 2D index for car Y's step count: row=car_type_X, col=car_type_Y → index = type_X*8 + type_Y |
| $3A67 | aa | tax |
| $3A68 | b9 2c 09 | ldatbl_enemy_car_type,y |
| $3A6B | a8 | tay |
| $3A6C | 8a | txa |
| $3A6D | 0a | asla |
| $3A6E | 0a | asla |
| $3A6F | 0a | asla |
| $3A70 | 85 49 | stazp_p_tmp_lo |
| $3A72 | 98 | tya |
| $3A73 | 18 | clc |
| $3A74 | 65 49 | adczp_p_tmp_lo |
| $3A76 | aa | tax |
| $3A77 | bd 20 3f | ldatbl_npc_col_step_count,x; X = car_type_x*8 + car_type_y → step count for NPC y's debris sprite |
| $3A7A | 85 49 | stazp_p_tmp_lo |
| $3A7C | 68 | pla |
| $3A7D | a8 | tay |
| $3A7E | 68 | pla |
| $3A7F | aa | tax |
| $3A80 | a5 49 | ldazp_p_tmp_lo |
| $3A82 | 99 14 09 | statbl_enemy_sprite_step_count,y |
| $3A85 | 8a | txa |
| $3A86 | 48 | pha |
| $3A87 | 98 | tya |
| $3A88 | 48 | pha |
| $3A89 | bd 2c 09 | ldatbl_enemy_car_type,x |
| $3A8C | aa | tax |
| $3A8D | b9 2c 09 | ldatbl_enemy_car_type,y |
| $3A90 | a8 | tay |
| $3A91 | 0a | asla |
| $3A92 | 0a | asla |
| $3A93 | 0a | asla |
| $3A94 | 85 49 | stazp_p_tmp_lo |
| $3A96 | 8a | txa |
| $3A97 | 18 | clc |
| $3A98 | 65 49 | adczp_p_tmp_lo |
| $3A9A | a8 | tay |
| $3A9B | b9 20 3f | ldatbl_npc_col_step_count,y; Y = car_type_y*8 + car_type_x → step count for NPC x's debris sprite |
| $3A9E | 85 49 | stazp_p_tmp_lo |
| $3AA0 | 68 | pla |
| $3AA1 | a8 | tay |
| $3AA2 | 68 | pla |
| $3AA3 | aa | tax |
| $3AA4 | a5 49 | ldazp_p_tmp_lo |
| $3AA6 | 9d 14 09 | statbl_enemy_sprite_step_count,x |
| $3AA9 | bd 2c 09 | ldatbl_enemy_car_type,x |
| $3AAC | c9 02 | cmp#$02 |
| $3AAE | d0 08 | bneb_3AB8 |
| $3AB0 | a9 03 | lda#$03 |
| $3AB2 | 9d 20 09 | statbl_enemy_sprite_lifetime,x; truck (type 2): shorter lifetime ($03 frames) |
| $3AB5 | 4c bd 3a | jmpj_3ABD |
| $3AB8 | a9 08 | b_3AB8lda#$08; x-ref: $3AAE |
| $3ABA | 9d 20 09 | statbl_enemy_sprite_lifetime,x; all other types: normal lifetime ($08 frames) |
| $3ABD | b9 2c 09 | j_3ABDldatbl_enemy_car_type,y; continue scanning remaining pairs ; x-ref: $3AB5 |
| $3AC0 | c9 02 | cmp#$02 |
| $3AC2 | d0 08 | bneb_3ACC |
| $3AC4 | a9 03 | lda#$03 |
| $3AC6 | 99 20 09 | statbl_enemy_sprite_lifetime,y |
| $3AC9 | 4c d1 3a | jmpj_3AD1 |
| $3ACC | a9 08 | b_3ACClda#$08; x-ref: $3AC2 |
| $3ACE | 99 20 09 | statbl_enemy_sprite_lifetime,y |
| $3AD1 | 4c 91 39 | j_3AD1jmpb_3991; x-ref: $3AC9 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; A small wrapper routine called by the main loop. |
| ; It manages spawning new enemy cars, and then handles player jump inputs. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Can spawn entities and mutate player state. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| process_entities_and_input |
| $3AD4 | 20 00 4a | jsrspawn_enemy_cars; x-ref: $183B |
| $3AD7 | 20 00 1a | jsrcheck_jump_input |
| $3ADA | 60 | rts |
| $3ADB | | .byte$00, $00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Calls detect_npc_car_collision with X and Y registers preserved. |
| ; Used by callers that need X/Y intact after the NPC collision scan. |
| ; |
| ; Inputs: Same as detect_npc_car_collision |
| ; Outputs: Same as detect_npc_car_collision |
| ; Side Effects: X and Y restored on exit |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| detect_npc_car_collision_preserve_xy |
| $3AE0 | 8a | txa; Wrapper: preserves X/Y across detect_npc_car_collision ; x-ref: $4CD6, $4FB3 |
| $3AE1 | 48 | pha |
| $3AE2 | 98 | tya |
| $3AE3 | 48 | pha |
| $3AE4 | 20 80 39 | jsrdetect_npc_car_collision |
| $3AE7 | 68 | pla |
| $3AE8 | a8 | tay |
| $3AE9 | 68 | pla |
| $3AEA | aa | tax |
| $3AEB | 60 | rts |
| $3AEC | | .byte$48, $0a, $a8, $60 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Calls update_enemy_cars then check_jump_input. |
| ; Used as an alternate main-loop dispatch that skips spawning. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Updates enemy car positions and reads player jump input |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_enemies_and_check_jump |
| $3AF0 | 20 00 4c | jsrupdate_enemy_cars; Wrapper: preserves X/Y across update_enemy_cars + check_jump_input ; x-ref: $184A |
| $3AF3 | 20 00 1a | jsrcheck_jump_input |
| $3AF6 | 60 | rts |
| $3AF7 | | .fill9, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Detects collision between the player (sprite 0) and any NPC car (slots 0..3). |
| ; Exits early if a crash SFX is already playing on Voice 1. |
| ; |
| ; For each NPC slot with car_state == 1 (on-road/active), checks if its sprite |
| ; is within 16 pixels of the player in both X and Y. On collision: |
| ; - Records which quadrant the NPC occupies relative to the player: |
| ; collision_rel_x: 0 = NPC left of player, 1 = NPC right |
| ; collision_rel_y: 0 = NPC above player, 1 = NPC below |
| ; - Sets sprite_direction[x] so the NPC bounces away from the player |
| ; - Plays crash SFX on SID Voice 1 (noise, freq=$0112, A=1/D=8) |
| ; - Computes sprite_lifetime = (npc_speed >> type_shift) + (player_speed >> type_shift) + 4 |
| ; - Computes a098B = (npc_speed >> type_shift) + (player_speed >> type_shift) + 1 |
| ; - Jumps (no RTS) to apply_collision_speed_score |
| ; |
| ; Inputs: sfx_voice_1_en, car_state[0..3], VIC-II regs $D000-$D009, |
| ; f0900[0..3] (NPC speeds), a0804 (player speed), |
| ; f092C[0..3] (car type index), f3F60/f3F68/f3F70 (type tables) |
| ; Outputs: sprite_direction[x], sprite_active[x], sprite_lifetime[x], |
| ; collision_rel_x, collision_rel_y, a0988, a098A, a098B |
| ; Side Effects: Plays crash SFX on Voice 1; falls through to apply_collision_speed_score |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| detect_player_car_collision |
| $3B00 | ad 05 08 | ldaplayer_is_jumping; Skip if crash SFX already playing on Voice 1 ; x-ref: $1847 |
| $3B03 | d0 0e | bner_3B13 |
| $3B05 | a2 00 | ldx#$00 |
| $3B07 | bd 28 09 | b_3B07ldatbl_enemy_car_state,x; x-ref: $3B11 |
| $3B0A | c9 01 | cmp#$01; Only check cars in state 1 (on-road/active) |
| $3B0C | f0 06 | beqb_3B14 |
| $3B0E | e8 | j_3B0Einx; x-ref: $3B2A, $3B42, $3B5C, $3B71, $3E3F, $3E6E |
| $3B0F | e0 04 | cpx#$04; 4 NPC slots (0..3) |
| $3B11 | d0 f4 | bneb_3B07 |
| $3B13 | 60 | r_3B13rts; x-ref: $3B03 |
| $3B14 | 8a | b_3B14txa; x-ref: $3B0C |
| $3B15 | 48 | pha |
| $3B16 | 0a | asla |
| $3B17 | aa | tax |
| $3B18 | bd 02 d0 | lda$d002,x; X = slot * 2 (VIC-II sprite reg offset); Sprite 1 X Pos |
| $3B1B | cd 00 d0 | cmp$d000; Compare NPC X vs player X; Sprite 0 X Pos |
| $3B1E | 90 15 | bccb_3B35 |
| $3B20 | 38 | sec |
| $3B21 | ed 00 d0 | sbc$d000; Sprite 0 X Pos |
| $3B24 | c9 10 | cmp#$10; Proximity threshold: 16 pixels |
| $3B26 | 90 05 | bccb_3B2D |
| $3B28 | 68 | pla |
| $3B29 | aa | tax |
| $3B2A | 4c 0e 3b | jmpj_3B0E |
| $3B2D | a9 01 | b_3B2Dlda#$01; x-ref: $3B26 |
| $3B2F | 8d d3 08 | stacollision_rel_x; NPC is right of player (collision_rel_x=1) |
| $3B32 | 4c 4a 3b | jmpj_3B4A |
| $3B35 | ad 00 d0 | b_3B35lda$d000; x-ref: $3B1E Sprite 0 X Pos |
| $3B38 | 38 | sec |
| $3B39 | fd 02 d0 | sbc$d002,x; Sprite 1 X Pos |
| $3B3C | c9 10 | cmp#$10 |
| $3B3E | 90 05 | bccb_3B45 |
| $3B40 | 68 | pla |
| $3B41 | aa | tax |
| $3B42 | 4c 0e 3b | jmpj_3B0E |
| $3B45 | a9 00 | b_3B45lda#$00; x-ref: $3B3E |
| $3B47 | 8d d3 08 | stacollision_rel_x; NPC is left of player (collision_rel_x=0) |
| $3B4A | bd 03 d0 | j_3B4Alda$d003,x; Now check Y proximity ; x-ref: $3B32 Sprite 1 Y Pos |
| $3B4D | cd 01 d0 | cmp$d001; Sprite 0 Y Pos |
| $3B50 | 90 12 | bccb_3B64 |
| $3B52 | 38 | sec |
| $3B53 | ed 01 d0 | sbc$d001; Sprite 0 Y Pos |
| $3B56 | c9 10 | cmp#$10; Proximity threshold: 16 pixels |
| $3B58 | 90 05 | bccb_3B5F |
| $3B5A | 68 | pla |
| $3B5B | aa | tax |
| $3B5C | 4c 0e 3b | jmpj_3B0E |
| $3B5F | a9 01 | b_3B5Flda#$01; NPC below player — stores collision_rel_y=1, plays crash SFX ; x-ref: $3B58 |
| $3B61 | 4c 76 3b | jmpj_3B76 |
| $3B64 | ad 01 d0 | b_3B64lda$d001; x-ref: $3B50 Sprite 0 Y Pos |
| $3B67 | 38 | sec |
| $3B68 | fd 03 d0 | sbc$d003,x; Sprite 1 Y Pos |
| $3B6B | c9 10 | cmp#$10 |
| $3B6D | 90 05 | bccb_3B74 |
| $3B6F | 68 | pla |
| $3B70 | aa | tax |
| $3B71 | 4c 0e 3b | jmpj_3B0E |
| $3B74 | a9 00 | b_3B74lda#$00; NPC above player — stores collision_rel_y=0, plays crash SFX ; x-ref: $3B6D |
| $3B76 | 20 f4 3e | j_3B76jsrset_col_y_dir_play_sfx; x-ref: $3B61 |
| $3B79 | 68 | pla |
| $3B7A | aa | tax |
| $3B7B | ad d3 08 | ldacollision_rel_x; Branch on X side to pick bounce direction |
| $3B7E | d0 1f | bneb_3B9F |
| $3B80 | ad d4 08 | ldacollision_rel_y |
| $3B83 | d0 0d | bneb_3B92 |
| $3B85 | a9 04 | lda#$04 |
| $3B87 | 8d 88 09 | stacol_quadrant |
| $3B8A | a9 01 | lda#$01 |
| $3B8C | 9d 10 09 | statbl_enemy_sprite_direction,x; NPC left+above → bounce up-left (dir 1) |
| $3B8F | 4c bb 3b | jmpj_3BBB |
| $3B92 | a9 02 | b_3B92lda#$02; x-ref: $3B83 |
| $3B94 | 8d 88 09 | stacol_quadrant |
| $3B97 | a9 03 | lda#$03 |
| $3B99 | 9d 10 09 | statbl_enemy_sprite_direction,x; NPC left+below → bounce down-left (dir 3) |
| $3B9C | 4c bb 3b | jmpj_3BBB |
| $3B9F | ad d4 08 | b_3B9Fldacollision_rel_y; x-ref: $3B7E |
| $3BA2 | d0 0d | bneb_3BB1 |
| $3BA4 | a9 03 | lda#$03 |
| $3BA6 | 8d 88 09 | stacol_quadrant |
| $3BA9 | a9 02 | lda#$02 |
| $3BAB | 9d 10 09 | statbl_enemy_sprite_direction,x; NPC right+above → bounce up-right (dir 2) |
| $3BAE | 4c bb 3b | jmpj_3BBB |
| $3BB1 | a9 01 | b_3BB1lda#$01; x-ref: $3BA2 |
| $3BB3 | 8d 88 09 | stacol_quadrant |
| $3BB6 | a9 04 | lda#$04 |
| $3BB8 | 9d 10 09 | statbl_enemy_sprite_direction,x; NPC right+below → bounce down-right (dir 4) |
| $3BBB | a9 01 | j_3BBBlda#$01; x-ref: $3B8F, $3B9C, $3BAE |
| $3BBD | 9d 24 09 | statbl_enemy_sprite_active,x; Activate bounce slot |
| $3BC0 | 8d 8a 09 | stacol_active |
| $3BC3 | bd 2c 09 | ldatbl_enemy_car_type,x |
| $3BC6 | a8 | tay |
| $3BC7 | b9 68 3f | ldatbl_sprite_step_count_1,y |
| $3BCA | 9d 14 09 | statbl_enemy_sprite_step_count,x; Pixels moved per step (from car-type table) |
| $3BCD | b9 60 3f | ldatbl_col_recoil_step_px,y; A = recoil pixels/step for this car type |
| $3BD0 | 8d 89 09 | stacol_step_px |
| $3BD3 | b9 70 3f | ldatbl_col_lifetime_shift,y; A = shift count: divides both speeds before adding to sprite lifetime |
| $3BD6 | 48 | pha |
| $3BD7 | a8 | tay |
| $3BD8 | bd 00 09 | ldaf_0900,x; lifetime = (npc_speed >> type_shift) + (player_speed >> type_shift) + 4 |
| $3BDB | 4a | b_3BDBlsra; x-ref: $3BDD |
| $3BDC | 88 | dey |
| $3BDD | d0 fc | bneb_3BDB |
| $3BDF | 85 49 | stazp_p_tmp_lo |
| $3BE1 | 68 | pla |
| $3BE2 | a8 | tay |
| $3BE3 | ad 04 08 | ldaplayer_speed |
| $3BE6 | 4a | b_3BE6lsra; x-ref: $3BE8 |
| $3BE7 | 88 | dey |
| $3BE8 | d0 fc | bneb_3BE6 |
| $3BEA | 18 | clc |
| $3BEB | 65 49 | adczp_p_tmp_lo |
| $3BED | 18 | clc |
| $3BEE | 69 04 | adc#$04 |
| $3BF0 | 9d 20 09 | statbl_enemy_sprite_lifetime,x; Longer lifetime for faster collisions |
| $3BF3 | ac 78 3f | ldycol_frames_shift; Y = fixed shift for col_frames_left (NPC speed term) |
| $3BF6 | bd 00 09 | ldaf_0900,x; a098B = same formula + 1 (feeds into score) |
| $3BF9 | 4a | b_3BF9lsra; x-ref: $3BFB |
| $3BFA | 88 | dey |
| $3BFB | d0 fc | bneb_3BF9 |
| $3BFD | 85 49 | stazp_p_tmp_lo |
| $3BFF | ac 78 3f | ldycol_frames_shift; Y = fixed shift for col_frames_left (player speed term) |
| $3C02 | ad 04 08 | ldaplayer_speed |
| $3C05 | 4a | b_3C05lsra; x-ref: $3C07 |
| $3C06 | 88 | dey |
| $3C07 | d0 fc | bneb_3C05 |
| $3C09 | 18 | clc |
| $3C0A | 65 49 | adczp_p_tmp_lo |
| $3C0C | 18 | clc |
| $3C0D | 69 01 | adc#$01 |
| $3C0F | 8d 8b 09 | stacol_frames_left |
| $3C12 | 4c 00 3e | jmpapply_collision_speed_score; Update player speed and score based on collision |
| ; Checks if a debris sprite's current pixel position is over a passable road tile. |
| ; Converts sprite X/Y to tile col/row (origin $10/$32, cell=8px), walks Screen |
| ; RAM ($0400, 40 cols/row) and reads the tile. Tiles $20/$65 = road (pass-through). |
| ; Any other tile triggers the hit handler (b3C64): deactivates the debris sprite, |
| ; flashes it white, sets the NPC to damaged state, awards score, spawns score popup. |
| ; Inputs: X = VIC-II sprite reg offset (slot*2), Y = tile column (from caller) |
| ; Stack: slot index (pushed by update_moving_sprites) |
| ; Outputs: None — returns cleanly on road tile, or non-local exit via hit handler. |
| $3C15 | 8a | check_road_collisiontxa; x-ref: $3D2D, $3D5E, $3D7A, $3D96 |
| $3C16 | 48 | pha; save VIC-II sprite offset (slot*2) before clobbering X |
| $3C17 | 98 | tya |
| $3C18 | 48 | pha |
| $3C19 | 20 c0 3c | jsrcheck_sprite_offscreen |
| $3C1C | 38 | sec |
| $3C1D | e9 10 | sbc#$10; subtract playfield left edge ($10 = 16px) |
| $3C1F | 4a | lsra; tile col = (spriteX - $10) / 8 (3x LSR = divide by 8) |
| $3C20 | 4a | lsra |
| $3C21 | 4a | lsra |
| $3C22 | a8 | tay; Y = tile column |
| $3C23 | bd 03 d0 | lda$d003,x; subtract left playfield edge offset ($10=16px) before tile-column divide; Sprite 1 Y Pos |
| $3C26 | 38 | sec; 3x LSR = divide by 8 (8px per tile cell) |
| $3C27 | e9 32 | sbc#$32; subtract playfield top edge ($32 = 50px) |
| $3C29 | 4a | lsra |
| $3C2A | 4a | lsra; tile_row = (spriteY - $32) / 8 ($32 = top playfield edge; 3x LSR = ÷8) |
| $3C2B | 4a | lsra |
| $3C2C | aa | tax; X = tile row (used as row-advance loop counter) |
| $3C2D | a9 00 | lda#<SCREEN_RAM; subtract top playfield edge ($32=50px) |
| $3C2F | 85 49 | stazp_p_tmp_lo |
| $3C31 | a9 04 | lda#>SCREEN_RAM |
| $3C33 | 85 4a | stazp_p_tmp_hi |
| $3C35 | e0 00 | j_3C35cpx#$00; x-ref: $3C47 |
| $3C37 | f0 11 | beqb_3C4A; walk p_tmp down tile_row rows (each screen row = 40=$28 bytes) |
| $3C39 | a5 49 | ldazp_p_tmp_lo |
| $3C3B | 18 | clc |
| $3C3C | 69 28 | adc#$28; advance one screen row (40 cols = $28 bytes) |
| $3C3E | 85 49 | stazp_p_tmp_lo |
| $3C40 | a5 4a | ldazp_p_tmp_hi |
| $3C42 | 69 00 | adc#$00 |
| $3C44 | 85 4a | stazp_p_tmp_hi |
| $3C46 | ca | dex |
| $3C47 | 4c 35 3c | jmpj_3C35 |
| $3C4A | b1 49 | b_3C4Alda(zp_p_tmp_lo),y; read first tile under sprite; $20=space, $65=road marker — both passable ; x-ref: $3C37 |
| $3C4C | c9 20 | cmp#$20; non-local exit: unwind own saved X/Y + JSR return addr (2 bytes) + caller's slot push |
| $3C4E | f0 04 | beqb_3C54 |
| $3C50 | c9 65 | cmp#$65; discard saved X from check_road_collision's pha at $3C16 |
| $3C52 | d0 10 | bneb_3C64 |
| $3C54 | c8 | b_3C54iny; check right-adjacent tile: sprite straddles two 8px cells; both must be road ; x-ref: $3C4E |
| $3C55 | b1 49 | lda(zp_p_tmp_lo),y |
| $3C57 | c9 20 | cmp#$20 |
| $3C59 | f0 04 | beqb_3C5F |
| $3C5B | c9 65 | cmp#$65 |
| $3C5D | d0 05 | bneb_3C64 |
| $3C5F | 68 | b_3C5Fpla; road clear: restore regs and return to movement step loop ; x-ref: $3C59 |
| $3C60 | a8 | tay |
| $3C61 | 68 | pla |
| $3C62 | aa | tax |
| $3C63 | 60 | rts |
| $3C64 | 68 | b_3C64pla; non-road hit: unwind stack — pop check_road_collision's saved Y ; x-ref: $3C52, $3C5D, $3CCA |
| $3C65 | a8 | tay |
| $3C66 | 68 | pla; pop check_road_collision's saved X |
| $3C67 | aa | tax |
| $3C68 | 68 | pla; sprite_active=0 (plain debris): clear state only, no SFX |
| $3C69 | 68 | pla; pop JSR return address hi |
| $3C6A | 68 | pla; pop slot index pushed by update_moving_sprites |
| $3C6B | aa | tax; X = debris sprite slot index (0-3) |
| $3C6C | bd 24 09 | ldatbl_enemy_sprite_active,x |
| $3C6F | d0 08 | bneb_3C79 |
| $3C71 | a9 00 | lda#$00 |
| $3C73 | 9d 0c 09 | statbl_enemy_sprite_state,x |
| $3C76 | 4c 0c 3d | jmpnext_sprite_slot |
| $3C79 | a9 00 | b_3C79lda#$00; sprite_active≠0: deactivate debris sprite (A=0) + play thud SFX ; x-ref: $3C6F |
| $3C7B | 20 fa 3e | jsrdeactivate_debris_and_play_thud; deactivate debris sprite (A=0) + play thud SFX |
| $3C7E | a9 02 | lda#$02; set NPC car state to 2 (damaged) |
| $3C80 | 9d 28 09 | statbl_enemy_car_state,x |
| $3C83 | a9 01 | lda#$01 |
| $3C85 | 9d 28 d0 | sta$d028,x; flash debris sprite white (colour 1); Sprite 1 Color |
| $3C88 | bd 2c 09 | ldatbl_enemy_car_type,x |
| $3C8B | a8 | tay |
| $3C8C | b9 18 3f | ldatbl_points_sprite_frame,y |
| $3C8F | 20 a0 47 | jsraward_collision_score_and_damage_sprite |
| $3C92 | a9 10 | lda#$10; NPC damage display timer = $10 frames |
| $3C94 | 9d 30 09 | statbl_npc_damage_timer,x |
| $3C97 | a0 00 | ldy#$00 |
| $3C99 | b9 80 09 | b_3C99ldatbl_score_sprite_active,y; scan for a free score sprite slot (0-2) ; x-ref: $3CA1 |
| $3C9C | f0 07 | beqb_3CA5 |
| $3C9E | c8 | iny |
| $3C9F | c0 03 | cpy#$03 |
| $3CA1 | d0 f6 | bneb_3C99 |
| $3CA3 | a0 00 | ldy#$00; all 3 slots taken: wrap back to slot 0 (overwrite oldest) |
| $3CA5 | a9 e2 | b_3CA5lda#$e2; x-ref: $3C9C |
| $3CA7 | 20 cd 3c | jsrspawn_score_sprite; spawn score popup at NPC's screen position |
| $3CAA | a9 10 | lda#$10 |
| $3CAC | 99 83 09 | staf_0983,y; score popup display duration = $10 frames |
| $3CAF | 4c 0c 3d | jmpnext_sprite_slot |
| $3CB2 | | .byte$0c, $3d |
| $3CB4 | | .fill12, $00 |
| ; Guards check_road_collision: if the debris sprite's X pos is $FF (off right |
| ; edge), performs a non-local exit by discarding check_road_collision's saved |
| ; X/Y from the stack and jumping directly to the collision hit handler (b3C64), |
| ; bypassing the tile-lookup. On normal return, A = sprite X pos for tile calc. |
| check_sprite_offscreen |
| $3CC0 | bd 02 d0 | lda$d002,x; x-ref: $3C19 Sprite 1 X Pos |
| $3CC3 | c9 ff | cmp#$ff; $FF = sprite scrolled off right edge of playfield |
| $3CC5 | f0 01 | beqb_3CC8 |
| $3CC7 | 60 | rts |
| $3CC8 | 68 | b_3CC8pla; discard check_road_collision's saved X (non-local exit) ; x-ref: $3CC5 |
| $3CC9 | 68 | pla; discard check_road_collision's saved Y |
| $3CCA | 4c 64 3c | jmpb_3C64; skip remaining road check → go straight to hit handler |
| ; Spawns a floating score sprite at the NPC car's current screen position. |
| ; A = sprite frame (e.g. $E2 = points graphic), X = NPC slot (0-3), |
| ; Y = score sprite slot (0-2, pre-scanned for a free slot by caller). |
| ; Copies NPC VIC-II X/Y regs to score sprite regs (sprites 5-7). |
| $3CCD | 99 fd 07 | spawn_score_spritestasprite_ptr_5,y; store frame into score sprite pointer table ; x-ref: $3CA7 |
| $3CD0 | a9 01 | lda#$01 |
| $3CD2 | 99 80 09 | statbl_score_sprite_active,y; mark score sprite slot as active |
| $3CD5 | 98 | tya |
| $3CD6 | 48 | pha |
| $3CD7 | 0a | asla; Y*2 → VIC-II offset for score sprites 5-7 |
| $3CD8 | a8 | tay |
| $3CD9 | 8a | txa |
| $3CDA | 48 | pha |
| $3CDB | 0a | asla; X*2 → VIC-II offset for NPC sprites 1-4 |
| $3CDC | aa | tax |
| $3CDD | bd 02 d0 | lda$d002,x; read NPC sprite X pos; Sprite 1 X Pos |
| $3CE0 | 99 0a d0 | sta$d00a,y; copy to score sprite X pos (sprites 5-7); Sprite 5 X Pos |
| $3CE3 | bd 03 d0 | lda$d003,x; read NPC sprite Y pos; Sprite 1 Y Pos |
| $3CE6 | 99 0b d0 | sta$d00b,y; copy to score sprite Y pos (sprites 5-7); Sprite 5 Y Pos |
| $3CE9 | 68 | pla |
| $3CEA | aa | tax |
| $3CEB | 68 | pla |
| $3CEC | a8 | tay |
| $3CED | 60 | rts |
| $3CEE | | .byte$00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Resets the colors of the score overlay sprites (sprites 5-7) back to white. |
| ; This is used to restore the normal color after a collision flash. |
| ; |
| ; Inputs: None |
| ; Outputs: $d02c, $d02d, $d02e (Sprite 5-7 color registers) |
| ; Side Effects: Changes sprite colors on screen |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| reset_score_sprite_colors |
| $3CF0 | a9 01 | lda#$01; reset score sprite overlay colours to white (colour 1) after collision flash ; x-ref: $1795 |
| $3CF2 | 8d 2c d0 | sta$d02c; Sprite 5 Color |
| $3CF5 | 8d 2d d0 | sta$d02d; Sprite 6 Color |
| $3CF8 | 8d 2e d0 | sta$d02e; Sprite 7 Color |
| $3CFB | 60 | rts |
| $3CFC | | .byte$00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Moves up to 4 active sprites diagonally each frame (collision debris/sparks |
| ; spawned when cars collide). For each active slot, reads direction and step |
| ; count, then moves the sprite one pixel at a time in the given direction. |
| ; |
| ; Direction codes (sprite_direction): |
| ; 1 → up-left (dec X, dec Y) |
| ; 2 → up-right (inc X, dec Y) |
| ; 3 → down-left (dec X, inc Y) |
| ; 4 → down-right (inc X, inc Y) [default] |
| ; |
| ; Each pixel step calls check_road_collision; if the tile under the sprite is |
| ; not a passable road tile ($20/$65), the collision handler fires: triggers |
| ; hit animation (white sprite, new frame), then deactivates the slot. |
| ; After all steps, decrements sprite_lifetime; reaching zero deactivates |
| ; the slot (sprite_active and sprite_state both cleared). |
| ; |
| ; Inputs: sprite_active[0..3], sprite_state[0..3], |
| ; sprite_direction[0..3], sprite_step_count[0..3], |
| ; sprite_lifetime[0..3]; VIC-II sprite X/Y regs |
| ; Outputs: VIC-II sprite X/Y regs ($D002-$D009) |
| ; Side Effects: Deactivates slots on lifetime expiry or road collision; |
| ; triggers hit animation on collision (color, shape change) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_moving_sprites |
| $3D00 | a2 00 | ldx#$00; x-ref: $183E |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Main loop for updating moving NPC/debris sprites. Iterates over the 4 sprite slots, |
| ; checking if they are active before dispatching to movement handlers. |
| ; |
| ; Inputs: X register (current slot index) |
| ; Outputs: None |
| ; Side Effects: Dispatches to direction handlers if active |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D02 | bd 24 09 | moving_sprites_loopldatbl_enemy_sprite_active,x; Skip slot if both sprite_active and sprite_state are 0 (inactive) ; x-ref: $3D0F |
| $3D05 | d0 0b | bnedispatch_direction; slot is active, handle movement |
| $3D07 | bd 0c 09 | ldatbl_enemy_sprite_state,x; Also skip if sprite_state is 0 |
| $3D0A | d0 06 | bnedispatch_direction; state is non-zero, handle movement |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Advances to the next sprite slot and loops back if more slots remain (0..3). |
| ; |
| ; Inputs: X register (current slot index) |
| ; Outputs: X register (next slot index) |
| ; Side Effects: Loops back to moving_sprites_loop |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D0C | e8 | next_sprite_slotinx; x-ref: $3C76, $3CAF, $3D44, $3D4F |
| $3D0D | e0 04 | cpx#$04; 4 sprite slots (0..3) |
| $3D0F | d0 f1 | bnemoving_sprites_loop |
| $3D11 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Reads the direction code for the current sprite and dispatches to the |
| ; appropriate diagonal movement routine. |
| ; |
| ; Inputs: X register (slot index), tbl_enemy_sprite_direction |
| ; Outputs: None |
| ; Side Effects: Branches to directional handlers |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D12 | bd 10 09 | dispatch_directionldatbl_enemy_sprite_direction,x; fetch direction code (1-4) ; x-ref: $3D05, $3D0A |
| $3D15 | c9 01 | cmp#$01; Direction 1 = up-left |
| $3D17 | f0 39 | beqdir_up_left_entry; 1 = up-left |
| $3D19 | c9 02 | cmp#$02; Direction 2 = up-right |
| $3D1B | f0 51 | beqdir_up_right; 2 = up-right |
| $3D1D | c9 03 | cmp#$03 |
| $3D1F | f0 69 | beqdir_down_left; 3 = down-left, 4 = down-right (default) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Moves the sprite down-right by incrementing both X and Y coordinates. |
| ; |
| ; Inputs: X register (slot index), tbl_enemy_sprite_step_count |
| ; Outputs: VIC-II sprite X/Y registers |
| ; Side Effects: Updates sprite position, pushes slot index to stack, checks collision |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D21 | bd 14 09 | dir_down_rightldatbl_enemy_sprite_step_count,x; fetch steps to move |
| $3D24 | a8 | tay; use Y as step counter |
| $3D25 | 8a | txa; push slot index; asl = slot*2 for VIC-II reg offset |
| $3D26 | 48 | pha; slot*2 = VIC-II offset ($D002+offset = sprite X reg) |
| $3D27 | 0a | asla; X = slot_index * 2 (VIC-II sprite reg offset) |
| $3D28 | aa | tax; X = sprite offset for VIC-II registers |
| $3D29 | c0 00 | j_3D29cpy#$00; are we done moving? ; x-ref: $3D3A |
| $3D2B | f0 10 | beqmove_steps_done |
| $3D2D | 20 15 3c | jsrcheck_road_collision; check if hit non-road tile |
| $3D30 | fe 02 d0 | inc$d002,x; Move sprite right (inc X); Sprite 1 X Pos |
| $3D33 | fe 03 d0 | inc$d003,x; Move sprite down (inc Y); Sprite 1 Y Pos |
| $3D36 | ea | nop; 3x NOP: timing padding (matches step-loop timing in other direction handlers) |
| $3D37 | ea | nop |
| $3D38 | ea | nop |
| $3D39 | 88 | dey |
| $3D3A | 4c 29 3d | jmpj_3D29 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Completes the movement steps for a sprite, decrements its lifetime counter, |
| ; and checks if it should be deactivated. |
| ; |
| ; Inputs: Stack (pushed slot index), tbl_enemy_sprite_lifetime |
| ; Outputs: X register (slot index), tbl_enemy_sprite_lifetime |
| ; Side Effects: Restores slot index, decrements lifetime, may jump to deactivate |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D3D | 68 | move_steps_donepla; x-ref: $3D2B, $3D5C, $3D78, $3D94 |
| $3D3E | aa | tax |
| $3D3F | de 20 09 | dectbl_enemy_sprite_lifetime,x; reduce lifetime |
| $3D42 | f0 03 | beqlifetime_expired_deactivate; Lifetime expired: deactivate slot |
| $3D44 | 4c 0c 3d | jmpnext_sprite_slot |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Deactivates a sprite when its lifetime runs out by clearing its active and |
| ; state flags. |
| ; |
| ; Inputs: X register (slot index) |
| ; Outputs: tbl_enemy_sprite_active, tbl_enemy_sprite_state |
| ; Side Effects: Retires the sprite slot |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| lifetime_expired_deactivate |
| $3D47 | a9 00 | lda#$00; clear flags to retire sprite ; x-ref: $3D42 |
| $3D49 | 9d 24 09 | statbl_enemy_sprite_active,x |
| $3D4C | 9d 0c 09 | statbl_enemy_sprite_state,x |
| $3D4F | 4c 0c 3d | jmpnext_sprite_slot |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Entry point for up-left movement. Fetches the step count and converts the |
| ; slot index into a VIC-II register offset. |
| ; |
| ; Inputs: X register (slot index), tbl_enemy_sprite_step_count |
| ; Outputs: Y register (step count), X register (VIC-II offset) |
| ; Side Effects: Pushes slot index to stack |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D52 | bd 14 09 | dir_up_left_entryldatbl_enemy_sprite_step_count,x; all steps done — restore slot index from stack, decrement lifetime ; x-ref: $3D17 |
| $3D55 | a8 | tay |
| $3D56 | 8a | txa |
| $3D57 | 48 | pha |
| $3D58 | 0a | asla |
| $3D59 | aa | tax |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Moves the sprite up-left by decrementing both X and Y coordinates. |
| ; |
| ; Inputs: X register (VIC-II offset), Y register (step count) |
| ; Outputs: VIC-II sprite X/Y registers |
| ; Side Effects: Updates sprite position, checks collision |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D5A | c0 00 | dir_up_leftcpy#$00; dir 1: up-left — dec X, dec Y ; x-ref: $3D6B |
| $3D5C | f0 df | beqmove_steps_done |
| $3D5E | 20 15 3c | jsrcheck_road_collision |
| $3D61 | de 02 d0 | dec$d002,x; Move sprite left (dec X) — direction 1; Sprite 1 X Pos |
| $3D64 | de 03 d0 | dec$d003,x; Move sprite up (dec Y) — direction 1; Sprite 1 Y Pos |
| $3D67 | ea | nop |
| $3D68 | ea | nop |
| $3D69 | ea | nop |
| $3D6A | 88 | dey |
| $3D6B | 4c 5a 3d | jmpdir_up_left |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Moves the sprite up-right by incrementing the X coordinate and decrementing |
| ; the Y coordinate. |
| ; |
| ; Inputs: X register (slot index), tbl_enemy_sprite_step_count |
| ; Outputs: VIC-II sprite X/Y registers |
| ; Side Effects: Updates sprite position, pushes slot index, checks collision |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D6E | bd 14 09 | dir_up_rightldatbl_enemy_sprite_step_count,x; dir 2: up-right — inc X, dec Y ; x-ref: $3D1B |
| $3D71 | a8 | tay |
| $3D72 | 8a | txa |
| $3D73 | 48 | pha |
| $3D74 | 0a | asla |
| $3D75 | aa | tax |
| $3D76 | c0 00 | j_3D76cpy#$00; x-ref: $3D87 |
| $3D78 | f0 c3 | beqmove_steps_done |
| $3D7A | 20 15 3c | jsrcheck_road_collision |
| $3D7D | fe 02 d0 | inc$d002,x; Move sprite right (inc X) — direction 2; Sprite 1 X Pos |
| $3D80 | de 03 d0 | dec$d003,x; Move sprite up (dec Y) — direction 2; Sprite 1 Y Pos |
| $3D83 | ea | nop |
| $3D84 | ea | nop |
| $3D85 | ea | nop |
| $3D86 | 88 | dey |
| $3D87 | 4c 76 3d | jmpj_3D76 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Moves the sprite down-left by decrementing the X coordinate and incrementing |
| ; the Y coordinate. |
| ; |
| ; Inputs: X register (slot index), tbl_enemy_sprite_step_count |
| ; Outputs: VIC-II sprite X/Y registers |
| ; Side Effects: Updates sprite position, pushes slot index, checks collision |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3D8A | bd 14 09 | dir_down_leftldatbl_enemy_sprite_step_count,x; dir 3: down-left — dec X, inc Y ; x-ref: $3D1F |
| $3D8D | a8 | tay |
| $3D8E | 8a | txa |
| $3D8F | 48 | pha |
| $3D90 | 0a | asla |
| $3D91 | aa | tax |
| $3D92 | c0 00 | j_3D92cpy#$00; x-ref: $3DA3 |
| $3D94 | f0 a7 | beqmove_steps_done |
| $3D96 | 20 15 3c | jsrcheck_road_collision |
| $3D99 | de 02 d0 | dec$d002,x; Move sprite left (dec X) — direction 3; Sprite 1 X Pos |
| $3D9C | fe 03 d0 | inc$d003,x; Move sprite down (inc Y) — direction 3; Sprite 1 Y Pos |
| $3D9F | ea | nop |
| $3DA0 | ea | nop |
| $3DA1 | ea | nop |
| $3DA2 | 88 | dey |
| $3DA3 | 4c 92 3d | jmpj_3D92 |
| $3DA6 | | .byte$00, $00 |
| $3DA8 | | .fill8, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Per-frame player horizontal recoil. Called every frame from the main loop |
| ; while a collision is active (col_active != 0). Slides the player sprite X |
| ; by col_step_px pixels in the direction of the hit, for col_frames_left frames. |
| ; |
| ; col_quadrant 1 or 3 (NPC was LEFT of player): |
| ; dec $D000 col_step_px times; calls apply_collision_recoil (Y nudge) each step |
| ; col_quadrant 2 or 4 (NPC was RIGHT of player): |
| ; inc $D000 col_step_px times; no Y nudge (3x NOP — possible bug) |
| ; |
| ; Decrements col_frames_left each call; when it reaches zero, clears col_active |
| ; to end the effect. |
| ; |
| ; Inputs: col_active, col_quadrant, col_step_px, col_frames_left |
| ; Outputs: $D000 (Sprite 0 X Pos) |
| ; Side Effects: Calls apply_collision_recoil for left-side hits; clears |
| ; col_active when col_frames_left expires |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| apply_player_x_recoil |
| $3DB0 | ad 8a 09 | ldacol_active; Skip if no collision in progress ; x-ref: $4ECD |
| $3DB3 | d0 01 | bneb_3DB6 |
| $3DB5 | 60 | rts |
| $3DB6 | ad 88 09 | b_3DB6ldacol_quadrant; x-ref: $3DB3 |
| $3DB9 | c9 01 | cmp#$01; Dirs 1 & 3 = NPC was to LEFT → push player left |
| $3DBB | f0 21 | beqb_3DDE |
| $3DBD | c9 03 | cmp#$03 |
| $3DBF | f0 1d | beqb_3DDE |
| $3DC1 | ac 89 09 | ldycol_step_px; Pixels to move this frame |
| $3DC4 | c0 00 | j_3DC4cpy#$00; x-ref: $3DCF |
| $3DC6 | f0 0a | beqb_3DD2 |
| $3DC8 | ee 00 d0 | inc$d000; Push player right (NPC was right of player); Sprite 0 X Pos |
| $3DCB | ea | nop; NOPs where apply_collision_recoil call is missing (possible bug) |
| $3DCC | ea | nop |
| $3DCD | ea | nop |
| $3DCE | 88 | dey |
| $3DCF | 4c c4 3d | jmpj_3DC4 |
| $3DD2 | ce 8b 09 | b_3DD2deccol_frames_left; Decrement frame counter ; x-ref: $3DC6 |
| $3DD5 | f0 01 | beqb_3DD8; counter > 0: still running — return, come back next frame |
| $3DD7 | 60 | rts |
| $3DD8 | a9 00 | b_3DD8lda#$00; counter hit 0: recoil complete — deactivate ; x-ref: $3DD5 |
| $3DDA | 8d 8a 09 | stacol_active; Collision effect complete — deactivate |
| $3DDD | 60 | rts |
| $3DDE | ac 89 09 | b_3DDEldycol_step_px; x-ref: $3DBB, $3DBF |
| $3DE1 | c0 00 | j_3DE1cpy#$00; x-ref: $3DEC |
| $3DE3 | f0 0a | beqb_3DEF |
| $3DE5 | ce 00 d0 | dec$d000; Push player left (NPC was left of player); Sprite 0 X Pos |
| $3DE8 | 20 a0 3e | jsrapply_collision_recoil; Y nudge toward collision (only applied for left-side hits) |
| $3DEB | 88 | dey |
| $3DEC | 4c e1 3d | jmpj_3DE1 |
| $3DEF | ce 8b 09 | b_3DEFdeccol_frames_left; Decrement frame counter ; x-ref: $3DE3 |
| $3DF2 | f0 01 | beqb_3DF5; counter > 0: still running — return, come back next frame |
| $3DF4 | 60 | rts |
| $3DF5 | a9 00 | b_3DF5lda#$00; counter hit 0: recoil complete — deactivate ; x-ref: $3DF2 |
| $3DF7 | 8d 8a 09 | stacol_active; Collision effect complete — deactivate |
| $3DFA | 60 | rts |
| $3DFB | | .byte$00, $00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Applies speed and score adjustments upon bumping into a car. |
| ; This block is jumped to from the collision detection loop. Based on the angle |
| ; of impact ($0988) and the car type, it either slows the player down (subtracting |
| ; speed and score penalties) or speeds the player up (adding speed and score bonuses). |
| ; |
| ; Inputs: $0988 (collision angle), X (enemy index), Y (amount modifier) |
| ; Outputs: None |
| ; Side Effects: Modifies player speed ($0804) and score digits ($08E0). Returns via JMP back to collision loop. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| apply_collision_speed_score |
| $3E00 | bd 2c 09 | ldatbl_enemy_car_type,x; A = enemy car type (0=truck, 1=sedan...) ; x-ref: $3C12 |
| $3E03 | a8 | tay; car type → index into repeat-count table |
| $3E04 | b9 79 3f | ldatbl_col_score_repeat,y; A = number of penalty/bonus cycles for this car type |
| $3E07 | a8 | tay; Y = repeat count (saved/restored around score loop) |
| $3E08 | ad 88 09 | ldacol_quadrant; load collision angle quadrant |
| $3E0B | c9 01 | cmp#$01; quadrant 1 = rear/side hit → bonus |
| $3E0D | f0 33 | beqb_3E42 |
| $3E0F | c9 02 | cmp#$02; quadrant 2 = rear/side hit → bonus |
| $3E11 | f0 2f | beqb_3E42 |
| $3E13 | ad 04 08 | b_3E13ldaplayer_speed; --- PENALTY PATH: head-on collision --- ; x-ref: $3E3D |
| $3E16 | c9 14 | cmp#$14; already at minimum speed ($14)? |
| $3E18 | f0 25 | beqb_3E3F; yes → skip penalty, return to loop |
| $3E1A | 38 | sec |
| $3E1B | e9 01 | sbc#$01; speed -= 1 |
| $3E1D | 8d 04 08 | staplayer_speed; store reduced speed |
| $3E20 | 98 | tya; index 2 = ones digit of the 3 low-order score digits (score_digits[0]=hundreds, [2]=ones) |
| $3E21 | 48 | pha; preserve repeat counter on stack |
| $3E22 | a0 02 | ldy#$02; start digit loop at index 2 (ones digit) |
| $3E24 | b9 e0 08 | j_3E24ldascore_digits,y; penalty: subtract 1 from ones digit; propagate borrow upward through score_digits[0..2] ; x-ref: $3E37 |
| $3E27 | 38 | sec |
| $3E28 | e9 01 | sbc#$01; digit -= 1 |
| $3E2A | 99 e0 08 | stascore_digits,y; store updated digit |
| $3E2D | c9 ff | cmp#$ff; $FF = digit wrapped below 0 (borrow) |
| $3E2F | d0 09 | bneb_3E3A; no borrow → score loop done |
| $3E31 | a9 09 | lda#$09; digit borrowed: set to 9 |
| $3E33 | 99 e0 08 | stascore_digits,y |
| $3E36 | 88 | dey; propagate borrow to next higher digit |
| $3E37 | 4c 24 3e | jmpj_3E24 |
| $3E3A | 68 | b_3E3Apla; restore repeat counter from stack ; x-ref: $3E2F |
| $3E3B | a8 | tay |
| $3E3C | 88 | dey; one penalty cycle done |
| $3E3D | d0 d4 | bneb_3E13; repeat for remaining cycles |
| $3E3F | 4c 0e 3b | b_3E3Fjmpj_3B0E; tail call → back to collision detection loop ; x-ref: $3E18 |
| $3E42 | ad 04 08 | b_3E42ldaplayer_speed; --- BONUS PATH: rear/side hit --- ; x-ref: $3E0D, $3E11, $3E6C |
| $3E45 | c9 dc | cmp#$dc; already at maximum speed ($DC)? |
| $3E47 | f0 25 | beqb_3E6E; yes → skip bonus, return to loop |
| $3E49 | 18 | clc |
| $3E4A | 69 01 | adc#$01; speed += 1 |
| $3E4C | 8d 04 08 | staplayer_speed; store increased speed |
| $3E4F | 98 | tya; save repeat counter before clobbering Y |
| $3E50 | 48 | pha; preserve repeat counter on stack |
| $3E51 | a0 02 | ldy#$02; start digit loop at index 2 (ones digit) |
| $3E53 | b9 e0 08 | j_3E53ldascore_digits,y; bonus: add 1 to ones digit; propagate carry upward through score_digits[0..2] ; x-ref: $3E66 |
| $3E56 | 18 | clc |
| $3E57 | 69 01 | adc#$01; digit += 1 |
| $3E59 | 99 e0 08 | stascore_digits,y; store updated digit |
| $3E5C | c9 0a | cmp#$0a; $0A = digit overflowed past 9 (carry) |
| $3E5E | d0 09 | bneb_3E69; no carry → score loop done |
| $3E60 | a9 00 | lda#$00; digit carried: reset to 0 |
| $3E62 | 99 e0 08 | stascore_digits,y |
| $3E65 | 88 | dey; propagate carry to next higher digit |
| $3E66 | 4c 53 3e | jmpj_3E53 |
| $3E69 | 68 | b_3E69pla; restore repeat counter from stack ; x-ref: $3E5E |
| $3E6A | a8 | tay |
| $3E6B | 88 | dey; one bonus cycle done |
| $3E6C | d0 d4 | bneb_3E42; repeat for remaining cycles |
| $3E6E | 4c 0e 3b | b_3E6Ejmpj_3B0E; tail call → back to collision detection loop ; x-ref: $3E47 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Resets SID Voice 1 ADSR envelope to 0, effectively silencing the channel. |
| ; Often called before setting up a new sound effect. |
| ; |
| ; Inputs: None |
| ; Outputs: A = $00 |
| ; Side Effects: Modifies SID Voice 1 ADSR registers ($D405, $D406). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3E71 | a9 00 | reset_voice1_statelda#$00; Clear A for ADSR reset ; x-ref: $3E7D, $3ED1, $3F81, $51BE |
| $3E73 | 20 c0 12 | jsrsilence_voice1_or_bail_if_jumping; Clear gate bit (if not jumping) |
| $3E76 | 8d 05 d4 | sta$d405; Voice 1: Attack / Decay Cycle Control |
| $3E79 | 8d 06 d4 | sta$d406; Voice 1: Sustain / Release Cycle Control |
| $3E7C | 60 | rts |
| $3E7D | 20 71 3e | j3E7Djsrreset_voice1_state; x-ref: $3ECE |
| $3E80 | a9 0f | lda#$0f |
| $3E82 | 8d 06 d4 | sta$d406; Voice 1: Sustain / Release Cycle Control |
| $3E85 | a9 6b | lda#$6b |
| $3E87 | 8d 05 d4 | sta$d405; Voice 1: Attack / Decay Cycle Control |
| $3E8A | a9 1e | lda#$1e |
| $3E8C | 8d 01 d4 | sta$d401; Voice 1: Frequency Control - High-Byte |
| $3E8F | a9 8c | lda#$8c |
| $3E91 | 8d 00 d4 | sta$d400; Voice 1: Frequency Control - Low-Byte |
| $3E94 | a9 81 | lda#$81 |
| $3E96 | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| $3E99 | 60 | rts |
| $3E9A | | .byte$00, $00, $00, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Applies visual recoil to the player's car after a collision. |
| ; Based on the collision angle ($0988), it shifts the player sprite (Sprite 0) |
| ; either up or down on the screen to simulate a physical bump. |
| ; It clamps the player's vertical position between $90 and $D0 to keep them |
| ; within the visible gameplay area. |
| ; |
| ; Inputs: $0988 (collision angle) |
| ; Outputs: None |
| ; Side Effects: Modifies Sprite 0 Y Pos ($D001). |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| apply_collision_recoil |
| $3EA0 | ad 88 09 | ldacol_quadrant; x-ref: $3DE8 |
| $3EA3 | c9 01 | cmp#$01 |
| $3EA5 | f0 14 | beqb_3EBB |
| $3EA7 | c9 02 | cmp#$02 |
| $3EA9 | f0 10 | beqb_3EBB |
| $3EAB | ee 01 d0 | inc$d001; Sprite 0 Y Pos |
| $3EAE | ad 01 d0 | lda$d001; Sprite 0 Y Pos |
| $3EB1 | c9 d0 | cmp#$d0 |
| $3EB3 | 90 05 | bccr_3EBA |
| $3EB5 | a9 d0 | lda#$d0 |
| $3EB7 | 8d 01 d0 | sta$d001; Sprite 0 Y Pos |
| $3EBA | 60 | r_3EBArts; x-ref: $3EB3 |
| $3EBB | ce 01 d0 | b_3EBBdec$d001; x-ref: $3EA5, $3EA9 Sprite 0 Y Pos |
| $3EBE | ad 01 d0 | lda$d001; Sprite 0 Y Pos |
| $3EC1 | c9 90 | cmp#$90 |
| $3EC3 | b0 05 | bcsr_3ECA |
| $3EC5 | a9 90 | lda#$90 |
| $3EC7 | 8d 01 d0 | sta$d001; Sprite 0 Y Pos |
| $3ECA | 60 | r_3ECArts; x-ref: $3EC3 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Sets the player's sprite frame pointer and plays a sound effect on Voice 1. |
| ; Used for jump/explosion animations. |
| ; |
| ; Inputs: A = Sprite frame pointer value |
| ; Outputs: None |
| ; Side Effects: Updates sprite_ptr_0, configures SID Voice 1. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| set_sprite0_frame_and_play_sfx |
| $3ECB | 8d f8 07 | stasprite_ptr_0; Update player sprite frame ; x-ref: $4826 |
| $3ECE | 4c 7d 3e | jmpj3E7D; Play SFX tone |
| ; Plays crash SFX on SID Voice 1 (Noise, Freq=$0112, A=1/D=8) |
| $3ED1 | 20 71 3e | play_crash_sfxjsrreset_voice1_state; x-ref: $3EF7, $5233 |
| $3ED4 | a9 00 | lda#$00 |
| $3ED6 | 8d 06 d4 | sta$d406; Voice 1: Sustain / Release Cycle Control |
| $3ED9 | a9 18 | lda#$18 |
| $3EDB | 8d 05 d4 | sta$d405; Voice 1: Attack / Decay Cycle Control |
| $3EDE | a9 01 | lda#$01 |
| $3EE0 | 8d 01 d4 | sta$d401; Voice 1: Frequency Control - High-Byte |
| $3EE3 | a9 12 | lda#$12 |
| $3EE5 | 8d 00 d4 | sta$d400; Voice 1: Frequency Control - Low-Byte |
| $3EE8 | a9 81 | lda#$81 |
| $3EEA | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| $3EED | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the state of an enemy car and plays a thud sound effect. |
| ; |
| ; Inputs: X = Enemy index, A = New state value |
| ; Outputs: None |
| ; Side Effects: Modifies tbl_enemy_car_state,X and plays SFX. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| set_enemy_state_and_play_thud |
| $3EEE | 9d 28 09 | statbl_enemy_car_state,x; Update enemy state ; x-ref: $45B9 |
| $3EF1 | 4c 81 3f | jmpplay_thud_sfx; Trigger thud sound |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Records the relative Y direction of a collision and plays a crash sound effect. |
| ; |
| ; Inputs: A = Relative Y collision direction |
| ; Outputs: None |
| ; Side Effects: Updates collision_rel_y and triggers crash SFX. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| set_col_y_dir_play_sfx |
| $3EF4 | 8d d4 08 | stacollision_rel_y; Store collision Y direction ; x-ref: $3B76 |
| $3EF7 | 4c d1 3e | jmpplay_crash_sfx; Trigger crash sound |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Deactivates an enemy/debris sprite and plays a thud sound effect. |
| ; |
| ; Inputs: X = Sprite index, A = Active flag (usually 0) |
| ; Outputs: None |
| ; Side Effects: Updates tbl_enemy_sprite_active,X and triggers thud SFX. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| deactivate_debris_and_play_thud |
| $3EFA | 9d 24 09 | statbl_enemy_sprite_active,x; Set sprite active flag ; x-ref: $3C7B |
| $3EFD | 4c 81 3f | jmpplay_thud_sfx; Trigger thud sound |
| $3F00 | | tbl_sprite_color.byte$01, $01, $04, $07, $0e, $0e, $05, $0d; x-ref: $4B19 |
| $3F08 | | .byte$66, $66, $44, $7c, $9c, $64, $64, $64 |
| $3F10 | | .byte$e5, $e5, $64, $fa, $dc, $e4, $e4, $e4 |
| tbl_points_sprite_frame |
| $3F18 | | .byte$e3, $e3, $e4, $e4, $e4, $e5, $e5, $e5; x-ref: $3C8C, $45C5, $47A4, $47DD |
| ; Row = attacker type (0-7), Col = victim type (0-7); truck col (2) always gives lowest recoil (1 step) |
| tbl_npc_col_step_count |
| $3F20 | | .byte$03, $03, $01, $03, $03, $04, $04, $05; x-ref: $3A77, $3A9B |
| $3F28 | | .byte$03, $03, $01, $03, $03, $04, $04, $05 |
| $3F30 | | .byte$07, $07, $02, $07, $07, $08, $08, $09 |
| $3F38 | | .byte$03, $03, $01, $03, $03, $04, $04, $05 |
| $3F40 | | .byte$03, $03, $01, $03, $03, $04, $04, $05 |
| $3F48 | | .byte$02, $02, $01, $02, $02, $03, $03, $05 |
| $3F50 | | .byte$02, $02, $01, $02, $02, $03, $03, $05 |
| $3F58 | | .byte$01, $01, $01, $01, $01, $02, $02, $03 |
| ; Per-car-type collision recoil step size in pixels. Indexed by car type (0-7). |
| ; Truck (idx 2) = 7px (hardest hit), Bus (idx 7) = 2px (softest bounce). |
| tbl_col_recoil_step_px |
| $3F60 | | .byte$05, $05, $07, $05, $05, $04, $04, $02; x-ref: $3BCD |
| tbl_sprite_step_count_1 |
| $3F68 | | .byte$03, $03, $01, $03, $03, $04, $04, $04; x-ref: $3BC7 |
| ; Per-car-type right-shift count for collision debris sprite lifetime. |
| ; Lifetime = (npc_speed >> shift) + (player_speed >> shift) + 4. |
| ; Truck (idx 2) = 7 (speed barely contributes); Bus (idx 7) = 4. |
| tbl_col_lifetime_shift |
| $3F70 | | .byte$05, $05, $07, $05, $05, $05, $05, $04; x-ref: $3BD3 |
| ; Fixed right-shift count (6) used to compute col_frames_left from NPC and player speeds. |
| ; col_frames_left = (npc_speed >> 6) + (player_speed >> 6) + 1. |
| ; Unlike tbl_col_lifetime_shift, this is not per-car-type — same value for all collisions. |
| $3F78 | | col_frames_shift.byte$06; x-ref: $3BF3, $3BFF |
| ; Per-car-type repeat count for the speed/score adjustment loop in apply_collision_speed_score. |
| ; Each cycle adds or subtracts 1 from player_speed and one point from the score. |
| ; Truck (idx 2) = 10 (most impact); Bus (idx 7) = 2 (least impact). |
| $3F79 | | tbl_col_score_repeat.byte$06, $06, $0a, $06, $06, $04, $04, $02; x-ref: $3E04 |
| ; Plays a short thud SFX on SID Voice 1 (Noise, Freq=$0112, A=1/D=9). |
| ; Slightly softer than play_crash_sfx (A=1/D=8). Used for minor bumps |
| ; and NPC state transitions. Always preceded by reset_voice1_state. |
| $3F81 | 20 71 3e | play_thud_sfxjsrreset_voice1_state; x-ref: $3EF1, $3EFD |
| $3F84 | a9 00 | lda#$00 |
| $3F86 | 8d 06 d4 | sta$d406; Voice 1: Sustain / Release Cycle Control |
| $3F89 | a9 19 | lda#$19 |
| $3F8B | 8d 05 d4 | sta$d405; Voice 1: Attack / Decay Cycle Control |
| $3F8E | a9 01 | lda#$01 |
| $3F90 | 8d 01 d4 | sta$d401; Voice 1: Frequency Control - High-Byte |
| $3F93 | a9 12 | lda#$12 |
| $3F95 | 8d 00 d4 | sta$d400; Voice 1: Frequency Control - Low-Byte |
| $3F98 | a9 81 | lda#$81 |
| $3F9A | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| $3F9D | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Plays a click/beep UI sound effect using SID Voice 1. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Modifies SID Voice 1 control, frequency, ADSR registers |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3F9E | a9 00 | play_click_sfxlda#$00; A = 0 to gate off voice ; x-ref: $3FBE, $3FC4 |
| $3FA0 | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| $3FA3 | 8d 05 d4 | sta$d405; Voice 1: Attack / Decay Cycle Control |
| $3FA6 | 8d 06 d4 | sta$d406; Voice 1: Sustain / Release Cycle Control |
| $3FA9 | a9 09 | lda#$09; Attack: 0, Decay: 9 |
| $3FAB | 8d 05 d4 | sta$d405; Voice 1: Attack / Decay Cycle Control |
| $3FAE | a9 44 | lda#$44; Freq high byte |
| $3FB0 | 8d 01 d4 | sta$d401; Voice 1: Frequency Control - High-Byte |
| $3FB3 | a9 95 | lda#$95; Freq low byte |
| $3FB5 | 8d 00 d4 | sta$d400; Voice 1: Frequency Control - Low-Byte |
| $3FB8 | a9 21 | lda#$21; Control: Triangle wave + Gate on |
| $3FBA | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| $3FBD | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles the fire button press on the high-score screen, playing a click sound and jumping to the hotspot handler. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Plays SID Voice 1 sound, jumps to handle_screen_hotspots |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| highscore_fire_pressed |
| $3FBE | 20 9e 3f | jsrplay_click_sfx; x-ref: $1DF8 |
| $3FC1 | 4c 37 46 | jmphandle_screen_hotspots |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Plays a click sound effect and loads the player's remaining lives (ones digit). |
| ; |
| ; Inputs: None |
| ; Outputs: A = ones digit of remaining lives |
| ; Side Effects: Plays SID Voice 1 sound |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| sid_tick_sfx_and_get_ones |
| $3FC4 | 20 9e 3f | jsrplay_click_sfx; x-ref: $4973 |
| $3FC7 | ad 23 08 | ldalives_ones |
| $3FCA | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes menu variables and polls input for player selection or menu navigation. |
| ; |
| ; Inputs: key_scan (current input state) |
| ; Outputs: p_tmp_hi, p_tmp_lo, level_nr_self_modifiying |
| ; Side Effects: Jumps to player selection routines or menu handler |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3FCB | a9 30 | title_screen_menulda#$30; Initialize temp pointer ; x-ref: $115C |
| $3FCD | 85 4a | stazp_p_tmp_hi |
| $3FCF | a9 00 | lda#$00 |
| $3FD1 | 8d 01 12 | stalevel_nr_self_modifiying; Reset starting level |
| $3FD4 | a9 31 | lda#$31 |
| $3FD6 | 85 49 | stazp_p_tmp_lo |
| $3FD8 | a5 c5 | j_3FD8ldazp_key_scan; x-ref: $3FFD |
| $3FDA | c9 df | cmp#$df; Check if '2' was pressed (key_scan) |
| $3FDC | f0 0f | beqselect_2_players |
| $3FDE | c9 ef | cmp#$ef; Check if '1' was pressed (key_scan) |
| $3FE0 | d0 18 | bneb_3FFA |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Configures the game for a single player and jumps to the main game start. |
| ; |
| ; Inputs: None |
| ; Outputs: current_player_nr = 1, number_of_players = 1 |
| ; Side Effects: Transfers control to game initialization |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3FE2 | a9 01 | select_1_playerlda#$01 |
| $3FE4 | 8d 01 0f | stacurrent_player_nr |
| $3FE7 | 8d 00 0f | stanumber_of_players |
| $3FEA | 4c 8e 11 | jmpj_118E |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Configures the game for two players and jumps to the main game start. |
| ; |
| ; Inputs: None |
| ; Outputs: number_of_players = 2, current_player_nr = 1 |
| ; Side Effects: Transfers control to game initialization |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $3FED | a9 02 | select_2_playerslda#$02; x-ref: $3FDC |
| $3FEF | 8d 00 0f | stanumber_of_players |
| $3FF2 | a9 01 | lda#$01 |
| $3FF4 | 8d 01 0f | stacurrent_player_nr |
| $3FF7 | 4c 8e 11 | jmpj_118E |
| $3FFA | 20 00 53 | b_3FFAjsrhandle_menu_selection_input; x-ref: $3FE0 |
| $3FFD | 4c d8 3f | jmpj_3FD8 |
| ; tile map (?). |
| ; Each level has $20 bytes, there are 32 levels: 1024 bytes in total |
| $4000 | | level_tile_tbl.byte$01, $02, $02, $03, $03, $02, $06, $06; level 0 ; x-ref: $1309, $130D, $487B, $487F |
| $4008 | | .byte$06, $06, $06, $07, $08, $02, $02, $03 |
| $4010 | | .byte$03, $04, $05, $02, $02, $03, $03, $04 |
| $4018 | | .byte$05, $02, $02, $03, $02, $06, $07, $08 |
| $4020 | | .byte$02, $02, $03, $03, $03, $04, $05, $03; level 1 |
| $4028 | | .byte$03, $02, $02, $02, $03, $03, $04, $09 |
| $4030 | | .byte$09, $05, $03, $02, $02, $07, $08, $01 |
| $4038 | | .byte$01, $02, $02, $03, $03, $03, $04, $05 |
| $4040 | | .byte$02, $03, $03, $03, $04, $09, $05, $03; level 2 |
| $4048 | | .byte$03, $03, $02, $02, $06, $06, $06, $02 |
| $4050 | | .byte$02, $03, $03, $04, $05, $03, $02, $02 |
| $4058 | | .byte$06, $07, $08, $06, $02, $03, $04, $05 |
| $4060 | | .byte$01, $02, $02, $03, $03, $03, $02, $0a; level 3 |
| $4068 | | .byte$0c, $04, $05, $03, $02, $02, $02, $03 |
| $4070 | | .byte$02, $0a, $0c, $04, $05, $03, $03, $02 |
| $4078 | | .byte$03, $02, $02, $07, $0e, $08, $07, $08 |
| $4080 | | .byte$01, $02, $02, $03, $03, $04, $09, $09; level 4 |
| $4088 | | .byte$09, $05, $01, $01, $02, $0a, $0c, $02 |
| $4090 | | .byte$02, $0d, $0c, $04, $05, $01, $01, $02 |
| $4098 | | .byte$02, $03, $03, $07, $0e, $08, $07, $08 |
| $40A0 | | .byte$02, $02, $07, $08, $07, $08, $02, $02; level 5 |
| $40A8 | | .byte$03, $03, $03, $04, $09, $05, $03, $03 |
| $40B0 | | .byte$02, $02, $07, $08, $0c, $03, $03, $04 |
| $40B8 | | .byte$05, $03, $07, $08, $02, $03, $03, $02 |
| $40C0 | | .byte$02, $02, $02, $07, $0e, $08, $07, $08; level 6 |
| $40C8 | | .byte$02, $02, $03, $03, $04, $09, $09, $05 |
| $40D0 | | .byte$03, $0d, $0c, $0d, $0c, $02, $02, $07 |
| $40D8 | | .byte$08, $07, $08, $02, $02, $03, $04, $05 |
| $40E0 | | .byte$02, $02, $02, $07, $0e, $0e, $08, $07; level 7 |
| $40E8 | | .byte$08, $02, $02, $03, $03, $0d, $0c, $04 |
| $40F0 | | .byte$05, $0c, $02, $02, $03, $03, $03, $02 |
| $40F8 | | .byte$07, $08, $02, $06, $06, $06, $01, $01 |
| $4100 | | .byte$02, $02, $02, $07, $0e, $08, $07, $0e; level 8 |
| $4108 | | .byte$08, $07, $08, $02, $03, $03, $02, $02 |
| $4110 | | .byte$03, $03, $04, $05, $01, $07, $08, $06 |
| $4118 | | .byte$06, $06, $06, $02, $02, $02, $03, $03 |
| $4120 | | .byte$02, $02, $03, $03, $03, $02, $02, $0d; level 9 |
| $4128 | | .byte$0f, $0f, $0c, $07, $08, $02, $02, $02 |
| $4130 | | .byte$0d, $0f, $0f, $0c, $03, $04, $05, $03 |
| $4138 | | .byte$03, $03, $07, $0e, $08, $07, $0e, $08 |
| $4140 | | .byte$02, $02, $03, $03, $04, $09, $09, $09; level 10 |
| $4148 | | .byte$05, $01, $01, $07, $08, $07, $0e, $08 |
| $4150 | | .byte$07, $08, $02, $02, $03, $03, $02, $02 |
| $4158 | | .byte$06, $06, $06, $02, $03, $03, $04, $05 |
| $4160 | | .byte$02, $02, $02, $0d, $0f, $0f, $0f, $0c; level 11 |
| $4168 | | .byte$07, $0e, $08, $07, $08, $0d, $0f, $0c |
| $4170 | | .byte$0d, $0f, $0c, $02, $02, $03, $03, $04 |
| $4178 | | .byte$09, $09, $05, $03, $03, $04, $09, $05 |
| $4180 | | .byte$02, $02, $02, $10, $07, $08, $07, $08; level 12 |
| $4188 | | .byte$02, $02, $02, $10, $0d, $0f, $0c, $02 |
| $4190 | | .byte$02, $03, $03, $03, $02, $02, $06, $06 |
| $4198 | | .byte$06, $02, $03, $04, $05, $03, $04, $05 |
| $41A0 | | .byte$02, $02, $02, $03, $03, $10, $02, $10; level 13 |
| $41A8 | | .byte$07, $08, $07, $0e, $08, $03, $03, $04 |
| $41B0 | | .byte$09, $09, $05, $03, $03, $02, $02, $07 |
| $41B8 | | .byte$08, $02, $02, $07, $0e, $08, $07, $08 |
| $41C0 | | .byte$02, $02, $02, $03, $03, $02, $07, $0e; level 14 |
| $41C8 | | .byte$08, $07, $0e, $08, $07, $08, $02, $02 |
| $41D0 | | .byte$03, $03, $02, $10, $02, $10, $02, $10 |
| $41D8 | | .byte$02, $02, $02, $03, $03, $02, $02, $01 |
| $41E0 | | .byte$01, $02, $02, $03, $03, $04, $05, $03; level 15 |
| $41E8 | | .byte$04, $09, $05, $02, $02, $06, $06, $06 |
| $41F0 | | .byte$07, $08, $07, $0e, $08, $02, $0d, $0f |
| $41F8 | | .byte$0c, $10, $02, $10, $0a, $0c, $02, $02 |
| $4200 | | .byte$02, $02, $02, $02, $02, $07, $0e, $08; level 16 |
| $4208 | | .byte$07, $0e, $08, $07, $08, $02, $03, $03 |
| $4210 | | .byte$04, $09, $05, $0f, $0c, $10, $07, $08 |
| $4218 | | .byte$07, $08, $02, $10, $02, $10, $02, $10 |
| $4220 | | .byte$02, $02, $02, $0b, $02, $0b, $02, $0b; level 17 |
| $4228 | | .byte$02, $02, $0d, $0f, $0c, $02, $10, $07 |
| $4230 | | .byte$08, $07, $0e, $08, $07, $08, $07, $08 |
| $4238 | | .byte$02, $02, $03, $04, $05, $02, $02, $02 |
| $4240 | | .byte$02, $0a, $0c, $0a, $0f, $0c, $02, $02; level 18 |
| $4248 | | .byte$03, $04, $05, $03, $03, $03, $02, $0b |
| $4250 | | .byte$02, $0b, $02, $10, $06, $06, $07, $0e |
| $4258 | | .byte$08, $07, $0e, $08, $02, $07, $0e, $08 |
| $4260 | | .byte$02, $02, $03, $03, $02, $07, $0e, $08; level 19 |
| $4268 | | .byte$0d, $0f, $0f, $0c, $02, $0b, $02, $10 |
| $4270 | | .byte$02, $0b, $02, $10, $02, $02, $03, $03 |
| $4278 | | .byte$04, $09, $05, $02, $07, $08, $07, $08 |
| $4280 | | .byte$01, $01, $02, $02, $0d, $0f, $0f, $0c; level 20 |
| $4288 | | .byte$02, $10, $07, $05, $02, $02, $10, $0d |
| $4290 | | .byte$0f, $0f, $0c, $07, $0e, $08, $07, $0e |
| $4298 | | .byte$08, $02, $02, $03, $03, $03, $07, $05 |
| $42A0 | | .byte$02, $02, $02, $03, $03, $02, $02, $0d; level 21 |
| $42A8 | | .byte$0f, $0c, $07, $08, $07, $08, $07, $0e |
| $42B0 | | .byte$0e, $08, $0d, $0f, $0f, $0c, $02, $0b |
| $42B8 | | .byte$02, $10, $02, $0b, $02, $10, $07, $08 |
| $42C0 | | .byte$03, $03, $03, $04, $09, $09, $05, $02; level 22 |
| $42C8 | | .byte$02, $0b, $02, $10, $0b, $07, $08, $07 |
| $42D0 | | .byte$0e, $08, $07, $0e, $08, $03, $03, $04 |
| $42D8 | | .byte$05, $03, $02, $02, $02, $01, $01, $01 |
| $42E0 | | .byte$02, $02, $03, $03, $03, $02, $0d, $0c; level 23 |
| $42E8 | | .byte$0d, $0f, $0f, $0c, $02, $02, $07, $08 |
| $42F0 | | .byte$07, $08, $02, $03, $04, $05, $02, $03 |
| $42F8 | | .byte$03, $02, $02, $07, $0e, $08, $07, $08 |
| $4300 | | .byte$02, $02, $03, $03, $02, $02, $07, $0e; level 24 |
| $4308 | | .byte$08, $07, $0e, $08, $07, $0e, $08, $02 |
| $4310 | | .byte$0b, $02, $0b, $02, $10, $02, $10, $07 |
| $4318 | | .byte$08, $07, $08, $02, $02, $03, $03, $02 |
| $4320 | | .byte$02, $02, $03, $04, $05, $0c, $02, $02; level 25 |
| $4328 | | .byte$03, $04, $05, $0c, $02, $02, $0b, $02 |
| $4330 | | .byte$10, $02, $0b, $07, $08, $07, $0e, $0e |
| $4338 | | .byte$0e, $08, $02, $02, $03, $04, $05, $0c |
| $4340 | | .byte$02, $02, $01, $01, $02, $02, $03, $03; level 26 |
| $4348 | | .byte$04, $05, $0c, $0d, $0f, $0f, $0f, $0c |
| $4350 | | .byte$02, $02, $10, $02, $0b, $02, $10, $02 |
| $4358 | | .byte$0b, $02, $07, $0e, $0e, $08, $07, $08 |
| $4360 | | .byte$02, $02, $02, $07, $0e, $08, $07, $08; level 27 |
| $4368 | | .byte$07, $0e, $08, $07, $0e, $0e, $08, $02 |
| $4370 | | .byte$02, $02, $03, $04, $05, $0c, $0b, $02 |
| $4378 | | .byte$02, $02, $03, $03, $01, $01, $02, $02 |
| $4380 | | .byte$02, $0d, $0c, $04, $05, $02, $02, $02; level 28 |
| $4388 | | .byte$0d, $0c, $04, $05, $02, $02, $02, $07 |
| $4390 | | .byte$08, $07, $08, $02, $02, $03, $03, $02 |
| $4398 | | .byte$0d, $0c, $04, $05, $02, $02, $07, $08 |
| $43A0 | | .byte$02, $02, $02, $07, $08, $06, $07, $0e; level 29 |
| $43A8 | | .byte$08, $06, $07, $08, $03, $03, $02, $02 |
| $43B0 | | .byte$0b, $02, $10, $07, $08, $07, $0e, $08 |
| $43B8 | | .byte$02, $02, $0b, $02, $10, $02, $10, $02 |
| $43C0 | | .byte$01, $02, $03, $04, $05, $0c, $0d, $0c; level 30 |
| $43C8 | | .byte$02, $0b, $02, $10, $02, $10, $07, $08 |
| $43D0 | | .byte$07, $0e, $08, $07, $0e, $08, $02, $02 |
| $43D8 | | .byte$01, $01, $02, $02, $03, $04, $05, $02 |
| $43E0 | | .byte$01, $02, $02, $03, $03, $04, $09, $05; level 31 |
| $43E8 | | .byte$02, $0d, $0f, $0c, $0a, $0c, $02, $06 |
| $43F0 | | .byte$06, $07, $08, $07, $0e, $08, $02, $0b |
| $43F8 | | .byte$0d, $0f, $0c, $10, $02, $03, $04, $05 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Applies a buffered vertical offset to Sprite 0 (the player's car). |
| ; Takes the accumulated vertical offset stored at $0808, adds it to the current |
| ; Y position of Sprite 0 ($D001), and then clears $0808 back to 0. This is |
| ; used to process collision bumps, road bumps, or other vertical shifts pending |
| ; for the frame. |
| ; |
| ; Inputs: Y position at $D001, offset at $0808 |
| ; Outputs: None |
| ; Side Effects: Modifies Sprite 0 Y pos ($D001) and sets $0808 to 0. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4400 | ad 01 d0 | apply_y_offsetlda$d001; x-ref: $182A, $4768 Sprite 0 Y Pos |
| $4403 | 18 | clc |
| $4404 | 6d 08 08 | adcplayer_y_offset; Add offset buffered in $0808 |
| $4407 | 8d 01 d0 | sta$d001; Sprite 0 Y Pos |
| $440A | a9 00 | lda#$00; Clear the buffered offset |
| $440C | 8d 08 08 | staplayer_y_offset |
| $440F | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles player acceleration (Up direction) and deceleration (Down direction). |
| ; Reads the parsed input state at $00F5. If 'Up' (Bit 0) is pressed, the car |
| ; moves up the screen (Y position at $D001 decreases until clamped at $90), |
| ; the scrolling speed $0804 is increased, and the 3-byte visual speedometer array |
| ; at $08E0 is incremented in base-10. |
| ; If 'Down' is pressed, it branches to $4464 which performs the inverse (speed |
| ; array decrements, car moves down the screen until clamped at $D0). |
| ; |
| ; Inputs: Parsed input state at $00F5 |
| ; Outputs: None |
| ; Side Effects: Modifies Sprite 0 Y pos ($D001), speed $0804, and speedometer $08E0 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4410 | ad f5 00 | handle_accelerationlda@w zp_joy_state; x-ref: $17D4, $4770 |
| $4413 | 29 0f | and#$0f; Check Bit 0 (Up/Forward) |
| $4415 | 29 01 | and#$01 |
| $4417 | d0 47 | bneb_4460; Branch if not pressed to check Down |
| $4419 | ad 01 d0 | lda$d001; Sprite 0 Y Pos |
| $441C | c9 90 | cmp#$90 |
| $441E | f0 09 | beqb_4429 |
| $4420 | ad 01 d0 | lda$d001; Move Car UP 1 pixel; Sprite 0 Y Pos |
| $4423 | 38 | sec |
| $4424 | e9 01 | sbc#$01 |
| $4426 | 8d 01 d0 | sta$d001; Sprite 0 Y Pos |
| $4429 | ee 04 08 | b_4429incplayer_speed; Increase scroll speed ($0804) x2 ; x-ref: $441E |
| $442C | ee 04 08 | incplayer_speed |
| $442F | a0 00 | ldy#$00 |
| $4431 | a2 02 | b_4431ldx#$02; x-ref: $444C |
| $4433 | bd e0 08 | j_4433ldascore_digits,x; Base-10 Increment Speedometer array ($08E0) ; x-ref: $4446 |
| $4436 | 18 | clc |
| $4437 | 69 01 | adc#$01 |
| $4439 | 9d e0 08 | stascore_digits,x |
| $443C | c9 0a | cmp#$0a |
| $443E | d0 09 | bneb_4449 |
| $4440 | a9 00 | lda#$00 |
| $4442 | 9d e0 08 | stascore_digits,x |
| $4445 | ca | dex |
| $4446 | 4c 33 44 | jmpj_4433 |
| $4449 | c8 | b_4449iny; x-ref: $443E |
| $444A | c0 02 | cpy#$02 |
| $444C | d0 e3 | bneb_4431 |
| $444E | ad 04 08 | ldaplayer_speed |
| $4451 | c9 de | cmp#$de |
| $4453 | d0 0a | bner_445F |
| $4455 | a9 dc | lda#$dc |
| $4457 | 8d 04 08 | staplayer_speed |
| $445A | a9 00 | lda#$00 |
| $445C | 8d e2 08 | staspeed_hundreds_digit |
| $445F | 60 | r_445Frts; x-ref: $4453 |
| $4460 | 4c ed 49 | b_4460jmpj_49ED; x-ref: $4417 |
| $4463 | | .byte$ea |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles player speed deceleration. Slows down the car if not accelerating, |
| ; and applies faster deceleration if the fire button is pressed. Enforces a |
| ; minimum integer speed of 4. |
| ; Inputs: $DC00 (CIA 1 Port A) for joystick fire button state, is_jumping flag. |
| ; Outputs: Updates speed_fraction and player_speed_int. |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4464 | ad 01 d0 | handle_decelerationlda$d001; Read CIA 1 Port A (Joystick 2) ; x-ref: $49F4 Sprite 0 Y Pos |
| $4467 | c9 d0 | cmp#$d0; Check Fire button (bit 4) |
| $4469 | f0 09 | beqb_4474 |
| $446B | ad 01 d0 | lda$d001; Check if car is in mid-air; Sprite 0 Y Pos |
| $446E | 18 | clc |
| $446F | 69 01 | adc#$01 |
| $4471 | 8d 01 d0 | sta$d001; Sprite 0 Y Pos |
| $4474 | ce 04 08 | b_4474decplayer_speed; x-ref: $4469 |
| $4477 | ce 04 08 | decplayer_speed |
| $447A | a0 00 | ldy#$00 |
| $447C | a2 02 | b_447Cldx#$02; x-ref: $4497 |
| $447E | bd e0 08 | j_447Eldascore_digits,x; Enforce minimum speed of 4 ; x-ref: $4491 |
| $4481 | 38 | sec |
| $4482 | e9 01 | sbc#$01 |
| $4484 | 9d e0 08 | stascore_digits,x |
| $4487 | c9 ff | cmp#$ff |
| $4489 | d0 09 | bneb_4494 |
| $448B | a9 09 | lda#$09 |
| $448D | 9d e0 08 | stascore_digits,x |
| $4490 | ca | dex |
| $4491 | 4c 7e 44 | jmpj_447E |
| $4494 | c8 | b_4494iny; x-ref: $4489 |
| $4495 | c0 02 | cpy#$02 |
| $4497 | d0 e3 | bneb_447C |
| $4499 | ad 04 08 | ldaplayer_speed |
| $449C | c9 12 | cmp#$12 |
| $449E | d0 0f | bner_44AF |
| $44A0 | a9 14 | lda#$14 |
| $44A2 | 8d 04 08 | staplayer_speed |
| $44A5 | a9 00 | lda#$00 |
| $44A7 | 8d e2 08 | staspeed_hundreds_digit |
| $44AA | a9 02 | lda#$02 |
| $44AC | 8d e1 08 | staspeed_tens_digit |
| $44AF | 60 | r_44AFrts; x-ref: $449E |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the game's HUD/Dashboard at the bottom of the screen. |
| ; Draws the border graphics and prints the numeric values from $08E0. |
| ; |
| ; Inputs: $08E0..$08E2 (3-byte numeric value) |
| ; Outputs: Screen RAM ($0772-$07CA), Color RAM ($DB72-$DBCA) |
| ; Side Effects: Updates rows 22-24 of the screen display. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $44B0 | a2 00 | init_hudldx#$00; x-ref: $11F0 |
| $44B2 | bd e0 08 | b_44B2ldascore_digits,x; Loop through 3 digits at $08E0 ; x-ref: $44C3 |
| $44B5 | 18 | clc |
| $44B6 | 69 30 | adc#$30; Convert to PETSCII '0'-'9' |
| $44B8 | 9d 9b 07 | staSCREEN_RAM_R23C3,x; Store in Row 23, Column 3-5 |
| $44BB | a9 03 | lda#VicIIColors.CYAN |
| $44BD | 9d 9b db | staCOLOR_RAM_R23C3,x |
| $44C0 | e8 | inx |
| $44C1 | e0 03 | cpx#$03 |
| $44C3 | d0 ed | bneb_44B2 |
| $44C5 | ea | nop |
| $44C6 | a9 24 | lda#$24 |
| $44C8 | 8d 72 07 | staSCREEN_RAM_R22C2 |
| $44CB | a2 00 | ldx#$00 |
| $44CD | a9 25 | b_44CDlda#$25; Loop to draw 7 border chars ; x-ref: $44DA |
| $44CF | 9d 73 07 | staSCREEN_RAM_R22C3,x |
| $44D2 | a9 29 | lda#$29 |
| $44D4 | 9d c3 07 | staSCREEN_RAM_R24C3,x |
| $44D7 | e8 | inx |
| $44D8 | e0 07 | cpx#$07 |
| $44DA | d0 f1 | bneb_44CD |
| $44DC | a9 26 | lda#$26 |
| $44DE | 8d 7a 07 | staSCREEN_RAM_R22C10 |
| $44E1 | a9 27 | lda#$27 |
| $44E3 | 8d a2 07 | staSCREEN_RAM_R23C10 |
| $44E6 | a9 28 | lda#$28 |
| $44E8 | 8d ca 07 | staSCREEN_RAM_R24C10 |
| $44EB | a9 2a | lda#$2a |
| $44ED | 8d c2 07 | staSCREEN_RAM_R24C2 |
| $44F0 | a9 0d | lda#$0d |
| $44F2 | 8d 9f 07 | staSCREEN_RAM_R23C7 |
| $44F5 | a9 10 | lda#$10 |
| $44F7 | 8d a0 07 | staSCREEN_RAM_R23C8 |
| $44FA | a9 08 | lda#$08 |
| $44FC | 8d a1 07 | staSCREEN_RAM_R23C9 |
| $44FF | a2 00 | ldx#$00 |
| $4501 | a9 07 | lda#VicIIColors.YELLOW; yellow |
| $4503 | 9d 72 db | b_4503staCOLOR_RAM_R22C2,x; x-ref: $450F |
| $4506 | 9d 9a db | staCOLOR_RAM_R23C2,x |
| $4509 | 9d c2 db | staCOLOR_RAM_R24C2,x |
| $450C | e8 | inx |
| $450D | e0 09 | cpx#$09 |
| $450F | d0 f2 | bneb_4503 |
| $4511 | a9 2b | lda#$2b |
| $4513 | 20 1d 45 | jsrclamp_player_speed_bounds |
| $4516 | 60 | rts |
| ; dead code |
| $4517 | | .byte$20, $b0, $44, $4c, $46, $63 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Adjusts the player's integer speed to ensure it stays within valid bounds. |
| ; Ensures the minimum speed is 4. If the car is jumping, it applies specific |
| ; speed limits to prevent excessive speed while airborne. |
| ; Inputs: is_jumping flag, player_speed_int. |
| ; Outputs: player_speed_int is clamped. |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| clamp_player_speed_bounds |
| $451D | 8d 9a 07 | staSCREEN_RAM_R23C2; Check if car is jumping ; x-ref: $4513 |
| $4520 | a9 20 | lda#$20 |
| $4522 | 8d 9e 07 | staSCREEN_RAM_R23C6 |
| $4525 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the game state by decrementing the progress counter and checking for |
| ; collisions between the player car (Sprite 0) and enemy cars (Sprites 1-4). |
| ; |
| ; 1. Decrements the 3-byte BCD counter at $08E0 by 20 units. |
| ; 2. Checks for 16x16 pixel overlaps between Sprite 0 and Sprites 1-4. |
| ; 3. If collision detected, sets car_state to 2 and calls handler s3EEE. |
| ; |
| ; Inputs: $08E0 (HUD counter), car_state (car status), VIC sprite registers |
| ; Outputs: $08E0 (decremented), car_state (updated on collision) |
| ; Side Effects: Calls collision handler s3EEE on impact. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_tick_and_collisions |
| $4526 | 8a | txa; x-ref: $4C38 |
| $4527 | 48 | pha |
| $4528 | 98 | tya |
| $4529 | 48 | pha |
| $452A | a2 00 | ldx#$00 |
| $452C | ad 04 08 | ldaplayer_speed; Check against minimum speed 4 |
| $452F | 38 | sec |
| $4530 | e9 14 | sbc#$14 |
| $4532 | 8d 04 08 | staplayer_speed |
| $4535 | a0 02 | b_4535ldy#$02; x-ref: $4550 |
| $4537 | b9 e0 08 | j_4537ldascore_digits,y; Decrement BCD counter 20 times ; x-ref: $454A |
| $453A | 38 | sec |
| $453B | e9 01 | sbc#$01 |
| $453D | 99 e0 08 | stascore_digits,y |
| $4540 | c9 ff | cmp#$ff |
| $4542 | d0 09 | bneb_454D |
| $4544 | a9 09 | lda#$09 |
| $4546 | 99 e0 08 | stascore_digits,y |
| $4549 | 88 | dey |
| $454A | 4c 37 45 | jmpj_4537 |
| $454D | e8 | b_454Dinx; x-ref: $4542 |
| $454E | e0 14 | cpx#$14 |
| $4550 | d0 e3 | bneb_4535 |
| $4552 | a2 00 | ldx#$00; Check if enemy car is active |
| $4554 | bd 28 09 | b_4554ldatbl_enemy_car_state,x; x-ref: $455E |
| $4557 | c9 01 | cmp#$01 |
| $4559 | f0 0a | beqb_4565 |
| $455B | e8 | j_455Binx; x-ref: $457E, $45A4, $45ED |
| $455C | e0 04 | cpx#$04 |
| $455E | d0 f4 | bneb_4554 |
| $4560 | 68 | pla |
| $4561 | a8 | tay |
| $4562 | 68 | pla |
| $4563 | aa | tax |
| $4564 | 60 | rts |
| $4565 | 8a | b_4565txa; x-ref: $4559 |
| $4566 | 48 | pha |
| $4567 | 0a | asla |
| $4568 | aa | tax |
| $4569 | bd 02 d0 | lda$d002,x; X-coord collision check (16px); Sprite 1 X Pos |
| $456C | cd 00 d0 | cmp$d000; Sprite 0 X Pos |
| $456F | 90 10 | bccb_4581 |
| $4571 | bd 02 d0 | lda$d002,x; Sprite 1 X Pos |
| $4574 | 38 | sec |
| $4575 | ed 00 d0 | sbc$d000; Sprite 0 X Pos |
| $4578 | c9 10 | cmp#$10 |
| $457A | 90 13 | bccb_458F |
| $457C | 68 | j_457Cpla; x-ref: $458C |
| $457D | aa | tax |
| $457E | 4c 5b 45 | jmpj_455B |
| $4581 | ad 00 d0 | b_4581lda$d000; x-ref: $456F Sprite 0 X Pos |
| $4584 | 38 | sec |
| $4585 | fd 02 d0 | sbc$d002,x; Sprite 1 X Pos |
| $4588 | c9 10 | cmp#$10 |
| $458A | 90 03 | bccb_458F |
| $458C | 4c 7c 45 | jmpj_457C |
| $458F | bd 03 d0 | b_458Flda$d003,x; x-ref: $457A, $458A Sprite 1 Y Pos |
| $4592 | cd 01 d0 | cmp$d001; Sprite 0 Y Pos |
| $4595 | 90 10 | bccb_45A7 |
| $4597 | bd 03 d0 | lda$d003,x; Sprite 1 Y Pos |
| $459A | 38 | sec |
| $459B | ed 01 d0 | sbc$d001; Sprite 0 Y Pos |
| $459E | c9 10 | cmp#$10 |
| $45A0 | 90 13 | bccb_45B5 |
| $45A2 | 68 | j_45A2pla; x-ref: $45B2 |
| $45A3 | aa | tax |
| $45A4 | 4c 5b 45 | jmpj_455B |
| $45A7 | ad 01 d0 | b_45A7lda$d001; x-ref: $4595 Sprite 0 Y Pos |
| $45AA | 38 | sec |
| $45AB | fd 03 d0 | sbc$d003,x; Sprite 1 Y Pos |
| $45AE | c9 10 | cmp#$10 |
| $45B0 | 90 03 | bccb_45B5 |
| $45B2 | 4c a2 45 | jmpj_45A2 |
| $45B5 | 68 | b_45B5pla; x-ref: $45A0, $45B0 |
| $45B6 | aa | tax |
| $45B7 | a9 02 | lda#$02; Collision! Set color/state to 2 |
| $45B9 | 20 ee 3e | jsrset_enemy_state_and_play_thud |
| $45BC | a9 01 | lda#$01 |
| $45BE | 9d 28 d0 | sta$d028,x; Sprite 1 Color |
| $45C1 | bd 2c 09 | ldatbl_enemy_car_type,x |
| $45C4 | a8 | tay |
| $45C5 | b9 18 3f | ldatbl_points_sprite_frame,y |
| $45C8 | 20 a0 47 | jsraward_collision_score_and_damage_sprite |
| $45CB | a9 10 | lda#$10 |
| $45CD | 9d 30 09 | statbl_npc_damage_timer,x |
| $45D0 | a0 00 | ldy#$00 |
| $45D2 | b9 80 09 | b_45D2ldatbl_score_sprite_active,y; x-ref: $45DA |
| $45D5 | f0 07 | beqb_45DE |
| $45D7 | c8 | iny |
| $45D8 | c0 03 | cpy#$03 |
| $45DA | d0 f6 | bneb_45D2 |
| $45DC | a0 00 | ldy#$00 |
| $45DE | a9 e2 | b_45DElda#$e2; x-ref: $45D5 |
| $45E0 | 99 fd 07 | stasprite_ptr_5,y |
| $45E3 | a9 01 | lda#$01 |
| $45E5 | 99 80 09 | statbl_score_sprite_active,y |
| $45E8 | a9 10 | lda#$10 |
| $45EA | 20 3d 4e | jsrspawn_score_sprite_57 |
| $45ED | 4c 5b 45 | jmpj_455B |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Adds 8 sub-pixels to the car's X fractional position. Handles the overflow |
| ; into the integer X position and adjusts the screen X coordinate if a 256-pixel |
| ; boundary is crossed. |
| ; Inputs: car_x_fraction, car_x_int, car_screen_x |
| ; Outputs: Updates car_x_fraction, car_x_int, and car_screen_x |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $45F0 | a9 07 | add_car_x_subpixelslda#$07; Add 8 sub-pixels to X fraction ; x-ref: $13B4 |
| $45F2 | 8d 15 d0 | sta$d015; Sprite display Enable |
| $45F5 | a9 ff | lda#$ff |
| $45F7 | 8d 1c d0 | sta$d01c; Sprites Multi-Color Mode Select |
| $45FA | ae 03 08 | ldxseason_nr |
| $45FD | 60 | rts |
| $45FE | | .byte$00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Dynamic delay loop to govern the frame rate and scrolling speed. |
| ; Subtracts the current speed value ($0804) from a base constant ($F3). |
| ; The resulting value determines how many times a nested busy-wait loop executes. |
| ; The faster the car is going (higher $0804 value), the smaller the delay count, |
| ; resulting in the frame executing more quickly. |
| ; |
| ; Inputs: Speed variable at $0804 |
| ; Outputs: None |
| ; Side Effects: Busy waits (delays CPU execution) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4600 | a9 f3 | delay_frame_by_speedlda#$f3; Base delay count ; x-ref: $1835, $4773 |
| $4602 | 38 | sec |
| $4603 | ed 04 08 | sbcplayer_speed; Adjust screen tile/block coordinate |
| $4606 | aa | tax |
| $4607 | a0 30 | b_4607ldy#$30; Outer loop count (X register) ; x-ref: $460D |
| $4609 | 88 | b_4609dey; Inner busy loop (Y register) ; x-ref: $460A |
| $460A | d0 fd | bneb_4609 |
| $460C | ca | dex |
| $460D | d0 f8 | bneb_4607 |
| $460F | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Displays the "GAME OVER" message centered on row 9 and pauses execution for |
| ; approximately 2.6 seconds. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Writes to Screen RAM ($0578) and Color RAM ($D978) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| show_game_over_and_wait |
| $4610 | a2 00 | ldx#$00; x-ref: $1B5D |
| $4612 | bd f7 1f | b_4612ldatxt_game_over,x; Read 'GAME OVER' character from $1FF7 ; x-ref: $4620 |
| $4615 | 9d 78 05 | staSCREEN_RAM_R9C16,x; Write char to centered screen row 9 |
| $4618 | a9 03 | lda#VicIIColors.CYAN; color cyan |
| $461A | 9d 78 d9 | staCOLOR_RAM_R9C16,x |
| $461D | e8 | inx |
| $461E | e0 09 | cpx#$09 |
| $4620 | d0 f0 | bneb_4612 |
| $4622 | a9 08 | lda#$08; Approx 8 * 256 * 256 iterations (~2.6s) |
| $4624 | 8d c0 08 | stagame_over_delay_ctr; Init outer loop count to 8 → 8 × 256 × 256 = ~524k iterations ≈ 2.6s delay |
| $4627 | a2 00 | b_4627ldx#$00; x-ref: $4634 |
| $4629 | a0 00 | b_4629ldy#$00; x-ref: $462F |
| $462B | 88 | b_462Bdey; x-ref: $462C |
| $462C | d0 fd | bneb_462B |
| $462E | ca | dex |
| $462F | d0 f8 | bneb_4629 |
| $4631 | ce c0 08 | decgame_over_delay_ctr |
| $4634 | d0 f1 | bneb_4627 |
| $4636 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles screen interactions by calculating Color RAM pointers and checking |
| ; for specific coordinate hotspots (Row 9, Col $1B/$21) to trigger screen cleanup. |
| ; |
| ; Inputs: active_row ($0860), active_col ($0861), state_cleanup_index ($0857) |
| ; Outputs: p_color_ram ($49/$4A), reset flags at $0858/$0859 |
| ; Side Effects: Modifies Screen RAM and internal buffers (erases elements) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| handle_screen_hotspots |
| $4637 | a9 d8 | lda#>COLOR_RAM; x-ref: $3FC1 |
| $4639 | 85 4a | stazp_p_tmp_hi |
| $463B | ad 61 08 | ldaactive_col |
| $463E | 85 49 | stazp_p_tmp_lo |
| $4640 | ac 60 08 | ldyactive_row |
| $4643 | f0 11 | j_4643beqb_4656; x-ref: $4653 |
| $4645 | a5 49 | ldazp_p_tmp_lo |
| $4647 | 18 | clc |
| $4648 | 69 28 | adc#$28 |
| $464A | 85 49 | stazp_p_tmp_lo |
| $464C | a5 4a | ldazp_p_tmp_hi |
| $464E | 69 00 | adc#$00 |
| $4650 | 85 4a | stazp_p_tmp_hi |
| $4652 | 88 | dey |
| $4653 | 4c 43 46 | jmpj_4643 |
| $4656 | 4c dd 1e | b_4656jmpj_1EDD; Jumps to a location that jumps to the next instruction ; x-ref: $4643 |
| $4659 | ad 60 08 | j_4659ldaactive_row; x-ref: $1EDD |
| $465C | c9 09 | cmp#$09 |
| $465E | d0 07 | bneb_4667 |
| $4660 | ad 61 08 | ldaactive_col |
| $4663 | c9 1b | cmp#$1b |
| $4665 | f0 11 | beqhighscore_backspace_handler |
| $4667 | ad 60 08 | b_4667ldaactive_row; x-ref: $465E |
| $466A | c9 09 | cmp#$09 |
| $466C | d0 07 | bneb_4675 |
| $466E | ad 61 08 | ldaactive_col |
| $4671 | c9 21 | cmp#$21 |
| $4673 | f0 52 | beqterminate_name_entry |
| $4675 | 4c f5 1e | b_4675jmphandle_name_letter_selection; x-ref: $466C |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles the backspace action during the highscore name entry screen. Decrements |
| ; the active character index and erases the previously entered letter from the |
| ; highscore string buffer and the screen memory (including color RAM). |
| ; Inputs: name_entry_substate (current character index 1-5). |
| ; Outputs: Updates screen memory and name buffer with space character ($20). |
| ; Side Effects: Decrements name entry timer. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| highscore_backspace_handler |
| $4678 | ad 57 08 | ldaname_entry_substate; Check which letter index we are on ; x-ref: $4665 |
| $467B | c9 01 | cmp#$01 |
| $467D | d0 0c | bneb_468B |
| $467F | 20 d4 46 | jsrname_entry_backspace; Decrement index and get space char |
| $4682 | 9d 30 74 | staf_7430,x; Erase from screen RAM buffer |
| $4685 | 9d 18 06 | staSCREEN_RAM_R13C16,x; Erase from color RAM buffer |
| $4688 | 4c 9c 1d | jmpdecrement_timer |
| $468B | c9 02 | b_468Bcmp#$02; x-ref: $467D |
| $468D | d0 0c | bneb_469B |
| $468F | 20 d4 46 | jsrname_entry_backspace |
| $4692 | 9d 38 74 | staf_7438,x |
| $4695 | 9d 68 06 | staSCREEN_RAM_R15C16,x |
| $4698 | 4c 9c 1d | jmpdecrement_timer |
| $469B | c9 03 | b_469Bcmp#$03; x-ref: $468D |
| $469D | d0 0c | bneb_46AB |
| $469F | 20 d4 46 | jsrname_entry_backspace |
| $46A2 | 9d 40 74 | staf_7440,x |
| $46A5 | 9d b8 06 | staSCREEN_RAM_R17C16,x |
| $46A8 | 4c 9c 1d | jmpdecrement_timer |
| $46AB | c9 04 | b_46ABcmp#$04; x-ref: $469D |
| $46AD | d0 0c | bneb_46BB |
| $46AF | 20 d4 46 | jsrname_entry_backspace |
| $46B2 | 9d 48 74 | staf_7448,x |
| $46B5 | 9d 08 07 | staSCREEN_RAM_R19C16,x |
| $46B8 | 4c 9c 1d | jmpdecrement_timer |
| $46BB | 20 d4 46 | b_46BBjsrname_entry_backspace; x-ref: $46AD |
| $46BE | 9d 50 74 | staf_7450,x |
| $46C1 | 9d 58 07 | staSCREEN_RAM_R21C16,x |
| $46C4 | 4c 9c 1d | jmpdecrement_timer |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Terminates the highscore name entry process by forcing the countdown timer to |
| ; zero, which triggers the auto-confirm path and transitions the game state. |
| ; Inputs: None |
| ; Outputs: Clears highscore_timer_tens and highscore_timer_ones to 0. |
| ; Side Effects: Transitions game state. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $46C7 | a9 00 | terminate_name_entrylda#$00; Force tens digit to 0 ; x-ref: $1EF9, $4673 |
| $46C9 | 8d 58 08 | stahighscore_timer_tens |
| $46CC | a9 00 | lda#$00 |
| $46CE | 8d 59 08 | stahighscore_timer_ones; Force ones digit to 0 |
| $46D1 | 4c c8 1d | jmpb_1DC8; Jump to state transition logic |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Helper routine for name entry backspace. Decrements the character index (X reg) |
| ; and clamps it at 0. Returns the space character ($20) in the accumulator. |
| ; Inputs: X register (current character index). |
| ; Outputs: X register decremented, A register = $20. |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $46D4 | ca | name_entry_backspacedex; Decrement index ; x-ref: $467F, $468F, $469F, $46AF, $46BB |
| $46D5 | e0 ff | cpx#$ff; Check for underflow |
| $46D7 | d0 02 | bneb_46DB |
| $46D9 | a2 00 | ldx#$00; Clamp to 0 |
| $46DB | a9 20 | b_46DBlda#$20; Return space char ($20) ; x-ref: $46D7 |
| $46DD | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Checks if the current map tile the player has collided with is an obstacle. |
| ; If it is an empty road ($20), the routine returns normally. If it is a specific |
| ; pickup tile ($65), it processes the score update. Otherwise, it triggers a crash |
| ; by aborting the current routine path and jumping to the collision handler. |
| ; Inputs: A register (tile ID). |
| ; Outputs: None |
| ; Side Effects: May pop return address from stack and jump to crash handler. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| check_tile_is_obstacle |
| $46DE | c9 20 | cmp#$20; Check if tile is empty road ; x-ref: $1B38, $1B3F, $1B4A, $1B51 |
| $46E0 | d0 01 | bneb_46E3 |
| $46E2 | 60 | r_46E2rts; x-ref: $46EF |
| $46E3 | c9 65 | b_46E3cmp#$65; Check if tile is pickup/coin ; x-ref: $46E0 |
| $46E5 | f0 41 | beqb_4728 |
| $46E7 | 68 | pla; Pop return address (abort caller) |
| $46E8 | 68 | pla |
| $46E9 | 4c 55 1b | jmpj_1B55; Jump to collision/crash handler |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Synchronizes the position of the player overlay sprite (Sprite 7) with the main |
| ; player sprite (Sprite 0). Used when a pickup is collected to show points. |
| ; Initializes the sprite color and sets the display duration timer. |
| ; Inputs: pickup_mode_active flag, VIC-II Sprite 0 coordinates. |
| ; Outputs: Updates VIC-II Sprite 7 coordinates, color, and sprite pointer. |
| ; Side Effects: Activates pickup display state flags. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| sync_player_overlay_sprite |
| $46EC | ad 5e 08 | ldapickup_mode_active; Check if already active ; x-ref: $4748 |
| $46EF | d0 f1 | bner_46E2 |
| $46F1 | a9 dd | lda#$dd; Set sprite pointer for Sprite 7 |
| $46F3 | 8d ff 07 | stasprite_ptr_7 |
| $46F6 | ad 00 d0 | lda$d000; Copy X pos from Sprite 0; Sprite 0 X Pos |
| $46F9 | 8d 0e d0 | sta$d00e; Sprite 7 X Pos |
| $46FC | ad 01 d0 | lda$d001; Copy Y pos from Sprite 0; Sprite 0 Y Pos |
| $46FF | 8d 0f d0 | sta$d00f; Sprite 7 Y Pos |
| $4702 | a9 01 | lda#$01; Set color to White |
| $4704 | 8d 2e d0 | sta$d02e; Sprite 7 Color |
| $4707 | a9 01 | lda#$01 |
| $4709 | 8d 5e 08 | stapickup_mode_active |
| $470C | a9 20 | lda#$20 |
| $470E | 8d 5f 08 | stapickup_display_timer; Set display timer duration |
| $4711 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the temporary display timer for a pickup/coin sprite. |
| ; When the player hits a specific map tile (e.g., $65), Sprite 7 is spawned as |
| ; a visual indicator of the points gained, and state flag $085E is set. |
| ; This routine runs each frame to tick down its lifespan timer at $085F. |
| ; Once the timer hits 0, it deactivates the flag and hides Sprite 7 off-screen. |
| ; |
| ; Inputs: Pickup Active Flag at $085E, Timer at $085F |
| ; Outputs: None |
| ; Side Effects: Modifies $085E, $085F, and Sprite 7 X Pos ($D00E) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4712 | ad 5e 08 | update_pickup_timerldapickup_mode_active; Check if pickup sprite is active ; x-ref: $1838, $4776 |
| $4715 | d0 01 | bneb_4718 |
| $4717 | 60 | r_4717rts; x-ref: $471B |
| $4718 | ce 5f 08 | b_4718decpickup_display_timer; Decrement duration timer ; x-ref: $4715 |
| $471B | d0 fa | bner_4717 |
| $471D | a9 00 | lda#$00; Turn off active flag |
| $471F | 8d 5e 08 | stapickup_mode_active |
| $4722 | a9 00 | lda#$00; Hide Sprite 7 off-screen |
| $4724 | 8d 0e d0 | sta$d00e; Sprite 7 X Pos |
| $4727 | 60 | rts |
| $4728 | ad 5e 08 | b_4728ldapickup_mode_active; x-ref: $46E5 |
| $472B | d0 1b | bneb_4748 |
| $472D | a2 03 | ldx#$03 |
| $472F | bd 25 08 | j_472Fldascore_7digits,x; x-ref: $4742 |
| $4732 | 18 | clc |
| $4733 | 69 01 | adc#$01 |
| $4735 | 9d 25 08 | stascore_7digits,x |
| $4738 | c9 0a | cmp#$0a |
| $473A | d0 09 | bneb_4745 |
| $473C | a9 00 | lda#$00 |
| $473E | 9d 25 08 | stascore_7digits,x |
| $4741 | ca | dex |
| $4742 | 4c 2f 47 | jmpj_472F |
| $4745 | 20 b0 16 | b_4745jsrupdate_hud_display; x-ref: $473A |
| $4748 | 4c ec 46 | b_4748jmpsync_player_overlay_sprite; x-ref: $472B |
| ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
| is_speed_above_100_else_return |
| $474B | ad 04 08 | ldaplayer_speed; x-ref: $1A0D |
| $474E | c9 64 | cmp#100 |
| $4750 | 30 01 | bmib_4753 |
| $4752 | 60 | rts |
| $4753 | 68 | b_4753pla; x-ref: $4750 |
| $4754 | 68 | pla |
| $4755 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Main gameplay tick routine. |
| ; This is the core subroutine called every frame/tick during gameplay to process |
| ; all major game systems. It updates the HUD, increments the score, handles player |
| ; input and movement, processes jumps and background collisions, applies vertical |
| ; offsets, handles acceleration (if enabled), manages frame delays, and ticks down |
| ; the pickup/coin visual indicator. |
| ; |
| ; Inputs: None (relies on global state) |
| ; Outputs: None |
| ; Side Effects: Updates player coordinates, animations, score, HUD, and timers. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| tick_gameplay_systems |
| $4756 | 20 b0 16 | jsrupdate_hud_display; x-ref: $13AA |
| $4759 | 20 c9 15 | jsrincrement_score |
| $475C | 20 a0 17 | jsrhandle_player_movement |
| $475F | 20 00 1a | jsrcheck_jump_input |
| $4762 | 20 3a 1a | jsrupdate_jump_animation |
| $4765 | 20 00 1b | jsrcheck_background_collision |
| $4768 | 20 00 44 | jsrapply_y_offset |
| $476B | ad 05 08 | ldaplayer_is_jumping |
| $476E | d0 03 | bneb_4773 |
| $4770 | 20 10 44 | jsrhandle_acceleration |
| $4773 | 20 00 46 | b_4773jsrdelay_frame_by_speed; x-ref: $476E |
| $4776 | 20 12 47 | jsrupdate_pickup_timer |
| $4779 | 20 00 4c | jsrupdate_enemy_cars |
| $477C | 20 55 4e | jsrupdate_explosion_animations |
| $477F | 60 | rts |
| $4780 | | .byte$00, $00, $60 |
| $4783 | | .fill29, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; award_collision_score_and_damage_sprite |
| ; |
| ; Called when the player's car lands on (or collides with) an NPC car. |
| ; On entry, X = NPC slot index (0-3), Y = car type index from f092C,x. |
| ; |
| ; Phase 1 — Score award: |
| ; Looks up the NPC's sprite frame byte from f3F18,y: |
| ; $E3 (small car) => add 5 points to score array f0825 |
| ; $E4 (medium car) => add 3 points |
| ; $E5 (large car) => add 2 points |
| ; Score is stored as individual BCD-style digits at f0825 (7 bytes, |
| ; index 4=ones ... index 0=highest). The loop ripple-carries from |
| ; digit 4 upward for as many iterations as the point value (Y). |
| ; Then calls update_hud_display to redraw the score on the HUD. |
| ; |
| ; Phase 2 — Sprite damage: |
| ; After restoring X/Y, re-reads f3F18,y (same frame byte) and |
| ; falls through to j4E03, which: |
| ; - Stores the frame byte into a07F9,x (sprite pointer for NPC slot) |
| ; - Builds a single-bit mask for slot X, inverts it, ANDs it into |
| ; $D01C (Sprites Multi-Color Select), switching that NPC sprite |
| ; from multicolor to hires mode (visual 'hit' state) |
| ; - Increments a0821 (hit sub-counter); when it reaches 10, |
| ; resets to 0 and increments hud_level_digit |
| ; |
| ; Inputs: X = NPC car slot index (0-3) |
| ; Y = car type index (f092C,x), used to index f3F18 |
| ; Outputs: None (returns via j4E03/RTS at $4E3C) |
| ; Side Effects: f0825 score digits updated; $D01C multicolor bit cleared |
| ; for the hit NPC sprite; a0821 and hud_level_digit may |
| ; increment; HUD redrawn via update_hud_display |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| award_collision_score_and_damage_sprite |
| $47A0 | 8a | txa; Save X (NPC slot) and Y (car type index) — restored at $47D9 ; x-ref: $3C8F, $45C8 |
| $47A1 | 48 | pha |
| $47A2 | 98 | tya |
| $47A3 | 48 | pha |
| $47A4 | b9 18 3f | ldatbl_points_sprite_frame,y |
| $47A7 | c9 e3 | cmp#$e3; $E3 = 500 pts |
| $47A9 | d0 05 | bneb_47B0 |
| $47AB | a0 05 | ldy#$05; 05 == 500 pts |
| $47AD | 4c bb 47 | jmpj_47BB |
| $47B0 | c9 e4 | b_47B0cmp#$e4; $E4 = 300 pts ; x-ref: $47A9 |
| $47B2 | d0 05 | bneb_47B9 |
| $47B4 | a0 03 | ldy#$03; 03 = 300 pts |
| $47B6 | 4c bb 47 | jmpj_47BB |
| $47B9 | a0 02 | b_47B9ldy#$02; Assume frame pointer is $E5, which is 200 pts ; x-ref: $47B2 |
| $47BB | a2 04 | j_47BBldx#$04; Start ripple-carry loop at digit index 4 (hundreds) ; x-ref: $47AD, $47B6, $47D4 |
| $47BD | bd 25 08 | j_47BDldascore_7digits,x; Load current score digit ; x-ref: $47D0 |
| $47C0 | 18 | clc |
| $47C1 | 69 01 | adc#$01; Increment digit by 1 |
| $47C3 | 9d 25 08 | stascore_7digits,x |
| $47C6 | c9 0a | cmp#$0a; Overflow at 10? (BCD-style carry) |
| $47C8 | d0 09 | bneb_47D3 |
| $47CA | a9 00 | lda#$00; Reset digit to 0, carry to next column |
| $47CC | 9d 25 08 | stascore_7digits,x |
| $47CF | ca | dex; Move left to next score digit |
| $47D0 | 4c bd 47 | jmpj_47BD |
| $47D3 | 88 | b_47D3dey; Repeat for each point unit (Y times total) ; x-ref: $47C8 |
| $47D4 | d0 e5 | bnej_47BB |
| $47D6 | 20 b0 16 | jsrupdate_hud_display; Redraw HUD score display after all digits updated |
| $47D9 | 68 | pla; Restore Y (car type index) and X (NPC slot) |
| $47DA | a8 | tay |
| $47DB | 68 | pla |
| $47DC | aa | tax |
| $47DD | b9 18 3f | ldatbl_points_sprite_frame,y; Re-read sprite frame byte for this car type |
| $47E0 | 4c 03 4e | jmpj_4E03; Fall into j4E03: store frame, clear D01C multicolor bit for this sprite slot |
| ; dead code |
| $47E3 | | .byte$a2, $00, $bd, $f8, $07, $29, $01, $f0 |
| $47EB | | .byte$0e, $bd, $f8, $07, $29, $fe, $9d, $f8 |
| $47F3 | | .byte$07, $e8, $e0, $05, $d0, $ec, $60, $4c |
| $47FB | | .byte$95, $49, $00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles the player's death sequence: decrements lives, plays an explosion |
| ; animation based on the hazard, and jumps to either "Game Over" or scans |
| ; backward through level map data (starting at $4000) for a valid respawn |
| ; checkpoint. |
| ; |
| ; Inputs: lives_ones, lives_tens, (p_tmp_lo),Y (hazard type), level_nr, a0801 |
| ; Outputs: lives_ones, lives_tens, a0801 (respawn offset), p_tmp_lo/hi |
| ; Side Effects: Modifies sprite_ptr_0 ($07F8), disables sprites ($D015 = 0) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4800 | ce 23 08 | player_death_handlerdeclives_ones; x-ref: $1B55 |
| $4803 | ad 23 08 | ldalives_ones |
| $4806 | c9 ff | cmp#$ff |
| $4808 | d0 14 | bneb_481E |
| $480A | a9 09 | lda#$09 |
| $480C | 8d 23 08 | stalives_ones |
| $480F | ce 22 08 | declives_tens |
| $4812 | ad 22 08 | ldalives_tens |
| $4815 | c9 ff | cmp#$ff |
| $4817 | d0 05 | bneb_481E |
| $4819 | a9 00 | lda#$00 |
| $481B | 8d 22 08 | stalives_tens |
| $481E | b1 49 | b_481Elda(zp_p_tmp_lo),y; x-ref: $4808, $4817 |
| $4820 | c9 61 | cmp#$61 |
| $4822 | d0 20 | bneb_4844 |
| $4824 | a9 de | lda#$de; explosion sprite #0 |
| $4826 | 20 cb 3e | jsrset_sprite0_frame_and_play_sfx |
| $4829 | 20 e0 48 | jsrbusy_wait_delay |
| $482C | a9 df | lda#$df; explosion sprite #1 |
| $482E | 8d f8 07 | stasprite_ptr_0 |
| $4831 | 20 e0 48 | jsrbusy_wait_delay |
| $4834 | a9 de | lda#$de; explosion sprite #0 |
| $4836 | 8d f8 07 | stasprite_ptr_0 |
| $4839 | 20 e0 48 | jsrbusy_wait_delay |
| $483C | a9 00 | lda#$00 |
| $483E | 8d 15 d0 | sta$d015; disable all sprites; Sprite display Enable |
| $4841 | 4c 61 48 | jmpj_4861 |
| $4844 | a9 e0 | b_4844lda#$e0; explosion sprite #2 ; x-ref: $4822 |
| $4846 | 20 db 51 | jsrset_sprite0_and_play_noise |
| $4849 | 20 e0 48 | jsrbusy_wait_delay |
| $484C | a9 e1 | lda#$e1; explosion sprite #3 |
| $484E | 8d f8 07 | stasprite_ptr_0 |
| $4851 | 20 e0 48 | jsrbusy_wait_delay |
| $4854 | a9 e0 | lda#$e0; explosion sprite #2 |
| $4856 | 8d f8 07 | stasprite_ptr_0 |
| $4859 | 20 e0 48 | jsrbusy_wait_delay |
| $485C | a9 00 | lda#$00 |
| $485E | 8d 15 d0 | sta$d015; disable all sprites; Sprite display Enable |
| $4861 | ad 23 08 | j_4861ldalives_ones; x-ref: $4841 |
| $4864 | c9 00 | cmp#$00 |
| $4866 | f0 03 | beqb_486B |
| $4868 | 4c 73 48 | jmpj_4873 |
| $486B | ad 22 08 | b_486Bldalives_tens; x-ref: $4866 |
| $486E | d0 03 | bnej_4873 |
| $4870 | 4c 5d 1b | jmpj_1B5D |
| $4873 | a9 18 | j_4873lda#24; x-ref: $4868, $486E |
| $4875 | 8d 02 08 | stalevel_tile_y_offset |
| $4878 | ac 00 08 | ldylevel_nr |
| $487B | a9 00 | lda#<level_tile_tbl |
| $487D | 85 49 | stazp_p_tmp_lo |
| $487F | a9 40 | lda#>level_tile_tbl |
| $4881 | 85 4a | stazp_p_tmp_hi |
| $4883 | c0 00 | j_4883cpy#$00; x-ref: $4895 |
| $4885 | f0 11 | beqb_4898 |
| $4887 | a5 49 | ldazp_p_tmp_lo |
| $4889 | 18 | clc |
| $488A | 69 20 | adc#$20 |
| $488C | 85 49 | stazp_p_tmp_lo |
| $488E | a5 4a | ldazp_p_tmp_hi |
| $4890 | 69 00 | adc#$00 |
| $4892 | 85 4a | stazp_p_tmp_hi |
| $4894 | 88 | dey |
| $4895 | 4c 83 48 | jmpj_4883 |
| $4898 | ac 01 08 | b_4898ldylevel_block_idx; x-ref: $4885 |
| $489B | b1 49 | j_489Blda(zp_p_tmp_lo),y; x-ref: $48BC |
| $489D | c9 02 | cmp#$02 |
| $489F | f0 14 | beqb_48B5 |
| $48A1 | c9 03 | cmp#$03 |
| $48A3 | f0 10 | beqb_48B5 |
| $48A5 | c9 01 | cmp#$01 |
| $48A7 | f0 0c | beqb_48B5 |
| $48A9 | 4c bb 48 | jmpj_48BB |
| $48AC | | .byte$f2, $c9, $0e, $f0, $ee, $c9, $0f, $f0 |
| $48B4 | | .byte$ea |
| $48B5 | 8c 01 08 | b_48B5stylevel_block_idx; x-ref: $489F, $48A3, $48A7 |
| $48B8 | 4c 7b 50 | jmpj_507B |
| $48BB | 88 | j_48BBdey; x-ref: $48A9 |
| $48BC | 4c 9b 48 | jmpj_489B |
| ; dead code |
| $48BF | | .byte$ad, $86, $09, $cd, $27, $08, $30, $0a |
| $48C7 | | .byte$ad, $86, $09, $38, $ed, $27, $08, $4c |
| $48CF | | .byte$db, $48, $ad, $27, $08, $38, $ed, $86 |
| $48D7 | | .byte$09, $18, $69, $0a, $aa, $e0, $00, $00 |
| $48DF | | .byte$fe |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Busy-wait delay of approximately 0.67 seconds, used to pace the crash/explosion |
| ; animation in the game-over sequence. |
| ; |
| ; The routine burns CPU cycles with a three-level nested countdown loop: |
| ; outer : $08FF counts down from 2 to 0 (2 passes) |
| ; middle : X counts down from 0 to 0 (wraps) (256 iterations per pass) |
| ; inner : Y counts down from 0 to 0 (wraps) (256 iterations per X step) |
| ; |
| ; Total inner iterations = 2 x 256 x 256 = 131,072. |
| ; At ~5 cycles per DEY/BNE pair on PAL C64 (985 kHz) this is roughly 0.67 s. |
| ; |
| ; Called three times in succession during the crash sprite swap sequence at j4800 |
| ; ($4829, $4831, $4839 / $4849, $4851, $4859), producing a ~2-second animated |
| ; pause while the explosion sprite frames cycle and the SID crash sound plays. |
| ; |
| ; Note: $48F4-$48F9 are dead bytes (a BNE/DEX/BNE sequence that is unreachable |
| ; because the DEC $08FF / BNE loop exits only when $08FF reaches 0, at which |
| ; point the BNE at $48F2 falls through directly to RTS at $48F4). |
| ; |
| ; Inputs: none |
| ; Outputs: A = 0, X = 0, Y = 1 (loop residue); $08FF = 0 |
| ; Side Effects: ~0.67 s of CPU time consumed; $08FF zeroed |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $48E0 | a9 02 | busy_wait_delaylda#$02; outer loop counter = 2 passes ; x-ref: $4829, $4831, $4839, $4849, $4851, $4859 |
| $48E2 | 8d ff 08 | stabusy_wait_delay_ctr; store outer count in $08FF |
| $48E5 | a2 00 | b_48E5ldx#$00; middle loop: X = 256 iterations per outer pass ; x-ref: $48F2 |
| $48E7 | a0 00 | b_48E7ldy#$00; inner loop: Y = 256 iterations per X step ; x-ref: $48ED |
| $48E9 | 88 | b_48E9dey; inner burn: ~5 cycles per iteration ; x-ref: $48EA |
| $48EA | d0 fd | bneb_48E9 |
| $48EC | ca | dex; middle step: 256 inner loops done, decrement X |
| $48ED | d0 f8 | bneb_48E7 |
| $48EF | ce ff 08 | decbusy_wait_delay_ctr; decrement outer counter ($08FF); loop back if not zero |
| $48F2 | d0 f1 | bneb_48E5 |
| $48F4 | 60 | rts; return after ~0.67 s delay (2 x 256 x 256 inner iterations) |
| $48F5 | | .byte$d0, $fd, $ca, $d0, $f8, $60, $00, $00; DEAD: unreachable - BNE/DEX/BNE below $48F4 never executed |
| $48FD | | .byte$00, $00, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Advances a 4-stage pipeline of road colour-row data used by the scrolling engine. |
| ; |
| ; The game maintains four pipeline slots, each 40 bytes apart in RAM: |
| ; Slot 0 (newest): ptr $0748/$0749, colour strip $0753..$076F (29 bytes) |
| ; Slot 1: ptr $0770/$0771, colour strip $077B..$0797 |
| ; Slot 2: ptr $0798/$0799, colour strip $07A3..$07BF |
| ; Slot 3 (oldest): ptr $07C0/$07C1, colour strip $07CB..$07E7 |
| ; |
| ; Each call shifts all slots one step toward the screen bottom (slot 3 drops off): |
| ; strip[2] -> strip[3] (29 bytes, Y = 0..28) |
| ; strip[1] -> strip[2] |
| ; strip[0] -> strip[1] |
| ; ptr[2] -> ptr[3] (16-bit colour-RAM row address) |
| ; ptr[1] -> ptr[2] |
| ; ptr[0] -> ptr[1] |
| ; $0748/$0749 -> ptr[0] (freshest pointer, injected each frame by the map scroller) |
| ; |
| ; Slot 0 ($0753 strip + $0748 ptr) is written by the caller with the new road row |
| ; data before this routine runs, making it the "front" of the FIFO queue. |
| ; |
| ; Returns A = $07 so that scroll_screen_down ($1500) can immediately form the |
| ; screen pointer $0747 (a4A=$07, a49=$47 = last byte of the visible play area), |
| ; avoiding a redundant LDA #$07. |
| ; |
| ; Called once per frame by scroll_screen_down ($1500) as the first step of the |
| ; full downward screen scroll (road flows top-to-bottom in this top-down racer). |
| ; |
| ; Inputs: $0753..$076F colour strip, slot 0 (29 bytes, newest row) |
| ; $077B..$0797 colour strip, slot 1 |
| ; $07A3..$07BF colour strip, slot 2 |
| ; $0748/$0749 colour-RAM row pointer, slot 0 |
| ; $0770/$0771 colour-RAM row pointer, slot 1 |
| ; $0798/$0799 colour-RAM row pointer, slot 2 |
| ; Outputs: A = $07 (high byte for screen-RAM scroll pointer $0747) |
| ; $077B..$07E7 slots 1-3 colour strips overwritten with shifted data |
| ; $0770/$0771, $0798/$0799, $07C0/$07C1 colour-RAM ptrs shifted |
| ; Side Effects: Slot 3 previous content destroyed; slot 0 inputs are not touched. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| shift_colour_row_pipeline |
| $4900 | a0 00 | ldy#$00; Y = 0, loop index for 29-byte colour strip copy ; x-ref: $1500 |
| $4902 | b9 a3 07 | b_4902ldaSCREEN_RAM_R23C11,y; read slot 2 strip byte [y] ($07A3+y) ; x-ref: $4917 |
| $4905 | 99 cb 07 | staSCREEN_RAM_R24C11,y; write to slot 3 strip byte [y] ($07CB+y) -- slot2 -> slot3 |
| $4908 | b9 7b 07 | ldaSCREEN_RAM_R22C11,y; read slot 1 strip byte [y] ($077B+y) |
| $490B | 99 a3 07 | staSCREEN_RAM_R23C11,y; write to slot 2 strip byte [y] ($07A3+y) -- slot1 -> slot2 |
| $490E | b9 53 07 | ldaSCREEN_RAM_R21C11,y; read slot 0 strip byte [y] ($0753+y) -- newest row |
| $4911 | 99 7b 07 | staSCREEN_RAM_R22C11,y; write to slot 1 strip byte [y] ($077B+y) -- slot0 -> slot1 |
| $4914 | c8 | iny |
| $4915 | c0 1d | cpy#$1d; 29 bytes per strip (not 40; word ptrs live in the gap above $076F) |
| $4917 | d0 e9 | bneb_4902 |
| $4919 | ad 98 07 | ldaSCREEN_RAM_R23C0; slot 1 colour-RAM row ptr lo ($0798) ... |
| $491C | 8d c0 07 | staSCREEN_RAM_R24C0; ... -> slot 2 ptr lo ($07C0) -- slot1 ptr -> slot2 ptr |
| $491F | ad 99 07 | ldaSCREEN_RAM_R23C1; slot 1 colour-RAM row ptr hi ($0799) |
| $4922 | 8d c1 07 | staSCREEN_RAM_R24C1; -> slot 2 ptr hi ($07C1) |
| $4925 | ad 70 07 | ldaSCREEN_RAM_R22C0; slot 0 colour-RAM row ptr lo ($0770) |
| $4928 | 8d 98 07 | staSCREEN_RAM_R23C0; -> slot 1 ptr lo ($0798) -- slot0 ptr -> slot1 ptr |
| $492B | ad 71 07 | ldaSCREEN_RAM_R22C1; slot 0 colour-RAM row ptr hi ($0771) |
| $492E | 8d 99 07 | staSCREEN_RAM_R23C1; -> slot 1 ptr hi ($0799) |
| $4931 | ad 48 07 | ldaSCREEN_RAM_R21C0; incoming slot ptr lo ($0748) -- freshest ptr, set by caller/loader |
| $4934 | 8d 70 07 | staSCREEN_RAM_R22C0; -> slot 0 ptr lo ($0770) |
| $4937 | ad 49 07 | ldaSCREEN_RAM_R21C1; incoming slot ptr hi ($0749) |
| $493A | 8d 71 07 | staSCREEN_RAM_R22C1; -> slot 0 ptr hi ($0771) |
| $493D | a9 07 | lda#>SCREEN_RAM_R20C39; return A=$07: scroll_screen_down uses this as high byte of ptr $0747 |
| $493F | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Advances the two-digit on-screen distance counter shown in the HUD, driven by |
| ; how many new road rows have scrolled since the last call. |
| ; |
| ; scroll_row_counter ($0827) is a 0-9 modular counter incremented once per road |
| ; row by the map scroller. Each call computes delta = (current - snapshot) mod 10 |
| ; to get the number of new rows that have passed. For each delta tick the |
| ; sub-step counter dist_substep ($0987) is incremented; once it reaches 7 the |
| ; ones digit dist_digit_ones ($0823) advances by 1, carrying into the tens digit |
| ; dist_digit_tens ($0822) on overflow. Every digit advance also fires a short SID |
| ; voice-1 "tick" click via sid_tick_sfx_and_get_ones. |
| ; |
| ; The routine does NOT end with RTS. It tail-calls update_hiscore_if_beaten |
| ; ($17DD), which compares the 7-digit score ($0825-$082B) against the stored |
| ; hi-score ($0F50-$0F56) and copies the score over if it is higher. That routine |
| ; returns with A = hud_level_digit ($0820), which propagates back to the caller |
| ; update_hud_display ($16B0) and is written to screen RAM at $0420 as the level |
| ; digit after adding $30. |
| ; |
| ; Inputs: scroll_row_counter ($0827) current 0-9 row counter |
| ; scroll_row_snapshot ($0986) row counter value at previous call |
| ; dist_substep ($0987) sub-step accumulator (0-6) |
| ; dist_digit_ones ($0823) ones digit of distance counter (0-9) |
| ; dist_digit_tens ($0822) tens digit of distance counter (0-9) |
| ; Outputs: A = hud_level_digit ($0820) (returned via tail-call to $17DD) |
| ; dist_digit_ones and dist_digit_tens updated in place |
| ; Side Effects: scroll_row_snapshot ($0986) updated to current scroll_row_counter |
| ; dist_substep ($0987) updated |
| ; SID voice 1 programmed with tick SFX on each digit advance |
| ; Hi-score at $0F50-$0F56 overwritten if current score is higher |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| advance_distance_counter |
| $4940 | ad 27 08 | ldascroll_row_counter; load current scroll-row counter (0-9, wraps each 10 rows) ; x-ref: $16B0 |
| $4943 | cd 86 09 | cmpscroll_row_snapshot; compare with snapshot from previous call |
| $4946 | 30 0a | bmib_4952; current < snapshot means counter wrapped through 0; take wrap path |
| ; no-wrap path: delta = current - snapshot (0..9) |
| $4948 | ad 27 08 | ldascroll_row_counter |
| $494B | 38 | sec |
| $494C | ed 86 09 | sbcscroll_row_snapshot; delta = current - snapshot |
| $494F | 4c 5c 49 | jmpj_495C |
| ; wrap path: counter passed through 0; delta = (current - snapshot) + 10 |
| $4952 | ad 27 08 | b_4952ldascroll_row_counter; x-ref: $4946 |
| $4955 | 38 | sec |
| $4956 | ed 86 09 | sbcscroll_row_snapshot; partial subtraction (will be negative without correction) |
| $4959 | 18 | clc |
| $495A | 69 0a | adc#$0a; +10 corrects for modular wrap: delta = (current - snapshot) + 10 |
| $495C | aa | j_495Ctax; X = number of scroll-row ticks to consume this frame ; x-ref: $494F |
| $495D | e0 00 | j_495Dcpx#$00; loop: all ticks consumed? ; x-ref: $4989 |
| $495F | f0 2b | beqb_498C; yes -> save snapshot and exit |
| $4961 | ad 87 09 | ldadist_substep; load sub-step counter (0-6); digit advances once every 7 ticks |
| $4964 | 18 | clc |
| $4965 | 69 01 | adc#$01 |
| $4967 | 8d 87 09 | stadist_substep |
| $496A | c9 07 | cmp#$07; completed a full 7-step cycle? |
| $496C | d0 1a | bneb_4988; no -> skip digit advance this tick |
| $496E | a9 00 | lda#$00 |
| $4970 | 8d 87 09 | stadist_substep; reset sub-step to 0 for next cycle |
| $4973 | 20 c4 3f | jsrsid_tick_sfx_and_get_ones; fire SID voice-1 tick SFX; returns current dist_digit_ones in A |
| $4976 | 18 | clc |
| $4977 | 69 01 | adc#$01; increment ones digit |
| $4979 | 8d 23 08 | stalives_ones |
| $497C | c9 0a | cmp#$0a; ones digit reached 10? (overflow) |
| $497E | d0 08 | bneb_4988; no overflow -> continue loop |
| $4980 | a9 00 | lda#$00 |
| $4982 | 8d 23 08 | stalives_ones; wrap ones digit back to 0 |
| $4985 | ee 22 08 | inclives_tens; carry into tens digit |
| $4988 | ca | b_4988dex; consume one tick; loop back ; x-ref: $496C, $497E |
| $4989 | 4c 5d 49 | jmpj_495D |
| $498C | ad 27 08 | b_498Cldascroll_row_counter; reload current row counter (snapshot must be fresh, not stale in A) ; x-ref: $495F |
| $498F | 8d 86 09 | stascroll_row_snapshot; save as new snapshot for next call |
| $4992 | 4c 99 17 | jmpj_1799; tail-call: update hi-score if beaten; returns A = hud_level_digit ($0820) |
| ; dead code |
| $4995 | | .byte$bd, $f8, $07, $09, $01, $9d, $f8, $07 |
| $499D | | .byte$4c, $f4, $47 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates 2-frame animations for player and active enemy car sprites. |
| ; Toggles bit 0 of sprite pointers ($07F8-$07FC) to cycle frames. |
| ; |
| ; Inputs: sfx_voice_1_en ($0805) - Player animation enable flag |
| ; car_state ($0928) - Array of 4 enemy car states (1 = Active) |
| ; Outputs: None |
| ; Side Effects: Modifies sprite pointers in screen memory. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_sprite_animations |
| $49A0 | ad 05 08 | ldaplayer_is_jumping; x-ref: $1844 |
| $49A3 | f0 05 | beqb_49AA |
| $49A5 | a2 01 | ldx#$01 |
| $49A7 | 4c c4 49 | jmpj_49C4 |
| $49AA | ad f8 07 | b_49AAldasprite_ptr_0; x-ref: $49A3 |
| $49AD | 29 01 | and#$01 |
| $49AF | d0 0b | bneb_49BC; If bit 0 set, clear it. Else set it. |
| $49B1 | ad f8 07 | ldasprite_ptr_0 |
| $49B4 | 09 01 | ora#$01 |
| $49B6 | 8d f8 07 | stasprite_ptr_0 |
| $49B9 | 4c c4 49 | jmpj_49C4 |
| $49BC | ad f8 07 | b_49BCldasprite_ptr_0; x-ref: $49AF |
| $49BF | 29 fe | and#$fe |
| $49C1 | 8d f8 07 | stasprite_ptr_0 |
| $49C4 | a2 00 | j_49C4ldx#$00; x-ref: $49A7, $49B9 |
| $49C6 | bd 28 09 | b_49C6ldatbl_enemy_car_state,x; x-ref: $49EA |
| $49C9 | c9 01 | cmp#$01 |
| $49CB | d0 1a | bneb_49E7 |
| $49CD | bd f9 07 | ldasprite_ptr_1,x |
| $49D0 | 29 01 | and#$01 |
| $49D2 | d0 0b | bneb_49DF |
| $49D4 | bd f9 07 | ldasprite_ptr_1,x; Toggle frame for active enemy car |
| $49D7 | 09 01 | ora#$01 |
| $49D9 | 9d f9 07 | stasprite_ptr_1,x |
| $49DC | 4c e7 49 | jmpb_49E7 |
| $49DF | bd f9 07 | b_49DFldasprite_ptr_1,x; x-ref: $49D2 |
| $49E2 | 29 fe | and#$fe |
| $49E4 | 9d f9 07 | stasprite_ptr_1,x |
| $49E7 | e8 | b_49E7inx; x-ref: $49CB, $49DC |
| $49E8 | e0 04 | cpx#$04 |
| $49EA | d0 da | bneb_49C6 |
| $49EC | 60 | rts |
| ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
| $49ED | ad f5 00 | j_49EDlda@w zp_joy_state; x-ref: $4460 |
| $49F0 | 29 02 | and#$02 |
| $49F2 | d0 03 | bner_49F7 |
| $49F4 | 4c 64 44 | jmphandle_deceleration |
| $49F7 | 60 | r_49F7rts; x-ref: $49F2 |
| $49F8 | | .fill8, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Iterates through the 4 available enemy car slots ($0928). |
| ; If it finds an empty slot, it uses the KERNAL ROM's random number generator |
| ; rutines ($E097) multiple times to determine the enemy car's sprite shape (0-7), |
| ; initial starting X coordinate (bounded so it stays on the road), and speed. |
| ; |
| ; Inputs: Enemy active array at $0928 |
| ; Outputs: None |
| ; Side Effects: Spawns new enemies, modifies Sprite Pointers $07F9-$07FC, |
| ; and relies on KERNAL ROM state. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4A00 | a2 00 | spawn_enemy_carsldx#$00; x-ref: $3AD4 |
| $4A02 | bd 28 09 | b_4A02ldatbl_enemy_car_state,x; x-ref: $4A0A |
| $4A05 | f0 06 | beqb_4A0D; Check if slot is empty (0) |
| $4A07 | e8 | j_4A07inx; x-ref: $4ABC, $4B1F |
| $4A08 | e0 04 | cpx#$04 |
| $4A0A | d0 f6 | bneb_4A02 |
| $4A0C | 60 | rts |
| $4A0D | 8a | b_4A0Dtxa; x-ref: $4A05 |
| $4A0E | 48 | pha |
| $4A0F | 20 97 e0 | jsre_E097; Generate Random Number (uses BASIC ROM) |
| $4A12 | 68 | pla |
| $4A13 | aa | tax |
| $4A14 | a5 8c | ldazp_rnd_car_type_byte; AND #$07 → random car type 0-7; FAC byte from first ROM_RND call |
| $4A16 | 29 07 | and#$07; Random 0-7 (enemy car type) |
| $4A18 | 9d 2c 09 | statbl_enemy_car_type,x |
| $4A1B | 0a | asla |
| $4A1C | 18 | clc |
| $4A1D | 69 c2 | adc#$c2 |
| $4A1F | 9d f9 07 | stasprite_ptr_1,x |
| $4A22 | 8a | txa |
| $4A23 | 48 | pha |
| $4A24 | 20 97 e0 | jsre_E097; Generate Random Number for Position |
| $4A27 | 68 | pla |
| $4A28 | aa | tax |
| $4A29 | bd 2c 09 | ldatbl_enemy_car_type,x |
| $4A2C | c9 00 | cmp#$00 |
| $4A2E | f0 1d | beqb_4A4D |
| $4A30 | c9 01 | cmp#$01 |
| $4A32 | f0 19 | beqb_4A4D |
| $4A34 | c9 02 | cmp#$02 |
| $4A36 | f0 22 | beqb_4A5A |
| $4A38 | c9 03 | cmp#$03 |
| $4A3A | f0 2b | beqb_4A67 |
| $4A3C | c9 04 | cmp#$04 |
| $4A3E | f0 34 | beqb_4A74 |
| $4A40 | c9 05 | cmp#$05 |
| $4A42 | f0 3d | beqb_4A81 |
| $4A44 | c9 06 | cmp#$06 |
| $4A46 | f0 39 | beqb_4A81 |
| $4A48 | c9 07 | cmp#$07 |
| $4A4A | f0 35 | beqb_4A81 |
| $4A4C | 00 | brk |
| $4A4D | a5 8f | b_4A4Dldazp_rnd_pos_byte; Mask random byte to [0,$7F] range, add $67 offset → NPC X start position for car types 0/1 ; x-ref: $4A2E, $4A32 |
| $4A4F | 29 7f | and#$7f |
| $4A51 | 18 | clc |
| $4A52 | 69 67 | adc#$67 |
| $4A54 | 20 ec 4e | jsrspawn_npc_car |
| $4A57 | 4c 8b 4a | jmpj_4A8B |
| $4A5A | a5 8f | b_4A5Aldazp_rnd_pos_byte; x-ref: $4A36 |
| $4A5C | 29 3f | and#$3f |
| $4A5E | 18 | clc |
| $4A5F | 69 45 | adc#$45 |
| $4A61 | 20 ec 4e | jsrspawn_npc_car |
| $4A64 | 4c 8b 4a | jmpj_4A8B |
| $4A67 | a5 8f | b_4A67ldazp_rnd_pos_byte; x-ref: $4A3A |
| $4A69 | 29 7f | and#$7f |
| $4A6B | 18 | clc |
| $4A6C | 69 7b | adc#$7b |
| $4A6E | 20 ec 4e | jsrspawn_npc_car |
| $4A71 | 4c 8b 4a | jmpj_4A8B |
| $4A74 | a5 8f | b_4A74ldazp_rnd_pos_byte; x-ref: $4A3E |
| $4A76 | 29 3f | and#$3f |
| $4A78 | 18 | clc |
| $4A79 | 69 a0 | adc#$a0 |
| $4A7B | 20 ec 4e | jsrspawn_npc_car |
| $4A7E | 4c 8b 4a | jmpj_4A8B |
| $4A81 | a5 8f | b_4A81ldazp_rnd_pos_byte; x-ref: $4A42, $4A46, $4A4A |
| $4A83 | 29 7f | and#$7f |
| $4A85 | 18 | clc |
| $4A86 | 69 65 | adc#$65 |
| $4A88 | 20 ec 4e | jsrspawn_npc_car |
| $4A8B | 8a | j_4A8Btxa; x-ref: $4A57, $4A64, $4A71, $4A7E |
| $4A8C | 48 | pha |
| $4A8D | 20 97 e0 | jsre_E097; Generate Random Number for Speed |
| $4A90 | 68 | pla |
| $4A91 | aa | tax |
| $4A92 | 4c 74 4c | jmpj_4C74 |
| $4A95 | | .byte$cd, $04, $08, $30, $0b |
| $4A9A | a9 07 | j_4A9Alda#$07; x-ref: $4C7D |
| $4A9C | 85 4a | stazp_p_tmp_hi |
| $4A9E | a9 73 | lda#$73 |
| $4AA0 | 85 49 | stazp_p_tmp_lo |
| $4AA2 | 4c ad 4a | jmpj_4AAD |
| $4AA5 | a9 04 | j_4AA5lda#>SCREEN_RAM_R2C0; x-ref: $4C80 |
| $4AA7 | 85 4a | stazp_p_tmp_hi |
| $4AA9 | a9 50 | lda#<SCREEN_RAM_R2C0 |
| $4AAB | 85 49 | stazp_p_tmp_lo |
| $4AAD | a5 8f | j_4AADldazp_rnd_pos_byte; x-ref: $4AA2 |
| $4AAF | 29 17 | and#$17 |
| $4AB1 | a8 | tay |
| $4AB2 | b1 49 | lda(zp_p_tmp_lo),y |
| $4AB4 | c9 20 | cmp#$20 |
| $4AB6 | f0 07 | beqb_4ABF |
| $4AB8 | c9 65 | cmp#$65 |
| $4ABA | f0 03 | beqb_4ABF |
| $4ABC | 4c 07 4a | jmpj_4A07 |
| $4ABF | 98 | b_4ABFtya; x-ref: $4AB6, $4ABA |
| $4AC0 | 0a | asla |
| $4AC1 | 0a | asla |
| $4AC2 | 0a | asla |
| $4AC3 | 18 | clc |
| $4AC4 | 69 18 | adc#$18 |
| $4AC6 | 48 | pha |
| $4AC7 | 8a | txa |
| $4AC8 | 0a | asla |
| $4AC9 | aa | tax |
| $4ACA | 68 | pla |
| $4ACB | 9d 02 d0 | sta$d002,x; Sprite 1 X Pos |
| $4ACE | 8a | txa |
| $4ACF | 4a | lsra |
| $4AD0 | aa | tax |
| $4AD1 | 4c 83 4c | jmpj_4C83 |
| ; dead code |
| $4AD4 | | .byte$cd, $04, $08, $30, $05 |
| $4AD9 | a9 e0 | j_4AD9lda#$e0; x-ref: $4C8C |
| $4ADB | 4c e0 4a | jmpj_4AE0 |
| $4ADE | a9 3a | j_4ADElda#$3a; x-ref: $4C8F |
| $4AE0 | 48 | j_4AE0pha; x-ref: $4ADB |
| $4AE1 | 8a | txa |
| $4AE2 | 0a | asla |
| $4AE3 | aa | tax |
| $4AE4 | 68 | pla |
| $4AE5 | 9d 03 d0 | sta$d003,x; Sprite 1 Y Pos |
| $4AE8 | 8a | txa |
| $4AE9 | 4a | lsra |
| $4AEA | aa | tax |
| $4AEB | a5 8d | ldazp_rnd_direction_byte; AND #$01 → random lane direction (0=down, 1=up); FAC byte from third ROM_RND call |
| $4AED | 29 01 | and#$01 |
| $4AEF | 9d 04 09 | staf_0904,x |
| $4AF2 | a5 8e | ldazp_rnd_speed_byte; AND #$03 → random speed index 0-3; FAC byte from third ROM_RND call |
| $4AF4 | 29 03 | and#$03 |
| $4AF6 | 9d 08 09 | staf_0908,x |
| $4AF9 | a9 01 | lda#$01 |
| $4AFB | 9d 28 09 | statbl_enemy_car_state,x |
| $4AFE | a9 00 | lda#$00 |
| $4B00 | 9d 0c 09 | statbl_enemy_sprite_state,x |
| $4B03 | 9d 10 09 | statbl_enemy_sprite_direction,x |
| $4B06 | 9d 14 09 | statbl_enemy_sprite_step_count,x |
| $4B09 | 9d 18 09 | staf_0918,x |
| $4B0C | 9d 0c 09 | statbl_enemy_sprite_state,x |
| $4B0F | 9d 20 09 | statbl_enemy_sprite_lifetime,x |
| $4B12 | 9d 24 09 | statbl_enemy_sprite_active,x |
| $4B15 | bd 2c 09 | ldatbl_enemy_car_type,x |
| $4B18 | a8 | tay |
| $4B19 | b9 00 3f | ldatbl_sprite_color,y |
| $4B1C | 9d 28 d0 | sta$d028,x; Sprite 1 Color |
| $4B1F | 4c 07 4a | jmpj_4A07 |
| $4B22 | | .fill222, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the position and state of the enemy cars (Sprites 1-4). |
| ; This routine iterates through up to 4 active enemy entities. For each active |
| ; entity, it updates their horizontal position (swerving left or right) based on |
| ; their local state metrics. It then computes their new vertical position on the |
| ; screen by factoring in the player's current speed/scroll offset ($0804). |
| ; If an enemy car falls off the top or bottom of the screen (Y < $3A or Y >= $F0), |
| ; the routine automatically despawns it by clearing its status flag and hiding the |
| ; sprite. |
| ; |
| ; Inputs: Global scroll/speed ($0804), arrays at $0900/0904/0908/090C/0924/0928 |
| ; Outputs: None |
| ; Side Effects: Modifies Sprite 1-4 X/Y coordinates ($D002-$D009) and entity states. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4C00 | a2 00 | update_enemy_carsldx#$00; x-ref: $3AF0, $4779 |
| $4C02 | bd 0c 09 | b_4C02ldatbl_enemy_sprite_state,x; x-ref: $4C0A |
| $4C05 | f0 06 | beqb_4C0D |
| $4C07 | e8 | b_4C07inx; x-ref: $4C10, $4C17, $4CFD, $4D30 |
| $4C08 | e0 04 | cpx#$04 |
| $4C0A | d0 f6 | bneb_4C02 |
| $4C0C | 60 | rts |
| $4C0D | bd 24 09 | b_4C0Dldatbl_enemy_sprite_active,x; x-ref: $4C05 |
| $4C10 | d0 f5 | bneb_4C07 |
| $4C12 | bd 28 09 | ldatbl_enemy_car_state,x |
| $4C15 | c9 01 | cmp#$01 |
| $4C17 | d0 ee | bneb_4C07 |
| $4C19 | bd 08 09 | ldaf_0908,x |
| $4C1C | a8 | tay |
| $4C1D | c0 00 | j_4C1Dcpy#$00; x-ref: $4C58 |
| $4C1F | f0 44 | beqb_4C65 |
| $4C21 | bd 04 09 | ldaf_0904,x |
| $4C24 | f0 1f | beqb_4C45 |
| $4C26 | 8a | txa |
| $4C27 | 48 | pha |
| $4C28 | 0a | asla |
| $4C29 | aa | tax |
| $4C2A | fe 02 d0 | inc$d002,x; Sprite 1 X Pos |
| $4C2D | 4c 40 4c | jmpj_4C40 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Resets the player sprite pointer and terminates the jump sound effect. |
| ; |
| ; Inputs: A (sprite pointer value for sprite 0) |
| ; Outputs: Sprite 0 pointer updated, SID voice 1 control register cleared |
| ; Side Effects: Ends jump sound, updates sprite, proceeds to update_tick_and_collisions |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| restore_player_sprite_stop_sound |
| $4C30 | 8d f8 07 | stasprite_ptr_0; x-ref: $1ADE |
| $4C33 | a9 00 | lda#$00 |
| $4C35 | 8d 04 d4 | sta$d404; Clear Voice 1 Control Register to stop jump sound; Voice 1: Control Register |
| $4C38 | 4c 26 45 | jmpupdate_tick_and_collisions |
| $4C3B | | .byte$00, $00, $00, $00, $00 |
| $4C40 | 68 | j_4C40pla; x-ref: $4C2D, $4C4C |
| $4C41 | aa | tax |
| $4C42 | 4c 5e 4c | jmpj_4C5E |
| $4C45 | 8a | b_4C45txa; x-ref: $4C24 |
| $4C46 | 48 | pha |
| $4C47 | 0a | asla |
| $4C48 | aa | tax |
| $4C49 | de 02 d0 | dec$d002,x; Sprite 1 X Pos |
| $4C4C | 4c 40 4c | jmpj_4C40 |
| $4C4F | 20 a8 4d | j_4C4Fjsrcheck_npc_car_on_road; x-ref: $4CA9 |
| $4C52 | 4c 68 4c | jmpj_4C68 |
| $4C55 | ea | j_4C55nop; x-ref: $4C62 |
| $4C56 | ea | nop |
| $4C57 | ea | nop |
| $4C58 | 4c 1d 4c | jmpj_4C1D |
| $4C5B | | .byte$00, $00, $00 |
| $4C5E | 20 33 4d | j_4C5Ejsrcheck_car_on_road; x-ref: $4C42 |
| $4C61 | 88 | dey |
| $4C62 | 4c 55 4c | jmpj_4C55 |
| $4C65 | 4c 9a 4c | b_4C65jmpj_4C9A; x-ref: $4C1F |
| $4C68 | bd 00 09 | j_4C68ldaf_0900,x; x-ref: $4C52 |
| $4C6B | 38 | sec |
| $4C6C | ed 04 08 | sbcplayer_speed |
| $4C6F | 90 56 | bccb_4CC7 |
| $4C71 | 4c b1 4c | jmpj_4CB1 |
| $4C74 | bd 00 09 | j_4C74ldaf_0900,x; x-ref: $4A92 |
| $4C77 | 38 | sec |
| $4C78 | ed 04 08 | sbcplayer_speed |
| $4C7B | 90 03 | bccb_4C80 |
| $4C7D | 4c 9a 4a | jmpj_4A9A |
| $4C80 | 4c a5 4a | b_4C80jmpj_4AA5; x-ref: $4C7B |
| $4C83 | bd 00 09 | j_4C83ldaf_0900,x; x-ref: $4AD1 |
| $4C86 | 38 | sec |
| $4C87 | ed 04 08 | sbcplayer_speed |
| $4C8A | 90 03 | bccb_4C8F |
| $4C8C | 4c d9 4a | jmpj_4AD9 |
| $4C8F | 4c de 4a | b_4C8Fjmpj_4ADE; x-ref: $4C8A |
| ; dead code |
| $4C92 | | .byte$38, $ed, $04, $08, $90, $03, $4c, $d9 |
| $4C9A | 8a | j_4C9Atxa; x-ref: $4C65, $4DA5 |
| $4C9B | 48 | pha |
| $4C9C | 0a | asla |
| $4C9D | aa | tax |
| $4C9E | bd 03 d0 | lda$d003,x; Sprite 1 Y Pos |
| $4CA1 | 18 | clc |
| $4CA2 | 69 08 | adc#$08 |
| $4CA4 | 9d 03 d0 | sta$d003,x; Sprite 1 Y Pos |
| $4CA7 | 68 | pla |
| $4CA8 | aa | tax |
| $4CA9 | 4c 4f 4c | jmpj_4C4F |
| ; dead code |
| $4CAC | | .byte$cd, $04, $08, $30, $16 |
| $4CB1 | bd 00 09 | j_4CB1ldaf_0900,x; x-ref: $4C71 |
| $4CB4 | 38 | sec |
| $4CB5 | ed 04 08 | sbcplayer_speed |
| $4CB8 | 4a | lsra |
| $4CB9 | 4a | lsra |
| $4CBA | 4a | lsra |
| $4CBB | 18 | clc |
| $4CBC | 69 08 | adc#$08 |
| $4CBE | c9 10 | cmp#$10 |
| $4CC0 | 30 02 | bmib_4CC4 |
| $4CC2 | a9 10 | lda#$10 |
| $4CC4 | 4c d1 4c | b_4CC4jmpj_4CD1; x-ref: $4CC0 |
| $4CC7 | ad 04 08 | b_4CC7ldaplayer_speed; x-ref: $4C6F |
| $4CCA | 38 | sec |
| $4CCB | fd 00 09 | sbcf_0900,x |
| $4CCE | 4c 09 4d | jmpj_4D09 |
| $4CD1 | a8 | j_4CD1tay; x-ref: $4CC4, $4D19 |
| $4CD2 | c0 00 | j_4CD2cpy#$00; x-ref: $4CE3 |
| $4CD4 | f0 10 | beqb_4CE6 |
| $4CD6 | 20 e0 3a | jsrdetect_npc_car_collision_preserve_xy |
| $4CD9 | 8a | txa |
| $4CDA | 48 | pha |
| $4CDB | 0a | asla |
| $4CDC | aa | tax |
| $4CDD | de 03 d0 | dec$d003,x; Sprite 1 Y Pos |
| $4CE0 | 68 | pla |
| $4CE1 | aa | tax |
| $4CE2 | 88 | dey |
| $4CE3 | 4c d2 4c | jmpj_4CD2 |
| $4CE6 | 8a | b_4CE6txa; x-ref: $4CD4, $4DF0 |
| $4CE7 | 48 | pha |
| $4CE8 | 0a | asla |
| $4CE9 | aa | tax |
| $4CEA | 4c 1c 4d | jmpj_4D1C |
| $4CED | | .byte$03, $d0, $00, $0f |
| $4CF1 | a9 00 | j_4CF1lda#$00; x-ref: $4D27 |
| $4CF3 | 9d 03 d0 | sta$d003,x; Sprite 1 Y Pos |
| $4CF6 | 68 | pla |
| $4CF7 | aa | tax |
| $4CF8 | a9 00 | lda#$00 |
| $4CFA | 9d 28 09 | statbl_enemy_car_state,x |
| $4CFD | 4c 07 4c | jmpb_4C07 |
| ; dead code |
| $4D00 | | .byte$c9, $f0, $10, $ed, $68, $aa, $4c, $07 |
| $4D08 | | .byte$4c |
| $4D09 | 4a | j_4D09lsra; x-ref: $4CCE |
| $4D0A | 4a | lsra |
| $4D0B | 4a | lsra |
| $4D0C | c9 09 | cmp#$09 |
| $4D0E | 30 02 | bmib_4D12 |
| $4D10 | a9 08 | lda#$08 |
| $4D12 | 85 49 | b_4D12stazp_p_tmp_lo; x-ref: $4D0E |
| $4D14 | a9 08 | lda#$08 |
| $4D16 | 38 | sec |
| $4D17 | e5 49 | sbczp_p_tmp_lo |
| $4D19 | 4c d1 4c | jmpj_4CD1 |
| $4D1C | bd 03 d0 | j_4D1Clda$d003,x; x-ref: $4CEA Sprite 1 Y Pos |
| $4D1F | c9 80 | cmp#$80 |
| $4D21 | 30 07 | bmib_4D2A |
| $4D23 | c9 f0 | cmp#$f0 |
| $4D25 | 30 07 | bmib_4D2E |
| $4D27 | 4c f1 4c | b_4D27jmpj_4CF1; x-ref: $4D2C |
| $4D2A | c9 3a | b_4D2Acmp#$3a; x-ref: $4D21 |
| $4D2C | 30 f9 | bmib_4D27 |
| $4D2E | 68 | b_4D2Epla; x-ref: $4D25 |
| $4D2F | aa | tax |
| $4D30 | 4c 07 4c | jmpb_4C07 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Checks whether an enemy car (sprite N, passed in X) is on a drivable road tile. |
| ; |
| ; The routine converts the sprite's screen-space pixel position (from VIC-II |
| ; $D002/$D003 registers) into a tile column (Y) and tile row (X) by subtracting |
| ; a fixed border offset and dividing by 8 (three LSRs). It then computes a |
| ; pointer into screen RAM at $0400 using a 16-bit base address in (a49/a4A) |
| ; and multiplies the row by 40 ($28) to find the correct row offset. |
| ; |
| ; A lookup table at $F0904, indexed by sprite number X, provides a half-tile |
| ; column adjustment (+1) to handle wide sprites that straddle two tiles. |
| ; |
| ; The road tile check reads the screen code at the computed (row, col) position: |
| ; - $20 (space) = road tile -> jump to j4ED3 (car is off-road / blocked) |
| ; - $65 (letter) = another road variant -> also treated as blocked |
| ; |
| ; If the car is on road (non-road tile), the routine stores $01 at f0904,x (car |
| ; is on-road flag = active), restores registers, samples bits 0-1 of ZP $8E for |
| ; a 2-bit value and stores it at f0908,x (road direction/surface type), then |
| ; jumps to j4C9A (continue normal car movement logic). |
| ; |
| ; If the car is off-road, f0904,x is cleared ($00), and the routine redirects to |
| ; j4ED3 which will handle the out-of-bounds / collision branch. |
| ; |
| ; Inputs: X = sprite/car index (0-3) |
| ; Outputs: f0904,x = 1 if on-road, 0 if off-road; f0908,x = road surface bits |
| ; Side Effects: Reads VIC-II sprite X/Y registers ($D002/$D003); reads screen RAM |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4D33 | 8a | check_car_on_roadtxa; sprite index -> X reg (doubled for VIC pair offset) ; x-ref: $4C5E |
| $4D34 | 48 | pha |
| $4D35 | 98 | tya |
| $4D36 | 48 | pha |
| $4D37 | 8a | txa |
| $4D38 | 48 | pha |
| $4D39 | 0a | asla |
| $4D3A | aa | tax |
| $4D3B | bd 02 d0 | lda$d002,x; Sprite 1 X Pos |
| $4D3E | 38 | sec |
| $4D3F | e9 10 | sbc#$10 |
| $4D41 | 4a | lsra |
| $4D42 | 4a | lsra |
| $4D43 | 4a | lsra; subtract left border ($10 px) then >> 3 = tile column -> Y |
| $4D44 | a8 | tay |
| $4D45 | bd 03 d0 | lda$d003,x; Sprite 1 Y Pos |
| $4D48 | 38 | sec |
| $4D49 | e9 32 | sbc#$32 |
| $4D4B | 4a | lsra |
| $4D4C | 4a | lsra |
| $4D4D | 4a | lsra |
| $4D4E | aa | tax |
| $4D4F | a9 00 | lda#<SCREEN_RAM |
| $4D51 | 85 49 | stazp_p_tmp_lo |
| $4D53 | a9 04 | lda#>SCREEN_RAM; base screen RAM low byte = $00 (addr $0400) |
| $4D55 | 85 4a | stazp_p_tmp_hi; base screen RAM high byte = $04 (addr $0400) |
| $4D57 | e0 00 | j_4D57cpx#$00; x-ref: $4D69 |
| $4D59 | f0 11 | beqb_4D6C |
| $4D5B | a5 49 | ldazp_p_tmp_lo |
| $4D5D | 18 | clc |
| $4D5E | 69 28 | adc#$28 |
| $4D60 | 85 49 | stazp_p_tmp_lo |
| $4D62 | a5 4a | ldazp_p_tmp_hi |
| $4D64 | 69 00 | adc#$00 |
| $4D66 | 85 4a | stazp_p_tmp_hi |
| $4D68 | ca | dex |
| $4D69 | 4c 57 4d | jmpj_4D57 |
| $4D6C | 68 | b_4D6Cpla; $20 (space screencode) = road tile -> car is off-road/blocked ; x-ref: $4D59 |
| $4D6D | aa | tax |
| $4D6E | bd 04 09 | ldaf_0904,x |
| $4D71 | f0 01 | beqb_4D74 |
| $4D73 | c8 | iny |
| $4D74 | b1 49 | b_4D74lda(zp_p_tmp_lo),y; x-ref: $4D71 |
| $4D76 | c9 20 | cmp#$20 |
| $4D78 | d0 05 | bneb_4D7F |
| $4D7A | 4c d3 4e | b_4D7Ajmpcheck_npc_offscreen_right; x-ref: $4D81 |
| $4D7D | | .byte$ea, $60 |
| $4D7F | c9 65 | b_4D7Fcmp#$65; $65 = alternate road screencode -> also off-road ; x-ref: $4D78 |
| $4D81 | f0 f7 | beqb_4D7A |
| $4D83 | bd 04 09 | j_4D83ldaf_0904,x; not on road: clear on-road flag for this car ; x-ref: $4EE9 |
| $4D86 | f0 08 | beqb_4D90 |
| $4D88 | a9 00 | lda#$00 |
| $4D8A | 9d 04 09 | staf_0904,x |
| $4D8D | 4c 95 4d | jmpj_4D95 |
| $4D90 | a9 01 | b_4D90lda#$01; x-ref: $4D86 |
| $4D92 | 9d 04 09 | staf_0904,x |
| $4D95 | ea | j_4D95nop; x-ref: $4D8D |
| $4D96 | ea | nop |
| $4D97 | ea | nop |
| $4D98 | 68 | pla |
| $4D99 | a8 | tay |
| $4D9A | 68 | pla |
| $4D9B | aa | tax |
| $4D9C | 68 | pla |
| $4D9D | 68 | pla |
| $4D9E | a5 8e | ldazp_rnd_speed_byte |
| $4DA0 | 29 03 | and#$03 |
| $4DA2 | 9d 08 09 | staf_0908,x |
| $4DA5 | 4c 9a 4c | jmpj_4C9A |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Checks if the NPC car is still on the road or has hit the off-road boundary. |
| ; If off-road, it pops the return address and jumps to b4CE6 to abort caller. |
| ; |
| ; Inputs: X (NPC car index) |
| ; Outputs: None (if on road) |
| ; Side Effects: Aborts caller by manipulating stack if off-road. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| check_npc_car_on_road |
| $4DA8 | 8a | txa; Save NPC car index (X) and loop counter (Y) ; x-ref: $4C4F |
| $4DA9 | 48 | pha |
| $4DAA | 98 | tya |
| $4DAB | 48 | pha |
| $4DAC | 8a | txa |
| $4DAD | 0a | asla |
| $4DAE | aa | tax |
| $4DAF | bd 02 d0 | lda$d002,x; Convert Sprite 1 X Pos to tile column; Sprite 1 X Pos |
| $4DB2 | 38 | sec |
| $4DB3 | e9 10 | sbc#$10 |
| $4DB5 | 4a | lsra |
| $4DB6 | 4a | lsra |
| $4DB7 | 4a | lsra |
| $4DB8 | a8 | tay |
| $4DB9 | bd 03 d0 | lda$d003,x; Convert Sprite 1 Y Pos to tile row; Sprite 1 Y Pos |
| $4DBC | 38 | sec |
| $4DBD | e9 32 | sbc#$32 |
| $4DBF | 4a | lsra |
| $4DC0 | 4a | lsra |
| $4DC1 | 4a | lsra |
| $4DC2 | aa | tax |
| $4DC3 | a9 d9 | lda#<p_03D9; Base address $03D9 (Screen RAM $0400 - $27) |
| $4DC5 | 85 49 | stazp_p_tmp_lo |
| $4DC7 | a9 03 | lda#>p_03D9 |
| $4DC9 | 85 4a | stazp_p_tmp_hi |
| $4DCB | e0 00 | j_4DCBcpx#$00; x-ref: $4DDD |
| $4DCD | f0 11 | beqb_4DE0 |
| $4DCF | a5 49 | ldazp_p_tmp_lo |
| $4DD1 | 18 | clc |
| $4DD2 | 69 28 | adc#$28 |
| $4DD4 | 85 49 | stazp_p_tmp_lo |
| $4DD6 | a5 4a | ldazp_p_tmp_hi |
| $4DD8 | 69 00 | adc#$00 |
| $4DDA | 85 4a | stazp_p_tmp_hi |
| $4DDC | ca | dex |
| $4DDD | 4c cb 4d | jmpj_4DCB |
| $4DE0 | b1 49 | b_4DE0lda(zp_p_tmp_lo),y; x-ref: $4DCD |
| $4DE2 | c9 20 | cmp#$20 |
| $4DE4 | f0 0d | beqb_4DF3 |
| $4DE6 | c9 65 | cmp#$65 |
| $4DE8 | f0 09 | beqb_4DF3 |
| $4DEA | 68 | b_4DEApla; Off-road: pop Y, X, and caller return address! ; x-ref: $4DFC |
| $4DEB | a8 | tay |
| $4DEC | 68 | pla |
| $4DED | aa | tax |
| $4DEE | 68 | pla |
| $4DEF | 68 | pla |
| $4DF0 | 4c e6 4c | jmpb_4CE6 |
| $4DF3 | c8 | b_4DF3iny; x-ref: $4DE4, $4DE8 |
| $4DF4 | b1 49 | lda(zp_p_tmp_lo),y |
| $4DF6 | c9 20 | cmp#$20 |
| $4DF8 | f0 04 | beqb_4DFE |
| $4DFA | c9 65 | cmp#$65 |
| $4DFC | d0 ec | bneb_4DEA |
| $4DFE | 68 | b_4DFEpla; x-ref: $4DF8 |
| $4DFF | a8 | tay |
| $4E00 | 68 | pla |
| $4E01 | aa | tax |
| $4E02 | 60 | rts |
| $4E03 | 9d f9 07 | j_4E03stasprite_ptr_1,x; x-ref: $47E0 |
| $4E06 | 8a | txa |
| $4E07 | 48 | pha |
| $4E08 | aa | tax |
| $4E09 | a9 02 | lda#$02 |
| $4E0B | e0 00 | j_4E0Bcpx#$00; x-ref: $4E11 |
| $4E0D | f0 05 | beqb_4E14 |
| $4E0F | 0a | asla |
| $4E10 | ca | dex |
| $4E11 | 4c 0b 4e | jmpj_4E0B |
| $4E14 | 85 49 | b_4E14stazp_p_tmp_lo; x-ref: $4E0D |
| $4E16 | a9 ff | lda#$ff |
| $4E18 | 38 | sec |
| $4E19 | e5 49 | sbczp_p_tmp_lo |
| $4E1B | 85 49 | stazp_p_tmp_lo |
| $4E1D | ad 1c d0 | lda$d01c; Sprites Multi-Color Mode Select |
| $4E20 | 25 49 | andzp_p_tmp_lo |
| $4E22 | 8d 1c d0 | sta$d01c; Sprites Multi-Color Mode Select |
| $4E25 | 68 | pla |
| $4E26 | aa | tax |
| $4E27 | ee 21 08 | inccrashed_cars_ones |
| $4E2A | ad 21 08 | ldacrashed_cars_ones |
| $4E2D | 8d 21 08 | stacrashed_cars_ones |
| $4E30 | c9 0a | cmp#$0a |
| $4E32 | d0 08 | bner_4E3C |
| $4E34 | a9 00 | lda#$00 |
| $4E36 | 8d 21 08 | stacrashed_cars_ones |
| $4E39 | ee 20 08 | inccrashed_cars_tens |
| $4E3C | 60 | r_4E3Crts; x-ref: $4E32 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes a score sprite (Sprites 5-7) at the player's current location. |
| ; |
| ; Inputs: A (timer duration), Y (score sprite index 0-2) |
| ; Outputs: Initializes timer array $0983,Y |
| ; Side Effects: Modifies sprite 5-7 color and coordinates to match player |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| spawn_score_sprite_57 |
| $4E3D | 99 83 09 | staf_0983,y; x-ref: $45EA |
| $4E40 | a9 01 | lda#$01 |
| $4E42 | 99 2c d0 | sta$d02c,y; Set color to 1 (white); Sprite 5 Color |
| $4E45 | 98 | tya |
| $4E46 | 0a | asla |
| $4E47 | a8 | tay |
| $4E48 | ad 00 d0 | lda$d000; Sprite 0 X Pos |
| $4E4B | 99 0a d0 | sta$d00a,y; Copy player X Pos to score sprite X Pos; Sprite 5 X Pos |
| $4E4E | ad 01 d0 | lda$d001; Sprite 0 Y Pos |
| $4E51 | 99 0b d0 | sta$d00b,y; Copy player Y Pos to score sprite Y Pos; Sprite 5 Y Pos |
| $4E54 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates explosion and projectile animation timers. |
| ; First, it checks the enemy pool (Sprites 1-4). If an enemy is in state $02 |
| ; (exploding), it ticks down a duration timer at $0930. When the timer reaches 0, |
| ; it resets their state, restores their default multi-color bit config, and hides them. |
| ; Then, it runs a second loop over a pool of 3 secondary objects (Sprites 5-7), |
| ; ticking their timers and dropping them downward visually by adding to their Y Pos. |
| ; |
| ; Inputs: Enemy states at $0928, Timers at $0930 and $0983 |
| ; Outputs: None |
| ; Side Effects: Modifies Sprites 1-7 coordinates and multi-color registers. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| update_explosion_animations |
| $4E55 | a2 00 | ldx#$00; x-ref: $1841, $477C |
| $4E57 | bd 28 09 | b_4E57ldatbl_enemy_car_state,x; x-ref: $4E61 |
| $4E5A | c9 02 | cmp#$02 |
| $4E5C | f0 08 | beqb_4E66 |
| $4E5E | e8 | j_4E5Einx; x-ref: $4E95 |
| $4E5F | e0 04 | cpx#$04 |
| $4E61 | d0 f4 | bneb_4E57 |
| $4E63 | 4c 98 4e | jmpj_4E98 |
| $4E66 | de 30 09 | b_4E66dectbl_npc_damage_timer,x; x-ref: $4E5C |
| $4E69 | f0 03 | beqb_4E6E |
| $4E6B | 4c 98 4e | jmpj_4E98 |
| $4E6E | a9 00 | b_4E6Elda#$00; x-ref: $4E69 |
| $4E70 | 9d 28 09 | statbl_enemy_car_state,x |
| $4E73 | 8a | txa |
| $4E74 | 48 | pha |
| $4E75 | a9 02 | lda#$02 |
| $4E77 | e0 00 | j_4E77cpx#$00; x-ref: $4E7D |
| $4E79 | f0 05 | beqb_4E80 |
| $4E7B | 0a | asla |
| $4E7C | ca | dex |
| $4E7D | 4c 77 4e | jmpj_4E77 |
| $4E80 | 85 49 | b_4E80stazp_p_tmp_lo; x-ref: $4E79 |
| $4E82 | ad 1c d0 | lda$d01c; Sprites Multi-Color Mode Select |
| $4E85 | 05 49 | orazp_p_tmp_lo |
| $4E87 | 8d 1c d0 | sta$d01c; Sprites Multi-Color Mode Select |
| $4E8A | 68 | pla |
| $4E8B | 48 | pha |
| $4E8C | 0a | asla |
| $4E8D | aa | tax |
| $4E8E | a9 00 | lda#$00 |
| $4E90 | 9d 02 d0 | sta$d002,x; Sprite 1 X Pos |
| $4E93 | 68 | pla |
| $4E94 | aa | tax |
| $4E95 | 4c 5e 4e | jmpj_4E5E |
| $4E98 | a2 00 | j_4E98ldx#$00; x-ref: $4E63, $4E6B |
| $4E9A | bd 80 09 | b_4E9Aldatbl_score_sprite_active,x; x-ref: $4EA2 |
| $4E9D | d0 06 | bneb_4EA5 |
| $4E9F | e8 | j_4E9Finx; x-ref: $4EBA |
| $4EA0 | e0 03 | cpx#$03 |
| $4EA2 | d0 f6 | bneb_4E9A |
| $4EA4 | 60 | rts |
| $4EA5 | de 83 09 | b_4EA5decf_0983,x; x-ref: $4E9D |
| $4EA8 | d0 13 | bneb_4EBD |
| $4EAA | a9 00 | lda#$00 |
| $4EAC | 9d 80 09 | statbl_score_sprite_active,x |
| $4EAF | 8a | txa |
| $4EB0 | 48 | pha |
| $4EB1 | 0a | asla |
| $4EB2 | aa | tax |
| $4EB3 | a9 00 | lda#$00 |
| $4EB5 | 9d 0a d0 | sta$d00a,x; Sprite 5 X Pos |
| $4EB8 | 68 | j_4EB8pla; x-ref: $4F01 |
| $4EB9 | aa | tax |
| $4EBA | 4c 9f 4e | jmpj_4E9F |
| $4EBD | 8a | b_4EBDtxa; x-ref: $4EA8 |
| $4EBE | 48 | pha |
| $4EBF | 0a | asla |
| $4EC0 | aa | tax |
| $4EC1 | bd 0b d0 | lda$d00b,x; Sprite 5 Y Pos |
| $4EC4 | 18 | clc |
| $4EC5 | 69 08 | adc#$08 |
| $4EC7 | 9d 0b d0 | sta$d00b,x; Sprite 5 Y Pos |
| $4ECA | 4c f5 4e | jmpclamp_sprite5_top_boundary |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Main loop tail: applies player X recoil then hands off to the finalizer. |
| ; |
| ; Called unconditionally at the bottom of main_loop via JMP. Applies any |
| ; pending X-axis collision recoil to the player sprite, then falls through |
| ; to main_loop_finalize_and_repeat which runs the remaining per-frame |
| ; housekeeping before jumping back to main_loop. |
| ; |
| ; Inputs: Recoil state managed by apply_player_x_recoil |
| ; Outputs: None |
| ; Side Effects: May shift player sprite X position |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| main_loop_apply_recoil |
| $4ECD | 20 b0 3d | jsrapply_player_x_recoil; Apply X-axis collision recoil to the player sprite ; x-ref: $184D |
| $4ED0 | 4c b0 4f | jmpmain_loop_finalize_and_repeat; Fall through to per-frame housekeeping and re-enter main loop |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; NPC off-screen-right guard, called from the NPC road-tile walker. |
| ; |
| ; On entry the stack holds (top to bottom): NPC slot index, Y, return address. |
| ; Checks whether the NPC's sprite X position is $FF (sprite has scrolled off |
| ; the right edge of the screen). Two paths: |
| ; |
| ; Not $FF (still on-screen): pop all three stack frames (slot, Y, ret) |
| ; and return to the caller's caller — early exit from the tile walk. |
| ; $FF (off-screen right): restore slot index into X, read the next tile |
| ; byte from the current map pointer (p_tmp_lo),Y, then jump back |
| ; into the tile-walk loop at j4D83 to handle the new tile. |
| ; |
| ; Inputs: Stack: NPC slot (1 byte), Y (1 byte), return address (2 bytes) |
| ; $D002+X: NPC sprite X register (VIC-II) |
| ; (p_tmp_lo),Y: current map tile pointer |
| ; Outputs: A = next tile byte (off-screen path only) |
| ; Side Effects: Unwinds 3 stack frames on the on-screen early-exit path |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| check_npc_offscreen_right |
| $4ED3 | 8a | txa; Push NPC slot index; compute sprite reg offset (slot * 2) into X ; x-ref: $4D7A |
| $4ED4 | 48 | pha |
| $4ED5 | 0a | asla |
| $4ED6 | aa | tax |
| $4ED7 | bd 02 d0 | lda$d002,x; Load NPC sprite X pos; $FF means sprite has scrolled off the right edge; Sprite 1 X Pos |
| $4EDA | c9 ff | cmp#$ff |
| $4EDC | f0 06 | beqb_4EE4 |
| $4EDE | 68 | pla; On-screen path: pop slot, Y, and return address — early exit from tile walk |
| $4EDF | 68 | pla |
| $4EE0 | a8 | tay |
| $4EE1 | 68 | pla |
| $4EE2 | aa | tax |
| $4EE3 | 60 | rts |
| $4EE4 | 68 | b_4EE4pla; Off-screen path: restore slot index into X ; x-ref: $4EDC |
| $4EE5 | aa | tax |
| $4EE6 | ea | nop |
| $4EE7 | b1 49 | lda(zp_p_tmp_lo),y; Read next map tile byte via current pointer |
| $4EE9 | 4c 83 4d | jmpj_4D83; Re-enter tile walk loop to process the new tile |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes speed and fresh flag for a newly spawned NPC car. |
| ; |
| ; Inputs: A (initial speed), X (NPC car slot 0-3) |
| ; Outputs: Initializes $0900,X (speed) and $0910,X (fresh flag) |
| ; Side Effects: Sets up NPC car speed and marks it fresh for the overtake check |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $4EEC | 9d 00 09 | spawn_npc_carstaf_0900,x; Set NPC speed ; x-ref: $4A54, $4A61, $4A6E, $4A7B, $4A88 |
| $4EEF | a9 01 | lda#$01 |
| $4EF1 | 9d 34 09 | statbl_enemy_car_fresh_flag,x; Set fresh flag to 1 for overtake check |
| $4EF4 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Top-boundary clamp for Sprite 5 during NPC car movement. |
| ; |
| ; Called mid-loop when an NPC car's Sprite 5 Y position is being updated. |
| ; If the Y position has gone above $20 (off the top of the playfield), the |
| ; sprite's X position is clamped to 1 to effectively reset/hide it at the |
| ; left edge. Execution always rejoins the NPC car movement loop at j4EB8. |
| ; |
| ; Inputs: $D00B+X: Sprite 5 Y position for the current NPC slot |
| ; Outputs: $D00A+X: Sprite 5 X position (set to 1 if Y < $20) |
| ; Side Effects: None |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| clamp_sprite5_top_boundary |
| $4EF5 | bd 0b d0 | lda$d00b,x; Load Sprite 5 Y pos for this NPC slot ; x-ref: $4ECA Sprite 5 Y Pos |
| $4EF8 | c9 20 | cmp#$20; Is Y >= $20? If so, sprite is still in bounds; skip clamp |
| $4EFA | b0 05 | bcsb_4F01 |
| $4EFC | a9 01 | lda#$01; Y < $20: sprite scrolled off the top — clamp X to 1 to hide/reset it |
| $4EFE | 9d 0a d0 | sta$d00a,x; Sprite 5 X Pos |
| $4F01 | 4c b8 4e | b_4F01jmpj_4EB8; Rejoin NPC movement loop ; x-ref: $4EFA |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Writes a 2x2 tile stamp to screen RAM when the player successfully passes |
| ; over a type-4 NPC car (the "jump target" car). Only fires once per car |
| ; appearance: car_fresh_flag[x] is set at spawn and cleared here after stamping. |
| ; |
| ; Proximity conditions (both must hold): |
| ; Y: player sprite Y >= NPC sprite Y + $20 (player is >= 32px past the NPC) |
| ; X: |player X - NPC X| < $40 (within 64px horizontally) |
| ; |
| ; Screen address: $0400 + ((npc_sprite_y - $22) >> 3) * 40 + ((npc_sprite_x - $10) >> 3) |
| ; Tile stamp (2x2): |
| ; $1B $1C <- top row at computed address |
| ; $1D $1E <- bottom row 40 chars later |
| ; |
| ; Skipped if game state (a0800) is 0 or 3. |
| ; |
| ; Inputs: a0800 (game state), car_state[0..3], f092C[0..3] (car type), |
| ; car_fresh_flag[0..3], VIC-II sprite regs $D000-$D009 |
| ; Outputs: Screen RAM ($0400+) |
| ; Side Effects: Clears car_fresh_flag[x] after stamping (one-shot per car) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| draw_car_overtake_mark |
| $4F04 | ad 00 08 | ldalevel_nr; x-ref: $4FB0 |
| $4F07 | c9 00 | cmp#$00; Skip if game state 0 or 3 (not in active play) |
| $4F09 | f0 12 | beqr_4F1D |
| $4F0B | c9 03 | cmp#$03 |
| $4F0D | f0 0e | beqr_4F1D |
| $4F0F | a2 00 | ldx#$00 |
| $4F11 | bd 28 09 | b_4F11ldatbl_enemy_car_state,x; x-ref: $4F1B |
| $4F14 | c9 01 | cmp#$01; Only check on-road/active cars (state 1) |
| $4F16 | f0 06 | beqb_4F1E |
| $4F18 | e8 | b_4F18inx; x-ref: $4F23, $4F28, $4F46, $4FAC |
| $4F19 | e0 04 | cpx#$04 |
| $4F1B | d0 f4 | bneb_4F11 |
| $4F1D | 60 | r_4F1Drts; x-ref: $4F09, $4F0D |
| $4F1E | bd 2c 09 | b_4F1Eldatbl_enemy_car_type,x; x-ref: $4F16 |
| $4F21 | c9 04 | cmp#$04; Only process type-4 cars (jump target) |
| $4F23 | d0 f3 | bneb_4F18 |
| $4F25 | bd 34 09 | ldatbl_enemy_car_fresh_flag,x |
| $4F28 | f0 ee | beqb_4F18; Skip if already stamped (flag cleared after first hit) |
| $4F2A | 8a | txa |
| $4F2B | 48 | pha |
| $4F2C | 0a | asla |
| $4F2D | aa | tax |
| $4F2E | bd 03 d0 | lda$d003,x; Check Y: is player past this car?; Sprite 1 Y Pos |
| $4F31 | cd 01 d0 | cmp$d001; Sprite 0 Y Pos |
| $4F34 | 90 03 | bccb_4F39 |
| $4F36 | 4c 44 4f | jmpj_4F44 |
| $4F39 | ad 01 d0 | b_4F39lda$d001; x-ref: $4F34 Sprite 0 Y Pos |
| $4F3C | 38 | sec |
| $4F3D | fd 03 d0 | sbc$d003,x; Sprite 1 Y Pos |
| $4F40 | c9 20 | cmp#$20; Player must be >= 32px below NPC (past it in race direction) |
| $4F42 | b0 05 | bcsb_4F49 |
| $4F44 | 68 | j_4F44pla; x-ref: $4F36, $4F61 |
| $4F45 | aa | tax |
| $4F46 | 4c 18 4f | jmpb_4F18 |
| $4F49 | bd 02 d0 | b_4F49lda$d002,x; x-ref: $4F42 Sprite 1 X Pos |
| $4F4C | cd 00 d0 | cmp$d000; Sprite 0 X Pos |
| $4F4F | 90 07 | bccb_4F58 |
| $4F51 | 38 | sec |
| $4F52 | ed 00 d0 | sbc$d000; Sprite 0 X Pos |
| $4F55 | 4c 5f 4f | jmpj_4F5F |
| $4F58 | ad 00 d0 | b_4F58lda$d000; x-ref: $4F4F Sprite 0 X Pos |
| $4F5B | 38 | sec |
| $4F5C | fd 02 d0 | sbc$d002,x; Sprite 1 X Pos |
| $4F5F | c9 40 | j_4F5Fcmp#$40; X proximity: must be within 64px ; x-ref: $4F55 |
| $4F61 | b0 e1 | bcsj_4F44 |
| $4F63 | bd 02 d0 | lda$d002,x; Sprite 1 X Pos |
| $4F66 | 38 | sec |
| $4F67 | e9 10 | sbc#$10; sprite_x - $10 = pixel offset from left edge; >>3 = tile column (0-39) |
| $4F69 | 4a | lsra |
| $4F6A | 4a | lsra |
| $4F6B | 4a | lsra |
| $4F6C | 85 49 | stazp_p_tmp_lo |
| $4F6E | bd 03 d0 | lda$d003,x; Sprite 1 Y Pos |
| $4F71 | 38 | sec |
| $4F72 | e9 22 | sbc#$22; sprite_y - $22 = pixel offset from top; >>3 = tile row (0-24) |
| $4F74 | 4a | lsra |
| $4F75 | 4a | lsra |
| $4F76 | 4a | lsra |
| $4F77 | a8 | tay |
| $4F78 | a9 04 | lda#$04 |
| $4F7A | 85 4a | stazp_p_tmp_hi |
| $4F7C | c0 00 | j_4F7Ccpy#$00; Multiply row by 40 (screen width) to get row byte offset ; x-ref: $4F8E |
| $4F7E | f0 11 | beqb_4F91 |
| $4F80 | a5 49 | ldazp_p_tmp_lo |
| $4F82 | 18 | clc |
| $4F83 | 69 28 | adc#$28 |
| $4F85 | 85 49 | stazp_p_tmp_lo |
| $4F87 | a5 4a | ldazp_p_tmp_hi |
| $4F89 | 69 00 | adc#$00 |
| $4F8B | 85 4a | stazp_p_tmp_hi |
| $4F8D | 88 | dey |
| $4F8E | 4c 7c 4f | jmpj_4F7C |
| $4F91 | a9 1b | b_4F91lda#$1b; Write top-left tile of 2x2 stamp ; x-ref: $4F7E |
| $4F93 | 91 49 | sta(zp_p_tmp_lo),y |
| $4F95 | c8 | iny |
| $4F96 | a9 1c | lda#$1c; Write top-right tile |
| $4F98 | 91 49 | sta(zp_p_tmp_lo),y |
| $4F9A | a0 28 | ldy#$28; Next screen row (+40 chars) |
| $4F9C | a9 1d | lda#$1d; Write bottom-left tile |
| $4F9E | 91 49 | sta(zp_p_tmp_lo),y |
| $4FA0 | c8 | iny |
| $4FA1 | a9 1e | lda#$1e; Write bottom-right tile |
| $4FA3 | 91 49 | sta(zp_p_tmp_lo),y |
| $4FA5 | 68 | pla |
| $4FA6 | aa | tax |
| $4FA7 | a9 00 | lda#$00; Clear flag: don't stamp this car again |
| $4FA9 | 9d 34 09 | statbl_enemy_car_fresh_flag,x |
| $4FAC | 4c 18 4f | jmpb_4F18 |
| $4FAF | | .byte$00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Per-frame finalizer: last three housekeeping calls before looping back. |
| ; |
| ; Runs at the very end of every game frame, after recoil has been applied. |
| ; Draws the car-overtake tile stamp if the player jumped over a type-4 NPC, |
| ; detects any remaining NPC-vs-NPC collisions (X/Y registers preserved), |
| ; syncs the loop pace to keyboard input, then unconditionally jumps back to |
| ; the top of main_loop. |
| ; |
| ; Inputs: None (reads global game state) |
| ; Outputs: None |
| ; Side Effects: May stamp screen RAM, trigger NPC collision, stall on input |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| main_loop_finalize_and_repeat |
| $4FB0 | 20 04 4f | jsrdraw_car_overtake_mark; Draw 2x2 tile stamp if player jumped over a type-4 NPC car this frame ; x-ref: $4ED0 |
| $4FB3 | 20 e0 3a | jsrdetect_npc_car_collision_preserve_xy; Detect NPC-vs-NPC car collisions (X/Y registers preserved by wrapper) |
| $4FB6 | 20 39 52 | jsrsync_to_keypress; Sync loop pace to keyboard: stall if no key held, else return immediately |
| $4FB9 | 4c 09 18 | jmpmain_loop; Loop unconditionally back to top of main_loop |
| $4FBC | | .fill68, $00 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Restores game variables from double buffers. |
| ; This routine copies game state data from back buffers ($0A00/$0B00 or $0C00/$0D00) |
| ; into the active variables pages ($0800/$0900). It chooses which buffer to pull |
| ; from based on player/turn states in $0F00 and $0F01 (useful for 2-player modes). |
| ; |
| ; Inputs: $0F00, $0F01 |
| ; Outputs: None |
| ; Side Effects: Overwrites $0800-$09FF memory region. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $5000 | ea | restore_game_varsnop; x-ref: $170C |
| $5001 | ea | nop |
| $5002 | ea | nop |
| $5003 | ad 00 0f | ldanumber_of_players |
| $5006 | c9 02 | cmp#$02 |
| $5008 | f0 12 | beqb_501C |
| $500A | a2 00 | b_500Aldx#$00; x-ref: $5021 |
| $500C | bd 00 0a | b_500Cldaf_0A00,x; x-ref: $5019 |
| $500F | 9d 00 08 | stalevel_nr,x |
| $5012 | bd 00 0b | ldaf_0B00,x |
| $5015 | 9d 00 09 | staf_0900,x |
| $5018 | e8 | inx |
| $5019 | d0 f1 | bneb_500C |
| $501B | 60 | rts |
| $501C | ad 01 0f | b_501Cldacurrent_player_nr; x-ref: $5008 |
| $501F | c9 01 | cmp#$01 |
| $5021 | f0 e7 | beqb_500A |
| $5023 | a2 00 | ldx#$00 |
| $5025 | bd 00 0c | b_5025ldaf_0C00,x; x-ref: $5032 |
| $5028 | 9d 00 08 | stalevel_nr,x |
| $502B | bd 00 0d | ldaf_0D00,x |
| $502E | 9d 00 09 | staf_0900,x |
| $5031 | e8 | inx |
| $5032 | d0 f1 | bneb_5025 |
| $5034 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Initializes the player's turn by setting Y position and flashing the |
| ; \"PLAYER X\" banner on screen before clearing it. |
| ; |
| ; Inputs: A (initial player sprite Y position), current_player_nr (1 or 2) |
| ; Outputs: Sprite 0 Y Pos updated |
| ; Side Effects: Draws \"PLAYER X\" on screen, busy waits, then clears it. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| set_player_y_and_draw_player_row |
| $5035 | 8d 01 d0 | sta$d001; Store A into Sprite 0 Y pos ; x-ref: $174D Sprite 0 Y Pos |
| $5038 | a2 00 | ldx#$00 |
| $503A | bd f0 50 | b_503Aldatxt_player,x; x-ref: $5048 |
| $503D | 9d 00 05 | staSCREEN_RAM_R6C16,x |
| $5040 | a9 07 | lda#VicIIColors.YELLOW |
| $5042 | 9d 00 d9 | staCOLOR_RAM_R6C16,x |
| $5045 | e8 | inx |
| $5046 | e0 08 | cpx#$08 |
| $5048 | d0 f0 | bneb_503A |
| $504A | ad 01 0f | ldacurrent_player_nr |
| $504D | 18 | clc |
| $504E | 69 30 | adc#$30 |
| $5050 | 8d 07 05 | staSCREEN_RAM_R6C23 |
| $5053 | a9 04 | lda#$04; Busy wait delay loop |
| $5055 | 85 49 | stazp_p_tmp_lo |
| $5057 | a2 00 | b_5057ldx#$00; x-ref: $5063 |
| $5059 | a0 00 | b_5059ldy#$00; x-ref: $505F |
| $505B | 88 | b_505Bdey; x-ref: $505C |
| $505C | d0 fd | bneb_505B |
| $505E | ca | dex |
| $505F | d0 f8 | bneb_5059 |
| $5061 | c6 49 | deczp_p_tmp_lo |
| $5063 | d0 f2 | bneb_5057 |
| $5065 | a2 00 | ldx#$00 |
| $5067 | a9 20 | b_5067lda#$20; Clear banner with spaces ; x-ref: $5078 |
| $5069 | 9d 00 05 | staSCREEN_RAM_R6C16,x |
| $506C | ac 03 08 | ldyseason_nr |
| $506F | b9 7c 16 | ldatbl_text_color_seasons,y; One byte per season (0=Summer, 1=Autumn, 2=Winter, 3=Spring) |
| $5072 | 9d 00 d9 | staCOLOR_RAM_R6C16,x |
| $5075 | e8 | inx |
| $5076 | e0 08 | cpx#$08 |
| $5078 | d0 ed | bneb_5067 |
| $507A | 60 | rts |
| $507B | ad 00 0f | j_507Bldanumber_of_players; x-ref: $48B8 |
| $507E | c9 02 | cmp#$02 |
| $5080 | f0 03 | beqb_5085 |
| $5082 | 4c aa 50 | jmpj_50AA |
| $5085 | 4c 75 51 | b_5085jmpj_5175; x-ref: $5080 |
| ; dead code |
| $5088 | | .byte$c9, $01, $f0, $19 |
| $508C | a9 01 | j_508Clda#$01; x-ref: $512D, $519A |
| $508E | 8d 01 0f | stacurrent_player_nr |
| $5091 | a2 00 | j_5091ldx#$00; x-ref: $50CF |
| $5093 | bd 00 08 | b_5093ldalevel_nr,x; x-ref: $50A0 |
| $5096 | 9d 00 0c | staf_0C00,x |
| $5099 | bd 00 09 | ldaf_0900,x |
| $509C | 9d 00 0d | staf_0D00,x |
| $509F | e8 | inx |
| $50A0 | d0 f1 | bneb_5093 |
| $50A2 | 4c 0c 17 | jmpinit_level_screen |
| $50A5 | a9 02 | j_50A5lda#$02; x-ref: $5152, $51BB |
| $50A7 | 8d 01 0f | stacurrent_player_nr |
| $50AA | a2 00 | j_50AAldx#$00; x-ref: $5082, $50C5, $50CD |
| $50AC | bd 00 08 | b_50ACldalevel_nr,x; x-ref: $50B9 |
| $50AF | 9d 00 0a | staf_0A00,x |
| $50B2 | bd 00 09 | ldaf_0900,x |
| $50B5 | 9d 00 0b | staf_0B00,x |
| $50B8 | e8 | inx |
| $50B9 | d0 f1 | bneb_50AC |
| $50BB | 4c 0c 17 | jmpinit_level_screen |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Saves the active player's variables into their backup buffers. |
| ; Player 1 uses $0A00/$0B00, Player 2 uses $0C00/$0D00. |
| ; |
| ; Inputs: number_of_players, current_player_nr |
| ; Outputs: Backup buffers updated |
| ; Side Effects: Copies 2 pages of memory |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| switch_active_player_state |
| $50BE | ad 00 0f | ldanumber_of_players; Check if 2-player game ; x-ref: $16A9 |
| $50C1 | c9 02 | cmp#$02 |
| $50C3 | f0 03 | beqb_50C8 |
| $50C5 | 4c aa 50 | jmpj_50AA |
| $50C8 | ad 01 0f | b_50C8ldacurrent_player_nr; x-ref: $50C3 |
| $50CB | c9 01 | cmp#$01 |
| $50CD | f0 db | beqj_50AA |
| $50CF | 4c 91 50 | jmpj_5091 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Copies a single character from the HUD text data to screen RAM row 1. |
| ; |
| ; Inputs: X (character index) |
| ; Outputs: Screen RAM at $0428,X |
| ; Side Effects: Updates one character of the HUD text on screen. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $50D2 | bd 38 80 | copy_hud_text_rowldaf_8038,x; Copy 1 byte from $8038+X (HUD row text under BASIC ROM) to $0428+X (screen row 1) ; x-ref: $1711 |
| $50D5 | 9d 28 04 | staSCREEN_RAM_R1C0,x |
| $50D8 | 60 | rts |
| ; dead code |
| $50D9 | | .byte$ad, $00, $0f, $c9, $02, $f0, $03, $4c |
| $50E1 | | .byte$03, $18, $ad, $01, $0f, $c9, $01, $f0 |
| $50E9 | | .byte$f6, $a2, $00, $4c, $f8, $50, $08 |
| | .encode |
| | .enc"screen" |
| $50F0 | | txt_player.text"PLAYER ", $ff; x-ref: $503A |
| | .endencode |
| $50F9 | | .byte$49, $00, $00, $ff, $49, $33, $ff |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles a scroll direction change event, triggered from the countdown/wait |
| ; loop at $51E6 once it expires. It checks two state variables to decide how |
| ; to swap the map scroll buffers, then reloads the game level via s170C. |
| ; |
| ; $0F00 = current scroll mode (must be $02 = "switching direction" to act) |
| ; $0F01 = current scroll direction ($01 = scrolling up/reverse, $02 = forward) |
| ; |
| ; If $0F00 != $02: bail out immediately to j1803 (re-init video). |
| ; |
| ; If $0F00 == $02, four paths based on $0F01 + pending car data: |
| ; |
| ; PATH A ($0F01 != $01, pending cars at $0A22/$0A23): |
| ; Set $0F01 = $01, copy work buffer $0800 -> $0C00, |
| ; copy car table $0900 -> $0D00, then reload level (s170C). |
| ; |
| ; PATH B ($0F01 != $01, pending cars at $0A22/$0A23 absent): |
| ; Copy work buffer $0800 -> $0A00, |
| ; copy car table $0900 -> $0B00, then reload level (s170C). |
| ; Set $0F01 = $02. |
| ; |
| ; PATH C ($0F01 == $01, pending cars at $0C22/$0C23): |
| ; Copy work buffer $0800 -> $0A00, |
| ; copy car table $0900 -> $0B00, then reload level (s170C). |
| ; |
| ; PATH D ($0F01 == $01, no pending cars): |
| ; Set $0F01 = $01, copy work buffer $0800 -> $0C00, |
| ; copy car table $0900 -> $0D00, then reload level (s170C). |
| ; |
| ; In all active paths, the 256-byte buffers are fully copied via a DEX/BNE loop. |
| ; |
| ; Inputs: $0F00 = scroll mode flag; $0F01 = direction; $0A22/$0A23, $0C22/$0C23 |
| ; = pending NPC car presence flags; $0800, $0900 = source work buffers |
| ; Outputs: $0A00/$0B00 or $0C00/$0D00 = updated scroll/car buffers; |
| ; $0F01 = updated direction state |
| ; Side Effects: Calls s170C (restore_game_vars + level reload), re-entering the |
| ; main game flow from the top of the level |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| handle_scroll_direction_switch |
| $5100 | ad 00 0f | ldanumber_of_players; $02 = scroll direction-change mode; anything else = bail ; x-ref: $51FC |
| $5103 | c9 02 | cmp#$02 |
| $5105 | f0 03 | beqb_510A |
| $5107 | 4c 03 18 | jmpgame_init_and_loop |
| $510A | ad 01 0f | b_510Aldacurrent_player_nr; $01 = reverse direction, $02 = forward direction ; x-ref: $5105 |
| $510D | c9 01 | cmp#$01 |
| $510F | f0 0d | beqb_511E |
| $5111 | ad 23 0a | ldabuf_a_pending_cars_hi; check if any pending NPC cars in secondary lane buffer |
| $5114 | d0 15 | bneb_512B |
| $5116 | ad 22 0a | ldabuf_a_pending_cars_lo |
| $5119 | d0 10 | bneb_512B |
| $511B | 4c 03 18 | jmpgame_init_and_loop |
| $511E | ad 23 0c | b_511Eldabuf_c_pending_cars_hi; direction is $01: check $0C22/$0C23 pending cars instead ; x-ref: $510F |
| $5121 | d0 2d | bneb_5150 |
| $5123 | ad 22 0c | ldabuf_c_pending_cars_lo |
| $5126 | d0 28 | bneb_5150 |
| $5128 | 4c 03 18 | jmpgame_init_and_loop |
| $512B | a2 00 | b_512Bldx#$00; PATH A: pending cars present in lane A; set dir=$01, swap to C/D buffers ; x-ref: $5114, $5119 |
| $512D | 4c 8c 50 | jmpj_508C |
| ; dead code |
| $5130 | | .byte$9d, $00, $0c, $bd, $00, $09, $9d, $00 |
| $5138 | | .byte$0d, $e8, $d0, $f1, $a2, $00, $4c, $a5 |
| $5140 | | .byte$50, $9d, $00, $08, $bd, $00, $0b, $9d |
| $5148 | | .byte$00, $09, $e8, $d0, $f1, $4c, $0c, $17 |
| $5150 | a2 00 | b_5150ldx#$00; PATH C: direction $01, pending cars in C lane; swap to A/B buffers ; x-ref: $5121, $5126 |
| $5152 | 4c a5 50 | jmpj_50A5 |
| ; dead code |
| $5155 | | .byte$9d, $00, $0a, $bd, $00, $09, $9d, $00 |
| $515D | | .byte$0b, $e8, $d0, $f1, $a2, $00, $4c, $8c |
| $5165 | | .byte$50, $9d, $00, $08, $bd, $00, $0d, $9d |
| $516D | | .byte$00, $09, $e8, $d0, $f1, $4c, $0c, $17 |
| $5175 | ad 01 0f | j_5175ldacurrent_player_nr; x-ref: $5085 |
| $5178 | c9 01 | cmp#$01 |
| $517A | f0 21 | beqb_519D |
| $517C | ad 23 0a | ldabuf_a_pending_cars_hi |
| $517F | d0 19 | bneb_519A |
| $5181 | ad 22 0a | ldabuf_a_pending_cars_lo |
| $5184 | d0 14 | bneb_519A |
| $5186 | a2 00 | ldx#$00 |
| $5188 | bd 00 08 | b_5188ldalevel_nr,x; x-ref: $5195 |
| $518B | 9d 00 0c | staf_0C00,x |
| $518E | bd 00 09 | ldaf_0900,x |
| $5191 | 9d 00 0d | staf_0D00,x |
| $5194 | e8 | inx |
| $5195 | d0 f1 | bneb_5188 |
| $5197 | 4c 0c 17 | jmpinit_level_screen |
| $519A | 4c 8c 50 | b_519Ajmpj_508C; x-ref: $517F, $5184 |
| $519D | ad 23 0c | b_519Dldabuf_c_pending_cars_hi; x-ref: $517A |
| $51A0 | d0 19 | bneb_51BB |
| $51A2 | ad 22 0c | ldabuf_c_pending_cars_lo |
| $51A5 | d0 14 | bneb_51BB |
| $51A7 | a2 00 | ldx#$00 |
| $51A9 | bd 00 08 | b_51A9ldalevel_nr,x; x-ref: $51B6 |
| $51AC | 9d 00 0a | staf_0A00,x |
| $51AF | bd 00 09 | ldaf_0900,x |
| $51B2 | 9d 00 0b | staf_0B00,x |
| $51B5 | e8 | inx |
| $51B6 | d0 f1 | bneb_51A9 |
| $51B8 | 4c 0c 17 | jmpinit_level_screen |
| $51BB | 4c a5 50 | b_51BBjmpj_50A5; x-ref: $51A0, $51A5 |
| $51BE | 20 71 3e | j_51BEjsrreset_voice1_state; x-ref: $51DE |
| $51C1 | a9 00 | lda#$00 |
| $51C3 | 8d 06 d4 | sta$d406; Voice 1: Sustain / Release Cycle Control |
| $51C6 | a9 1d | lda#$1d |
| $51C8 | 8d 05 d4 | sta$d405; Voice 1: Attack / Decay Cycle Control |
| $51CB | a9 01 | lda#$01 |
| $51CD | 8d 01 d4 | sta$d401; Voice 1: Frequency Control - High-Byte |
| $51D0 | a9 12 | lda#$12 |
| $51D2 | 8d 00 d4 | sta$d400; Voice 1: Frequency Control - Low-Byte |
| $51D5 | a9 81 | lda#$81 |
| $51D7 | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| $51DA | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Sets sprite 0's image pointer to the provided frame and plays a noise explosion. |
| ; |
| ; Inputs: A = Sprite frame pointer value |
| ; Outputs: None |
| ; Side Effects: Updates sprite_ptr_0, resets and configures SID Voice 1 for noise |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| set_sprite0_and_play_noise |
| $51DB | 8d f8 07 | stasprite_ptr_0; Set sprite 0 frame pointer ; x-ref: $4846 |
| $51DE | 4c be 51 | jmpj_51BE; Play noise effect on Voice 1 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Polls the joystick for a UP movement with a timeout loop. |
| ; If UP is pressed (bit 0 is 0), or if the timeout expires, it proceeds |
| ; to handle the scroll direction switch. |
| ; |
| ; Inputs: joy_state |
| ; Outputs: None |
| ; Side Effects: Delays execution, calls handle_scroll_direction_switch |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| poll_joy_for_scroll_switch |
| $51E1 | a9 20 | lda#$20; Set timeout to $20 ; x-ref: $1E0E |
| $51E3 | 8d da 08 | stajoy_poll_timeout |
| $51E6 | a2 00 | b_51E6ldx#$00; x-ref: $51FA |
| $51E8 | a0 00 | b_51E8ldy#$00; x-ref: $51F5 |
| $51EA | ad f5 00 | b_51EAlda@w zp_joy_state; Read joystick state ; x-ref: $51F2 |
| $51ED | 29 01 | and#$01; Check bit 0 (UP) |
| $51EF | f0 0b | beqb_51FC; If 0 (pressed), exit loop |
| $51F1 | 88 | dey |
| $51F2 | d0 f6 | bneb_51EA |
| $51F4 | ca | dex |
| $51F5 | d0 f1 | bneb_51E8 |
| $51F7 | ce da 08 | decjoy_poll_timeout; Decrement timeout |
| $51FA | d0 ea | bneb_51E6 |
| $51FC | 4c 00 51 | b_51FCjmphandle_scroll_direction_switch; Proceed to handle scroll direction switch ; x-ref: $51EF |
| ; dead code |
| $51FF | | .byte$ff, $ad, $05, $08, $d0, $01, $60, $ae |
| $5207 | | .byte$06, $08, $a9, $00, $8d, $04, $d4, $8d |
| $520F | | .byte$05, $d4, $8d, $06, $d4, $bd, $50, $52 |
| $5217 | | .byte$8d, $01, $d4, $bd, $60, $52, $8d, $00 |
| $521F | | .byte$d4, $a9, $09, $8d, $05, $d4, $a9, $0f |
| $5227 | | .byte$8d, $06, $d4, $a9, $11, $8d, $04, $d4 |
| $522F | | .byte$60 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Updates the state of an enemy sprite and triggers a crash sound effect. |
| ; Returns 1 in the accumulator. |
| ; |
| ; Inputs: A = New enemy sprite state, X = Enemy sprite index |
| ; Outputs: A = 1 |
| ; Side Effects: Updates tbl_enemy_sprite_state, plays crash SFX |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| set_collision_state_and_play_sfx |
| $5230 | 9d 0c 09 | statbl_enemy_sprite_state,x; Update enemy state for index X ; x-ref: $3A4F |
| $5233 | 20 d1 3e | jsrplay_crash_sfx; Play the crash sound effect |
| $5236 | a9 01 | lda#$01; Return 1 to indicate success/state change |
| $5238 | 60 | r_5238rts; x-ref: $523D |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Main-loop input synchronizer. Called every frame from j4FB0. |
| ; |
| ; Ties the main loop's execution pace to player key input: |
| ; - If any key is currently held (key_scan != $7F): returns immediately, |
| ; allowing the game loop to run at full speed. |
| ; - If no key is held (key_scan == $7F): spins through a full |
| ; press -> release -> press cycle before returning. |
| ; |
| ; The CIA keyboard scanner (j56E2) runs inside the IRQ, so key_scan is |
| ; updated even during the spin-waits — sprite animation continues unaffected. |
| ; |
| ; Phase 1 ($5239): bail immediately if a key is already held |
| ; Phase 2 ($523F): spin until any key is pressed |
| ; Phase 3 ($5245): spin until key is released |
| ; Phase 4 (j5270): spin until key is pressed again, then return |
| ; |
| ; Inputs: key_scan ($C5) |
| ; Outputs: A = key_scan on early exit; undefined on full wait path |
| ; Side Effects: Stalls main loop execution until a fresh keypress cycle |
| ; completes when no key is being held |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $5239 | a5 c5 | sync_to_keypressldazp_key_scan; Phase 1: key already held? Return immediately ; x-ref: $4FB6 |
| $523B | c9 7f | cmp#$7f; $7F = no key; wait for release |
| $523D | d0 f9 | bner_5238 |
| $523F | a5 c5 | b_523Fldazp_key_scan; Phase 2: spin until any key pressed ; x-ref: $5243 |
| $5241 | c9 7f | cmp#$7f; $7F = no key; loop until a key is pressed |
| $5243 | f0 fa | beqb_523F |
| $5245 | a5 c5 | b_5245ldazp_key_scan; Phase 3: spin until key released ; x-ref: $5249 |
| $5247 | c9 7f | cmp#$7f; $7F = no key; wait for release |
| $5249 | d0 fa | bneb_5245 |
| $524B | 4c 70 52 | jmpj_5270; Phase 4: wait for second press, then return |
| $524E | | .byte$ea, $ea |
| ; posibly dead data. referenced only by dead code |
| unused_sid_freq_hi_tbl |
| $5250 | | .byte>$0893, >$099f, >$0acd, >$0b72, >$0cd8 |
| $5255 | | .byte>$0e6b, >$102f, >$1125, >$133f, >$083f |
| $525A | | .byte>$0025, >$8845, >$d068, >$fd8c, >$cab3 |
| $525F | | .byte>$d08c |
| unused_sid_freq_lo_tbl |
| $5260 | | .byte<$0893, <$099f, <$0acd, <$0b72, <$0cd8 |
| $5265 | | .byte<$0e6b, <$102f, <$1125, <$133f, <$083f |
| $526A | | .byte<$0025, <$8845, <$d068, <$fd8c, <$cab3 |
| $526F | | .byte<$d08c |
| $5270 | a5 c5 | j_5270ldazp_key_scan; Phase 4: spin until key pressed, return (shared entry point) ; x-ref: $524B, $5274 |
| $5272 | c9 7f | cmp#$7f; $7F = no key; wait for press |
| $5274 | f0 fa | beqj_5270; Loop while no key |
| $5276 | 60 | rts |
| $5277 | | .byte$08, $ff, $00, $ff, $00, $02, $00, $ff |
| $527F | | .byte$00, $40, $ff, $00, $ff, $00, $ff, $00 |
| $5287 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $528F | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $5297 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $529F | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52A7 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52AF | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52B7 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52BF | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52C7 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52CF | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52D7 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52DF | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52E7 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52EF | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52F7 | | .byte$ff, $00, $ff, $00, $ff, $00, $ff, $00 |
| $52FF | | .byte$ff |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Handles user input during the main menu / selection screen. |
| ; This routine monitors a specific key press (flagged as $F7 in the keyboard |
| ; matrix byte $C5, likely the F1 key or spacebar) to increment a 2-digit number |
| ; stored in $49 and $4A as ASCII/Screen Code characters. The number cycles |
| ; from '01' up to '16', and wraps back around. It then renders those digits directly |
| ; to Video RAM at $0651 and $0652 to provide visual feedback of the selection |
| ; (e.g., selecting a starting level or difficulty). |
| ; |
| ; Inputs: $C5 (Current Key Pressed) |
| ; Outputs: None |
| ; Side Effects: Modifies $49 (units), $4A (tens), and Video RAM $0651-$0652. |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| handle_menu_selection_input |
| $5300 | a5 49 | ldazp_p_tmp_lo; x-ref: $3FFA |
| $5302 | 8d 52 06 | staSCREEN_RAM_R14C34 |
| $5305 | a5 4a | ldazp_p_tmp_hi |
| $5307 | 8d 51 06 | staSCREEN_RAM_R14C33 |
| $530A | a5 c5 | ldazp_key_scan |
| $530C | c9 f7 | cmp#$f7; $F7 = %11110111 (bit 3 clear) |
| $530E | f0 01 | beqb_5311 |
| $5310 | 60 | rts |
| $5311 | ee 01 12 | b_5311inclevel_nr_self_modifiying; x-ref: $530E |
| $5314 | ad 01 12 | ldalevel_nr_self_modifiying |
| $5317 | c9 10 | cmp#$10 |
| $5319 | d0 05 | bneb_5320 |
| $531B | a9 00 | lda#$00 |
| $531D | 8d 01 12 | stalevel_nr_self_modifiying |
| $5320 | e6 49 | b_5320inczp_p_tmp_lo; x-ref: $5319 |
| $5322 | a5 49 | ldazp_p_tmp_lo |
| $5324 | c9 3a | cmp#$3a |
| $5326 | d0 06 | bneb_532E |
| $5328 | a9 30 | lda#$30 |
| $532A | 85 49 | stazp_p_tmp_lo |
| $532C | e6 4a | inczp_p_tmp_hi |
| $532E | a5 4a | b_532Eldazp_p_tmp_hi; x-ref: $5326 |
| $5330 | c9 31 | cmp#$31 |
| $5332 | d0 0e | bneb_5342 |
| $5334 | a5 49 | ldazp_p_tmp_lo |
| $5336 | c9 37 | cmp#$37 |
| $5338 | d0 08 | bneb_5342 |
| $533A | a9 31 | lda#$31 |
| $533C | 85 49 | stazp_p_tmp_lo |
| $533E | a9 30 | lda#$30 |
| $5340 | 85 4a | stazp_p_tmp_hi |
| $5342 | a5 49 | b_5342ldazp_p_tmp_lo; x-ref: $5332, $5338 |
| $5344 | 8d 52 06 | staSCREEN_RAM_R14C34 |
| $5347 | a5 4a | ldazp_p_tmp_hi |
| $5349 | 8d 51 06 | staSCREEN_RAM_R14C33 |
| $534C | a5 c5 | b_534Cldazp_key_scan; x-ref: $5350 |
| $534E | c9 f7 | cmp#$f7; $F7 held — wait for release |
| $5350 | f0 fa | beqb_534C |
| $5352 | 60 | rts |
| | .encode |
| | .enc"screen" |
| $5353 | | txt_bonus_10000.text"BONUS 10000", $ff, "@"; x-ref: $5367 |
| | .endencode |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Displays a "BONUS 10000" message and awards bonus points. |
| ; This routine copies the "BONUS 10000" text to the screen ($0756 area) and colors |
| ; it purple ($04). It then calls the score increment routine twice to award the |
| ; points, performs a nested delay loop to leave the text on-screen momentarily, |
| ; and finally jumps back to the main flow. |
| ; |
| ; Inputs: None |
| ; Outputs: None |
| ; Side Effects: Updates Screen RAM, Color RAM, Score array, and delays execution. |
| ; Bugs: Message says "BONUS 10000", but it actually increases it by 100000 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $5360 | a9 00 | award_bonus_scorelda#$00; x-ref: $157E |
| $5362 | 8d 00 08 | stalevel_nr |
| $5365 | a2 00 | ldx#$00 |
| $5367 | bd 53 53 | b_5367ldatxt_bonus_10000,x; x-ref: $5375 |
| $536A | 9d 56 07 | staSCREEN_RAM_R21C14,x |
| $536D | a9 04 | lda#VicIIColors.PURPLE |
| $536F | 9d 56 db | staCOLOR_RAM_R21C14,x |
| $5372 | e8 | inx |
| $5373 | e0 0b | cpx#$0b |
| $5375 | d0 f0 | bneb_5367 |
| $5377 | 20 a7 15 | jsrincrement_score_by_50000; BUG: Message says "BONUS 10000", but it actually increments 100,000 |
| $537A | 20 a7 15 | jsrincrement_score_by_50000 |
| $537D | ea | nop |
| $537E | ea | nop |
| $537F | ea | nop |
| $5380 | ea | nop |
| $5381 | ea | nop |
| $5382 | ea | nop |
| $5383 | a9 08 | lda#$08 |
| $5385 | 85 49 | stazp_p_tmp_lo |
| $5387 | a2 00 | b_5387ldx#$00; x-ref: $5393 |
| $5389 | a0 00 | b_5389ldy#$00; x-ref: $538F |
| $538B | 88 | b_538Bdey; x-ref: $538C |
| $538C | d0 fd | bneb_538B |
| $538E | ca | dex |
| $538F | d0 f8 | bneb_5389 |
| $5391 | c6 49 | deczp_p_tmp_lo |
| $5393 | d0 f2 | bneb_5387 |
| $5395 | 4c 81 15 | jmpb_1581 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; SFX Engine Voice 1 (Engine Sound) Handler |
| ; |
| ; Initializes and modulates Voice 1 on the SID to create a continuous sound |
| ; while sfx_voice_1_en is non-zero. When zeroed, it resets the local state. |
| ; |
| ; Inputs: sfx_voice_1_en ($0805) - Enable flag for the Voice 1 SFX |
| ; Outputs: sfx_voice_1_state ($7080), sfx_voice_1_freq_lo ($7081), |
| ; sfx_voice_1_freq_mod ($7082) |
| ; Side Effects: Updates Voice 1 registers (Frequency, Control, Attack/Decay, Sustain/Release) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $5398 | ad 05 08 | irq_handler_musicldaplayer_is_jumping; x-ref: $1291, $1296 |
| $539B | f0 56 | beqsfx_voice_1_reset; If sf_voice_1_en is clear, reset state |
| $539D | ae 80 70 | ldxsfx_voice_1_state |
| $53A0 | d0 21 | bnesfx_voice_1_modulate; If state > 0 (already playing), branch to modulation |
| $53A2 | 8e 81 70 | stxsfx_voice_1_freq_lo; Clear internal freq_lo component |
| $53A5 | 8e 00 d4 | stx$d400; Clear SID Voice 1 frequency low; Voice 1: Frequency Control - Low-Byte |
| $53A8 | 8e 01 d4 | stx$d401; Clear SID Voice 1 frequency high; Voice 1: Frequency Control - High-Byte |
| $53AB | 8e 05 d4 | stx$d405; Voice 1: Attack / Decay Cycle Control |
| $53AE | 8e 04 d4 | stx$d404; Voice 1: Control Register |
| $53B1 | e8 | inx; Set state to 1 (initialized) |
| $53B2 | 8e 80 70 | stxsfx_voice_1_state |
| $53B5 | e8 | inx |
| $53B6 | 8e 82 70 | stxsfx_voice_1_freq_mod; Set mod factor to 2 |
| $53B9 | a9 f4 | lda#$f4; Sustain = $F, Release = $4 |
| $53BB | 8d 06 d4 | sta$d406; Voice 1: Sustain / Release Cycle Control |
| $53BE | a9 11 | lda#$11; Gate ON + Triangle Wave |
| $53C0 | 8d 04 d4 | sta$d404; Voice 1: Control Register |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Modulates the frequency of Voice 1 by adding the frequency modifier. |
| ; If the frequency modifier is negative (falling pitch), it handles the bounce effect. |
| ; |
| ; Inputs: sfx_voice_1_state, sfx_voice_1_freq_lo, sfx_voice_1_freq_mod |
| ; Outputs: A = new frequency mod or voice state |
| ; Side Effects: May gate off Voice 1 if modulation ends |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $53C3 | 30 2b | sfx_voice_1_modulatebmib_53F0; Skip modulation if state is $80 (releasing) ; x-ref: $53A0 |
| $53C5 | ad 81 70 | ldasfx_voice_1_freq_lo |
| $53C8 | 18 | clc |
| $53C9 | 6d 82 70 | adcsfx_voice_1_freq_mod; Add mod factor to frequency low byte |
| $53CC | d0 1c | bnesfx_voice_1_store_freq |
| $53CE | ad 82 70 | ldasfx_voice_1_freq_mod |
| $53D1 | 10 0c | bplsfx_voice_1_bounce |
| $53D3 | a9 10 | lda#$10 |
| $53D5 | 8d 04 d4 | sta$d404; Gate OFF Voice 1; Voice 1: Control Register |
| $53D8 | a9 80 | lda#$80 |
| $53DA | 8d 80 70 | stasfx_voice_1_state; Set state to releasing ($80) |
| $53DD | d0 11 | bneb_53F0 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Reverses the direction of the frequency modulation to create a bounce effect. |
| ; The modifier is negated and the frequency wraps around to $FE. |
| ; |
| ; Inputs: sfx_voice_1_freq_mod |
| ; Outputs: sfx_voice_1_freq_mod |
| ; Side Effects: Updates frequency modifier, prepares for store |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $53DF | a9 00 | sfx_voice_1_bouncelda#$00; x-ref: $53D1 |
| $53E1 | 38 | sec |
| $53E2 | ed 82 70 | sbcsfx_voice_1_freq_mod; Negate the frequency modifier |
| $53E5 | 8d 82 70 | stasfx_voice_1_freq_mod; Store negated modifier (reverse direction) |
| $53E8 | a9 fe | lda#$fe; Set frequency to wrap-around value ($FE) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Stores the newly calculated frequency for Voice 1 into memory and the SID. |
| ; The high byte of the Voice 1 frequency is updated directly. |
| ; |
| ; Inputs: A = new frequency value |
| ; Outputs: sfx_voice_1_freq_lo |
| ; Side Effects: Updates SID Voice 1 frequency high register ($D401) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| sfx_voice_1_store_freq |
| $53EA | 8d 81 70 | stasfx_voice_1_freq_lo; Update internal frequency low byte state ; x-ref: $53CC |
| $53ED | 8d 01 d4 | sta$d401; Update SID Voice 1 frequency high; Voice 1: Frequency Control - High-Byte |
| $53F0 | 4c d0 54 | b_53F0jmpj_54D0; Chain to next IRQ routine ; x-ref: $53C3, $53DD, $53F8 |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Resets the Voice 1 SFX state to 0, effectively turning off the sound effect |
| ; processing for this voice. |
| ; |
| ; Inputs: None |
| ; Outputs: sfx_voice_1_state = 0 |
| ; Side Effects: Clears the Voice 1 state variable |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $53F3 | a9 00 | sfx_voice_1_resetlda#$00; Clear Accumulator ; x-ref: $539B |
| $53F5 | 8d 80 70 | stasfx_voice_1_state; Reset Voice 1 state to 0 |
| $53F8 | f0 f6 | beqb_53F0 |
| $53FA | 00 | brk |
| $53FB | 00 | brk |
| $53FC | 00 | brk |
| $53FD | 00 | brk |
| $53FE | 00 | brk |
| $53FF | 00 | brk |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; IRQ-driven melody player for SID Voices 2 & 3. |
| ; |
| ; Called every IRQ frame. Steps through a looping note sequence in the melody |
| ; table at $5500 using a self-modifying pointer ($5445/$5446). A rate-limiting |
| ; timer controls the pace: 8 ticks per note, then a 3-tick gate-off gap. |
| ; Notes alternate between Voice 2 and Voice 3 so the prior note's release |
| ; envelope can finish on one voice while the next note starts on the other. |
| ; |
| ; Table encoding: |
| ; $30 = rest (silent tick, exit immediately) |
| ; $00-$2F = pitch index into sid_freq2_lo/hi_tbl |
| ; >= $40 = end-of-sequence; wrap pointer back to $5500 |
| ; |
| ; Key $BF toggles playback on/off; pressing it immediately gates both voices. |
| ; Waveform: triangle ($21), A=0/D=0, Sustain=$B, Release=$A. |
| ; |
| ; Inputs: $C5 (key scan), sfx_prev_key, sfx_v23_en, sfx_v23_timer, |
| ; sfx_v23_idx, sfx_v23_toggle; self-mod melody ptr at $5445/$5446 |
| ; Outputs: SID Voice 2 regs ($D407-$D40D), Voice 3 regs ($D40E-$D414) |
| ; Side Effects: Advances self-modifying melody pointer through $5500+; |
| ; updates sfx_prev_key, sfx_v23_en, sfx_v23_timer, |
| ; sfx_v23_idx, sfx_v23_toggle |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| $5400 | a5 c5 | irq_handler_voice23ldazp_key_scan; Load current key pressed ; x-ref: $54DB, $54E3 |
| $5402 | cd 26 54 | cmpsfx_prev_key |
| $5405 | f0 17 | beqb_541E; If key unchanged, skip to processing |
| $5407 | 8d 26 54 | stasfx_prev_key |
| $540A | c9 bf | cmp#$bf; Check if F5 was pressed |
| $540C | d0 10 | bneb_541E |
| $540E | a9 20 | lda#$20 |
| $5410 | 8d 0b d4 | sta$d40b; Gate OFF Voice 2; Voice 2: Control Register |
| $5413 | 8d 12 d4 | sta$d412; Gate OFF Voice 3; Voice 3: Control Register |
| $5416 | ad 27 54 | ldasfx_v23_en; Toggle the enable flag |
| $5419 | 49 01 | eor#$01 |
| $541B | 8d 27 54 | stasfx_v23_en |
| $541E | ad 27 54 | b_541Eldasfx_v23_en; x-ref: $5405, $540C |
| $5421 | d0 0d | bneb_5430; If not enabled, skip processing |
| $5423 | 4c e2 56 | b_5423jmpscan_keyboard_joystick; x-ref: $5433, $5461, $5488, $54A0 |
| $5426 | | sfx_prev_key.byte$40; x-ref: $5402, $5407 |
| $5427 | | sfx_v23_en.byte$01; x-ref: $5416, $541B, $541E |
| $5428 | | sfx_v23_timer.byte$03; x-ref: $5430, $5441, $54A7 |
| $5429 | | sfx_v23_idx.byte$01; x-ref: $5435, $543C, $54A2 |
| $542A | | sfx_v23_toggle.byte$00; x-ref: $546B, $54AC, $54B3, $54BC |
| $542B | 00 | .byte$00 |
| $542C | ff | .byte$ff |
| $542D | 00 | .byte$00 |
| $542E | ff | .byte$ff |
| $542F | 00 | .byte$00 |
| $5430 | ce 28 54 | b_5430decsfx_v23_timer; Decrement wait timer ; x-ref: $5421 |
| $5433 | d0 ee | bneb_5423; If timer hasn't expired, exit |
| $5435 | ad 29 54 | ldasfx_v23_idx; Check phase: 0=play next note, 1=gate-off |
| $5438 | f0 68 | beqb_54A2; idx=1: enter gate-off phase for current voice |
| $543A | a0 00 | ldy#$00 |
| $543C | 8c 29 54 | stysfx_v23_idx; Reset to play phase (idx=0) |
| $543F | a9 08 | lda#$08 |
| $5441 | 8d 28 54 | stasfx_v23_timer; 8 IRQ ticks per note |
| melody_lo =*+$01 ; x-ref: $5447, $545A |
| melody_hi =*+$02 ; x-ref: $544C, $5455 |
| $5444 | ad 00 55 | b_5444ldamelody_tbl; Self-modifying LDA; ptr lo=$5445, hi=$5446 walk melody table ; x-ref: $545D |
| $5447 | ee 45 54 | incmelody_lo; Advance melody ptr low byte |
| $544A | d0 03 | bneb_544F |
| $544C | ee 46 54 | incmelody_hi; Page overflow: advance ptr high byte |
| $544F | c9 40 | b_544Fcmp#$40; >= $40 = end-of-sequence sentinel ; x-ref: $544A |
| $5451 | 90 0c | bccb_545F |
| $5453 | a9 55 | lda#$55; Reset ptr hi to $55 (back to $5500) |
| $5455 | 8d 46 54 | stamelody_hi |
| $5458 | a9 00 | lda#$00 |
| $545A | 8d 45 54 | stamelody_lo; Reset ptr lo to $00 |
| $545D | f0 e5 | beqb_5444; Z set by lda #$00; always branches — re-read first note |
| $545F | c9 30 | b_545Fcmp#$30; $30 = rest note ; x-ref: $5451 |
| $5461 | f0 c0 | beqb_5423; Rest: exit without playing |
| $5463 | aa | tax; Load pitch index into X |
| $5464 | bd 80 56 | ldasid_freq_hi_tbl,x; Read frequency high byte into A |
| $5467 | a8 | tay |
| $5468 | bd 40 56 | ldasid_freq_lo_tbl,x; Read frequency low byte into A |
| $546B | ae 2a 54 | ldxsfx_v23_toggle; Check voice toggle flag |
| $546E | f0 1a | beqb_548A; If 0, use Voice 3. If !0, use Voice 2 |
| $5470 | a2 00 | ldx#$00 |
| $5472 | 8e 0b d4 | stx$d40b; Voice 2: Control Register |
| $5475 | 8d 07 d4 | sta$d407; Voice 2: Frequency Control - Low-Byte |
| $5478 | 8c 08 d4 | sty$d408; Voice 2: Frequency Control - High-Byte |
| $547B | 8e 0c d4 | stx$d40c; Voice 2: Attack / Decay Cycle Control |
| $547E | a9 ba | lda#$ba |
| $5480 | 8d 0d d4 | sta$d40d; Voice 2: Sustain / Release Cycle Control |
| $5483 | a9 21 | lda#$21 |
| $5485 | 8d 0b d4 | sta$d40b; Voice 2: Control Register |
| $5488 | d0 99 | bneb_5423 |
| $548A | 8e 12 d4 | b_548Astx$d412; x-ref: $546E Voice 3: Control Register |
| $548D | 8d 0e d4 | sta$d40e; Voice 3: Frequency Control - Low-Byte |
| $5490 | 8c 0f d4 | sty$d40f; Voice 3: Frequency Control - High-Byte |
| $5493 | 8e 13 d4 | stx$d413; Voice 3: Attack / Decay Cycle Control |
| $5496 | a9 ba | lda#$ba |
| $5498 | 8d 14 d4 | sta$d414; Voice 3: Sustain / Release Cycle Control |
| $549B | a9 21 | lda#$21 |
| $549D | 8d 12 d4 | sta$d412; Voice 3: Control Register |
| $54A0 | d0 81 | bneb_5423 |
| $54A2 | ee 29 54 | b_54A2incsfx_v23_idx; x-ref: $5438 |
| $54A5 | a9 03 | lda#$03 |
| $54A7 | 8d 28 54 | stasfx_v23_timer; 3-tick release gap between notes |
| $54AA | a9 20 | lda#$20; %00100000 = triangle wave, gate OFF |
| $54AC | ae 2a 54 | ldxsfx_v23_toggle; Which voice was just playing? |
| $54AF | f0 0b | beqb_54BC; toggle=0: V3 was playing → gate off V3 |
| $54B1 | a2 00 | ldx#$00 |
| $54B3 | 8e 2a 54 | stxsfx_v23_toggle; Clear toggle → next note plays on V3 |
| $54B6 | 8d 0b d4 | sta$d40b; Voice 2: Control Register |
| $54B9 | 4c e2 56 | b_54B9jmpscan_keyboard_joystick; x-ref: $54C2 |
| $54BC | ee 2a 54 | b_54BCincsfx_v23_toggle; Set toggle (non-zero) → next note plays on V2 ; x-ref: $54AF |
| $54BF | 8d 12 d4 | sta$d412; Gate off Voice 3 (it was playing); Voice 3: Control Register |
| $54C2 | d0 f5 | bneb_54B9 |
| $54C4 | | .fill12, $00 |
| $54D0 | ad 00 d0 | j_54D0lda$d000; x-ref: $53F0 Sprite 0 X Pos |
| $54D3 | c9 0c | cmp#$0c |
| $54D5 | 90 07 | bccb_54DE |
| $54D7 | c9 18 | cmp#$18 |
| $54D9 | 90 0b | bccb_54E6 |
| $54DB | 4c 00 54 | jmpirq_handler_voice23 |
| $54DE | a9 ff | b_54DElda#$ff; x-ref: $54D5 |
| $54E0 | 8d 00 d0 | b_54E0sta$d000; x-ref: $54E8 Sprite 0 X Pos |
| $54E3 | 4c 00 54 | jmpirq_handler_voice23 |
| $54E6 | a9 18 | b_54E6lda#$18; x-ref: $54D9 |
| $54E8 | d0 f6 | bneb_54E0 |
| $54EA | | .fill22, $00 |
| $5500 | | melody_tbl.byte$30, $12, $30, $0e, $10, $12, $30, $0e; x-ref: $5444 |
| $5508 | | .byte$12, $30, $10, $0e, $30, $09, $30, $0a |
| $5510 | | .byte$0b, $0e, $10, $13, $30, $0e, $10, $0e |
| $5518 | | .byte$10, $13, $30, $10, $30, $12, $0e, $10 |
| $5520 | | .byte$12, $30, $0e, $12, $30, $10, $0e, $30 |
| $5528 | | .byte$09, $30, $13, $30, $10, $30, $0e, $30 |
| $5530 | | .byte$0b, $30, $0b, $0b, $30, $02, $04, $07 |
| $5538 | | .byte$06, $30, $12, $0e, $10, $12, $30, $0e |
| $5540 | | .byte$12, $30, $10, $0e, $30, $09, $30, $0a |
| $5548 | | .byte$0b, $0e, $10, $13, $30, $0e, $10, $0e |
| $5550 | | .byte$10, $13, $30, $10, $30, $0c, $30, $0d |
| $5558 | | .byte$30, $13, $30, $10, $30, $0e, $30, $09 |
| $5560 | | .byte$30, $13, $30, $30, $12, $30, $30, $13 |
| $5568 | | .fill12, $30 |
| $5574 | | .byte$13, $10, $0e, $10, $0c, $10, $0b, $10 |
| $557C | | .byte$09, $10, $07, $10, $05, $10, $0e, $0c |
| $5584 | | .byte$0e, $0e, $0c, $0e, $0b, $0e, $09, $0e |
| $558C | | .byte$07, $0e, $05, $0e, $04, $0e, $0c, $0b |
| $5594 | | .byte$0c, $0c, $0b, $0c, $09, $0c, $07, $0c |
| $559C | | .byte$05, $0c, $04, $0c, $03, $0c, $0b, $09 |
| $55A4 | | .byte$0b, $0b, $09, $0b, $08, $0b, $06, $0b |
| $55AC | | .byte$04, $0b, $02, $0b, $00, $0b, $09, $07 |
| $55B4 | | .byte$09, $0e, $0c, $0c, $10, $0e, $0e, $13 |
| $55BC | | .byte$12, $13, $0e, $0b, $07, $09, $0b, $0c |
| $55C4 | | .byte$0e, $10, $0e, $0c, $0b, $09, $0b, $07 |
| $55CC | | .byte$06, $07, $09, $02, $06, $09, $0c, $0b |
| $55D4 | | .byte$09, $0b, $07, $09, $0b, $0e, $0c, $0c |
| $55DC | | .byte$10, $0e, $0e, $13, $12, $13, $0e, $0b |
| $55E4 | | .byte$07, $09, $0b, $04, $0e, $0c, $0b, $09 |
| $55EC | | .byte$07, $02, $07, $06, $07, $0b, $0e, $13 |
| $55F4 | | .byte$0e, $0b, $07, $0b, $0e, $11, $0e, $0b |
| $55FC | | .byte$07, $0b, $0e, $10, $0c, $09, $06, $09 |
| $5604 | | .byte$0c, $0e, $0b, $07, $04, $07, $0b, $0c |
| $560C | | .byte$09, $06, $02, $06, $09, $0c, $0b, $09 |
| $5614 | | .byte$07, $0b, $0e, $13 |
| $5618 | | .fill8, $30 |
| $5620 | | .byte$80 |
| $5621 | | .byte$00, $ff, $00, $ff, $00, $ff, $00, $ff |
| $5629 | | .byte$00, $ff, $00, $ff, $00, $ff, $00, $ff |
| $5631 | | .byte$00, $ff, $00, $ff, $00, $ff, $00, $ff |
| $5639 | | .byte$00, $ff, $00, $02, $00, $ff, $00 |
| $5640 | | sid_freq_lo_tbl.byte<$0893, <$0915, <$099f, <$0a3c, <$0acd; x-ref: $5468 |
| $5645 | | .byte<$0b72, <$0c20, <$0cd8, <$0d9c, <$0e6b |
| $564A | | .byte<$0f66, <$102f, <$1125, <$122a, <$133f |
| $564F | | .byte<$1464, <$159a, <$16e3, <$183f, <$19b1 |
| $5654 | | .byte<$1b38, <$1cd6, <$1e8d, <$205e, <$224b |
| $5659 | | .byte<$2455, <$267e, <$28c8, <$2b34, <$2dc6 |
| $565E | | .byte<$307f, <$3361, <$366f, <$39ac, <$3d7e |
| $5663 | | .byte<$40bc, <$4495, <$0000, <$0000, <$0000 |
| $5668 | | .byte<$0000, <$0000, <$0000, <$0000, <$0000 |
| $566D | | .byte<$0000, <$0000, <$0000, <$0000, <$0000 |
| $5672 | | .byte<$0000, <$0000, <$0000, <$0000, <$0000 |
| $5677 | | .byte<$0000, <$0000, <$0000, <$0000, <$0000 |
| $567C | | .byte<$0000, <$0000, <$0000, <$0000 |
| $5680 | | sid_freq_hi_tbl.byte>$0893, >$0915, >$099f, >$0a3c, >$0acd; x-ref: $5464 |
| $5685 | | .byte>$0b72, >$0c20, >$0cd8, >$0d9c, >$0e6b |
| $568A | | .byte>$0f66, >$102f, >$1125, >$122a, >$133f |
| $568F | | .byte>$1464, >$159a, >$16e3, >$183f, >$19b1 |
| $5694 | | .byte>$1b38, >$1cd6, >$1e8d, >$205e, >$224b |
| $5699 | | .byte>$2455, >$267e, >$28c8, >$2b34, >$2dc6 |
| $569E | | .byte>$307f, >$3361, >$366f, >$39ac, >$3d7e |
| $56A3 | | .byte>$40bc, >$4495, >$0000, >$0000, >$0000 |
| $56A8 | | .byte>$0000, >$0000, >$0000, >$0000, >$0000 |
| $56AD | | .byte>$0000, >$0000, >$0000, >$0000, >$0000 |
| $56B2 | | .byte>$0000, >$0000, >$0000, >$0000, >$0000 |
| $56B7 | | .byte>$0000, >$0000, >$0000, >$0000, >$0000 |
| $56BC | | .byte>$0000, >$0000, >$0000, >$0000 |
| ; Scans CIA1 keyboard matrix by driving Port B (rows) and reading Port A (cols). |
| ; A = DDR-B mask (row to drive). Returns stable column byte in A (debounced). |
| $56C0 | 8d 03 dc | cia1_scan_rowsta$dc03; x-ref: $56EE, $5702, $5714 CIA1: Data Direction Register B |
| $56C3 | a9 00 | lda#$00 |
| $56C5 | 8d 02 dc | sta$dc02; CIA1: Data Direction Register A |
| $56C8 | ad 00 dc | b_56C8lda$dc00; x-ref: $56CE CIA1: Data Port Register A |
| $56CB | cd 00 dc | cmp$dc00; CIA1: Data Port Register A |
| $56CE | d0 f8 | bneb_56C8 |
| $56D0 | 60 | rts |
| ; Scans CIA1 keyboard matrix by driving Port A (cols) and reading Port B (rows). |
| ; A = DDR-A mask (column to drive). Returns stable row byte in A (debounced). |
| $56D1 | 8d 02 dc | cia1_scan_colsta$dc02; x-ref: $56F7, $570B, $5728 CIA1: Data Direction Register A |
| $56D4 | a9 00 | lda#$00 |
| $56D6 | 8d 03 dc | sta$dc03; CIA1: Data Direction Register B |
| $56D9 | ad 01 dc | b_56D9lda$dc01; x-ref: $56DF CIA1: Data Port Register B |
| $56DC | cd 01 dc | cmp$dc01; CIA1: Data Port Register B |
| $56DF | d0 f8 | bneb_56D9 |
| $56E1 | 60 | rts |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| ; Custom keyboard/joystick scanner. Replaces part of the KERNAL's standard |
| ; keyboard scan by directly driving the CIA1 matrix to read joystick port 2 |
| ; and specific keyboard rows/columns. Builds a combined key code and a |
| ; joystick-format direction byte, then tail-calls into the KERNAL at $EA7E. |
| ; |
| ; Inputs: CIA1 hardware registers ($DC00-$DC03) |
| ; Outputs: key_scan ($C5) = current key matrix code ($7F = no key) |
| ; joy_state ($F5) = joystick state (active-low bits 0-4: U/D/L/R/Fire) |
| ; Side Effects: Modifies CIA1 DDRs; tail-calls KERNAL $EA7E (no RTS) |
| ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
| scan_keyboard_joystick |
| $56E2 | a2 04 | ldx#$04; Clear CIA1 ports $DC00-$DC03 (via $DBFF+X, X=4..1) ; x-ref: $5423, $54B9 |
| $56E4 | a9 00 | lda#$00 |
| $56E6 | 9d ff db | b_56E6staf_DBFF,x; x-ref: $56EA |
| $56E9 | ca | dex |
| $56EA | d0 fa | bneb_56E6 |
| $56EC | a9 10 | lda#$10; Drive row 4 → read joystick fire + key row |
| $56EE | 20 c0 56 | jsrcia1_scan_row |
| $56F1 | 09 7f | ora#%01111111; Keep bit 7 (fire); idle bits high |
| $56F3 | 85 c5 | stazp_key_scan; First scan result → key_scan |
| $56F5 | a9 01 | lda#$01; Drive column 0 |
| $56F7 | 20 d1 56 | jsrcia1_scan_col |
| $56FA | 09 87 | ora#%10000111; Mask unused bits 3-6 |
| $56FC | 25 c5 | andzp_key_scan; Combine row + column scans → final key code |
| $56FE | 85 c5 | stazp_key_scan; Final combined key state → key_scan ($7F = no key) |
| $5700 | a9 00 | lda#$00; Scan full row 0 to check for any key |
| $5702 | 20 c0 56 | jsrcia1_scan_row |
| $5705 | c9 ff | cmp#$ff; Key pressed → skip joystick decode |
| $5707 | d0 31 | bneb_573A |
| $5709 | a9 00 | lda#$00; Scan full column 0 |
| $570B | 20 d1 56 | jsrcia1_scan_col |
| $570E | c9 ff | cmp#$ff |
| $5710 | d0 28 | bneb_573A; Key pressed → skip joystick decode |
| $5712 | a9 04 | lda#$04; Drive row 2 for direction bits |
| $5714 | 20 c0 56 | jsrcia1_scan_row |
| $5717 | aa | tax |
| $5718 | 09 ef | ora#$ef; Isolate bit 4 (joy right) |
| $571A | 85 f5 | stazp_joy_state |
| $571C | 8a | txa |
| $571D | 4a | lsra; Shift raw bits right ×3 for bits 2-3 |
| $571E | 4a | lsra |
| $571F | 4a | lsra |
| $5720 | 09 f3 | ora#%11110011; Isolate bits 2-3 (joy up/down) |
| $5722 | 25 f5 | andzp_joy_state; Merge direction bits |
| $5724 | 85 f5 | stazp_joy_state |
| $5726 | a9 20 | lda#%00100000; Drive column 5 for left direction |
| $5728 | 20 d1 56 | jsrcia1_scan_col |
| $572B | 4a | lsra; Shift into position |
| $572C | aa | tax |
| $572D | 09 fe | ora#%11111110; Isolate bit 0 (joy up) |
| $572F | 25 f5 | andzp_joy_state |
| $5731 | 85 f5 | stazp_joy_state |
| $5733 | 8a | txa; Shift right ×2 more |
| $5734 | 4a | lsra |
| $5735 | 4a | lsra |
| $5736 | 09 fd | ora#%11111101; Isolate bit 1 (joy down) |
| $5738 | 25 f5 | andzp_joy_state; Final merge of all direction bits |
| $573A | 09 e0 | b_573Aora#%11100000; Set upper 3 bits high (unused, always 1) ; x-ref: $5707, $5710 |
| $573C | 85 f5 | stazp_joy_state |
| $573E | 4c 7e ea | jmpe_EA7E; Continue into KERNAL keyboard scan completion |
| $5741 | | .fill47, $00 |
| | .encode |
| | .enc"screen" |
| $5770 | | .text"copyright colosoftware xrom system br" |
| $5798 | | .text"ussels 1983 " |
| | .endencode |
| $57A6 | | .fill90, $00 |
| $5800 | | .binary"c64_burnin_rubber_5800.html" |
| ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
| $8000 | | .wordKERNAL_RESET_VECTOR, cartridge_reset_entry |
| $8004 | | .byte$c3, $c2, $cd, $38, $30, $20, $20, $20; CBM80 |
| $800C | | .byte$20, $20, $20, $20 |
| | .encode |
| | .enc"none" |
| ; Each "tile" consists of $0400 (1024) bytes, what fits in a screen. |
| ; Each level consists of different "tiles" that are defined in $4000 |
| ; block idx #00 |
| level_tile_definition_tbl |
| $8010 | | .text"EEEEEE@B BCEEEEEEE"; x-ref: $1329, $132D, $138D, $1391 |
| $8038 | | f_8038.text"EEEEEEAB BDEEEEEEE"; x-ref: $50D2 |
| $8060 | | .text"EEEEEE@B BCEEEEEEE" |
| $8088 | | .text"EEEEEEAB BDEEEEEEE" |
| $80B0 | | .text"EEEEEE@B BCEEEEEEE" |
| $80D8 | | .text"EEEEEEAB BDEEEEEEE" |
| $8100 | | .text"EEEEEE@B " |
| $8110 | | f_8110.text" BCEEEEEEEEEEEEEAB "; x-ref: $1714 |
| $8138 | | .text" BDEEEEEEEEEEEEE@B " |
| $8160 | | .text" BCEEEEEEEEEEEEEAB " |
| $8188 | | .text" BDEEEEEEEEEEEEE@B " |
| $81B0 | | .text" BCEEEEEEEEEEEEEAB " |
| $81D8 | | .text" BDEEEEEEEEEEEEE@B " |
| $8200 | | .text" B" |
| $8210 | | f_8210.text"CEEEEEEEEEEEEEAB B"; x-ref: $171A |
| $8238 | | .text"DEEEEEEEEEEEEE@B B" |
| $8260 | | .text"CEEEEEEEEEEEEEAB B" |
| $8288 | | .text"DEEEEEEEEEEEEE@B B" |
| $82B0 | | .text"CEEEEEEEEEEEEEAB B" |
| $82D8 | | .text"DEEEEEEEEEEEEE@B B" |
| $8300 | | f_8300.text"CEEEEEEEEEEEEEAB B"; x-ref: $1720 |
| $8328 | | .text"DEEEEEEEEEEEEE@B B" |
| $8350 | | .text"CEEEEEEEEEEEEEAB B" |
| $8378 | | .text"DEEEEEEEEEEEEE@B B" |
| $83A0 | | .text"CEEEEEEEEEEEEEAB B" |
| $83C8 | | .text"DEEEEEEEEEEEEE@B B" |
| $83F0 | | .text"CEEEEEEEEEEEEEAB " |
| ; block idx #01 |
| $8410 | | .text"KKKKKKFG MLKKKKKKK" |
| $8438 | | .text"KKKKKKKH NKKKKKKKK" |
| $8460 | | .text"KKKKKKJI OPKKKKKKK" |
| $8488 | | .text"KKKKKKH NKKKKKKK" |
| $84B0 | | .text"KKKKKKFG MLKKKKKKKK" |
| $84D8 | | .text"KKKKKKKH NKKKKKKKKK" |
| $8500 | | .text"KKKKKKJI OPKKKKKKKK" |
| $8528 | | .text"KKKKKKH NKKKKKKKK" |
| $8550 | | .text"KKKKKKKFG MLKKKKKKKK" |
| $8578 | | .text"KKKKKKKKH NKKKKKKKKK" |
| $85A0 | | .text"KKKKKKKKH OPKKKKKKKK" |
| $85C8 | | .text"KKKKKKKJI NKKKKKKKK" |
| $85F0 | | .text"KKKKKKH MLKKKKKKKK" |
| $8618 | | .text"KKKKKKFG NKKKKKKKKK" |
| $8640 | | .text"KKKKKKKH NKKKKKKKKK" |
| $8668 | | .text"KKKKKKJI RFG OPKKKKKKKK" |
| $8690 | | .text"KKKKKKH NKH NKKKKKKK" |
| $86B8 | | .text"KKKKKKFG QJI MLKKKKKKK" |
| $86E0 | | .text"KKKKKKKH NKKKKKKKK" |
| $8708 | | .text"KKKKKKJI OPKKKKKKK" |
| $8730 | | .text"KKKKKKH NKKKKKKK" |
| $8758 | | .text"KKKKKKFG MLKKKKKKK" |
| $8780 | | .text"KKKKKKKH NKKKKKKKK" |
| $87A8 | | .text"KKKKKKJI OPKKKKKKK" |
| $87D0 | | .text"KKKKKKH NKKKKKKK" |
| $87F8 | | .text" ", $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #02 |
| $8810 | | .text"KKKKKKKFG NKKKKKKK" |
| $8838 | | .text"KKKKKKKKFG NKKKKKKK" |
| $8860 | | .text"KKKKKKKKKFG NKKKKKKK" |
| $8888 | | .text"KKKKKKKKKKFG NKKKKKKK" |
| $88B0 | | .text"KKKKKKKKKKKFG MLKKKKKKK" |
| $88D8 | | .text"KKKKKKKKKKKKFG MLKKKKKKKK" |
| $8900 | | .text"KKKKKKKKKKKKKFG MLKKKKKKKKK" |
| $8928 | | .text"KKKKKKKKKKKKKKH MLKKKKKKKKKK" |
| $8950 | | .text"KKKKKKKKKKKKKKH MLKKKKKKKKKKK" |
| $8978 | | .text"KKKKKKKKKKKKKKH NKKKKKKKKKKKK" |
| $89A0 | | .text"KKKKKKKKKKKKKKH NKKKKKKKKKKKK" |
| $89C8 | | .text"KKKKKKKKKKKKKKH OPKKKKKKKKKKK" |
| $89F0 | | .text"KKKKKKKKKKKKKJI OPKKKKKKKKKK" |
| $8A18 | | .text"KKKKKKKKKKKKJI OPKKKKKKKKK" |
| $8A40 | | .text"KKKKKKKKKKKJI NKKKKKKKKK" |
| $8A68 | | .text"KKKKKKKKKKJI NKKKKKKKKK" |
| $8A90 | | .text"KKKKKKKKKJI NKKKKKKKKK" |
| $8AB8 | | .text"KKKKKKKKJI NKKKKKKKKK" |
| $8AE0 | | .text"KKKKKKKJI NKKKKKKKKK" |
| $8B08 | | .text"KKKKKKJI RFG NKKKKKKKKK" |
| $8B30 | | .text"KKKKKKH NKH NKKKKKKKKK" |
| $8B58 | | .text"KKKKKKH QJI OPKKKKKKKK" |
| $8B80 | | .text"KKKKKKH OPKKKKKKK" |
| $8BA8 | | .text"KKKKKKH NKKKKKKK" |
| $8BD0 | | .text"KKKKKKH NKKKKKKK" |
| $8BF8 | | .text" ", $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #03 |
| $8C10 | | .text"acacacUWB Wcacacacacacacacacacacacac" |
| $8C38 | | .text"bdbdbdWWB Bbdbdbdbdbdbdbdbdbdbdbdbdbd" |
| $8C60 | | .text"KKFBBBBBB BBBBBBBBBBBBBBBBBBBLKKKKKKK" |
| $8C88 | | .text"KKKFG RFG NKKKKKKKK" |
| $8CB0 | | .text"KKKKH NKH OPKKKKKKK" |
| $8CD8 | | .text"KKKKH QJI NKKKKKKK" |
| $8D00 | | .text"KKKKH MLKKKKKKK" |
| $8D28 | | .text"KKKKH NKKKKKKKK" |
| $8D50 | | .text"KKKKH OPKKKKKKK" |
| $8D78 | | .text"KKKKH NKKKKKKK" |
| $8DA0 | | .text"KKKKKKKKKKKKKH MLKKKKKKK" |
| $8DC8 | | .text"KKKKKKKKKKKKJI MLKKKKKKKK" |
| $8DF0 | | .text"KKKKKKKKKKKKH MLKKKKKKKKK" |
| $8E18 | | .text"KKKKKKKKKKKJI MLKKKKKKKKKK" |
| $8E40 | | .text"KKKKKKKKKKJI NKKKKKKKKKKK" |
| $8E68 | | .text"KKKKKKKKKH MLKKKKKKKKKKKK" |
| $8E90 | | .text"KKKKKKKKJI NKKKKKKKKKKKKK" |
| $8EB8 | | .text"KKKKKKKJI OPKKKKKKKKKKKK" |
| $8EE0 | | .text"KKKKKKJI OPKKKKKKKKKKK" |
| $8F08 | | .text"KKKKKKH OPKKKKKKKKKK" |
| $8F30 | | .text"KKKKKKH OPKKKKKKKKK" |
| $8F58 | | .text"KKKKKKFG RFG OPKKKKKKKK" |
| $8F80 | | .text"KKKKKKKH NKH OPKKKKKKK" |
| $8FA8 | | .text"KKKKKKJI QJI NKKKKKKK" |
| $8FD0 | | .text"KKKKKKH NKKKKKKK" |
| $8FF8 | | .text" ", $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #04 |
| $9010 | | .text"]_]_]_^WB BYY]_]_]_]_]_]_]_]_]_]_]_]_" |
| $9038 | | .text"^`^`^`^WB BY^`^`^`^`^`^`^`^`^`^`^`^`^" |
| $9060 | | .text"aaaaaaVXB Z\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $9088 | | .text"aaaaaaUWB Y[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $90B0 | | .text"aaaaaaVXB BZ\aaaaaaaacacacaaaaaaaaaaa" |
| $90D8 | | .text"aaaaaaUW BY[aaaaaaabdbdbdbdaaaaaaaaa" |
| $9100 | | .text"aaaaaaVX BZ\aaaaaaUWeeeeeeY[aaaaaaaa" |
| $9128 | | .text"aaaaaaUW BY[aaaaaaVXeeeeeeZ\aaaaaaaa" |
| $9150 | | .text"aaaaaaVX BZ\aaaaaaUWeeeeeeY[aaaaaaaa" |
| $9178 | | .text"aaaaaaUW BY[aaaaaaVXeeeeeeZ\aaaaaaaa" |
| $91A0 | | .text"aaaaaaVXB BZ\aaaaaaUWeeeeeeY[aaaaaaaa" |
| $91C8 | | .text"aaaaaaUWB BY[aaaaaaVXeeeeeeZ\aaaaaaaa" |
| $91F0 | | .text"aaaaaaVXB BZ\aaaaaaUWeeeeeeY[aaaaaaaa" |
| $9218 | | .text"aaaaaaUWB Y[aaaaaaVXeeeeeeZ\aaaaaaaa" |
| $9240 | | .text"aaaaaaVXB Z\aaaaaaUWeeeeeeY[aaaaaaaa" |
| $9268 | | .text"aaaaaaUWB Y[aaaaaaa]_]_]_]_aaaaaaaaa" |
| $9290 | | .text"aaaaaaVXB Z\aaaaaaa^`^`^`^aaaaaaaaaa" |
| $92B8 | | .text"aaaaaaUWB Y[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $92E0 | | .text"aaaaaaVX Z\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $9308 | | .text"aaaaaaUW BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $9330 | | .text"aaaaaaVX BZ\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $9358 | | .text"aaaaaaUW BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $9380 | | .text"aaaaaaVX BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $93A8 | | .text"aaaaaaUWB BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $93D0 | | .text"aaaaaaVXB BZ\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $93F8 | | .text" ", $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #05 |
| $9410 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9438 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9460 | | .text"aaaaaaaaaaUWB Y[aaaaaaaaaa" |
| $9488 | | .text"aaaaaaaaaaVXB Z\aaaaaaaaaa" |
| $94B0 | | .text"aaaaaaaaaaUWB Y[aaaaaaaaaa" |
| $94D8 | | .text"aaaaaaaaaaVXB Z\aaaaaaaaaa" |
| $9500 | | .text"aaaaaaaaaaUWB Y[aaaaaaaaaa" |
| $9528 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9550 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9578 | | .text"aaaaaaaaaaVX BZ\aaaaaaaaaa" |
| $95A0 | | .text"aaaaaaaaaaUW BY[aaaaaaaaaa" |
| $95C8 | | .text"aaaaaaaaaaVX BZ\aaaaaaaaaa" |
| $95F0 | | .text"aaaaaaaaaaUW BY[aaaaaaaaaa" |
| $9618 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9640 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9668 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9690 | | .text"aaaaaaaaaaUW Y[aaaaaaaaaa" |
| $96B8 | | .text"aaaaaaaaaaVX Z\aaaaaaaaaa" |
| $96E0 | | .text"aaaaaaaaaaUW Y[aaaaaaaaaa" |
| $9708 | | .text"aaaaaaaaaaVX BZ\aaaaaaaaaa" |
| $9730 | | .text"aaaaaaaaaaUW BY[aaaaaaaaaa" |
| $9758 | | .text"aaaaaaaaaaVX BZ\aaaaaaaaaa" |
| $9780 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $97A8 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $97D0 | | .text"aaaaaaaaaaUWB Y[aaaaaaaaaa" |
| $97F8 | | .text"aaaaaaaaaaVXB " |
| ; block idx #06 |
| $9810 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9838 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9860 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9888 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $98B0 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $98D8 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9900 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9928 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9950 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9978 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $99A0 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $99C8 | | .text"aaaaaaaaaaaa^`^`^`^`^`^`^`^`aaaaaaaaaaaa" |
| $99F0 | | .text"aaaaaaaaaaaabdbdbdbdbdbdbdbdaaaaaaaaaaaa" |
| $9A18 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9A40 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9A68 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9A90 | | .text"aaaaaaaaaaVXB Z\aaaaaaaaaa" |
| $9AB8 | | .text"aaaaaaaaaaUWB Y[aaaaaaaaaa" |
| $9AE0 | | .text"aaaaaaaaaaVX Z\aaaaaaaaaa" |
| $9B08 | | .text"aaaaaaaaaaUW Y[aaaaaaaaaa" |
| $9B30 | | .text"aaaaaaaaaaVX Z\aaaaaaaaaa" |
| $9B58 | | .text"aaaaaaaaaaUW BY[aaaaaaaaaa" |
| $9B80 | | .text"aaaaaaaaaaVX BZ\aaaaaaaaaa" |
| $9BA8 | | .text"aaaaaaaaaaUW BY[aaaaaaaaaa" |
| $9BD0 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9BF8 | | .text" ", $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #07 |
| $9C10 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9C38 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9C60 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9C88 | | .text"aaaaaaaaaaUW BY[aaaaaaaaaa" |
| $9CB0 | | .text"aaaaaaaaaaVX BZ\aaaaaaaaaa" |
| $9CD8 | | .text"aaaaaaaaaaUW BY[aaaaaaaaaa" |
| $9D00 | | .text"aaaaaaaaaaVX Z\aaaaaaaaaa" |
| $9D28 | | .text"aaaaaaaaaaUW Y[aaaaaaaaaa" |
| $9D50 | | .text"aaaaaaaaaaVXB BZ\aaaaaaaaaa" |
| $9D78 | | .text"aaaaaaaaaaUWB BY[aaaaaaaaaa" |
| $9DA0 | | .text"aaaaaaaaaaVXB Z\aaaaaaaaaa" |
| $9DC8 | | .text"aaaaaaaaaaUWB Y[aaaaaaaaaa" |
| $9DF0 | | .text"aaaaaaaaaaa^]_]_]_]_]_]_]_]_`aaaaaaaaaaa" |
| $9E18 | | .text"aaaaaaaaaaaa^`^`^`^`^`^`^`^`aaaaaaaaaaaa" |
| $9E40 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9E68 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9E90 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9EB8 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9EE0 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9F08 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9F30 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9F58 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9F80 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9FA8 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9FD0 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $9FF8 | | .text"aaaaaaaaaaaaaaaaaaaaaaaa" |
| ; block idx #08 |
| $A010 | | .text"aaaaaaVXB Z\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A038 | | .text"aaaaaaUWB Y[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A060 | | .text"aaaaaaVXB Z\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A088 | | .text"aaaaaaUWB Y[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A0B0 | | .text"aaaaaaVXB Z\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A0D8 | | .text"aaaaaaUWB BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A100 | | .text"aaaaaaVX BZ\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A128 | | .text"aaaaaaUW BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A150 | | .text"aaaaaaVX BZ\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A178 | | .text"aaaaaaUW BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A1A0 | | .text"aaaaaaVXB BZ\aaaaaaabdbdbdbdaaaaaaaaa" |
| $A1C8 | | .text"aaaaaaUWB BY[aaaaaabeeeeeeeedaaaaaaaa" |
| $A1F0 | | .text"aaaaaaVXB Z\aaaaUWeeeeeeeeeeY[aaaaaa" |
| $A218 | | .text"aaaaaaUWB Y[aaaaVXeeeeeeeeeeZ\aaaaaa" |
| $A240 | | .text"aaaaaaVX Z\aaaaUWeeeeeeeeeeY[aaaaaa" |
| $A268 | | .text"aaaaaaUW Y[aaaaVXeeeeeeeeeeZ\aaaaaa" |
| $A290 | | .text"aaaaaaVX BZ\aaaaUWeeeeeeeeeeY[aaaaaa" |
| $A2B8 | | .text"aaaaaaUW BY[aaaaVXeeeeeeeeeeZ\aaaaaa" |
| $A2E0 | | .text"aaaaaaVX BZ\aaaaUWeeeeeeeeeeY[aaaaaa" |
| $A308 | | .text"aaaaaaUW BY[aaaaVXeeeeeeeeeeZ\aaaaaa" |
| $A330 | | .text"aaaaaaVXB BZ\aaaaaX]_]_]_]_]_Zaaaaaaa" |
| $A358 | | .text"aaaaaaUWB BY[aaaaa^`^`^`^`^`^`aaaaaaa" |
| $A380 | | .text"aaaaaaVXB BZ\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A3A8 | | .text"aaaaaaUWB BY[aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A3D0 | | .text"aaaaaaVXB Z\aaaaaaaaaaaaaaaaaaaaaaaa" |
| $A3F8 | | .text" ", $00, $ff, $00, $ff, $00, $ff, $00, $ff, $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #09 |
| $A410 | | .text"KKKKKKFG KKKH MNKKKKKKK" |
| $A438 | | .text"KKKKKKKH KKKH NKKKKKKKK" |
| $A460 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $A488 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $A4B0 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $A4D8 | | .text"KKKKKKKH KKKH NKKKKKKKK" |
| $A500 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $A528 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $A550 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $A578 | | .text"KKKKKKKH KKKH RFG NKKKKKKKK" |
| $A5A0 | | .text"KKKKKKJI KKKFGNKH OYKKKKKKK" |
| $A5C8 | | .text"KKKKKKH KKKKHQJI NKKKKKKK" |
| $A5F0 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $A618 | | .text"KKKKKKKH KKKH NKKKKKKKK" |
| $A640 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $A668 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $A690 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $A6B8 | | .text"KKKKKKKH KKJI NKKKKKKKK" |
| $A6E0 | | .text"KKKKKKJI KJI OPKKKKKKK" |
| $A708 | | .text"KKKKKKH JI NKKKKKKK" |
| $A730 | | .text"KKKKKKFG MLKKKKKKK" |
| $A758 | | .text"KKKKKKKH NKKKKKKKK" |
| $A780 | | .text"KKKKKKJIRFG OPKKKKKKK" |
| $A7A8 | | .text"KKKKKKH NKH NKKKKKKK" |
| $A7D0 | | .text"KKKKKKH QJI NKKKKKKK" |
| $A7F8 | | .text" ", $00, $ff, $00, $ff, $00, $ff, $00, $ff, $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #10 ($0a) |
| $A810 | | .text"KKKKKKFG MNKKKKKKK" |
| $A838 | | .text"KKKKKKKH NKKKKKKKK" |
| $A860 | | .text"KKKKKKJI OPKKKKKKK" |
| $A888 | | .text"KKKKKKBBBBBBBBBBBBB NKKKKKKK" |
| $A8B0 | | .text"KKKKKK]_]_]_]_]_]ZB MLKKKKKKK" |
| $A8D8 | | .text"KKKKKK^`^`^`^`^`^WB NKKKKKKKK" |
| $A900 | | .text"KKKKKKbdbdbdbdbdbdB OPKKKKKKK" |
| $A928 | | .text"KKKKKKBBBBBBBBBBBBB NKKKKKKK" |
| $A950 | | .text"KKKKKKFG MLKKKKKKK" |
| $A978 | | .text"KKKKKKKH NKKKKKKKK" |
| $A9A0 | | .text"KKKKKKJI OPKKKKKKK" |
| $A9C8 | | .text"KKKKKKH BBBBBBBBBBBBBBBBKKKKKK" |
| $A9F0 | | .text"KKKKKKFG B]_]_]_]_]_]_]_]KKKKKK" |
| $AA18 | | .text"KKKKKKKH BY^`^`^`^`^`^`^`KKKKKK" |
| $AA40 | | .text"KKKKKKJI BYbdbdbdbdbdbdbdKKKKKK" |
| $AA68 | | .text"KKKKKKH BBBBBBBBBBBBBBBBKKKKKK" |
| $AA90 | | .text"KKKKKKFG MLKKKKKKK" |
| $AAB8 | | .text"KKKKKKKH NKKKKKKKK" |
| $AAE0 | | .text"KKKKKKJI OPKKKKKKK" |
| $AB08 | | .text"KKKKKKBBBBBBBBBBBBB NKKKKKKK" |
| $AB30 | | .text"KKKKKK]_]_]_]_]_]YB MLKKKKKKK" |
| $AB58 | | .text"KKKKKK^`^`^`^`^`^YB NKKKKKKKK" |
| $AB80 | | .text"KKKKKKbdbdbdbdbdbdB OPKKKKKKK" |
| $ABA8 | | .text"KKKKKKBBBBBBBBBBBBB NKKKKKKK" |
| $ABD0 | | .text"KKKKKKH NKKKKKKK" |
| $ABF8 | | .text" ", $00, $ff, $00, $ff, $00, $ff, $00, $ff, $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #11 ($0b) |
| $AC10 | | .text"KKKKKKFG MNKKKKKKK" |
| $AC38 | | .text"KKKKKKKH NKKKKKKKK" |
| $AC60 | | .text"KKKKKKJI OPKKKKKKK" |
| $AC88 | | .text"KKKKKKH NKKKKKKK" |
| $ACB0 | | .text"KKKKKKFG MLKKKKKKK" |
| $ACD8 | | .text"KKKKKKKH NKKKKKKKK" |
| $AD00 | | .text"KKKKKKJI OPKKKKKKK" |
| $AD28 | | .text"KKKKKKH FG NKKKKKKK" |
| $AD50 | | .text"KKKKKKFG KFG MLKKKKKKK" |
| $AD78 | | .text"KKKKKKKH KKFG NKKKKKKKK" |
| $ADA0 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $ADC8 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $ADF0 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $AE18 | | .text"KKKKKKKH KKKBBBBBBBBBBBBBBBBBKKKKKKK" |
| $AE40 | | .text"KKKKKKJI KKK]_]_]_]_]_]_]_]_]KKKKKKK" |
| $AE68 | | .text"KKKKKKH KKK^`^`^`^`^`^`^`^`^KKKKKKK" |
| $AE90 | | .text"KKKKKKFG KKKbdbdbdbdbdbdbdbdbKKKKKKK" |
| $AEB8 | | .text"KKKKKKKH KKKBBBBBBBBBBBBBBBBBKKKKKKK" |
| $AEE0 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $AF08 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $AF30 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $AF58 | | .text"KKKKKKKH KKKH NKKKKKKKK" |
| $AF80 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $AFA8 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $AFD0 | | .text"KKKKKKH KKKJI NKKKKKKK" |
| $AFF8 | | .text" ", $00, $ff, $00, $ff, $00, $ff, $00, $ff, $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #12 ($0c) |
| $B010 | | .text"KKKKKKFG KKKH MNKKKKKKK" |
| $B038 | | .text"KKKKKKKH KKKBBBBBBBBBBBBBBBBBKKKKKKK" |
| $B060 | | .text"KKKKKKJI KKK]_]_]_]_]_]_]_]_]KKKKKKK" |
| $B088 | | .text"KKKKKKH KKK^`^`^`^`^`^`^`^`^KKKKKKK" |
| $B0B0 | | .text"KKKKKKFG KKKbdbdbdbdbdbdbdbdbKKKKKKK" |
| $B0D8 | | .text"KKKKKKKH KKKBBBBBBBBBBBBBBBBBKKKKKKK" |
| $B100 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $B128 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $B150 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $B178 | | .text"KKKKKKKH KKKH RFG NKKKKKKKK" |
| $B1A0 | | .text"KKKKKKJI KKKFGNKH OPKKKKKKK" |
| $B1C8 | | .text"KKKKKKH KKKKHQJI NKKKKKKK" |
| $B1F0 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $B218 | | .text"KKKKKKKH KKKH NKKKKKKKK" |
| $B240 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $B268 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $B290 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $B2B8 | | .text"KKKKKKKH KKJI NKKKKKKKK" |
| $B2E0 | | .text"KKKKKKJI KJI OPKKKKKKK" |
| $B308 | | .text"KKKKKKH JI NKKKKKKK" |
| $B330 | | .text"KKKKKKFG MLKKKKKKK" |
| $B358 | | .text"KKKKKKKH NKKKKKKKK" |
| $B380 | | .text"KKKKKKJIRFG OPKKKKKKK" |
| $B3A8 | | .text"KKKKKKH NKH NKKKKKKK" |
| $B3D0 | | .text"KKKKKKH QJI NKKKKKKK" |
| $B3F8 | | .text" ", $00, $ff, $00, $ff, $00, $ff, $00, $ff, $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #13 ($0d) |
| $B410 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B438 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B460 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B488 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B4B0 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B4D8 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B500 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B528 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B550 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B578 | | .text"aaaaaaaaaabdbdbdbdbdbdbdbdbdbaaaaaaaaaaa" |
| $B5A0 | | .text"aaaaaaaaaUWeeeeeeeeeeeeeeeeeY[aaaaaaaaaa" |
| $B5C8 | | .text"aaaaaaaaaVXeeeeeeeeeeeeeeeeeZ\aaaaaaaaaa" |
| $B5F0 | | .text"aaaaaaaaaUWeeeeeeeeeeeeeeeeeY[aaaaaaaaaa" |
| $B618 | | .text"aaaaaaaaaVXeeeeeeeeeeeeeeeeeZ\aaaaaaaaaa" |
| $B640 | | .text"aaaaaaaaaUWeeeeeeeeeeeeeeeeeY[aaaaaaaaaa" |
| $B668 | | .text"aaaaaaaaaVXeeeeeeeeeeeeeeeeeY[aaaaaaaaaa" |
| $B690 | | .text"aaaaaaaaaVXeeeeeeeeeeeeeeeeeZ\aaaaaaaaaa" |
| $B6B8 | | .text"aaaaaaaaaa]_]_]_]_]_]_]_]_]_]aaaaaaaaaaa" |
| $B6E0 | | .text"aaaaaaaaaa^`^`^`^`^`^`^`^`^`^aaaaaaaaaaa" |
| $B708 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B730 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B758 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B780 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B7A8 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B7D0 | | .text"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
| $B7F8 | | .text" ", $00, $ff, $00, $ff, $00, $ff, $00, $ff, $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #14 ($0e) |
| $B810 | | .text"KKKKKKFG KKKH MNKKKKKKK" |
| $B838 | | .text"KKKKKKKH KKKBBBBBBBBBBBBBBBBBKKKKKKK" |
| $B860 | | .text"KKKKKKJI KKK]_]_]_]_]_]_]_]_]KKKKKKK" |
| $B888 | | .text"KKKKKKH KKK^`^`^`^`^`^`^`^`^KKKKKKK" |
| $B8B0 | | .text"KKKKKKFG KKKbdbdbdbdbdbdbdbdbKKKKKKK" |
| $B8D8 | | .text"KKKKKKKH KKKBBBBBBBBBBBBBBBBBKKKKKKK" |
| $B900 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $B928 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $B950 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $B978 | | .text"KKKKKKKH KKKH RFG NKKKKKKKK" |
| $B9A0 | | .text"KKKKKKJI KKKFGNKH OPKKKKKKK" |
| $B9C8 | | .text"KKKKKKH KKKKHQJI NKKKKKKK" |
| $B9F0 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $BA18 | | .text"KKKKKKKH KKKH NKKKKKKKK" |
| $BA40 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $BA68 | | .text"KKKKKKH KKKKH NKKKKKKK" |
| $BA90 | | .text"KKKKKKFG KKKJI MLKKKKKKK" |
| $BAB8 | | .text"KKKKKKKH KKKH NKKKKKKKK" |
| $BAE0 | | .text"KKKKKKJI KKKFG OPKKKKKKK" |
| $BB08 | | .text"KKKKKKBBBBBBBKKKKH NKKKKKKK" |
| $BB30 | | .text"KKKKKK]_]_]_]KKKJI MLKKKKKKK" |
| $BB58 | | .text"KKKKKK^`^`^`^KKKH NKKKKKKKK" |
| $BB80 | | .text"KKKKKKbdbdbdbKKKFG OPKKKKKKK" |
| $BBA8 | | .text"KKKKKKBBBBBBBKKKKH NKKKKKKK" |
| $BBD0 | | .text"KKKKKKH KKKJI NKKKKKKK" |
| $BBF8 | | .text" ", $00, $ff, $00, $ff, $00, $ff, $00, $ff, $c0, $c4, $c6, $c8, $ca, $cc, $ce, $d0 |
| ; block idx #15 ($0f) |
| $BC10 | | .text"KKKKKKH NKKKKKKK" |
| $BC38 | | .text"KKKKKKBBBBBBBBBBBBBBBBBBBBBBBBBBBKKKKKKK" |
| $BC60 | | .text"KKKKKK]_]_]_]_]_]_]_]_]_]_]_]_]_]KKKKKKK" |
| $BC88 | | .text"KKKKKK^`^`^`^`^`^`^`^`^`^`^`^`^`^KKKKKKK" |
| $BCB0 | | .text"KKKKKKbdbdbdbdbdbdbdbdbdbdbdbdbdbKKKKKKK" |
| $BCD8 | | .text"KKKKKKBBBBBBBBBBBBBBBBBBBBBBBBBBBKKKKKKK" |
| $BD00 | | .text"KKKKKKJI RFG OPKKKKKKK" |
| $BD28 | | .text"KKKKKKH NKH NKKKKKKK" |
| $BD50 | | .text"KKKKKKFG QJI MLKKKKKKK" |
| $BD78 | | .text"KKKKKKKH NKKKKKKKK" |
| $BDA0 | | .text"KKKKKKJI OPKKKKKKK" |
| $BDC8 | | .text"KKKKKKH NKKKKKKK" |
| $BDF0 | | .text"KKKKKKFG MLKKKKKKK" |
| $BE18 | | .text"KKKKKKKH NKKKKKKKK" |
| $BE40 | | .text"KKKKKKJI OPKKKKKKK" |
| $BE68 | | .text"KKKKKKH NKKKKKKK" |
| $BE90 | | .text"KKKKKKFG MLKKKKKKK" |
| $BEB8 | | .text"KKKKKKKH NKKKKKKKK" |
| $BEE0 | | .text"KKKKKKJI OPKKKKKKK" |
| $BF08 | | .text"KKKKKKBBBBBBBBBBBBBBBBBBBBBBBBBBBBKKKKKK" |
| $BF30 | | .text"KKKKKK]_]_]_]]_]_]_]_]_]_]_]_]_]_]KKKKKK" |
| $BF58 | | .text"KKKKKK^`^`^`^`^`^`^`^`^`^`^`^`^`^`KKKKKK" |
| $BF80 | | .text"KKKKKKbdbdbdbbdbdbdbdbdbdbdbdbdbdbKKKKKK" |
| $BFA8 | | .text"KKKKKKBBBBBBBBBBBBBBBBBBBBBBBBBBBBKKKKKK" |
| $BFD0 | | .text"KKKKKKH NKKKKKKK" |
| $BFF8 | | .text" " |
| | .endencode |