3D Pool disassembly =================== 3d Pool was written by Nick "Orlando" Pelling, and was published by Firebird Software for the BBC Micro in 1989. It is notable for its solid graphics. The following disassembly was created by reverse engineering binary images, without access to any source code. It is nevertheless reasonably complete, allowing the technical approaches used to be understood. The author of this disassembly imposes no additional copyright restrictions beyond those already present on the game itself. It is provided for educational purposes only, and it is hoped that the original authors will accept it in the good faith it was intended - as a tribute to their skills. Technical notes =============== The binaries have false load addresses. The main game binary is protected by a fifty-stage decryption routine. The game uses double buffering and sampled sound. If sideways RAM is available, the game uses faster multiplication, velocity and screen address calculation routines. The sideways RAM version has more ball sprites and tricks. It also caches a snapshot of the table for faster updates, using generated code and unrolled loops. When considering the computer's move, the game scores potential moves, playing the first move that exceeds the computer player's skill level, if any exist, or the first non-foul move otherwise. Each computer player always uses the same strike point and power. There is a probability of the computer not making a move accurately, resulting in the chosen angle being changed by a fraction. The abilities of the computer players are as follows: rank accuracy power skill FLASH HARRY 0 66 09 04 NO-GOOD NIK 1 80 09 04 CATFORD KID 2 6c 09 05 FAST FREDDY 3 99 0a 05 MIGHTY MIKE 4 b3 09 06 BILLY T KID 5 cc 0a 06 JAC DERRIDA 6 d9 0a 07 MALTESE JOE 7 e6 0b 08 When deciding tournament matches between two computer players, a random number between -2 and 2 is added to each player's rank. Moves are scored as follows: 5 for cue ball bouncing off edge of table before hitting any ball 3 for cue ball bouncing off edge of table after hitting any ball 1 for cue ball hitting first ball 5 for cue ball hitting wrong coloured ball first 0 for potting first ball hit 2 for potting second ball hit 4 for potting any other ball 3 for collision involving first ball hit and cue ball 3 for collision involving first ball hit and same coloured ball 4 for collision involving first ball hit and different coloured ball Interesting pokes ================= &2e89 = &08 allowing practising against Maltese Joe &3766 = &83, &3770 = &87 use alternative table colour Loader disassembly ================== ; 3D-Load ; ffff0400 ffff0900 00000164 # Actually loads at &0900 ; entry_point &0900 a9 ea LDA #&ea ; Write Tube present flag # Disable Tube &0902 a2 00 LDX #&00 &0904 a0 00 LDY #&00 &0906 20 f4 ff JSR &fff4 ; OSBYTE &0909 a9 14 LDA #&14 ; Implode user defined font &090b a2 00 LDX #&00 &090d 20 f4 ff JSR &fff4 ; OSBYTE &0910 a2 00 LDX #&00 &0912 a0 0e LDY #&0e ; &0e00 &0914 86 70 STX &70 ; wipe_address_low &0916 84 71 STY &71 ; wipe_address_high &0918 a0 00 LDY #&00 &091a 98 TYA &091b a2 28 LDX #&28 ; wipe_0e00_to_35ff_loop # Wipe &0e00 - &35ff &091d 91 70 STA (&70),Y ; wipe_address &091f c8 INY &0920 d0 fb BNE &091d ; wipe_0e00_to_35ff_loop &0922 e6 71 INC &71 ; wipe_address_high &0924 ca DEX &0925 d0 f6 BNE &091d ; wipe_0e00_to_35ff_loop ; write_initialise_screen_text_loop # Change to MODE 4 &0927 bd bf 09 LDA &09bf,X ; initialise_screen_text &092a 20 ee ff JSR &ffee ; OSWRCH &092d e8 INX &092e e0 36 CPX #&36 &0930 90 f5 BCC &0927 ; write_initialise_screen_text_loop &0932 a2 00 LDX #&00 ; &0e00 &0934 a0 0e LDY #&0e &0936 8e 50 03 STX &0350 ; os_screen_start_address_low &0939 8c 51 03 STY &0351 ; os_screen_start_address_high &093c 8c 4e 03 STY &034e ; os_screen_memory_high_byte &093f a2 00 LDX #&00 ; write_3d_pool_now_loading_text_loop # Write "3D pool now loading..." &0941 bd f5 09 LDA &09f5,X ; 3d_pool_now_loading_text &0944 20 ee ff JSR &ffee ; OSWRCH &0947 e8 INX &0948 e0 1e CPX #&1e &094a 90 f5 BCC &0941 ; write_3d_pool_now_loading_text_loop &094c a2 4d LDX #&4d ; &0a4d = run_DoMJ-5 &094e a0 0a LDY #&0a &0950 20 f7 ff JSR &fff7 ; OSCLI # *RUN DoMJ-5 to unpack loading screen &0953 78 SEI &0954 a9 08 LDA #&08 ; R8: Interlace and delay register &0956 8d 00 fe STA &fe00 ; video register number &0959 a9 f0 LDA #&f0 ; normal sync mode, disable video output, disable cursor output &095b 8d 01 fe STA &fe01 ; video register value &095e 58 CLI &095f ea NOP &0960 a2 00 LDX #&00 ; &5800 &0962 a0 58 LDY #&58 &0964 86 70 STX &70 ; source_address_low &0966 84 71 STY &71 ; source_address_high &0968 a2 00 LDX #&00 ; &0e00 &096a a0 0e LDY #&0e &096c 86 72 STX &72 ; target_address_low &096e 84 73 STY &73 ; target_address_high &0970 a0 00 LDY #&00 &0972 a2 28 LDX #&28 ; move_5800_to_7fff_loop # Move &5800 - &7fff to &0e00 - &35ff &0974 b1 70 LDA (&70),Y ; source_address &0976 91 72 STA (&72),Y &0978 c8 INY &0979 d0 f9 BNE &0974 ; move_5800_to_7fff_loop &097b e6 71 INC &71 ; source_address_high &097d e6 73 INC &73 ; target_address_high &097f ca DEX &0980 d0 f2 BNE &0974 ; move_5800_to_7fff_loop ; write_initialise_loading_screen_text_loop # Change to MODE 5, revealing loading screen &0982 bd 13 0a LDA &0a13,X ; initialise_loading_screen_text &0985 20 ee ff JSR &ffee ; OSWRCH &0988 e8 INX &0989 e0 34 CPX #&34 &098b 90 f5 BCC &0982 ; write_initialise_loading_screen_text_loop &098d a2 00 LDX #&00 ; &0e00 &098f a0 0e LDY #&0e &0991 8e 50 03 STX &0350 ; os_screen_start_address_low &0994 8c 51 03 STY &0351 ; os_screen_start_address_high &0997 8c 4e 03 STY &034e ; os_screen_memory_high_byte &099a a2 00 LDX #&00 &099c 86 70 STX &70 ; delay_low &099e 86 71 STX &71 ; delay_high &09a0 a2 0c LDX #&0c ; delay_loop &09a2 e6 70 INC &70 ; delay_low &09a4 d0 fc BNE &09a2 ; delay_loop &09a6 e6 71 INC &71 ; delay_high &09a8 d0 f8 BNE &09a2 ; delay_loop &09aa ca DEX &09ab d0 f5 BNE &09a2 ; delay_loop ; write_loading_text_window_text_loop # Set text window &09ad bd 47 0a LDA &0a47,X ; loading_text_window_text &09b0 20 ee ff JSR &ffee ; OSWRCH &09b3 e8 INX &09b4 e0 06 CPX #&06 &09b6 90 f5 BCC &09ad ; write_loading_text_window_text_loop &09b8 a2 58 LDX #&58 ; &0a58 = run_poolBBC &09ba a0 0a LDY #&0a &09bc 4c f7 ff JMP &fff7 ; OSCLI # *RUN PoolBBC to run main game binary ; initialise_screen_text &09bf 16 04 ; MODE 4 &09c1 13 00 02 30 30 30 ; set colour 0 to green &09c7 13 01 00 30 30 30 ; set colour 1 to black &09cd 17 00 06 1e 31 32 33 34 35 36 ; R6: Vertical displayed register &09d7 17 00 07 21 31 32 33 34 35 36 ; R7: Vertical sync position &09e1 17 00 0c 01 31 32 33 34 35 36 ; R12: Displayed screen start address register (high) to &0e00 &09eb 17 00 0d c0 31 32 33 34 35 36 ; R13: Displayed screen start address register (low) ; 3d_pool_now_loading_text &09f5 1c 00 1d 27 00 ; define text window x:(&00, &27), y:(&00, &1d) &09fa 33 44 20 50 6f 6f 6c 20 6e 6f 77 20 6c 6f 61 64 ; "3D pool now loading..." &0a0a 69 6e 67 2e 2e 2e &0a10 0d 0a 0a ; initialise_loading_screen_text &0a13 16 05 ; MODE 5 &0a15 13 02 02 30 30 30 ; set colour 2 to green &0a1b 11 82 ; COLOUR 128 + 2 &0a1d 11 00 ; COLOUR 0 &0a1f 17 00 06 1e 31 32 33 34 35 36 ; R6: Vertical displayed register &0a29 17 00 07 21 31 32 33 34 35 36 ; R7: Vertical sync position &0a33 17 00 0c 01 31 32 33 34 35 36 ; R12: Displayed screen start address register (high) to &0e00 &0a3d 17 00 0d c0 31 32 33 34 35 36 ; R13: Displayed screen start address register (low) ; loading_text_window_text &0a47 1c 00 1d 0d 1a ; define text window x:(&00, &0d), y:(&1a, &1d) &0a4c 0c ; CLS ; run_DoMJ-5 &0a4d 52 55 4e 20 44 6f 4d 4a 2d 35 0d ; "RUN DoMJ-5" ; run_poolBBC &0a58 52 55 4e 20 50 6f 6f 6c 42 42 43 0d ; "RUN PoolBBC" ; DoMJ-5 ; ffff6000 ffff7034 00000fcc # Actually loads at &7034 ; entry_point &7034 a2 26 LDX #&26 ; &7126 = packed_screen_data &7036 a0 71 LDY #&71 &7038 86 9c STX &9c ; packed_data_address_low &703a 84 9d STY &9d ; packed_data_address_high &703c a9 58 LDA #&58 &703e 85 91 STA &91 ; screen_address_high &7040 a2 00 LDX #&00 &7042 86 90 STX &90 ; screen_address_low &7044 86 94 STX &94 ; eor ; move_7058_to_7125_loop # Move &7058 - &7125 to &0c00 - &0ccd &7046 bd 58 70 LDA &7058,X &7049 9d 00 0c STA &0c00,X &704c e8 INX &704d e0 ce CPX #&ce &704f 90 f5 BCC &7046 ; move_7058_to_7125_loop &7051 a0 00 LDY #&00 &7053 a2 00 LDX #&00 &7055 4c 00 0c JMP &0c00 ; unpack_screen_data # &7058 - &7125 is moved to to &0c00 - &0ccd at &7046 ; unpack_screen_data ; unpack_screen_data_loop &0c00 20 27 0c JSR &0c27 ; get_byte_of_packed_data # Get a byte of packed data &0c03 c9 80 CMP #&80 &0c05 29 7f AND #&7f &0c07 85 95 STA &95 ; count # Lowest seven bits set length of run &0c09 90 10 BCC &0c1b ; unpack_screen_data_inner_loop # If top bit set, repeated run &0c0b 20 27 0c JSR &0c27 ; get_byte_of_packed_data # Get a byte of packed data for byte to repeat &0c0e 85 98 STA &98 ; byte ; unpack_screen_data_repeated_run_loop &0c10 a5 98 LDA &98 ; byte &0c12 20 31 0c JSR &0c31 ; set_byte_of_screen_data &0c15 c6 95 DEC &95 ; count &0c17 d0 f7 BNE &0c10 ; unpack_screen_data_repeated_run_loop &0c19 f0 e5 BEQ &0c00 ; unpack_screen_data_loop ; unpack_screen_data_unique_run_loop # If top bit clear, unique run &0c1b 20 27 0c JSR &0c27 ; get_byte_of_packed_data # Get a byte of packed data for each byte in run &0c1e 20 31 0c JSR &0c31 ; set_byte_of_screen_data &0c21 c6 95 DEC &95 ; count &0c23 d0 f6 BNE &0c1b ; unpack_screen_data_unique_run_loop &0c25 f0 d9 BEQ &0c00 ; unpack_screen_data_loop ; get_byte_of_packed_data &0c27 a1 9c LDA (&9c,X) ; packed_data_address &0c29 e6 9c INC &9c ; packed_data_address_low &0c2b f0 01 BEQ &0c2e ; next_page_of_packed_data &0c2d 60 RTS ; next_page_of_packed_data &0c2e e6 9d INC &9d ; packed_data_address_high &0c30 60 RTS ; set_byte_of_screen_data &0c31 45 94 EOR &94 ; eor # Allow repeated runs to dither &0c33 85 94 STA &94 ; eor &0c35 91 90 STA (&90),Y ; screen_address &0c37 c8 INY &0c38 f0 01 BEQ &0c3b ; next_page_of_screen_data &0c3a 60 RTS ; next_page_of_screen_data &0c3b e6 91 INC &91 ; screen_address_high &0c3d 30 01 BMI &0c40 ; shuffle_unpacked_data # Is this the end of the screen data? &0c3f 60 RTS ; shuffle_unpacked_data # Packed data is stored in full column, not group order &0c40 68 PLA # Leave unpack_screen_data on return &0c41 68 PLA &0c42 a2 08 LDX #&08 ; &5808 &0c44 a0 58 LDY #&58 &0c46 86 90 STX &90 ; source_address_low &0c48 84 91 STY &91 ; source_address_high &0c4a a2 00 LDX #&00 # source = (source_address - &5800) / 8 &0c4c 86 95 STX &95 ; source_high &0c4e e8 INX ; 1 ; 1 # Start one column right of top left corner &0c4f 86 94 STX &94 ; source_low ; shuffle_unpacked_data_loop &0c51 a6 94 LDX &94 ; source_low &0c53 a4 95 LDY &95 ; source_high &0c55 86 98 STX &98 ; tmp_low # tmp = source &0c57 84 99 STY &99 ; tmp_high ; calculate_target_loop &0c59 a0 ff LDY #&ff # Calculate tmp / 40 &0c5b a6 99 LDX &99 ; tmp_high &0c5d a5 98 LDA &98 ; tmp_low &0c5f e8 INX ; divide_by_forty_loop &0c60 38 SEC ; divide_by_forty_inner_loop &0c61 c8 INY &0c62 e9 28 SBC #&28 ; 40 &0c64 b0 fb BCS &0c61 ; divide_by_forty_inner_loop &0c66 ca DEX &0c67 d0 f7 BNE &0c60 ; divide_by_forty_loop &0c69 69 28 ADC #&28 ; 40 # A = tmp MOD 40, i.e. column in group &0c6b 84 98 STY &98 ; tmp_low # Y = tmp DIV 40, i.e. group &0c6d aa TAX &0c6e 4a LSR A &0c6f 4a LSR A &0c70 4a LSR A &0c71 a8 TAY &0c72 8a TXA &0c73 0a ASL A &0c74 0a ASL A &0c75 0a ASL A &0c76 0a ASL A &0c77 0a ASL A &0c78 18 CLC &0c79 65 98 ADC &98 ; tmp_low &0c7b 85 98 STA &98 ; target_low # target = (tmp MOD 40) * 32 + (tmp DIV 40) &0c7d 98 TYA &0c7e 69 00 ADC #&00 &0c80 85 99 STA &99 ; target_high &0c82 a5 98 LDA &98 ; target_low &0c84 c5 94 CMP &94 ; source_low &0c86 a5 99 LDA &99 ; target_high &0c88 e5 95 SBC &95 ; source_high # If target < tmp, &0c8a 90 cd BCC &0c59 ; calculate_target_loop # repeat division with tmp = target &0c8c d0 06 BNE &0c94 ; skip_checking_low &0c8e a5 98 LDA &98 ; target_low &0c90 c5 94 CMP &94 ; source_low &0c92 f0 1e BEQ &0cb2 ; skip_swapping_column # Don't swap if target and source are the same ; skip_checking_low &0c94 a5 99 LDA &99 ; target_high # target_address = (target * 8) + &5800 &0c96 06 98 ASL &98 ; target_low &0c98 2a ROL A &0c99 06 98 ASL &98 ; target_low &0c9b 2a ROL A &0c9c 06 98 ASL &98 ; target_address_low &0c9e 2a ROL A &0c9f 69 58 ADC #&58 &0ca1 85 99 STA &99 ; target_address_high &0ca3 a0 07 LDY #&07 ; swap_bytes_in_columns_loop &0ca5 b1 90 LDA (&90),Y ; source_address # Swap one column of bytes between source and target &0ca7 aa TAX &0ca8 b1 98 LDA (&98),Y ; target_address &0caa 91 90 STA (&90),Y ; source_address &0cac 8a TXA &0cad 91 98 STA (&98),Y ; target_address &0caf 88 DEY &0cb0 10 f3 BPL &0ca5 ; swap_bytes_in_columns_loop ; skip_swapping_column &0cb2 18 CLC &0cb3 a5 90 LDA &90 ; source_address_low &0cb5 69 08 ADC #&08 &0cb7 85 90 STA &90 ; source_address_low &0cb9 90 02 BCC &0cbd ; skip_page &0cbb e6 91 INC &91 ; source_address_high ; skip_page &0cbd e6 94 INC &94 ; source_low &0cbf d0 02 BNE &0cc3 ; skip_overflow &0cc1 e6 95 INC &95 ; source_high ; skip_overflow &0cc3 a5 94 LDA &94 ; source_low &0cc5 c9 fe CMP #&fe ; &04fe = 1278 # End one column left of bottom right corner &0cc7 a5 95 LDA &95 ; source_high &0cc9 e9 04 SBC #&04 &0ccb 90 84 BCC &0c51 ; shuffle_unpacked_data_loop &0ccd 60 RTS # Leave this binary ; packed_screen_data &7126 8a 00 03 33 9d fb 96 ff 83 77 04 33 11 11 11 bd &7136 00 0a 11 ee f5 0f 1e e5 0e 01 f1 50 87 f0 03 d0 &7146 80 00 ab 00 03 20 30 30 83 30 03 10 00 00 d1 00 &7156 03 f0 00 00 87 00 03 0c c0 88 87 88 03 40 04 04 &7166 89 04 8a 88 03 00 88 00 b9 00 0a 11 ee fa 0f 3d &7176 c9 0e 03 e3 b0 86 f0 03 d0 80 00 9b 00 05 11 22 &7186 00 00 44 8a 00 0b 04 00 02 c0 c1 c0 e0 f0 f0 70 &7196 20 d2 00 03 f0 00 00 87 00 03 27 72 77 87 77 8b &71a6 3b 0e b3 77 77 77 77 66 66 77 66 66 64 42 00 8c &71b6 b8 00 0a 11 ee f5 0f 3e c7 0c 12 e2 50 86 f0 03 &71c6 e0 40 00 9b 00 04 ff 00 00 00 84 10 8d 00 06 0a &71d6 05 00 a0 f0 a0 d2 00 03 f0 00 00 86 00 03 11 be &71e6 fa 8a ff 05 ee ee ff cd cd 83 ee 03 cc 88 88 83 &71f6 88 0c 00 11 11 11 02 20 11 11 15 73 76 23 b4 00 &7206 0a 11 fe ea 0f 7d 8b 0c 16 f6 b0 86 f0 03 d0 80 &7216 00 9c 00 0a 88 44 22 80 80 91 00 00 40 c0 86 00 &7226 0b 01 00 02 10 16 1a 30 70 f0 f0 a0 d2 00 03 f0 &7236 00 00 86 00 04 4f f4 dc cd 83 ee 07 88 88 cc 88 &7246 88 80 08 83 11 0b 02 20 11 55 11 33 3b 3b ff 77 &7256 77 88 ff 03 fd db 8c b3 00 0a 33 dc e5 0f 7a 87 &7266 08 34 e4 70 86 f0 03 e0 40 00 ff 00 8b 00 03 f0 &7276 00 00 86 00 0e 11 00 00 02 20 11 11 15 73 77 77 &7286 3b b3 77 95 ff 03 ee f4 4f b3 00 09 33 fd cb 0f &7296 f5 07 08 3c 9c 87 f0 03 d0 80 00 ff 00 8c 00 03 &72a6 f0 00 00 85 00 03 2f f2 77 a1 ff 03 fa af 00 b2 &72b6 00 0a 77 ba c7 1f ea 0f 01 79 a8 70 85 f0 03 d0 &72c6 80 00 86 00 06 20 70 70 70 70 20 ff 00 03 00 00 &72d6 f0 86 00 03 11 ae ea a1 ff 03 75 57 88 b2 00 09 &72e6 77 f9 8b 1e e5 0e 01 79 d8 84 f0 06 e0 f1 c3 07 &72f6 07 87 84 0f 83 07 06 82 80 80 d0 f0 50 d5 00 03 &7306 50 f0 f0 84 f0 03 50 00 00 a1 00 03 f0 00 00 84 &7316 00 03 5f f5 ff a0 ff 03 fe e5 4e b2 00 09 ff 72 &7326 87 3d c9 0e 03 e3 b0 85 f0 07 a0 80 48 e4 02 13 &7336 c7 84 0f 08 0e 0e 0a 10 10 50 f0 50 c3 00 04 11 &7346 00 01 21 8a 03 84 01 05 41 c0 e0 e0 e0 83 f0 03 &7356 b0 10 00 a0 00 03 f0 00 00 83 00 03 27 7a f7 a0 &7366 ff 03 dd d9 ae b1 00 0a 11 ee f5 0f 3e c7 0c 12 &7376 e2 50 84 f0 03 e0 40 00 8d 00 84 80 c0 00 03 10 &7386 65 8f 95 0f 08 07 03 01 00 80 c0 e0 50 a1 00 03 &7396 f0 00 00 83 00 03 af fa ff a0 ff 03 f5 5f 00 b0 &73a6 00 0a 11 fe ea 0f 7d 8b 0c 16 f6 b0 84 f0 03 d0 &73b6 80 00 83 00 05 20 30 30 30 10 97 00 06 20 30 30 &73c6 30 30 20 ad 00 0d ea 1f 0f 0f 2e 5c 4c 2c 3c 5c &73d6 28 58 0d 8c 0f 07 0e 0e 0a 00 10 b0 50 a1 00 03 &73e6 f0 00 00 83 00 03 cc 00 00 86 88 03 40 04 04 87 &73f6 04 85 88 03 89 98 98 87 90 03 91 88 00 b0 00 11 &7406 33 dc e5 0f 7a 87 08 34 e4 70 f0 f0 d3 14 98 10 &7416 10 84 00 06 08 00 07 80 d0 a0 88 00 04 10 00 00 &7426 20 8a 00 07 80 e0 e0 e0 f0 f0 50 ad 00 07 88 40 &7436 0c ae 06 86 97 83 87 88 0f 83 0e 0a 0c 18 18 18 &7446 10 50 70 70 e0 40 a1 00 0a f0 00 00 00 00 57 31 &7456 33 77 77 8a 3b 03 ff 77 77 88 77 88 ff 06 ef ea &7466 ae 00 00 01 ae 00 0f ee eb 0f f5 07 08 3c 9c f0 &7476 f0 e0 c0 80 88 c4 83 80 83 00 06 24 30 38 30 50 &7486 80 87 00 08 f0 00 11 22 22 00 00 11 8c 00 03 a0 &7496 f0 a0 c4 00 84 80 a4 00 07 f0 00 00 00 27 7a f7 &74a6 90 ff 03 ef ef ee 84 ee 09 ce ec 08 81 01 01 21 &74b6 02 02 84 00 07 01 02 00 01 00 00 cc 83 44 83 00 &74c6 06 66 22 00 00 00 11 8a 00 03 10 02 00 84 00 04 &74d6 02 00 00 01 88 00 09 6c 00 84 3c 30 3c f8 50 80 &74e6 99 00 05 80 40 00 00 a8 83 88 88 00 07 10 10 30 &74f6 70 f0 d0 80 ec 00 06 f0 00 00 11 ae ea 8b ff 05 &7506 ef ef ae 8c 88 8a 00 15 08 04 06 0d 0d 0f 1e 3c &7516 38 1c 0b 08 0e 28 0a 3b 1a 0b 05 06 07 85 03 83 &7526 01 03 00 00 88 84 00 12 44 00 00 c0 00 00 02 00 &7536 00 05 02 06 03 07 02 18 10 01 88 00 04 50 f0 f0 &7546 80 83 30 03 10 00 00 9c 00 03 11 00 00 86 00 04 &7556 01 00 00 b0 84 f0 03 a0 00 00 e8 00 05 f0 00 00 &7566 5f f5 8b ff 03 dd 88 00 91 00 03 08 a7 f0 84 f0 &7576 1d 78 30 14 18 08 0c 10 10 0a 1e 3c 2c 1e 0f 1d &7586 1c 0d 0d 06 0a 14 10 03 00 44 22 00 11 44 83 33 &7596 88 00 13 08 08 0c 00 4a 51 10 04 10 40 72 60 e1 &75a6 e0 e0 70 20 00 80 83 c0 06 60 00 30 30 30 10 90 &75b6 00 03 33 44 88 8d 00 08 08 04 83 80 80 d0 f0 50 &75c6 e9 00 05 f0 00 27 7a f7 8b ff 04 77 33 10 01 8d &75d6 00 04 01 30 16 78 84 f0 0e f1 e2 c5 81 59 1c 70 &75e6 12 f0 b0 70 b0 30 b0 83 70 08 50 48 c9 8c 0e 00 &75f6 04 08 85 00 04 88 00 00 88 8e 00 11 08 3f 3d 65 &7606 d4 87 00 23 51 68 a1 84 d0 00 32 00 11 84 00 0b &7616 80 c0 00 c0 c0 60 30 30 00 30 10 86 00 08 cc 22 &7626 71 20 60 40 40 20 88 00 08 01 00 06 18 10 50 f0 &7636 50 e9 00 04 f0 11 ae ea 90 ff 04 73 37 33 33 83 &7646 11 14 01 01 02 02 04 0a 82 82 a0 e5 e4 e0 c2 c0 &7656 48 0f 84 c0 48 8a 84 c0 12 80 84 80 80 80 08 00 &7666 00 11 00 00 11 11 00 22 00 00 22 83 33 06 77 77 &7676 33 33 33 11 8c 00 1b 88 f7 6a 9f 65 1c 03 84 e5 &7686 d1 60 78 f0 70 f4 30 42 20 d9 10 74 10 00 32 00 &7696 00 11 83 00 06 80 c0 c0 c0 00 60 83 30 04 10 00 &76a6 00 88 88 00 04 08 00 00 00 84 c0 03 80 00 00 e8 &76b6 00 04 f0 5f e4 ee 88 ff 87 ee 03 dc cd cd 85 cd &76c6 05 45 45 ee 66 22 93 00 05 11 22 44 00 88 92 00 &76d6 09 88 cc cc cc 88 00 11 33 11 89 00 0b cc f7 3e &76e6 8f 65 1c 03 84 e5 d1 e0 84 f0 11 70 20 00 88 00 &76f6 80 44 40 a2 20 40 99 10 20 44 00 32 83 00 0d 22 &7706 50 b4 34 d0 80 e2 60 21 00 30 30 10 83 00 83 10 &7716 83 01 04 11 00 10 10 e7 00 03 f0 00 88 89 80 03 &7726 08 00 00 a2 00 03 33 cc 00 9c 00 3d 44 88 44 88 &7736 00 22 22 88 44 66 44 22 00 aa 66 e4 0c 8c 64 0c &7746 02 84 e4 e0 c2 c0 c0 d0 d0 51 00 21 10 00 20 30 &7756 30 10 10 54 e8 e0 20 20 50 e0 40 30 40 90 bc 18 &7766 0c 3c 0e a2 00 05 87 c3 e9 84 60 08 a8 9c ff 0b &7776 1f fe be 40 e7 00 03 e0 00 00 86 00 03 01 00 00 &7786 91 00 03 11 00 00 91 00 03 88 66 11 b6 00 09 88 &7796 aa a2 08 00 88 c0 80 e0 84 f0 03 70 70 f0 86 f0 &77a6 11 70 90 44 06 83 03 83 01 41 61 28 80 54 00 32 &77b6 00 11 84 00 06 80 c0 c0 c0 60 00 83 30 03 10 00 &77c6 00 e0 00 04 80 50 70 20 83 00 03 80 0f 00 92 00 &77d6 03 ff 00 00 95 00 04 88 00 00 44 84 00 03 22 00 &77e6 00 84 00 03 11 00 00 a5 00 0c 88 88 20 64 30 88 &77f6 de 62 c0 c0 f0 e0 8c f0 17 e0 60 60 60 71 71 70 &7806 34 75 55 f5 b1 10 50 00 e8 20 04 50 10 22 20 31 &7816 83 00 0b 80 c0 00 c0 c0 60 30 00 30 30 10 d8 00 &7826 03 80 00 10 83 30 03 10 b0 0f 93 00 03 ff 00 00 &7836 a8 00 05 88 00 00 00 44 84 00 05 22 00 00 00 11 &7846 98 00 37 01 00 00 00 88 01 44 00 ee 00 2d 00 00 &7856 08 00 00 80 c4 c2 d1 b0 98 f8 90 80 4c 2c 28 3c &7866 94 d5 b3 80 91 c4 80 80 86 44 80 02 f2 92 00 42 &7876 60 99 20 00 54 10 22 00 00 11 83 00 0b 80 c0 00 &7886 c0 c0 60 30 30 00 30 10 ce 00 1d 20 00 00 80 00 &7896 00 70 d0 0f 33 47 8c 00 01 00 8e 45 00 00 45 8e &78a6 00 01 00 8c 47 33 00 ff 87 00 08 22 66 14 01 01 &78b6 10 62 22 8c 00 07 ee 44 00 44 66 00 88 9d 00 14 &78c6 88 00 00 00 88 00 00 cc f7 3e 0f 87 63 1d 03 08 &78d6 ca b2 c0 e0 86 f0 03 50 00 00 89 00 13 80 0c c0 &78e6 d3 4a 3a 10 67 d4 f2 f8 f9 f9 21 44 90 e3 70 20 &78f6 88 00 10 88 00 80 c4 00 62 60 10 a9 00 44 10 00 &7906 32 00 11 84 00 06 80 c0 c0 c0 00 60 83 30 03 10 &7916 00 00 c3 00 1d 80 40 50 00 30 10 e0 50 0f cc 2e &7926 13 00 08 00 00 08 13 13 08 00 00 08 00 13 2e cc &7936 00 ff 87 00 08 44 64 88 88 80 82 66 44 8c 00 05 &7946 dd 44 00 00 99 88 00 03 10 10 00 9d 00 0d ee f5 &7956 1e 0f 87 63 1d 03 08 ca b2 c0 e0 86 f0 03 50 00 &7966 00 8b 00 0e 88 44 c2 82 40 aa e6 c0 40 00 00 88 &7976 00 88 93 00 10 88 00 c4 00 80 22 40 71 a8 00 54 &7986 10 22 00 00 11 83 00 0b 80 00 c0 c0 c0 60 30 00 &7996 30 30 10 95 00 03 20 30 30 84 30 03 20 00 00 9e &79a6 00 09 10 b0 10 a0 f0 e0 0f 33 01 8e 00 04 01 33 &79b6 00 ff 87 00 03 22 46 44 83 00 03 51 71 00 8b 00 &79c6 07 dd 88 00 88 dd 11 11 86 00 03 f4 f4 00 87 00 &79d6 07 33 11 00 11 11 00 22 90 00 0e cc fb 3d 0f 0f &79e6 87 72 0e 01 08 ca b2 c0 e0 85 f0 03 b0 10 00 b5 &79f6 00 0f 88 80 c4 00 62 20 40 99 10 20 44 00 33 00 &7a06 10 84 00 07 80 c0 c1 00 c0 40 02 8c 00 04 02 01 &7a16 01 a1 87 f0 03 50 00 00 9d 00 0c 20 10 60 30 d0 &7a26 b0 0f ff 0f 00 00 06 88 00 07 06 00 00 0f ff 00 &7a36 ff 87 00 08 64 cc 08 c0 42 02 00 20 8c 00 07 dd &7a46 88 00 88 99 88 cc 86 00 03 88 88 00 87 00 05 aa &7a56 00 00 11 bb 84 00 05 01 06 07 07 03 84 00 03 04 &7a66 00 00 83 00 0e 88 66 f9 1d 0f 0f c7 3a 07 00 08 &7a76 ca b2 d0 87 f0 03 70 20 00 bb 00 0b 88 00 08 8c &7a86 44 c6 08 83 06 04 08 96 00 09 08 04 04 85 c3 e1 &7a96 f0 f0 a0 9c 00 0c 10 10 00 00 00 10 90 80 0f 00 &7aa6 88 4c 8c 00 05 4c 88 00 00 ff 87 00 08 e4 4c 08 &7ab6 40 40 02 46 e4 8c 00 05 bb aa 22 00 33 83 00 0a &7ac6 71 d3 02 00 30 10 00 08 fc 74 83 00 07 22 00 99 &7ad6 11 00 11 bb 83 00 06 02 02 0b 09 08 08 84 00 03 &7ae6 02 00 00 85 00 0e cc f7 3e 0f 0f 8f 65 1c 03 00 &7af6 0c cf b3 d0 87 f0 03 70 20 00 9a 00 06 10 30 30 &7b06 30 30 10 a0 00 03 0f 00 00 9b 00 05 0a a5 f0 f0 &7b16 a0 9c 00 09 e0 a0 00 10 00 00 d0 80 0f 85 00 05 &7b26 11 00 00 00 32 83 00 07 10 33 00 11 11 00 ff 87 &7b36 00 08 64 cc 08 c0 42 02 00 20 8c 00 05 55 22 22 &7b46 00 55 84 00 09 80 00 00 22 7e 4c 01 81 10 83 00 &7b56 03 22 00 88 83 00 0f aa 00 00 00 00 01 06 07 07 &7b66 02 00 01 00 00 04 88 00 03 88 f7 75 83 0f 08 cb &7b76 39 06 01 00 84 65 b1 88 f0 03 70 20 00 8a 00 04 &7b86 11 00 00 22 87 00 06 02 00 21 40 e0 e0 84 f0 03 &7b96 50 00 00 9c 00 03 0c 02 01 98 00 08 01 03 07 1a &7ba6 b0 f0 f0 a0 9e 00 15 80 d0 00 00 d0 80 0f 77 f8 &7bb6 10 30 00 80 70 20 30 00 c0 00 80 f0 83 00 03 ff &7bc6 00 ff 85 00 0f 11 01 00 30 00 51 71 11 23 02 20 &7bd6 10 32 22 10 87 00 12 55 22 22 00 55 00 00 11 23 &7be6 02 01 00 d7 c6 00 00 31 11 83 00 07 88 88 bb 11 &7bf6 33 22 bb 85 00 09 0b 03 03 09 00 08 00 01 0b 8a &7c06 00 03 ee f9 1d 83 0f 08 eb 1d 03 00 08 ca 32 a0 &7c16 88 f0 03 50 00 00 85 00 03 77 88 00 8f 00 08 08 &7c26 04 03 80 c0 e0 f0 a0 a0 00 03 08 00 04 83 00 03 &7c36 02 00 00 88 00 85 02 04 04 08 08 48 84 e0 03 c0 &7c46 80 00 9d 00 1b 80 c0 c0 80 c0 c0 0f ee d1 80 00 &7c56 00 50 80 00 10 a0 00 00 10 30 22 00 66 bb 00 ff &7c66 83 00 11 88 08 c0 00 84 e4 00 50 70 c0 a4 64 c4 &7c76 a4 02 a6 c4 85 00 03 44 44 55 83 00 03 55 00 00 &7c86 85 00 06 44 e6 02 08 d8 70 83 00 07 44 00 33 22 &7c96 00 00 55 84 00 0a 08 05 0c 0c 0c 00 00 04 08 0d &7ca6 8b 00 03 cc f7 3e 83 0f 09 87 72 0e 01 00 0c ed &7cb6 51 e0 87 f0 03 b0 10 00 84 00 0a cc 22 00 11 40 &7cc6 20 80 80 20 40 86 00 0a 01 00 02 04 18 10 50 f0 &7cd6 f0 a0 dc 00 0f 60 30 00 30 30 00 30 60 0f ff f0 &7ce6 70 20 00 f0 83 00 05 f0 00 80 c0 e0 83 00 03 ff &7cf6 00 ff 86 00 0e c8 e8 c4 4c f8 50 00 00 44 ec 08 &7d06 02 e6 44 87 00 07 99 cc 00 00 55 11 11 85 00 06 &7d16 c4 66 02 00 19 b9 85 00 05 66 00 22 22 66 84 00 &7d26 05 04 0a 0c 0e 0e 83 00 03 0e 0c 00 8b 00 03 88 &7d36 f7 75 84 0f 09 c7 3a 07 00 00 86 f6 c0 e0 87 f0 &7d46 03 b0 10 00 88 00 03 88 00 00 85 00 06 08 00 80 &7d56 00 00 40 83 c0 03 80 00 00 de 00 09 20 70 60 60 &7d66 20 70 0f dd b2 83 00 0f b0 00 00 20 50 00 10 30 &7d76 70 44 00 cc 77 00 ff 86 00 10 b2 f6 04 00 00 40 &7d86 22 66 04 a0 a0 00 00 04 cc 88 85 00 03 cc 88 00 &7d96 83 88 03 cc 00 20 83 00 06 44 c6 02 08 f9 51 83 &7da6 00 07 22 00 cc 44 00 44 ee 83 00 05 08 08 0d 05 &7db6 01 85 00 03 09 00 00 8c 00 03 ee f9 1d 83 0f 09 &7dc6 8f 65 1c 03 00 08 cb b3 d0 88 f0 03 b0 10 00 f8 &7dd6 00 0d 60 20 00 00 90 d0 0f ff f0 e0 40 00 f0 83 &7de6 00 0b e0 00 00 80 c0 00 00 11 ee 00 ff 83 00 11 &7df6 20 00 00 44 cc 08 02 d6 74 80 00 54 4c 09 01 d4 &7e06 44 87 00 04 44 aa aa 44 88 00 06 44 ec 08 02 e2 &7e16 40 83 00 03 11 00 00 83 00 03 11 00 00 83 00 09 &7e26 0e 0c 0c 0a 00 06 00 00 02 8f 00 03 cc f7 3e 84 &7e36 0f 08 cb 39 06 01 00 84 65 b1 89 f0 03 b0 10 00 &7e46 f4 00 0f 80 00 40 60 00 00 70 d0 0f 77 b8 10 00 &7e56 00 70 83 00 0b e0 00 30 70 f0 88 00 88 ff 00 ff &7e66 86 00 0e a8 08 02 e6 04 40 00 00 10 01 41 04 fc &7e76 a8 85 00 07 11 00 66 22 00 22 77 89 00 03 32 32 &7e86 00 86 00 13 dd 88 00 88 dd 11 11 00 01 01 0f 07 &7e96 00 02 00 02 00 07 0f 90 00 03 88 f7 75 85 0f 08 &7ea6 eb 1d 03 00 08 ca 32 a0 89 f0 03 b0 10 00 f4 00 &7eb6 09 40 e0 c0 c0 d0 70 0f ff e0 83 00 05 20 00 00 &7ec6 00 40 83 00 07 91 00 00 22 cc 00 ff 86 00 0e c8 &7ed6 e8 c4 4c f8 50 00 00 64 74 62 26 74 20 87 00 05 &7ee6 66 00 22 22 66 89 00 03 f4 f4 00 86 00 03 44 00 &7ef6 00 83 88 03 cc 00 08 89 00 03 08 00 00 90 00 03 &7f06 ee f9 1d 84 0f 09 87 72 0e 01 00 0c ed 51 e0 89 &7f16 f0 03 b0 10 00 f2 00 07 d0 70 30 30 10 b0 0f 83 &7f26 00 03 88 00 00 83 00 03 88 00 00 87 00 03 ff 00 &7f36 00 84 00 0e b2 f6 04 00 00 40 00 00 51 73 02 00 &7f46 80 a0 87 00 05 dd 44 cc 88 dd b8 00 03 cc f7 3e &7f56 85 0f 09 c7 3a 07 00 00 86 f6 c0 e0 89 f0 03 b0 &7f66 10 00 ed 00 0a 80 c0 00 50 b0 10 20 30 a0 0f 93 &7f76 00 15 ff 00 00 00 40 00 00 10 01 33 36 04 50 00 &7f86 00 a2 f6 34 20 70 30 87 00 07 77 22 00 22 66 66 &7f96 77 b7 00 03 88 f7 75 85 0f 09 8b 71 0e 01 00 08 &7fa6 cb b3 d0 8a f0 03 b0 10 00 eb 00 03 70 00 00 86 &7fb6 00 03 08 00 00 91 00 03 88 00 00 99 00 05 66 33 &7fc6 00 00 55 ba 00 03 88 77 fa 86 0f 08 ea 1c 03 00 &7fd6 00 84 65 b1 8a f0 03 70 20 00 ea 00 03 f0 00 00 &7fe6 f7 00 03 ff f5 0f 85 0f 09 e5 1c 03 00 00 08 ca &7ff6 32 a0 8a f0 03 70 20 00 e9 00 Game disassembly ================ ; PoolBBC ; ffff3000 ffff349d 00004be5 # Actually loads at &339d ; decryption_key &339d 50 02 f3 5a 43 cd 46 80 5c 4a 62 0e 66 60 c7 c1 &33ad 69 67 59 7a 21 13 af 52 33 c4 c9 79 49 05 01 3a &33bd 42 41 53 51 30 18 45 77 e7 cb 2c 26 f8 5d 04 65 &33cd 1b fa 54 7b e1 11 47 63 07 0c fb f9 28 38 ce 3c &33dd 31 9f 97 6c 5e 2d 0f 4e c8 06 76 48 27 6e 4b 57 &33ed 6a c5 39 e8 14 d9 58 25 3d 4f 29 1f 6f db 6b 61 &33fd 56 4d 22 0a 7f 55 17 16 20 5b 10 40 dc 6d 3f 3e &340d ef e4 44 1a 2a 03 24 37 9c 2f f4 cf 2e 08 68 75 &341d 7d ec 78 0d d8 2b fc 36 ca 3b e5 f5 7c 1c 98 81 &342d 35 f7 dd 19 0b 1d 82 ed e0 e3 d1 84 da b0 15 c6 &343d 71 4c fd 34 8c c0 ff f0 f6 b1 a1 aa c3 12 23 96 &344d d5 f1 d3 32 7e cc e9 91 70 a5 74 99 00 09 c2 72 &345d 64 e2 e6 73 d7 de ea 8f 1e d2 8b 93 b2 95 9a 83 &346d 9d 85 df 87 b9 89 bd 8d 8e ee 8a 9b 5f 86 9e fe &347d 94 eb a2 a7 88 f2 d6 ba b7 ad b8 d4 a3 a4 ae a8 &348d a9 d0 a0 b3 a6 b5 ab ac bc 90 be bb b4 92 b6 bf ; entry_point &349d a2 00 LDX #&00 ; copy_decryption_key_byte_loop &349f bd 9d 33 LDA &339d,X ; decryption_key &34a2 9d 00 09 STA &0900,X ; key &34a5 e8 INX &34a6 d0 f7 BNE &349f ; copy_decryption_key_byte_loop ; decryption_stage_0 # Decrypt &34e1 - &3553 (nothing extra) &34a8 a2 54 LDX #&54 ; &3554 &34aa a0 35 LDY #&35 &34ac 86 70 STX &70 ; target_address_low &34ae 84 71 STY &71 ; target_address_high &34b0 a2 8d LDX #&8d ; &ff8d &34b2 a0 ff LDY #&ff &34b4 86 72 STX &72 ; size_low &34b6 84 73 STY &73 ; size_high &34b8 a0 ff LDY #&ff ; decryption_stage_0_page_loop &34ba c6 71 DEC &71 ; target_address_high &34bc 4c c4 34 JMP &34c4 ; decryption_stage_0_byte ; decryption_stage_0_byte_loop &34bf 88 DEY &34c0 c0 ff CPY #&ff &34c2 f0 f6 BEQ &34ba ; decryption_stage_0_page_loop ; decryption_stage_0_byte &34c4 b1 70 LDA (&70),Y ; target_address &34c6 aa TAX &34c7 bd 00 09 LDA &0900,X ; key &34ca 85 74 STA &74 ; tmp &34cc b9 00 09 LDA &0900,Y ; key &34cf 9d 00 09 STA &0900,X ; key &34d2 91 70 STA (&70),Y ; target_address &34d4 a5 74 LDA &74 ; tmp &34d6 99 00 09 STA &0900,Y ; key &34d9 e6 72 INC &72 ; size_low &34db d0 e2 BNE &34bf ; decryption_stage_0_byte_loop &34dd e6 73 INC &73 ; size_high &34df d0 de BNE &34bf ; decryption_stage_0_byte_loop ; decryption_stage_1 # Decrypt &351a - &3597 (nothing extra) &34e1 a2 98 LDX #&98 ; &3598 &34e3 a0 35 LDY #&35 &34e5 86 70 STX &70 ; target_address_low &34e7 84 71 STY &71 ; target_address_high &34e9 a2 82 LDX #&82 ; &ff82 &34eb a0 ff LDY #&ff &34ed 86 72 STX &72 ; size_low &34ef 84 73 STY &73 ; size_high &34f1 a0 ff LDY #&ff ; decryption_stage_1_page_loop &34f3 c6 71 DEC &71 ; target_address_high &34f5 4c fd 34 JMP &34fd ; decryption_stage_1_byte ; decryption_stage_1_byte_loop &34f8 88 DEY &34f9 c0 ff CPY #&ff &34fb f0 f6 BEQ &34f3 ; decryption_stage_1_page_loop ; decryption_stage_1_byte &34fd b1 70 LDA (&70),Y ; target_address &34ff aa TAX &3500 bd 00 09 LDA &0900,X ; key &3503 85 74 STA &74 ; tmp &3505 b9 00 09 LDA &0900,Y ; key &3508 9d 00 09 STA &0900,X ; key &350b 91 70 STA (&70),Y ; target_address &350d a5 74 LDA &74 ; tmp &350f 99 00 09 STA &0900,Y ; key &3512 e6 72 INC &72 ; size_low &3514 d0 e2 BNE &34f8 ; decryption_stage_1_byte_loop &3516 e6 73 INC &73 ; size_high &3518 d0 de BNE &34f8 ; decryption_stage_1_byte_loop ; decryption_stage_2 # Decrypt &3554 - &35d7 (set interrupts) &351a 78 SEI &351b a2 d8 LDX #&d8 ; &35d8 &351d a0 35 LDY #&35 &351f 86 70 STX &70 ; target_address_low &3521 84 71 STY &71 ; target_address_high &3523 a2 7c LDX #&7c ; &ff7c &3525 a0 ff LDY #&ff &3527 86 72 STX &72 ; size_low &3529 84 73 STY &73 ; size_high &352b a0 ff LDY #&ff ; decryption_stage_2_page_loop &352d c6 71 DEC &71 ; target_address_high &352f 4c 37 35 JMP &3537; decryption_stage_2_byte ; decryption_stage_2_byte_loop &3532 88 DEY &3533 c0 ff CPY #&ff &3535 f0 f6 BEQ &352d ; decryption_stage_2_page_loop ; decryption_stage_2_byte &3537 b1 70 LDA (&70),Y ; target_address &3539 aa TAX &353a bd 00 09 LDA &0900,X ; key &353d 85 74 STA &74 ; tmp &353f b9 00 09 LDA &0900,Y ; key &3542 9d 00 09 STA &0900,X ; key &3545 91 70 STA (&70),Y ; target_address &3547 a5 74 LDA &74 ; tmp &3549 99 00 09 STA &0900,Y ; key &354c e6 72 INC &72 ; size_low &354e d0 e2 BNE &3532 ; decryption_stage_2_byte_loop &3550 e6 73 INC &73 ; size_high &3552 d0 de BNE &3532 ; decryption_stage_2_byte_loop ; decryption_stage_3 # Decrypt &3598 - &3611 (disable video) &3554 a9 08 LDA #&08 ; R8: Interlace and delay register &3556 a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3558 8d 00 fe STA &fe00 ; video register number &355b 8e 01 fe STX &fe01 ; video register value &355e 78 SEI &355f a2 12 LDX #&12 ; &3612 &3561 a0 36 LDY #&36 &3563 86 70 STX &70 ; target_address_low &3565 84 71 STY &71 ; target_address_high &3567 a2 86 LDX #&86 ; &ff86 &3569 a0 ff LDY #&ff &356b 86 72 STX &72 ; size_low &356d 84 73 STY &73 ; size_high &356f a0 ff LDY #&ff ; decryption_stage_3_page_loop &3571 c6 71 DEC &71 ; target_address_high &3573 4c 7b 35 JMP &357b; decryption_stage_3_byte ; decryption_stage_3_byte_loop &3576 88 DEY &3577 c0 ff CPY #&ff &3579 f0 f6 BEQ &3571 ; decryption_stage_3_page_loop ; decryption_stage_3_byte &357b b1 70 LDA (&70),Y ; target_address &357d aa TAX &357e bd 00 09 LDA &0900,X ; key &3581 85 74 STA &74 ; tmp &3583 b9 00 09 LDA &0900,Y ; key &3586 9d 00 09 STA &0900,X ; key &3589 91 70 STA (&70),Y ; target_address &358b a5 74 LDA &74 ; tmp &358d 99 00 09 STA &0900,Y ; key &3590 e6 72 INC &72 ; size_low &3592 d0 e2 BNE &3576 ; decryption_stage_3_byte_loop &3594 e6 73 INC &73 ; size_high &3596 d0 de BNE &3576 ; decryption_stage_3_byte_loop ; decryption_stage_4 # Decrypt &35d8 - &3651 (check interrupts) &3598 08 PHP ; processor status &3599 68 PLA ; processor status &359a 29 04 AND #&04 ; INTERRUPT_DISABLE &359c f0 17 BEQ &35b5 ; decryption_stage_4_failed # Misaligned code if interrupts enabled &359e 78 SEI &359f a2 52 LDX #&52 ; &3652 &35a1 a0 36 LDY #&36 &35a3 86 70 STX &70 ; target_address_low &35a5 84 71 STY &71 ; target_address_high &35a7 a2 86 LDX #&86 ; &ff86 &35a9 a0 ff LDY #&ff &35ab 86 72 STX &72 ; size_low &35ad 84 73 STY &73 ; size_high &35af a0 ff LDY #&ff ; decryption_stage_4_page_loop &35b1 c6 71 DEC &71 ; target_address_high &35b3 4c bb 35 JMP &35bb; decryption_stage_4_byte ; decryption_stage_4_byte_loop &35b6 88 DEY &35b7 c0 ff CPY #&ff &35b9 f0 f6 BEQ &35b1 ; decryption_stage_4_page_loop ; decryption_stage_4_byte &35bb b1 70 LDA (&70),Y ; target_address &35bd aa TAX &35be bd 00 09 LDA &0900,X ; key &35c1 85 74 STA &74 ; tmp &35c3 b9 00 09 LDA &0900,Y ; key &35c6 9d 00 09 STA &0900,X ; key &35c9 91 70 STA (&70),Y ; target_address &35cb a5 74 LDA &74 ; tmp &35cd 99 00 09 STA &0900,Y ; key &35d0 e6 72 INC &72 ; size_low &35d2 d0 e2 BNE &35b6 ; decryption_stage_4_byte_loop &35d4 e6 73 INC &73 ; size_high &35d6 d0 de BNE &35b6 ; decryption_stage_4_byte_loop ; decryption_stage_5 # Decrypt &3612 - &3694 (set interrupts) &35d8 78 SEI &35d9 a2 95 LDX #&95 ; &3695 &35db a0 36 LDY #&36 &35dd 86 70 STX &70 ; target_address_low &35df 84 71 STY &71 ; target_address_high &35e1 a2 7d LDX #&7d ; &ff7d &35e3 a0 ff LDY #&ff &35e5 86 72 STX &72 ; size_low &35e7 84 73 STY &73 ; size_high &35e9 a0 ff LDY #&ff ; decryption_stage_5_page_loop &35eb c6 71 DEC &71 ; target_address_high &35ed 4c f5 35 JMP &35f5; decryption_stage_5_byte ; decryption_stage_5_byte_loop &35f0 88 DEY &35f1 c0 ff CPY #&ff &35f3 f0 f6 BEQ &35eb ; decryption_stage_5_page_loop ; decryption_stage_5_byte &35f5 b1 70 LDA (&70),Y ; target_address &35f7 aa TAX &35f8 bd 00 09 LDA &0900,X ; key &35fb 85 74 STA &74 ; tmp &35fd b9 00 09 LDA &0900,Y ; key &3600 9d 00 09 STA &0900,X ; key &3603 91 70 STA (&70),Y ; target_address &3605 a5 74 LDA &74 ; tmp &3607 99 00 09 STA &0900,Y ; key &360a e6 72 INC &72 ; size_low &360c d0 e2 BNE &35f0 ; decryption_stage_5_byte_loop &360e e6 73 INC &73 ; size_high &3610 d0 de BNE &35f0 ; decryption_stage_5_byte_loop ; decryption_stage_6 # Decrypt &3652 - &36d3 (check interrupts) &3612 08 PHP ; processor status &3613 68 PLA ; processor status &3614 29 04 AND #&04 ; INTERRUPT_DISABLE &3616 f0 1d BEQ &3635 ; decryption_stage_6_failed # Skip setting addresses if interrupts enabled &3618 78 SEI &3619 a2 d4 LDX #&d4 ; &36d4 &361b a0 36 LDY #&36 &361d 86 70 STX &70 ; target_address_low &361f 84 71 STY &71 ; target_address_high &3621 a2 7e LDX #&7e ; &ff7e &3623 a0 ff LDY #&ff &3625 86 72 STX &72 ; size_low &3627 84 73 STY &73 ; size_high &3629 a0 ff LDY #&ff ; decryption_stage_6_page_loop &362b c6 71 DEC &71 ; target_address_high &362d 4c 35 36 JMP &3635; decryption_stage_6_byte ; decryption_stage_6_byte_loop &3630 88 DEY &3631 c0 ff CPY #&ff &3633 f0 f6 BEQ &362b ; decryption_stage_6_page_loop ; decryption_stage_6_byte &3635 b1 70 LDA (&70),Y ; target_address &3637 aa TAX &3638 bd 00 09 LDA &0900,X ; key &363b 85 74 STA &74 ; tmp &363d b9 00 09 LDA &0900,Y ; key &3640 9d 00 09 STA &0900,X ; key &3643 91 70 STA (&70),Y ; target_address &3645 a5 74 LDA &74 ; tmp &3647 99 00 09 STA &0900,Y ; key &364a e6 72 INC &72 ; size_low &364c d0 e2 BNE &3630 ; decryption_stage_6_byte_loop &364e e6 73 INC &73 ; size_high &3650 d0 de BNE &3630 ; decryption_stage_6_byte_loop ; decryption_stage_7 # Decrypt &3695 - &370c (disable video) &3652 a9 08 LDA #&08 ; R8: Interlace and delay register &3654 a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3656 8d 00 fe STA &fe00 ; video register number &3659 8e 01 fe STX &fe01 ; video register value &365c a2 0d LDX #&0d ; &370d &365e a0 37 LDY #&37 &3660 86 70 STX &70 ; target_address_low &3662 84 71 STY &71 ; target_address_high &3664 a2 88 LDX #&88 ; &ff88 &3666 a0 ff LDY #&ff &3668 86 72 STX &72 ; size_low &366a 84 73 STY &73 ; size_high &366c a0 ff LDY #&ff ; decryption_stage_7_page_loop &366e c6 71 DEC &71 ; target_address_high &3670 4c 78 36 JMP &3678; decryption_stage_7_byte ; decryption_stage_7_byte_loop &3673 88 DEY &3674 c0 ff CPY #&ff &3676 f0 f6 BEQ &366e ; decryption_stage_7_page_loop ; decryption_stage_7_byte &3678 b1 70 LDA (&70),Y ; target_address &367a aa TAX &367b bd 00 09 LDA &0900,X ; key &367e 85 74 STA &74 ; tmp &3680 b9 00 09 LDA &0900,Y ; key &3683 9d 00 09 STA &0900,X ; key &3686 91 70 STA (&70),Y ; target_address &3688 a5 74 LDA &74 ; tmp &368a 99 00 09 STA &0900,Y ; key &368d e6 72 INC &72 ; size_low &368f d0 e2 BNE &3673 ; decryption_stage_7_byte_loop &3691 e6 73 INC &73 ; size_high &3693 d0 de BNE &3673 ; decryption_stage_7_byte_loop ; decryption_stage_8 # Decrypt &36d4 - &374c (check interrupts) &3695 08 PHP ; processor status &3696 68 PLA ; processor status &3697 29 04 AND #&04 ; INTERRUPT_DISABLE &3699 f0 1c BEQ &36b7 ; decryption_stage_8_failed # Skip setting addresses if interrupts enabled &369b a2 4d LDX #&4d ; &374d &369d a0 37 LDY #&37 &369f 86 70 STX &70 ; target_address_low &36a1 84 71 STY &71 ; target_address_high &36a3 a2 87 LDX #&87 ; &ff87 &36a5 a0 ff LDY #&ff &36a7 86 72 STX &72 ; size_low &36a9 84 73 STY &73 ; size_high &36ab a0 ff LDY #&ff ; decryption_stage_8_page_loop &36ad c6 71 DEC &71 ; target_address_high &36af 4c b7 36 JMP &36b7; decryption_stage_8_byte ; decryption_stage_8_byte_loop &36b2 88 DEY &36b3 c0 ff CPY #&ff &36b5 f0 f6 BEQ &36ad ; decryption_stage_8_page_loop ; decryption_stage_8_byte &36b7 b1 70 LDA (&70),Y ; target_address &36b9 aa TAX &36ba bd 00 09 LDA &0900,X ; key &36bd 85 74 STA &74 ; tmp &36bf b9 00 09 LDA &0900,Y ; key &36c2 9d 00 09 STA &0900,X ; key &36c5 91 70 STA (&70),Y ; target_address &36c7 a5 74 LDA &74 ; tmp &36c9 99 00 09 STA &0900,Y ; key &36cc e6 72 INC &72 ; size_low &36ce d0 e2 BNE &36b2 ; decryption_stage_8_byte_loop &36d0 e6 73 INC &73 ; size_high &36d2 d0 de BNE &36b2 ; decryption_stage_8_byte_loop ; decryption_stage_9 # Decrypt &370d - &3790 (nothing extra) &36d4 a2 91 LDX #&91 ; &3791 &36d6 a0 37 LDY #&37 &36d8 86 70 STX &70 ; target_address_low &36da 84 71 STY &71 ; target_address_high &36dc a2 7c LDX #&7c ; &ff7c &36de a0 ff LDY #&ff &36e0 86 72 STX &72 ; size_low &36e2 84 73 STY &73 ; size_high &36e4 a0 ff LDY #&ff ; decryption_stage_9_page_loop &36e6 c6 71 DEC &71 ; target_address_high &36e8 4c f0 36 JMP &36f0; decryption_stage_9_byte ; decryption_stage_9_byte_loop &36eb 88 DEY &36ec c0 ff CPY #&ff &36ee f0 f6 BEQ &36e6 ; decryption_stage_9_page_loop ; decryption_stage_9_byte &36f0 b1 70 LDA (&70),Y ; target_address &36f2 aa TAX &36f3 bd 00 09 LDA &0900,X ; key &36f6 85 74 STA &74 ; tmp &36f8 b9 00 09 LDA &0900,Y ; key &36fb 9d 00 09 STA &0900,X ; key &36fe 91 70 STA (&70),Y ; target_address &3700 a5 74 LDA &74 ; tmp &3702 99 00 09 STA &0900,Y ; key &3705 e6 72 INC &72 ; size_low &3707 d0 e2 BNE &36eb ; decryption_stage_9_byte_loop &3709 e6 73 INC &73 ; size_high &370b d0 de BNE &36eb ; decryption_stage_9_byte_loop ; decryption_stage_10 # Decrypt &374d - &37d0 (check interrupts) &370d 08 PHP ; processor status &370e 68 PLA ; processor status &370f 29 04 AND #&04 ; INTERRUPT_DISABLE &3711 f0 23 BEQ &3736 ; decryption_stage_10_failed # Skip setting addresses if interrupts enabled &3713 78 SEI &3714 a2 d1 LDX #&d1 ; &37d1 &3716 a0 37 LDY #&37 &3718 86 70 STX &70 ; target_address_low &371a 84 71 STY &71 ; target_address_high &371c a2 7c LDX #&7c ; &ff7c &371e a0 ff LDY #&ff &3720 86 72 STX &72 ; size_low &3722 84 73 STY &73 ; size_high &3724 a0 ff LDY #&ff ; decryption_stage_10_page_loop &3726 c6 71 DEC &71 ; target_address_high &3728 4c 30 37 JMP &3730; decryption_stage_10_byte ; decryption_stage_10_byte_loop &372b 88 DEY &372c c0 ff CPY #&ff &372e f0 f6 BEQ &3726 ; decryption_stage_10_page_loop ; decryption_stage_10_byte &3730 b1 70 LDA (&70),Y ; target_address &3732 aa TAX &3733 bd 00 09 LDA &0900,X ; key &3736 85 74 STA &74 ; tmp &3738 b9 00 09 LDA &0900,Y ; key &373b 9d 00 09 STA &0900,X ; key &373e 91 70 STA (&70),Y ; target_address &3740 a5 74 LDA &74 ; tmp &3742 99 00 09 STA &0900,Y ; key &3745 e6 72 INC &72 ; size_low &3747 d0 e2 BNE &372b ; decryption_stage_10_byte_loop &3749 e6 73 INC &73 ; size_high &374b d0 de BNE &372b ; decryption_stage_10_byte_loop ; decryption_stage_11 # Decrypt &3791 - &380a (disable video) &374d a9 08 LDA #&08 ; R8: Interlace and delay register &374f a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3751 8d 00 fe STA &fe00 ; video register number &3754 8e 01 fe STX &fe01 ; video register value &3757 78 SEI &3758 a2 0b LDX #&0b ; &380b &375a a0 38 LDY #&38 &375c 86 70 STX &70 ; target_address_low &375e 84 71 STY &71 ; target_address_high &3760 a2 86 LDX #&86 ; &ff86 &3762 a0 ff LDY #&ff &3764 86 72 STX &72 ; size_low &3766 84 73 STY &73 ; size_high &3768 a0 ff LDY #&ff ; decryption_stage_11_page_loop &376a c6 71 DEC &71 ; target_address_high &376c 4c 74 37 JMP &3774; decryption_stage_11_byte ; decryption_stage_11_byte_loop &376f 88 DEY &3770 c0 ff CPY #&ff &3772 f0 f6 BEQ &376a ; decryption_stage_11_page_loop ; decryption_stage_11_byte &3774 b1 70 LDA (&70),Y ; target_address &3776 aa TAX &3777 bd 00 09 LDA &0900,X ; key &377a 85 74 STA &74 ; tmp &377c b9 00 09 LDA &0900,Y ; key &377f 9d 00 09 STA &0900,X ; key &3782 91 70 STA (&70),Y ; target_address &3784 a5 74 LDA &74 ; tmp &3786 99 00 09 STA &0900,Y ; key &3789 e6 72 INC &72 ; size_low &378b d0 e2 BNE &376f ; decryption_stage_11_byte_loop &378d e6 73 INC &73 ; size_high &378f d0 de BNE &376f ; decryption_stage_11_byte_loop ; decryption_stage_12 # Decrypt &37d1 - &384a (check interrupts) &3791 08 PHP ; processor status &3792 68 PLA ; processor status &3793 29 04 AND #&04 ; INTERRUPT_DISABLE &3795 f0 26 BEQ &37bd ; decryption_stage_12_failed # Break if interrupts enabled &3797 78 SEI &3798 a2 4b LDX #&4b ; &384b &379a a0 38 LDY #&38 &379c 86 70 STX &70 ; target_address_low &379e 84 71 STY &71 ; target_address_high &37a0 a2 86 LDX #&86 ; &ff86 &37a2 a0 ff LDY #&ff &37a4 86 72 STX &72 ; size_low &37a6 84 73 STY &73 ; size_high &37a8 a0 ff LDY #&ff ; decryption_stage_12_page_loop &37aa c6 71 DEC &71 ; target_address_high &37ac 4c b4 37 JMP &37b4; decryption_stage_12_byte ; decryption_stage_12_byte_loop &37af 88 DEY &37b0 c0 ff CPY #&ff &37b2 f0 f6 BEQ &37aa ; decryption_stage_12_page_loop ; decryption_stage_12_byte &37b4 b1 70 LDA (&70),Y ; target_address &37b6 aa TAX &37b7 bd 00 09 LDA &0900,X ; key &37ba 85 74 STA &74 ; tmp &37bc b9 00 09 LDA &0900,Y ; key &37bf 9d 00 09 STA &0900,X ; key &37c2 91 70 STA (&70),Y ; target_address &37c4 a5 74 LDA &74 ; tmp &37c6 99 00 09 STA &0900,Y ; key &37c9 e6 72 INC &72 ; size_low &37cb d0 e2 BNE &37af ; decryption_stage_12_byte_loop &37cd e6 73 INC &73 ; size_high &37cf d0 de BNE &37af ; decryption_stage_12_byte_loop ; decryption_stage_13 # Decrypt &380b - &388e (set interrupts) &37d1 78 SEI &37d2 a2 8f LDX #&8f ; &388f &37d4 a0 38 LDY #&38 &37d6 86 70 STX &70 ; target_address_low &37d8 84 71 STY &71 ; target_address_high &37da a2 7c LDX #&7c ; &ff7c &37dc a0 ff LDY #&ff &37de 86 72 STX &72 ; size_low &37e0 84 73 STY &73 ; size_high &37e2 a0 ff LDY #&ff ; decryption_stage_13_page_loop &37e4 c6 71 DEC &71 ; target_address_high &37e6 4c ee 37 JMP &37ee; decryption_stage_13_byte ; decryption_stage_13_byte_loop &37e9 88 DEY &37ea c0 ff CPY #&ff &37ec f0 f6 BEQ &37e4 ; decryption_stage_13_page_loop ; decryption_stage_13_byte &37ee b1 70 LDA (&70),Y ; target_address &37f0 aa TAX &37f1 bd 00 09 LDA &0900,X ; key &37f4 85 74 STA &74 ; tmp &37f6 b9 00 09 LDA &0900,Y ; key &37f9 9d 00 09 STA &0900,X ; key &37fc 91 70 STA (&70),Y ; target_address &37fe a5 74 LDA &74 ; tmp &3800 99 00 09 STA &0900,Y ; key &3803 e6 72 INC &72 ; size_low &3805 d0 e2 BNE &37e9 ; decryption_stage_13_byte_loop &3807 e6 73 INC &73 ; size_high &3809 d0 de BNE &37e9 ; decryption_stage_13_byte_loop ; decryption_stage_14 # Decrypt &384b - &38ce (check interrupts) &380b 08 PHP ; processor status &380c 68 PLA ; processor status &380d 29 04 AND #&04 ; INTERRUPT_DISABLE &380f f0 1a BEQ &382b ; decryption_stage_14_failed # Misaligned code if interrupts enabled &3811 78 SEI &3812 a2 cf LDX #&cf ; &38cf &3814 a0 38 LDY #&38 &3816 86 70 STX &70 ; target_address_low &3818 84 71 STY &71 ; target_address_high &381a a2 7c LDX #&7c ; &ff7c &381c a0 ff LDY #&ff &381e 86 72 STX &72 ; size_low &3820 84 73 STY &73 ; size_high &3822 a0 ff LDY #&ff ; decryption_stage_14_page_loop &3824 c6 71 DEC &71 ; target_address_high &3826 4c 2e 38 JMP &382e; decryption_stage_14_byte ; decryption_stage_14_byte_loop &3829 88 DEY &382a c0 ff CPY #&ff &382c f0 f6 BEQ &3824 ; decryption_stage_14_page_loop ; decryption_stage_14_byte &382e b1 70 LDA (&70),Y ; target_address &3830 aa TAX &3831 bd 00 09 LDA &0900,X ; key &3834 85 74 STA &74 ; tmp &3836 b9 00 09 LDA &0900,Y ; key &3839 9d 00 09 STA &0900,X ; key &383c 91 70 STA (&70),Y ; target_address &383e a5 74 LDA &74 ; tmp &3840 99 00 09 STA &0900,Y ; key &3843 e6 72 INC &72 ; size_low &3845 d0 e2 BNE &3829 ; decryption_stage_14_byte_loop &3847 e6 73 INC &73 ; size_high &3849 d0 de BNE &3829 ; decryption_stage_14_byte_loop ; decryption_stage_15 # Decrypt &388f - &3908 (disable video) &384b a9 08 LDA #&08 ; R8: Interlace and delay register &384d a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &384f 8d 00 fe STA &fe00 ; video register number &3852 8e 01 fe STX &fe01 ; video register value &3855 78 SEI &3856 a2 09 LDX #&09 ; &3909 &3858 a0 39 LDY #&39 &385a 86 70 STX &70 ; target_address_low &385c 84 71 STY &71 ; target_address_high &385e a2 86 LDX #&86 ; &ff86 &3860 a0 ff LDY #&ff &3862 86 72 STX &72 ; size_low &3864 84 73 STY &73 ; size_high &3866 a0 ff LDY #&ff ; decryption_stage_15_page_loop &3868 c6 71 DEC &71 ; target_address_high &386a 4c 72 38 JMP &3872; decryption_stage_15_byte ; decryption_stage_15_byte_loop &386d 88 DEY &386e c0 ff CPY #&ff &3870 f0 f6 BEQ &3868 ; decryption_stage_15_page_loop ; decryption_stage_15_byte &3872 b1 70 LDA (&70),Y ; target_address &3874 aa TAX &3875 bd 00 09 LDA &0900,X ; key &3878 85 74 STA &74 ; tmp &387a b9 00 09 LDA &0900,Y ; key &387d 9d 00 09 STA &0900,X ; key &3880 91 70 STA (&70),Y ; target_address &3882 a5 74 LDA &74 ; tmp &3884 99 00 09 STA &0900,Y ; key &3887 e6 72 INC &72 ; size_low &3889 d0 e2 BNE &386d ; decryption_stage_15_byte_loop &388b e6 73 INC &73 ; size_high &388d d0 de BNE &386d ; decryption_stage_15_byte_loop ; decryption_stage_16 # Decrypt &38cf - &3948 (check interrupts) &388f 08 PHP ; processor status &3890 68 PLA ; processor status &3891 29 04 AND #&04 ; INTERRUPT_DISABLE &3893 f0 21 BEQ &38b6 ; decryption_stage_16_failed # Break if interrupts enabled &3895 78 SEI &3896 a2 49 LDX #&49 ; &3949 &3898 a0 39 LDY #&39 &389a 86 70 STX &70 ; target_address_low &389c 84 71 STY &71 ; target_address_high &389e a2 86 LDX #&86 ; &ff86 &38a0 a0 ff LDY #&ff &38a2 86 72 STX &72 ; size_low &38a4 84 73 STY &73 ; size_high &38a6 a0 ff LDY #&ff ; decryption_stage_16_page_loop &38a8 c6 71 DEC &71 ; target_address_high &38aa 4c b2 38 JMP &38b2; decryption_stage_16_byte ; decryption_stage_16_byte_loop &38ad 88 DEY &38ae c0 ff CPY #&ff &38b0 f0 f6 BEQ &38a8 ; decryption_stage_16_page_loop ; decryption_stage_16_byte &38b2 b1 70 LDA (&70),Y ; target_address &38b4 aa TAX &38b5 bd 00 09 LDA &0900,X ; key &38b8 85 74 STA &74 ; tmp &38ba b9 00 09 LDA &0900,Y ; key &38bd 9d 00 09 STA &0900,X ; key &38c0 91 70 STA (&70),Y ; target_address &38c2 a5 74 LDA &74 ; tmp &38c4 99 00 09 STA &0900,Y ; key &38c7 e6 72 INC &72 ; size_low &38c9 d0 e2 BNE &38ad ; decryption_stage_16_byte_loop &38cb e6 73 INC &73 ; size_high &38cd d0 de BNE &38ad ; decryption_stage_16_byte_loop ; decryption_stage_17 # Decrypt &3909 - &398c (set interrupts) &38cf 78 SEI &38d0 a2 8d LDX #&8d ; &398d &38d2 a0 39 LDY #&39 &38d4 86 70 STX &70 ; target_address_low &38d6 84 71 STY &71 ; target_address_high &38d8 a2 7c LDX #&7c ; &ff7c &38da a0 ff LDY #&ff &38dc 86 72 STX &72 ; size_low &38de 84 73 STY &73 ; size_high &38e0 a0 ff LDY #&ff ; decryption_stage_17_page_loop &38e2 c6 71 DEC &71 ; target_address_high &38e4 4c ec 38 JMP &38ec; decryption_stage_17_byte ; decryption_stage_17_byte_loop &38e7 88 DEY &38e8 c0 ff CPY #&ff &38ea f0 f6 BEQ &38e2 ; decryption_stage_17_page_loop ; decryption_stage_17_byte &38ec b1 70 LDA (&70),Y ; target_address &38ee aa TAX &38ef bd 00 09 LDA &0900,X ; key &38f2 85 74 STA &74 ; tmp &38f4 b9 00 09 LDA &0900,Y ; key &38f7 9d 00 09 STA &0900,X ; key &38fa 91 70 STA (&70),Y ; target_address &38fc a5 74 LDA &74 ; tmp &38fe 99 00 09 STA &0900,Y ; key &3901 e6 72 INC &72 ; size_low &3903 d0 e2 BNE &38e7 ; decryption_stage_17_byte_loop &3905 e6 73 INC &73 ; size_high &3907 d0 de BNE &38e7 ; decryption_stage_17_byte_loop ; decryption_stage_18 # Decrypt &3949 - &39cc (check interrupts) &3909 08 PHP ; processor status &390a 68 PLA ; processor status &390b 29 04 AND #&04 ; INTERRUPT_DISABLE &390d f0 26 BEQ &3935 ; decryption_stage_18_failed # Break if interrupts enabled &390f 78 SEI &3910 a2 cd LDX #&cd ; &39cd &3912 a0 39 LDY #&39 &3914 86 70 STX &70 ; target_address_low &3916 84 71 STY &71 ; target_address_high &3918 a2 7c LDX #&7c ; &ff7c &391a a0 ff LDY #&ff &391c 86 72 STX &72 ; size_low &391e 84 73 STY &73 ; size_high &3920 a0 ff LDY #&ff ; decryption_stage_18_page_loop &3922 c6 71 DEC &71 ; target_address_high &3924 4c 2c 39 JMP &392c; decryption_stage_18_byte ; decryption_stage_18_byte_loop &3927 88 DEY &3928 c0 ff CPY #&ff &392a f0 f6 BEQ &3922 ; decryption_stage_18_page_loop ; decryption_stage_18_byte &392c b1 70 LDA (&70),Y ; target_address &392e aa TAX &392f bd 00 09 LDA &0900,X ; key &3932 85 74 STA &74 ; tmp &3934 b9 00 09 LDA &0900,Y ; key &3937 9d 00 09 STA &0900,X ; key &393a 91 70 STA (&70),Y ; target_address &393c a5 74 LDA &74 ; tmp &393e 99 00 09 STA &0900,Y ; key &3941 e6 72 INC &72 ; size_low &3943 d0 e2 BNE &3927 ; decryption_stage_18_byte_loop &3945 e6 73 INC &73 ; size_high &3947 d0 de BNE &3927 ; decryption_stage_18_byte_loop ; decryption_stage_19 # Decrypt &398d - &3a06 (disable video) &3949 a9 08 LDA #&08 ; R8: Interlace and delay register &394b a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &394d 8d 00 fe STA &fe00 ; video register number &3950 8e 01 fe STX &fe01 ; video register value &3953 78 SEI &3954 a2 07 LDX #&07 ; &3a07 &3956 a0 3a LDY #&3a &3958 86 70 STX &70 ; target_address_low &395a 84 71 STY &71 ; target_address_high &395c a2 86 LDX #&86 ; &ff86 &395e a0 ff LDY #&ff &3960 86 72 STX &72 ; size_low &3962 84 73 STY &73 ; size_high &3964 a0 ff LDY #&ff ; decryption_stage_19_page_loop &3966 c6 71 DEC &71 ; target_address_high &3968 4c 70 39 JMP &3970; decryption_stage_19_byte ; decryption_stage_19_byte_loop &396b 88 DEY &396c c0 ff CPY #&ff &396e f0 f6 BEQ &3966 ; decryption_stage_19_page_loop ; decryption_stage_19_byte &3970 b1 70 LDA (&70),Y ; target_address &3972 aa TAX &3973 bd 00 09 LDA &0900,X ; key &3976 85 74 STA &74 ; tmp &3978 b9 00 09 LDA &0900,Y ; key &397b 9d 00 09 STA &0900,X ; key &397e 91 70 STA (&70),Y ; target_address &3980 a5 74 LDA &74 ; tmp &3982 99 00 09 STA &0900,Y ; key &3985 e6 72 INC &72 ; size_low &3987 d0 e2 BNE &396b ; decryption_stage_19_byte_loop &3989 e6 73 INC &73 ; size_high &398b d0 de BNE &396b ; decryption_stage_19_byte_loop ; decryption_stage_20 # Decrypt &39cd - &3a46 (check interrupts) &398d 08 PHP ; processor status &398e 68 PLA ; processor status &398f 29 04 AND #&04 ; INTERRUPT_DISABLE &3991 f0 1f BEQ &39b2 ; decryption_stage_20_failed # Skip setting addresses if interrupts enabled &3993 78 SEI &3994 a2 47 LDX #&47 ; &3a47 &3996 a0 3a LDY #&3a &3998 86 70 STX &70 ; target_address_low &399a 84 71 STY &71 ; target_address_high &399c a2 86 LDX #&86 ; &ff86 &399e a0 ff LDY #&ff &39a0 86 72 STX &72 ; size_low &39a2 84 73 STY &73 ; size_high &39a4 a0 ff LDY #&ff ; decryption_stage_20_page_loop &39a6 c6 71 DEC &71 ; target_address_high &39a8 4c b0 39 JMP &39b0; decryption_stage_20_byte ; decryption_stage_20_byte_loop &39ab 88 DEY &39ac c0 ff CPY #&ff &39ae f0 f6 BEQ &39a6 ; decryption_stage_20_page_loop ; decryption_stage_20_byte &39b0 b1 70 LDA (&70),Y ; target_address &39b2 aa TAX &39b3 bd 00 09 LDA &0900,X ; key &39b6 85 74 STA &74 ; tmp &39b8 b9 00 09 LDA &0900,Y ; key &39bb 9d 00 09 STA &0900,X ; key &39be 91 70 STA (&70),Y ; target_address &39c0 a5 74 LDA &74 ; tmp &39c2 99 00 09 STA &0900,Y ; key &39c5 e6 72 INC &72 ; size_low &39c7 d0 e2 BNE &39ab ; decryption_stage_20_byte_loop &39c9 e6 73 INC &73 ; size_high &39cb d0 de BNE &39ab ; decryption_stage_20_byte_loop ; decryption_stage_21 # Decrypt &3a07 - &3a8a (set interrupts) &39cd 78 SEI &39ce a2 8b LDX #&8b ; &3a8b &39d0 a0 3a LDY #&3a &39d2 86 70 STX &70 ; target_address_low &39d4 84 71 STY &71 ; target_address_high &39d6 a2 7c LDX #&7c ; &ff7c &39d8 a0 ff LDY #&ff &39da 86 72 STX &72 ; size_low &39dc 84 73 STY &73 ; size_high &39de a0 ff LDY #&ff ; decryption_stage_21_page_loop &39e0 c6 71 DEC &71 ; target_address_high &39e2 4c ea 39 JMP &39ea; decryption_stage_21_byte ; decryption_stage_21_byte_loop &39e5 88 DEY &39e6 c0 ff CPY #&ff &39e8 f0 f6 BEQ &39e0 ; decryption_stage_21_page_loop ; decryption_stage_21_byte &39ea b1 70 LDA (&70),Y ; target_address &39ec aa TAX &39ed bd 00 09 LDA &0900,X ; key &39f0 85 74 STA &74 ; tmp &39f2 b9 00 09 LDA &0900,Y ; key &39f5 9d 00 09 STA &0900,X ; key &39f8 91 70 STA (&70),Y ; target_address &39fa a5 74 LDA &74 ; tmp &39fc 99 00 09 STA &0900,Y ; key &39ff e6 72 INC &72 ; size_low &3a01 d0 e2 BNE &39e5 ; decryption_stage_21_byte_loop &3a03 e6 73 INC &73 ; size_high &3a05 d0 de BNE &39e5 ; decryption_stage_21_byte_loop ; decryption_stage_22 # Decrypt &3a47 - &3aca (check interrupts) &3a07 08 PHP ; processor status &3a08 68 PLA ; processor status &3a09 29 04 AND #&04 ; INTERRUPT_DISABLE &3a0b f0 1b BEQ &3a28 ; decryption_stage_22_failed # Skip setting addresses if interrupts enabled &3a0d 78 SEI &3a0e a2 cb LDX #&cb ; &3acb &3a10 a0 3a LDY #&3a &3a12 86 70 STX &70 ; target_address_low &3a14 84 71 STY &71 ; target_address_high &3a16 a2 7c LDX #&7c ; &ff7c &3a18 a0 ff LDY #&ff &3a1a 86 72 STX &72 ; size_low &3a1c 84 73 STY &73 ; size_high &3a1e a0 ff LDY #&ff ; decryption_stage_22_page_loop &3a20 c6 71 DEC &71 ; target_address_high &3a22 4c 2a 3a JMP &3a2a; decryption_stage_22_byte ; decryption_stage_22_byte_loop &3a25 88 DEY &3a26 c0 ff CPY #&ff &3a28 f0 f6 BEQ &3a20 ; decryption_stage_22_page_loop ; decryption_stage_22_byte &3a2a b1 70 LDA (&70),Y ; target_address &3a2c aa TAX &3a2d bd 00 09 LDA &0900,X ; key &3a30 85 74 STA &74 ; tmp &3a32 b9 00 09 LDA &0900,Y ; key &3a35 9d 00 09 STA &0900,X ; key &3a38 91 70 STA (&70),Y ; target_address &3a3a a5 74 LDA &74 ; tmp &3a3c 99 00 09 STA &0900,Y ; key &3a3f e6 72 INC &72 ; size_low &3a41 d0 e2 BNE &3a25 ; decryption_stage_22_byte_loop &3a43 e6 73 INC &73 ; size_high &3a45 d0 de BNE &3a25 ; decryption_stage_22_byte_loop ; decryption_stage_23 # Decrypt &3a8b - &3b04 (disable video) &3a47 a9 08 LDA #&08 ; R8: Interlace and delay register &3a49 a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3a4b 8d 00 fe STA &fe00 ; video register number &3a4e 8e 01 fe STX &fe01 ; video register value &3a51 78 SEI &3a52 a2 05 LDX #&05 ; &3b05 &3a54 a0 3b LDY #&3b &3a56 86 70 STX &70 ; target_address_low &3a58 84 71 STY &71 ; target_address_high &3a5a a2 86 LDX #&86 ; &ff86 &3a5c a0 ff LDY #&ff &3a5e 86 72 STX &72 ; size_low &3a60 84 73 STY &73 ; size_high &3a62 a0 ff LDY #&ff ; decryption_stage_23_page_loop &3a64 c6 71 DEC &71 ; target_address_high &3a66 4c 6e 3a JMP &3a6e; decryption_stage_23_byte ; decryption_stage_23_byte_loop &3a69 88 DEY &3a6a c0 ff CPY #&ff &3a6c f0 f6 BEQ &3a64 ; decryption_stage_23_page_loop ; decryption_stage_23_byte &3a6e b1 70 LDA (&70),Y ; target_address &3a70 aa TAX &3a71 bd 00 09 LDA &0900,X ; key &3a74 85 74 STA &74 ; tmp &3a76 b9 00 09 LDA &0900,Y ; key &3a79 9d 00 09 STA &0900,X ; key &3a7c 91 70 STA (&70),Y ; target_address &3a7e a5 74 LDA &74 ; tmp &3a80 99 00 09 STA &0900,Y ; key &3a83 e6 72 INC &72 ; size_low &3a85 d0 e2 BNE &3a69 ; decryption_stage_23_byte_loop &3a87 e6 73 INC &73 ; size_high &3a89 d0 de BNE &3a69 ; decryption_stage_23_byte_loop ; decryption_stage_24 # Decrypt &3acb - &3b44 (check interrupts) &3a8b 08 PHP ; processor status &3a8c 68 PLA ; processor status &3a8d 29 04 AND #&04 ; INTERRUPT_DISABLE &3a8f f0 14 BEQ &3aa5 ; decryption_stage_24_failed # Misaligned code if interrupts enabled &3a91 78 SEI &3a92 a2 45 LDX #&45 ; &3b45 &3a94 a0 3b LDY #&3b &3a96 86 70 STX &70 ; target_address_low &3a98 84 71 STY &71 ; target_address_high &3a9a a2 86 LDX #&86 ; &ff86 &3a9c a0 ff LDY #&ff &3a9e 86 72 STX &72 ; size_low &3aa0 84 73 STY &73 ; size_high &3aa2 a0 ff LDY #&ff ; decryption_stage_24_page_loop &3aa4 c6 71 DEC &71 ; target_address_high &3aa6 4c ae 3a JMP &3aae; decryption_stage_24_byte ; decryption_stage_24_byte_loop &3aa9 88 DEY &3aaa c0 ff CPY #&ff &3aac f0 f6 BEQ &3aa4 ; decryption_stage_24_page_loop ; decryption_stage_24_byte &3aae b1 70 LDA (&70),Y ; target_address &3ab0 aa TAX &3ab1 bd 00 09 LDA &0900,X ; key &3ab4 85 74 STA &74 ; tmp &3ab6 b9 00 09 LDA &0900,Y ; key &3ab9 9d 00 09 STA &0900,X ; key &3abc 91 70 STA (&70),Y ; target_address &3abe a5 74 LDA &74 ; tmp &3ac0 99 00 09 STA &0900,Y ; key &3ac3 e6 72 INC &72 ; size_low &3ac5 d0 e2 BNE &3aa9 ; decryption_stage_24_byte_loop &3ac7 e6 73 INC &73 ; size_high &3ac9 d0 de BNE &3aa9 ; decryption_stage_24_byte_loop ; decryption_stage_25 # Decrypt &3b05 - &3b88 (set interrupts) &3acb 78 SEI &3acc a2 89 LDX #&89 ; &3b89 &3ace a0 3b LDY #&3b &3ad0 86 70 STX &70 ; target_address_low &3ad2 84 71 STY &71 ; target_address_high &3ad4 a2 7c LDX #&7c ; &ff7c &3ad6 a0 ff LDY #&ff &3ad8 86 72 STX &72 ; size_low &3ada 84 73 STY &73 ; size_high &3adc a0 ff LDY #&ff ; decryption_stage_25_page_loop &3ade c6 71 DEC &71 ; target_address_high &3ae0 4c e8 3a JMP &3ae8; decryption_stage_25_byte ; decryption_stage_25_byte_loop &3ae3 88 DEY &3ae4 c0 ff CPY #&ff &3ae6 f0 f6 BEQ &3ade ; decryption_stage_25_page_loop ; decryption_stage_25_byte &3ae8 b1 70 LDA (&70),Y ; target_address &3aea aa TAX &3aeb bd 00 09 LDA &0900,X ; key &3aee 85 74 STA &74 ; tmp &3af0 b9 00 09 LDA &0900,Y ; key &3af3 9d 00 09 STA &0900,X ; key &3af6 91 70 STA (&70),Y ; target_address &3af8 a5 74 LDA &74 ; tmp &3afa 99 00 09 STA &0900,Y ; key &3afd e6 72 INC &72 ; size_low &3aff d0 e2 BNE &3ae3 ; decryption_stage_25_byte_loop &3b01 e6 73 INC &73 ; size_high &3b03 d0 de BNE &3ae3 ; decryption_stage_25_byte_loop ; decryption_stage_26 # Decrypt &3b45 - &3bc8 (check interrupts) &3b05 08 PHP ; processor status &3b06 68 PLA ; processor status &3b07 29 04 AND #&04 ; INTERRUPT_DISABLE &3b09 f0 25 BEQ &3b30 ; decryption_stage_26_failed # Skip setting addresses if interrupts enabled &3b0b 78 SEI &3b0c a2 c9 LDX #&c9 ; &3bc9 &3b0e a0 3b LDY #&3b &3b10 86 70 STX &70 ; target_address_low &3b12 84 71 STY &71 ; target_address_high &3b14 a2 7c LDX #&7c ; &ff7c &3b16 a0 ff LDY #&ff &3b18 86 72 STX &72 ; size_low &3b1a 84 73 STY &73 ; size_high &3b1c a0 ff LDY #&ff ; decryption_stage_26_page_loop &3b1e c6 71 DEC &71 ; target_address_high &3b20 4c 28 3b JMP &3b28; decryption_stage_26_byte ; decryption_stage_26_byte_loop &3b23 88 DEY &3b24 c0 ff CPY #&ff &3b26 f0 f6 BEQ &3b1e ; decryption_stage_26_page_loop ; decryption_stage_26_byte &3b28 b1 70 LDA (&70),Y ; target_address &3b2a aa TAX &3b2b bd 00 09 LDA &0900,X ; key &3b2e 85 74 STA &74 ; tmp &3b30 b9 00 09 LDA &0900,Y ; key &3b33 9d 00 09 STA &0900,X ; key &3b36 91 70 STA (&70),Y ; target_address &3b38 a5 74 LDA &74 ; tmp &3b3a 99 00 09 STA &0900,Y ; key &3b3d e6 72 INC &72 ; size_low &3b3f d0 e2 BNE &3b23 ; decryption_stage_26_byte_loop &3b41 e6 73 INC &73 ; size_high &3b43 d0 de BNE &3b23 ; decryption_stage_26_byte_loop ; decryption_stage_27 # Decrypt &3b89 - &3c02 (disable video) &3b45 a9 08 LDA #&08 ; R8: Interlace and delay register &3b47 a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3b49 8d 00 fe STA &fe00 ; video register number &3b4c 8e 01 fe STX &fe01 ; video register value &3b4f 78 SEI &3b50 a2 03 LDX #&03 ; &3c03 &3b52 a0 3c LDY #&3c &3b54 86 70 STX &70 ; target_address_low &3b56 84 71 STY &71 ; target_address_high &3b58 a2 86 LDX #&86 ; &ff86 &3b5a a0 ff LDY #&ff &3b5c 86 72 STX &72 ; size_low &3b5e 84 73 STY &73 ; size_high &3b60 a0 ff LDY #&ff ; decryption_stage_27_page_loop &3b62 c6 71 DEC &71 ; target_address_high &3b64 4c 6c 3b JMP &3b6c; decryption_stage_27_byte ; decryption_stage_27_byte_loop &3b67 88 DEY &3b68 c0 ff CPY #&ff &3b6a f0 f6 BEQ &3b62 ; decryption_stage_27_page_loop ; decryption_stage_27_byte &3b6c b1 70 LDA (&70),Y ; target_address &3b6e aa TAX &3b6f bd 00 09 LDA &0900,X ; key &3b72 85 74 STA &74 ; tmp &3b74 b9 00 09 LDA &0900,Y ; key &3b77 9d 00 09 STA &0900,X ; key &3b7a 91 70 STA (&70),Y ; target_address &3b7c a5 74 LDA &74 ; tmp &3b7e 99 00 09 STA &0900,Y ; key &3b81 e6 72 INC &72 ; size_low &3b83 d0 e2 BNE &3b67 ; decryption_stage_27_byte_loop &3b85 e6 73 INC &73 ; size_high &3b87 d0 de BNE &3b67 ; decryption_stage_27_byte_loop ; decryption_stage_28 # Decrypt &3bc9 - &3c42 (check interrupts) &3b89 08 PHP ; processor status &3b8a 68 PLA ; processor status &3b8b 29 04 AND #&04 ; INTERRUPT_DISABLE &3b8d f0 1c BEQ &3bab ; decryption_stage_28_failed # Misaligned code if interrupts enabled &3b8f 78 SEI &3b90 a2 43 LDX #&43 ; &3c43 &3b92 a0 3c LDY #&3c &3b94 86 70 STX &70 ; target_address_low &3b96 84 71 STY &71 ; target_address_high &3b98 a2 86 LDX #&86 ; &ff86 &3b9a a0 ff LDY #&ff &3b9c 86 72 STX &72 ; size_low &3b9e 84 73 STY &73 ; size_high &3ba0 a0 ff LDY #&ff ; decryption_stage_28_page_loop &3ba2 c6 71 DEC &71 ; target_address_high &3ba4 4c ac 3b JMP &3bac; decryption_stage_28_byte ; decryption_stage_28_byte_loop &3ba7 88 DEY &3ba8 c0 ff CPY #&ff &3baa f0 f6 BEQ &3ba2 ; decryption_stage_28_page_loop ; decryption_stage_28_byte &3bac b1 70 LDA (&70),Y ; target_address &3bae aa TAX &3baf bd 00 09 LDA &0900,X ; key &3bb2 85 74 STA &74 ; tmp &3bb4 b9 00 09 LDA &0900,Y ; key &3bb7 9d 00 09 STA &0900,X ; key &3bba 91 70 STA (&70),Y ; target_address &3bbc a5 74 LDA &74 ; tmp &3bbe 99 00 09 STA &0900,Y ; key &3bc1 e6 72 INC &72 ; size_low &3bc3 d0 e2 BNE &3ba7 ; decryption_stage_28_byte_loop &3bc5 e6 73 INC &73 ; size_high &3bc7 d0 de BNE &3ba7 ; decryption_stage_28_byte_loop ; decryption_stage_29 # Decrypt &3c03 - &3c86 (set interrupts) &3bc9 78 SEI &3bca a2 87 LDX #&87 ; &3c87 &3bcc a0 3c LDY #&3c &3bce 86 70 STX &70 ; target_address_low &3bd0 84 71 STY &71 ; target_address_high &3bd2 a2 7c LDX #&7c ; &ff7c &3bd4 a0 ff LDY #&ff &3bd6 86 72 STX &72 ; size_low &3bd8 84 73 STY &73 ; size_high &3bda a0 ff LDY #&ff ; decryption_stage_29_page_loop &3bdc c6 71 DEC &71 ; target_address_high &3bde 4c e6 3b JMP &3be6; decryption_stage_29_byte ; decryption_stage_29_byte_loop &3be1 88 DEY &3be2 c0 ff CPY #&ff &3be4 f0 f6 BEQ &3bdc ; decryption_stage_29_page_loop ; decryption_stage_29_byte &3be6 b1 70 LDA (&70),Y ; target_address &3be8 aa TAX &3be9 bd 00 09 LDA &0900,X ; key &3bec 85 74 STA &74 ; tmp &3bee b9 00 09 LDA &0900,Y ; key &3bf1 9d 00 09 STA &0900,X ; key &3bf4 91 70 STA (&70),Y ; target_address &3bf6 a5 74 LDA &74 ; tmp &3bf8 99 00 09 STA &0900,Y ; key &3bfb e6 72 INC &72 ; size_low &3bfd d0 e2 BNE &3be1 ; decryption_stage_29_byte_loop &3bff e6 73 INC &73 ; size_high &3c01 d0 de BNE &3be1 ; decryption_stage_29_byte_loop ; decryption_stage_30 # Decrypt &3c43 - &3cc6 (check interrupts) &3c03 08 PHP ; processor status &3c04 68 PLA ; processor status &3c05 29 04 AND #&04 ; INTERRUPT_DISABLE &3c07 f0 1c BEQ &3c25 ; decryption_stage_30_failed # Misaligned code if interrupts enabled &3c09 78 SEI &3c0a a2 c7 LDX #&c7 ; &3cc7 &3c0c a0 3c LDY #&3c &3c0e 86 70 STX &70 ; target_address_low &3c10 84 71 STY &71 ; target_address_high &3c12 a2 7c LDX #&7c ; &ff7c &3c14 a0 ff LDY #&ff &3c16 86 72 STX &72 ; size_low &3c18 84 73 STY &73 ; size_high &3c1a a0 ff LDY #&ff ; decryption_stage_30_page_loop &3c1c c6 71 DEC &71 ; target_address_high &3c1e 4c 26 3c JMP &3c26; decryption_stage_30_byte ; decryption_stage_30_byte_loop &3c21 88 DEY &3c22 c0 ff CPY #&ff &3c24 f0 f6 BEQ &3c1c ; decryption_stage_30_page_loop ; decryption_stage_30_byte &3c26 b1 70 LDA (&70),Y ; target_address &3c28 aa TAX &3c29 bd 00 09 LDA &0900,X ; key &3c2c 85 74 STA &74 ; tmp &3c2e b9 00 09 LDA &0900,Y ; key &3c31 9d 00 09 STA &0900,X ; key &3c34 91 70 STA (&70),Y ; target_address &3c36 a5 74 LDA &74 ; tmp &3c38 99 00 09 STA &0900,Y ; key &3c3b e6 72 INC &72 ; size_low &3c3d d0 e2 BNE &3c21 ; decryption_stage_30_byte_loop &3c3f e6 73 INC &73 ; size_high &3c41 d0 de BNE &3c21 ; decryption_stage_30_byte_loop ; decryption_stage_31 # Decrypt &3c87 - &3d00 (disable video) &3c43 a9 08 LDA #&08 ; R8: Interlace and delay register &3c45 a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3c47 8d 00 fe STA &fe00 ; video register number &3c4a 8e 01 fe STX &fe01 ; video register value &3c4d 78 SEI &3c4e a2 01 LDX #&01 ; &3d01 &3c50 a0 3d LDY #&3d &3c52 86 70 STX &70 ; target_address_low &3c54 84 71 STY &71 ; target_address_high &3c56 a2 86 LDX #&86 ; &ff86 &3c58 a0 ff LDY #&ff &3c5a 86 72 STX &72 ; size_low &3c5c 84 73 STY &73 ; size_high &3c5e a0 ff LDY #&ff ; decryption_stage_31_page_loop &3c60 c6 71 DEC &71 ; target_address_high &3c62 4c 6a 3c JMP &3c6a; decryption_stage_31_byte ; decryption_stage_31_byte_loop &3c65 88 DEY &3c66 c0 ff CPY #&ff &3c68 f0 f6 BEQ &3c60 ; decryption_stage_31_page_loop ; decryption_stage_31_byte &3c6a b1 70 LDA (&70),Y ; target_address &3c6c aa TAX &3c6d bd 00 09 LDA &0900,X ; key &3c70 85 74 STA &74 ; tmp &3c72 b9 00 09 LDA &0900,Y ; key &3c75 9d 00 09 STA &0900,X ; key &3c78 91 70 STA (&70),Y ; target_address &3c7a a5 74 LDA &74 ; tmp &3c7c 99 00 09 STA &0900,Y ; key &3c7f e6 72 INC &72 ; size_low &3c81 d0 e2 BNE &3c65 ; decryption_stage_31_byte_loop &3c83 e6 73 INC &73 ; size_high &3c85 d0 de BNE &3c65 ; decryption_stage_31_byte_loop ; decryption_stage_32 # Decrypt &3cc7 - &3d40 (check interrupts) &3c87 08 PHP ; processor status &3c88 68 PLA ; processor status &3c89 29 04 AND #&04 ; INTERRUPT_DISABLE &3c8b f0 24 BEQ &3cb1 ; decryption_stage_32_failed # Misaligned code if interrupts enabled &3c8d 78 SEI &3c8e a2 41 LDX #&41 ; &3d41 &3c90 a0 3d LDY #&3d &3c92 86 70 STX &70 ; target_address_low &3c94 84 71 STY &71 ; target_address_high &3c96 a2 86 LDX #&86 ; &ff86 &3c98 a0 ff LDY #&ff &3c9a 86 72 STX &72 ; size_low &3c9c 84 73 STY &73 ; size_high &3c9e a0 ff LDY #&ff ; decryption_stage_32_page_loop &3ca0 c6 71 DEC &71 ; target_address_high &3ca2 4c aa 3c JMP &3caa; decryption_stage_32_byte ; decryption_stage_32_byte_loop &3ca5 88 DEY &3ca6 c0 ff CPY #&ff &3ca8 f0 f6 BEQ &3ca0 ; decryption_stage_32_page_loop ; decryption_stage_32_byte &3caa b1 70 LDA (&70),Y ; target_address &3cac aa TAX &3cad bd 00 09 LDA &0900,X ; key &3cb0 85 74 STA &74 ; tmp &3cb2 b9 00 09 LDA &0900,Y ; key &3cb5 9d 00 09 STA &0900,X ; key &3cb8 91 70 STA (&70),Y ; target_address &3cba a5 74 LDA &74 ; tmp &3cbc 99 00 09 STA &0900,Y ; key &3cbf e6 72 INC &72 ; size_low &3cc1 d0 e2 BNE &3ca5 ; decryption_stage_32_byte_loop &3cc3 e6 73 INC &73 ; size_high &3cc5 d0 de BNE &3ca5 ; decryption_stage_32_byte_loop ; decryption_stage_33 # Decrypt &3d01 - &3d84 (set interrupts) &3cc7 78 SEI &3cc8 a2 85 LDX #&85 ; &3d85 &3cca a0 3d LDY #&3d &3ccc 86 70 STX &70 ; target_address_low &3cce 84 71 STY &71 ; target_address_high &3cd0 a2 7c LDX #&7c ; &ff7c &3cd2 a0 ff LDY #&ff &3cd4 86 72 STX &72 ; size_low &3cd6 84 73 STY &73 ; size_high &3cd8 a0 ff LDY #&ff ; decryption_stage_33_page_loop &3cda c6 71 DEC &71 ; target_address_high &3cdc 4c e4 3c JMP &3ce4; decryption_stage_33_byte ; decryption_stage_33_byte_loop &3cdf 88 DEY &3ce0 c0 ff CPY #&ff &3ce2 f0 f6 BEQ &3cda ; decryption_stage_33_page_loop ; decryption_stage_33_byte &3ce4 b1 70 LDA (&70),Y ; target_address &3ce6 aa TAX &3ce7 bd 00 09 LDA &0900,X ; key &3cea 85 74 STA &74 ; tmp &3cec b9 00 09 LDA &0900,Y ; key &3cef 9d 00 09 STA &0900,X ; key &3cf2 91 70 STA (&70),Y ; target_address &3cf4 a5 74 LDA &74 ; tmp &3cf6 99 00 09 STA &0900,Y ; key &3cf9 e6 72 INC &72 ; size_low &3cfb d0 e2 BNE &3cdf ; decryption_stage_33_byte_loop &3cfd e6 73 INC &73 ; size_high &3cff d0 de BNE &3cdf ; decryption_stage_33_byte_loop ; decryption_stage_34 # Decrypt &3d41 - &3dc4 (check interrupts) &3d01 08 PHP ; processor status &3d02 68 PLA ; processor status &3d03 29 04 AND #&04 ; INTERRUPT_DISABLE &3d05 f0 15 BEQ &3d1c ; decryption_stage_34_failed # Skip setting addresses if interrupts enabled &3d07 78 SEI &3d08 a2 c5 LDX #&c5 ; &3dc5 &3d0a a0 3d LDY #&3d &3d0c 86 70 STX &70 ; target_address_low &3d0e 84 71 STY &71 ; target_address_high &3d10 a2 7c LDX #&7c ; &ff7c &3d12 a0 ff LDY #&ff &3d14 86 72 STX &72 ; size_low &3d16 84 73 STY &73 ; size_high &3d18 a0 ff LDY #&ff ; decryption_stage_34_page_loop &3d1a c6 71 DEC &71 ; target_address_high &3d1c 4c 24 3d JMP &3d24; decryption_stage_34_byte ; decryption_stage_34_byte_loop &3d1f 88 DEY &3d20 c0 ff CPY #&ff &3d22 f0 f6 BEQ &3d1a ; decryption_stage_34_page_loop ; decryption_stage_34_byte &3d24 b1 70 LDA (&70),Y ; target_address &3d26 aa TAX &3d27 bd 00 09 LDA &0900,X ; key &3d2a 85 74 STA &74 ; tmp &3d2c b9 00 09 LDA &0900,Y ; key &3d2f 9d 00 09 STA &0900,X ; key &3d32 91 70 STA (&70),Y ; target_address &3d34 a5 74 LDA &74 ; tmp &3d36 99 00 09 STA &0900,Y ; key &3d39 e6 72 INC &72 ; size_low &3d3b d0 e2 BNE &3d1f ; decryption_stage_34_byte_loop &3d3d e6 73 INC &73 ; size_high &3d3f d0 de BNE &3d1f ; decryption_stage_34_byte_loop ; decryption_stage_35 # Decrypt &3d85 - &3dfe (disable video) &3d41 a9 08 LDA #&08 ; R8: Interlace and delay register &3d43 a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3d45 8d 00 fe STA &fe00 ; video register number &3d48 8e 01 fe STX &fe01 ; video register value &3d4b 78 SEI &3d4c a2 ff LDX #&ff ; &3dff &3d4e a0 3d LDY #&3d &3d50 86 70 STX &70 ; target_address_low &3d52 84 71 STY &71 ; target_address_high &3d54 a2 86 LDX #&86 ; &ff86 &3d56 a0 ff LDY #&ff &3d58 86 72 STX &72 ; size_low &3d5a 84 73 STY &73 ; size_high &3d5c a0 ff LDY #&ff ; decryption_stage_35_page_loop &3d5e c6 71 DEC &71 ; target_address_high &3d60 4c 68 3d JMP &3d68; decryption_stage_35_byte ; decryption_stage_35_byte_loop &3d63 88 DEY &3d64 c0 ff CPY #&ff &3d66 f0 f6 BEQ &3d5e ; decryption_stage_35_page_loop ; decryption_stage_35_byte &3d68 b1 70 LDA (&70),Y ; target_address &3d6a aa TAX &3d6b bd 00 09 LDA &0900,X ; key &3d6e 85 74 STA &74 ; tmp &3d70 b9 00 09 LDA &0900,Y ; key &3d73 9d 00 09 STA &0900,X ; key &3d76 91 70 STA (&70),Y ; target_address &3d78 a5 74 LDA &74 ; tmp &3d7a 99 00 09 STA &0900,Y ; key &3d7d e6 72 INC &72 ; size_low &3d7f d0 e2 BNE &3d63 ; decryption_stage_35_byte_loop &3d81 e6 73 INC &73 ; size_high &3d83 d0 de BNE &3d63 ; decryption_stage_35_byte_loop ; decryption_stage_36 # Decrypt &3dc5 - &3e3e (check interrupts) &3d85 08 PHP ; processor status &3d86 68 PLA ; processor status &3d87 29 04 AND #&04 ; INTERRUPT_DISABLE &3d89 f0 1d BEQ &3da8 ; decryption_stage_36_failed # Skip setting addresses if interrupts enabled &3d8b 78 SEI &3d8c a2 3f LDX #&3f ; &3e3f &3d8e a0 3e LDY #&3e &3d90 86 70 STX &70 ; target_address_low &3d92 84 71 STY &71 ; target_address_high &3d94 a2 86 LDX #&86 ; &ff86 &3d96 a0 ff LDY #&ff &3d98 86 72 STX &72 ; size_low &3d9a 84 73 STY &73 ; size_high &3d9c a0 ff LDY #&ff ; decryption_stage_36_page_loop &3d9e c6 71 DEC &71 ; target_address_high &3da0 4c a8 3d JMP &3da8; decryption_stage_36_byte ; decryption_stage_36_byte_loop &3da3 88 DEY &3da4 c0 ff CPY #&ff &3da6 f0 f6 BEQ &3d9e ; decryption_stage_36_page_loop ; decryption_stage_36_byte &3da8 b1 70 LDA (&70),Y ; target_address &3daa aa TAX &3dab bd 00 09 LDA &0900,X ; key &3dae 85 74 STA &74 ; tmp &3db0 b9 00 09 LDA &0900,Y ; key &3db3 9d 00 09 STA &0900,X ; key &3db6 91 70 STA (&70),Y ; target_address &3db8 a5 74 LDA &74 ; tmp &3dba 99 00 09 STA &0900,Y ; key &3dbd e6 72 INC &72 ; size_low &3dbf d0 e2 BNE &3da3 ; decryption_stage_36_byte_loop &3dc1 e6 73 INC &73 ; size_high &3dc3 d0 de BNE &3da3 ; decryption_stage_36_byte_loop ; decryption_stage_37 # Decrypt &3dff - &3e82 (set interrupts) &3dc5 78 SEI &3dc6 a2 83 LDX #&83 ; &3e83 &3dc8 a0 3e LDY #&3e &3dca 86 70 STX &70 ; target_address_low &3dcc 84 71 STY &71 ; target_address_high &3dce a2 7c LDX #&7c ; &ff7c &3dd0 a0 ff LDY #&ff &3dd2 86 72 STX &72 ; size_low &3dd4 84 73 STY &73 ; size_high &3dd6 a0 ff LDY #&ff ; decryption_stage_37_page_loop &3dd8 c6 71 DEC &71 ; target_address_high &3dda 4c e2 3d JMP &3de2; decryption_stage_37_byte ; decryption_stage_37_byte_loop &3ddd 88 DEY &3dde c0 ff CPY #&ff &3de0 f0 f6 BEQ &3dd8 ; decryption_stage_37_page_loop ; decryption_stage_37_byte &3de2 b1 70 LDA (&70),Y ; target_address &3de4 aa TAX &3de5 bd 00 09 LDA &0900,X ; key &3de8 85 74 STA &74 ; tmp &3dea b9 00 09 LDA &0900,Y ; key &3ded 9d 00 09 STA &0900,X ; key &3df0 91 70 STA (&70),Y ; target_address &3df2 a5 74 LDA &74 ; tmp &3df4 99 00 09 STA &0900,Y ; key &3df7 e6 72 INC &72 ; size_low &3df9 d0 e2 BNE &3ddd ; decryption_stage_37_byte_loop &3dfb e6 73 INC &73 ; size_high &3dfd d0 de BNE &3ddd ; decryption_stage_37_byte_loop ; decryption_stage_38 # Decrypt &3e3f - &3ec2 (check interrupts) &3dff 08 PHP ; processor status &3e00 68 PLA ; processor status &3e01 29 04 AND #&04 ; INTERRUPT_DISABLE &3e03 f0 21 BEQ &3e26 ; decryption_stage_38_failed # Misaligned code if interrupts enabled &3e05 78 SEI &3e06 a2 c3 LDX #&c3 ; &3ec3 &3e08 a0 3e LDY #&3e &3e0a 86 70 STX &70 ; target_address_low &3e0c 84 71 STY &71 ; target_address_high &3e0e a2 7c LDX #&7c ; &ff7c &3e10 a0 ff LDY #&ff &3e12 86 72 STX &72 ; size_low &3e14 84 73 STY &73 ; size_high &3e16 a0 ff LDY #&ff ; decryption_stage_38_page_loop &3e18 c6 71 DEC &71 ; target_address_high &3e1a 4c 22 3e JMP &3e22; decryption_stage_38_byte ; decryption_stage_38_byte_loop &3e1d 88 DEY &3e1e c0 ff CPY #&ff &3e20 f0 f6 BEQ &3e18 ; decryption_stage_38_page_loop ; decryption_stage_38_byte &3e22 b1 70 LDA (&70),Y ; target_address &3e24 aa TAX &3e25 bd 00 09 LDA &0900,X ; key &3e28 85 74 STA &74 ; tmp &3e2a b9 00 09 LDA &0900,Y ; key &3e2d 9d 00 09 STA &0900,X ; key &3e30 91 70 STA (&70),Y ; target_address &3e32 a5 74 LDA &74 ; tmp &3e34 99 00 09 STA &0900,Y ; key &3e37 e6 72 INC &72 ; size_low &3e39 d0 e2 BNE &3e1d ; decryption_stage_38_byte_loop &3e3b e6 73 INC &73 ; size_high &3e3d d0 de BNE &3e1d ; decryption_stage_38_byte_loop ; decryption_stage_39 # Decrypt &3e83 - &3efc (disable video) &3e3f a9 08 LDA #&08 ; R8: Interlace and delay register &3e41 a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3e43 8d 00 fe STA &fe00 ; video register number &3e46 8e 01 fe STX &fe01 ; video register value &3e49 78 SEI &3e4a a2 fd LDX #&fd ; &3efd &3e4c a0 3e LDY #&3e &3e4e 86 70 STX &70 ; target_address_low &3e50 84 71 STY &71 ; target_address_high &3e52 a2 86 LDX #&86 ; &ff86 &3e54 a0 ff LDY #&ff &3e56 86 72 STX &72 ; size_low &3e58 84 73 STY &73 ; size_high &3e5a a0 ff LDY #&ff ; decryption_stage_39_page_loop &3e5c c6 71 DEC &71 ; target_address_high &3e5e 4c 66 3e JMP &3e66; decryption_stage_39_byte ; decryption_stage_39_byte_loop &3e61 88 DEY &3e62 c0 ff CPY #&ff &3e64 f0 f6 BEQ &3e5c ; decryption_stage_39_page_loop ; decryption_stage_39_byte &3e66 b1 70 LDA (&70),Y ; target_address &3e68 aa TAX &3e69 bd 00 09 LDA &0900,X ; key &3e6c 85 74 STA &74 ; tmp &3e6e b9 00 09 LDA &0900,Y ; key &3e71 9d 00 09 STA &0900,X ; key &3e74 91 70 STA (&70),Y ; target_address &3e76 a5 74 LDA &74 ; tmp &3e78 99 00 09 STA &0900,Y ; key &3e7b e6 72 INC &72 ; size_low &3e7d d0 e2 BNE &3e61 ; decryption_stage_39_byte_loop &3e7f e6 73 INC &73 ; size_high &3e81 d0 de BNE &3e61 ; decryption_stage_39_byte_loop ; decryption_stage_40 # Decrypt &3ec3 - &3f3c (check interrupts) &3e83 08 PHP ; processor status &3e84 68 PLA ; processor status &3e85 29 04 AND #&04 ; INTERRUPT_DISABLE &3e87 f0 17 BEQ &3ea0 ; decryption_stage_40_failed # Misaligned code if interrupts enabled &3e89 78 SEI &3e8a a2 3d LDX #&3d ; &3f3d &3e8c a0 3f LDY #&3f &3e8e 86 70 STX &70 ; target_address_low &3e90 84 71 STY &71 ; target_address_high &3e92 a2 86 LDX #&86 ; &ff86 &3e94 a0 ff LDY #&ff &3e96 86 72 STX &72 ; size_low &3e98 84 73 STY &73 ; size_high &3e9a a0 ff LDY #&ff ; decryption_stage_40_page_loop &3e9c c6 71 DEC &71 ; target_address_high &3e9e 4c a6 3e JMP &3ea6; decryption_stage_40_byte ; decryption_stage_40_byte_loop &3ea1 88 DEY &3ea2 c0 ff CPY #&ff &3ea4 f0 f6 BEQ &3e9c ; decryption_stage_40_page_loop ; decryption_stage_40_byte &3ea6 b1 70 LDA (&70),Y ; target_address &3ea8 aa TAX &3ea9 bd 00 09 LDA &0900,X ; key &3eac 85 74 STA &74 ; tmp &3eae b9 00 09 LDA &0900,Y ; key &3eb1 9d 00 09 STA &0900,X ; key &3eb4 91 70 STA (&70),Y ; target_address &3eb6 a5 74 LDA &74 ; tmp &3eb8 99 00 09 STA &0900,Y ; key &3ebb e6 72 INC &72 ; size_low &3ebd d0 e2 BNE &3ea1 ; decryption_stage_40_byte_loop &3ebf e6 73 INC &73 ; size_high &3ec1 d0 de BNE &3ea1 ; decryption_stage_40_byte_loop ; decryption_stage_41 # Decrypt &3efd - &3f80 (set interrupts) &3ec3 78 SEI &3ec4 a2 81 LDX #&81 ; &3f81 &3ec6 a0 3f LDY #&3f &3ec8 86 70 STX &70 ; target_address_low &3eca 84 71 STY &71 ; target_address_high &3ecc a2 7c LDX #&7c ; &ff7c &3ece a0 ff LDY #&ff &3ed0 86 72 STX &72 ; size_low &3ed2 84 73 STY &73 ; size_high &3ed4 a0 ff LDY #&ff ; decryption_stage_41_page_loop &3ed6 c6 71 DEC &71 ; target_address_high &3ed8 4c e0 3e JMP &3ee0; decryption_stage_41_byte ; decryption_stage_41_byte_loop &3edb 88 DEY &3edc c0 ff CPY #&ff &3ede f0 f6 BEQ &3ed6 ; decryption_stage_41_page_loop ; decryption_stage_41_byte &3ee0 b1 70 LDA (&70),Y ; target_address &3ee2 aa TAX &3ee3 bd 00 09 LDA &0900,X ; key &3ee6 85 74 STA &74 ; tmp &3ee8 b9 00 09 LDA &0900,Y ; key &3eeb 9d 00 09 STA &0900,X ; key &3eee 91 70 STA (&70),Y ; target_address &3ef0 a5 74 LDA &74 ; tmp &3ef2 99 00 09 STA &0900,Y ; key &3ef5 e6 72 INC &72 ; size_low &3ef7 d0 e2 BNE &3edb ; decryption_stage_41_byte_loop &3ef9 e6 73 INC &73 ; size_high &3efb d0 de BNE &3edb ; decryption_stage_41_byte_loop ; decryption_stage_42 # Decrypt &3f3d - &7f81 (check interrupts) &3efd 08 PHP ; processor status &3efe 68 PLA ; processor status &3eff 29 04 AND #&04 ; INTERRUPT_DISABLE &3f01 f0 21 BEQ &3f24 ; decryption_stage_42_failed # Break if interrupts enabled &3f03 78 SEI &3f04 a2 82 LDX #&82 ; &7f82 &3f06 a0 7f LDY #&7f &3f08 86 70 STX &70 ; target_address_low &3f0a 84 71 STY &71 ; target_address_high &3f0c a2 bb LDX #&bb ; &bfbb &3f0e a0 bf LDY #&bf &3f10 86 72 STX &72 ; size_low &3f12 84 73 STY &73 ; size_high &3f14 a0 ff LDY #&ff ; decryption_stage_42_page_loop &3f16 c6 71 DEC &71 ; target_address_high &3f18 4c 20 3f JMP &3f20; decryption_stage_42_byte ; decryption_stage_42_byte_loop &3f1b 88 DEY &3f1c c0 ff CPY #&ff &3f1e f0 f6 BEQ &3f16 ; decryption_stage_42_page_loop ; decryption_stage_42_byte &3f20 b1 70 LDA (&70),Y ; target_address &3f22 aa TAX &3f23 bd 00 09 LDA &0900,X ; key &3f26 85 74 STA &74 ; tmp &3f28 b9 00 09 LDA &0900,Y ; key &3f2b 9d 00 09 STA &0900,X ; key &3f2e 91 70 STA (&70),Y ; target_address &3f30 a5 74 LDA &74 ; tmp &3f32 99 00 09 STA &0900,Y ; key &3f35 e6 72 INC &72 ; size_low &3f37 d0 e2 BNE &3f1b ; decryption_stage_42_byte_loop &3f39 e6 73 INC &73 ; size_high &3f3b d0 de BNE &3f1b ; decryption_stage_42_byte_loop ; decryption_stage_43 # Decrypt &3f81 - &7f81 (disable video) &3f3d a9 08 LDA #&08 ; R8: Interlace and delay register &3f3f a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &3f41 8d 00 fe STA &fe00 ; video register number &3f44 8e 01 fe STX &fe01 ; video register value &3f47 78 SEI &3f48 a2 82 LDX #&82 ; &7f82 &3f4a a0 7f LDY #&7f &3f4c 86 70 STX &70 ; target_address_low &3f4e 84 71 STY &71 ; target_address_high &3f50 a2 ff LDX #&ff ; &bfff &3f52 a0 bf LDY #&bf &3f54 86 72 STX &72 ; size_low &3f56 84 73 STY &73 ; size_high &3f58 a0 ff LDY #&ff ; decryption_stage_43_page_loop &3f5a c6 71 DEC &71 ; target_address_high &3f5c 4c 64 3f JMP &3f64; decryption_stage_43_byte ; decryption_stage_43_byte_loop &3f5f 88 DEY &3f60 c0 ff CPY #&ff &3f62 f0 f6 BEQ &3f5a ; decryption_stage_43_page_loop ; decryption_stage_43_byte &3f64 b1 70 LDA (&70),Y ; target_address &3f66 aa TAX &3f67 bd 00 09 LDA &0900,X ; key &3f6a 85 74 STA &74 ; tmp &3f6c b9 00 09 LDA &0900,Y ; key &3f6f 9d 00 09 STA &0900,X ; key &3f72 91 70 STA (&70),Y ; target_address &3f74 a5 74 LDA &74 ; tmp &3f76 99 00 09 STA &0900,Y ; key &3f79 e6 72 INC &72 ; size_low &3f7b d0 e2 BNE &3f5f ; decryption_stage_43_byte_loop &3f7d e6 73 INC &73 ; size_high &3f7f d0 de BNE &3f5f ; decryption_stage_43_byte_loop ; decryption_stage_44 # Decrypt &3fc1 - &7f81 (check interrupts) &3f81 08 PHP ; processor status &3f82 68 PLA ; processor status &3f83 29 04 AND #&04 ; INTERRUPT_DISABLE &3f85 f0 17 BEQ &3f9e ; decryption_stage_44_failed # Misaligned code if interrupts enabled &3f87 78 SEI &3f88 a2 82 LDX #&82 ; &7f82 &3f8a a0 7f LDY #&7f &3f8c 86 70 STX &70 ; target_address_low &3f8e 84 71 STY &71 ; target_address_high &3f90 a2 3f LDX #&3f ; &c03f &3f92 a0 c0 LDY #&c0 &3f94 86 72 STX &72 ; size_low &3f96 84 73 STY &73 ; size_high &3f98 a0 ff LDY #&ff ; decryption_stage_44_page_loop &3f9a c6 71 DEC &71 ; target_address_high &3f9c 4c a4 3f JMP &3fa4; decryption_stage_44_byte ; decryption_stage_44_byte_loop &3f9f 88 DEY &3fa0 c0 ff CPY #&ff &3fa2 f0 f6 BEQ &3f9a ; decryption_stage_44_page_loop ; decryption_stage_44_byte &3fa4 b1 70 LDA (&70),Y ; target_address &3fa6 aa TAX &3fa7 bd 00 09 LDA &0900,X ; key &3faa 85 74 STA &74 ; tmp &3fac b9 00 09 LDA &0900,Y ; key &3faf 9d 00 09 STA &0900,X ; key &3fb2 91 70 STA (&70),Y ; target_address &3fb4 a5 74 LDA &74 ; tmp &3fb6 99 00 09 STA &0900,Y ; key &3fb9 e6 72 INC &72 ; size_low &3fbb d0 e2 BNE &3f9f ; decryption_stage_44_byte_loop &3fbd e6 73 INC &73 ; size_high &3fbf d0 de BNE &3f9f ; decryption_stage_44_byte_loop ; decryption_stage_45 # Decrypt &3ffb - &7f81 (set interrupts) &3fc1 78 SEI &3fc2 a2 82 LDX #&82 ; &7f82 &3fc4 a0 7f LDY #&7f &3fc6 86 70 STX &70 ; target_address_low &3fc8 84 71 STY &71 ; target_address_high &3fca a2 79 LDX #&79 ; &c079 &3fcc a0 c0 LDY #&c0 &3fce 86 72 STX &72 ; size_low &3fd0 84 73 STY &73 ; size_high &3fd2 a0 ff LDY #&ff ; decryption_stage_45_page_loop &3fd4 c6 71 DEC &71 ; target_address_high &3fd6 4c de 3f JMP &3fde; decryption_stage_45_byte ; decryption_stage_45_byte_loop &3fd9 88 DEY &3fda c0 ff CPY #&ff &3fdc f0 f6 BEQ &3fd4 ; decryption_stage_45_page_loop ; decryption_stage_45_byte &3fde b1 70 LDA (&70),Y ; target_address &3fe0 aa TAX &3fe1 bd 00 09 LDA &0900,X ; key &3fe4 85 74 STA &74 ; tmp &3fe6 b9 00 09 LDA &0900,Y ; key &3fe9 9d 00 09 STA &0900,X ; key &3fec 91 70 STA (&70),Y ; target_address &3fee a5 74 LDA &74 ; tmp &3ff0 99 00 09 STA &0900,Y ; key &3ff3 e6 72 INC &72 ; size_low &3ff5 d0 e2 BNE &3fd9 ; decryption_stage_45_byte_loop &3ff7 e6 73 INC &73 ; size_high &3ff9 d0 de BNE &3fd9 ; decryption_stage_45_byte_loop ; decryption_stage_46 # Decrypt &403b - &7f81 (check interrupts) &3ffb 08 PHP ; processor status &3ffc 68 PLA ; processor status &3ffd 29 04 AND #&04 ; INTERRUPT_DISABLE &3fff f0 24 BEQ &4025 ; decryption_stage_46_failed # Misaligned code if interrupts enabled &4001 78 SEI &4002 a2 82 LDX #&82 ; &7f82 &4004 a0 7f LDY #&7f &4006 86 70 STX &70 ; target_address_low &4008 84 71 STY &71 ; target_address_high &400a a2 b9 LDX #&b9 ; &c0b9 &400c a0 c0 LDY #&c0 &400e 86 72 STX &72 ; size_low &4010 84 73 STY &73 ; size_high &4012 a0 ff LDY #&ff ; decryption_stage_46_page_loop &4014 c6 71 DEC &71 ; target_address_high &4016 4c 1e 40 JMP &401e; decryption_stage_46_byte ; decryption_stage_46_byte_loop &4019 88 DEY &401a c0 ff CPY #&ff &401c f0 f6 BEQ &4014 ; decryption_stage_46_page_loop ; decryption_stage_46_byte &401e b1 70 LDA (&70),Y ; target_address &4020 aa TAX &4021 bd 00 09 LDA &0900,X ; key &4024 85 74 STA &74 ; tmp &4026 b9 00 09 LDA &0900,Y ; key &4029 9d 00 09 STA &0900,X ; key &402c 91 70 STA (&70),Y ; target_address &402e a5 74 LDA &74 ; tmp &4030 99 00 09 STA &0900,Y ; key &4033 e6 72 INC &72 ; size_low &4035 d0 e2 BNE &4019 ; decryption_stage_46_byte_loop &4037 e6 73 INC &73 ; size_high &4039 d0 de BNE &4019 ; decryption_stage_46_byte_loop ; decryption_stage_47 # Decrypt &407f - &7f81 (disable video) &403b a9 08 LDA #&08 ; R8: Interlace and delay register &403d a2 f0 LDX #&f0 ; normal sync mode, disable video output, disable cursor output &403f 8d 00 fe STA &fe00 ; video register number &4042 8e 01 fe STX &fe01 ; video register value &4045 78 SEI &4046 a2 82 LDX #&82 ; &7f82 &4048 a0 7f LDY #&7f &404a 86 70 STX &70 ; target_address_low &404c 84 71 STY &71 ; target_address_high &404e a2 fd LDX #&fd ; &c0fd &4050 a0 c0 LDY #&c0 &4052 86 72 STX &72 ; size_low &4054 84 73 STY &73 ; size_high &4056 a0 ff LDY #&ff ; decryption_stage_47_page_loop &4058 c6 71 DEC &71 ; target_address_high &405a 4c 62 40 JMP &4062; decryption_stage_47_byte ; decryption_stage_47_byte_loop &405d 88 DEY &405e c0 ff CPY #&ff &4060 f0 f6 BEQ &4058 ; decryption_stage_47_page_loop ; decryption_stage_47_byte &4062 b1 70 LDA (&70),Y ; target_address &4064 aa TAX &4065 bd 00 09 LDA &0900,X ; key &4068 85 74 STA &74 ; tmp &406a b9 00 09 LDA &0900,Y ; key &406d 9d 00 09 STA &0900,X ; key &4070 91 70 STA (&70),Y ; target_address &4072 a5 74 LDA &74 ; tmp &4074 99 00 09 STA &0900,Y ; key &4077 e6 72 INC &72 ; size_low &4079 d0 e2 BNE &405d ; decryption_stage_47_byte_loop &407b e6 73 INC &73 ; size_high &407d d0 de BNE &405d ; decryption_stage_47_byte_loop ; decryption_stage_48 # Decrypt &40bf - &7f81 (check interrupts) &407f 08 PHP ; processor status &4080 68 PLA ; processor status &4081 29 04 AND #&04 ; INTERRUPT_DISABLE &4083 f0 24 BEQ &40a9 ; decryption_stage_48_failed # Misaligned code if interrupts enabled &4085 78 SEI &4086 a2 82 LDX #&82 ; &7f82 &4088 a0 7f LDY #&7f &408a 86 70 STX &70 ; target_address_low &408c 84 71 STY &71 ; target_address_high &408e a2 3d LDX #&3d ; &c13d &4090 a0 c1 LDY #&c1 &4092 86 72 STX &72 ; size_low &4094 84 73 STY &73 ; size_high &4096 a0 ff LDY #&ff ; decryption_stage_48_page_loop &4098 c6 71 DEC &71 ; target_address_high &409a 4c a2 40 JMP &40a2; decryption_stage_48_byte ; decryption_stage_48_byte_loop &409d 88 DEY &409e c0 ff CPY #&ff &40a0 f0 f6 BEQ &4098 ; decryption_stage_48_page_loop ; decryption_stage_48_byte &40a2 b1 70 LDA (&70),Y ; target_address &40a4 aa TAX &40a5 bd 00 09 LDA &0900,X ; key &40a8 85 74 STA &74 ; tmp &40aa b9 00 09 LDA &0900,Y ; key &40ad 9d 00 09 STA &0900,X ; key &40b0 91 70 STA (&70),Y ; target_address &40b2 a5 74 LDA &74 ; tmp &40b4 99 00 09 STA &0900,Y ; key &40b7 e6 72 INC &72 ; size_low &40b9 d0 e2 BNE &409d ; decryption_stage_48_byte_loop &40bb e6 73 INC &73 ; size_high &40bd d0 de BNE &409d ; decryption_stage_48_byte_loop ; decryption_stage_49 # Decrypt &40f9 - &7f81 (set interrupts) &40bf 78 SEI &40c0 a2 82 LDX #&82 ; &7f82 &40c2 a0 7f LDY #&7f &40c4 86 70 STX &70 ; target_address_low &40c6 84 71 STY &71 ; target_address_high &40c8 a2 77 LDX #&77 ; &c177 &40ca a0 c1 LDY #&c1 &40cc 86 72 STX &72 ; size_low &40ce 84 73 STY &73 ; size_high &40d0 a0 ff LDY #&ff ; decryption_stage_49_page_loop &40d2 c6 71 DEC &71 ; target_address_high &40d4 4c dc 40 JMP &40dc; decryption_stage_49_byte ; decryption_stage_49_byte_loop &40d7 88 DEY &40d8 c0 ff CPY #&ff &40da f0 f6 BEQ &40d2 ; decryption_stage_49_page_loop ; decryption_stage_49_byte &40dc b1 70 LDA (&70),Y ; target_address &40de aa TAX &40df bd 00 09 LDA &0900,X ; key &40e2 85 74 STA &74 ; tmp &40e4 b9 00 09 LDA &0900,Y ; key &40e7 9d 00 09 STA &0900,X ; key &40ea 91 70 STA (&70),Y ; target_address &40ec a5 74 LDA &74 ; tmp &40ee 99 00 09 STA &0900,Y ; key &40f1 e6 72 INC &72 ; size_low &40f3 d0 e2 BNE &40d7 ; decryption_stage_49_byte_loop &40f5 e6 73 INC &73 ; size_high &40f7 d0 de BNE &40d7 ; decryption_stage_49_byte_loop ; decryption_stage_50 # Check interrupts &40f9 08 PHP ; processor status &40fa 68 PLA ; processor status &40fb 29 04 AND #&04 ; INTERRUPT_DISABLE &40fd f0 15 BEQ &4114 ; decryption_stage_50_failed # Break if interrupts enabled &40ff 78 SEI ; decrypted_entry_point &4100 d8 CLD &4101 a2 ff LDX #&ff &4103 9a TXS &4104 e8 INX ; 0 &4105 86 6f STX &6f ; sideways_ram_version # Set to positive to indicate not using sideways RAM &4107 8a TXA &4108 a2 02 LDX #&02 ; wipe_0000_to_00b9_loop # Wipe &0000 - &00b9 &410a 95 00 STA &00,X &410c e8 INX &410d e0 ba CPX #&ba &410f 90 f9 BCC &410a ; wipe_0000_to_00b9_loop &4111 a2 80 LDX #&80 ; wipe_0180_to_01ff_loop # Wipe &0180 - &01ff &4113 9d 00 01 STA &0100,X &4116 e8 INX &4117 d0 fa BNE &4113 ; wipe_0180_to_01ff_loop &4119 85 2e STA &2e ; player_viewpoint_horizontal_rotation &411b a9 19 LDA #&19 &411d 85 2f STA &2f ; player_viewpoint_vertical_rotation &411f a9 ff LDA #&ff &4121 85 4f STA &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint &4123 85 40 STA &40 ; crtc_start_address_high &4125 a9 40 LDA #&40 ; RTI &4127 8d 00 0d STA &0d00 ; nmi_handler &412a 78 SEI &412b a9 08 LDA #&08 ; R8: Interlace and delay register # Disable video &412d 8d 00 fe STA &fe00 ; video register number &4130 a9 f0 LDA #&f0 ; normal sync mode, disable video output, disable cursor output &4132 8d 01 fe STA &fe01 ; video register value &4135 ad b7 ff LDA &ffb7 ; os_rom_default_vector_table_address_low # Reset vectors &4138 85 02 STA &02 ; default_vector_table_address_low &413a ad b8 ff LDA &ffb8 ; os_rom_default_vector_table_address_high &413d 85 03 STA &03 ; default_vector_table_address_high &413f ac b6 ff LDY &ffb6 ; os_rom_vector_table_length ; reset_vector_table_loop &4142 88 DEY &4143 b1 02 LDA (&02),Y ; default_vector_table_address &4145 99 00 02 STA &0200,Y ; os_vector_table &4148 98 TYA &4149 d0 f7 BNE &4142 ; reset_vector_table_loop &414b a9 8f LDA #&8f ; Issue SWR service request &414d a2 0c LDX #&0c ; Claim NMI code area &414f a0 ff LDY #&ff &4151 20 f4 ff JSR &fff4 ; OSBYTE &4154 58 CLI &4155 ea NOP &4156 78 SEI &4157 a9 7f LDA #&7f # Disable all interrupts &4159 8d 4e fe STA &fe4e ; System VIA interrupt enable register &415c 8d 6e fe STA &fe6e ; User VIA interrupt enable register &415f a9 92 LDA #&92 # Enable end of analogue conversion and v-sync interrupts &4161 8d 4e fe STA &fe4e ; System VIA interrupt enable register &4164 a9 ff LDA #&ff # Clear all interrupts &4166 8d 4d fe STA &fe4d ; System VIA interrupt flag register &4169 8d 6d fe STA &fe6d ; User VIA interrupt flag register &416c 58 CLI &416d ea NOP &416e a2 06 LDX #&06 &4170 a0 00 LDY #&00 &4172 8c 65 fe STY &fe65 ; User VIA timer 1 counter MSB &4175 8e 64 fe STX &fe64 ; User VIA timer 1 counter LSB &4178 a9 40 LDA #&40 # Set timer 1 to continuous interrupts &417a 8d 4b fe STA &fe4b ; System VIA auxiliary control register &417d 8d 6b fe STA &fe6b ; User VIA auxiliary control register &4180 20 a6 46 JSR &46a6 ; consider_using_sideways_ram # Returns carry set if using sideways RAM &4183 b0 09 BCS &418e ; skip_clearing_memory_on_break # The sideways RAM version has its own break handler &4185 a9 c8 LDA #&c8 ; Read/Write BREAK/ESCAPE effect &4187 a2 02 LDX #&02 ; Clear memory on next RESET &4189 a0 00 LDY #&00 &418b 20 f4 ff JSR &fff4 ; OSBYTE ; skip_clearing_memory_on_break &418e a9 ea LDA #&ea ; Write Tube present flag # Disable Tube &4190 a2 00 LDX #&00 &4192 a0 00 LDY #&00 &4194 20 f4 ff JSR &fff4 ; OSBYTE &4197 a9 0d LDA #&0d ; Disable event &4199 a2 04 LDX #&04 ; v-sync event &419b 20 f4 ff JSR &fff4 ; OSBYTE &419e a2 62 LDX #&62 ; &3162 = event_handler &41a0 a0 31 LDY #&31 &41a2 78 SEI &41a3 8c 21 02 STY &0221 ; event_vector_high &41a6 8e 20 02 STX &0220 ; event_vector_low &41a9 a2 c8 LDX #&c8 &41ab a0 00 LDY #&00 &41ad 8c 45 fe STY &fe45 ; System VIA timer 1 counter MSB &41b0 8e 44 fe STX &fe44 ; System VIA timer 1 counter LSB &41b3 58 CLI &41b4 ea NOP &41b5 a9 ff LDA #&ff &41b7 a2 40 LDX #&40 ; initialise_pending_sounds_loop # Wipe &0781 - &07c0 with &ff &41b9 ca DEX &41ba 9d 81 07 STA &0781,X ; pending_sounds # Set to negative to indicate no sound pending &41bd d0 fa BNE &41b9 ; initialise_pending_sounds_loop &41bf a2 15 LDX #&15 ; &4a15 &41c1 a0 4a LDY #&4a &41c3 84 03 STY &03 ; source_address_high &41c5 86 02 STX &02 ; source_address_low &41c7 a2 56 LDX #&56 ; &1056 &41c9 a0 10 LDY #&10 &41cb 84 05 STY &05 ; target_address_high &41cd 86 04 STX &04 ; target_address_low &41cf a2 59 LDX #&59 ; &d159 &41d1 a0 d1 LDY #&d1 &41d3 84 07 STY &07 ; size_high &41d5 a0 00 LDY #&00 ; move_4a15_to_78bb_loop # Move &4a15 - &78bb to &1056 - &3efc &41d7 b1 02 LDA (&02),Y ; source_address &41d9 91 04 STA (&04),Y ; target_address &41db 98 TYA &41dc 91 02 STA (&02),Y ; source_address &41de e6 02 INC &02 ; source_address_low &41e0 d0 02 BNE &41e4 ; skip_source_page &41e2 e6 03 INC &03 ; source_address_high ; skip_source_page &41e4 e6 04 INC &04 ; target_address_low &41e6 d0 02 BNE &41ea ; skip_target_page &41e8 e6 05 INC &05 ; target_address_high ; skip_target_page &41ea e8 INX &41eb d0 ea BNE &41d7 ; move_loop &41ed e6 07 INC &07 ; size_high &41ef d0 e6 BNE &41d7 ; move_loop &41f1 a9 0e LDA #&0e ; Enable event &41f3 a2 04 LDX #&04 ; v-sync event &41f5 20 f4 ff JSR &fff4 ; OSBYTE &41f8 58 CLI &41f9 ea NOP &41fa a2 07 LDX #&07 ; move_solid_status_ball_sprite_data_loop &41fc bd 62 7f LDA &7f62,X ; unrelocated_sprite_status_ball_solid_top_left &41ff 9d 00 01 STA &0100,X ; sprite_status_ball_solid &4202 bd 6a 7f LDA &7f6a,X ; unrelocated_sprite_status_ball_solid_bottom_left &4205 9d 10 01 STA &0110,X ; sprite_status_ball_solid + 16 &4208 bd 72 7f LDA &7f72,X ; unrelocated_sprite_status_ball_solid_top_right &420b 9d 08 01 STA &0108,X ; sprite_status_ball_solid + 8 &420e bd 7a 7f LDA &7f7a,X ; unrelocated_sprite_status_ball_solid_bottom_right &4211 9d 18 01 STA &0118,X ; sprite_status_ball_solid + 24 &4214 ca DEX &4215 10 e5 BPL &41fc ; move_solid_status_ball_sprite_data_loop &4217 a0 00 LDY #&00 ; 0000 &4219 8c 00 04 STY &0400 ; combined_bytes_used_in_colour_tables # Add colour table entry for empty pixel value &421c 8c 00 05 STY &0500 ; right_bytes_used_in_colour_tables &421f 8c 16 08 STY &0816 ; colour_table_solid_shift_3 &4222 8c 6d 08 STY &086d ; colour_table_solid_shift_2 &4225 8c c4 08 STY &08c4 ; colour_table_solid_shift_1 &4228 8c 1b 09 STY &091b ; colour_table_solid_shift_0 &422b c8 INY ; 1 &422c 84 24 STY &24 ; colour_tables_last_entry_plus_one &422e a2 00 LDX #&00 ; initialise_ball_sprites_sprite_loop # Unprocessed ball sprites are stored at &78bc - &7b41 &4230 86 2a STX &2a ; ball_sprite &4232 a0 00 LDY #&00 &4234 b1 02 LDA (&02),Y ; source_address # Get one byte of data for sprite width in pixels &4236 9d dd 07 STA &07dd,X ; ball_sprite_widths_in_pixels &4239 85 56 STA &56 ; width &423b c8 INY &423c b1 02 LDA (&02),Y ; source_address # Get one byte of data for sprite width in bytes &423e 9d eb 07 STA &07eb,X ; ball_sprite_widths_in_bytes &4241 85 25 STA &25 ; width_in_bytes &4243 c8 INY &4244 b1 02 LDA (&02),Y ; source_address # Get one byte of data for sprite height in rows &4246 9d f9 07 STA &07f9,X ; ball_sprite_heights_in_rows &4249 85 26 STA &26 ; height &424b a5 04 LDA &04 ; target_address_low # Processed ball sprites are stored at &3efd - &40b4, &424d 9d c1 07 STA &07c1,X ; ball_sprite_addresses_low # &3efd - &4230 in sideways ram version &4250 a5 05 LDA &05 ; target_address_high &4252 9d cf 07 STA &07cf,X ; ball_sprite_addresses_high &4255 98 TYA &4256 38 SEC # Set carry to add Y + 1, i.e. past read data &4257 65 02 ADC &02 ; source_address_low &4259 85 02 STA &02 ; source_address_low &425b 90 02 BCC &425f; skip_page &425d e6 03 INC &03 ; source_address_high ; skip_page ; initialise_ball_sprites_row_loop &425f a0 00 LDY #&00 &4261 84 08 STY &08 ; left_byte ; initialise_ball_sprites_byte_loop &4263 a5 08 LDA &08 ; left_byte &4265 0a ASL A # Shift the previous byte left one pixel &4266 29 ee AND #&ee ; 3330 &4268 85 0c STA &0c ; three_left_pixels &426a b1 02 LDA (&02),Y ; source_address # Get next byte of sprite data &426c 85 08 STA &08 ; left_byte &426e c4 25 CPY &25 ; width_in_bytes &4270 90 02 BCC &4274 ; not_end_of_row # If this is beyond the right of the sprite, &4272 a9 00 LDA #&00 ; 0000 # Use a blank byte ; not_end_of_row &4274 48 PHA ; right_byte &4275 4a LSR A # Shift this byte right three pixels &4276 4a LSR A # i.e. keep leftmost pixel &4277 4a LSR A &4278 29 11 AND #&11 ; 0003 &427a 05 0c ORA &0c ; three_left_pixels # Combine to give two bytes shifted left one pixel &427c aa TAX # X = combined byte for ball shifted left one pixel &427d a9 00 LDA #&00 &427f c4 25 CPY &25 ; width_in_bytes &4281 b0 02 BCS &4285 ; skip_clearing # If a byte of packed data has been used, &4283 91 02 STA (&02),Y ; source_address # wipe it ; skip_clearing &4285 68 PLA ; right_byte &4286 0a ASL A &4287 29 ee AND #&ee ; 3330 # A = right byte shifted left one pixel &4289 20 69 45 JSR &4569 ; get_offset_into_colour_tables &428c a2 00 LDX #&00 &428e 81 04 STA (&04,X) ; target_address # Processed sprite stores offsets into colour tables &4290 e6 04 INC &04 ; target_address_low &4292 d0 02 BNE &4296 ; skip_target_page &4294 e6 05 INC &05 ; target_address_high ; skip_target_page &4296 c8 INY &4297 c4 25 CPY &25 ; width_in_bytes &4299 f0 c8 BEQ &4263 ; initialise_ball_sprites_byte_loop &429b 90 c6 BCC &4263 ; initialise_ball_sprites_byte_loop &429d 18 CLC &429e a5 02 LDA &02 ; source_address_low &42a0 65 25 ADC &25 ; width_in_bytes &42a2 85 02 STA &02 ; source_address_low &42a4 90 02 BCC &42a8 ; skip_source_page &42a6 e6 03 INC &03 ; source_address_high ; skip_source_page &42a8 c6 26 DEC &26 ; rows_to_unpack &42aa d0 b3 BNE &425f ; initialise_ball_sprites_row_loop &42ac a6 2a LDX &2a ; ball_sprite &42ae e8 INX &42af 24 6f BIT &6f ; sideways_ram_version # Negative if using sideways RAM &42b1 30 04 BMI &42b7 ; skip_check &42b3 e0 0a CPX #&0a # Only use first ten ball sprites on standard version &42b5 b0 0b BCS &42c2 ; finished_initialising_ball_sprites ; skip_check &42b7 c9 42 CMP #&42 ; &7b42 = end_of_packed_ball_sprite_data &42b9 a5 03 LDA &03 ; source_address_high &42bb e9 7b SBC #&7b &42bd b0 03 BCS &42c2 ; finished_initialising_ball_sprites &42bf 4c 30 42 JMP &4230 ; initialise_ball_sprites_sprite_loop ; finished_initialising_ball_sprites &42c2 a5 04 LDA &04 ; target_address_low &42c4 8d 80 01 STA &0180 ; end_of_processed_ball_sprites_address_low &42c7 a5 05 LDA &05 ; target_address_high &42c9 8d 81 01 STA &0181 ; end_of_processed_ball_sprites_address_high &42cc a5 24 LDA &24 ; colour_tables_last_entry_plus_one &42ce 8d 82 01 STA &0182 ; size_of_colour_tables # Unused variable &42d1 8e 83 01 STX &0183 ; number_of_ball_sprites &42d4 a2 00 LDX #&00 ; initialise_mask_table_loop &42d6 8a TXA &42d7 20 3e 46 JSR &463e ; calculate_mask_table_value &42da 9d 00 06 STA &0600,X ; mask_table &42dd e8 INX &42de d0 f6 BNE &42d6 ; initialise_mask_table_loop &42e0 a2 13 LDX #&13 ; initialise_colour_tables_table_loop # For each colour table to be created, &42e2 86 06 STX &06 ; count &42e4 8a TXA &42e5 0a ASL A &42e6 0a ASL A &42e7 a8 TAY &42e8 b9 ee 45 LDA &45ee,Y ; colour_tables_table # First two bytes specify address &42eb 85 04 STA &04 ; target_colour_table_address_low &42ed b9 ef 45 LDA &45ef,Y ; colour_tables_table + 1 &42f0 85 05 STA &05 ; target_colour_table_address_high &42f2 b9 f0 45 LDA &45f0,Y ; colour_tables_table + 2 # Third byte specifies colour mask &42f5 85 07 STA &07 ; colour_table_mask &42f7 b9 f1 45 LDA &45f1,Y ; colour_tables_table + 3 # Fourth byte specifies number of pixels to shift &42fa 0a ASL A &42fb 0a ASL A &42fc aa TAX &42fd bd ee 45 LDA &45ee,X ; colour_tables_table # Use colour_table_solid_shift_* as source &4300 85 02 STA &02 ; source_colour_table_address_low &4302 bd ef 45 LDA &45ef,X ; colour_tables_table + 1 &4305 85 03 STA &03 ; source_colour_table_address_high &4307 a0 57 LDY #&57 ; &57 = colour_table_solid_shift_2 - colour_table_solid_shift_3, i.e. size of colour table &4309 88 DEY ; initialise_colour_tables_byte_loop &430a b1 02 LDA (&02),Y ; source_colour_table_address &430c 20 c2 45 JSR &45c2 ; apply_colour_to_byte_of_sprite &430f 91 04 STA (&04),Y ; target_colour_table_address &4311 98 TYA &4312 d0 f5 BNE &4309 ; initialise_colour_tables_table_loop &4314 a6 06 LDX &06 ; count &4316 ca DEX &4317 e0 04 CPX #&04 # Don't create solid colour tables &4319 b0 c7 BCS &42e2 ; initialise_colour_tables_table_loop ; initialise_status_ball_sprites &431b a2 1f LDX #&1f ; initialise_status_ball_sprites_loop &431d 86 06 STX &06 ; offset &431f bc 00 01 LDY &0100,X ; sprite_status_ball_solid &4322 a9 f0 LDA #&f0 ; 2222 # Make white version of ball &4324 85 07 STA &07 ; colour_pixel_value &4326 98 TYA &4327 20 c2 45 JSR &45c2 ; apply_colour_to_byte_of_sprite &432a 48 PHA ; cue ball even byte &432b a9 ff LDA #&ff ; 3333 # Make black version of ball &432d 85 07 STA &07 ; colour_pixel_value &432f 98 TYA &4330 20 c2 45 JSR &45c2 ; apply_colour_to_byte_of_sprite &4333 48 PHA ; black ball even byte &4334 a9 af LDA #&af ; 3131 # Make dithered version of ball &4336 85 07 STA &07 ; colour_pixel_value &4338 98 TYA &4339 20 c2 45 JSR &45c2 ; apply_colour_to_byte_of_sprite &433c a6 06 LDX &06 ; offset &433e 9d 20 01 STA &0120,X ; sprite_status_ball_dithered &4341 68 PLA ; black ball even byte &4342 9d 60 01 STA &0160,X ; sprite_status_ball_black &4345 68 PLA ; cue ball even byte &4346 9d 40 01 STA &0140,X ; sprite_status_ball_cue &4349 ca DEX &434a 86 06 STX &06 ; offset &434c bc 00 01 LDY &0100,X ; sprite_status_ball_solid &434f a9 f0 LDA #&f0 ; 2222 # Make white version of ball &4351 85 07 STA &07 ; colour_pixel_value &4353 98 TYA &4354 20 c2 45 JSR &45c2 ; apply_colour_to_byte_of_sprite &4357 48 PHA ; cue ball odd byte &4358 a9 ff LDA #&ff ; 3333 # Make black version of ball &435a 85 07 STA &07 ; colour_pixel_value &435c 98 TYA &435d 20 c2 45 JSR &45c2 ; apply_colour_to_byte_of_sprite &4360 48 PHA ; black ball odd byte &4361 a9 5f LDA #&5f ; 1313 # Make dithered version of ball &4363 85 07 STA &07 ; colour_pixel_value &4365 98 TYA &4366 20 c2 45 JSR &45c2 ; apply_colour_to_byte_of_sprite &4369 a6 06 LDX &06 ; offset &436b 9d 20 01 STA &0120,X ; sprite_status_ball_dithered &436e 68 PLA ; black ball odd byte &436f 9d 60 01 STA &0160,X ; sprite_status_ball_black &4372 68 PLA ; cue ball odd byte &4373 9d 40 01 STA &0140,X ; sprite_status_ball_cue &4376 ca DEX &4377 10 a4 BPL &431d ; initialise_status_ball_sprites_loop &4379 a2 06 LDX #&06 ; initialise_sound_data_addresses &437b 18 CLC &437c bd 10 3b LDA &3b10,X ; sound_data_addresses &437f 69 10 ADC #&10 ; &3b10 = sound_data_addresses &4381 9d 10 3b STA &3b10,X ; sound_data_addresses &4384 bd 11 3b LDA &3b11,X ; sound_data_addresses + 1 &4387 69 3b ADC #&3b &4389 9d 11 3b STA &3b11,X ; sound_data_addresses + 1 &438c ca DEX &438d ca DEX &438e 10 eb BPL &437b ; initialise_sound_data_addresses &4390 20 04 44 JSR &4404 ; initialise_squares_tables ; initialise_fill_line_routine # Populate fill_line_routine: &4393 a2 00 LDX #&00 &4395 a0 f8 LDY #&f8 # ; fill_line_routine ; initialise_fill_line_routine_loop # &0700 a0 f8 LDY #&f8 &4397 a9 a0 LDA #&a0 ; LDY #&.. # &0702 91 67 STA (&67),Y ; fill_screen_address &4399 9d 00 07 STA &0700,X ; fill_line_routine # &0700 a0 f0 LDY #&f0 &439c e8 INX # &0702 91 67 STA (&67),Y ; fill_screen_address &439d 98 TYA # ... &439e 9d 00 07 STA &0700,X ; fill_line_routine # &0778 a0 08 LDY #&08 &43a1 38 SEC # &077a 91 67 STA (&67),Y ; fill_screen_address &43a2 e9 08 SBC #&08 # &077c a0 00 LDY #&00 &43a4 a8 TAY # &077e 91 67 STA (&67),Y ; fill_screen_address &43a5 e8 INX &43a6 a9 91 LDA #&91 ; STA (&..),Y &43a8 9d 00 07 STA &0700,X ; fill_line_routine &43ab e8 INX &43ac a9 67 LDA #&67 &43ae 9d 00 07 STA &0700,X ; fill_line_routine &43b1 e8 INX &43b2 10 e3 BPL &4397 ; initialise_fill_line_routine_loop &43b4 a9 60 LDA #&60 ; RTS # &0780 60 RTS &43b6 8d 80 07 STA &0780 ; fill_routine ; initialise_variables &43b9 a5 28 LDA &28 ; vsync_counter &43bb 85 29 STA &29 ; unused_vsync_counter # Unused variable &43bd 85 6b STA &6b ; vsync_counter_for_update &43bf 85 3e STA &3e ; previous_vsync_counter &43c1 a9 12 LDA #&12 &43c3 85 2f STA &2f ; player_viewpoint_vertical_rotation &43c5 85 37 STA &37 ; trick_viewpoint_vertical_rotation &43c7 a9 08 LDA #&08 &43c9 85 30 STA &30 ; player_strike_power &43cb 85 38 STA &38 ; trick_strike_power &43cd a9 0a LDA #&0a ; STRIKE_MIDDLE &43cf 85 31 STA &31 ; player_strike_point &43d1 85 39 STA &39 ; trick_strike_point &43d3 a9 01 LDA #&01 &43d5 85 53 STA &53 ; return_or_fire_state # Set to one to indicate not recently pressed &43d7 a9 00 LDA #&00 &43d9 85 77 STA &77 ; flashing_ball_flag &43db a9 30 LDA #&30 &43dd 85 5d STA &5d ; left_clip_x &43df a9 d0 LDA #&d0 &43e1 85 5e STA &5e ; right_clip_x &43e3 a9 bf LDA #&bf &43e5 85 5f STA &5f ; screen_height_in_rows &43e7 a9 00 LDA #&00 &43e9 85 60 STA &60 ; screen_top_row &43eb 85 26 STA &26 ; rows_to_plot &43ed 85 95 STA &95 ; suppress_checking_for_return_or_fire # Set to positive to allow checking &43ef 85 a8 STA &a8 ; sound_muted # Set to positive to allow sound &43f1 20 54 46 JSR &4654 ; initialise_irq1_handler &43f4 20 6e 46 JSR &466e ; initialise_sound &43f7 24 6f BIT &6f ; sideways_ram_version # Negative if using sideways RAM &43f9 10 03 BPL &43fe ; skip_initialising_sideways_ram_code &43fb 20 75 47 JSR &4775 ; initialise_sideways_ram_code ; skip_initialising_sideways_ram_code &43fe 20 20 44 JSR &4420 ; initialise_ball_layouts &4401 4c 95 44 JMP &4495 ; consider_using_master_specific_code ; initialise_squares_tables # Populate &0400 - &04ff and &0500 - &05ff &4404 a2 00 LDX #&00 # with low and high bytes of X squared &4406 8a TXA &4407 a8 TAY &4408 d8 CLD ; initialise_squares_tables_loop &4409 9d 00 04 STA &0400,X ; squares_low_table &440c 98 TYA &440d 9d 00 05 STA &0500,X ; squares_high_table # Noting that (n + 1)^2 = n^2 + 2n + 1, &4410 8a TXA # X = n &4411 0a ASL A # 2n &4412 90 01 BCC &4415 ; skip_overflow &4414 c8 INY ; skip_overflow &4415 38 SEC # + 1 &4416 7d 00 04 ADC &0400,X ; squares_low_table # n^2 &4419 90 01 BCC &441c ; skip_overflow &441b c8 INY ; skip_overflow &441c e8 INX &441d d0 ea BNE &4409 ; initialise_squares_tables_loop &441f 60 RTS ; initialise_ball_layouts &4420 a2 9d LDX #&9d ; &8c9d = sideways_ram_ball_layouts_data &4422 a0 8c LDY #&8c &4424 a9 91 LDA #&91 ; &9100 = sideways_ram_screen_buffer &4426 24 6f BIT &6f ; sideways_ram_version # Negative if using sideways RAM &4428 30 08 BMI &4432 ; set_ball_layouts_address # XY = &40b5 if not using sideways RAM &442a ac 81 01 LDY &0181 ; end_of_processed_ball_sprites_address_high &442d ae 80 01 LDX &0180 ; end_of_processed_ball_sprites_address_low &4430 a9 44 LDA #&44 ; &4400 = screen_one ; set_ball_layouts_address &4432 85 05 STA &05 ; limit_address_high &4434 8e 9b 1a STX &1a9b ; ball_layouts_base_address_low &4437 8c a0 1a STY &1aa0 ; ball_layouts_base_address_high &443a 84 03 STY &03 ; target_address_high &443c 86 02 STX &02 ; target_address_low &443e a0 41 LDY #&41 ; copy_initial_ball_layout_data_loop # Copy initial table layout to &40b5 - &40f6 &4440 b9 42 7b LDA &7b42,Y ; unrelocated_initial_ball_layout_data # or &8c9d - &8cde if using sideways RAM &4443 91 02 STA (&02),Y ; target_address &4445 88 DEY &4446 10 f8 BPL &4440 ; copy_initial_ball_layout_data_loop &4448 a9 0f LDA #&0f &444a 24 b0 BIT &b0 ; sideways_ram_code_needed_copying # Negative if sideways ram code already present &444c 30 43 BMI &4491 ; set_maximum_trick_number &444e c8 INY ; 0 &444f 84 04 STY &04 ; count &4451 a2 84 LDX #&84 ; &7b84 = unrelocated_trick_ball_layout_data &4453 a0 7b LDY #&7b &4455 84 07 STY &07 ; source_address_high &4457 86 06 STX &06 ; source_address_low &4459 18 CLC &445a a5 02 LDA &02 ; target_address_low &445c 69 84 ADC #&84 ; &42 * 2 # Move past layout one (used for computer thinking) &445e 85 02 STA &02 ; target_address_low &4460 90 02 BCC &4464 ; skip_page &4462 e6 03 INC &03 ; target_address_high ; skip_page ; copy_trick_ball_layout_data_trick_loop # Copy trick layouts 1 - 10 to &4139 - &43cc &4464 a0 41 LDY #&41 # or 1 - 15 to &8d21 - &90fe if using sideways RAM &4466 38 SEC &4467 98 TYA &4468 65 02 ADC &02 ; target_address_low &446a aa TAX &446b a5 03 LDA &03 ; target_address_high &446d 69 00 ADC #&00 &446f c5 05 CMP &05 ; limit_address_high &4471 b0 1c BCS &448f ; set_maximum_trick_number_from_count &4473 48 PHA ; target_address_high &4474 e6 04 INC &04 ; trick_count ; copy_trick_ball_layout_data_byte_loop &4476 b1 06 LDA (&06),Y ; source_address &4478 91 02 STA (&02),Y ; target_address &447a 88 DEY &447b 10 f9 BPL &4476 ; copy_trick_ball_layout_data_byte_loop &447d 68 PLA ; target_address_high &447e 86 02 STX &02 ; target_address_low &4480 85 03 STA &03 ; target_address_high &4482 18 CLC &4483 a5 06 LDA &06 ; source_address_low &4485 69 42 ADC #&42 # Move to next trick layout &4487 85 06 STA &06 ; source_address_low &4489 90 d9 BCC &4464 ; copy_trick_ball_layout_data_trick_loop &448b e6 07 INC &07 ; source_address_high &448d b0 d5 BCS &4464 ; copy_trick_ball_layout_data_trick_loop # Always branches ; set_maximum_trick_number_from_count &448f a5 04 LDA &04 ; count ; set_maximum_trick_number &4491 8d 97 2e STA &2e97 ; maximum_trick_number &4494 60 RTS ; consider_using_master_specific_code &4495 a2 00 LDX #&00 ; move_4527_to_4568_loop # Move &4527 - &4568 to &4400 - &4441 &4497 bd 27 45 LDA &4527,X ; unrelocated_final_initialisation &449a 9d 00 44 STA &4400,X ; final_initialisation &449d e8 INX &449e e0 42 CPX #&42 &44a0 90 f5 BCC &4497 ; move_4527_to_4568_loop &44a2 a9 00 LDA #&00 ; Identify Host/Operating System &44a4 a2 ff LDX #&ff &44a6 20 f4 ff JSR &fff4 ; OSBYTE # Returns host/OS in X &44a9 e0 03 CPX #&03 ; Master 128 &44ab 90 38 BCC &44e5 ; not_master &44ad e0 05 CPX #&05 ; Master Compact &44af d0 1b BNE &44cc ; is_master ; is_master_compact &44b1 a2 18 LDX #&18 ; copy_master_compact_check_joystick_loop &44b3 bd 03 45 LDA &4503,X ; master_compact_check_joystick &44b6 9d 19 32 STA &3219,X ; check_joystick &44b9 e0 0b CPX #&0b ; check_for_joystick_directions - check_joystick + 1 &44bb b0 06 BCS &44c3 ; copy_master_compact_check_joystick_loop # Bug: doesn't fully copy code ; copy_master_compact_check_for_fire_loop &44bd bd 1c 45 LDA &451c,X ; master_compact_check_for_fire &44c0 9d 42 32 STA &3242,X ; check_for_fire &44c3 ca DEX &44c4 10 ed BPL &44b3 ; copy_master_compact_check_for_fire_loop &44c6 e8 INX ; 0 &44c7 8e 62 fe STX &fe62 ; User VIA data direction register B # Set all bits to input &44ca f0 19 BEQ &44e5 ; not_master # Always branches ; is_master &44cc a2 0e LDX #&0e &44ce a9 01 LDA #&01 # Addresses are for instructions &44d0 85 02 STA &02 ; address_address_low # Add one to give low byte of address ; change_adc_addresses_loop &44d2 bc f3 44 LDY &44f3,X ; adc_address_addresses &44d5 bd f4 44 LDA &44f4,X ; adc_address_addresses + 1 &44d8 85 03 STA &03 ; address_address_high &44da b1 02 LDA (&02),Y ; address_address &44dc 38 SEC &44dd e9 a8 SBC #&a8 # Change &fec0 to &fe18 and &fec1 to &fe19 &44df 91 02 STA (&02),Y ; address_address &44e1 ca DEX &44e2 ca DEX &44e3 10 ed BPL &44d2 ; change_adc_addresses_loop ; not_master &44e5 a0 00 LDY #&00 &44e7 84 a3 STY &a3 ; adc_channel &44e9 a9 16 LDA #&16 # Change to MODE 5 &44eb 20 ee ff JSR &ffee ; OSWRCH &44ee a9 05 LDA #&05 &44f0 4c 00 44 JMP &4400 ; final_initialisation ; adc_address_addresses &44f3 78 30 ; &3078 &44f5 83 30 ; &3083 &44f7 96 30 ; &3096 &44f9 a8 30 ; &30a8 &44fb 0d 31 ; &310d &44fd 29 31 ; &3129 &44ff 57 31 ; &3157 &4501 2f 44 ; &442f # Bug: not an ADC address # &4503 - &451b should be moved to &3219 - &3231 at &44b3 on a Master Compact ; master_compact_check_joystick &3219 ad 60 fe LDA &fe60 ; User VIA port B input/output register &321c 4a LSR A &321d 4a LSR A &321e b0 02 BCS &3222 ; joystick_not_down &3220 c6 82 DEC &82 ; down_pressed ; joystick_not_down &3222 4a LSR A &3223 b0 02 BCS &3227 ; joystick_not_left # Bug: only &3224 - &3231 is overwritten (see &44b9) &3225 c6 7f DEC &7f ; left_pressed ; joystick_not_left &3227 4a LSR A &3228 b0 02 BCS &322c ; joystick_not_up &322a c6 81 DEC &81 ; up_pressed ; joystick_not_up &322c 4a LSR A &322d b0 02 BCS &3231 ; joystick_not_right &322f c6 80 DEC &80 ; right_pressed ; joystick_not_right &3231 60 RTS # &451c - &4526 is moved to &3242 - &324c at &44bd on a Master Compact ; master_compact_check_for_fire &3242 ad 60 fe LDA &fe60 ; User VIA port B input/output register &3245 4a LSR A &3246 a9 00 LDA #&00 &3248 e9 00 SBC #&00 &324a 4c ef 31 JMP &31ef ; consider_return_or_fire # &4527 - &4568 is moved to &4400 - &4441 at &4497 ; final_initialisation &4400 20 ee ff JSR &ffee ; OSWRCH &4403 a0 03 LDY #&03 &4405 78 SEI ; initialise_video_registers_loop &4406 b9 3c 44 LDA &443c,Y ; video_register_numbers &4409 8d 00 fe STA &fe00 ; video register number &440c b9 3f 44 LDA &443f,Y ; video_register_values &440f 8d 01 fe STA &fe01 ; video register value &4412 b9 07 36 LDA &3607,Y ; palette_values &4415 a2 03 LDX #&03 ; initialise_palette_registers_loop &4417 5d 03 36 EOR &3603,X ; palette_eors &441a 8d 21 fe STA &fe21 ; video ULA palette register &441d ca DEX &441e 10 f7 BPL &4417 ; initialise_palette_registers_loop &4420 88 DEY &4421 10 e3 BPL &4406 ; initialise_video_registers_loop &4423 2c 40 fe BIT &fe40 ; System VIA port B input/output register # Clear interrupt &4426 a9 90 LDA #&90 # Enable interrupt for end of analogue conversion &4428 8d 4e fe STA &fe4e ; System VIA interrupt enable register &442b 8c 4d fe STY &fe4d ; System VIA interrupt flag register # Clear all interrupts &442e c8 INY &442f a2 40 LDX #&40 ; &0c40 = &6200 / 8 # Set screen start address to &6200 # or LDX #&98 ; &0c98 = &64c0 / 8 on Master # or &64c0 on Master (see &4501) &4431 a0 0c LDY #&0c &4433 86 41 STX &41 ; crtc_start_address_low &4435 84 40 STY &40 ; crtc_start_address_high &4437 58 CLI &4438 ea NOP &4439 4c 56 10 JMP &1056 ; after_initialisation_finished ; video_register_numbers # R6: Vertical displayed register &443c 06 07 0a # R7: Vertical sync position ; video_register_values # R10: Cursor start register (disable cursor) &443f 18 1f 20 ; get_offset_into_colour_tables &4569 86 1c STX &1c ; combined_shifted_byte # X = combined byte for ball shifted left one pixel &456b 85 1d STA &1d ; right_byte_shifted_left_once # A = right byte shifted left one pixel &456d a2 00 LDX #&00 ; check_if_pair_present_in_colour_tables_loop # For each existing entry in the colour tables, &456f bd 00 04 LDA &0400,X ; combined_bytes_used_in_colour_tables &4572 c5 1c CMP &1c ; combined_shifted_byte &4574 d0 09 BNE &457f ; consider_next_pair &4576 bd 00 05 LDA &0500,X ; right_bytes_used_in_colour_tables &4579 c5 1d CMP &1d ; right_byte_shifted_left_once &457b d0 02 BNE &457f ; consider_next_pair # Does it match this pair of bytes? &457d 8a TXA # Leave with X = A = offset into coloured sprite data &457e 60 RTS ; consider_next_pair &457f e8 INX &4580 e4 24 CPX &24 ; colour_tables_last_entry_plus_one &4582 d0 eb BNE &456f ; check_if_pair_present_in_colour_tables_loop &4584 8a TXA &4585 d0 01 BNE &4588 ; add_colour_table_entry # If the colour table isn't full (always branches), &4587 60 RTS ; add_colour_table_entry # Add a new entry &4588 a5 1c LDA &1c ; combined_shifted_byte &458a 9d 00 04 STA &0400,X ; combined_bytes_used_in_colour_tables &458d a5 1d LDA &1d ; right_byte_shifted_left_once &458f 9d 00 05 STA &0500,X ; right_bytes_used_in_colour_tables &4592 a5 1d LDA &1d ; right_byte_shifted_left_once &4594 4a LSR A &4595 85 0c STA &0c ; shifted_right_once &4597 4a LSR A &4598 29 33 AND #&33 ; 0033 &459a 85 0d STA &0d ; shifted_right_twice &459c 4a LSR A &459d 29 11 AND #&11 ; 0003 &459f 85 0e STA &0e ; shifted_right_thrice &45a1 a5 1c LDA &1c ; combined_shifted_byte &45a3 9d 16 08 STA &0816,X ; colour_table_solid_shift_3 &45a6 0a ASL A &45a7 29 ee AND #&ee ; 3333 &45a9 05 0e ORA &0e ; shifted_right_thrice &45ab 9d 6d 08 STA &086d,X ; colour_table_solid_shift_2 &45ae 0a ASL A &45af 29 cc AND #&cc ; 3300 &45b1 05 0d ORA &0d ; shifted_right_twice &45b3 9d c4 08 STA &08c4,X ; colour_table_solid_shift_1 &45b6 0a ASL A &45b7 29 88 AND #&88 ; 3000 &45b9 05 0c ORA &0c ; shifted_right_once &45bb 9d 1b 09 STA &091b,X ; colour_table_solid_shift_0 &45be e6 24 INC &24 ; colour_tables_last_entry_plus_one &45c0 8a TXA &45c1 60 RTS ; apply_colour_to_byte_of_sprite # Called with A = byte of sprite to colour &45c2 aa TAX &45c3 84 0e STY &0e ; tmp_y &45c5 a9 88 LDA #&88 ; 3000 &45c7 85 0c STA &0c ; pixel &45c9 a0 00 LDY #&00 ; apply_colour_to_byte_of_sprite_pixel_loop # For each pixel in the byte, &45cb 8a TXA &45cc 25 0c AND &0c ; pixel &45ce f0 08 BEQ &45d8 ; skip_setting_pixel &45d0 c9 10 CMP #&10 ; 1000 &45d2 b0 04 BCS &45d8 ; skip_setting_pixel # Is it colour 1 (red)? &45d4 98 TYA &45d5 05 0c ORA &0c ; pixel # If so, set it to colour 3; otherwise, colour 0 &45d7 a8 TAY ; skip_setting_pixel &45d8 46 0c LSR &0c ; pixel &45da 90 ef BCC &45cb ; apply_colour_to_byte_of_sprite_pixel_loop &45dc 98 TYA # Y has colour 3 where original byte had colour 1 &45dd 49 ff EOR #&ff &45df 85 0c STA &0c ; mask # mask has colour 3 where original byte not colour 1 &45e1 8a TXA # X is original byte &45e2 25 0c AND &0c ; mask &45e4 85 0c STA &0c ; masked_byte # masked_byte contains only non-colour 1 pixels &45e6 98 TYA &45e7 25 07 AND &07 ; colour_pixel_value # Set colour 1 pixels to desired colour &45e9 05 0c ORA &0c ; mask # Merge with original non-colour 1 pixels &45eb a4 0e LDY &0e ; tmp_y &45ed 60 RTS # Leave with A = coloured byte ; colour_tables_table ; addr c s &45ee 16 08 0f 00 ; &0816 = colour_table_solid_shift_3 : pixel colours 1111, shift 0 # Used only as source &45f2 6d 08 0f 01 ; &086d = colour_table_solid_shift_2 : pixel colours 1111, shift 1 # Used only as source &45f6 c4 08 0f 02 ; &08c4 = colour_table_solid_shift_1 : pixel colours 1111, shift 2 # Used only as source &45fa 1b 09 0f 03 ; &091b = colour_table_solid_shift_0 : pixel colours 1111, shift 3 # Used only as source &45fe 72 09 5f 00 ; &0972 = colour_table_dithered_even_shift_3 : pixel colours 1313, shift 0 &4602 c9 09 5f 01 ; &09c9 = colour_table_dithered_even_shift_2 : pixel colours 1313, shift 1 &4606 20 0a 5f 02 ; &0a20 = colour_table_dithered_even_shift_1 : pixel colours 1313, shift 2 &460a 77 0a 5f 03 ; &0a77 = colour_table_dithered_even_shift_0 : pixel colours 1313, shift 3 &460e ce 0a f0 00 ; &0ace = colour_table_cue_shift_3 : pixel colours 2222, shift 0 &4612 25 0b f0 01 ; &0b25 = colour_table_cue_shift_2 : pixel colours 2222, shift 1 &4616 7c 0b f0 02 ; &0b7c = colour_table_cue_shift_1 : pixel colours 2222, shift 2 &461a d3 0b f0 03 ; &0bd3 = colour_table_cue_shift_0 : pixel colours 2222, shift 3 &461e 2a 0c ff 00 ; &0c2a = colour_table_black_shift_3 : pixel colours 3333, shift 0 &4622 81 0c ff 01 ; &0c81 = colour_table_black_shift_2 : pixel colours 3333, shift 1 &4626 d8 0c ff 02 ; &0cd8 = colour_table_black_shift_1 : pixel colours 3333, shift 2 &462a 2f 0d ff 03 ; &0d2f = colour_table_black_shift_0 : pixel colours 3333, shift 3 &462e 86 0d af 00 ; &0d86 = colour_table_dithered_odd_shift_3 : pixel colours 3131, shift 0 &4632 dd 0d af 01 ; &0ddd = colour_table_dithered_odd_shift_2 : pixel colours 3131, shift 1 &4636 34 0e af 02 ; &0e34 = colour_table_dithered_odd_shift_1 : pixel colours 3131, shift 2 &463a 8b 0e af 03 ; &0e8b = colour_table_dithered_odd_shift_0 : pixel colours 3131, shift 3 ; calculate_mask_table_value # Called with A = pixel value &463e a8 TAY &463f 85 02 STA &02 ; pixel_value # 76543210 &4641 4a LSR A &4642 4a LSR A &4643 4a LSR A &4644 4a LSR A # ....7654 &4645 05 02 ORA &02 ; pixel_value &4647 85 03 STA &03 ; set_pixels # Low four bits set if corresponding pixels not colour 0 &4649 0a ASL A &464a 0a ASL A &464b 0a ASL A &464c 0a ASL A # 7654.... &464d 05 03 ORA &03 ; set_pixels # Any pixels that weren't colour 0 are now colour 3 &464f 49 ff EOR #&ff # Invert to create a mask that is zero for set pixels &4651 05 02 ORA &02 ; sprite_pixel_value # Add original colour of pixels to mask &4653 60 RTS ; initialise_irq1_handler &4654 78 SEI &4655 ac 05 02 LDY &0205 ; irq1_vector_high &4658 ae 04 02 LDX &0204 ; irq1_vector_low &465b 8c c5 30 STY &30c5 ; previous_irq1_vector_high &465e 8e c4 30 STX &30c4 ; previous_irq1_vector_low &4661 a2 c6 LDX #&c6 ; &30c6 = irq1_handler &4663 a0 30 LDY #&30 &4665 8c 05 02 STY &0205 ; irq1_vector_high &4668 8e 04 02 STX &0204 ; irq1_vector_low &466b 58 CLI &466c ea NOP &466d 60 RTS ; initialise_sound &466e a2 00 LDX #&00 ; initialise_sound_loop &4670 bd 9b 46 LDA &469b,X ; sound_initial_bytes &4673 20 7c 46 JSR &467c ; write_initial_byte_sound_chip &4676 e8 INX &4677 e0 0b CPX #&0b &4679 90 f5 BCC &4670 ; initialise_sound_loop &467b 60 RTS ; write_initial_byte_sound_chip &467c 08 PHP ; tmp_a &467d 78 SEI &467e a0 ff LDY #&ff # Set all bits to to output &4680 8c 43 fe STY &fe43 ; System VIA data direction register A &4683 8d 41 fe STA &fe41 ; System VIA output register A # Write byte to sound chip &4686 c8 INY ; 0 # Set sound chip write pin low &4687 8c 40 fe STY &fe40 ; System VIA port B input/output register &468a a0 02 LDY #&02 ; delay_for_two_loop &468c 88 DEY &468d d0 fd BNE &468c ; delay_for_two_loop &468f a0 08 LDY #&08 # Set sound chip write pin high &4691 8c 40 fe STY &fe40 ; System VIA port B input/output register &4694 a0 08 LDY #&08 ; delay_for_eight_loop &4696 88 DEY &4697 d0 fd BNE &4696 ; delay_for_eight_loop &4699 28 PLP ; tmp_a &469a 60 RTS ; sound_initial_bytes &469b 80 ; set channel 3 frequency high to 0 &469c 00 ; set channel 3 frequency low to 0 &469d a0 ; set channel 2 frequency high to 0 &469e 00 ; set channel 3 frequency low to 0 &469f c0 ; set channel 1 frequency high to 0 &46a0 00 ; set channel 3 frequency low to 0 &46a1 e4 ; set channel 0 frequency to 4 &46a2 9f ; set channel 3 volume to 0 &46a3 bf ; set channel 2 volume to 0 &46a4 df ; set channel 1 volume to 0 &46a5 ff ; set channel 0 volume to 0 ; consider_using_sideways_ram &46a6 a2 0f LDX #&0f &46a8 8e 62 fe STX &fe62 ; User VIA data direction register B ; check_unoccupied_slots_loop &46ab bd a1 02 LDA &02a1,X ; os_paged_rom_type_table &46ae d0 05 BNE &46b5 ; consider_next_unoccupied_slot &46b0 20 3d 47 JSR &473d ; check_slot_for_sideways_ram # Returns carry set if slot is usable &46b3 b0 1b BCS &46d0 ; use_sideways_ram ; consider_next_unoccupied_slot &46b5 ca DEX &46b6 10 f3 BPL &46ab ; check_unoccupied_slots_loop &46b8 a2 0f LDX #&0f ; check_occupied_slots_loop &46ba bd a1 02 LDA &02a1,X ; os_paged_rom_type_table &46bd f0 05 BEQ &46c4 ; consider_next_occupied_slot &46bf 20 3d 47 JSR &473d ; check_slot_for_sideways_ram # Returns carry set if slot is usable &46c2 b0 0c BCS &46d0 ; use_sideways_ram ; consider_next_occupied_slot &46c4 ca DEX &46c5 10 f3 BPL &46ba ; check_occupied_slots_loop &46c7 a2 ff LDX #&ff &46c9 20 3d 47 JSR &473d ; check_slot_for_sideways_ram # Returns carry set if slot is usable &46cc b0 02 BCS &46d0 ; use_sideways_ram &46ce 18 CLC # Leave with carry clear to indicate not using sideways RAM &46cf 60 RTS ; use_sideways_ram &46d0 c6 6f DEC &6f ; sideways_ram_version # Set to negative to indicate using sideways RAM &46d2 8e 2f 47 STX &472f ; sideways_ram_slot &46d5 a2 00 LDX #&00 ; backup_function_keys_and_dfs_workspace_loop &46d7 bd 00 0b LDA &0b00,X ; os_function_key_data &46da 9d 00 80 STA &8000,X ; backup_of_os_function_key_data &46dd bd 00 10 LDA &1000,X ; dfs_workspace_1000 &46e0 9d 00 81 STA &8100,X ; backup_of_dfs_workspace_1000 &46e3 bd 00 17 LDA &1700,X ; dfs_workspace_1700 &46e6 9d 00 82 STA &8200,X ; backup_of_dfs_workspace_1700 &46e9 bd 00 18 LDA &1800,X ; dfs_workspace_1800 &46ec 9d 00 83 STA &8300,X ; backup_of_dfs_workspace_1800 &46ef e8 INX &46f0 d0 e5 BNE &46d7 ; backup_function_keys_and_dfs_workspace_loop &46f2 a2 0f LDX #&0f ; backup_paged_rom_data_loop &46f4 bd a1 02 LDA &02a1,X ; os_paged_rom_type_table &46f7 9d e0 af STA &afe0,X ; backup_of_os_paged_rom_type_table &46fa bd f0 0d LDA &0df0,X ; os_paged_rom_workspace_addresses &46fd 9d f0 af STA &aff0,X ; backup_of_os_paged_rom_workspace_addresses &4700 ca DEX &4701 10 f1 BPL &46f4 ; backup_paged_rom_data_loop ; initialise_break_handler &4703 a2 11 LDX #&11 ; copy_break_handler_loop # Copy &472b - &473c to &0184 to &0195 &4705 bd 2b 47 LDA &472b,X ; unrelocated_break_handler &4708 9d 84 01 STA &0184,X ; break_handler &470b ca DEX &470c 10 f7 BPL &4705 ; copy_break_handler_loop &470e a9 f8 LDA #&f8 ; Write LSB BREAK interceptor jump address # Set BREAK to jump to &0184 (break_handler) &4710 a2 84 LDX #&84 ; &0184 = break_handler &4712 a0 00 LDY #&00 &4714 20 f4 ff JSR &fff4 ; OSBYTE &4717 a9 f9 LDA #&f9 ; Write MSB BREAK interceptor jump address &4719 a2 01 LDX #&01 &471b a0 00 LDY #&00 &471d 20 f4 ff JSR &fff4 ; OSBYTE &4720 a9 f7 LDA #&f7 ; Write BREAK interceptor jump instruction &4722 a2 4c LDX #&4c ; JMP &4724 a0 00 LDY #&00 &4726 20 f4 ff JSR &fff4 ; OSBYTE &4729 38 SEC # Leave with carry set to indicate using sideways RAM &472a 60 RTS # &472b - &473c is copied to &0184 to &0195 at &4705 if sideways RAM is used ; break_handler &0184 a5 f4 LDA &f4 ; os_ram_copy_of_currently_selected_rom_number &0186 48 PHA ; rom number &0187 a9 ff LDA #&ff # actually LDA sideways_ram_slot &0189 20 90 01 JSR &0190 ; select_slot &018c 20 1b 84 JSR &841b ; restore_data_from_sideways_ram &018f 68 PLA ; rom number ; select_slot &0190 85 f4 STA &f4 ; os_ram_copy_of_currently_selected_rom_number &0192 8d 30 fe STA &fe30 ; Paged ROM latch &0195 60 RTS ; check_slot_for_sideways_ram &473d 86 f4 STX &f4 ; os_ram_copy_of_currently_selected_rom_number &473f 8e 30 fe STX &fe30 ; Paged ROM latch &4742 8e 32 fe STX &fe32 ; Solidisk RAM access register &4745 8e 60 fe STX &fe60 ; User VIA port B input/output register &4748 bd 30 ff LDA &ff30,X ; Watford Electronics ROM/RAM board write latches &474b 9d 30 ff STA &ff30,X ; Watford Electronics ROM/RAM board write latches &474e a9 00 LDA #&00 &4750 8d 00 80 STA &8000 &4753 cd 00 80 CMP &8000 &4756 d0 1b BNE &4773 ; leave_with_carry_clear # Check that slot is writeable &4758 a9 ff LDA #&ff &475a 8d 00 80 STA &8000 &475d cd 00 80 CMP &8000 &4760 d0 11 BNE &4773 ; leave_with_carry_clear # Check that slot is writeable &4762 a9 00 LDA #&00 &4764 8d 00 a0 STA &a000 &4767 cd 00 a0 CMP &a000 &476a d0 07 BNE &4773 ; leave_with_carry_clear # Check that slot has usable 16k &476c cd 00 80 CMP &8000 &476f f0 02 BEQ &4773 ; leave_with_carry_clear # Check that slot has usable 16k &4771 38 SEC # Leave with carry set to indicate slot is usable &4772 60 RTS ; leave_with_carry_clear &4773 18 CLC # Leave with carry clear to indicate slot is not usable &4774 60 RTS ; initialise_sideways_ram_code &4775 78 SEI &4776 a2 00 LDX #&00 &4778 a0 ff LDY #&ff ; copy_sideways_ram_code_loop &477a bd 94 49 LDA &4994,X ; unrelocated_sideways_ram_code &477d dd 00 84 CMP &8400,X ; sideways_ram_code &4780 9d 00 84 STA &8400,X ; sideways_ram_code &4783 f0 02 BEQ &4787 ; no_change &4785 a0 00 LDY #&00 # Set to positive to indicate code wasn't present ; no_change &4787 e8 INX &4788 e0 81 CPX #&81 &478a 90 ee BCC &477a ; copy_sideways_ram_code_loop &478c 84 b0 STY &b0 ; sideways_ram_code_needed_copying # Negative if sideways ram code was already present ; initialise_sideways_ram_screen_copying_code &478e a2 81 LDX #&81 ; &8481 = copy_from_sideways_ram_to_screen_one &4790 a0 84 LDY #&84 &4792 84 03 STY &03 ; copy_to_screen_one_code_address_high &4794 86 02 STX &02 ; copy_to_screen_one_code_address_low &4796 a2 58 LDX #&58 ; &8758 = copy_from_sideways_ram_to_screen_two &4798 a0 87 LDY #&87 &479a 84 05 STY &05 ; copy_to_screen_two_code_address_high &479c 86 04 STX &04 ; copy_to_screen_two_code_address_low &479e a9 00 LDA #&00 &47a0 85 06 STA &06 ; address_offset_low &47a2 85 07 STA &07 ; address_offset_high &47a4 a2 78 LDX #&78 ; initialise_sideways_ram_screen_copying_code_loop # Build copy_from_sideways_ram_to_screen_* &47a6 a0 00 LDY #&00 &47a8 a9 bd LDA #&bd ; LDA &....,X &47aa 91 02 STA (&02),Y ; copy_to_screen_one_code_address &47ac 91 04 STA (&04),Y ; copy_to_screen_two_code_address &47ae c8 INY &47af a5 06 LDA &06 ; address_offset_low &47b1 91 02 STA (&02),Y ; copy_to_screen_one_code_address &47b3 91 04 STA (&04),Y ; copy_to_screen_two_code_address &47b5 c8 INY &47b6 18 CLC &47b7 a5 07 LDA &07 ; address_offset_high &47b9 69 91 ADC #&91 ; &9100 = sideways_ram_screen_buffer &47bb 91 02 STA (&02),Y ; copy_to_screen_one_code_address &47bd 91 04 STA (&04),Y ; copy_to_screen_two_code_address &47bf c8 INY &47c0 a9 9d LDA #&9d ; STA &....,X &47c2 91 02 STA (&02),Y ; copy_to_screen_one_code_address &47c4 91 04 STA (&04),Y &47c6 c8 INY &47c7 a5 06 LDA &06 ; address_offset_low &47c9 91 02 STA (&02),Y ; copy_to_screen_one_code_address &47cb 91 04 STA (&04),Y ; copy_to_screen_two_code_address &47cd c8 INY &47ce 18 CLC &47cf a5 07 LDA &07 ; address_offset_high &47d1 69 44 ADC #&44 ; &4400 = screen_one &47d3 91 02 STA (&02),Y ; copy_to_screen_one_code_address &47d5 18 CLC &47d6 a5 07 LDA &07 ; address_offset_high &47d8 69 62 ADC #&62 ; &6200 = screen_two &47da 91 04 STA (&04),Y ; copy_to_screen_two_code_address &47dc 18 CLC &47dd a5 06 LDA &06 ; address_offset_low &47df 69 40 ADC #&40 &47e1 85 06 STA &06 ; address_offset_low &47e3 90 02 BCC &47e7 ; skip_offset_page &47e5 e6 07 INC &07 ; address_offset_high ; skip_offset_page &47e7 38 SEC &47e8 98 TYA &47e9 65 02 ADC &02 ; copy_to_screen_one_code_address_low &47eb 85 02 STA &02 ; copy_to_screen_one_code_address_low &47ed 90 02 BCC &47f1 ; skip_one_page &47ef e6 03 INC &03 ; copy_to_screen_one_code_address_high ; skip_one_page &47f1 38 SEC &47f2 98 TYA &47f3 65 04 ADC &04 ; copy_to_screen_two_code_address_low &47f5 85 04 STA &04 ; copy_to_screen_two_code_address_low &47f7 90 02 BCC &47fb ; skip_two_page &47f9 e6 05 INC &05 ; copy_to_screen_two_code_address_high ; skip_two_page &47fb ca DEX &47fc d0 a8 BNE &47a6 ; initialise_sideways_ram_screen_copying_code_loop ; copy_end_of_sideways_ram_screen_copying_code_loop &47fe bd 86 49 LDA &4986,X ; unrelocated_copy_from_sideways_ram_to_screen_one_end &4801 9d 51 87 STA &8751,X ; copy_from_sideways_ram_to_screen_one_end &4804 bd 8d 49 LDA &498d,X ; unrelocated_copy_from_sideways_ram_to_screen_two_end &4807 9d 28 8a STA &8a28,X ; copy_from_sideways_ram_to_screen_two_end &480a e8 INX &480b e0 07 CPX #&07 &480d 90 ef BCC &47fe ; copy_end_of_sideways_ram_screen_copying_code_loop &480f 58 CLI &4810 ea NOP &4811 a5 f4 LDA &f4 ; os_ram_copy_of_currently_selected_rom_number &4813 c9 ff CMP #&ff &4815 d0 01 BNE &4818 ; initialise_velocities_and_row_addresses # Should always branch &4817 60 RTS ; initialise_velocities_and_row_addresses &4818 a2 00 LDX #&00 ; initialise_velocities_and_row_addresses_tables_loop &481a 8a TXA # Multiply velocity by eight &481b 0a ASL A # Get top nibble &481c 2a ROL A &481d 2a ROL A &481e 2a ROL A &481f 29 07 AND #&07 # .421.... -> .....421 &4821 c9 04 CMP #&04 # &40 of velocity sets sign &4823 90 02 BCC &4827 ; not_negative &4825 09 f8 ORA #&f8 ; not_negative &4827 9d 00 b9 STA &b900,X ; velocities_table &482a 8a TXA &482b 0a ASL A # ...18421 -> 18421... &482c 0a ASL A &482d 0a ASL A &482e 9d 00 b8 STA &b800,X ; velocities_fraction_table &4831 8a TXA &4832 29 07 AND #&07 &4834 85 0c STA &0c ; row_in_group &4836 8a TXA &4837 29 f8 AND #&f8 &4839 4a LSR A &483a 4a LSR A &483b a8 TAY &483c b9 ef 37 LDA &37ef,Y ; group_offsets_table &483f 05 0c ORA &0c ; row_in_group &4841 9d 00 ba STA &ba00,X ; row_addresses_low_table &4844 b9 f0 37 LDA &37f0,Y ; group_offsets_table + 1 &4847 9d 00 bb STA &bb00,X ; row_addresses_high_table &484a e8 INX &484b d0 cd BNE &481a ; initialise_velocities_and_row_addresses_tables_loop ; copy_alternative_apply_velocities_to_ball_loop &484d bd d9 48 LDA &48d9,X ; alternative_apply_velocities_to_ball &4850 9d 7c 16 STA &167c,X ; apply_velocities_to_ball &4853 e8 INX &4854 e0 48 CPX #&48 &4856 90 f5 BCC &484d ; copy_alternative_apply_velocities_to_ball_loop &4858 a2 00 LDX #&00 ; copy_alternative_calculate_row_address_loop &485a bd 08 49 LDA &4908,X ; alternative_calculate_row_address &485d 9d 8e 1e STA &1e8e,X ; calculate_row_address &4860 e8 INX &4861 e0 21 CPX #&21 &4863 90 f5 BCC &485a ; copy_alternative_calculate_row_address_loop &4865 20 04 44 JSR &4404 ; initialise_squares_tables # Unnecessary code; already initialised at &4390 ; initialise_alternative_multiply &4868 a2 01 LDX #&01 ; &fe01 = &ff * &ff &486a a0 fe LDY #&fe &486c 84 07 STY &07 ; minus_square_high &486e 86 06 STX &06 ; minus_square_low &4870 a2 02 LDX #&02 ; &fe02 = (&ff * &ff) + 1 &4872 a0 fe LDY #&fe &4874 84 09 STY &09 ; minus_delta_high &4876 86 08 STX &08 ; minus_delta_low &4878 a0 00 LDY #&00 &487a 84 02 STY &02 ; plus_square_low &487c 84 03 STY &03 ; plus_square_high &487e 84 04 STY &04 ; plus_delta_low &4880 84 05 STY &05 ; plus_delta_high &4882 84 0a STY &0a ; plus_high_high &4884 84 0b STY &0b ; minus_high_high &4886 a9 b0 LDA #&b0 ; &b000 = plus_half_squares_low_table # Populate &b000 - &b1ff and &b200 - &b3ff &4888 85 b3 STA &b3 ; plus_half_squares_low_table_address_high # with low and high bytes of (X / 2) squared &488a 8d 34 49 STA &4934 ; plus_half_squares_low_table_address_low &488d a9 b2 LDA #&b2 ; &b200 = plus_half_squares_high_table &488f 85 b5 STA &b5 ; plus_half_squares_high_table_address_high &4891 8d 38 49 STA &4938 ; plus_half_squares_high_table_address_low &4894 a9 b4 LDA #&b4 ; &b400 = minus_half_squares_low_table # Populate &b400 - &b5ff and &b600 - &b7ff &4896 85 b7 STA &b7 ; minus_half_squares_low_table_address_high # with low and high bytes of ((X - &100) / 2) squared &4898 8d 4e 49 STA &494e ; minus_half_squares_low_table_address_low &489b a9 b6 LDA #&b6 ; &b600 = minus_half_squares_high_table &489d 85 b9 STA &b9 ; minus_half_squares_high_table_address_high &489f 8d 52 49 STA &4952 ; minus_half_squares_high_table_address_low &48a2 20 1f 49 JSR &491f ; initialise_half_squares_tables &48a5 ee 34 49 INC &4934 ; plus_half_squares_low_table_address_low &48a8 ee 38 49 INC &4938 ; plus_half_squares_high_table_address_low &48ab ee 4e 49 INC &494e ; minus_half_squares_low_table_address_low &48ae ee 52 49 INC &4952 ; minus_half_squares_high_table_address_low &48b1 20 1f 49 JSR &491f ; initialise_half_squares_tables &48b4 a2 00 LDX #&00 ; copy_alternative_multiply_X_and_Y_loop &48b6 bd c2 48 LDA &48c2,X ; alternative_multiply_X_and_Y &48b9 9d 3c 24 STA &243c,X ; multiply_X_and_Y &48bc e8 INX &48bd e0 17 CPX #&17 &48bf 90 f5 BCC &48b6 ; copy_alternative_multiply_X_and_Y_loop &48c1 60 RTS # &48c2 - &48d8 is moved to &243c - &2452 at &48b6 if sideways RAM is used ; alternative_multiply_X_and_Y # Multiply two eight bit unsigned numbers &243c 8a TXA &243d 85 b2 STA &b2 ; plus_half_squares_low_table_address_low &243f 85 b4 STA &b4 ; plus_half_squares_high_table_address_low &2441 49 ff EOR #&ff &2443 85 b6 STA &b6 ; minus_half_squares_low_table_address_low &2445 85 b8 STA &b8 ; minus_half_squares_high_table_address_low &2447 38 SEC &2448 b1 b2 LDA (&b2),Y ; plus_half_squares_low_table_address # ((Y + X) / 2) ^ 2 &244a f1 b6 SBC (&b6),Y ; minus_half_squares_low_table_address # -((Y - X) / 2) ^ 2 &244c aa TAX # = ((Y^2 + 2XY + X^2) - (Y^2 - 2XY + X^2)) / 4 &244d b1 b4 LDA (&b4),Y ; plus_half_squares_high_table_address # = 4XY / 4 &244f f1 b8 SBC (&b8),Y ; minus_half_squares_high_table_address # = XY &2451 a8 TAY &2452 60 RTS # Leave with X = result low, Y = result high # &48d9 - &4907 is moved to &167c - &16aa at &484d if sideways RAM is used ; alternative_apply_velocities_to_ball &167c bc 72 0f LDY &0f72,X ; balls_x_velocity &167f 18 CLC &1680 bd 52 0f LDA &0f52,X ; balls_table_x_fraction &1683 79 00 b8 ADC &b800,Y ; velocities_fraction_table &1686 9d 52 0f STA &0f52,X ; balls_table_x_fraction &1689 bd 22 0f LDA &0f22,X ; balls_table_x &168c 79 00 b9 ADC &b900,Y ; velocities_table &168f 9d 22 0f STA &0f22,X ; balls_table_x &1692 bc 82 0f LDY &0f82,X ; balls_y_velocity &1695 18 CLC &1696 bd 62 0f LDA &0f62,X ; balls_table_y_fraction &1699 79 00 b8 ADC &b800,Y ; velocities_fraction_table &169c 9d 62 0f STA &0f62,X ; balls_table_y_fraction &169f bd 42 0f LDA &0f42,X ; balls_table_y &16a2 79 00 b9 ADC &b900,Y ; velocities_table &16a5 9d 42 0f STA &0f42,X ; balls_table_y &16a8 4c c4 16 JMP &16c4 ; check_for_bounce_off_right_table_edge # &4908 - &491e is moved to &1e8e - &1ea4 at &485a if sideways RAM is used ; alternative_calculate_row_address # Look up screen address for start of row &1e8e 8a TXA &1e8f 29 7c AND #&7c &1e91 0a ASL A &1e92 79 00 ba ADC &ba00,Y ; row_addresses_low_table &1e95 85 67 STA &67 ; fill_screen_address_low &1e97 b9 00 bb LDA &bb00,Y ; row_addresses_high_table &1e9a 65 a0 ADC &a0 ; background_screen_address_high &1e9c e0 80 CPX #&80 &1e9e 69 00 ADC #&00 &1ea0 85 68 STA &68 ; fill_screen_address_high &1ea2 4c af 1e JMP &1eaf ; consider_left_of_row ; initialise_half_squares_tables ; initialise_half_squares_tables_loop &491f a5 0a LDA &0a ; plus_high_high &4921 24 05 BIT &05 ; plus_delta_high &4923 08 PHP ; plus delta sign &4924 a2 02 LDX #&02 &4926 20 57 49 JSR &4957 ; calculate_next_half_square # Returns A = result low, X = result high &4929 90 02 BCC &492d ; skip_overflow_plus &492b e6 0a INC &0a ; plus_high_high ; skip_overflow_plus &492d 28 PLP ; plus delta sign &492e 10 02 BPL &4932 ; skip_underflow_plus &4930 c6 0a DEC &0a ; plus_high_high ; skip_underflow_plus &4932 99 00 b0 STA &b000,Y # actually STA plus_half_squares_low_table_address_low,Y &4935 8a TXA &4936 99 00 b2 STA &b200,Y # actually STA plus_half_squares_high_table_address_low,Y &4939 a5 0b LDA &0b ; minus_high_high &493b 24 09 BIT &09 ; minus_delta_high &493d 08 PHP ; minus delta sign &493e a2 06 LDX #&06 &4940 20 57 49 JSR &4957 ; calculate_next_half_square # Returns A = result low, X = result high &4943 90 02 BCC &4947 ; skip_overflow_minus &4945 e6 0b INC &0b ; minus_high_high ; skip_overflow_minus &4947 28 PLP ; minus delta sign &4948 10 02 BPL &494c ; skip_underflow_minus &494a c6 0b DEC &0b ; minus_high_high ; skip_underflow_minus &494c 99 00 b4 STA &b400,Y # actually STA minus_half_squares_low_table_address_low,Y &494f 8a TXA &4950 99 00 b6 STA &b600,Y # actually STA minus_half_squares_low_table_address_high,Y &4953 c8 INY &4954 d0 c9 BNE &491f ; initialise_half_squares_tables_loop &4956 60 RTS ; calculate_next_half_square # Noting that (x + 1)^2 = x^2 + 2x + 1, &4957 48 PHA ; plus_high_high or minus_high_high # square = (2x)^2 &4958 38 SEC &4959 b5 00 LDA &00,X ; plus_square_low - 2 # If X = 2, plus_square += plus_delta + 1 &495b 85 0c STA &0c ; result_low # If X = 6, minus_square += minus_delta + 1 &495d 75 02 ADC &02,X ; plus_delta_low - 2 &495f 95 00 STA &00,X ; plus_square_low - 2 &4961 b5 01 LDA &01,X ; plus_square_high - 2 &4963 85 0d STA &0d ; result_high &4965 75 03 ADC &03,X ; plus_delta_high - 2 &4967 95 01 STA &01,X ; plus_square_high - 2 &4969 68 PLA ; plus_high_high or minus_high_high &496a 08 PHP ; square overflow &496b 4a LSR A # result = (square + delta) / 4, i.e. (x + 1)^2 &496c 66 0d ROR &0d ; result_high &496e 66 0c ROR &0c ; result_low &4970 4a LSR A &4971 66 0d ROR &0d ; result_high &4973 66 0c ROR &0c ; result_low &4975 18 CLC &4976 b5 02 LDA &02,X ; plus_delta_low - 2 # If X = 2, plus_delta += 2 &4978 69 02 ADC #&02 # If X = 6, minus_delta += 2 &497a 95 02 STA &02,X ; plus_delta_low - 2 &497c 90 02 BCC &4980 ; skip_overflow &497e f6 03 INC &03,X ; plus_delta_high - 2 ; skip_overflow &4980 a5 0c LDA &0c ; result_low &4982 a6 0d LDX &0d ; result_high &4984 28 PLP ; square overflow &4985 60 RTS # Leave with A = result low, X = result high # &4986 - &498c is moved to &8751 - &8757 at &47fe if sideways RAM is used ; copy_from_sideways_ram_to_screen_one ; copy_from_sideways_ram_to_screen_one_loop #8481 bd 00 91 LDA &9100,X ; sideways_ram_screen_buffer # &8481 - &8750 is built at &478e #8484 9d 00 44 STA &4400,X ; screen_one #8487 bd 40 91 LDA &9140,X ; sideways_ram_screen_buffer + &40 #848a 9d 40 44 STA &4440,X ; screen_one + &40 # ... #8745 bd 80 ae LDA &ae80,X ; sideways_ram_screen_buffer + &1d80 #8748 9d 80 61 STA &6180,X ; screen_one + &1d80 #874b bd c0 ae LDA &aec0,X ; sideways_ram_screen_buffer + &1dc0 #874e 9d c0 61 STA &61c0,X ; screen_one + &1dc0 ; copy_from_sideways_ram_to_screen_one_end &8751 ca DEX &8752 30 03 BMI &8757 ; leave &8754 4c 81 84 JMP &8481 ; copy_from_sideways_ram_to_screen_one_loop ; leave &8757 60 RTS # &498d - &4993 is moved to &8a28 - &8a2e at &4804 if sideways RAM is used ; copy_from_sideways_ram_to_screen_two ; copy_from_sideways_ram_to_screen_two_loop #8758 bd 00 91 LDA &9100,X ; sideways_ram_screen_buffer # &8758 - &82a7 is built at &478e #875b 9d 00 62 STA &6200,X ; screen_two #875e bd 40 91 LDA &9140,X ; sideways_ram_screen_buffer + &40 #8761 9d 40 62 STA &6240,X ; screen_two + &40 # ... #8a1c bd 80 ae LDA &ae80,X ; sideways_ram_screen_buffer + &1d80 #8a1f 9d 80 7f STA &7f80,X ; screen_two + &1d80 #8a22 bd c0 ae LDA &aec0,X ; sideways_ram_screen_buffer + &1dc0 #8a25 9d c0 7f STA &7fc0,X ; screen_two + &1dc0 ; buffer_screen_from_sideways_ram_end &8a28 ca DEX &8a29 30 03 BMI &8a2e ; leave &8a2b 4c 58 87 JMP &8758 ; copy_from_sideways_ram_to_screen_two_loop ; leave &8a2e 60 RTS # &4994 - &4a14 is moved to &8400 - &8480 at &477a if sideways RAM is used ; sideways_ram_code &8400 49 20 48 45 41 52 44 20 59 4f 55 20 54 48 45 20 ; "I HEARD YOU THE FIRST TIME!" &8410 46 49 52 53 54 20 54 49 4d 45 21 ; restore_data_from_sideways_ram &841b 78 SEI &841c 48 PHA ; tmp_a &841d 8a TXA &841e 48 PHA ; tmp_x &841f 98 TYA &8420 48 PHA ; tmp_y &8421 a0 00 LDY #&00 &8423 84 70 STY &70 ; wipe_address_low &8425 a9 08 LDA #&08 &8427 85 71 STA &71 ; wipe_address_high &8429 98 TYA ; wipe_0800_to_7fff_loop # Wipe &0800 - &7fff &842a 91 70 STA (&70),Y ; wipe_address &842c c8 INY &842d d0 fb BNE &842a ; wipe_0800_to_7fff_loop &842f e6 71 INC &71 ; wipe_address_high &8431 10 f7 BPL &842a ; wipe_0800_to_7fff_loop &8433 a2 00 LDX #&00 ; restore_function_keys_and_dfs_workspace_loop &8435 bd 00 80 LDA &8000,X ; backup_of_os_function_key_data &8438 9d 00 0b STA &0b00,X ; os_function_key_data &843b bd 00 81 LDA &8100,X ; backup_of_dfs_workspace_1000 &843e 9d 00 10 STA &1000,X ; dfs_workspace_1000 &8441 bd 00 82 LDA &8200,X ; backup_of_dfs_workspace_1700 &8444 9d 00 17 STA &1700,X ; dfs_workspace_1700 &8447 bd 00 83 LDA &8300,X ; backup_of_dfs_workspace_1800 &844a 9d 00 18 STA &1800,X ; dfs_workspace_1800 &844d e8 INX &844e d0 e5 BNE &8435 ; restore_function_keys_and_dfs_workspace_loop &8450 a2 0f LDX #&0f ; restore_paged_rom_data_loop &8452 bd e0 af LDA &afe0,X ; backup_of_os_paged_rom_type_table &8455 9d a1 02 STA &02a1,X ; os_paged_rom_type_table &8458 bd f0 af LDA &aff0,X ; backup_of_os_paged_rom_workspace_addresses &845b 9d f0 0d STA &0df0,X ; os_paged_rom_workspace_addresses &845e ca DEX &845f 10 f1 BPL &8452 ; restore_paged_rom_data_loop &8461 a9 f7 LDA #&f7 ; Write BREAK interceptor jump instruction # Clear break handler &8463 a2 00 LDX #&00 &8465 a0 00 LDY #&00 &8467 20 f4 ff JSR &fff4 ; OSBYTE &846a 58 CLI &846b ea NOP &846c 68 PLA ; tmp_y &846d a8 TAY &846e 68 PLA ; tmp_x &846f aa TAX &8470 68 PLA ; tmp_a &8471 60 RTS ; unbuffer_screen_from_sideways_ram &8472 a2 3f LDX #&3f &8474 a5 27 LDA &27 ; buffer_start_address_high &8476 c9 62 CMP #&62 ; &6200 = screen_two ; wait_for_buffer_swap &8478 24 40 BIT &40 ; crtc_start_address_high # Positive if buffer is waiting to be swapped &847a 10 fc BPL &8478 ; wait_for_buffer_swap &847c 90 03 BCC &8481 ; copy_from_sideways_ram_to_screen_one &847e 4c 58 87 JMP &8758 ; copy_from_sideways_ram_to_screen_two # &4a15 - &78bb is moved to &1056 - &3efc at &41d7 ; after_initialisation_finished &1056 a9 62 LDA #&62 ; &6200 = screen_two &1058 85 27 STA &27 ; buffer_start_address_high &105a 20 dd 22 JSR &22dd ; calculate_crtc_start_address &105d a9 00 LDA #&00 &105f 85 85 STA &85 ; keyboard_or_joystick # Set to positive to use keyboard &1061 a9 00 LDA #&00 ; MATCH_TYPE_TOURNAMENT &1063 85 87 STA &87 ; match_type &1065 20 6f 2e JSR &2e6f ; new_tournament &1068 4c c1 10 JMP &10c1 ; start_or_continue_frame ; start_frame &106b a9 00 LDA #&00 &106d 85 2e STA &2e ; player_viewpoint_horizontal_rotation &106f a9 12 LDA #&12 &1071 85 2f STA &2f ; player_viewpoint_vertical_rotation ; start_frame_without_resetting_viewpoint &1073 a9 0a LDA #&0a ; STRIKE_MIDDLE &1075 85 31 STA &31 ; player_strike_point &1077 a9 08 LDA #&08 &1079 85 30 STA &30 ; player_strike_power &107b 20 73 14 JSR &1473 ; initialise_balls &107e a9 00 LDA #&00 &1080 85 3a STA &3a ; horizontal_rotation_speed &1082 85 3b STA &3b ; vertical_rotation_speed &1084 85 4b STA &4b ; unused # Unused variable &1086 85 4c STA &4c ; trick_state # Set to positive to indicate not playing trick &1088 85 51 STA &51 ; permit_swapping_colours # Set to positive to indicates colours can't be swapped &108a a9 01 LDA #&01 &108c 85 53 STA &53 ; return_or_fire_state # Set to one to indicate not recently pressed &108e a9 ff LDA #&ff &1090 85 4f STA &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint &1092 18 CLC &1093 a5 99 LDA &99 ; players_frames_won &1095 65 9a ADC &9a ; players_frames_won + 1 &1097 29 01 AND #&01 &1099 a6 87 LDX &87 ; match_type &109b f0 02 BEQ &109f ; is_tournament # In a tournament, set first player from frames won &109d a9 00 LDA #&00 # Otherwise, player one starts ; is_tournament &109f 85 78 STA &78 ; active_player &10a1 a9 01 LDA #&01 &10a3 85 72 STA &72 ; cue_balls_remaining # Set to one to indicate player has cue ball &10a5 a9 00 LDA #&00 &10a7 85 79 STA &79 ; black_ball_potted # Set to zero to indicate black not potted &10a9 85 7b STA &7b ; player_has_free_ball # Set to zero to indicate no free ball &10ab 85 52 STA &52 ; previous_return_or_fire_pressed &10ad 85 54 STA &54 ; return_or_fire_pressed # Set to zero to indicate not pressed ; main_game_loop &10af 24 4c BIT &4c ; trick_state # Negative if playing trick &10b1 30 13 BMI &10c6 ; escape_not_pressed &10b3 24 98 BIT &98 ; frame_in_progress # Negative if frame in progress &10b5 10 07 BPL &10be ; menu_screen_then_start_or_continue_frame &10b7 a9 8f LDA #&8f ; ESCAPE &10b9 20 64 32 JSR &3264 ; check_for_keypress &10bc 10 08 BPL &10c6 ; escape_not_pressed ; menu_screen_then_start_or_continue_frame &10be 20 3b 2d JSR &2d3b ; menu_screen # Returns carry set if starting new frame ; start_or_continue_frame &10c1 b0 a8 BCS &106b ; start_frame &10c3 20 78 1c JSR &1c78 ; update_screen ; escape_not_pressed &10c6 a9 00 LDA #&00 &10c8 85 86 STA &86 ; only_potential_move # Set to positive to indicate moves are real &10ca a5 97 LDA &97 ; tournament_opponent &10cc 85 8e STA &8e ; computer_player &10ce a5 87 LDA &87 ; match_type &10d0 a6 78 LDX &78 ; active_player &10d2 c9 02 CMP #&02 ; MATCH_TYPE_DEMO &10d4 90 16 BCC &10ec ; is_tournament_or_two_player &10d6 f0 0d BEQ &10e5 ; is_demo &10d8 c9 04 CMP #&04 ; MATCH_TYPE_TRICK &10da f0 27 BEQ &1103 ; not_computer_move ; is_practice &10dc a5 9d LDA &9d ; practice_player &10de 85 8e STA &8e ; computer_player &10e0 8a TXA &10e1 f0 20 BEQ &1103 ; not_computer_move &10e3 d0 0d BNE &10f2 ; consider_computer_move # Always branches ; is_demo &10e5 b5 9b LDA &9b,X ; demo_players &10e7 85 8e STA &8e ; computer_player &10e9 4c f2 10 JMP &10f2 ; consider_computer_move ; is_tournament_or_two_player &10ec a8 TAY &10ed d0 14 BNE &1103 ; not_computer_move # Branch if two-player match &10ef 8a TXA &10f0 f0 11 BEQ &1103 ; not_computer_move # Branch if human player's turn in tournament ; consider_computer_move &10f2 24 4c BIT &4c ; trick_state # Negative if playing trick &10f4 30 0d BMI &1103 ; not_computer_move &10f6 c6 86 DEC &86 ; only_potential_move # Set to negative to indicate moves are potential &10f8 20 34 25 JSR &2534 ; calculate_computer_move &10fb 20 78 1c JSR &1c78 ; update_screen &10fe e6 86 INC &86 ; only_potential_move # Set to positive to indicate moves are real &1100 4c 39 13 JMP &1339 ; start_move ; not_computer_move &1103 20 b0 31 JSR &31b0 ; check_for_player_movement &1106 a5 87 LDA &87 ; match_type &1108 c9 04 CMP #&04 ; MATCH_TYPE_TRICK &110a d0 23 BNE &112f ; not_editing_trick &110c 24 50 BIT &50 ; placing_ball # Negative if placing ball &110e 10 1f BPL &112f ; not_editing_trick &1110 24 4c BIT &4c ; trick_state # Negative if playing trick &1112 30 1b BMI &112f ; not_editing_trick &1114 a9 dc LDA #&dc ; T # If T is pressed while editing a trick, &1116 20 64 32 JSR &3264 ; check_for_keypress &1119 10 14 BPL &112f ; not_editing_trick &111b a9 02 LDA #&02 # Tricks are stored in layouts two onwards &111d 18 CLC &111e 65 a2 ADC &a2 ; trick_number &1120 20 58 1a JSR &1a58 ; store_balls_in_layout # Store the trick layout &1123 a2 03 LDX #&03 ; use_trick_viewpoint_loop # and use the last played shot to test the trick &1125 b5 36 LDA &36,X ; trick_viewpoint &1127 95 32 STA &32,X ; viewpoint &1129 ca DEX &112a 10 f9 BPL &1125 ; use_trick_viewpoint_loop &112c 4c 39 13 JMP &1339 ; start_move ; not_editing_trick &112f a5 a9 LDA &a9 ; focus_ball &1131 f0 2b BEQ &115e ; a_not_pressed # If the cue ball isn't focused, &1133 24 50 BIT &50 ; placing_ball # Negative if placing ball &1135 10 27 BPL &115e ; a_not_pressed &1137 a9 be LDA #&be ; A &1139 20 64 32 JSR &3264 ; check_for_keypress # If A is pressed while editing a trick, &113c 10 20 BPL &115e ; a_not_pressed ; wait_for_a_to_be_released &113e 20 0a 2d JSR &2d0a ; wait_for_vsync &1141 a9 be LDA #&be ; A &1143 20 64 32 JSR &3264 ; check_for_keypress &1146 30 f6 BMI &113e ; wait_for_a_to_be_released &1148 a9 01 LDA #&01 ; SOUND_COLLISION &114a 20 20 30 JSR &3020 ; start_sound # Play a sound for toggling the presence of the ball &114d a6 a9 LDX &a9 ; focus_ball &114f bd e2 0e LDA &0ee2,X ; balls_state # Negative if ball not present &1152 30 04 BMI &1158 ; set_ball_present &1154 a9 ff LDA #&ff &1156 30 03 BMI &115b ; set_ball_state ; set_ball_present &1158 bd df 37 LDA &37df,X ; balls_colour ; set_ball_state &115b 9d e2 0e STA &0ee2,X ; balls_state # Toggle the presence of the ball ; a_not_pressed &115e a2 00 LDX #&00 &1160 a9 c6 LDA #&c6 ; UP &1162 20 64 32 JSR &3264 ; check_for_keypress &1165 10 01 BPL &1168 ; up_not_pressed &1167 ca DEX # Zoom in if UP pressed ; up_not_pressed &1168 a9 d6 LDA #&d6 ; DOWN &116a 20 64 32 JSR &3264 ; check_for_keypress &116d 10 01 BPL &1170 ; down_not_pressed &116f e8 INX # Zoom out if DOWN pressed ; down_not_pressed &1170 8a TXA &1171 f0 12 BEQ &1185 ; skip_changing_zoom &1173 0a ASL A &1174 0a ASL A &1175 0a ASL A &1176 18 CLC &1177 65 3d ADC &3d ; viewpoint_zoom &1179 c9 28 CMP #&28 &117b b0 08 BCS &1185 ; skip_changing_zoom &117d c5 3d CMP &3d ; viewpoint_zoom &117f 85 3d STA &3d ; viewpoint_zoom &1181 f0 02 BEQ &1185 ; skip_changing_zoom &1183 c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint ; skip_changing_zoom &1185 a9 ca LDA #&ca ; U &1187 20 64 32 JSR &3264 ; check_for_keypress # If U pressed, &118a c5 9e CMP &9e ; suppress_u_autorepeat &118c 85 9e STA &9e ; suppress_u_autorepeat # Set to negative if U pressed &118e f0 0a BEQ &119a ; u_not_pressed &1190 90 08 BCC &119a ; u_not_pressed &1192 a5 2e LDA &2e ; player_viewpoint_horizontal_rotation &1194 49 80 EOR #&80 ; 180 degrees # Rotate viewpoint by 180 degrees horizontally &1196 85 2e STA &2e ; player_viewpoint_horizontal_rotation &1198 c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint ; u_not_pressed &119a a6 87 LDX &87 ; match_type &119c e0 04 CPX #&04 ; MATCH_TYPE_TRICK &119e f0 04 BEQ &11a4 ; consider_if_s_pressed &11a0 24 51 BIT &51 ; permit_swapping_colours # Negative if colours can be swapped &11a2 10 2b BPL &11cf ; s_not_pressed ; consider_if_s_pressed &11a4 a9 ae LDA #&ae ; S &11a6 20 64 32 JSR &3264 ; check_for_keypress &11a9 10 24 BPL &11cf ; s_not_pressed ; wait_for_s_to_be_released &11ab 20 0a 2d JSR &2d0a ; wait_for_vsync &11ae a9 ae LDA #&ae ; S &11b0 20 64 32 JSR &3264 ; check_for_keypress &11b3 30 f6 BMI &11ab ; wait_for_s_to_be_released &11b5 e0 04 CPX #&04 ; MATCH_TYPE_TRICK &11b7 d0 10 BNE &11c9 ; swap_colours_in_game ; store_trick_layout # If S is pressed during a trick, &11b9 a9 02 LDA #&02 # Tricks are stored in layouts two onwards &11bb 18 CLC &11bc 65 a2 ADC &a2 ; trick_number &11be 20 58 1a JSR &1a58 ; store_balls_in_layout # store ball layout &11c1 a9 02 LDA #&02 ; SOUND_POT &11c3 20 20 30 JSR &3020 ; start_sound # Play sound to indicate trick layout was stored &11c6 4c cf 11 JMP &11cf ; s_not_pressed ; swap_colours_in_game # If S is pressed during a game, &11c9 a5 71 LDA &71 ; first_player_colour &11cb 49 01 EOR #&01 ; BALL_TYPE_DITHERED ^ BALL_SOLID &11cd 85 71 STA &71 ; first_player_colour # Swap colours ; s_not_pressed &11cf 24 52 BIT &52 ; previous_return_or_fire_pressed &11d1 10 03 BPL &11d6 ; not_pressing_return_or_file &11d3 4c 51 12 JMP &1251 ; pressing_return_or_fire ; not_pressing_return_or_file # If RETURN or fire isn't being pressed, &11d6 a2 00 LDX #&00 &11d8 24 7f BIT &7f ; left_pressed &11da 10 01 BPL &11dd ; left_not_pressed &11dc e8 INX # Rotate anticlockwise horizontally if LEFT pressed ; left_not_pressed &11dd 24 80 BIT &80 ; right_pressed &11df 10 01 BPL &11e2 ; right_not_pressed &11e1 ca DEX # Rotate clockwise horizontally if RIGHT pressed ; right_not_pressed &11e2 8a TXA &11e3 f0 16 BEQ &11fb ; reset_horizontal_rotation_speed &11e5 a5 3a LDA &3a ; horizontal_rotation_speed &11e7 f0 05 BEQ &11ee ; change_horizontal_rotation_speed &11e9 8a TXA &11ea 45 3a EOR &3a ; horizontal_rotation_speed &11ec 30 0d BMI &11fb ; reset_horizontal_rotation_speed ; change_horizontal_rotation_speed &11ee 8a TXA &11ef 18 CLC &11f0 65 3a ADC &3a ; horizontal_rotation_speed &11f2 c9 08 CMP #&08 &11f4 10 09 BPL &11ff ; set_horizontal_rotation_speed &11f6 c9 f9 CMP #&f9 &11f8 30 05 BMI &11ff ; set_horizontal_rotation_speed &11fa 2c a9 00 BIT &00a9 ; reset_horizontal_rotation_speed #11fb LDA #&00 ; set_horizontal_rotation_speed &11fd 85 3a STA &3a ; horizontal_rotation_speed &11ff a5 3a LDA &3a ; horizontal_rotation_speed &1201 18 CLC &1202 65 2e ADC &2e ; player_viewpoint_horizontal_rotation &1204 c5 2e CMP &2e ; player_viewpoint_horizontal_rotation &1206 85 2e STA &2e ; player_viewpoint_horizontal_rotation &1208 f0 02 BEQ &120c ; horizontal_rotation_not_changed &120a c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint ; horizontal_rotation_not_changed &120c a2 00 LDX #&00 &120e 24 81 BIT &81 ; up_pressed &1210 10 01 BPL &1213 ; up_not_pressed &1212 e8 INX # Rotate anticlockwise vertically if UP pressed ; up_not_pressed &1213 24 82 BIT &82 ; down_pressed &1215 10 01 BPL &1218 ; down_not_pressed &1217 ca DEX # Rotate clockwise vertically if DOWN pressed ; down_not_pressed &1218 8a TXA &1219 f0 16 BEQ &1231 ; reset_vertical_rotation_speed &121b a5 3b LDA &3b ; vertical_rotation_speed &121d f0 05 BEQ &1224 ; change_vertical_rotation_speed &121f 8a TXA &1220 45 3b EOR &3b ; vertical_rotation_speed &1222 30 0d BMI &1231 ; reset_vertical_rotation_speed ; change_vertical_rotation_speed &1224 8a TXA &1225 18 CLC &1226 65 3b ADC &3b ; vertical_rotation_speed &1228 c9 07 CMP #&07 &122a 10 09 BPL &1235 ; set_vertical_rotation_speed &122c c9 fa CMP #&fa &122e 30 05 BMI &1235 ; set_vertical_rotation_speed &1230 2c a9 00 BIT &00a9 ; reset_vertical_rotation_speed #1231 LDA #&00 ; set_vertical_rotation_speed &1233 85 3b STA &3b ; vertical_rotation_speed &1235 a5 2f LDA &2f ; player_viewpoint_vertical_rotation &1237 18 CLC &1238 65 3b ADC &3b ; vertical_rotation_speed &123a c9 22 CMP #&22 &123c 90 02 BCC &1240 ; skip_ceiling &123e a9 21 LDA #&21 ; skip_ceiling &1240 c9 08 CMP #&08 &1242 10 02 BPL &1246 ; skip_floor &1244 a9 08 LDA #&08 ; skip_floor &1246 c5 2f CMP &2f ; player_viewpoint_vertical_rotation &1248 85 2f STA &2f ; player_viewpoint_vertical_rotation &124a f0 02 BEQ &124e ; vertical_rotation_not_changed &124c c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint ; vertical_rotation_not_changed &124e 4c e7 12 JMP &12e7 ; use_viewpoint ; pressing_return_or_fire # If RETURN or fire is being pressed, &1251 24 50 BIT &50 ; placing_ball # Negative if placing ball &1253 30 2f BMI &1284 ; adjust_ball_position &1255 24 4c BIT &4c ; trick_state # Negative if playing trick &1257 30 28 BMI &1281 ; to_use_viewpoint ; adjust_strike_point_and_power # If not placing ball, &1259 a6 30 LDX &30 ; player_strike_power &125b 24 81 BIT &81 ; up_pressed &125d 10 01 BPL &1260 ; up_not_pressed &125f e8 INX # Increase strike power if UP pressed ; up_not_pressed &1260 24 82 BIT &82 ; down_pressed &1262 10 01 BPL &1265 ; down_not_pressed &1264 ca DEX # Decrease strike power if DOWN pressed ; down_not_pressed &1265 e0 01 CPX #&01 &1267 30 06 BMI &126f ; skip_setting_strike_power &1269 e0 10 CPX #&10 &126b 10 02 BPL &126f ; skip_setting_strike_power &126d 86 30 STX &30 ; player_strike_power ; skip_setting_strike_power &126f a6 31 LDX &31 ; player_strike_point &1271 24 7f BIT &7f ; left_pressed &1273 10 01 BPL &1276 ; left_not_pressed &1275 ca DEX # Move strike point left if LEFT pressed ; left_not_pressed &1276 24 80 BIT &80 ; right_pressed &1278 10 01 BPL &127b ; right_not_pressed &127a e8 INX # Move strike point right if RIGHT pressed ; right_not_pressed &127b e0 15 CPX #&15 &127d b0 02 BCS &1281 ; to_use_viewpoint &127f 86 31 STX &31 ; player_strike_point ; to_use_viewpoint &1281 4c e7 12 JMP &12e7 ; use_viewpoint ; adjust_ball_position # If placing ball, &1284 a5 7f LDA &7f ; left_pressed &1286 45 80 EOR &80 ; right_pressed &1288 30 06 BMI &1290 ; single_direction_pressed &128a a5 81 LDA &81 ; up_pressed &128c 45 82 EOR &82 ; down_pressed &128e 10 16 BPL &12a6 ; to_use_viewpoint ; single_direction_pressed &1290 a5 87 LDA &87 ; match_type &1292 c9 04 CMP #&04 ; MATCH_TYPE_TRICK &1294 f0 13 BEQ &12a9 ; adjust_ball_position_in_trick ; adjust_ball_position_in_game &1296 a2 00 LDX #&00 ; BALL_CUE &1298 20 1b 2c JSR &2c1b ; apply_rotated_change_of_position_to_ball &129b 20 8d 2c JSR &2c8d ; check_if_ball_is_in_D # Returns carry clear if ball is in "D" &129e b0 06 BCS &12a6 ; to_use_viewpoint &12a0 20 76 2c JSR &2c76 ; apply_changed_position_to_cue_ball &12a3 ce a2 0f DEC &0fa2 ; balls_needs_recalculating # Set to negative to indicate cue ball needs recalculating ; to_use_viewpoint &12a6 4c e7 12 JMP &12e7 ; use_viewpoint ; adjust_ball_position_in_trick &12a9 a6 a9 LDX &a9 ; focus_ball &12ab 20 1b 2c JSR &2c1b ; apply_rotated_change_of_position_to_ball &12ae a6 a9 LDX &a9 ; focus_ball &12b0 a5 11 LDA &11 ; x &12b2 10 05 BPL &12b9 ; skip_x_inversion &12b4 49 ff EOR #&ff &12b6 38 SEC &12b7 69 00 ADC #&00 ; skip_x_inversion &12b9 c9 20 CMP #&20 &12bb b0 0d BCS &12ca ; skip_x_movement &12bd a5 10 LDA &10 ; x_fraction &12bf 9d 52 0f STA &0f52,X ; balls_table_x_fraction &12c2 a5 11 LDA &11 ; x &12c4 9d 22 0f STA &0f22,X ; balls_table_x &12c7 de a2 0f DEC &0fa2,X ; balls_needs_recalculating # Set to negative to indicate ball needs recalculating ; skip_x_movement &12ca a5 13 LDA &13 ; y &12cc 10 05 BPL &12d3 ; skip_y_inversion &12ce 49 ff EOR #&ff &12d0 38 SEC &12d1 69 00 ADC #&00 ; skip_y_inversion &12d3 c9 40 CMP #&40 &12d5 b0 0d BCS &12e4 ; to_use_viewpoint &12d7 a5 12 LDA &12 ; y_fraction &12d9 9d 62 0f STA &0f62,X ; balls_table_y_fraction &12dc a5 13 LDA &13 ; y &12de 9d 42 0f STA &0f42,X ; balls_table_y &12e1 de a2 0f DEC &0fa2,X ; balls_needs_recalculating ; to_use_viewpoint &12e4 4c e7 12 JMP &12e7 ; use_viewpoint # Unnecessary code ; use_viewpoint &12e7 a5 87 LDA &87 ; match_type &12e9 c9 04 CMP #&04 ; MATCH_TYPE_TRICK &12eb d0 0d BNE &12fa ; skip_setting_trick_viewpoint # If playing a trick, &12ed 24 50 BIT &50 ; placing_ball # Negative if placing ball &12ef 30 09 BMI &12fa ; skip_setting_trick_viewpoint &12f1 a2 03 LDX #&03 ; set_trick_viewpoint_loop # Store the shot for use when editing the trick &12f3 b5 2e LDA &2e,X ; viewpoint # or when playing the trick next &12f5 95 36 STA &36,X ; trick_viewpoint &12f7 ca DEX &12f8 10 f9 BPL &12f3 ; set_trick_viewpoint_loop ; skip_setting_trick_viewpoint &12fa 24 4c BIT &4c ; trick_state # Negative if playing trick &12fc 30 60 BMI &135e ; update_balls_loop &12fe 24 83 BIT &83 ; return_or_fire_double_press # Negative if RETURN or fire has been double pressed &1300 10 34 BPL &1336 ; to_update_screen_and_consider_end_of_frame &1302 a9 01 LDA #&01 &1304 85 53 STA &53 ; return_or_fire_state # Set to one to indicate not recently pressed &1306 a5 2e LDA &2e ; player_viewpoint_horizontal_rotation # Use player's viewpoint &1308 85 32 STA &32 ; viewpoint_horizontal_rotation &130a a5 2f LDA &2f ; player_viewpoint_vertical_rotation &130c 85 33 STA &33 ; viewpoint_vertical_rotation &130e a5 30 LDA &30 ; player_strike_power # and strike power and point when striking ball &1310 85 34 STA &34 ; strike_power &1312 a5 31 LDA &31 ; player_strike_point &1314 85 35 STA &35 ; strike_point &1316 24 86 BIT &86 ; only_potential_move # Negative if move is potential &1318 30 1c BMI &1336 ; to_update_screen_and_consider_end_of_frame &131a 24 50 BIT &50 ; placing_ball # Negative if placing ball &131c 10 1b BPL &1339 ; start_move ; is_placing_ball &131e a5 87 LDA &87 ; match_type &1320 c9 04 CMP #&04 ; MATCH_TYPE_TRICK &1322 d0 0c BNE &1330 ; is_placing_ball_in_game &1324 a5 a9 LDA &a9 ; focus_ball &1326 69 00 ADC #&00 # Carry set, so add one &1328 29 0f AND #&0f # i.e. move to next ball &132a 85 a9 STA &a9 ; focus_ball &132c c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint &132e 30 06 BMI &1336 ; to_update_screen_and_consider_end_of_frame # Always branches ; is_placing_ball_in_game &1330 a9 00 LDA #&00 &1332 85 50 STA &50 ; placing_ball # Set to positive to indicate not placing ball &1334 c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint ; to_update_screen_and_consider_end_of_frame &1336 4c 43 14 JMP &1443 ; update_screen_and_consider_end_of_frame ; start_move &1339 a9 00 LDA #&00 &133b 85 4b STA &4b ; unused # Unused variable &133d 24 7b BIT &7b ; player_has_free_ball # Negative if player has free ball &133f 30 02 BMI &1343 ; skip_forbidding_swapping_colours &1341 85 51 STA &51 ; permit_swapping_colours # Set to zero to indicate colours can't be swapped ; skip_forbidding_swapping_colours &1343 20 ec 14 JSR &14ec ; set_current_player_ball_colour &1346 20 06 15 JSR &1506 ; strike_cue_ball &1349 c6 72 DEC &72 ; cue_balls_remaining &134b 20 78 1c JSR &1c78 ; update_screen &134e 20 78 1c JSR &1c78 ; update_screen &1351 a5 28 LDA &28 ; vsync_counter &1353 85 6b STA &6b ; vsync_counter_for_update &1355 a9 01 LDA #&01 &1357 85 4e STA &4e ; dampening_cooldown &1359 a9 00 LDA #&00 ; SOUND_BOUNCE &135b 20 11 2d JSR &2d11 ; cue_sound_for_playing # Play sound for striking cue ball ; update_balls_loop &135e 20 55 16 JSR &1655 ; update_moving_balls &1361 a5 4d LDA &4d ; number_of_balls_in_motion &1363 f0 0e BEQ &1373 ; no_balls_moving &1365 a5 6b LDA &6b ; vsync_counter_for_update &1367 18 CLC &1368 69 02 ADC #&02 &136a 85 6b STA &6b ; vsync_counter_for_update &136c c5 28 CMP &28 ; vsync_counter # Incremented every v-sync &136e 30 ee BMI &135e ; update_balls_loop # Update balls until vsync_counter_for_update >= vsync_counter &1370 4c 43 14 JMP &1443 ; update_screen_and_consider_end_of_frame ; no_balls_moving &1373 85 4c STA &4c ; trick_state # Negative if playing trick &1375 85 52 STA &52 ; previous_return_or_fire_pressed &1377 85 54 STA &54 ; return_or_fire_pressed # Set to zero to indicate not pressed &1379 a5 87 LDA &87 ; match_type &137b c9 04 CMP #&04 ; MATCH_TYPE_TRICK &137d d0 1f BNE &139e ; no_balls_moving_in_game ; no_balls_moving_in_trick &137f 20 78 1c JSR &1c78 ; update_screen &1382 a2 dc LDX #&dc ; at ( 5, 18), eor &0f, string &62 ("PRESS SPACE TO CONTINUE ") &1384 20 ff 27 JSR &27ff ; plot_string_to_visible_buffer &1387 24 7a BIT &7a ; foul_shot # Negative if foul shot &1389 30 0d BMI &1398 ; trick_not_completed &138b a5 73 LDA &73 ; solid_balls_remaining &138d f0 09 BEQ &1398 ; trick_not_completed &138f c5 75 CMP &75 ; solid_balls_potted &1391 d0 05 BNE &1398 ; trick_not_completed &1393 a2 e0 LDX #&e0 ; at (12, 12), eor &0f, string &64 ("WELL DONE ") &1395 20 ff 27 JSR &27ff ; plot_string_to_visible_buffer ; trick_not_completed &1398 20 f5 2c JSR &2cf5 ; wait_for_space &139b 4c 73 10 JMP &1073 ; start_frame_without_resetting_viewpoint ; no_balls_moving_in_game &139e ae e2 0e LDX &0ee2 ; balls_state # Positive if cue ball present &13a1 10 05 BPL &13a8 ; not_placing_cue_ball &13a3 86 50 STX &50 ; placing_ball # Set to negative to indicate placing ball &13a5 e8 INX ; 0 = BALL_CUE &13a6 86 a9 STX &a9 ; focus_ball # Set to zero to indicate cue ball is focused ; not_placing_cue_ball &13a8 a9 02 LDA #&02 ; BALL_TYPE_CUE &13aa 8d e2 0e STA &0ee2 ; balls_state # Set to positive to indicate cue ball is present &13ad 24 50 BIT &50 ; placing_ball # Negative if placing ball &13af 30 04 BMI &13b5 ; force_screen_update &13b1 24 70 BIT &70 ; sideways_ram_has_table_snapshot # Negative if sideways RAM has snapshot of table &13b3 10 05 BPL &13ba ; skip_additional_screen_update ; force_screen_update &13b5 c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint &13b7 20 78 1c JSR &1c78 ; update_screen ; skip_additional_screen_update &13ba 20 78 1c JSR &1c78 ; update_screen &13bd 38 SEC &13be a5 73 LDA &73 ; solid_balls_remaining &13c0 e5 75 SBC &75 ; solid_balls_potted &13c2 85 73 STA &73 ; solid_balls_remaining &13c4 38 SEC &13c5 a5 74 LDA &74 ; dithered_balls_remaining &13c7 e5 76 SBC &76 ; dithered_balls_potted &13c9 85 74 STA &74 ; dithered_balls_remaining &13cb a9 00 LDA #&00 &13cd 85 7b STA &7b ; player_has_free_ball # Set to zero to indicate no free ball &13cf a9 0a LDA #&0a ; STRIKE_MIDDLE &13d1 85 31 STA &31 ; player_strike_point # Reset player's strike point and power &13d3 a9 08 LDA #&08 &13d5 85 30 STA &30 ; player_strike_power &13d7 24 71 BIT &71 ; first_player_colour # Positive if colours have been decided &13d9 10 24 BPL &13ff ; skip_setting_first_player_colour # If colours have not been decided, &13db a5 75 LDA &75 ; solid_balls_potted &13dd 05 76 ORA &76 ; dithered_balls_potted &13df f0 1e BEQ &13ff ; skip_setting_first_player_colour # and both colours have been potted, &13e1 24 7a BIT &7a ; foul_shot # Negative if foul shot &13e3 30 08 BMI &13ed ; set_permit_swapping_colours # and the shot wasn't foul, &13e5 a5 75 LDA &75 ; solid_balls_potted &13e7 f0 08 BEQ &13f1 ; skip_permitting_swapping_colours # Never branches; A is never zero here &13e9 a5 76 LDA &76 ; dithered_balls_potted &13eb f0 04 BEQ &13f1 ; skip_permitting_swapping_colours # Never branches; A is never zero here ; set_permit_swapping_colours &13ed a9 ff LDA #&ff &13ef 85 51 STA &51 ; permit_swapping_colours # Set to negative to permit colours to be swapped ; skip_permitting_swapping_colours &13f1 a5 73 LDA &73 ; solid_balls_remaining &13f3 c5 74 CMP &74 ; dithered_balls_remaining &13f5 a9 00 LDA #&00 &13f7 2a ROL A # Carry set if more solid than dithered balls remaining &13f8 45 78 EOR &78 ; active_player &13fa 85 71 STA &71 ; first_player_colour # Set to zero for solid, one for dithered &13fc 4c 17 14 JMP &1417 ; give_player_cue_ball ; skip_setting_first_player_colour &13ff a5 7c LDA &7c ; first_ball_hit # Negative if no ball hit &1401 05 7a ORA &7a ; foul_shot # Negative if foul shot &1403 30 1a BMI &141f ; give_other_player_free_ball &1405 24 71 BIT &71 ; first_player_colour # Negative if colours haven't been decided &1407 30 12 BMI &141b ; skip_setting_cue_balls_remaining &1409 24 79 BIT &79 ; black_ball_potted # Negative if black potted &140b 30 0a BMI &1417 ; give_player_cue_ball &140d a6 7e LDX &7e ; current_player_ball_colour &140f e0 02 CPX #&02 &1411 b0 08 BCS &141b ; skip_setting_cue_balls_remaining # Branch if black or no colour &1413 b5 75 LDA &75,X ; solid_balls_potted &1415 f0 04 BEQ &141b ; skip_setting_cue_balls_remaining # Branch if player has no coloured balls remaining ; give_player_cue_ball &1417 a9 01 LDA #&01 &1419 85 72 STA &72 ; cue_balls_remaining ; skip_setting_cue_balls_remaining &141b 24 7a BIT &7a ; foul_shot # Negative if foul shot &141d 10 0a BPL &1429 ; skip_giving_other_player_free_ball ; give_other_player_free_ball &141f a9 00 LDA #&00 &1421 85 7a STA &7a ; foul_shot # Set to zero to indicate shot wasn't foul &1423 c6 7b DEC &7b ; player_has_free_ball # Set to negative to indicate player has free ball &1425 a9 02 LDA #&02 # Set to two to indicate player has free cue ball &1427 d0 06 BNE &142f ; set_cue_balls_remaining_and_swap_player # Always branches ; skip_giving_other_player_free_ball &1429 a5 72 LDA &72 ; cue_balls_remaining &142b d0 16 BNE &1443 ; update_screen_and_consider_end_of_frame &142d a9 01 LDA #&01 ; set_cue_balls_remaining_and_swap_player &142f 85 72 STA &72 ; cue_balls_remaining &1431 a5 78 LDA &78 ; active_player &1433 49 01 EOR #&01 # Swap to other player &1435 85 78 STA &78 ; active_player &1437 a5 72 LDA &72 ; cue_balls_remaining &1439 d0 08 BNE &1443 ; update_screen_and_consider_end_of_frame &143b a9 01 LDA #&01 &143d 85 72 STA &72 ; cue_balls_remaining &143f 45 78 EOR &78 ; active_player # Swap back to original player &1441 85 78 STA &78 ; active_player ; update_screen_and_consider_end_of_frame &1443 20 78 1c JSR &1c78 ; update_screen &1446 24 4c BIT &4c ; trick_state # Negative if playing trick &1448 30 07 BMI &1451 ; to_main_game_loop &144a 24 79 BIT &79 ; black_ball_potted # Negative if black potted &144c 10 03 BPL &1451 ; to_main_game_loop &144e 4c 6b 28 JMP &286b ; end_of_frame ; to_main_game_loop &1451 4c af 10 JMP &10af ; main_game_loop ; add_score_to_potential_move &1454 24 88 BIT &88 ; suppress_scoring # Negative if suppressing scoring &1456 30 13 BMI &146b ; leave &1458 24 8c BIT &8c ; computer_is_thinking # Positive if this is a real move, not a potential one &145a 10 0f BPL &146b ; leave &145c 18 CLC &145d 65 aa ADC &aa ; score # Add to score &145f c5 ab CMP &ab ; score_limit_for_ending_evaluation &1461 b0 09 BCS &146c ; end_evaluation_of_potential_move # If the score is now too high, end evaluation &1463 c9 40 CMP #&40 &1465 90 02 BCC &1469 ; skip_ceiling &1467 a9 3f LDA #&3f ; skip_ceiling &1469 85 aa STA &aa ; score ; leave &146b 60 RTS ; end_evaluation_of_potential_move &146c a6 ad LDX &ad ; stack_point_prior_to_evaluating_potential_computer_move &146e 9a TXS # Remove any intermediate calls from stack &146f 18 CLC &1470 4c 75 26 JMP &2675 ; set_score_for_potential_computer_move # Leave as though returning from evaluate_potential_computer_move ; initialise_balls &1473 a9 ff LDA #&ff &1475 85 a1 STA &a1 ; balls_not_broken # Set to negative to indicate balls not broken &1477 85 71 STA &71 ; first_player_colour # Set to negative to indicate colours haven't been decided &1479 a5 87 LDA &87 ; match_type &147b c9 04 CMP #&04 ; MATCH_TYPE_TRICK &147d f0 27 BEQ &14a6 ; initialise_balls_for_trick ; initialise_balls_for_game &147f a9 00 LDA #&00 ; BALL_CUE &1481 85 a9 STA &a9 ; focus_ball &1483 20 f6 19 JSR &19f6 ; get_balls_from_layout # Use initial table layout (layout zero) &1486 a2 0f LDX #&0f ; BALL_LAST ; randomise_ball_positions_loop # For each ball, &1488 20 0d 30 JSR &300d ; rnd &148b 29 0f AND #&0f &148d 5d 52 0f EOR &0f52,X ; balls_table_x_fraction # Add randomness to ball's x position &1490 9d 52 0f STA &0f52,X ; balls_table_x_fraction &1493 20 0d 30 JSR &300d ; rnd &1496 29 0f AND #&0f &1498 5d 62 0f EOR &0f62,X ; balls_table_y_fraction # Add randomness to ball's y position &149b 9d 62 0f STA &0f62,X ; balls_table_y_fraction &149e ca DEX &149f 10 e7 BPL &1488 ; randomise_ball_positions_loop &14a1 86 50 STX &50 ; placing_ball # Set to negative to indicate placing ball &14a3 4c 5b 2c JMP &2c5b ; add_randomness_to_cue_ball_position ; initialise_balls_for_trick &14a6 e6 71 INC &71 ; first_player_colour # Set to zero to use solid balls for tricks &14a8 24 50 BIT &50 ; placing_ball # Negative if placing ball &14aa 30 09 BMI &14b5 ; skip_using_trick_viewpoint &14ac a2 03 LDX #&03 ; use_trick_viewpoint_loop # Use last played shot as initial viewpoint for trick &14ae b5 36 LDA &36,X ; trick_viewpoint &14b0 95 2e STA &2e,X ; viewpoint &14b2 ca DEX &14b3 10 f9 BPL &14ae ; use_trick_viewpoint_loop ; skip_using_trick_viewpoint &14b5 a9 01 LDA #&01 # Carry is set, so add two &14b7 65 a2 ADC &a2 ; trick_number # Tricks are stored in layouts two onwards &14b9 4c f6 19 JMP &19f6 ; get_balls_from_layout ; clear_collisions_after_bounce_off_edge_of_table # X = ball that bounced off edge of table &14bc bc 92 0f LDY &0f92,X ; balls_collided_with # Negative if ball didn't collide with any others &14bf 30 15 BMI &14d6 ; skip_resetting_collided_with # Otherwise Y = collision partner &14c1 a9 ff LDA #&ff &14c3 9d 92 0f STA &0f92,X ; balls_collided_with # Clear collision for original ball &14c6 b9 92 0f LDA &0f92,Y ; balls_collided_with &14c9 30 0b BMI &14d6 ; skip_resetting_collided_with # Negative if partner has no collision &14cb 8a TXA &14cc d9 92 0f CMP &0f92,Y ; balls_collided_with &14cf d0 05 BNE &14d6 ; skip_resetting_collided_with # Is the partner's collision partner the original ball? &14d1 a9 ff LDA #&ff &14d3 99 92 0f STA &0f92,Y ; balls_collided_with # If so, clear collision for partner ; skip_resetting_collided_with &14d6 8a TXA &14d7 d0 09 BNE &14e2 ; leave # Is the original ball the cue ball? &14d9 a5 7c LDA &7c ; first_ball_hit # Positive if a ball has already been hit &14db 10 06 BPL &14e3 ; ball_already_hit &14dd a9 05 LDA #&05 # Move scores five for bouncing off edge before hit &14df 4c 54 14 JMP &1454 ; add_score_to_potential_move ; leave &14e2 60 RTS ; ball_already_hit &14e3 e4 7c CPX &7c ; first_ball_hit &14e5 d0 fb BNE &14e2 ; leave # X is always zero here, so never branches &14e7 a9 03 LDA #&03 # Move scores three for bouncing off edge after hit &14e9 4c 54 14 JMP &1454 ; add_score_to_potential_move ; set_current_player_ball_colour &14ec a5 71 LDA &71 ; first_player_colour # Negative if colours haven't been decided &14ee 30 13 BMI &1503 ; leave_with_colour # Leave with negative if player can pot either colour &14f0 45 78 EOR &78 ; active_player # A = current player's colour &14f2 4a LSR A # Carry set if current player has dithered balls &14f3 a9 03 LDA #&03 ; BALL_TYPE_BLACK &14f5 a6 73 LDX &73 ; solid_balls_remaining &14f7 90 02 BCC &14fb ; consider_balls_remaining &14f9 a6 74 LDX &74 ; dithered_balls_remaining ; consider_balls_remaining &14fb f0 06 BEQ &1503 ; leave_with_colour # Leave with black if player has only black remaining &14fd a9 00 LDA #&00 ; BALL_TYPE_SOLID # Otherwise leave with player's colour &14ff 90 02 BCC &1503 ; leave_with_colour &1501 a9 01 LDA #&01 ; BALL_TYPE_DITHERED ; leave_with_colour &1503 85 7e STA &7e ; current_player_ball_colour &1505 60 RTS ; strike_cue_ball &1506 a9 00 LDA #&00 &1508 85 7a STA &7a ; foul_shot # Set to zero to indicate shot wasn't foul &150a 85 75 STA &75 ; solid_balls_potted # Set to zero to indicate no solid balls potted &150c 85 76 STA &76 ; dithered_balls_potted # Set to zero to indicate no dithered balls potted &150e 85 88 STA &88 ; suppress_scoring # Set to zero to permit scoring &1510 85 79 STA &79 ; black_ball_potted # Set to zero to indicate black not potted &1512 85 aa STA &aa ; score &1514 a9 ff LDA #&ff &1516 85 4c STA &4c ; trick_state # Set to negative to indicate playing trick, if trick &1518 85 7c STA &7c ; first_ball_hit # Set to negative to indicate no ball hit &151a 85 7d STA &7d ; second_ball_hit # Set to negative to indicate no ball hit &151c a2 0f LDX #&0f ; reset_balls_collided_with_and_velocities_loop &151e a9 ff LDA #&ff &1520 9d 92 0f STA &0f92,X ; balls_collided_with # Set to negative to indicate no collision occurred &1523 a9 00 LDA #&00 &1525 9d 72 0f STA &0f72,X ; balls_x_velocity &1528 9d 82 0f STA &0f82,X ; balls_y_velocity &152b ca DEX &152c 10 f0 BPL &151e ; reset_balls_collided_with_and_velocities_loop &152e a5 34 LDA &34 ; strike_power # power = (strike_power * 8) | 2 &1530 0a ASL A &1531 0a ASL A &1532 0a ASL A &1533 09 02 ORA #&02 &1535 a8 TAY # Y = power high &1536 a2 00 LDX #&00 # X = power low &1538 a9 40 LDA #&40 ; 90 degrees &153a 20 79 15 JSR &1579 ; split_strike_into_x_and_y_components &153d a6 11 LDX &11 ; x &153f a4 13 LDY &13 ; y &1541 8e 72 0f STX &0f72 ; balls_x_velocity # x velocity = power * cos(-ha + 90 degrees) &1544 8c 82 0f STY &0f82 ; balls_y_velocity # y velocity = power * sin(-ha + 90 degrees) &1547 a6 33 LDX &33 ; viewpoint_vertical_rotation &1549 e0 0f CPX #&0f # Carry set if strike point is below centre &154b bc 58 36 LDY &3658,X ; vertical_strike_point_to_power_table # Y = vp high &154e a2 00 LDX #&00 # X = vp low &1550 a9 40 LDA #&40 ; 90 degrees &1552 90 02 BCC &1556 ; skip_va_inversion &1554 49 80 EOR #&80 ; 180 degrees ; skip_va_inversion # x += vp * cos(-ha + 90 degrees) &1556 20 79 15 JSR &1579 ; split_strike_into_x_and_y_components # y += vp * sin(-ha + 90 degrees) &1559 a6 35 LDX &35 ; strike_point &155b e0 0a CPX #&0a : STRIKE_MIDDLE # Carry set if strike point is right of centre &155d bc 81 36 LDY &3681,X ; horizontal_strike_point_to_power_table # Y = hp high &1560 a2 00 LDX #&00 # X = hp low &1562 a9 00 LDA #&00 ; 0 degrees &1564 b0 02 BCS &1568 ; skip_ha_inversion &1566 49 80 EOR #&80 ; 180 degrees ; skip_ha_inversion &1568 38 SEC &1569 e5 32 SBC &32 ; viewpoint_horizontal_rotation # x += hp * cos(-2ha + 90 degrees) &156b 20 98 23 JSR &2398 ; add_rotated_coordinate # y += hp * sin(-2ha + 90 degrees) &156e a6 11 LDX &11 ; x &1570 a4 13 LDY &13 ; y &1572 8e d2 0f STX &0fd2 ; balls_x_acceleration # x acceleration = x &1575 8c e2 0f STY &0fe2 ; balls_y_acceleration # y acceleration = y &1578 60 RTS ; split_strike_into_x_and_y_components &1579 38 SEC &157a e5 32 SBC &32 ; viewpoint_horizontal_rotation &157c 85 0c STA &0c ; angle &157e a9 00 LDA #&00 &1580 85 10 STA &10 ; x_fraction &1582 85 11 STA &11 ; x &1584 85 12 STA &12 ; y_fraction &1586 85 13 STA &13 ; y &1588 a5 0c LDA &0c ; angle &158a 4c 98 23 JMP &2398 ; add_rotated_coordinate ; check_for_side_pockets &158d bd 42 0f LDA &0f42,X ; balls_table_y &1590 10 05 BPL &1597 ; skip_inversion &1592 49 ff EOR #&ff &1594 38 SEC &1595 69 00 ADC #&00 ; skip_inversion &1597 c9 05 CMP #&05 &1599 90 35 BCC &15d0 ; pot_ball # Absolute ball y must be < 5 to enter pocket ; bounce_off_edge_of_table &159b a9 00 LDA #&00 ; SOUND_BOUNCE &159d 85 af STA &af ; moving_ball_sound &159f 20 b6 17 JSR &17b6 ; apply_and_clear_acceleration &15a2 20 bc 14 JSR &14bc ; clear_collisions_after_bounce_off_edge_of_table &15a5 18 CLC # Leave with carry clear to indicate ball not potted &15a6 60 RTS ; check_for_top_or_bottom_pockets &15a7 bd 42 0f LDA &0f42,X ; balls_table_y &15aa 10 05 BPL &15b1 ; skip_inversion_y &15ac 49 ff EOR #&ff &15ae 38 SEC &15af 69 00 ADC #&00 ; skip_inversion_y &15b1 38 SEC &15b2 e9 3b SBC #&3b &15b4 90 18 BCC &15ce ; leave_with_carry_clear # Absolute ball y must >= &3b to enter pocket &15b6 85 0c STA &0c ; y_difference &15b8 bd 22 0f LDA &0f22,X ; balls_table_x &15bb 10 05 BPL &15c2 ; skip_inversion_x &15bd 49 ff EOR #&ff &15bf 38 SEC &15c0 69 00 ADC #&00 ; skip_inversion_x &15c2 38 SEC &15c3 e9 1b SBC #&1b &15c5 90 07 BCC &15ce ; leave_with_carry_clear # Absolute ball x must >= &1b to enter pocket &15c7 18 CLC &15c8 65 0c ADC &0c ; y_difference &15ca c9 04 CMP #&04 # If (abs(x) - &1b) + (abs(y) - &3b) >= 4, &15cc b0 02 BCS &15d0 ; pot_ball # ball entered one of top or bottom pockets ; leave_with_carry_clear &15ce 18 CLC # Leave with carry clear to indicate ball not potted &15cf 60 RTS ; pot_ball &15d0 bd e2 0e LDA &0ee2,X ; balls_state # Negative if ball not present, otherwise colour &15d3 c9 00 CMP #&00 ; BALL_TYPE_SOLID &15d5 d0 02 BNE &15d9 ; not_solid &15d7 e6 75 INC &75 ; solid_balls_potted ; not_solid &15d9 c9 01 CMP #&01 ; BALL_TYPE_DITHERED &15db d0 02 BNE &15df ; not_dithered &15dd e6 76 INC &76 ; dithered_balls_potted ; not_dithered &15df c9 02 CMP #&02 ; BALL_TYPE_CUE &15e1 f0 34 BEQ &1617 ; pot_cue ; not_cue_ball &15e3 e4 7c CPX &7c ; first_ball_hit # Move scores zero for potting first ball hit &15e5 f0 0e BEQ &15f5 ; skip_scoring &15e7 a9 02 LDA #&02 # Move scores two for potting second ball hit &15e9 e4 7d CPX &7d ; second_ball_hit &15eb f0 02 BEQ &15ef ; add_score &15ed a9 04 LDA #&04 # Move scores four for potting any other ball ; add_score &15ef 20 54 14 JSR &1454 ; add_score_to_potential_move &15f2 bd e2 0e LDA &0ee2,X ; balls_state # Negative if ball not present, otherwise colour ; skip_scoring &15f5 24 71 BIT &71 ; first_player_colour # Negative if colours haven't been decided &15f7 30 04 BMI &15fd ; set_suppress_scoring &15f9 24 7b BIT &7b ; player_has_free_ball # Negative if player has free ball &15fb 30 02 BMI &15ff ; skip_suppressing_scoring ; set_suppress_scoring &15fd c6 88 DEC &88 ; suppress_scoring # Set to negative to suppress scoring ; skip_suppressing_scoring &15ff 24 7b BIT &7b ; player_has_free_ball # Negative if player has free ball &1601 30 0a BMI &160d ; skip_checking_colour &1603 24 71 BIT &71 ; first_player_colour # Negative if colours haven't been decided &1605 30 06 BMI &160d ; skip_checking_colour &1607 c5 7e CMP &7e ; current_player_ball_colour # Otherwise, is the potted ball the player's colour? &1609 d0 20 BNE &162b ; foul_pot # Foul shot if player potted the wrong colour &160b f0 29 BEQ &1636 ; valid_pot # Always branches ; skip_checking_colour &160d c9 03 CMP #&03 ; BALL_TYPE_BLACK &160f d0 25 BNE &1636 ; valid_pot &1611 c5 7e CMP &7e ; current_player_ball_colour # Is the player ready to pot the black ball? &1613 f0 21 BEQ &1636 ; valid_pot &1615 d0 14 BNE &162b ; foul_pot # If not, foul shot; always branches ; pot_cue_ball &1617 a9 00 LDA #&00 ; BALL_CUE &1619 20 92 1a JSR &1a92 ; get_ball_layout_address &161c a0 02 LDY #&02 &161e a2 00 LDX #&00 &1620 20 1c 1a JSR &1a1c ; get_ball_from_layout # Restore cue ball to initial position &1623 20 5b 2c JSR &2c5b ; add_randomness_to_cue_ball_position &1626 a9 ff LDA #&ff &1628 8d e2 0e STA &0ee2 ; balls_state # Set to negative to indicate cue ball not present ; foul_pot &162b a9 ff LDA #&ff &162d 85 7a STA &7a ; foul_shot # Set to negative to indicate foul shot (foul pot) &162f 24 86 BIT &86 ; only_potential_move # Positive if move is real &1631 10 03 BPL &1636 ; valid_pot &1633 68 PLA # If this was only a potential move, &1634 68 PLA # leave update_moving_balls on return &1635 60 RTS # i.e. stop evaluation immediately after foul pot ; valid_pot &1636 bd e2 0e LDA &0ee2,X ; balls_state # Negative if ball not present, otherwise colour &1639 c9 03 CMP #&03 ; BALL_BLACK &163b d0 0c BNE &1649 ; set_ball_as_not_present_and_play_sound &163d a9 ff LDA #&ff &163f 85 79 STA &79 ; black_ball_potted # Set to negative to indicate black was potted &1641 a4 7e LDY &7e ; current_player_ball_colour &1643 c0 03 CPY #&03 ; BALL_TYPE_BLACK &1645 f0 02 BEQ &1649 ; set_ball_as_not_present_and_play_sound &1647 85 7a STA &7a ; foul_shot # Set to negative to indicate foul shot (black potted) ; set_ball_as_not_present_and_play_sound &1649 a9 ff LDA #&ff &164b 9d e2 0e STA &0ee2,X ; balls_state # Set to negative to indicate ball not present &164e a9 02 LDA #&02 ; SOUND_POT &1650 20 11 2d JSR &2d11 ; cue_sound_for_playing # Play sound for potting ball &1653 38 SEC # Leave with carry set to indicate ball was potted &1654 60 RTS ; update_moving_balls &1655 a2 0f LDX #&0f &1657 a9 00 LDA #&00 &1659 85 4d STA &4d ; number_of_balls_in_motion &165b c6 4e DEC &4e ; dampening_cooldown &165d 10 04 BPL &1663 ; update_moving_balls_loop &165f a9 0e LDA #&0e &1661 85 4e STA &4e ; dampening_cooldown ; update_moving_balls_loop &1663 bd e2 0e LDA &0ee2,X ; balls_state # Negative if ball not present, otherwise colour &1666 10 03 BPL &166b ; update_moving_ball ; to_consider_next_moving_ball &1668 4c a2 17 JMP &17a2 ; consider_next_moving_ball ; update_moving_ball &166b bd 72 0f LDA &0f72,X ; balls_x_velocity &166e 1d 82 0f ORA &0f82,X ; balls_y_velocity &1671 f0 f5 BEQ &1668 ; to_consider_next_moving_ball # Consider next ball if ball isn't moving &1673 e6 4d INC &4d ; number_of_balls_in_motion &1675 a9 ff LDA #&ff &1677 9d a2 0f STA &0fa2,X ; balls_needs_recalculating # Set to negative to indicate ball needs recalculating &167a 85 af STA &af ; moving_ball_sound # Set to negative to indicate no sound ; apply_velocities_to_ball # &167c - &16aa is replaced in sideways RAM version ; apply_x_velocity_to_ball &167c bd 72 0f LDA &0f72,X ; balls_x_velocity # Multiply velocity by eight &167f 0a ASL A # Get top nibble &1680 2a ROL A &1681 2a ROL A &1682 2a ROL A &1683 29 07 AND #&07 # .421.... -> .....421 &1685 c9 04 CMP #&04 # &40 of velocity sets sign &1687 90 02 BCC &168b ; not_negative_x &1689 09 f8 ORA #&f8 ; not_negative_x &168b a8 TAY &168c bd 72 0f LDA &0f72,X ; balls_x_velocity # ...18421 -> 18421... &168f 0a ASL A &1690 0a ASL A &1691 0a ASL A &1692 18 CLC &1693 7d 52 0f ADC &0f52,X ; balls_table_x_fraction # Apply x velocity to ball &1696 9d 52 0f STA &0f52,X ; balls_table_x_fraction &1699 98 TYA &169a 7d 22 0f ADC &0f22,X ; balls_table_x &169d 9d 22 0f STA &0f22,X ; balls_table_x ; apply_y_velocity_to_ball &16a0 bd 82 0f LDA &0f82,X ; balls_y_velocity # Multiply velocity by eight &16a3 0a ASL A # Get top nibble &16a4 2a ROL A &16a5 2a ROL A &16a6 2a ROL A &16a7 29 07 AND #&07 # .421.... -> .....421 &16a9 c9 04 CMP #&04 # &40 of velocity sets sign &16ab 90 02 BCC &16af ; not_negative_y &16ad 09 f8 ORA #&f8 ; not_negative_y &16af a8 TAY &16b0 bd 82 0f LDA &0f82,X ; balls_y_velocity # ...18421 -> 18421... &16b3 0a ASL A &16b4 0a ASL A &16b5 0a ASL A &16b6 18 CLC &16b7 7d 62 0f ADC &0f62,X ; balls_table_y_fraction # Apply y velocity to ball &16ba 9d 62 0f STA &0f62,X ; balls_table_y_fraction &16bd 98 TYA &16be 7d 42 0f ADC &0f42,X ; balls_table_y &16c1 9d 42 0f STA &0f42,X ; balls_table_y ; check_for_bounce_off_right_table_edge &16c4 bd 22 0f LDA &0f22,X ; balls_table_x &16c7 30 1f BMI &16e8 ; check_for_bounce_off_left_table_edge &16c9 c9 20 CMP #&20 &16cb 90 1b BCC &16e8 ; check_for_bounce_off_left_table_edge # Has the ball hit the right edge of the table? &16cd a9 00 LDA #&00 &16cf fd 72 0f SBC &0f72,X ; balls_x_velocity # Invert x velocity &16d2 a8 TAY &16d3 b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen x velocity &16d6 9d 72 0f STA &0f72,X ; balls_x_velocity &16d9 20 8d 15 JSR &158d ; check_for_side_pockets # Returns carry set if ball entered pocket &16dc b0 22 BCS &1700 ; to_consider_next_moving_ball_if_potted &16de a9 1f LDA #&1f # Otherwise, align ball with right edge &16e0 9d 22 0f STA &0f22,X ; balls_table_x &16e3 a9 ff LDA #&ff &16e5 9d 52 0f STA &0f52,X ; balls_table_x_fraction ; check_for_bounce_off_left_table_edge &16e8 bd 22 0f LDA &0f22,X ; balls_table_x &16eb 10 1f BPL &170c ; check_for_bounce_off_top_table_edge &16ed c9 e1 CMP #&e1 &16ef b0 1b BCS &170c ; check_for_bounce_off_top_table_edge # Has the ball hit the left edge of the table? &16f1 a9 01 LDA #&01 &16f3 fd 72 0f SBC &0f72,X ; balls_x_velocity # Invert x velocity &16f6 a8 TAY &16f7 b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen x velocity &16fa 9d 72 0f STA &0f72,X ; balls_x_velocity &16fd 20 8d 15 JSR &158d ; check_for_side_pockets # Returns carry set if ball entered pocket ; to_consider_next_moving_ball_if_potted &1700 b0 54 BCS &1756 ; consider_next_moving_ball_if_potted &1702 a9 e1 LDA #&e1 # Otherwise, align ball with left edge &1704 9d 22 0f STA &0f22,X ; balls_table_x &1707 a9 00 LDA #&00 &1709 9d 52 0f STA &0f52,X ; balls_table_x_fraction ; check_for_bounce_off_top_table_edge &170c bd 42 0f LDA &0f42,X ; balls_table_y &170f 30 20 BMI &1731 ; check_for_bounce_off_bottom_table_edge &1711 c9 40 CMP #&40 &1713 90 1c BCC &1731 ; check_for_bounce_off_bottom_table_edge # Has the ball hit the top edge of the table? &1715 a9 00 LDA #&00 &1717 fd 82 0f SBC &0f82,X ; balls_y_velocity # Invert y velocity &171a a8 TAY &171b b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen y velocity &171e 9d 82 0f STA &0f82,X ; balls_y_velocity &1721 a9 3f LDA #&3f # Align ball with top edge &1723 9d 42 0f STA &0f42,X ; balls_table_y &1726 a9 ff LDA #&ff &1728 9d 62 0f STA &0f62,X ; balls_table_y_fraction &172b 20 9b 15 JSR &159b ; bounce_off_edge_of_table &172e 4c 53 17 JMP &1753 ; to_check_for_top_or_bottom_pockets ; check_for_bounce_off_bottom_table_edge &1731 bd 42 0f LDA &0f42,X ; balls_table_y &1734 10 1d BPL &1753 ; to_check_for_top_or_bottom_pockets &1736 c9 c0 CMP #&c0 &1738 b0 19 BCS &1753 ; to_check_for_top_or_bottom_pockets # Has the ball hit the bottom edge of the table? &173a a9 01 LDA #&01 &173c fd 82 0f SBC &0f82,X ; balls_y_velocity # Invert y velocity &173f a8 TAY &1740 b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen y velocity &1743 9d 82 0f STA &0f82,X ; balls_y_velocity &1746 a9 c1 LDA #&c1 # Align ball with bottom edge &1748 9d 42 0f STA &0f42,X ; balls_table_y &174b a9 00 LDA #&00 &174d 9d 62 0f STA &0f62,X ; balls_table_y_fraction &1750 20 9b 15 JSR &159b ; bounce_off_edge_of_table ; to_check_for_top_or_bottom_pockets &1753 20 a7 15 JSR &15a7 ; check_for_top_or_bottom_pockets # Returns carry set if ball entered pocket ; consider_next_moving_ball_if_potted &1756 b0 4a BCS &17a2 ; consider_next_moving_ball # Consider next ball if this ball was potted &1758 a5 af LDA &af ; moving_ball_sound &175a 30 03 BMI &175f ; skip_sound &175c 20 11 2d JSR &2d11 ; cue_sound_for_playing ; skip_sound &175f a5 4e LDA &4e ; dampening_cooldown &1761 d0 3f BNE &17a2 ; consider_next_moving_ball # Is it time to dampen this ball's velocity? ; dampen_x_velocity &1763 bc 72 0f LDY &0f72,X ; balls_x_velocity &1766 b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen x velocity &1769 bc d2 0f LDY &0fd2,X ; balls_x_acceleration &176c 18 CLC &176d 7d d2 0f ADC &0fd2,X ; balls_x_acceleration # Apply dampened x acceleration &1770 38 SEC &1771 f9 70 38 SBC &3870,Y ; velocity_dampening_table &1774 9d 72 0f STA &0f72,X ; balls_x_velocity &1777 b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen x acceleration &177a 9d d2 0f STA &0fd2,X ; balls_x_acceleration ; dampen_y_velocity &177d bc 82 0f LDY &0f82,X ; balls_y_velocity &1780 b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen y velocity &1783 bc e2 0f LDY &0fe2,X ; balls_y_acceleration &1786 18 CLC &1787 7d e2 0f ADC &0fe2,X ; balls_y_acceleration # Apply dampened y acceleration &178a 38 SEC &178b f9 70 38 SBC &3870,Y ; velocity_dampening_table &178e 9d 82 0f STA &0f82,X ; balls_y_velocity &1791 b9 70 38 LDA &3870,Y ; velocity_dampening_table # Dampen y acceleration &1794 9d e2 0f STA &0fe2,X ; balls_y_acceleration ; check_if_ball_has_stopped_moving &1797 bd 72 0f LDA &0f72,X ; balls_x_velocity &179a 1d 82 0f ORA &0f82,X ; balls_y_velocity &179d d0 03 BNE &17a2 ; consider_next_moving_ball # Has the ball stopped moving? &179f 20 b6 17 JSR &17b6 ; apply_and_clear_acceleration # If so, apply any residual acceleration ; consider_next_moving_ball &17a2 ca DEX &17a3 30 03 BMI &17a8 ; updated_all_moving_balls &17a5 4c 63 16 JMP &1663 ; update_moving_balls_loop ; updated_all_moving_balls &17a8 a5 4d LDA &4d ; number_of_balls_in_motion &17aa f0 03 BEQ &17af ; no_balls_moving &17ac 4c d4 17 JMP &17d4 ; consider_collisions_between_moving_balls ; no_balls_moving &17af a5 7c LDA &7c ; first_ball_hit # Negative if no ball was hit &17b1 10 02 BPL &17b5 ; leave &17b3 85 7a STA &7a ; foul_shot # Set to negative to indicate foul shot (no balls hit) ; leave &17b5 60 RTS ; apply_and_clear_acceleration &17b6 bd 72 0f LDA &0f72,X ; balls_x_velocity &17b9 18 CLC &17ba 7d d2 0f ADC &0fd2,X ; balls_x_acceleration &17bd 9d 72 0f STA &0f72,X ; balls_x_velocity &17c0 bd 82 0f LDA &0f82,X ; balls_y_velocity &17c3 18 CLC &17c4 7d e2 0f ADC &0fe2,X ; balls_y_acceleration &17c7 9d 82 0f STA &0f82,X ; balls_y_velocity &17ca a9 00 LDA #&00 &17cc 9d d2 0f STA &0fd2,X ; balls_x_acceleration &17cf 9d e2 0f STA &0fe2,X ; balls_y_acceleration &17d2 60 RTS ; leave &17d3 60 RTS ; consider_collisions_between_moving_balls &17d4 a2 00 LDX #&00 ; BALL_FIRST &17d6 4c e2 17 JMP &17e2 ; consider_collisions_between_moving_balls_loop ; find_possible_collision_source &17d9 24 7c BIT &7c ; first_ball_hit # Negative if no ball was hit by cue ball &17db 30 f6 BMI &17d3 ; leave &17dd e8 INX &17de e0 0f CPX #&0f ; BALL_LAST &17e0 b0 f1 BCS &17d3 ; leave ; consider_collisions_between_moving_balls_loop &17e2 86 02 STX &02 ; source_ball &17e4 bd e2 0e LDA &0ee2,X ; balls_state # Negative if ball not present &17e7 30 f0 BMI &17d9 ; find_possible_collision_source &17e9 a4 02 LDY &02 ; source_ball &17eb 4c f2 17 JMP &17f2 ; consider_collisions ; consider_collisions_for_ball_X_loop_XY &17ee a6 02 LDX &02 ; source_ball &17f0 a4 03 LDY &03 ; target_ball ; consider_collisions_for_ball_X_loop &17f2 c8 INY &17f3 c0 10 CPY #&10 ; BALL_LAST + 1 &17f5 b0 e2 BCS &17d9 ; find_possible_collision_source &17f7 b9 e2 0e LDA &0ee2,Y ; balls_state # Negative if ball not present &17fa 30 f6 BMI &17f2 ; consider_collisions_for_ball_X_loop # No collision if ball not present &17fc bd 72 0f LDA &0f72,X ; balls_x_velocity &17ff 1d 82 0f ORA &0f82,X ; balls_y_velocity &1802 19 72 0f ORA &0f72,Y ; balls_x_velocity &1805 19 82 0f ORA &0f82,Y ; balls_y_velocity &1808 f0 e8 BEQ &17f2 ; consider_collisions_for_ball_X_loop # Consider next target if both balls stationary &180a b9 62 0f LDA &0f62,Y ; balls_table_y_fraction &180d dd 62 0f CMP &0f62,X ; balls_table_y_fraction &1810 b9 42 0f LDA &0f42,Y ; balls_table_y &1813 fd 42 0f SBC &0f42,X ; balls_table_y &1816 85 09 STA &09 ; delta_y &1818 10 05 BPL &181f ; skip_inversion_y &181a 49 ff EOR #&ff &181c 38 SEC &181d 69 00 ADC #&00 ; skip_inversion_y &181f c9 07 CMP #&07 &1821 b0 cf BCS &17f2 ; consider_collisions_for_ball_X_loop # Consider next target if balls too far apart in y &1823 85 0d STA &0d ; absolute_delta_y &1825 b9 52 0f LDA &0f52,Y ; balls_table_x_fraction &1828 dd 52 0f CMP &0f52,X ; balls_table_x_fraction &182b b9 22 0f LDA &0f22,Y ; balls_table_x &182e fd 22 0f SBC &0f22,X ; balls_table_x &1831 85 08 STA &08 ; delta_x &1833 10 05 BPL &183a ; skip_inversion_x &1835 49 ff EOR #&ff &1837 38 SEC &1838 69 00 ADC #&00 ; skip_inversion_x &183a c9 07 CMP #&07 &183c b0 b4 BCS &17f2 ; consider_collisions_for_ball_X_loop # Consider next target if balls too far apart in x &183e aa TAX &183f 84 03 STY &03 ; target_ball &1841 a4 0d LDY &0d ; absolute_y_delta &1843 bd 00 04 LDA &0400,X ; squares_low_table # (absolute_x_delta) ^ 2 + (absolute_y_delta) ^ 2 &1846 79 00 04 ADC &0400,Y ; squares_low_table # i.e. square of distance between balls &1849 b0 a3 BCS &17ee ; consider_collisions_for_ball_X_loop_XY # Consider next target if balls too far apart &184b c9 2f CMP #&2f &184d b0 9f BCS &17ee ; consider_collisions_for_ball_X_loop_XY # Consider next target if balls too far apart &184f 85 0e STA &0e ; square_of_distance_between_balls &1851 86 0c STX &0c ; absolute_delta_x &1853 a6 02 LDX &02 ; source_ball &1855 a4 03 LDY &03 ; target_ball &1857 38 SEC &1858 bd 72 0f LDA &0f72,X ; balls_x_velocity &185b f9 72 0f SBC &0f72,Y ; balls_x_velocity &185e 85 04 STA &04 ; delta_x_velocity &1860 10 05 BPL &1867 ; skip_inversion_x_velocity &1862 49 ff EOR #&ff &1864 38 SEC &1865 69 00 ADC #&00 ; skip_inversion_x_velocity &1867 85 06 STA &06 ; absolute_delta_x_velocity &1869 38 SEC &186a bd 82 0f LDA &0f82,X ; balls_y_velocity &186d f9 82 0f SBC &0f82,Y ; balls_y_velocity &1870 85 05 STA &05 ; delta_y_velocity &1872 10 05 BPL &1879 ; skip_inversion_y_velocity &1874 49 ff EOR #&ff &1876 38 SEC &1877 69 00 ADC #&00 ; skip_inversion_y_velocity &1879 85 07 STA &07 ; absolute_delta_y_velocity &187b a5 08 LDA &08 ; delta_x &187d 45 04 EOR &04 ; delta_x_velocity &187f 10 09 BPL &188a ; check_for_collision_carefully &1881 45 09 EOR &09 ; delta_y &1883 45 05 EOR &05 ; delta_y_velocity &1885 30 03 BMI &188a ; check_for_collision_carefully ; to_consider_collisions_for_ball_X_loop_XY &1887 4c ee 17 JMP &17ee ; consider_collisions_for_ball_X_loop_XY ; check_for_collision_carefully &188a a6 0c LDX &0c ; absolute_delta_x # Calculate delta_x * delta_x_velocity &188c a4 06 LDY &06 ; absolute_delta_x_velocity &188e 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &1891 a5 08 LDA &08 ; delta_x &1893 45 04 EOR &04 ; delta_x_velocity &1895 10 0c BPL &18a3 ; skip_inversion_x_times_x_velocity &1897 8a TXA &1898 49 ff EOR #&ff &189a aa TAX &189b 98 TYA &189c 49 ff EOR #&ff &189e a8 TAY &189f e8 INX &18a0 d0 01 BNE &18a3 ; skip_inversion_x_times_x_velocity &18a2 c8 INY ; skip_inversion_x_times_x_velocity &18a3 84 17 STY &17 ; delta_x_times_delta_x_velocity &18a5 86 16 STX &16 ; delta_x_times_delta_x_velocity_fraction &18a7 a6 0d LDX &0d ; absolute_delta_y # Calculate delta_y * delta_y_velocity &18a9 a4 07 LDY &07 ; absolute_delta_y_velocity &18ab 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &18ae a5 09 LDA &09 ; delta_y &18b0 45 05 EOR &05 ; delta_y_velocity &18b2 10 0c BPL &18c0 ; skip_inversion_y_times_y_velocity &18b4 8a TXA &18b5 49 ff EOR #&ff &18b7 aa TAX &18b8 98 TYA &18b9 49 ff EOR #&ff &18bb a8 TAY &18bc e8 INX &18bd d0 01 BNE &18c0 ; skip_inversion_y_times_y_velocity &18bf c8 INY ; skip_inversion_y_times_y_velocity &18c0 18 CLC # Calculate (delta_x * delta_x_velocity) &18c1 8a TXA # + (delta_y * delta_y_velocity) &18c2 65 16 ADC &16 ; delta_x_times_delta_x_velocity # = total &18c4 aa TAX &18c5 98 TYA &18c6 65 17 ADC &17 ; delta_x_times_delta_x_velocity_fraction &18c8 a8 TAY &18c9 30 bc BMI &1887 ; to_consider_collisions_for_ball_X_loop_XY &18cb 84 17 STY &17 ; delta_times_delta_velocity &18cd 86 16 STX &16 ; delta_times_delta_velocity_fraction ; calculate_collision_velocity_change_x &18cf a6 0c LDX &0c ; absolute_delta_x # Calculate impact_force * delta_x &18d1 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &18d4 8a TXA &18d5 a6 0c LDX &0c ; absolute_delta_x &18d7 85 0c STA &0c ; result_middle &18d9 a4 16 LDY &16 ; delta_times_delta_velocity_fraction &18db 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &18de 18 CLC &18df 98 TYA &18e0 65 0c ADC &0c ; result_middle &18e2 a8 TAY &18e3 a5 0e LDA &0e ; square_of_distance_between_balls &18e5 20 ba 24 JSR &24ba ; divide_XY_by_A # Calculate A = (total * delta_x) / distance &18e8 24 08 BIT &08 ; delta_x &18ea 10 05 BPL &18f1 ; skip_inversion_change_x &18ec 49 ff EOR #&ff &18ee 38 SEC &18ef 69 00 ADC #&00 ; skip_inversion_change_x &18f1 85 10 STA &10 ; collision_velocity_change_x ; calculate_collision_velocity_change_y &18f3 a6 0d LDX &0d ; absolute_delta_y # Calculate momentum * delta_y &18f5 a4 17 LDY &17 ; delta_times_delta_velocity &18f7 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &18fa 8a TXA &18fb a6 0d LDX &0d ; absolute_delta_y &18fd 85 0d STA &0d ; result_middle &18ff a4 16 LDY &16 ; delta_times_delta_velocity_fraction &1901 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &1904 18 CLC &1905 98 TYA &1906 65 0d ADC &0d ; result_middle &1908 a8 TAY &1909 a5 0e LDA &0e ; square_of_distance_between_balls &190b 20 ba 24 JSR &24ba ; divide_XY_by_A # Calculate A = (total * delta_y) / distance &190e 24 09 BIT &09 ; delta_y &1910 10 05 BPL &1917 ; skip_inversion_change_y &1912 49 ff EOR #&ff &1914 38 SEC &1915 69 00 ADC #&00 ; skip_inversion_change_y &1917 85 11 STA &11 ; collision_velocity_change_y &1919 05 10 ORA &10 ; collision_velocity_change_x &191b d0 03 BNE &1920 ; collision_occurred &191d 4c 87 18 JMP &1887 ; to_consider_collisions_for_ball_X_loop_XY ; collision_occurred &1920 a6 03 LDX &03 ; target_ball # Apply change of velocities to both balls &1922 18 CLC &1923 bd 72 0f LDA &0f72,X ; balls_x_velocity &1926 65 10 ADC &10 ; collision_velocity_change_x # target velocity x += collision velocity change x &1928 9d 72 0f STA &0f72,X ; balls_x_velocity &192b 18 CLC &192c bd 82 0f LDA &0f82,X ; balls_y_velocity &192f 65 11 ADC &11 ; collision_velocity_change_y # target velocity y += collision velocity change y &1931 9d 82 0f STA &0f82,X ; balls_y_velocity &1934 a6 02 LDX &02 ; source_ball &1936 38 SEC &1937 bd 72 0f LDA &0f72,X ; balls_x_velocity &193a e5 10 SBC &10 ; collision_velocity_change_x # source velocity x -= collision velocity change x &193c 9d 72 0f STA &0f72,X ; balls_x_velocity &193f 38 SEC &1940 bd 82 0f LDA &0f82,X ; balls_y_velocity &1943 e5 11 SBC &11 ; collision_velocity_change_y # source velocity y -= collision velocity change y &1945 9d 82 0f STA &0f82,X ; balls_y_velocity ; consider_setting_second_ball_hit &1948 a6 02 LDX &02 ; source_ball &194a a4 03 LDY &03 ; target_ball &194c 24 7d BIT &7d ; second_ball_hit # Has a second ball already been hit? Negative if not &194e 10 14 BPL &1964 ; consider_scoring_for_collision &1950 e4 7c CPX &7c ; first_ball_hit &1952 d0 07 BNE &195b ; consider_target_ball # If the source ball is not the first ball hit, &1954 98 TYA &1955 f0 0d BEQ &1964 ; consider_scoring_for_collision # and the target ball is not the cue ball, &1957 84 7d STY &7d ; second_ball_hit # use the target ball as the second ball hit &1959 d0 09 BNE &1964 ; consider_scoring_for_collision # Always branches ; consider_target_ball &195b c4 7c CPY &7c ; first_ball_hit # Otherwise, if the target ball is not the first ball hit, &195d d0 05 BNE &1964 ; consider_scoring_for_collision &195f 8a TXA &1960 d0 02 BNE &1964 ; consider_scoring_for_collision # and the target ball is not the cue ball, &1962 86 7d STX &7d ; second_ball_hit # use the source ball as the second ball hit ; consider_scoring_for_collision &1964 e4 7c CPX &7c ; first_ball_hit # If the source ball is the first ball hit, &1966 d0 17 BNE &197f ; skip_source_ball_scoring &1968 a9 03 LDA #&03 # Move scores three for collision involving cue ball &196a c0 00 CPY #&00 ; BALL_CUE &196c f0 0e BEQ &197c ; add_score_for_source_ball &196e bd e2 0e LDA &0ee2,X ; balls_state &1971 d9 e2 0e CMP &0ee2,Y ; balls_state &1974 08 PHP ; source and target balls are same colour &1975 a9 03 LDA #&03 # Move scores three for collisions of same colour &1977 28 PLP ; source and target balls are same colour &1978 f0 02 BEQ &197c ; add_score_for_source_ball &197a a9 04 LDA #&04 # Move scores four for collisions of different colours ; add_score_for_source_ball &197c 20 54 14 JSR &1454 ; add_score_to_potential_move ; skip_source_ball_scoring &197f c4 7c CPY &7c ; first_ball_hit # If the target ball is the first ball hit, &1981 d0 17 BNE &199a ; skip_target_ball_scoring &1983 a9 03 LDA #&03 # Move scores three for collision involving cue ball &1985 e0 00 CPX #&00 ; BALL_CUE &1987 f0 0e BEQ &1997 ; add_score_for_target_ball &1989 bd e2 0e LDA &0ee2,X ; balls_state &198c dd e2 0e CMP &0ee2,X ; balls_state # Bug: should be CMP &0ee2,Y (see &1971) &198f 08 PHP ; source and target balls are same colour &1990 a9 03 LDA #&03 # Move scores three for all other collisions &1992 28 PLP ; source and target balls are same colour &1993 f0 02 BEQ &1997 ; add_score_for_target_ball # Bug: always branches &1995 a9 04 LDA #&04 # Would score four for collisions of different colours ; add_score_for_target_ball &1997 20 54 14 JSR &1454 ; add_score_to_potential_move ; skip_target_ball_scoring &199a 8a TXA &199b d0 33 BNE &19d0 ; not_first_ball_hit # If the source ball is the cue ball, &199d 24 7c BIT &7c ; first_ball_hit &199f 10 2f BPL &19d0 ; not_first_ball_hit # and the target is the first other ball to be hit, &19a1 84 7c STY &7c ; first_ball_hit &19a3 b9 e2 0e LDA &0ee2,Y ; balls_state &19a6 48 PHA ; target ball colour &19a7 a9 01 LDA #&01 # Move scores one for hitting first ball &19a9 20 54 14 JSR &1454 ; add_score_to_potential_move &19ac 68 PLA ; target ball colour &19ad 24 71 BIT &71 ; first_player_colour # Negative if colours haven't been decided &19af 30 1f BMI &19d0 ; not_first_ball_hit &19b1 c5 7e CMP &7e ; current_player_ball_colour &19b3 f0 0f BEQ &19c4 ; not_foul_shot # If the player has hit the wrong colour, &19b5 48 PHA ; target ball colour &19b6 a9 05 LDA #&05 # Move scores five for hitting wrong colour first &19b8 20 54 14 JSR &1454 ; add_score_to_potential_move &19bb 68 PLA ; target ball colour &19bc 24 7b BIT &7b ; player_has_free_ball # Negative if player has free ball &19be 30 10 BMI &19d0 ; not_first_ball_hit &19c0 a9 ff LDA #&ff &19c2 85 7a STA &7a ; foul_shot # Set to negative to indicate foul shot (hit wrong colour) ; not_foul_shot &19c4 24 86 BIT &86 ; only_potential_move # Negative if move is potential &19c6 10 08 BPL &19d0 ; not_first_ball_hit &19c8 24 8c BIT &8c ; computer_is_thinking # Negative if computer is just thinking &19ca 30 1b BMI &19e7 ; skip_collision &19cc 24 7a BIT &7a ; foul_shot # Negative if foul shot &19ce 30 17 BMI &19e7 ; skip_collision ; not_first_ball_hit &19d0 98 TYA &19d1 dd 92 0f CMP &0f92,X ; balls_collided_with &19d4 f0 11 BEQ &19e7 ; skip_collision # Has the source ball already collided with the target ball? &19d6 98 TYA &19d7 9d 92 0f STA &0f92,X ; balls_collided_with # If not, store target ball as source's collision partner &19da 8a TXA &19db 99 92 0f STA &0f92,Y ; balls_collided_with # and source ball as target's collision partner &19de a9 01 LDA #&01 ; SOUND_COLLISION &19e0 20 11 2d JSR &2d11 ; cue_sound_for_playing # Play sound for collision between balls &19e3 a9 00 LDA #&00 &19e5 85 a1 STA &a1 ; balls_not_broken # Set to zero to indicate balls have been broken ; skip_collision &19e7 a6 02 LDX &02 ; source_ball &19e9 20 b6 17 JSR &17b6 ; apply_and_clear_acceleration &19ec a6 03 LDX &03 ; target_ball &19ee 20 b6 17 JSR &17b6 ; apply_and_clear_acceleration &19f1 e6 4d INC &4d ; number_of_balls_in_motion &19f3 4c ee 17 JMP &17ee ; consider_collisions_for_ball_X_loop_XY ; get_balls_from_layout &19f6 20 92 1a JSR &1a92 ; get_ball_layout_address &19f9 a0 00 LDY #&00 &19fb 84 73 STY &73 ; solid_balls_remaining &19fd 84 74 STY &74 ; dithered_balls_remaining &19ff b1 02 LDA (&02),Y ; layout_address # First two bytes are bitmap for balls present &1a01 85 0c STA &0c ; balls_present_in_layout &1a03 c8 INY &1a04 b1 02 LDA (&02),Y ; layout_address &1a06 85 0d STA &0d ; balls_present_in_layout + 1 &1a08 c8 INY &1a09 a2 00 LDX #&00 ; BALL_FIRST ; get_balls_from_layout_loop &1a0b 20 14 1a JSR &1a14 ; get_ball_from_layout_if_present &1a0e e8 INX &1a0f e0 10 CPX #&10 ; BALL_LAST + 1 &1a11 90 f8 BCC &1a0b ; get_balls_from_layout_loop &1a13 60 RTS ; get_ball_from_layout_if_present &1a14 a9 ff LDA #&ff &1a16 46 0d LSR &0d ; balls_present_in_layout + 1 &1a18 66 0c ROR &0c ; balls_present_in_layout &1a1a 90 03 BCC &1a1f ; not_present ; get_ball_from_layout &1a1c bd df 37 LDA &37df,X ; balls_colour ; not_present &1a1f 9d e2 0e STA &0ee2,X ; balls_state # Negative if ball not present, otherwise colour &1a22 c9 00 CMP #&00 ; BALL_TYPE_SOLID &1a24 d0 02 BNE &1a28 ; not_solid &1a26 e6 73 INC &73 ; solid_balls_remaining ; not_solid &1a28 c9 01 CMP #&01 ; BALL_TYPE_DITHERED &1a2a d0 02 BNE &1a2e ; not_dithered &1a2c e6 74 INC &74 ; dithered_balls_remaining ; not_dithered &1a2e b1 02 LDA (&02),Y ; layout_address # Four bytes per ball &1a30 9d 52 0f STA &0f52,X ; balls_table_x_fraction &1a33 c8 INY &1a34 b1 02 LDA (&02),Y ; layout_address &1a36 9d 22 0f STA &0f22,X ; balls_table_x &1a39 c8 INY &1a3a b1 02 LDA (&02),Y ; layout_address &1a3c 9d 62 0f STA &0f62,X ; balls_table_y_fraction &1a3f c8 INY &1a40 b1 02 LDA (&02),Y ; layout_address &1a42 9d 42 0f STA &0f42,X ; balls_table_y &1a45 c8 INY &1a46 a9 00 LDA #&00 &1a48 9d 32 0f STA &0f32,X ; balls_unused &1a4b 9d 72 0f STA &0f72,X ; balls_x_velocity &1a4e 9d 82 0f STA &0f82,X ; balls_y_velocity &1a51 9d d2 0f STA &0fd2,X ; balls_x_acceleration &1a54 9d e2 0f STA &0fe2,X ; balls_y_acceleration &1a57 60 RTS ; store_balls_in_layout &1a58 20 92 1a JSR &1a92 ; get_ball_layout_address &1a5b a0 02 LDY #&02 &1a5d a2 00 LDX #&00 ; BALL_FIRST ; store_balls_in_layout_loop &1a5f bd df 37 LDA &37df,X ; balls_colour &1a62 dd e2 0e CMP &0ee2,X ; balls_state # Negative if ball not present &1a65 66 0d ROR &0d ; balls_present_in_layout + 1 # Carry set if ball present; if so, set bit in layout &1a67 66 0c ROR &0c ; balls_present_in_layout &1a69 bd 52 0f LDA &0f52,X ; balls_table_x_fraction &1a6c 91 02 STA (&02),Y ; layout_address &1a6e c8 INY &1a6f bd 22 0f LDA &0f22,X ; balls_table_x &1a72 91 02 STA (&02),Y ; layout_address &1a74 c8 INY &1a75 bd 62 0f LDA &0f62,X ; balls_table_y_fraction &1a78 91 02 STA (&02),Y ; layout_address &1a7a c8 INY &1a7b bd 42 0f LDA &0f42,X ; balls_table_y &1a7e 91 02 STA (&02),Y ; layout_address &1a80 c8 INY &1a81 e8 INX &1a82 e0 10 CPX #&10 ; BALL_LAST + 1 &1a84 90 d9 BCC &1a5f ; store_balls_in_layout_loop &1a86 a0 00 LDY #&00 &1a88 a5 0c LDA &0c ; balls_present_in_layout &1a8a 91 02 STA (&02),Y ; layout_address &1a8c c8 INY &1a8d a5 0d LDA &0d ; balls_present_in_layout + 1 &1a8f 91 02 STA (&02),Y ; layout_address &1a91 60 RTS ; get_ball_layout_address &1a92 aa TAX &1a93 a0 42 LDY #&42 &1a95 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &1a98 18 CLC &1a99 8a TXA &1a9a 69 00 ADC #&00 # actually ADC ball_layouts_base_address_low &1a9c 85 02 STA &02 ; layout_address_low &1a9e 98 TYA &1a9f 69 00 ADC #&00 # actually ADC ball_layouts_base_address_high &1aa1 85 03 STA &03 ; layout_address_high &1aa3 60 RTS ; calculate_table_and_balls_screen_coordinates &1aa4 20 cd 1a JSR &1acd ; calculate_viewpoint_offsets &1aa7 20 28 1b JSR &1b28 ; calculate_table_points_screen_coordinates &1aaa 20 f7 1a JSR &1af7 ; calculate_plotting_offsets &1aad a2 00 LDX #&00 ; BALL_FIRST ; calculate_balls_screen_coordinates_loop &1aaf e4 a9 CPX &a9 ; focus_ball &1ab1 f0 05 BEQ &1ab8 ; skip_considering_state &1ab3 bd e2 0e LDA &0ee2,X ; balls_state # Negative if ball not present, otherwise colour &1ab6 30 0f BMI &1ac7 ; consider_next_ball ; skip_considering_state &1ab8 bd a2 0f LDA &0fa2,X ; balls_needs_recalculating # Negative if ball's screen position needs recalculating &1abb 05 4f ORA &4f ; viewpoint_has_changed # Negative if viewpoint has changed &1abd 10 08 BPL &1ac7 ; consider_next_ball &1abf 20 03 1c JSR &1c03 ; calculate_ball_screen_coordinates &1ac2 a9 00 LDA #&00 &1ac4 9d a2 0f STA &0fa2,X ; balls_needs_recalculating # Set to zero to indicate no recalculation needed ; consider_next_ball &1ac7 e8 INX &1ac8 e0 10 CPX #&10 ; BALL_LAST + 1 &1aca 90 e3 BCC &1aaf ; calculate_balls_screen_coordinates_loop &1acc 60 RTS ; calculate_viewpoint_offsets &1acd 24 4f BIT &4f ; viewpoint_has_changed # Negative if viewpoint has changed &1acf 10 25 BPL &1af6 ; leave &1ad1 a6 2f LDX &2f ; player_viewpoint_vertical_rotation &1ad3 8a TXA &1ad4 18 CLC &1ad5 69 34 ADC #&34 &1ad7 85 49 STA &49 ; viewpoint_y_offset &1ad9 18 CLC &1ada bd 2f 36 LDA &362f,X ; vertical_rotation_to_z_offset_table &1add 65 3d ADC &3d ; viewpoint_zoom &1adf 85 4a STA &4a ; viewpoint_z_offset &1ae1 a2 00 LDX #&00 &1ae3 86 47 STX &47 ; viewpoint_x_offset_fraction &1ae5 a9 80 LDA #&80 &1ae7 85 48 STA &48 ; viewpoint_x_offset &1ae9 a6 a9 LDX &a9 ; focus_ball &1aeb 20 03 1c JSR &1c03 ; calculate_ball_screen_coordinates &1aee a5 02 LDA &02 ; t_x_fraction &1af0 85 47 STA &47 ; viewpoint_x_offset_fraction &1af2 a5 03 LDA &03 ; t_x &1af4 85 48 STA &48 ; viewpoint_x_offset ; leave &1af6 60 RTS ; calculate_plotting_offsets &1af7 24 4f BIT &4f ; viewpoint_has_changed # Negative if viewpoint has changed &1af9 10 2c BPL &1b27 ; leave &1afb a2 00 LDX #&00 &1afd 86 61 STX &61 ; plotting_x_offset &1aff a6 a9 LDX &a9 ; focus_ball &1b01 20 03 1c JSR &1c03 ; calculate_ball_screen_coordinates &1b04 a5 08 LDA &08 ; screen_x_fraction &1b06 38 SEC &1b07 e5 62 SBC &62 ; minimum_screen_x_fraction &1b09 aa TAX &1b0a a5 09 LDA &09 ; screen_x &1b0c e5 63 SBC &63 ; minimum_screen_x &1b0e e0 80 CPX #&80 # Multiply by two, keeping sign &1b10 2a ROL A &1b11 aa TAX &1b12 38 SEC &1b13 e9 50 SBC #&50 &1b15 85 61 STA &61 ; plotting_x_offset &1b17 b0 02 BCS &1b1b ; set_left_clip_x &1b19 a9 00 LDA #&00 ; set_left_clip_x &1b1b 85 5d STA &5d ; left_clip_x &1b1d 8a TXA &1b1e 18 CLC &1b1f 69 50 ADC #&50 &1b21 90 02 BCC &1b25 ; set_right_clip_x &1b23 a9 00 LDA #&00 ; set_right_clip_x &1b25 85 5e STA &5e ; right_clip_x ; leave &1b27 60 RTS ; calculate_table_points_screen_coordinates &1b28 24 4f BIT &4f ; viewpoint_has_changed # Negative if viewpoint has changed &1b2a 10 fb BPL &1b27 ; leave &1b2c a0 1c LDY #&1c &1b2e 24 50 BIT &50 ; placing_ball # Negative if placing ball &1b30 10 02 BPL &1b34 ; skip_d &1b32 a0 21 LDY #&21 # Include points for "D" ; skip_d &1b34 84 8f STY &8f ; number_of_points_plus_one &1b36 a9 ff LDA #&ff &1b38 85 62 STA &62 ; minimum_screen_x_fraction &1b3a 85 63 STA &63 ; minimum_screen_x ; calculate_table_points_screen_coordinates_loop &1b3c 88 DEY &1b3d 30 40 BMI &1b7f ; offset_points &1b3f be 76 37 LDX &3776,Y ; three_times_table &1b42 98 TYA &1b43 48 PHA ; point &1b44 a0 00 LDY #&00 &1b46 bd b2 36 LDA &36b2,X ; table_points_coordinates # x &1b49 84 02 STY &02 ; world_x_fraction &1b4b 85 03 STA &03 ; world_x &1b4d bd b3 36 LDA &36b3,X ; table_points_coordinates + 1 # z &1b50 84 04 STY &04 ; world_z_fraction &1b52 85 05 STA &05 ; world_z &1b54 bd b4 36 LDA &36b4,X ; table_points_coordinates + 2 # y &1b57 84 06 STY &06 ; world_y_fraction &1b59 85 07 STA &07 ; world_y &1b5b 20 04 23 JSR &2304 ; transform_world_to_screen_coordinates &1b5e 68 PLA ; point &1b5f a8 TAY &1b60 a5 08 LDA &08 ; screen_x_fraction &1b62 99 f2 0f STA &0ff2,Y ; table_points_screen_x_fraction &1b65 c5 62 CMP &62 ; minimum_screen_x_fraction &1b67 a5 09 LDA &09 ; screen_x &1b69 99 12 10 STA &1012,Y ; table_points_screen_x &1b6c e5 63 SBC &63 ; minimum_screen_x &1b6e a5 0b LDA &0b ; screen_y &1b70 99 34 10 STA &1034,Y ; table_points_screen_y &1b73 b0 c7 BCS &1b3c ; calculate_table_points_screen_coordinates_loop &1b75 a5 08 LDA &08 ; screen_x_fraction &1b77 85 62 STA &62 ; minimum_screen_x_fraction &1b79 a5 09 LDA &09 ; screen_x &1b7b 85 63 STA &63 ; minimum_screen_x &1b7d 90 bd BCC &1b3c ; calculate_table_points_screen_coordinates_loop ; offset_points &1b7f a4 8f LDY &8f ; number_of_points_plus_one ; offset_points_loop &1b81 88 DEY &1b82 30 15 BMI &1b99 ; leave &1b84 b9 f2 0f LDA &0ff2,Y ; table_points_screen_x_fraction # screen_x = (screen_x - minimum_screen_x) * 2 &1b87 38 SEC &1b88 e5 62 SBC &62 ; minimum_screen_x_fraction &1b8a aa TAX &1b8b b9 12 10 LDA &1012,Y ; table_points_screen_x &1b8e e5 63 SBC &63 ; minimum_screen_x &1b90 e0 80 CPX #&80 # Multiply by two, keeping sign &1b92 2a ROL A &1b93 99 12 10 STA &1012,Y ; table_points_screen_x &1b96 4c 81 1b JMP &1b81 ; offset_points_loop ; leave &1b99 60 RTS ; plot_table &1b9a 24 4f BIT &4f ; viewpoint_has_changed # Negative if viewpoint has changed &1b9c 30 0b BMI &1ba9 ; plot_table_polygons &1b9e 24 6f BIT &6f ; sideways_ram_version # Negative if using sideways RAM &1ba0 10 07 BPL &1ba9 ; plot_table_polygons &1ba2 24 70 BIT &70 ; sideways_ram_has_table_snapshot # Negative if sideways RAM has snapshot of table &1ba4 10 03 BPL &1ba9 ; plot_table_polygons &1ba6 4c 72 84 JMP &8472 ; unbuffer_screen_from_sideways_ram # Don't redraw; use saved snapshot of table ; plot_table_polygons &1ba9 a0 00 LDY #&00 ; plot_table_polygon_loop &1bab 84 02 STY &02 ; polygon_data_offset &1bad b9 16 37 LDA &3716,Y ; table_polygon_data + 1 # Second byte of polygon data sets colour of polygon &1bb0 20 e5 1f JSR &1fe5 ; set_polygon_colour &1bb3 a4 02 LDY &02 ; polygon_data_offset &1bb5 b9 15 37 LDA &3715,Y ; table_polygon_data # First byte of polygon data sets number of points &1bb8 48 PHA ; number of points &1bb9 aa TAX &1bba c8 INY &1bbb c8 INY &1bbc a9 5a LDA #&5a &1bbe 24 50 BIT &50 ; placing_ball # Negative if placing ball &1bc0 10 02 BPL &1bc4 ; set_end_of_polygon_data_offset &1bc2 a9 61 LDA #&61 # Include "D" ; set_end_of_polygon_data_offset &1bc4 85 90 STA &90 ; end_of_polygon_data_offset ; copy_polygon_points_loop &1bc6 b9 15 37 LDA &3715,Y ; table_polygon_data # Remaining bytes of polygon data are point numbers &1bc9 84 02 STY &02 ; polygon_data_offset &1bcb a8 TAY &1bcc b9 12 10 LDA &1012,Y ; table_points_screen_x &1bcf 95 c4 STA &c4,X ; polygon_points_screen_x - 1 &1bd1 b9 34 10 LDA &1034,Y ; table_points_screen_y &1bd4 95 cc STA &cc,X ; polygon_points_screen_y - 1 &1bd6 a4 02 LDY &02 ; polygon_data_offset &1bd8 c8 INY &1bd9 ca DEX &1bda d0 ea BNE &1bc6 ; copy_polygon_points_loop &1bdc 68 PLA ; number of points &1bdd aa TAX &1bde 98 TYA &1bdf 48 PHA ; polygon_data_offset &1be0 8a TXA &1be1 20 ba 1d JSR &1dba ; plot_polygon &1be4 68 PLA ; polygon_data_offset &1be5 a8 TAY &1be6 c4 90 CPY &90 ; end_of_polygon_data_offset &1be8 90 c1 BCC &1bab ; plot_table_polygon_loop ; finished_plotting_table &1bea 24 6f BIT &6f ; sideways_ram_version # Negative if using sideways RAM &1bec 10 04 BPL &1bf2 ; no_snapshot_of_table &1bee 24 4f BIT &4f ; viewpoint_has_changed # Negative if viewpoint has changed &1bf0 10 05 BPL &1bf7 ; consider_using_snapshot_of_table ; no_snapshot_of_table &1bf2 a9 01 LDA #&01 &1bf4 85 70 STA &70 ; sideways_ram_has_table_snapshot # Set to one to indicate snapshot needs creating &1bf6 60 RTS ; consider_using_snapshot_of_table &1bf7 a5 70 LDA &70 ; sideways_ram_has_table_snapshot # Negative if sideways RAM has snapshot of table &1bf9 30 07 BMI &1c02 ; leave &1bfb d0 03 BNE &1c00 ; skip_unbuffering # Non-zero if no snapshot of table in sideways RAM &1bfd 20 72 84 JSR &8472 ; unbuffer_screen_from_sideways_ram # Copy snapshot of table to screen ; skip_unbuffering &1c00 c6 70 DEC &70 ; sideways_ram_has_table_snapshot # Set to negative if sideways RAM has snapshot of table ; leave &1c02 60 RTS ; calculate_ball_screen_coordinates # Called with X = ball to update &1c03 8a TXA &1c04 48 PHA ; ball &1c05 bd 52 0f LDA &0f52,X ; balls_table_x_fraction &1c08 85 02 STA &02 ; world_x_fraction &1c0a bd 22 0f LDA &0f22,X ; balls_table_x &1c0d 85 03 STA &03 ; world_x &1c0f a9 93 LDA #&93 &1c11 85 04 STA &04 ; world_z_fraction &1c13 a9 fc LDA #&fc &1c15 85 05 STA &05 ; world_z &1c17 bd 62 0f LDA &0f62,X ; balls_table_y_fraction &1c1a 85 06 STA &06 ; world_y_fraction &1c1c bd 42 0f LDA &0f42,X ; balls_table_y &1c1f 85 07 STA &07 ; world_y &1c21 20 04 23 JSR &2304 ; transform_world_to_screen_coordinates &1c24 a2 6d LDX #&6d &1c26 a0 03 LDY #&03 &1c28 a5 07 LDA &07 ; screen_z &1c2a 20 ba 24 JSR &24ba ; divide_XY_by_A # Calculate A = screen_z / &036d &1c2d a8 TAY &1c2e 68 PLA ; ball &1c2f aa TAX &1c30 98 TYA &1c31 38 SEC &1c32 e9 02 SBC #&02 # to determine size of ball &1c34 b0 02 BCS &1c38 ; skip_floor &1c36 a9 00 LDA #&00 ; skip_floor &1c38 cd 83 01 CMP &0183 ; number_of_ball_sprites &1c3b 90 05 BCC &1c42 ; skip_ceiling &1c3d ad 83 01 LDA &0183 ; number_of_ball_sprites &1c40 e9 01 SBC #&01 ; skip_ceiling &1c42 9d c2 0f STA &0fc2,X ; balls_screen_size &1c45 a5 07 LDA &07 ; screen_z &1c47 9d 12 0f STA &0f12,X ; balls_screen_z &1c4a a5 08 LDA &08 ; screen_x_fraction &1c4c 38 SEC &1c4d e5 62 SBC &62 ; minimum_screen_x_fraction &1c4f a8 TAY &1c50 a5 09 LDA &09 ; screen_x &1c52 e5 63 SBC &63 ; minimum_screen_x &1c54 c0 80 CPY #&80 # Multiply by two, keeping sign &1c56 2a ROL A &1c57 85 0c STA &0c ; centre_x # centre_x = (screen_x - minimum_screen_x) * 2 &1c59 bc c2 0f LDY &0fc2,X ; balls_screen_size &1c5c b9 dd 07 LDA &07dd,Y ; ball_sprite_widths_in_pixels &1c5f 4a LSR A &1c60 49 ff EOR #&ff &1c62 38 SEC &1c63 65 0c ADC &0c ; centre_x &1c65 9d b2 0f STA &0fb2,X ; balls_screen_x # ball_screen_x = centre_x - sprite_width / 2 &1c68 b9 f9 07 LDA &07f9,Y ; ball_sprite_heights_in_rows &1c6b 4a LSR A &1c6c 49 ff EOR #&ff &1c6e 18 CLC &1c6f 69 01 ADC #&01 &1c71 18 CLC &1c72 65 0b ADC &0b ; screen_y &1c74 9d 02 0f STA &0f02,X ; balls_screen_y # ball_screen_y = 1 + screen_y - sprite_height / 2 &1c77 60 RTS ; update_screen &1c78 20 a4 1a JSR &1aa4 ; calculate_table_and_balls_screen_coordinates &1c7b a5 28 LDA &28 ; vsync_counter &1c7d 29 1f AND #&1f &1c7f c9 08 CMP #&08 &1c81 66 77 ROR &77 ; flashing_ball_flag # Set top bit 24 v-syncs out of 32 &1c83 20 f6 1f JSR &1ff6 ; sort_balls_by_z_order &1c86 24 4f BIT &4f ; viewpoint_has_changed # Negative if viewpoint has changed &1c88 30 0e BMI &1c98 ; skip_using_snapshot &1c8a 24 6f BIT &6f ; sideways_ram_version # Negative if using sideways RAM &1c8c 10 0a BPL &1c98 ; skip_using_snapshot &1c8e a5 70 LDA &70 ; sideways_ram_has_table_snapshot # Negative if sideways RAM has snapshot of table &1c90 30 09 BMI &1c9b ; skip_plotting_background # Zero if update is creating snapshot &1c92 d0 04 BNE &1c98 ; use_regular_screen_buffer # One if snapshot needs creating ; create_snapshot_of_table &1c94 a9 91 LDA #&91 ; &9100 = sideways_ram_screen_buffer &1c96 85 a0 STA &a0 ; background_screen_address_high ; use_regular_screen_buffer &1c98 20 cb 1c JSR &1ccb ; plot_background ; skip_plotting_background &1c9b 20 9a 1b JSR &1b9a ; plot_table &1c9e 20 98 2a JSR &2a98 ; plot_status_bar &1ca1 20 e4 20 JSR &20e4 ; plot_balls &1ca4 a9 00 LDA #&00 &1ca6 85 4f STA &4f ; viewpoint_has_changed # Set to zero to indicate viewpoint doesn't need recalculating &1ca8 4c dd 22 JMP &22dd ; calculate_crtc_start_address ; background_pixel_values &1cab fa ff f5 0f ; 3232 3333 2323 1111 &1caf fa ff f5 0f &1cb3 fa ff f5 0f &1cb7 fa ff f5 0f &1cbb fa ff f5 0f &1cbf fa ff f5 0f &1cc3 fa ff f5 0f &1cc7 fa ff f5 0f ; plot_background &1ccb a4 a0 LDY &a0 ; background_screen_address_high &1ccd 84 0d STY &0d ; background_screen_addresses_high # + &0000 &1ccf 84 0f STY &0f ; background_screen_addresses_high + 2 # + &0040 &1cd1 84 11 STY &11 ; background_screen_addresses_high + 4 # + &0080 &1cd3 84 13 STY &13 ; background_screen_addresses_high + 6 # + &00c0 &1cd5 c8 INY &1cd6 84 15 STY &15 ; background_screen_addresses_high + 8 # + &0100 &1cd8 a9 40 LDA #&40 &1cda 85 0e STA &0e ; background_screen_addresses_low + 2 &1cdc a9 80 LDA #&80 &1cde 85 10 STA &10 ; background_screen_addresses_low + 4 &1ce0 a9 c0 LDA #&c0 &1ce2 85 12 STA &12 ; background_screen_addresses_low + 6 &1ce4 a2 00 LDX #&00 &1ce6 86 0c STX &0c ; background_screen_addresses_low &1ce8 86 14 STX &14 ; background_screen_addresses_low + 8 &1cea a9 2a LDA #&2a &1cec 38 SEC &1ced e5 2f SBC &2f ; player_viewpoint_vertical_rotation &1cef 0a ASL A &1cf0 8d 08 1d STA &1d08 ; horizon_row ; wait_for_buffer_swap &1cf3 24 40 BIT &40 ; crtc_start_address_high # Positive if buffer is waiting to be swapped &1cf5 10 fc BPL &1cf3 ; wait_for_buffer_swap &1cf7 8a TXA &1cf8 29 07 AND #&07 &1cfa 4c 07 1d JMP &1d07 ; plot_background_group_loop ; plot_background_row_loop &1cfd e6 0c INC &0c ; background_screen_addresses_low &1cff e6 0e INC &0e ; background_screen_addresses_low + 2 &1d01 e6 10 INC &10 ; background_screen_addresses_low + 4 &1d03 e6 12 INC &12 ; background_screen_addresses_low + 6 &1d05 e6 14 INC &14 ; background_screen_addresses_low + 8 ; plot_background_group_loop &1d07 e0 00 CPX #&00 # actually CPX horizon_row # Carry set if below horizon &1d09 2a ROL A &1d0a a8 TAY &1d0b b9 ab 1c LDA &1cab,Y ; background_pixel_values &1d0e a0 00 LDY #&00 # Unrolled loop plots entire row &1d10 91 0c STA (&0c),Y ; background_screen_addresses &1d12 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d14 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d16 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d18 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d1a a0 08 LDY #&08 &1d1c 91 0c STA (&0c),Y ; background_screen_addresses &1d1e 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d20 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d22 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d24 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d26 a0 10 LDY #&10 &1d28 91 0c STA (&0c),Y ; background_screen_addresses &1d2a 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d2c 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d2e 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d30 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d32 a0 18 LDY #&18 &1d34 91 0c STA (&0c),Y ; background_screen_addresses &1d36 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d38 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d3a 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d3c 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d3e a0 20 LDY #&20 &1d40 91 0c STA (&0c),Y ; background_screen_addresses &1d42 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d44 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d46 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d48 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d4a a0 28 LDY #&28 &1d4c 91 0c STA (&0c),Y ; background_screen_addresses &1d4e 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d50 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d52 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d54 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d56 a0 30 LDY #&30 &1d58 91 0c STA (&0c),Y ; background_screen_addresses &1d5a 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d5c 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d5e 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d60 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d62 a0 38 LDY #&38 &1d64 91 0c STA (&0c),Y ; background_screen_addresses &1d66 91 0e STA (&0e),Y ; background_screen_addresses + 2 &1d68 91 10 STA (&10),Y ; background_screen_addresses + 4 &1d6a 91 12 STA (&12),Y ; background_screen_addresses + 6 &1d6c 91 14 STA (&14),Y ; background_screen_addresses + 8 &1d6e e8 INX # Move down a row &1d6f 8a TXA &1d70 29 07 AND #&07 &1d72 d0 89 BNE &1cfd ; plot_background_row_loop &1d74 e4 5f CPX &5f ; screen_height_in_rows &1d76 b0 41 BCS &1db9 ; leave &1d78 a8 TAY &1d79 a5 0c LDA &0c ; background_screen_addresses_low # Move down a group &1d7b 69 39 ADC #&39 &1d7d 85 0c STA &0c ; background_screen_addresses_low &1d7f a5 0d LDA &0d ; background_screen_addresses_high &1d81 69 01 ADC #&01 &1d83 85 0d STA &0d ; background_screen_addresses_high &1d85 a5 0e LDA &0e ; background_screen_addresses_low + 2 &1d87 69 39 ADC #&39 &1d89 85 0e STA &0e ; background_screen_addresses_low + 2 &1d8b a5 0f LDA &0f ; background_screen_addresses_high + 2 &1d8d 69 01 ADC #&01 &1d8f 85 0f STA &0f ; background_screen_addresses_high + 2 &1d91 a5 10 LDA &10 ; background_screen_addresses_low + 4 &1d93 69 39 ADC #&39 &1d95 85 10 STA &10 ; background_screen_addresses_low + 4 &1d97 a5 11 LDA &11 ; background_screen_addresses_high + 4 &1d99 69 01 ADC #&01 &1d9b 85 11 STA &11 ; background_screen_addresses_high + 4 &1d9d a5 12 LDA &12 ; background_screen_addresses_low + 6 &1d9f 69 39 ADC #&39 &1da1 85 12 STA &12 ; background_screen_addresses_low + 6 &1da3 a5 13 LDA &13 ; background_screen_addresses_high + 6 &1da5 69 01 ADC #&01 &1da7 85 13 STA &13 ; background_screen_addresses_high + 6 &1da9 a5 14 LDA &14 ; background_screen_addresses_low + 8 &1dab 69 39 ADC #&39 &1dad 85 14 STA &14 ; background_screen_addresses_low + 8 &1daf a5 15 LDA &15 ; background_screen_addresses_high + 8 &1db1 69 01 ADC #&01 &1db3 85 15 STA &15 ; background_screen_addresses_high + 8 &1db5 98 TYA &1db6 4c 07 1d JMP &1d07 ; plot_background_group_loop ; leave &1db9 60 RTS ; plot_polygon # Called with A = number of points in polygon &1dba 85 ba STA &ba ; number_of_points &1dbc aa TAX &1dbd a0 ff LDY #&ff &1dbf 84 bc STY &bc ; minimum_screen_y &1dc1 c8 INY ; 0 &1dc2 84 be STY &be ; maximum_screen_y &1dc4 ca DEX ; find_maximum_and_minimum_screen_y_loop &1dc5 b5 cd LDA &cd,X ; polygon_points_screen_y &1dc7 c5 bc CMP &bc ; minimum_screen_y &1dc9 b0 04 BCS &1dcf ; not_new_minimum &1dcb 85 bc STA &bc ; minimum_screen_y, polygon_row &1dcd 86 bf STX &bf ; first_point ; not_new_minimum &1dcf c5 be CMP &be ; maximum_screen_y &1dd1 90 02 BCC &1dd5 ; not_new_maximum &1dd3 85 be STA &be ; maximum_screen_y ; not_new_maximum &1dd5 ca DEX &1dd6 10 ed BPL &1dc5 ; find_maximum_and_minimum_screen_y_loop &1dd8 38 SEC &1dd9 a5 be LDA &be ; maximum_screen_y &1ddb e5 bc SBC &bc ; minimum_screen_y &1ddd f0 2c BEQ &1e0b ; leave # Leave if polygon doesn't occupy any rows &1ddf 85 be STA &be ; rows_to_fill &1de1 e6 be INC &be ; rows_to_fill &1de3 a6 bf LDX &bf ; first_point &1de5 86 c0 STX &c0 ; second_point &1de7 b5 c5 LDA &c5,X ; polygon_points_screen_x &1de9 85 bb STA &bb ; first_x &1deb 85 bd STA &bd ; second_x &1ded 20 7d 1f JSR &1f7d ; set_first_edge_gradient &1df0 20 b5 1f JSR &1fb5 ; set_second_edge_gradient &1df3 24 9f BIT &9f ; suppress_plotting_check &1df5 30 40 BMI &1e37 ; plot_polygon_row_loop # If top bit set, always plot polygon ; consider_if_polygon_should_be_plotted &1df7 a5 bd LDA &bd ; second_x # Second edge runs through points 0, n - 1, n - 2, etc &1df9 c5 bb CMP &bb ; first_x # First edge runs through points 0, 1, 2, etc &1dfb f0 04 BEQ &1e01 ; consider_edge_directions &1dfd 90 0c BCC &1e0b ; leave # Don't plot polygon if points run clockwise &1dff b0 36 BCS &1e37 ; plot_polygon_row_loop # Always branches ; consider_edge_directions &1e01 ad 59 1f LDA &1f59 ; second_direction_instruction # DEX = &ca, INX = &e8 &1e04 cd 43 1f CMP &1f43 ; first_direction_instruction # Carry set if second edge increasing, first decreasing &1e07 f0 06 BEQ &1e0f ; edges_slope_in_same_direction &1e09 b0 2c BCS &1e37 ; plot_polygon_row_loop # Plot polygon if points are anticlockwise ; leave &1e0b 60 RTS ; to_move_along_first_edge &1e0c 4c 36 1f JMP &1f36 ; move_along_first_edge ; edges_slope_in_same_direction &1e0f ae 3e 1f LDX &1f3e ; first_gradient_x &1e12 ac 5b 1f LDY &1f5b ; second_gradient_y &1e15 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &1e18 84 0d STY &0d ; first_x_times_second_y # Calculate first_gradient_x * second_gradient_y &1e1a 86 0c STX &0c ; first_x_times_second_y_fraction &1e1c ae 54 1f LDX &1f54 ; second_gradient_x &1e1f ac 45 1f LDY &1f45 ; first_gradient_y &1e22 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &1e25 e4 0c CPX &0c ; first_x_times_second_y_fraction # Compare to second_gradient_x * first_gradient_y &1e27 98 TYA &1e28 e5 0d SBC &0d ; first_x_times_second_y &1e2a 6a ROR A # Put sign of result into top bit &1e2b ae 59 1f LDX &1f59 ; second_direction_instruction &1e2e e0 e8 CPX #&e8 ; INX &1e30 f0 02 BEQ &1e34 ; skip_inversion &1e32 49 80 EOR #&80 # Invert if edges slope from right to left going down ; skip_inversion &1e34 0a ASL A # Put sign of result into carry &1e35 90 d4 BCC &1e0b ; leave # Don't plot polygon if second edge slopes more to side ; plot_polygon_row_loop # than down than first edge, i.e. points run clockwise &1e37 a5 5f LDA &5f ; screen_height_in_rows &1e39 f0 04 BEQ &1e3f ; skip_check &1e3b c5 bc CMP &bc ; polygon_row &1e3d 90 cc BCC &1e0b ; leave ; skip_check &1e3f a4 bc LDY &bc ; polygon_row &1e41 c4 60 CPY &60 ; screen_top_row &1e43 90 c7 BCC &1e0c ; to_move_along_first_edge &1e45 a6 bb LDX &bb ; first_x &1e47 a5 bd LDA &bd ; second_x &1e49 e4 bd CPX &bd ; second_x &1e4b 90 03 BCC &1e50 ; skip_swap &1e4d 8a TXA &1e4e a6 bd LDX &bd ; second_x ; skip_swap &1e50 a4 5e LDY &5e ; right_clip_x &1e52 f0 09 BEQ &1e5d ; skip_clipping_to_right &1e54 e4 5e CPX &5e ; right_clip_x &1e56 b0 b4 BCS &1e0c ; to_move_along_first_edge &1e58 c5 5e CMP &5e ; right_clip_x &1e5a 90 01 BCC &1e5d ; skip_clipping_to_right &1e5c 98 TYA ; skip_clipping_to_right &1e5d c5 5d CMP &5d ; left_clip_x &1e5f 90 ab BCC &1e0c ; to_move_along_first_edge &1e61 e4 5d CPX &5d ; left_clip_x &1e63 b0 02 BCS &1e67 ; skip_clipping_to_left &1e65 a6 5d LDX &5d ; left_clip_x ; skip_clipping_to_left &1e67 a8 TAY &1e68 8a TXA &1e69 38 SEC &1e6a e5 61 SBC &61 ; plotting_x_offset &1e6c aa TAX &1e6d 85 64 STA &64 ; fill_row_start_x &1e6f 98 TYA &1e70 38 SEC &1e71 e5 61 SBC &61 ; plotting_x_offset &1e73 c5 64 CMP &64 ; fill_row_start_x &1e75 f0 95 BEQ &1e0c ; to_move_along_first_edge &1e77 48 PHA &1e78 38 SEC &1e79 09 03 ORA #&03 &1e7b e5 64 SBC &64 ; fill_row_start_x &1e7d 4a LSR A &1e7e 4a LSR A &1e7f 85 65 STA &65 ; fill_row_length &1e81 a5 bc LDA &bc ; polygon_row # Choose pixel value for fill depending on row &1e83 4a LSR A &1e84 a5 69 LDA &69 ; polygon_fill_even_pixel_value &1e86 90 02 BCC &1e8a ; set_fill_pixel_value &1e88 a5 6a LDA &6a ; polygon_fill_odd_pixel_value ; set_fill_pixel_value &1e8a 85 66 STA &66 ; fill_pixel_value &1e8c a4 bc LDY &bc ; polygon_row ; calculate_row_address # &1e8e - &1ea4 is replaced in sideways RAM version &1e8e 98 TYA # Calculate screen address for start of row &1e8f 29 07 AND #&07 &1e91 85 0c STA &0c ; row_in_group &1e93 98 TYA &1e94 29 f8 AND #&f8 &1e96 4a LSR A &1e97 4a LSR A &1e98 a8 TAY &1e99 8a TXA &1e9a 29 7c AND #&7c &1e9c 0a ASL A &1e9d 79 ef 37 ADC &37ef,Y ; group_offsets_table &1ea0 05 0c ORA &0c ; row_in_group &1ea2 85 67 STA &67 ; fill_screen_address_low &1ea4 b9 f0 37 LDA &37f0,Y ; group_offsets_table + 1 &1ea7 65 a0 ADC &a0 ; background_screen_address_high &1ea9 e0 80 CPX #&80 &1eab 69 00 ADC #&00 &1ead 85 68 STA &68 ; fill_screen_address_high ; consider_left_of_row &1eaf a5 64 LDA &64 ; fill_row_start_x &1eb1 29 03 AND #&03 &1eb3 f0 1b BEQ &1ed0 ; skip_filling_partial_byte_to_left # Is the left of the row byte aligned? &1eb5 c6 65 DEC &65 ; fill_row_length &1eb7 30 39 BMI &1ef2 ; fill_single_byte_row # Does it span more than one byte? &1eb9 aa TAX &1eba a0 00 LDY #&00 &1ebc b1 67 LDA (&67),Y ; fill_screen_address &1ebe 45 66 EOR &66 ; fill_pixel_value &1ec0 3d 0f 36 AND &360f,X ; left_fill_masks &1ec3 45 66 EOR &66 ; fill_pixel_value &1ec5 91 67 STA (&67),Y ; fill_screen_address # Fill partial byte to left &1ec7 18 CLC &1ec8 a5 67 LDA &67 ; fill_screen_address_low &1eca 69 08 ADC #&08 # Move four pixels right &1ecc 85 67 STA &67 ; fill_screen_address_low &1ece b0 1e BCS &1eee ; next_page # Returns at &1ed0 ; skip_filling_partial_byte_to_left &1ed0 a5 65 LDA &65 ; fill_row_length &1ed2 f0 47 BEQ &1f1b ; consider_right_edge_of_row # Is there anything in the middle to fill? ; consider_middle_of_row &1ed4 38 SEC &1ed5 a9 20 LDA #&20 &1ed7 e5 65 SBC &65 ; fill_row_length &1ed9 b0 36 BCS &1f11 ; fill_remaining_middle_of_row # Is the middle larger than 32 bytes / 128 pixels? &1edb 49 ff EOR #&ff &1edd 69 01 ADC #&01 &1edf 85 65 STA &65 ; fill_row_length &1ee1 a5 66 LDA &66 ; fill_pixel_value &1ee3 20 00 07 JSR &0700 ; fill_line_routine # Fill a 32 byte / 128 pixel section of the middle &1ee6 e6 68 INC &68 ; fill_screen_address_high &1ee8 4c d4 1e JMP &1ed4 ; consider_middle_of_row ; to_move_along_first_edge # Unused &1eeb 4c 36 1f JMP &1f36 ; move_along_first_edge ; next_page &1eee e6 68 INC &68 ; fill_screen_address_high &1ef0 b0 de BCS &1ed0 ; skip_filling_partial_byte_to_left # Always branches ; fill_single_byte_row # Row starts and ends in same byte &1ef2 8a TXA &1ef3 29 03 AND #&03 &1ef5 aa TAX &1ef6 68 PLA &1ef7 29 03 AND #&03 &1ef9 a8 TAY &1efa bd 0f 36 LDA &360f,X ; left_fill_masks &1efd 19 13 36 ORA &3613,Y ; right_fill_masks &1f00 85 0c STA &0c ; combined_left_and_right_mask &1f02 a0 00 LDY #&00 &1f04 b1 67 LDA (&67),Y ; fill_screen_address &1f06 45 66 EOR &66 ; fill_pixel_value &1f08 25 0c AND &0c ; combined_left_and_right_mask &1f0a 45 66 EOR &66 ; fill_pixel_value &1f0c 91 67 STA (&67),Y ; fill_screen_address # Fill pixels in that byte &1f0e 4c 36 1f JMP &1f36 ; move_along_first_edge ; fill_remaining_middle_of_row &1f11 0a ASL A &1f12 0a ASL A &1f13 8d 19 1f STA &1f19 ; fill_line_routine_offset &1f16 a5 66 LDA &66 ; fill_pixel_value &1f18 20 00 07 JSR &0700 ; fill_line_routine # actually JSR fill_line_routine + fill_line_routine_offset # Fill remaining section of the middle ; consider_right_edge_of_row &1f1b 68 PLA &1f1c 29 03 AND #&03 &1f1e f0 16 BEQ &1f36 ; skip_filling_partial_byte_to_right # Is the right of the row byte aligned? &1f20 aa TAX &1f21 a5 65 LDA &65 ; fill_row_length &1f23 0a ASL A &1f24 0a ASL A &1f25 0a ASL A &1f26 a8 TAY &1f27 90 02 BCC &1f2b ; skip_page &1f29 e6 68 INC &68 ; fill_screen_address_high ; skip_page &1f2b b1 67 LDA (&67),Y ; fill_screen_address &1f2d 45 66 EOR &66 ; fill_pixel_value &1f2f 3d 13 36 AND &3613,X ; right_fill_masks &1f32 45 66 EOR &66 ; fill_pixel_value &1f34 91 67 STA (&67),Y ; fill_screen_address # Fill partial byte to right ; skip_filling_partial_byte_to_right ; move_along_first_edge &1f36 c6 c1 DEC &c1 ; rows_remaining_on_first_edge &1f38 f0 32 BEQ &1f6c ; end_of_first_edge &1f3a 38 SEC &1f3b a5 c3 LDA &c3 ; first_x_fraction &1f3d e9 00 SBC #&00 # actually SBC first_gradient_x &1f3f b0 09 BCS &1f4a ; skip_changing_first_x &1f41 a6 bb LDX &bb ; first_x ; first_direction_instruction # Set at &1fa9; move first edge left or right &1f43 ca DEX if first edge slopes from right to left going down # or INX if first edge slopes from left to right going down &1f44 69 00 ADC #&00 # actually ADC first_gradient_y &1f46 90 fb BCC &1f43 ; first_direction_instruction &1f48 86 bb STX &bb ; first_x ; skip_changing_first_x &1f4a 85 c3 STA &c3 ; first_x_fraction ; move_along_second_edge &1f4c c6 c2 DEC &c2 ; rows_remaining_on_second_edge &1f4e f0 22 BEQ &1f72 ; end_of_second_edge &1f50 38 SEC &1f51 a5 c4 LDA &c4 ; second_x_fraction &1f53 e9 00 SBC #&00 # actually SBC second_gradient_x &1f55 b0 09 BCS &1f60 ; skip_changing_second_x &1f57 a6 bd LDX &bd ; second_x ; second_direction_instruction # Set at &1fa9; move second edge left or right &1f59 ca DEX if second edge slopes from right to left going down # or INX if second edge slopes from left to right going down &1f5a 69 00 ADC #&00 # actually ADC second_gradient_y &1f5c 90 fb BCC &1f59 ; second_direction_instruction &1f5e 86 bd STX &bd ; second_x ; skip_changing_second_x &1f60 85 c4 STA &c4 ; second_x_fraction ; consider_next_row &1f62 e6 bc INC &bc ; polygon_row &1f64 c6 be DEC &be ; rows_to_fill &1f66 f0 03 BEQ &1f6b ; leave &1f68 4c 37 1e JMP &1e37 ; plot_polygon_row_loop ; leave &1f6b 60 RTS ; end_of_first_edge &1f6c 20 7d 1f JSR &1f7d ; set_first_edge_gradient &1f6f 4c 4c 1f JMP &1f4c ; move_along_second_edge ; end_of_second_edge &1f72 20 b5 1f JSR &1fb5 ; set_second_edge_gradient &1f75 4c 62 1f JMP &1f62 ; consider_next_row ; move_to_next_point_on_first_edge &1f78 b5 c5 LDA &c5,X ; polygon_points_screen_x &1f7a 85 bb STA &bb ; first_x &1f7c 2c a6 bf BIT &bfa6 ; set_first_edge_gradient #1f7d LDX &bf ; first_point &1f7f e8 INX # Consider the next point around the polygon &1f80 e4 ba CPX &ba ; number_of_points &1f82 d0 02 BNE &1f86 ; skip_wraparound &1f84 a2 00 LDX #&00 ; skip_wraparound &1f86 86 bf STX &bf ; first_point &1f88 38 SEC &1f89 b5 cd LDA &cd,X ; polygon_points_screen_y &1f8b e5 bc SBC &bc ; polygon_row &1f8d f0 e9 BEQ &1f78 ; move_to_next_point_on_first_edge # If the fill has reached it, use that as first point &1f8f 8d 45 1f STA &1f45 ; first_gradient_y &1f92 85 c1 STA &c1 ; rows_remaining_on_first_edge &1f94 4a LSR A &1f95 85 c3 STA &c3 ; first_x_fraction &1f97 a0 e8 LDY #&e8 ; INX &1f99 38 SEC &1f9a b5 c5 LDA &c5,X ; polygon_points_screen_x &1f9c e5 bb SBC &bb ; first_x &1f9e b0 06 BCS &1fa6 ; set_subtract_first &1fa0 49 ff EOR #&ff &1fa2 69 01 ADC #&01 &1fa4 a0 ca LDY #&ca ; DEX ; set_subtract_first &1fa6 8d 3e 1f STA &1f3e ; first_gradient_x &1fa9 8c 43 1f STY &1f43 ; first_direction_instruction &1fac e6 c1 INC &c1 ; rows_remaining_on_first_edge &1fae 60 RTS ; move_to_next_point_on_second_edge &1faf b5 c5 LDA &c5,X ; polygon_points_screen_x &1fb1 85 bd STA &bd ; second_x &1fb3 86 c0 STX &c0 ; second_point ; set_second_edge_gradient &1fb5 a6 c0 LDX &c0 ; second_point &1fb7 d0 02 BNE &1fbb ; skip_wraparound &1fb9 a6 ba LDX &ba ; number_of_points ; skip_wraparound &1fbb ca DEX &1fbc 86 c0 STX &c0 ; second_point &1fbe 38 SEC &1fbf b5 cd LDA &cd,X ; polygon_points_screen_y &1fc1 e5 bc SBC &bc ; polygon_row &1fc3 f0 ea BEQ &1faf ; move_to_next_point_on_second_edge &1fc5 8d 5b 1f STA &1f5b ; second_gradient_y &1fc8 85 c2 STA &c2 ; rows_remaining_on_second_edge &1fca 4a LSR A &1fcb 85 c4 STA &c4 ; second_x_fraction &1fcd a0 e8 LDY #&e8 ; INX &1fcf 38 SEC &1fd0 b5 c5 LDA &c5,X ; polygon_points_screen_x &1fd2 e5 bd SBC &bd ; second_x &1fd4 b0 06 BCS &1fdc ; set_subtract_second &1fd6 49 ff EOR #&ff &1fd8 69 01 ADC #&01 &1fda a0 ca LDY #&ca ; DEX ; set_subtract_second &1fdc 8d 54 1f STA &1f54 ; second_gradient_x &1fdf 8c 59 1f STY &1f59 ; second_direction_instruction &1fe2 e6 c2 INC &c2 ; rows_remaining_on_second_edge &1fe4 60 RTS ; set_polygon_colour &1fe5 85 9f STA &9f ; suppress_plotting_check # Top bit set if polygon should always be plotted &1fe7 29 07 AND #&07 &1fe9 0a ASL A &1fea a8 TAY &1feb b9 17 36 LDA &3617,Y ; polygon_colours_pixel_values &1fee 85 69 STA &69 ; polygon_fill_even_pixel_value &1ff0 b9 18 36 LDA &3618,Y ; polygon_colours_pixel_values + 1 &1ff3 85 6a STA &6a ; polygon_fill_odd_pixel_value &1ff5 60 RTS ; sort_balls_by_z_order &1ff6 a2 00 LDX #&00 &1ff8 a0 0f LDY #&0f ; BALL_LAST ; populate_list_of_balls_for_sorting_loop # Create a list of balls to be plotted &1ffa c4 a9 CPY &a9 ; focus_ball &1ffc d0 11 BNE &200f ; include_ball_if_present # Is this the focus ball? &1ffe 24 50 BIT &50 ; placing_ball # Negative if placing ball &2000 10 0d BPL &200f ; include_ball_if_present # If so, is it being placed? &2002 24 4c BIT &4c ; trick_state # Negative if playing trick &2004 30 09 BMI &200f ; include_ball_if_present &2006 a5 77 LDA &77 ; flashing_ball_flag # Negative for 24 v-syncs out of 32 &2008 59 e2 0e EOR &0ee2,Y ; balls_state # Negative if ball not present &200b 10 2e BPL &203b ; consider_next_ball # Hide present balls for 8 v-syncs, absent balls for 24 &200d 30 05 BMI &2014 ; include_ball # Always branches ; include_ball_if_present &200f b9 e2 0e LDA &0ee2,Y ; balls_state # Negative if ball not present &2012 30 27 BMI &203b ; consider_next_ball # Don't consider ball if ball not present ; include_ball &2014 b9 b2 0f LDA &0fb2,Y ; balls_screen_x &2017 c4 5e CPY &5e ; right_clip_x # Bug: Y = ball here &2019 b0 04 BCS &201f ; skip_checking_right_clip &201b c5 5e CMP &5e ; right_clip_x &201d b0 1c BCS &203b ; consider_next_ball # Don't include ball if beyond right of screen ; skip_checking_right_clip &201f 86 0c STX &0c ; ball_screen_x &2021 be c2 0f LDX &0fc2,Y ; balls_screen_size &2024 18 CLC &2025 7d dd 07 ADC &07dd,X ; ball_sprite_widths_in_pixels &2028 a6 0c LDX &0c ; ball_screen_x &202a c5 5d CMP &5d ; left_clip_x &202c 90 0d BCC &203b ; consider_next_ball # Don't include ball if beyond left of screen &202e f0 0b BEQ &203b ; consider_next_ball &2030 b9 12 0f LDA &0f12,Y ; balls_screen_z # Otherwise, add ball to list &2033 9d 02 10 STA &1002,X ; z_ordered_balls_screen_z &2036 98 TYA &2037 9d f2 0f STA &0ff2,X ; z_ordered_balls_number &203a e8 INX ; consider_next_ball &203b 88 DEY &203c 10 bc BPL &1ffa ; populate_list_of_balls_for_sorting_loop &203e 86 24 STX &24 ; number_of_z_ordered_balls &2040 a2 00 LDX #&00 &2042 a4 24 LDY &24 ; number_of_z_ordered_balls &2044 f0 04 BEQ &204a ; leave &2046 88 DEY &2047 4c 79 20 JMP &2079 ; recursive_sort ; leave &204a 60 RTS ; leave_after_restoring_sort_end &204b 85 43 STA &43 ; sort_end &204d 60 RTS ; store_saved_ball_in_slot_Y # If first ball in range had highest screen_z, &204e a5 0c LDA &0c ; saved_ball_number &2050 99 f2 0f STA &0ff2,Y ; z_ordered_balls_number # put it at the end of the range &2053 a5 46 LDA &46 ; saved_ball_screen_z &2055 99 02 10 STA &1002,Y ; z_ordered_balls_screen_z &2058 8a TXA &2059 4c 67 20 JMP &2067 ; continue_after_storing_saved_ball_ball ; store_saved_ball_ball_in_slot_X # If first ball in range had lowest screen_z, &205c a5 0c LDA &0c ; saved_ball_number &205e 9d f2 0f STA &0ff2,X ; z_ordered_balls_number # put it at the start of the range &2061 a5 46 LDA &46 ; saved_ball_screen_z &2063 9d 02 10 STA &1002,X ; z_ordered_balls_screen_z &2066 98 TYA ; continue_after_storing_saved_ball_ball &2067 a6 42 LDX &42 ; sort_start &2069 a8 TAY &206a f0 06 BEQ &2072 ; skip_recursive_sort &206c 48 PHA ; tmp_a &206d 88 DEY &206e 20 79 20 JSR &2079 ; recursive_sort &2071 68 PLA ; tmp_a ; skip_recursive_sort &2072 aa TAX &2073 e8 INX &2074 a4 43 LDY &43 ; sort_end &2076 68 PLA ; previous sort_end &2077 85 43 STA &43 ; sort_end ; recursive_sort # Called with X = first ball, Y = last ball + 1 &2079 a5 43 LDA &43 ; sort_end &207b 84 43 STY &43 ; sort_end &207d e4 43 CPX &43 ; sort_end &207f b0 ca BCS &204b ; leave_after_restoring_sort_end # Leave if there's nothing to be sorted &2081 86 42 STX &42 ; sort_start &2083 48 PHA ; previous sort_end &2084 c8 INY # Will be decreased on first iteration of sort_loop &2085 bd f2 0f LDA &0ff2,X ; z_ordered_balls_number # Store first ball in range &2088 85 0c STA &0c ; saved_ball_number &208a bd 02 10 LDA &1002,X ; z_ordered_balls_screen_z &208d 85 46 STA &46 ; saved_ball_screen_z ; sort_range_loop &208f a5 46 LDA &46 ; saved_ball_screen_z &2091 8e 96 20 STX &2096 ; start_of_range ; find_better_ball_from_end_of_range_loop # Moving backwards from the end of the range, &2094 88 DEY &2095 c0 00 CPY #&00 # actually CPY start_of_range &2097 f0 c3 BEQ &205c ; store_saved_ball_ball_in_slot_X # and stopping at the start of the range, &2099 d9 02 10 CMP &1002,Y ; z_ordered_balls_screen_z # look for a ball that has a lower screen_z &209c 90 f6 BCC &2094 ; find_better_ball_from_end_of_range_loop &209e f0 f4 BEQ &2094 ; find_better_ball_from_end_of_range_loop &20a0 b9 f2 0f LDA &0ff2,Y ; z_ordered_balls_number # Put that ball at the start of the range &20a3 9d f2 0f STA &0ff2,X ; z_ordered_balls_number &20a6 b9 02 10 LDA &1002,Y ; z_ordered_balls_screen_z &20a9 9d 02 10 STA &1002,X ; z_ordered_balls_screen_z &20ac a5 46 LDA &46 ; saved_ball_screen_z &20ae 8c b3 20 STY &20b3 ; end_of_range ; find_worse_ball_from_end_of_range_loop &20b1 e8 INX # Moving forwards from the start of the range, &20b2 e0 00 CPX #&00 # actually CPX end_of_range &20b4 f0 98 BEQ &204e ; store_saved_ball_ball_in_slot_Y # and stopping at the end of the range, &20b6 dd 02 10 CMP &1002,X ; z_ordered_balls_screen_z # look for a ball that has a higher screen_z &20b9 b0 f6 BCS &20b1 ; find_worse_ball_from_end_of_range_loop &20bb bd f2 0f LDA &0ff2,X ; z_ordered_balls_number # Put that ball in the lower one's place &20be 99 f2 0f STA &0ff2,Y ; z_ordered_balls_number &20c1 bd 02 10 LDA &1002,X ; z_ordered_balls_screen_z &20c4 99 02 10 STA &1002,Y ; z_ordered_balls_screen_z &20c7 4c 8f 20 JMP &208f ; sort_range_loop ; use_ball_sprite_variables &20ca b9 eb 07 LDA &07eb,Y ; ball_sprite_widths_in_bytes &20cd 85 25 STA &25 ; width_in_bytes &20cf b9 f9 07 LDA &07f9,Y ; ball_sprite_heights_in_rows &20d2 85 26 STA &26 ; rows_to_plot &20d4 b9 dd 07 LDA &07dd,Y ; ball_sprite_widths_in_pixels &20d7 85 56 STA &56 ; width_in_pixels &20d9 b9 c1 07 LDA &07c1,Y ; ball_sprite_addresses_low &20dc 85 1c STA &1c ; ball_sprite_address_low &20de b9 cf 07 LDA &07cf,Y ; ball_sprite_addresses_high &20e1 85 1d STA &1d ; ball_sprite_address_high &20e3 60 RTS ; plot_balls ; plot_balls_loop &20e4 c6 24 DEC &24 ; number_of_z_ordered_balls &20e6 30 29 BMI &2111 ; leave &20e8 a4 24 LDY &24 ; number_of_z_ordered_balls &20ea be f2 0f LDX &0ff2,Y ; z_ordered_balls_number &20ed 30 22 BMI &2111 ; leave # Should never branch &20ef bd b2 0f LDA &0fb2,X ; balls_screen_x &20f2 38 SEC &20f3 e5 61 SBC &61 ; plotting_x_offset &20f5 85 20 STA &20 ; ball_screen_x &20f7 bd 02 0f LDA &0f02,X ; balls_screen_y &20fa 85 21 STA &21 ; ball_screen_y &20fc bd df 37 LDA &37df,X ; balls_colour &20ff 0a ASL A &2100 0a ASL A &2101 0a ASL A &2102 8d 51 21 STA &2151 ; ball_colour_offset &2105 bc c2 0f LDY &0fc2,X ; balls_screen_size &2108 20 ca 20 JSR &20ca ; use_ball_sprite_variables &210b 20 12 21 JSR &2112 ; plot_ball &210e 4c e4 20 JMP &20e4 ; plot_balls_loop ; leave &2111 60 RTS ; plot_ball &2112 a5 56 LDA &56 ; width_in_pixels &2114 85 57 STA &57 ; width_in_pixels_after_clipping &2116 a5 20 LDA &20 ; ball_screen_x &2118 c9 a0 CMP #&a0 &211a 90 1e BCC &213a ; skip_clipping_to_left # Does the ball start beyond the left of the screen? &211c 29 fc AND #&fc &211e 85 0c STA &0c ; x_rounded_down_to_byte &2120 49 ff EOR #&ff &2122 4a LSR A &2123 4a LSR A &2124 38 SEC &2125 65 1c ADC &1c ; ball_sprite_address_low &2127 85 1c STA &1c ; ball_sprite_address_low &2129 90 02 BCC &212d ; skip_page &212b e6 1d INC &1d ; ball_sprite_address_high ; skip_page &212d a5 56 LDA &56 ; width_in_pixels &212f 18 CLC &2130 65 0c ADC &0c ; x_rounded_down_to_byte &2132 85 57 STA &57 ; width_in_pixels_after_clipping &2134 a5 20 LDA &20 ; ball_screen_x &2136 29 03 AND #&03 &2138 85 20 STA &20 ; ball_screen_x ; skip_clipping_to_left &213a a5 20 LDA &20 ; ball_screen_x &213c 18 CLC &213d 65 57 ADC &57 ; width_in_pixels_after_clipping &213f c9 a0 CMP #&a0 &2141 90 08 BCC &214b ; skip_clipping_to_right # Does the ball end beyond the right of the screen? &2143 e9 a0 SBC #&a0 &2145 49 ff EOR #&ff &2147 65 57 ADC &57 ; width_in_pixels_after_clipping &2149 85 57 STA &57 ; width_in_pixels_after_clipping ; skip_clipping_to_right &214b a5 20 LDA &20 ; ball_screen_x &214d 29 03 AND #&03 # Use pixel in byte &214f 0a ASL A &2150 09 00 ORA #&00 # actually ORA ball_colour_offset # and colour of ball to choose colour table &2152 aa TAX &2153 a0 c9 LDY #&c9 ; CMP #&.. # Used as dummy instruction to skip branch at &221b &2155 bd a8 37 LDA &37a8,X ; even_colour_table_addresses &2158 85 02 STA &02 ; even_colour_table_address_low &215a bd a9 37 LDA &37a9,X ; even_colour_table_addresses + 1 &215d 85 03 STA &03 ; even_colour_table_address_high &215f e0 08 CPX #&08 ; BALL_TYPE_DITHERED * 8 # If the ball is a solid colour, &2161 90 17 BCC &217a ; set_choose_row_routine_instruction &2163 e0 10 CPX #&10 ; BALL_TYPE_CUE * 8 # always use even row plotting routine &2165 b0 13 BCS &217a ; set_choose_row_routine_instruction ; is_dithered &2167 bd c0 37 LDA &37c0,X ; odd_colour_table_addresses - 8 &216a 85 04 STA &04 ; odd_colour_table_address_low &216c bd c1 37 LDA &37c1,X ; odd_colour_table_addresses - 8 + 1 &216f 85 05 STA &05 ; odd_colour_table_address_high &2171 a0 90 LDY #&90 ; BCC # Otherwise, alternate between even and odd routines &2173 a5 20 LDA &20 ; ball_screen_x &2175 4a LSR A &2176 b0 02 BCS &217a ; set_choose_row_routine_instruction # Keep dithering constant when sprites shifted &2178 a0 b0 LDY #&b0 ; BCS ; set_choose_row_routine_instruction &217a 8c 1b 22 STY &221b ; plot_row_branch_instruction &217d a5 57 LDA &57 ; width_in_pixels_after_clipping &217f 18 CLC &2180 69 03 ADC #&03 # Round up to the nearest byte &2182 4a LSR A &2183 4a LSR A &2184 aa TAX &2185 a5 20 LDA &20 ; ball_screen_x &2187 18 CLC &2188 65 57 ADC &57 ; width_in_pixels_after_clipping &218a 29 03 AND #&03 &218c d0 01 BNE &218f ; not_aligned &218e ca DEX ; not_aligned &218f 86 2d STX &2d ; width_in_bytes_after_clipping # Variable is unused &2191 8a TXA # Use width in bytes after clipping &2192 0a ASL A # to determine entry point into plot routines &2193 a8 TAY &2194 b9 d0 37 LDA &37d0,Y ; plot_row_routine_addresses &2197 85 58 STA &58 ; plot_even_row_address_low &2199 69 5d ADC #&5d ; &005d = plot_row_of_ball_*_odd - plot_row_of_ball_*_even &219b 85 5a STA &5a ; plot_odd_row_address_low &219d b9 d1 37 LDA &37d1,Y ; plot_row_routine_addresses + 1 &21a0 85 59 STA &59 ; plot_even_row_address_high &21a2 69 00 ADC #&00 &21a4 85 5b STA &5b ; plot_odd_row_address_high &21a6 bc da 37 LDY &37da,X ; plot_row_routines_first_colour_table_address_offsets &21a9 38 SEC ; poke_even_and_odd_colour_table_addresses_loop # For each of the bytes that will be plotted, &21aa a5 02 LDA &02 ; even_colour_table_address_low &21ac 91 58 STA (&58),Y ; plot_even_row_address # poke the colour table address into the routines &21ae a5 04 LDA &04 ; odd_colour_table_address_low &21b0 91 5a STA (&5a),Y ; plot_odd_row_address &21b2 c8 INY &21b3 a5 03 LDA &03 ; even_colour_table_address_high &21b5 91 58 STA (&58),Y ; plot_even_row_address &21b7 a5 05 LDA &05 ; odd_colour_table_address_high &21b9 91 5a STA (&5a),Y ; plot_odd_row_address &21bb 98 TYA &21bc e9 13 SBC #&13 &21be a8 TAY &21bf b0 e9 BCS &21aa ; poke_even_and_odd_colour_table_addresses_loop &21c1 a6 20 LDX &20 ; ball_screen_x # Calculate screen address &21c3 a4 21 LDY &21 ; ball_screen_y &21c5 98 TYA &21c6 29 07 AND #&07 &21c8 85 0c STA &0c ; row_in_group &21ca 98 TYA &21cb 29 f8 AND #&f8 &21cd 4a LSR A &21ce 4a LSR A &21cf a8 TAY &21d0 8a TXA &21d1 29 7c AND #&7c &21d3 0a ASL A &21d4 79 ef 37 ADC &37ef,Y ; group_offsets_table &21d7 05 0c ORA &0c ; row_in_group &21d9 85 1e STA &1e ; ball_screen_address_low &21db b9 f0 37 LDA &37f0,Y ; group_offsets_table + 1 &21de 65 27 ADC &27 ; buffer_start_address_high &21e0 e0 80 CPX #&80 &21e2 69 00 ADC #&00 &21e4 85 1f STA &1f ; ball_screen_address_high &21e6 4c 12 22 JMP &2212 ; plot_row_of_ball ; leave &21e9 60 RTS ; consider_next_row &21ea c6 26 DEC &26 ; rows_to_plot &21ec f0 fb BEQ &21e9 ; leave &21ee e6 21 INC &21 ; ball_screen_y &21f0 a5 1c LDA &1c ; ball_sprite_address_low # Move to next row of sprite &21f2 38 SEC &21f3 65 25 ADC &25 ; width_in_bytes &21f5 85 1c STA &1c ; ball_sprite_address_low &21f7 90 03 BCC &21fc ; skip_page &21f9 e6 1d INC &1d ; ball_sprite_address_high &21fb 18 CLC ; skip_page &21fc e6 1e INC &1e ; ball_screen_address_low # Move down a row &21fe a5 1e LDA &1e ; ball_screen_address_low &2200 29 07 AND #&07 &2202 d0 0e BNE &2212 ; not_group &2204 a6 1e LDX &1e ; ball_screen_address_low # Move down a group &2206 ca DEX &2207 8a TXA &2208 69 39 ADC #&39 &220a 85 1e STA &1e ; ball_screen_address_low &220c a5 1f LDA &1f ; ball_screen_address_high &220e 69 01 ADC #&01 &2210 85 1f STA &1f ; ball_screen_address_high ; plot_row_of_ball &2212 a5 5f LDA &5f ; screen_height_in_rows ; not_group &2214 c5 21 CMP &21 ; ball_screen_y &2216 90 d1 BCC &21e9 ; leave &2218 a5 26 LDA &26 ; rows_to_plot &221a 4a LSR A ; plot_row_branch_instruction &221b 90 03 BCC &2220 ; to_plot_odd_row_address # or BCS &2220 ; to_plot_odd_row_address # or CMP #&03 &221d 6c 58 00 JMP (&0058) ; plot_even_row_address ; to_plot_odd_row_address &2220 6c 5a 00 JMP (&005a) ; plot_odd_row_address ; plot_row_of_ball_4_even # Also used for odd rows of non-dithered balls &2223 a0 04 LDY #&04 &2225 b1 1c LDA (&1c),Y ; ball_sprite_address # Get offset into sprite data (i.e. shape of ball) &2227 aa TAX &2228 bd 16 08 LDA &0816,X ; colour_table_solid_shift_3 # actually LDA even_colour_table_address,X # Colour it &222b aa TAX &222c a0 20 LDY #&20 &222e 11 1e ORA (&1e),Y ; ball_screen_address # Merge screen and coloured ball &2230 3d 00 06 AND &0600,X ; mask_table # Remove screen colours from ball part of merge &2233 91 1e STA (&1e),Y ; ball_screen_address # Write to screen ; plot_row_of_ball_3_even &2235 a0 03 LDY #&03 &2237 b1 1c LDA (&1c),Y ; ball_sprite_address &2239 aa TAX &223a bd 16 08 LDA &0816,X ; colour_table_solid_shift_3 # actually LDA even_colour_table_address,X &223d aa TAX &223e a0 18 LDY #&18 &2240 11 1e ORA (&1e),Y ; ball_screen_address &2242 3d 00 06 AND &0600,X ; mask_table &2245 91 1e STA (&1e),Y ; ball_screen_address ; plot_row_of_ball_2_even &2247 a0 02 LDY #&02 &2249 b1 1c LDA (&1c),Y ; ball_sprite_address &224b aa TAX &224c bd 16 08 LDA &0816,X ; colour_table_solid_shift_3 # actually LDA even_colour_table_address,X &224f aa TAX &2250 a0 10 LDY #&10 &2252 11 1e ORA (&1e),Y ; ball_screen_address &2254 3d 00 06 AND &0600,X ; mask_table &2257 91 1e STA (&1e),Y ; ball_screen_address ; plot_row_of_ball_1_even &2259 a0 01 LDY #&01 &225b b1 1c LDA (&1c),Y ; ball_sprite_address &225d aa TAX &225e bd 16 08 LDA &0816,X ; colour_table_solid_shift_3 # actually LDA even_colour_table_address,X &2261 aa TAX &2262 a0 08 LDY #&08 &2264 11 1e ORA (&1e),Y ; ball_screen_address &2266 3d 00 06 AND &0600,X ; mask_table &2269 91 1e STA (&1e),Y ; ball_screen_address ; plot_row_of_ball_0_even &226b a0 00 LDY #&00 &226d b1 1c LDA (&1c),Y ; ball_sprite_address &226f aa TAX &2270 bd 16 08 LDA &0816,X ; colour_table_solid_shift_3 # actually LDA even_colour_table_address,X &2273 aa TAX &2274 a0 00 LDY #&00 &2276 11 1e ORA (&1e),Y ; ball_screen_address &2278 3d 00 06 AND &0600,X ; mask_table &227b 91 1e STA (&1e),Y ; ball_screen_address &227d 4c ea 21 JMP &21ea ; consider_next_row ; plot_row_of_ball_4_odd # Only used for dithered balls &2280 a0 04 LDY #&04 &2282 b1 1c LDA (&1c),Y ; ball_sprite_address &2284 aa TAX &2285 bd 86 0d LDA &0d86,X ; colour_table_dithered_odd_shift_3 # actually LDA odd_colour_table_address,X &2288 aa TAX &2289 a0 20 LDY #&20 &228b 11 1e ORA (&1e),Y ; ball_screen_address &228d 3d 00 06 AND &0600,X ; mask_table &2290 91 1e STA (&1e),Y ; ball_screen_address ; plot_row_of_ball_3_odd &2292 a0 03 LDY #&03 &2294 b1 1c LDA (&1c),Y ; ball_sprite_address &2296 aa TAX &2297 bd 86 0d LDA &0d86,X ; colour_table_dithered_odd_shift_3 # actually LDA odd_colour_table_address,X &229a aa TAX &229b a0 18 LDY #&18 &229d 11 1e ORA (&1e),Y ; ball_screen_address &229f 3d 00 06 AND &0600,X ; mask_table &22a2 91 1e STA (&1e),Y ; ball_screen_address ; plot_row_of_ball_2_odd &22a4 a0 02 LDY #&02 &22a6 b1 1c LDA (&1c),Y ; ball_sprite_address &22a8 aa TAX &22a9 bd 86 0d LDA &0d86,X ; colour_table_dithered_odd_shift_3 # actually LDA odd_colour_table_address,X &22ac aa TAX &22ad a0 10 LDY #&10 &22af 11 1e ORA (&1e),Y ; ball_screen_address &22b1 3d 00 06 AND &0600,X ; mask_table &22b4 91 1e STA (&1e),Y ; ball_screen_address ; plot_row_of_ball_1_odd &22b6 a0 01 LDY #&01 &22b8 b1 1c LDA (&1c),Y ; ball_sprite_address &22ba aa TAX &22bb bd 86 0d LDA &0d86,X ; colour_table_dithered_odd_shift_3 # actually LDA odd_colour_table_address,X &22be aa TAX &22bf a0 08 LDY #&08 &22c1 11 1e ORA (&1e),Y ; ball_screen_address &22c3 3d 00 06 AND &0600,X ; mask_table &22c6 91 1e STA (&1e),Y ; ball_screen_address ; plot_row_of_ball_0_odd &22c8 a0 00 LDY #&00 &22ca b1 1c LDA (&1c),Y ; ball_sprite_address &22cc aa TAX &22cd bd 86 0d LDA &0d86,X ; colour_table_dithered_odd_shift_3 # actually LDA odd_colour_table_address,X &22d0 aa TAX &22d1 a0 00 LDY #&00 &22d3 11 1e ORA (&1e),Y ; ball_screen_address &22d5 3d 00 06 AND &0600,X ; mask_table &22d8 91 1e STA (&1e),Y ; ball_screen_address &22da 4c ea 21 JMP &21ea ; consider_next_row ; calculate_crtc_start_address &22dd a5 28 LDA &28 ; vsync_counter &22df aa TAX &22e0 38 SEC &22e1 e5 3e SBC &3e ; previous_vsync_counter &22e3 86 3e STX &3e ; previous_vsync_counter &22e5 85 3f STA &3f ; frames_elapsed # Unused variable &22e7 18 CLC &22e8 65 3e ADC &3e ; previous_vsync_counter &22ea 85 29 STA &29 ; unused_vsync_counter # Unused variable &22ec a4 27 LDY &27 ; buffer_start_address_high &22ee 98 TYA &22ef 49 26 EOR #&26 ; &2600 = screen_two ^ screen_one # Use other buffer &22f1 85 27 STA &27 ; buffer_start_address_high &22f3 85 a0 STA &a0 ; background_screen_address_high &22f5 98 TYA # Calculate CRTC start address from screen address &22f6 0a ASL A &22f7 0a ASL A &22f8 0a ASL A &22f9 0a ASL A &22fa 0a ASL A &22fb 85 41 STA &41 ; crtc_start_address_low &22fd 98 TYA &22fe 4a LSR A &22ff 4a LSR A &2300 4a LSR A &2301 85 40 STA &40 ; crtc_start_address_high &2303 60 RTS ; transform_world_to_screen_coordinates &2304 a5 2e LDA &2e ; player_viewpoint_horizontal_rotation &2306 a2 02 LDX #&02 ; world_x_fraction &2308 a0 06 LDY #&06 ; world_y_fraction &230a 20 5a 23 JSR &235a ; rotate_pair_of_coordinates # tx = wx * cos(ah) - wy * sin(ah) &230d a5 2f LDA &2f ; player_viewpoint_vertical_rotation # ry = wx * sin(ah) + wy * cos(ah) &230f a2 04 LDX #&04 ; world_z_fraction &2311 a0 06 LDY #&06 ; world_y_fraction (actually r_y_fraction) &2313 20 5a 23 JSR &235a ; rotate_pair_of_coordinates # tz = wz * cos(av) - ry * sin(av) ; calculate_screen_z # ty = wz * sin(av) + ry * cos(av) &2316 a5 07 LDA &07 ; t_y &2318 18 CLC &2319 65 4a ADC &4a ; viewpoint_z_offset &231b 85 07 STA &07 ; screen_z # screen_z = ty + viewpoint_z_offset ; calculate_screen_x &231d 38 SEC &231e a5 02 LDA &02 ; t_x_fraction &2320 e5 47 SBC &47 ; viewpoint_x_offset_fraction &2322 85 0c STA &0c ; offset_fraction &2324 a5 03 LDA &03 ; t_x &2326 49 80 EOR #&80 &2328 85 03 STA &03 ; t_x &232a e5 48 SBC &48 ; viewpoint_x_offset &232c 6a ROR A &232d 49 80 EOR #&80 &232f 66 0c ROR &0c ; offset_fraction &2331 c9 80 CMP #&80 &2333 6a ROR A # Divide by two, keeping sign &2334 66 0c ROR &0c ; offset_fraction &2336 a8 TAY &2337 a6 0c LDX &0c ; offset_fraction &2339 20 df 24 JSR &24df ; divide_XY_by_ty &233c 86 08 STX &08 ; screen_x_fraction &233e 98 TYA &233f 49 80 EOR #&80 &2341 85 09 STA &09 ; screen_x # screen_x = (tx - viewpoint_x_offset) / ty ; calculate_screen_y &2343 a5 05 LDA &05 ; t_z &2345 c9 80 CMP #&80 &2347 6a ROR A # Divide by two, keeping sign &2348 a8 TAY &2349 a5 04 LDA &04 ; t_z_fraction &234b 6a ROR A &234c aa TAX # XY = tz / 2 &234d 20 df 24 JSR &24df ; divide_XY_by_ty &2350 e0 80 CPX #&80 &2352 98 TYA &2353 2a ROL A # Multiply by two, keeping sign &2354 18 CLC &2355 65 49 ADC &49 ; viewpoint_y_offset &2357 85 0b STA &0b ; screen_y # screen_y = (tz / ty) + viewpoint_y_offset &2359 60 RTS ; rotate_pair_of_coordinates &235a 84 0d STY &0d ; two_address &235c 86 0c STX &0c ; one_address &235e 85 0e STA &0e ; angle &2360 a9 00 LDA #&00 &2362 85 10 STA &10 ; cos_one_minus_sin_two_fraction &2364 85 11 STA &11 ; cos_one_minus_sin_two &2366 85 12 STA &12 ; sin_one_plus_cos_two_fraction &2368 85 13 STA &13 ; sin_one_plus_cos_two &236a b5 00 LDA &00,X ; one_fraction &236c b4 01 LDY &01,X ; one &236e aa TAX &236f a5 0e LDA &0e ; angle &2371 20 98 23 JSR &2398 ; add_rotated_coordinate # Add one * cos(angle) and one * sin(angle) &2374 a6 0d LDX &0d ; two_address &2376 b5 00 LDA &00,X ; two_fraction &2378 b4 01 LDY &01,X ; two &237a aa TAX &237b a5 0e LDA &0e ; angle &237d 18 CLC &237e 69 40 ADC #&40 ; 90 degrees # cos(X + 90 degrees) = -sin(X) &2380 20 98 23 JSR &2398 ; add_rotated_coordinate # Add -two * sin(angle) and two * cos(angle) &2383 a6 0c LDX &0c ; one_address &2385 a5 10 LDA &10 ; cos_one_minus_sin_two_fraction &2387 95 00 STA &00,X ; one_fraction &2389 a5 11 LDA &11 ; cos_one_minus_sin_two &238b 95 01 STA &01,X ; one # one = old_one * cos(angle) - old_two * sin(angle) &238d a6 0d LDX &0d ; two_address &238f a5 12 LDA &12 ; sin_one_plus_cos_two_fraction &2391 95 00 STA &00,X ; two_fraction &2393 a5 13 LDA &13 ; sin_one_plus_cos_two &2395 95 01 STA &01,X ; two # two = old_one * sin(angle) + old_two * cos(angle) &2397 60 RTS ; add_rotated_coordinate &2398 84 15 STY &15 ; coordinate_high &239a 86 14 STX &14 ; coordinate_low &239c 85 0f STA &0f ; angle &239e 20 c4 23 JSR &23c4 ; multiply_XY_by_cosine_A # Returns coordinate * cos(angle) in X and Y &23a1 18 CLC &23a2 8a TXA &23a3 65 10 ADC &10 ; cos_one_minus_sin_two_fraction &23a5 85 10 STA &10 ; cos_one_minus_sin_two_fraction &23a7 98 TYA &23a8 65 11 ADC &11 ; cos_one_minus_sin_two &23aa 85 11 STA &11 ; cos_one_minus_sin_two &23ac a4 15 LDY &15 ; coordinate_high &23ae a6 14 LDX &14 ; coordinate_low &23b0 a5 0f LDA &0f ; angle &23b2 38 SEC &23b3 e9 40 SBC #&40 ; 90 degrees # sin(X) = cos(X - 90 degrees) &23b5 20 c4 23 JSR &23c4 ; multiply_XY_by_cosine_A # Returns coordinate * sin(angle) in X and Y &23b8 18 CLC &23b9 8a TXA &23ba 65 12 ADC &12 ; sin_one_plus_cos_two_fraction &23bc 85 12 STA &12 ; sin_one_plus_cos_two_fraction &23be 98 TYA &23bf 65 13 ADC &13 ; sin_one_plus_cos_two &23c1 85 13 STA &13 ; sin_one_plus_cos_two &23c3 60 RTS ; multiply_XY_by_cosine_A &23c4 c9 80 CMP #&80 ; 180 degrees &23c6 90 04 BCC &23cc ; skip_angle_inversion &23c8 49 ff EOR #&ff # cos(360 degrees - X) = cos(X) &23ca 69 00 ADC #&00 ; skip_angle_inversion &23cc c9 40 CMP #&40 ; 90 degrees &23ce 90 16 BCC &23e6 ; skip_multiplicand_inversion &23d0 f0 39 BEQ &240b ; leave_with_zero # cos(90 degrees) = 0 ; invert_multiplicand # Invert multiplicand if angle > 90 degrees &23d2 49 7f EOR #&7f &23d4 69 00 ADC #&00 &23d6 85 16 STA &16 ; multiplicand_low &23d8 8a TXA &23d9 49 ff EOR #&ff &23db aa TAX &23dc 98 TYA &23dd 49 ff EOR #&ff &23df a8 TAY &23e0 a5 16 LDA &16 ; multiplicand_low &23e2 e8 INX &23e3 d0 01 BNE &23e6 ; skip_overflow &23e5 c8 INY ; skip_overflow ; skip_multiplicand_inversion &23e6 84 17 STY &17 ; multiplicand_high &23e8 86 16 STX &16 ; multiplicand_low &23ea aa TAX &23eb bd 2f 38 LDA &382f,X ; cosine_table &23ee c0 80 CPY #&80 &23f0 b0 1e BCS &2410 ; multiplicand_is_negative ; multiplicand_is_positive &23f2 48 PHA ; cosine of partial angle &23f3 aa TAX &23f4 a4 16 LDY &16 ; multiplicand_low &23f6 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &23f9 84 16 STY &16 ; result_low &23fb 68 PLA ; cosine of partial angle &23fc aa TAX &23fd a4 17 LDY &17 ; multiplicand_high &23ff 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &2402 18 CLC &2403 8a TXA &2404 65 16 ADC &16 ; result_low &2406 aa TAX &2407 90 01 BCC &240a ; skip_overflow &2409 c8 INY ; skip_overflow &240a 60 RTS # Leave with X = result low, Y = result high ; leave_with_zero &240b a2 00 LDX #&00 &240d a0 00 LDY #&00 &240f 60 RTS # Leave with X = result low, Y = result high ; multiplicand_is_negative &2410 48 PHA ; cosine of partial angle &2411 aa TAX &2412 a9 00 LDA #&00 &2414 e5 16 SBC &16 ; multiplicand_low # Temporarily invert for multiplication &2416 a8 TAY &2417 a9 00 LDA #&00 &2419 e5 17 SBC &17 ; multiplicand_high &241b 85 17 STA &17 ; multiplicand_high &241d 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &2420 84 16 STY &16 ; result_low &2422 68 PLA ; cosine of partial angle &2423 aa TAX &2424 a4 17 LDY &17 ; multiplicand_high &2426 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &2429 18 CLC &242a 8a TXA &242b 65 16 ADC &16 ; result_low &242d 49 ff EOR #&ff # Invert result to use sign of original multiplicand &242f aa TAX &2430 90 01 BCC &2433 ; skip_overflow &2432 c8 INY ; skip_overflow &2433 98 TYA &2434 49 ff EOR #&ff &2436 a8 TAY &2437 e8 INX &2438 d0 01 BNE &243b ; skip_overflow &243a c8 INY ; skip_overflow &243b 60 RTS # Leave with X = result low, Y = result high ; multiply_X_and_Y # &243c - &2452 is replaced in sideways RAM version &243c 86 22 STX &22 ; x # Multiply two eight bit unsigned numbers &243e 84 23 STY &23 ; y &2440 38 SEC &2441 8a TXA &2442 e5 23 SBC &23 ; y &2444 90 38 BCC &247e ; y_is_greater_than_x ; x_is_greater_than_y &2446 4a LSR A &2447 aa TAX # X = (x - y) / 2 &2448 b0 16 BCS &2460 ; x_minus_y_is_odd ; x_minus_y_is_even &244a 65 23 ADC &23 ; y &244c a8 TAY # Y = (x + y) / 2 &244d 38 SEC &244e b9 00 04 LDA &0400,Y ; squares_low_table # Calculate ((x + y) / 2) ^ 2 - ((x - y) / 2) ^ 2 &2451 fd 00 04 SBC &0400,X ; squares_low_table # = ((x^2 + 2xy + y^2) - (x^2 - 2xy - y^2)) / 4 &2454 85 22 STA &22 ; result_low # = 4xy / 4 &2456 b9 00 05 LDA &0500,Y ; squares_high_table # = xy &2459 fd 00 05 SBC &0500,X ; squares_high_table &245c a8 TAY &245d a6 22 LDX &22 ; result_low &245f 60 RTS # Leave with X = result low, Y = result high ; x_minus_y_is_odd &2460 18 CLC &2461 65 23 ADC &23 ; y &2463 a8 TAY &2464 38 SEC &2465 b9 00 04 LDA &0400,Y ; squares_low_table &2468 fd 00 04 SBC &0400,X ; squares_low_table &246b 85 22 STA &22 ; result_low &246d b9 00 05 LDA &0500,Y ; squares_high_table &2470 fd 00 05 SBC &0500,X ; squares_high_table &2473 a8 TAY &2474 18 CLC &2475 a5 22 LDA &22 ; result_low &2477 65 23 ADC &23 ; y # Add y because of rounding down &2479 aa TAX &247a 90 01 BCC &247d ; skip_overflow &247c c8 INY ; skip_overflow &247d 60 RTS # Leave with X = result low, Y = result high ; y_is_greater_than_x &247e 49 ff EOR #&ff # Invert (x - y) to generate (y - x) &2480 69 01 ADC #&01 &2482 4a LSR A &2483 aa TAX # X = (y - x) / 2 &2484 b0 16 BCS &249c ; y_minus_x_is_odd ; y_minus_x_is_even &2486 65 22 ADC &22 ; x &2488 a8 TAY # X = (y + x) / 2 &2489 38 SEC &248a b9 00 04 LDA &0400,Y ; squares_low_table &248d fd 00 04 SBC &0400,X ; squares_low_table &2490 85 23 STA &23 ; result_low &2492 b9 00 05 LDA &0500,Y ; squares_high_table &2495 fd 00 05 SBC &0500,X ; squares_high_table &2498 a8 TAY &2499 a6 23 LDX &23 ; result_low &249b 60 RTS # Leave with X = result low, Y = result high ; y_minus_x_is_odd &249c 18 CLC &249d 65 22 ADC &22 ; x &249f a8 TAY &24a0 38 SEC &24a1 b9 00 04 LDA &0400,Y ; squares_low_table # Calculate ((y + x) / 2) ^ 2 - ((y - x) / 2) ^ 2 &24a4 fd 00 04 SBC &0400,X ; squares_low_table # = ((y^2 + 2xy + x^2) - (y^2 - 2xy - x^2)) / 4 &24a7 85 23 STA &23 ; result_low # = 4xy / 4 &24a9 b9 00 05 LDA &0500,Y ; squares_high_table # = xy &24ac fd 00 05 SBC &0500,X ; squares_high_table &24af a8 TAY &24b0 18 CLC &24b1 a5 23 LDA &23 ; result_low &24b3 65 22 ADC &22 ; x # Add x because of rounding down &24b5 aa TAX &24b6 90 01 BCC &24b9 ; leave &24b8 c8 INY ; leave &24b9 60 RTS # Leave with X = result low, Y = result high ; divide_XY_by_A # Divide 16 bit unsigned by 8 bit unsigned &24ba 86 18 STX &18 ; dividend_low &24bc 85 1a STA &1a ; divisor &24be a9 01 LDA #&01 &24c0 85 1b STA &1b ; result &24c2 98 TYA ; divide_XY_by_A_loop &24c3 06 18 ASL &18 ; dividend_low # dividend *= 2 &24c5 2a ROL A &24c6 90 0a BCC &24d2 ; check_if_greater # If an overflow occurs, &24c8 e5 1a SBC &1a ; divisor # dividend -= divisor &24ca 38 SEC &24cb 26 1b ROL &1b ; result &24cd 90 f4 BCC &24c3 ; divide_XY_by_A_loop &24cf a5 1b LDA &1b ; result # Leave with A = result &24d1 60 RTS ; check_if_greater &24d2 c5 1a CMP &1a ; divisor &24d4 90 02 BCC &24d8 ; skip_subtraction # Branch if dividend < divisor &24d6 e5 1a SBC &1a ; divisor # dividend -= divisor ; skip_subtraction &24d8 26 1b ROL &1b ; result &24da 90 e7 BCC &24c3 ; divide_XY_by_A_loop &24dc a5 1b LDA &1b ; result # Leave with A = result &24de 60 RTS ; divide_XY_by_ty # Calculate (XY / ty) * &10000 &24df c0 80 CPY #&80 &24e1 08 PHP ; sign &24e2 90 0c BCC &24f0 ; skip_inversion &24e4 8a TXA # If XY is negative, temporarily invert it &24e5 49 ff EOR #&ff &24e7 69 00 ADC #&00 &24e9 aa TAX &24ea 98 TYA &24eb 49 ff EOR #&ff &24ed 69 00 ADC #&00 &24ef a8 TAY ; skip_inversion &24f0 a9 01 LDA #&01 &24f2 85 18 STA &18 ; result_low &24f4 85 19 STA &19 ; result_high ; division_high_loop &24f6 8a TXA # XY = XY * 2 &24f7 0a ASL A &24f8 aa TAX &24f9 98 TYA &24fa 2a ROL A &24fb a8 TAY &24fc b0 07 BCS &2505 ; skip_high_comparison # Branches if overflow (XY > ty) &24fe e4 06 CPX &06 ; t_y_fraction &2500 98 TYA &2501 e5 07 SBC &07 ; t_y &2503 90 09 BCC &250e ; skip_high_subtraction # Branch if XY < ty ; skip_high_comparison &2505 8a TXA # XY = XY - ty &2506 e5 06 SBC &06 ; t_y_fraction &2508 aa TAX &2509 98 TYA &250a e5 07 SBC &07 ; t_y &250c a8 TAY &250d 38 SEC # Set carry to set bit of quotient ; skip_high_subtraction &250e 26 19 ROL &19 ; result_high &2510 90 e4 BCC &24f6 ; division_high_loop &2512 98 TYA ; division_low_loop &2513 0a ASL A # Y = Y * 2 &2514 b0 04 BCS &251a ; skip_low_comparison &2516 c5 07 CMP &07 ; t_y &2518 90 03 BCC &251d ; skip_low_subtraction # Branch if Y < ty ; skip_low_comparison &251a e5 07 SBC &07 ; t_y # Y = Y - ty &251c 38 SEC # Set carry to set bit of quotient ; skip_low_subtraction &251d 26 18 ROL &18 ; result_low &251f 90 f2 BCC &2513 ; division_low_loop &2521 28 PLP ; sign &2522 b0 05 BCS &2529 ; leave_with_inverted_result &2524 a6 18 LDX &18 ; result_low &2526 a4 19 LDY &19 ; result_high &2528 60 RTS # Leave with X = result low, Y = result high ; leave_with_inverted_result # If XY was initially negative, invert to restore sign &2529 a9 00 LDA #&00 &252b e5 18 SBC &18 ; result_low &252d aa TAX &252e a9 00 LDA #&00 &2530 e5 19 SBC &19 ; result_high &2532 a8 TAY &2533 60 RTS # Leave with X = result low, Y = result high ; calculate_computer_move &2534 20 d8 26 JSR &26d8 ; backup_table_layout # Copy actual table layout to layout one &2537 a5 a1 LDA &a1 ; balls_not_broken # Negative if balls haven't been broken &2539 25 50 AND &50 ; placing_ball # Negative if placing ball &253b 08 PHP ; computer needs to break balls &253c 24 51 BIT &51 ; permit_swapping_colours # Negative if colours can be swapped &253e 10 0b BPL &254b ; skip_swapping_colours &2540 a5 74 LDA &74 ; dithered_balls_remaining # If the computer can swap colours, &2542 c5 73 CMP &73 ; solid_balls_remaining &2544 a9 00 LDA #&00 # A = 0 if dithered balls < solid balls &2546 2a ROL A # A = 1 if dithered balls >= solid balls &2547 45 78 EOR &78 ; active_player &2549 85 71 STA &71 ; first_player_colour # i.e. computer chooses colour with least balls ; skip_swapping_colours &254b a5 51 LDA &51 ; permit_swapping_colours # Negative if colours can be swapped &254d 05 50 ORA &50 ; placing_ball # Negative if placing ball &254f 08 PHP ; can swap colours or placing ball &2550 a9 00 LDA #&00 &2552 85 51 STA &51 ; permit_swapping_colours # Negative if colours can be swapped &2554 24 50 BIT &50 ; placing_ball # Negative if placing ball &2556 10 03 BPL &255b ; skip_placing_ball &2558 e8 INX # X = &10 here (set at &1a82) &2559 86 50 STX &50 ; placing_ball # Set to positive to finish placing ball ; skip_placing_ball &255b 28 PLP ; can swap colours or placing ball &255c 10 05 BPL &2563 ; skip_updating_screen # If colours were swapped, or cue ball was placed, &255e c6 4f DEC &4f ; viewpoint_has_changed # Set to negative to recalculate viewpoint &2560 20 78 1c JSR &1c78 ; update_screen ; skip_updating_screen &2563 28 PLP ; computer needs to break balls &2564 10 32 BPL &2598 ; make_calculated_move ; make_random_move # If the computer needs to break the balls, &2566 a2 0f LDX #&0f # Wait for 15 v-syncs to simulate thinking ; delay_loop &2568 20 0a 2d JSR &2d0a ; wait_for_vsync &256b ca DEX &256c d0 fa BNE &2568 ; delay_loop &256e 20 0d 30 JSR &300d ; rnd &2571 29 0f AND #&0f &2573 18 CLC &2574 69 11 ADC #&11 &2576 85 33 STA &33 ; viewpoint_vertical_rotation # Use random vertical angle &2578 20 0d 30 JSR &300d ; rnd &257b 29 03 AND #&03 &257d 18 CLC &257e 69 0b ADC #&0b &2580 85 34 STA &34 ; strike_power # Use random strike power &2582 20 0d 30 JSR &300d ; rnd &2585 29 07 AND #&07 &2587 18 CLC &2588 69 04 ADC #&04 &258a 2c 22 0f BIT &0f22 ; balls_table_x &258d 10 02 BPL &2591 ; cue_ball_not_on_left_of_table &258f 69 04 ADC #&04 ; cue_ball_not_on_left_of_table &2591 85 35 STA &35 ; strike_point # Use random strike point, skewed towards table centre &2593 a0 00 LDY #&00 # Use fixed horizontal angle &2595 4c ff 25 JMP &25ff ; make_move ; make_calculated_move &2598 a2 ff LDX #&ff &259a 86 8c STX &8c ; computer_is_thinking # Set to negative to indicate computer is just thinking &259c a9 0a LDA #&0a ; STRIKE_MIDDLE &259e 85 35 STA &35 ; strike_point # Computer players all use the same strike point &25a0 a9 12 LDA #&12 &25a2 85 33 STA &33 ; viewpoint_vertical_rotation # Computer players all use the same vertical angle &25a4 a2 f0 LDX #&f0 ; at (18, 0), eor &00, string &68 ("HMMMMMM.... ") &25a6 20 ff 27 JSR &27ff ; plot_string_to_visible_buffer &25a9 20 ec 14 JSR &14ec ; set_current_player_ball_colour &25ac a0 00 LDY #&00 &25ae 98 TYA &25af 85 8d STA &8d ; acceptable_moves_found &25b1 85 b1 STA &b1 ; thinking_count ; wipe_potential_move_scores_loop &25b3 99 00 03 STA &0300,Y ; potential_move_scores # Set to positive to indicate move not evaluated yet &25b6 c8 INY &25b7 d0 fa BNE &25b3 ; wipe_potential_move_scores_loop &25b9 a6 8e LDX &8e ; computer_player &25bb bd a2 36 LDA &36a2,X ; computer_players_strike_power &25be 85 34 STA &34 ; strike_power # Computer players use their own fixed power &25c0 bd aa 36 LDA &36aa,X ; computer_players_skill &25c3 24 71 BIT &71 ; first_player_colour # Positive if colours have been decided &25c5 10 02 BPL &25c9 ; set_score_limit_for_acceptable_move &25c7 a9 02 LDA #&02 # If no colour potted, use maximum acceptable score of 2 ; set_score_limit_for_acceptable_move &25c9 85 ac STA &ac ; score_limit_for_acceptable_move &25cb a9 01 LDA #&01 # Start by searching for moves that score 2 ; search_for_increasingly_good_moves_loop &25cd 18 CLC &25ce 69 01 ADC #&01 &25d0 85 ab STA &ab ; score_limit_for_ending_evaluation &25d2 a5 b1 LDA &b1 ; thinking_count &25d4 4a LSR A &25d5 a2 f0 LDX #&f0 ; at (18, 0), eor &00, string &68 ("HMMMMMM.... ") &25d7 90 02 BCC &25db ; update_thinking_string &25d9 a2 f4 LDX #&f4 ; at (18, 0), eor &00, string &6a ("THINKING... ") ; update_thinking_string &25db 20 ff 27 JSR &27ff ; plot_string_to_visible_buffer &25de e6 b1 INC &b1 ; thinking_count &25e0 20 66 26 JSR &2666 ; evaluate_potential_computer_moves # Returns carry set if a good move was found &25e3 b0 1a BCS &25ff ; make_move # If so, make that move immediately &25e5 20 3b 26 JSR &263b ; find_worst_partially_evaluated_move # Returns A = worst score, Z set if no moves &25e8 f0 0d BEQ &25f7 ; all_moves_have_been_evaluated # If no unevaluated moves left, make a random move &25ea c5 ac CMP &ac ; score_limit_for_acceptable_move &25ec 90 df BCC &25cd ; search_for_increasingly_good_moves_loop # Keep thinking until player's skill level is reached &25ee a4 8d LDY &8d ; acceptable_moves_found &25f0 f0 db BEQ &25cd ; search_for_increasingly_good_moves_loop # Has an acceptable move been found? ; make_acceptable_move &25f2 a4 ae LDY &ae ; acceptable_move_angle &25f4 4c ff 25 JMP &25ff ; make_move # If so, make it ; all_moves_have_been_evaluated &25f7 a4 8d LDY &8d ; acceptable_moves_found &25f9 d0 f7 BNE &25f2 ; make_acceptable_move # Was there an acceptable move? If so, make it &25fb 20 0d 30 JSR &300d ; rnd # Otherwise, make a move at random &25fe a8 TAY ; make_move &25ff 84 32 STY &32 ; viewpoint_horizontal_rotation &2601 a5 75 LDA &75 ; solid_balls_potted &2603 05 76 ORA &76 ; dithered_balls_potted &2605 05 79 ORA &79 ; black_ball_potted # Negative if black was potted &2607 f0 29 BEQ &2632 ; finished_considering_potential_moves # If any balls were potted, &2609 a6 8e LDX &8e ; computer_player &260b 20 0d 30 JSR &300d ; rnd # randomly decide if computer makes move correctly, &260e dd 9a 36 CMP &369a,X ; computer_players_accuracy # depending on the player's accuracy &2611 90 1f BCC &2632 ; finished_considering_potential_moves ; computer_is_inaccurate &2613 4a LSR A &2614 88 DEY # Randomly rotate 360/256 degrees &2615 b0 02 BCS &2619 ; rotate_clockwise # either clockwise or anticlockwise, at random ; rotate_anticlockwise &2617 c8 INY &2618 c8 INY ; rotate_clockwise &2619 a5 8e LDA &8e ; computer_player &261b c9 04 CMP #&04 # Carry set for MIGHTY MIKE, BILLY T KID, JAC DERRIDA &261d a5 32 LDA &32 ; viewpoint_horizontal_rotation # and MALTESE JOE; if so, consider black foul shots &261f 84 32 STY &32 ; viewpoint_horizontal_rotation # Use inaccurate angle &2621 90 0f BCC &2632 ; finished_considering_potential_moves # Branch if computer player is less skilful &2623 48 PHA ; accurate angle &2624 a9 3f LDA #&3f &2626 85 ab STA &ab ; score_limit_for_ending_evaluation &2628 20 85 26 JSR &2685 ; evaluate_potential_computer_move # Returns score for accurate angle &262b aa TAX &262c 68 PLA ; accurate angle &262d e8 INX &262e d0 02 BNE &2632 ; finished_considering_potential_moves # If the accurate angle pots the black as a foul shot, &2630 85 32 STA &32 ; viewpoint_horizontal_rotation # Use the accurate angle instead ; finished_considering_potential_moves &2632 a9 00 LDA #&00 &2634 85 79 STA &79 ; black_ball_potted # Set to zero to indicate black not potted &2636 85 8c STA &8c ; computer_is_thinking # Set to positive to indicate computer not thinking &2638 4c dd 26 JMP &26dd ; restore_table_layout # Restore actual table layout from layout one ; find_worst_partially_evaluated_move &263b a0 ff LDY #&ff &263d 84 02 STY &02 ; minimum &263f c8 INY ; 0 &2640 84 03 STY &03 ; count ; find_worst_partially_evaluated_move_loop &2642 b9 00 03 LDA &0300,Y ; potential_move_scores &2645 30 0a BMI &2651 ; consider_next_move # Negative if move has been fully evaluated &2647 c5 02 CMP &02 ; minimum &2649 90 0e BCC &2659 ; is_new_minimum # Does this move score lower than the previous minimum? &264b d0 04 BNE &2651 ; consider_next_move &264d e6 03 INC &03 ; count &264f f0 10 BEQ &2661 ; at_ceiling ; consider_next_move &2651 c8 INY &2652 d0 ee BNE &2642 ; find_worst_partially_evaluated_move &2654 a5 02 LDA &02 ; minimum # Leave with A = worst score of partially evaluated moves &2656 a4 03 LDY &03 ; count # Leave with Z set if there are no partially evaluated moves &2658 60 RTS ; is_new_minimum &2659 85 02 STA &02 ; minimum &265b a9 01 LDA #&01 &265d 85 03 STA &03 ; count &265f d0 f0 BNE &2651 ; consider_next_move # Always branches ; at_ceiling &2661 c6 03 DEC &03 ; count # Stop count from wrapping round to zero &2663 4c 51 26 JMP &2651 ; consider_next_move ; evaluate_potential_computer_moves &2666 a0 00 LDY #&00 &2668 ba TSX &2669 86 ad STX &ad ; stack_point_prior_to_evaluating_potential_computer_move ; evaluate_potential_computer_moves_loop &266b b9 00 03 LDA &0300,Y ; potential_move_scores # Negative if move has been fully evaluated &266e 30 0c BMI &267c ; skip_evaluating_move &2670 84 32 STY &32 ; viewpoint_horizontal_rotation &2672 20 85 26 JSR &2685 ; evaluate_potential_computer_move # Returns score of move in A; carry set if good move ; set_score_for_potential_computer_move &2675 a4 32 LDY &32 ; viewpoint_horizontal_rotation &2677 99 00 03 STA &0300,Y ; potential_move_scores &267a b0 08 BCS &2684 ; leave # Leave with carry set if good move found, angle in Y ; skip_evaluating_move &267c 98 TYA &267d 18 CLC &267e 69 23 ADC #&23 # Cycle through all 256 possible angles &2680 a8 TAY &2681 d0 e8 BNE &266b ; evaluate_potential_computer_moves_loop &2683 18 CLC # Leave with carry clear to indicate no good move found ; leave &2684 60 RTS ; evaluate_potential_computer_move &2685 20 dd 26 JSR &26dd ; restore_table_layout # Restore actual table layout &2688 20 06 15 JSR &1506 ; strike_cue_ball ; evaluate_potential_computer_move_loop &268b 20 55 16 JSR &1655 ; update_moving_balls &268e 24 7a BIT &7a ; foul_shot # Negative if foul shot &2690 30 40 BMI &26d2 ; is_foul_shot # Stop evaluating move as soon as foul occurs &2692 a5 4d LDA &4d ; number_of_balls_in_motion &2694 d0 f5 BNE &268b ; evaluate_potential_computer_move_loop # Continue evaluating move until all balls stop &2696 24 7c BIT &7c ; first_ball_hit # Negative if no ball hit &2698 30 38 BMI &26d2 ; is_foul_shot &269a a4 8d LDY &8d ; acceptable_moves_found &269c d0 0c BNE &26aa ; potential_move_is_acceptable # Is this the first non-foul move found? &269e a5 32 LDA &32 ; viewpoint_horizontal_rotation &26a0 85 ae STA &ae ; acceptable_move_angle # If so, store move &26a2 a5 aa LDA &aa ; score &26a4 c5 ac CMP &ac ; score_limit_for_acceptable_move &26a6 f0 02 BEQ &26aa ; potential_move_is_acceptable &26a8 b0 22 BCS &26cc ; potential_move_is_good # If the move scores too highly, it is a good move ; potential_move_is_acceptable &26aa e6 8d INC &8d ; acceptable_moves_found &26ac d0 02 BNE &26b0 ; consider_remaining_balls # Always branches ; unused &26ae c6 8d DEC &8d ; acceptable_moves_found # Unused code ; consider_remaining_balls &26b0 a5 71 LDA &71 ; first_player_colour # Negative if colours haven't been decided &26b2 10 07 BPL &26bb ; consider_colour_potted_balls ; consider_any_potted_balls # If colours haven't been decided yet, &26b4 a5 75 LDA &75 ; solid_balls_potted # then potting any coloured ball is a good move &26b6 05 76 ORA &76 ; dithered_balls_potted &26b8 4c c9 26 JMP &26c9 ; consider_if_move_is_good ; consider_colour_potted_balls &26bb 45 78 EOR &78 ; active_player &26bd aa TAX # X = computer's colour &26be b5 73 LDA &73,X ; solid_balls_remaining &26c0 f0 05 BEQ &26c7 ; only_black_remaining_for_computer # If only the black remains, potting it is a good move &26c2 b5 75 LDA &75,X ; solid_balls_potted &26c4 4c c9 26 JMP &26c9 ; consider_if_move_is_good # Otherwise, potting computer's colour ball is a good move ; only_black_remaining_for_computer &26c7 a5 79 LDA &79 ; black_ball_potted # Non-zero if black was potted ; consider_if_move_is_good &26c9 18 CLC # Clear carry to indicate not good mood &26ca f0 01 BEQ &26cd ; not_good_move ; potential_move_is_good &26cc 38 SEC # Set carry to indicate good move ; not_good_move &26cd a5 aa LDA &aa ; score # Leave with score &26cf 09 80 ORA #&80 # Set top bit to indicate move has been fully evaluated &26d1 60 RTS ; is_foul_shot &26d2 a9 fe LDA #&fe # Leave with &fe if foul shot &26d4 05 79 ORA &79 ; black_ball_potted # Leave with &ff if foul shot because black was potted &26d6 18 CLC &26d7 60 RTS ; backup_table_layout &26d8 a9 01 LDA #&01 # Layout one stores backup of actual table &26da 4c 58 1a JMP &1a58 ; store_balls_in_layout ; restore_table_layout &26dd a9 01 LDA #&01 # Layout one stores backup of actual table &26df 85 4e STA &4e ; dampening_cooldown &26e1 4c f6 19 JMP &19f6 ; get_balls_from_layout ; wipe_menu_area &26e4 20 03 27 JSR &2703 ; set_menu_screen_address &26e7 a2 11 LDX #&11 ; wipe_menu_area_group_loop &26e9 a0 00 LDY #&00 &26eb a9 ff LDA #&ff ; wipe_menu_area_byte_loop &26ed 88 DEY &26ee 91 02 STA (&02),Y ; screen_address &26f0 d0 fb BNE &26ed ; wipe_menu_area_byte_loop &26f2 18 CLC &26f3 a5 02 LDA &02 ; screen_address_low &26f5 69 40 ADC #&40 # Move down a group &26f7 85 02 STA &02 ; screen_address_low &26f9 a5 03 LDA &03 ; screen_address_high &26fb 69 01 ADC #&01 &26fd 85 03 STA &03 ; screen_address_high &26ff ca DEX &2700 d0 e7 BNE &26e9 ; wipe_menu_area_group_loop &2702 60 RTS ; set_menu_screen_address &2703 a9 e0 LDA #&e0 &2705 85 02 STA &02 ; screen_address_low &2707 85 04 STA &04 ; screen_start_address_low &2709 a5 27 LDA &27 ; buffer_start_address_high &270b 49 26 EOR #&26 ; &2600 = screen_two ^ screen_one # Use other buffer &270d 18 CLC &270e 69 03 ADC #&03 &2710 85 03 STA &03 ; screen_address_high &2712 85 05 STA &05 ; screen_start_address_high &2714 60 RTS ; plot_tournament_strings &2715 20 40 27 JSR &2740 ; prepare_menu_strings &2718 20 fc 29 JSR &29fc ; prepare_power_gauge_and_player_string &271b 20 2e 2a JSR &2a2e ; prepare_tournament_strings &271e a2 4c LDX #&4c ; at (20, 1), eor &0f, string &10 ("PLAYER ONE ") ; at (20, 3), eor &0f, string &00 ("FLASH HARRY ") ; at (20, 5), eor &0f, string &02 ("NO-GOOD NIK ") ; at (20, 7), eor &0f, string &04 ("CATFORD KID ") ; at (20, 9), eor &0f, string &06 ("FAST FREDDY ") ; at (20, 11), eor &0f, string &08 ("MIGHTY MIKE ") ; at (20, 13), eor &0f, string &0a ("BILLY T KID ") ; at (20, 15), eor &0f, string &0c ("JAC DERRIDA ") ; at (12, 2), eor &0f, string &3c (" - - - - - ") ; at (12, 6), eor &0f, string &3c (" - - - - - ") ; at (12, 10), eor &0f, string &3c (" - - - - - ") ; at (12, 14), eor &0f, string &3c (" - - - - - ") ; at ( 4, 4), eor &0f, string &3c (" - - - - - ") ; at ( 4, 12), eor &0f, string &3c (" - - - - - ") ; at ( 1, 7), eor &0f, string &54 ("TOURNAMENT ") ; at ( 1, 8), eor &0f, string &3e ("WINNER CHALLENGES ") ; at ( 1, 9), eor &0f, string &0e ("MALTESE JOE ") ; at ( 1, 0), eor &0f, string &40 ("QUARTER FINALS ") ; at ( 1, 16), eor &0f, string &48 ("BEST OF 3 FRAMES ") &2720 a0 98 LDY #&98 &2722 d0 0d BNE &2731 ; plot_strings # Always branches ; plot_menu_strings &2724 a2 00 LDX #&00 ; at ( 2, 0), eor &0f, string &18 ("---------------------------- ") ; at ( 2, 1), eor &0f, string &16 ("MALTESE JOE PLAYS 3-D POOL ") ; at ( 2, 2), eor &0f, string &18 ("---------------------------- ") ; at ( 0, 6), eor &0f, string &40 ("QUARTER FINALS ") ; at (16, 6), eor &0f, string &48 ("BEST OF 3 FRAMES ") ; at (14, 4), eor &0f, string &20 ("-VS- ") ; at ( 2, 7), eor &0f, string &24 ("F1 INPUT TYPE - ") ; at ( 2, 8), eor &0f, string &26 ("F3 MATCH TYPE - ") ; at ( 2, 9), eor &0f, string &2c ("F5 VIEW PAIRINGS ") ; at ( 2, 10), eor &0f, string &34 ("F7 ENTER NEW TOURNAMENT ") ; at ( 5, 12), eor &0f, string &60 ("PRESS SPACE TO START ") ; at ( 1, 14), eor &0f, string &1a ("PROGRAMME + DESIGN - ORLANDO ") ; at ( 0, 15), eor &0f, string &1c ("COPYRIGHT 1989 AARDVARK SOFTWARE ") ; at ( 1, 16), eor &0f, string &1e ("PUBLISHED BY FIREBIRD SOFTWARE ") ; at ( 1, 4), eor &0f, string &10 ("PLAYER ONE ") ; at (20, 4), eor &0f, string &12 ("PLAYER TWO ") ; at (20, 7), eor &0f, string &38 ("KEYBOARD ") ; at (18, 7), eor &0f, string &54 ("TOURNAMENT ") &2726 2c a2 38 BIT &38a2 ; plot_menu_options #2727 LDX #&38 ; at ( 1, 4), eor &0f, string &10 ("PLAYER ONE ") ; at (20, 4), eor &0f, string &12 ("PLAYER TWO ") ; at (20, 7), eor &0f, string &38 ("KEYBOARD ") ; at (18, 7), eor &0f, string &54 ("TOURNAMENT ") &2729 a0 48 LDY #&48 &272b 24 98 BIT &98 ; frame_in_progress # Negative if frame in progress &272d 10 02 BPL &2731 ; plot_strings &272f a0 4c LDY #&4c ; at (12, 10), eor &0f, string &5e (" GAME IN PROGRESS ") ; plot_strings &2731 8c 3c 27 STY &273c ; end_string ; plot_strings_loop &2734 20 09 28 JSR &2809 ; plot_string &2737 e8 INX # Move to next string &2738 e8 INX &2739 e8 INX &273a e8 INX &273b e0 00 CPX #&00 # actually CPX end_string &273d 90 f5 BCC &2734 ; plot_strings_loop &273f 60 RTS ; prepare_menu_strings &2740 a9 38 LDA #&38 ; string_38 : "KEYBOARD" &2742 24 85 BIT &85 ; keyboard_or_joystick # Positive if using keyboard &2744 10 02 BPL &2748 ; set_keyboard_or_joystick_string ; is_joystick &2746 a9 3a LDA #&3a ; string_3a : "JOYSTICK" ; set_keyboard_or_joystick_string &2748 8d e4 2e STA &2ee4 ; string_data + &40 + 3 # Set keyboard or joystick string &274b 20 cb 2c JSR &2ccb ; get_player_strings # Returns X = player one string, Y = player two string &274e 8e dc 2e STX &2edc ; string_data + &38 + 3 # Set player one string &2751 8c e0 2e STY &2ee0 ; string_data + &3c + 3 # Set player two string &2754 a6 96 LDX &96 ; tournament_stage &2756 bd 96 36 LDA &3696,X ; frames_per_stage_of_tournament &2759 18 CLC &275a 69 01 ADC #&01 &275c 8d 59 35 STA &3559 ; string_48 + 8 # Set number in "BEST OF x FRAMES" &275f 8a TXA &2760 0a ASL A &2761 69 40 ADC #&40 ; string_40 : "QUARTER FINALS" &2763 8d 34 2f STA &2f34 ; string_data + &90 + 3 # Set round string &2766 8d b0 2e STA &2eb0 ; string_data + &0c + 3 &2769 a9 48 LDA #&48 ; string_48 : "BEST OF 3 FRAMES" &276b 8d b4 2e STA &2eb4 ; string_data + &10 + 3 &276e a5 87 LDA &87 ; match_type &2770 f0 08 BEQ &277a ; is_tournament &2772 a9 72 LDA #&72 ; string_72 : " " &2774 8d b0 2e STA &2eb0 ; string_data + &0c + 3 &2777 8d b4 2e STA &2eb4 ; string_data + &10 + 3 ; is_tournament &277a a2 34 LDX #&34 ; string_34 : "F7 ENTER NEW TOURNAMENT" &277c a0 26 LDY #&26 ; string_26 : "F3 MATCH TYPE -" &277e a5 87 LDA &87 ; match_type &2780 f0 02 BEQ &2784 ; is_tournament &2782 a2 72 LDX #&72 ; string_72 : " " ; is_tournament &2784 c9 04 CMP #&04 ; MATCH_TYPE_TRICK &2786 d0 02 BNE &278a ; not_trick &2788 a2 36 LDX #&36 ; string_36 : "F7 EDIT TRICK SHOT LAYOUT" ; not_trick &278a 24 98 BIT &98 ; frame_in_progress # Negative if frame in progress &278c 10 0a BPL &2798 ; set_f3_and_f7_strings &278e a2 5e LDX #&5e ; string_5e : " GAME IN PROGRESS" &2790 a0 28 LDY #&28 ; string_28 : "F3 CONCEDE CURRENT GAME" &2792 a5 87 LDA &87 ; match_type &2794 f0 02 BEQ &2798 ; set_f3_and_f7_strings &2796 a0 2a LDY #&2a ; string_2a : "F3 STOP CURRENT GAME" ; set_f3_and_f7_strings &2798 8e c8 2e STX &2ec8 ; string_data + &24 + 3 # Set f7 string &279b 8c c0 2e STY &2ec0 ; string_data + &1c + 3 # Set f3 string &279e a2 01 LDX #&01 &27a0 a4 a2 LDY &a2 ; trick_number &27a2 c8 INY &27a3 98 TYA ; divide_by_ten_loop &27a4 c9 0a CMP #&0a &27a6 90 05 BCC &27ad ; set_tens_and_digits &27a8 e9 0a SBC #&0a &27aa e8 INX &27ab b0 f7 BCS &27a4 ; divide_by_ten_loop ; set_tens_and_digits &27ad 69 01 ADC #&01 &27af 8e 5f 33 STX &335f ; string_14 + 8 # Set number of trick &27b2 8d 60 33 STA &3360 ; string_14 + 9 &27b5 a6 87 LDX &87 ; match_type &27b7 bd fa 27 LDA &27fa,X ; match_type_f5_strings &27ba 8d c4 2e STA &2ec4 ; string_data + &20 + 3 # Set f5 key &27bd a9 60 LDA #&60 ; string_60 : "PRESS SPACE TO START" &27bf a2 98 LDX #&98 ; &0a98 = &0140 * 8 + 8 * 19 # Plot match type at (19, 8) (right of "MATCH TYPE") &27c1 a0 0a LDY #&0a &27c3 24 98 BIT &98 ; frame_in_progress # Negative if frame in progress &27c5 10 06 BPL &27cd ; set_string_values &27c7 a9 62 LDA #&62 ; string_62 : "PRESS SPACE TO CONTINUE" &27c9 a2 90 LDX #&90 ; &0c90 = &0140 * 10 + 8 * 2 # Plot match type at (2, 10) (left of "GAME IN PROGRESS") &27cb a0 0c LDY #&0c ; set_string_values &27cd 8d cc 2e STA &2ecc ; string_data + &28 + 3 # Set press space string &27d0 8c e7 2e STY &2ee7 ; string_data + &44 + 2 # Set match type string screen address &27d3 8e e6 2e STX &2ee6 ; string_data + &44 + 1 &27d6 a5 87 LDA &87 ; match_type &27d8 0a ASL A &27d9 69 54 ADC #&54 ; "TOURNAMENT" &27db 8d e8 2e STA &2ee8 ; string_data + &44 + 3 # Set match type string &27de a9 20 LDA #&20 ; "-VS-" &27e0 a6 87 LDX &87 ; match_type &27e2 d0 02 BNE &27e6 ; not_tournament &27e4 a9 22 LDA #&22 ; "0--0 " ; not_tournament &27e6 8d b8 2e STA &2eb8 ; string_data + &14 + 3 # Set versus string &27e9 a5 99 LDA &99 ; players_frames_won &27eb 18 CLC &27ec 69 01 ADC #&01 &27ee 8d e4 32 STA &32e4 ; string_22 + 0 # Set number for player one wins &27f1 a5 9a LDA &9a ; players_frames_won + 1 &27f3 18 CLC &27f4 69 01 ADC #&01 &27f6 8d e7 32 STA &32e7 ; string_22 + 3 # Set number for player two wins &27f9 60 RTS ; match_type_f5_strings &27fa 2c ; &00 (MATCH_TYPE_TOURNAMENT) : string_2c : "F5 VIEW PAIRINGS" &27fb 72 ; &01 (MATCH_TYPE_TWO_PLAYER) : string_72 : " " &27fc 32 ; &02 (MATCH_TYPE_DEMO) : string_32 : "F5 NEW OPPONENTS" &27fd 2e ; &02 (MATCH_TYPE_PRACTICE) : string_2e : "F5 CHANGE PLAYER" &27fe 30 ; &03 (MATCH_TYPE_TRICK) : string_30 : "F5 TRY NEXT TRICK" ; plot_string_to_visible_buffer &27ff a5 27 LDA &27 ; buffer_start_address_high &2801 49 26 EOR #&26 ; &2600 = screen_two ^ screen_one # Use other buffer &2803 85 05 STA &05 ; screen_start_address_high &2805 a9 20 LDA #&20 &2807 85 04 STA &04 ; screen_start_address_low ; plot_string &2809 bd a1 2e LDA &2ea1,X ; string_data # First byte sets colour &280c 85 06 STA &06 ; text_eor &280e 18 CLC &280f bd a2 2e LDA &2ea2,X ; string_data + 1 # Second and third bytes set screen address &2812 65 04 ADC &04 ; screen_start_address_low &2814 85 02 STA &02 ; screen_address_low &2816 bd a3 2e LDA &2ea3,X ; string_data + 2 &2819 65 05 ADC &05 ; screen_start_address_high &281b 85 03 STA &03 ; screen_address_high &281d bc a4 2e LDY &2ea4,X ; string_data + 3 # Fourth byte sets string &2820 b9 99 2f LDA &2f99,Y ; string_addresses &2823 85 08 STA &08 ; string_address_low &2825 b9 9a 2f LDA &2f9a,Y ; string_addresses + 1 &2828 85 09 STA &09 ; string_address_high &282a a0 00 LDY #&00 ; plot_string_loop &282c b1 08 LDA (&08),Y ; string_address &282e 08 PHP ; end of string &282f 29 7f AND #&7f &2831 48 PHA ; character &2832 c8 INY &2833 84 0e STY &0e ; offset &2835 0a ASL A &2836 0a ASL A &2837 0a ASL A &2838 85 0c STA &0c ; font_data_address_low &283a 68 PLA ; character &283b 4a LSR A &283c 4a LSR A &283d 4a LSR A &283e 4a LSR A &283f 4a LSR A &2840 85 0d STA &0d ; font_data_address_high &2842 18 CLC &2843 a5 0c LDA &0c ; font_data_address_low &2845 69 70 ADC #&70 ; &3970 = font_data &2847 85 0c STA &0c ; font_data_address_low &2849 a5 0d LDA &0d ; font_data_address_high &284b 69 39 ADC #&39 &284d 85 0d STA &0d ; font_data_address_high &284f a0 07 LDY #&07 ; plot_character_loop &2851 b1 0c LDA (&0c),Y ; font_data_address &2853 45 06 EOR &06 ; text_eor &2855 91 02 STA (&02),Y ; screen_address &2857 88 DEY &2858 10 f7 BPL &2851 ; plot_character_loop &285a 18 CLC &285b a5 02 LDA &02 ; screen_address_low &285d 69 08 ADC #&08 &285f 85 02 STA &02 ; screen_address_low &2861 90 02 BCC &2865 ; skip_page &2863 e6 03 INC &03 ; screen_address_high ; skip_page &2865 a4 0e LDY &0e ; offset &2867 28 PLP ; end of string &2868 10 c2 BPL &282c ; plot_string_loop &286a 60 RTS ; end_of_frame &286b a9 00 LDA #&00 &286d 85 98 STA &98 ; frame_in_progress # Set to positive to indicate no frame in progress &286f 85 79 STA &79 ; black_ball_potted # Set to positive to indicate black not potted &2871 a5 87 LDA &87 ; match_type &2873 c9 02 CMP #&02 ; MATCH_TYPE_DEMO &2875 f0 6d BEQ &28e4 ; to_next_frame_in_tournament_stage &2877 20 e4 26 JSR &26e4 ; wipe_menu_area &287a a2 b4 LDX #&b4 ; at (12, 2), eor &0f, string &64 ("WELL DONE ") ; at (11, 5), eor &0f, string &10 ("PLAYER ONE ") ; at ( 5, 14), eor &0f, string &62 ("PRESS SPACE TO CONTINUE ") &287c a0 c0 LDY #&c0 &287e a5 78 LDA &78 ; active_player &2880 f0 04 BEQ &2886 ; plot_end_of_frame_strings &2882 a2 e4 LDX #&e4 ; at (12, 3), eor &0f, string &66 ("HARD LUCK ") ; at (11, 6), eor &0f, string &10 ("PLAYER ONE ") ; at ( 5, 14), eor &0f, string &62 ("PRESS SPACE TO CONTINUE ") &2884 a0 f0 LDY #&f0 ; plot_end_of_frame_strings &2886 20 31 27 JSR &2731 ; plot_strings &2889 20 f5 2c JSR &2cf5 ; wait_for_space &288c a5 87 LDA &87 ; match_type &288e d0 54 BNE &28e4 ; to_next_frame_in_tournament_stage # Zero if tournament &2890 a6 78 LDX &78 ; active_player &2892 b4 99 LDY &99,X ; players_frames_won &2894 c8 INY &2895 94 99 STY &99,X ; players_frames_won &2897 98 TYA &2898 0a ASL A &2899 a4 96 LDY &96 ; tournament_stage &289b d9 96 36 CMP &3696,Y ; frames_per_stage_of_tournament &289e 90 44 BCC &28e4 ; to_next_frame_in_tournament_stage # Has the player won enough frames for this stage? &28a0 a5 99 LDA &99 ; players_frames_won &28a2 e5 9a SBC &9a ; players_frames_won + 1 &28a4 a0 00 LDY #&00 &28a6 84 99 STY &99 ; players_frames_won &28a8 84 9a STY &9a ; players_frames_won + 1 &28aa b0 06 BCS &28b2 ; tournament_stage_completed # Carry set if human player won stage &28ac 20 6f 2e JSR &2e6f ; new_tournament &28af 4c c1 10 JMP &10c1 ; start_or_continue_frame ; tournament_stage_completed &28b2 aa TAX &28b3 a5 97 LDA &97 ; tournament_opponent # Calculate (delta frames won) * (opponent + 4) &28b5 18 CLC &28b6 69 04 ADC #&04 &28b8 a8 TAY &28b9 20 3c 24 JSR &243c ; multiply_X_and_Y # Returns X = result low, Y = result high &28bc 8a TXA &28bd 18 CLC &28be 65 3c ADC &3c ; win_history # Add to win history &28c0 85 3c STA &3c ; win_history &28c2 e6 96 INC &96 ; tournament_stage # Move to next stage of tournament &28c4 20 e4 26 JSR &26e4 ; wipe_menu_area &28c7 20 40 27 JSR &2740 ; prepare_menu_strings &28ca a5 96 LDA &96 ; tournament_stage &28cc c9 02 CMP #&02 ; STAGE_KNOCKOUT_FINAL &28ce 90 5f BCC &292f ; next_tournament_stage &28d0 f0 60 BEQ &2932 ; tournament_knockout_final &28d2 c9 04 CMP #&04 ; STAGE_POOL_CHALLENGE + 1 &28d4 f0 11 BEQ &28e7 ; completion_screen ; is_pool_challenge &28d6 a9 08 LDA #&08 ; PLAYER_PLAYER_ONE # Highlight winner of knockout final &28d8 8d 15 08 STA &0815 ; tournament_players + 8 + 4 + 2 &28db 20 2e 2a JSR &2a2e ; prepare_tournament_strings &28de a9 07 LDA #&07 ; PLAYER_MALTESE_JOE &28e0 85 97 STA &97 ; tournament_opponent &28e2 85 8e STA &8e ; computer_player ; to_next_frame_in_tournament_stage &28e4 4c be 10 JMP &10be ; menu_screen_then_start_or_continue_frame ; completion_screen &28e7 a2 11 LDX #&11 # Offset for first character of win-code in string_6e &28e9 a5 3c LDA &3c ; win_history &28eb 20 13 29 JSR &2913 ; set_three_win_code_digits &28ee a5 3c LDA &3c ; win_history &28f0 4a LSR A &28f1 65 3c ADC &3c ; win_history &28f3 20 13 29 JSR &2913 ; set_three_win_code_digits &28f6 a2 c0 LDX #&c0 ; at (12, 1), eor &0f, string &64 ("WELL DONE ") ; at (11, 3), eor &0f, string &10 ("PLAYER ONE ") ; at ( 3, 5), eor &0f, string &6c ("YOU HAVE BEATEN ") ; at (19, 5), eor &0f, string &0e ("MALTESE JOE ") ; at ( 5, 9), eor &0f, string &6e ("YOUR WIN-CODE IS ------ ") ; at ( 5, 11), eor &0f, string &70 ("MAKE A NOTE OF IT NOW!! ") &28f8 a0 d8 LDY #&d8 &28fa 20 31 27 JSR &2731 ; plot_strings &28fd a2 00 LDX #&00 ; delay_loop # Wait for 256 v-syncs &28ff 20 0a 2d JSR &2d0a ; wait_for_vsync &2902 e8 INX &2903 d0 fa BNE &28ff ; delay_loop &2905 a2 d8 LDX #&d8 ; at ( 5, 15), eor &0f, string &60 ("PRESS SPACE TO START ") &2907 20 09 28 JSR &2809 ; plot_string &290a 20 f5 2c JSR &2cf5 ; wait_for_space &290d 20 6f 2e JSR &2e6f ; new_tournament &2910 4c c1 10 JMP &10c1 ; start_or_continue_frame ; set_three_win_code_digits &2913 a8 TAY &2914 4a LSR A &2915 4a LSR A &2916 4a LSR A &2917 20 22 29 JSR &2922 ; set_win_code_digit_from_middle_three_bits &291a 98 TYA &291b 20 22 29 JSR &2922 ; set_win_code_digit_from_middle_three_bits &291e 98 TYA &291f 4c 25 29 JMP &2925 ; set_win_code_digit_from_low_three_bits ; set_win_code_digit_from_middle_three_bits &2922 4a LSR A &2923 4a LSR A &2924 4a LSR A ; set_win_code_digit_from_low_three_bits &2925 29 07 AND #&07 &2927 18 CLC &2928 69 02 ADC #&02 ; "1" # Win code contains numbers between 1 and 8 &292a 9d d3 35 STA &35d3,X ; string_6e # Set win code character &292d e8 INX &292e 60 RTS ; &0807 - &0815 ; tournament_players # Stores players competing in each stage ; &0807 - &080e - 8 QUARTER FINALS ; &080f - &0812 - 4 SEMI-FINALS ; &0813 - &0814 - 2 KNOCKOUT FINAL ; &0815 - 1 POOL CHALLENGE # Plays Maltese Joe ; next_tournament_stage &292f a9 00 LDA #&00 &2931 2c a9 08 BIT &08a9 ; tournament_knockout_final #2932 LDA #&08 &2934 48 PHA &2935 20 eb 29 JSR &29eb ; plot_tournament_strings_and_delay &2938 68 PLA &2939 aa TAX ; set_winners_of_pairings_loop &293a 86 8d STX &8d ; slot &293c 20 6f 29 JSR &296f ; set_winner_of_pairing &293f 20 e6 29 JSR &29e6 ; plot_tournament_strings_with_sound_and_delay &2942 a6 8d LDX &8d ; slot &2944 e8 INX &2945 e8 INX &2946 e0 08 CPX #&08 # Stop after processing quarter-finals &2948 f0 04 BEQ &294e ; find_human_players_opponent &294a e0 0c CPX #&0c ; 8 + 4 # Stop after processing semi-finals &294c d0 ec BNE &293a ; set_winners_of_pairings_loop ; find_human_player_opponent &294e a2 0d LDX #&0d ; (8 + 4 + 2) - 1 &2950 a9 08 LDA #&08 ; PLAYER_PLAYER_ONE ; find_human_player_slot_loop # Find slot containing human player &2952 dd 07 08 CMP &0807,X ; tournament_players &2955 f0 04 BEQ &295b ; found_human_player_slot &2957 ca DEX &2958 10 f8 BPL &2952 ; find_human_player_slot_loop # Should always branch &295a e8 INX # Should never be executed ; found_human_player_slot &295b 8a TXA &295c 49 01 EOR #&01 # Find human player's next opponent &295e aa TAX &295f bd 07 08 LDA &0807,X ; tournament_players &2962 85 97 STA &97 ; tournament_opponent &2964 85 8e STA &8e ; computer_player &2966 20 15 27 JSR &2715 ; plot_tournament_strings &2969 20 f5 2c JSR &2cf5 ; wait_for_space &296c 4c be 10 JMP &10be ; menu_screen_then_start_or_continue_frame ; set_winner_of_pairing &296f a6 8d LDX &8d ; slot &2971 8a TXA # X = first slot of pairing &2972 4a LSR A &2973 a8 TAY # Y = offset for winner slot &2974 a9 08 LDA #&08 ; PLAYER_PLAYER_ONE &2976 dd 07 08 CMP &0807,X ; tournament_players &2979 f0 21 BEQ &299c ; set_winner # If either slot in pair is the human player, &297b e8 INX &297c dd 07 08 CMP &0807,X ; tournament_players &297f f0 1b BEQ &299c ; set_winner # then the human player is always the winner &2981 ca DEX ; get_random_number_between_0_and_4_loop &2982 20 0d 30 JSR &300d ; rnd &2985 29 07 AND #&07 &2987 c9 05 CMP #&05 &2989 b0 f7 BCS &2982 ;get_random_number_between_0_and_4_loop &298b e9 02 SBC #&02 # Get a random number between -2 and 2 &298d 18 CLC &298e 7d 07 08 ADC &0807,X ; tournament_players # Otherwise, compare the two computer players' skill &2991 dd 08 08 CMP &0808,X ; tournament_players + 1 # levels, applying an element of randomness &2994 bd 07 08 LDA &0807,X ; tournament_players &2997 b0 03 BCS &299c ; set_winner &2999 bd 08 08 LDA &0808,X ; tournament_players + 1 ; set_winner &299c 99 0f 08 STA &080f,Y ; tournament_players + 8 &299f 60 RTS ; generate_tournament &29a0 a2 0e LDX #&0e &29a2 a9 ff LDA #&ff ; clear_tournament_players_loop &29a4 9d 07 08 STA &0807,X ; tournament_players # Set to negative to indicate no player in slot &29a7 ca DEX &29a8 10 fa BPL &29a4 ; clear_tournament_players_loop &29aa 20 eb 29 JSR &29eb ; plot_tournament_strings_and_delay &29ad a9 06 LDA #&06 &29af 85 8d STA &8d ; player ; randomly_allocate_players_to_slots # For each computer player, ; find_random_empty_slot_loop # find an empty slot &29b1 20 0d 30 JSR &300d ; rnd &29b4 29 07 AND #&07 &29b6 aa TAX &29b7 bd 07 08 LDA &0807,X ; tournament_players # Positive if slot already has player &29ba 10 f5 BPL &29b1 ; find_random_empty_slot_loop &29bc a5 8d LDA &8d ; player &29be 9d 07 08 STA &0807,X ; tournament_players # Put computer player in slot &29c1 20 e6 29 JSR &29e6 ; plot_tournament_strings_with_sound_and_delay &29c4 c6 8d DEC &8d ; player &29c6 10 e9 BPL &29b1 ; randomly_allocate_players_to_slots &29c8 a2 07 LDX #&07 ; find_empty_slot_loop # Find remaining empty slot &29ca bd 07 08 LDA &0807,X ; tournament_players &29cd 30 05 BMI &29d4 ; found_empty_slot &29cf ca DEX &29d0 10 f8 BPL &29ca ; find_empty_slot_loop # Should always branch &29d2 a2 00 LDX #&00 # Should never be executed ; found_empty_slot &29d4 a9 08 LDA #&08 ; PLAYER_PLAYER_ONE &29d6 9d 07 08 STA &0807,X ; tournament_players # Put human player in slot &29d9 8a TXA &29da 49 01 EOR #&01 # Find first computer opponent &29dc aa TAX &29dd bd 07 08 LDA &0807,X ; tournament_players &29e0 85 97 STA &97 ; tournament_opponent &29e2 a9 00 LDA #&00 &29e4 85 96 STA &96 ; tournament_stage ; plot_tournament_strings_with_sound_and_delay &29e6 a9 02 LDA #&02 : SOUND_POT &29e8 20 20 30 JSR &3020 ; start_sound # Play sound for placing player in tournament ; plot_tournament_strings_and_delay &29eb 20 15 27 JSR &2715 ; plot_tournament_strings &29ee 18 CLC &29ef a5 28 LDA &28 ; vsync_counter &29f1 69 0f ADC #&0f &29f3 aa TAX ; delay_loop # Wait for 15 v-syncs, shuffling rnd state throughout &29f4 20 0d 30 JSR &300d ; rnd &29f7 e4 28 CPX &28 ; vsync_counter &29f9 10 f9 BPL &29f4 ; delay_loop &29fb 60 RTS ; prepare_power_gauge_and_player_string &29fc a5 30 LDA &30 ; player_strike_power &29fe 4a LSR A # Carry set if strike power is odd &29ff aa TAX &2a00 a9 2e LDA #&2e ; POWER_GAUGE_HALF_END # If so, A = &2f : POWER_GAUGE_FULL_END &2a02 69 00 ADC #&00 &2a04 9d 62 35 STA &3562,X ; string_4a + 1 # Set character for end of power gauge &2a07 8a TXA &2a08 f0 09 BEQ &2a13 ; skip_filling_power_gauge &2a0a a8 TAY &2a0b a9 2d LDA #&2d ; POWER_GAUGE_FULL ; fill_power_gauge_loop &2a0d 88 DEY &2a0e 99 62 35 STA &3562,Y ; string_4a + 1 # Set character for full part of power gauge &2a11 d0 fa BNE &2a0d ; fill_power_gauge_loop ; skip_filling_power_gauge &2a13 e0 07 CPX #&07 &2a15 b0 0a BCS &2a21 ; skip_padding_power_gauge ; pad_power_gauge_loop &2a17 a9 30 LDA #&30 ; POWER_GAUGE_EMPTY &2a19 e8 INX &2a1a 9d 62 35 STA &3562,X ; string_4a + 1 # Set character for empty part of power gauge &2a1d e0 07 CPX #&07 &2a1f 90 f8 BCC &2a19 ; pad_power_gauge_loop ; skip_padding_power_gauge &2a21 20 cb 2c JSR &2ccb ; get_player_strings # Returns X = player one string, Y = player two string &2a24 8a TXA &2a25 a6 78 LDX &78 ; active_player &2a27 f0 01 BEQ &2a2a ; set_player_string &2a29 98 TYA ; set_player_string &2a2a 8d 40 2f STA &2f40 ; string_data + &9c + 3 # Set player string &2a2d 60 RTS ; prepare_tournament_strings &2a2e a2 0d LDX #&0d ; (8 + 4 + 2) - 1 ; prepare_tournament_strings_loop # For each slot in the tournament, &2a30 8a TXA &2a31 4a LSR A &2a32 a8 TAY &2a33 b9 0f 08 LDA &080f,Y ; tournament_players + 8 # Has the result of this pairing been decided? &2a36 10 02 BPL &2a3a ; parent_slot_has_player &2a38 a9 fe LDA #&fe # &fe isn't equal to any player ; parent_slot_has_player &2a3a 85 0c STA &0c ; parent_player &2a3c 8a TXA &2a3d 0a ASL A &2a3e 0a ASL A &2a3f a8 TAY &2a40 bd 07 08 LDA &0807,X ; tournament_players &2a43 0a ASL A &2a44 90 02 BCC &2a48 ; set_tournament_player_string # If top bit set, slot doesn't have player &2a46 a9 3c LDA #&3c ; string_3c : " - - - - - " ; set_tournament_player_string &2a48 99 f0 2e STA &2ef0,Y ; string_data + &4c + 3 &2a4b bd 07 08 LDA &0807,X ; tournament_players &2a4e c5 0c CMP &0c ; parent_player # Carry set if player won pairing &2a50 f0 01 BEQ &2a53 ; player_won_pairing &2a52 18 CLC # Carry clear if player hasn't won or didn't win pairing ; player_won_pairing &2a53 a9 00 LDA #&00 ; black on white # Use black on white for players that won pairing &2a55 b0 02 BCS &2a59 ; set_tournament_player_colour &2a57 a9 0f LDA #&0f ; white on black # Use white on black otherwise ; set_tournament_player_colour &2a59 99 ed 2e STA &2eed,Y ; string_data + &4c &2a5c ca DEX &2a5d 10 d1 BPL &2a30 ; prepare_tournament_strings_loop &2a5f 60 RTS ; plot_status_text &2a60 20 fc 29 JSR &29fc ; prepare_power_gauge_and_player_string &2a63 a9 00 LDA #&00 &2a65 85 04 STA &04 ; screen_start_address_low &2a67 a5 27 LDA &27 ; buffer_start_address_high &2a69 85 05 STA &05 ; screen_start_address_high &2a6b a2 98 LDX #&98 ; at (22, 0), eor &00, string &4a (power gauge) ; at ( 7, 0), eor &00, string &10 ("PLAYER ONE ") &2a6d a0 a0 LDY #&a0 &2a6f a5 4c LDA &4c ; trick_state # Negative if playing trick &2a71 49 ff EOR #&ff &2a73 25 50 AND &50 ; placing_ball # Negative if placing ball &2a75 10 04 BPL &2a7b ; plot_status_strings &2a77 a2 9c LDX #&9c ; at ( 7, 0), eor &00, string &10 ("PLAYER ONE ") ; at (20, 0), eor &0f, string &4c ("PLACE THE BALL ") &2a79 a0 a4 LDY #&a4 ; plot_status_strings &2a7b 20 31 27 JSR &2731 ; plot_strings &2a7e 24 51 BIT &51 ; permit_swapping_colours # Negative if colours can be swapped &2a80 10 07 BPL &2a89 ; skip_plotting_swap_colours &2a82 a2 a4 LDX #&a4 ; at ( 6, 1), eor &0f, string &4e ("PRESS S TO ") ; at (21, 1), eor &0f, string &50 ("SWAP COLOURS ") &2a84 a0 ac LDY #&ac &2a86 20 31 27 JSR &2731 ; plot_strings ; skip_plotting_swap_colours &2a89 24 7b BIT &7b ; player_has_free_ball # Negative if player has free ball &2a8b 10 0a BPL &2a97 ; leave &2a8d a5 78 LDA &78 ; active_player &2a8f 0a ASL A &2a90 0a ASL A &2a91 69 ac ADC #&ac : at ( 0, 2), eor &0f, string &52 ("FREE BALL ") &2a93 aa TAX &2a94 4c 09 28 JMP &2809 ; plot_string ; leave &2a97 60 RTS ; plot_status_bar &2a98 a9 00 LDA #&00 &2a9a 85 02 STA &02 ; left_ball_screen_address_low &2a9c a9 30 LDA #&30 &2a9e 85 04 STA &04 ; right_ball_screen_address_low &2aa0 a6 27 LDX &27 ; buffer_start_address_high &2aa2 86 03 STX &03 ; left_ball_screen_address_high &2aa4 e8 INX &2aa5 86 05 STX &05 ; right_ball_screen_address_high &2aa7 a9 01 LDA #&01 &2aa9 85 07 STA &07 ; ball_sprite_address_high &2aab 85 09 STA &09 ; bottom_ball_sprite_address_high &2aad a5 71 LDA &71 ; first_player_colour # Negative if colours haven't been decided &2aaf 30 31 BMI &2ae2 ; skip_plotting_first_player_colour &2ab1 d0 19 BNE &2acc ; player_is_potting_dithered_balls ; player_is_potting_solid_balls &2ab3 a9 00 LDA #&00 ; BALL_TYPE_SOLID &2ab5 a6 73 LDX &73 ; solid_balls_remaining &2ab7 d0 02 BNE &2abb ; not_black_solid_player &2ab9 a9 03 LDA #&03 ; BALL_TYPE_BLACK ; not_black_solid_player &2abb 20 56 2b JSR &2b56 ; plot_left_status_ball &2abe a9 01 LDA #&01 ; BALL_TYPE_DITHERED &2ac0 a6 74 LDX &74 ; dithered_balls_remaining &2ac2 d0 02 BNE &2ac6 ; not_black_dithered_opponent &2ac4 a9 03 LDA #&03 ; BALL_TYPE_BLACK ; not_black_dithered_opponent &2ac6 20 86 2b JSR &2b86 ; plot_right_status_ball &2ac9 4c e2 2a JMP &2ae2 ; skip_plotting_first_player_colour ; player_is_potting_dithered_balls &2acc a9 01 LDA #&01 ; BALL_TYPE_DITHERED &2ace a6 74 LDX &74 ; dithered_balls_remaining &2ad0 d0 02 BNE &2ad4 ; not_black_dithered_player &2ad2 a9 03 LDA #&03 ; BALL_TYPE_BLACK ; not_black_dithered_player &2ad4 20 56 2b JSR &2b56 ; plot_left_status_ball &2ad7 a9 00 LDA #&00 ; BALL_TYPE_SOLID &2ad9 a6 73 LDX &73 ; solid_balls_remaining &2adb d0 02 BNE &2adf ; not_black_solid_opponent &2add a9 03 LDA #&03 ; BALL_TYPE_BLACK ; not_black_solid_opponent &2adf 20 86 2b JSR &2b86 ; plot_right_status_ball ; skip_plotting_first_player_colour &2ae2 a5 72 LDA &72 ; cue_balls_remaining # Two if player has free ball &2ae4 c9 02 CMP #&02 &2ae6 90 05 BCC &2aed ; skip_plotting_free_ball &2ae8 a9 02 LDA #&02 ; BALL_TYPE_CUE &2aea 20 52 2b JSR &2b52 ; plot_left_or_right_status_ball ; skip_plotting_free_ball &2aed 24 77 BIT &77 ; flashing_ball_flag # Negative for 24 v-syncs out of 32 &2aef 30 0e BMI &2aff ; plot_cue_ball &2af1 a5 4c LDA &4c ; trick_state # Negative if playing trick &2af3 05 79 ORA &79 ; black_ball_potted # Negative if black ball has been potted &2af5 05 86 ORA &86 ; only_potential_move # Negative if move is potential &2af7 30 06 BMI &2aff ; plot_cue_ball &2af9 20 1f 2b JSR &2b1f ; plot_blank_status_ball &2afc 4c 08 2b JMP &2b08 ; skip_plotting_cue_ball ; plot_cue_ball &2aff a6 72 LDX &72 ; cue_balls_remaining &2b01 f0 05 BEQ &2b08 ; skip_plotting_cue_ball &2b03 a9 02 LDA #&02 ; BALL_TYPE_CUE &2b05 20 52 2b JSR &2b52 ; plot_left_or_right_status_ball ; skip_plotting_cue_ball &2b08 a5 4c LDA &4c ; trick_state # Negative if playing trick &2b0a 49 ff EOR #&ff &2b0c 25 50 AND &50 ; placing_ball # Negative if placing ball &2b0e 30 0c BMI &2b1c ; skip_plotting_middle_ball &2b10 a9 98 LDA #&98 &2b12 85 02 STA &02 ; left_ball_screen_address_low &2b14 a9 02 LDA #&02 ; BALL_TYPE_CUE &2b16 20 56 2b JSR &2b56 ; plot_left_status_ball # Plot middle ball &2b19 20 b6 2b JSR &2bb6 ; plot_strike_point ; skip_plotting_middle_ball &2b1c 4c 60 2a JMP &2a60 ; plot_status_text ; plot_blank_status_ball &2b1f a0 0f LDY #&0f &2b21 18 CLC &2b22 a6 78 LDX &78 ; active_player &2b24 d0 16 BNE &2b3c ; plot_right_blank_status_ball ; plot_left_blank_status_ball &2b26 a5 02 LDA &02 ; left_ball_screen_address_low &2b28 69 40 ADC #&40 &2b2a 85 0c STA &0c ; bottom_ball_screen_address_low &2b2c a5 03 LDA &03 ; left_ball_screen_address_high &2b2e 69 01 ADC #&01 &2b30 85 0d STA &0d ; bottom_ball_screen_address_high ; plot_left_blank_status_ball_loop &2b32 a9 00 LDA #&00 &2b34 91 02 STA (&02),Y ; left_ball_screen_address &2b36 91 0c STA (&0c),Y ; bottom_ball_screen_address &2b38 88 DEY &2b39 10 f7 BPL &2b32 ; plot_left_blank_status_ball_loop &2b3b 60 RTS ; plot_right_blank_status_ball &2b3c a5 04 LDA &04 ; right_ball_screen_address_low &2b3e 69 40 ADC #&40 &2b40 85 0c STA &0c ; bottom_ball_screen_address_low &2b42 a5 05 LDA &05 ; right_ball_screen_address_high &2b44 69 01 ADC #&01 &2b46 85 0d STA &0d ; bottom_ball_screen_address_high &2b48 a9 00 LDA #&00 ; plot_right_blank_status_ball_loop &2b4a 91 04 STA (&04),Y ; right_ball_screen_address &2b4c 91 0c STA (&0c),Y ; bottom_ball_screen_address &2b4e 88 DEY &2b4f 10 f7 BPL &2b48 ; plot_right_blank_status_ball_loop &2b51 60 RTS ; plot_left_or_right_status_ball &2b52 a6 78 LDX &78 ; active_player &2b54 d0 30 BNE &2b86 ; plot_right_status_ball # Non-zero if opponent is active ; plot_left_status_ball &2b56 0a ASL A &2b57 0a ASL A &2b58 0a ASL A &2b59 0a ASL A &2b5a 0a ASL A &2b5b 85 06 STA &06 ; ball_sprite_address_low &2b5d 09 10 ORA #&10 &2b5f 85 08 STA &08 ; bottom_ball_sprite_address_low &2b61 a5 02 LDA &02 ; left_ball_screen_address_low &2b63 69 40 ADC #&40 &2b65 85 0c STA &0c ; bottom_ball_screen_address_low &2b67 a5 03 LDA &03 ; left_ball_screen_address_high &2b69 69 01 ADC #&01 &2b6b 85 0d STA &0d ; bottom_ball_screen_address_high &2b6d a0 0f LDY #&0f ; plot_left_status_ball_loop &2b6f b1 06 LDA (&06),Y ; ball_sprite_address &2b71 91 02 STA (&02),Y ; left_ball_screen_address &2b73 b1 08 LDA (&08),Y ; bottom_ball_sprite_address &2b75 91 0c STA (&0c),Y ; bottom_ball_screen_address &2b77 88 DEY &2b78 10 f5 BPL &2b6f ; plot_left_status_ball_loop &2b7a 18 CLC &2b7b a5 02 LDA &02 ; left_ball_screen_address_low &2b7d 69 10 ADC #&10 &2b7f 85 02 STA &02 ; left_ball_screen_address_low &2b81 90 02 BCC &2b85 ; skip_page &2b83 e6 03 INC &03 ; left_ball_screen_address_high ; skip_page &2b85 60 RTS ; plot_right_status_ball &2b86 0a ASL A &2b87 0a ASL A &2b88 0a ASL A &2b89 0a ASL A &2b8a 0a ASL A &2b8b 85 06 STA &06 ; ball_sprite_address_low &2b8d 09 10 ORA #&10 &2b8f 85 08 STA &08 ; bottom_ball_sprite_address_low &2b91 a5 04 LDA &04 ; right_ball_screen_address_low &2b93 69 40 ADC #&40 &2b95 85 0c STA &0c ; bottom_ball_screen_address_low &2b97 a5 05 LDA &05 ; right_ball_screen_address_high &2b99 69 01 ADC #&01 &2b9b 85 0d STA &0d ; bottom_ball_screen_address_high &2b9d a0 0f LDY #&0f ; plot_right_status_ball_loop &2b9f b1 06 LDA (&06),Y ; ball_sprite_address &2ba1 91 04 STA (&04),Y ; right_ball_screen_address &2ba3 b1 08 LDA (&08),Y ; bottom_ball_sprite_address &2ba5 91 0c STA (&0c),Y ; bottom_ball_screen_address &2ba7 88 DEY &2ba8 10 f5 BPL &2b9f ; plot_right_status_ball_loop &2baa 38 SEC &2bab a5 04 LDA &04 ; right_ball_screen_address_low &2bad e9 10 SBC #&10 &2baf 85 04 STA &04 ; right_ball_screen_address_low &2bb1 b0 02 BCS &2bb5 ; skip_page &2bb3 c6 05 DEC &05 ; right_ball_screen_address_high ; skip_page &2bb5 60 RTS ; plot_strike_point &2bb6 a5 27 LDA &27 ; buffer_start_address_high # Calculate screen address for strike point &2bb8 85 03 STA &03 ; screen_address_high &2bba a6 31 LDX &31 ; player_strike_point &2bbc 8a TXA &2bbd 4a LSR A &2bbe 29 f8 AND #&f8 &2bc0 18 CLC &2bc1 69 98 ADC #&98 &2bc3 85 02 STA &02 ; screen_address_low &2bc5 a5 2f LDA &2f ; player_viewpoint_vertical_rotation &2bc7 4a LSR A &2bc8 4a LSR A &2bc9 18 CLC &2bca 69 03 ADC #&03 &2bcc a8 TAY # Y = row relative to ball &2bcd 29 07 AND #&07 &2bcf 05 02 ORA &02 ; screen_address_low &2bd1 85 02 STA &02 ; screen_address_low &2bd3 8a TXA &2bd4 29 0c AND #&0c # Use strike point divided by four to determine sprite &2bd6 aa TAX # X = offset to strike point sprite &2bd7 c0 08 CPY #&08 # Carry set if strike point is in second group of ball &2bd9 a0 00 LDY #&00 # Y = row of strike point &2bdb 90 14 BCC &2bf1 ; plot_strike_point_row_loop &2bdd 18 CLC &2bde a5 02 LDA &02 ; screen_address_low &2be0 69 08 ADC #&08 &2be2 85 02 STA &02 ; screen_address_low ; move_to_next_group &2be4 18 CLC &2be5 a5 02 LDA &02 ; screen_address_low &2be7 69 38 ADC #&38 # Move down a group &2be9 85 02 STA &02 ; screen_address_low &2beb a5 03 LDA &03 ; screen_address_high &2bed 69 01 ADC #&01 &2bef 85 03 STA &03 ; screen_address_high ; plot_strike_point_row_loop &2bf1 b1 02 LDA (&02),Y ; screen_address # Plot first byte / four pixels of strike point &2bf3 1d f8 3a ORA &3af8,X ; strike_point_left_sprites &2bf6 91 02 STA (&02),Y ; screen_address &2bf8 e0 08 CPX #&08 &2bfa 90 0f BCC &2c0b ; skip_second_byte &2bfc 98 TYA &2bfd 49 08 EOR #&08 # Move right four pixels &2bff a8 TAY &2c00 b1 02 LDA (&02),Y ; screen_address # Plot second byte / four pixels of strike point &2c02 1d 00 3b ORA &3b00,X ; strike_point_right_sprites &2c05 91 02 STA (&02),Y ; screen_address &2c07 98 TYA &2c08 49 08 EOR #&08 # Move left four pixels &2c0a a8 TAY ; skip_second_byte &2c0b e8 INX &2c0c c8 INY # Move down a row &2c0d c0 03 CPY #&03 &2c0f b0 09 BCS &2c1a ; leave &2c11 98 TYA &2c12 65 02 ADC &02 ; screen_address_low &2c14 29 07 AND #&07 &2c16 d0 d9 BNE &2bf1 ; plot_strike_point_row_loop &2c18 f0 ca BEQ &2be4 ; move_to_next_group # Always branches ; leave &2c1a 60 RTS ; apply_rotated_change_of_position_to_ball &2c1b bd 52 0f LDA &0f52,X ; balls_table_x_fraction &2c1e 85 10 STA &10 ; x_fraction &2c20 bd 22 0f LDA &0f22,X ; balls_table_x &2c23 85 11 STA &11 ; x &2c25 bd 62 0f LDA &0f62,X ; balls_table_y_fraction &2c28 85 12 STA &12 ; y_fraction &2c2a bd 42 0f LDA &0f42,X ; balls_table_y &2c2d 85 13 STA &13 ; y &2c2f a0 00 LDY #&00 &2c31 24 7f BIT &7f ; left_pressed &2c33 10 01 BPL &2c36 ; left_not_pressed &2c35 88 DEY ; left_not_pressed &2c36 24 80 BIT &80 ; right_pressed &2c38 10 01 BPL &2c3b ; right_not_pressed &2c3a c8 INY ; right_not_pressed &2c3b a2 00 LDX #&00 &2c3d 8a TXA &2c3e 38 SEC &2c3f e5 2e SBC &2e ; player_viewpoint_horizontal_rotation &2c41 20 98 23 JSR &2398 ; add_rotated_coordinate &2c44 a0 00 LDY #&00 &2c46 24 82 BIT &82 ; down_pressed &2c48 10 01 BPL &2c4b ; down_not_pressed &2c4a 88 DEY ; down_not_pressed &2c4b 24 81 BIT &81 ; up_pressed &2c4d 10 01 BPL &2c50 ; up_not_pressed &2c4f c8 INY ; up_not_pressed &2c50 a2 00 LDX #&00 &2c52 a9 40 LDA #&40 ; 90 degrees &2c54 38 SEC &2c55 e5 2e SBC &2e ; player_viewpoint_horizontal_rotation &2c57 20 98 23 JSR &2398 ; add_rotated_coordinate &2c5a 60 RTS ; add_randomness_to_cue_ball_position &2c5b 20 0d 30 JSR &300d ; rnd &2c5e 18 CLC &2c5f 6d 52 0f ADC &0f52 ; balls_table_x_fraction &2c62 8d 52 0f STA &0f52 ; balls_table_x_fraction &2c65 08 PHP ; overflow &2c66 20 0d 30 JSR &300d ; rnd &2c69 09 f8 ORA #&f8 &2c6b 18 CLC &2c6c 69 04 ADC #&04 &2c6e 28 PLP ; overflow &2c6f 6d 22 0f ADC &0f22 ; balls_table_x &2c72 8d 22 0f STA &0f22 ; balls_table_x &2c75 60 RTS ; apply_changed_position_to_cue_ball &2c76 a2 00 LDX #&00 ; BALL_CUE &2c78 a5 10 LDA &10 ; x_fraction &2c7a 9d 52 0f STA &0f52,X ; balls_table_x_fraction &2c7d a5 11 LDA &11 ; x &2c7f 9d 22 0f STA &0f22,X ; balls_table_x &2c82 a5 12 LDA &12 ; y_fraction &2c84 9d 62 0f STA &0f62,X ; balls_table_y_fraction &2c87 a5 13 LDA &13 ; y &2c89 9d 42 0f STA &0f42,X ; balls_table_y &2c8c 60 RTS ; check_if_ball_is_in_D &2c8d a9 00 LDA #&00 &2c8f 20 92 1a JSR &1a92 ; get_ball_layout_address &2c92 a0 02 LDY #&02 &2c94 b1 02 LDA (&02),Y ; layout_address # Consider ball's initial x fraction &2c96 c5 10 CMP &10 ; x_fraction &2c98 c8 INY &2c99 b1 02 LDA (&02),Y ; layout_address # Consider ball's initial x &2c9b e5 11 SBC &11 ; x &2c9d 10 05 BPL &2ca4 ; skip_inversion &2c9f 49 ff EOR #&ff &2ca1 38 SEC &2ca2 69 00 ADC #&00 ; skip_inversion &2ca4 aa TAX # X = absolute distance from initial x position &2ca5 c8 INY &2ca6 b1 02 LDA (&02),Y ; layout_address # Consider ball's initial y fraction &2ca8 c5 12 CMP &12 ; y_fraction &2caa c8 INY &2cab b1 02 LDA (&02),Y ; layout_address # Consider ball's initial y &2cad e5 13 SBC &13 ; y &2caf 30 18 BMI &2cc9 ; leave_with_carry_set # The "D" is semicircular &2cb1 a8 TAY # Y = distance from initial y position &2cb2 bd 00 05 LDA &0500,X ; squares_high_table &2cb5 19 00 05 ORA &0500,Y ; squares_high_table &2cb8 d0 0f BNE &2cc9 ; leave_with_carry_set # Consider distance from initial position &2cba 18 CLC &2cbb bd 00 04 LDA &0400,X ; squares_low_table &2cbe 79 00 04 ADC &0400,Y ; squares_low_table &2cc1 b0 06 BCS &2cc9 ; leave_with_carry_set &2cc3 c9 71 CMP #&71 &2cc5 b0 02 BCS &2cc9 ; leave_with_carry_set # If X^2 + Y^2 < 0x0071, ball is in "D" &2cc7 18 CLC # Return carry clear to indicate ball is in "D" &2cc8 60 RTS ; leave_with_carry_set &2cc9 38 SEC # Return carry set to indicate ball not in "D" &2cca 60 RTS ; get_player_strings &2ccb 20 d5 2c JSR &2cd5 ; get_players # Returns X = player one, Y = player two &2cce 8a TXA &2ccf 0a ASL A # Multiply by two to get corresponding string &2cd0 aa TAX &2cd1 98 TYA &2cd2 0a ASL A # Multiply by two to get corresponding string &2cd3 a8 TAY &2cd4 60 RTS ; get_players &2cd5 a6 9b LDX &9b ; demo_player_one &2cd7 a4 9c LDY &9c ; demo_player_two &2cd9 a5 87 LDA &87 ; match_type &2cdb c9 02 CMP #&02 ; MATCH_TYPE_DEMO &2cdd f0 15 BEQ &2cf4 ; leave &2cdf a2 08 LDX #&08 ; PLAYER_PLAYER_ONE &2ce1 a4 97 LDY &97 ; tournament_opponent &2ce3 c9 00 CMP #&00 ; MATCH_TYPE_TOURNAMENT &2ce5 f0 0d BEQ &2cf4 ; leave &2ce7 a4 9d LDY &9d ; practice_player &2ce9 c9 03 CMP #&03 ; MATCH_TYPE_PRACTICE &2ceb f0 07 BEQ &2cf4 ; leave &2ced a0 09 LDY #&09 ; PLAYER_PLAYER_TWO &2cef c9 04 CMP #&04 ; MATCH_TYPE_TRICK &2cf1 d0 01 BNE &2cf4 ; leave &2cf3 c8 INY ; &0a : PLAYER_TRICK ; leave &2cf4 60 RTS # Leave with X = player one, Y = player two ; wait_for_space &2cf5 20 0a 2d JSR &2d0a ; wait_for_vsync &2cf8 a9 9d LDA #&9d ; SPACE &2cfa 20 64 32 JSR &3264 ; check_for_keypress &2cfd 10 f6 BPL &2cf5 ; wait_for_space ; wait_for_space_to_be_released &2cff 20 0a 2d JSR &2d0a ; wait_for_vsync &2d02 a9 9d LDA #&9d ; SPACE &2d04 20 64 32 JSR &3264 ; check_for_keypress &2d07 30 f6 BMI &2cff ; wait_for_space_to_be_released &2d09 60 RTS ; wait_for_vsync &2d0a a5 28 LDA &28 ; vsync_counter ; wait_for_vsync_loop &2d0c c5 28 CMP &28 ; vsync_counter &2d0e f0 fc BEQ &2d0c ; wait_for_vsync_loop &2d10 60 RTS ; cue_sound_for_playing # Called with A = sound &2d11 24 86 BIT &86 ; only_potential_move # Negative if move is potential &2d13 30 25 BMI &2d3a ; leave &2d15 84 0d STY &0d ; tmp_y &2d17 86 0c STX &0c ; tmp_x &2d19 a8 TAY &2d1a a5 6b LDA &6b ; vsync_counter_for_update &2d1c 18 CLC &2d1d 69 06 ADC #&06 # Use vsync_counter_for_update + 6, unless &2d1f c5 28 CMP &28 ; vsync_counter &2d21 f0 02 BEQ &2d25 ; use_vsync_counter &2d23 10 05 BPL &2d2a ; add_sound # vsync_counter_for_update + 6 <= vsync_counter, ; use_vsync_counter &2d25 a5 28 LDA &28 ; vsync_counter # in which case, use vsync_counter + 2 &2d27 18 CLC &2d28 69 02 ADC #&02 ; add_sound &2d2a 29 3f AND #&3f &2d2c aa TAX # X = time to play sound &2d2d 98 TYA # Y = sound &2d2e dd 81 07 CMP &0781,X ; pending_sounds &2d31 30 03 BMI &2d36 ; skip_adding_sound # Don't add sound if lesser to existing one at that time &2d33 9d 81 07 STA &0781,X ; pending_sounds ; skip_adding_sound &2d36 a4 0d LDY &0d ; tmp_y &2d38 a6 0c LDX &0c ; tmp_x ; leave &2d3a 60 RTS ; menu_screen &2d3b a5 87 LDA &87 ; match_type &2d3d 38 SEC &2d3e e9 04 SBC #&04 ; MATCH_TYPE_TRICK &2d40 d0 02 BNE &2d44 ; not_trick # If trick, &2d42 85 98 STA &98 ; frame_in_progress # Set to positive to indicate no frame in progress ; not_trick &2d44 20 e4 26 JSR &26e4 ; wipe_menu_area &2d47 20 40 27 JSR &2740 ; prepare_menu_strings &2d4a 20 24 27 JSR &2724 ; plot_menu_strings &2d4d 4c 56 2d JMP &2d56 ; menu_screen_loop ; update_menu_screen &2d50 20 40 27 JSR &2740 ; prepare_menu_strings &2d53 20 27 27 JSR &2727 ; plot_menu_options ; menu_screen_loop &2d56 a9 8e LDA #&8e ; f1 &2d58 20 64 32 JSR &3264 ; check_for_keypress &2d5b 30 68 BMI &2dc5 ; set_keyboard_or_joystick # Set keyboard or joystick if f1 pressed &2d5d a9 8c LDA #&8c ; f3 &2d5f 20 64 32 JSR &3264 ; check_for_keypress &2d62 30 71 BMI &2dd5 ; set_match_type # Set match type if f3 pressed &2d64 a4 87 LDY &87 ; match_type &2d66 88 DEY &2d67 f0 0a BEQ &2d73 ; f5_not_pressed # Ignore f5 if match type is two-player &2d69 a9 8b LDA #&8b ; f5 &2d6b 20 64 32 JSR &3264 ; check_for_keypress &2d6e 10 03 BPL &2d73 ; f5_not_pressed &2d70 4c 26 2e JMP &2e26 ; set_match_options # Set match options if f5 pressed ; f5_not_pressed &2d73 24 98 BIT &98 ; frame_in_progress # Negative if frame in progress &2d75 30 12 BMI &2d89 ; f7_not_pressed &2d77 a5 87 LDA &87 ; match_type &2d79 f0 04 BEQ &2d7f ; is_tournament_or_trick &2d7b c9 04 CMP #&04 ; MATCH_TYPE_TRICK &2d7d d0 0a BNE &2d89 ; f7_not_pressed ; is_tournament_or_trick &2d7f a9 e9 LDA #&e9 ; f7 &2d81 20 64 32 JSR &3264 ; check_for_keypress &2d84 10 03 BPL &2d89 ; f7_not_pressed &2d86 4c 5b 2e JMP &2e5b ; new_tournament_or_edit_trick_layout ; f7_not_pressed &2d89 a0 ff LDY #&ff &2d8b a9 eb LDA #&eb ; f4 &2d8d 20 64 32 JSR &3264 ; check_for_keypress &2d90 30 7a BMI &2e0c ; set_sound_muted # Set to negative if f4 pressed to mute sound &2d92 c8 INY ; 0 &2d93 a9 8d LDA #&8d ; f2 &2d95 20 64 32 JSR &3264 ; check_for_keypress &2d98 30 72 BMI &2e0c ; set_sound_muted # Set to positive if f2 pressed to allow sound &2d9a a9 8a LDA #&8a ; f6 &2d9c 20 64 32 JSR &3264 ; check_for_keypress &2d9f 30 6f BMI &2e10 ; set_colour_scheme # Set to 0 if f6 pressed to use colour scheme &2da1 a0 04 LDY #&04 &2da3 a9 89 LDA #&89 ; f8 &2da5 20 64 32 JSR &3264 ; check_for_keypress &2da8 30 66 BMI &2e10 ; set_colour_scheme # Set to 4 if f8 pressed to use black and white scheme &2daa a9 9d LDA #&9d ; SPACE &2dac 20 64 32 JSR &3264 ; check_for_keypress &2daf 10 a5 BPL &2d56 ; menu_screen_loop ; space_pressed &2db1 a5 87 LDA &87 ; match_type &2db3 38 SEC &2db4 e9 04 SBC #&04 ; MATCH_TYPE_TRICK &2db6 d0 02 BNE &2dba ; not_trick &2db8 85 50 STA &50 ; placing_ball # Set to positive to indicate not placing ball ; not_trick &2dba 18 CLC # Leave with carry clear to continue existing frame &2dbb 24 98 BIT &98 ; frame_in_progress # Negative if frame in progress &2dbd 30 05 BMI &2dc4 ; leave ; set_frame_in_progress &2dbf a9 ff LDA #&ff &2dc1 85 98 STA &98 ; frame_in_progress # Set to negative to indicate frame in progress &2dc3 38 SEC # Leave with carry set to start new frame ; leave &2dc4 60 RTS ; set_keyboard_or_joystick &2dc5 a9 8e LDA #&8e ; f1 &2dc7 20 64 32 JSR &3264 ; check_for_keypress &2dca 30 f9 BMI &2dc5 ; set_keyboard_or_joystick # Wait for f1 to be released &2dcc a5 85 LDA &85 ; keyboard_or_joystick &2dce 49 80 EOR #&80 # Set to positive for keyboard, negative for joystick &2dd0 85 85 STA &85 ; keyboard_or_joystick ; to_update_menu_screen &2dd2 4c 50 2d JMP &2d50 ; update_menu_screen ; set_match_type &2dd5 a9 8c LDA #&8c ; f3 &2dd7 20 64 32 JSR &3264 ; check_for_keypress &2dda 30 f9 BMI &2dd5 ; set_match_type # Wait for f3 to be released &2ddc 24 98 BIT &98 ; frame_in_progress # Negative if frame in progress &2dde 30 65 BMI &2e45 ; concede_frame &2de0 a6 87 LDX &87 ; match_type &2de2 e8 INX &2de3 e0 05 CPX #&05 ; MATCH_TYPE_TRICK + 1 &2de5 90 02 BCC &2de9 ; skip_wraparound &2de7 a2 00 LDX #&00 ; MATCH_TYPE_TOURNAMENT ; skip_wraparound &2de9 86 87 STX &87 ; match_type &2deb e0 02 CPX #&02 ; MATCH_TYPE_DEMO &2ded d0 1a BNE &2e09 ; to_menu_screen ; set_demo_players &2def 20 0d 30 JSR &300d ; rnd &2df2 29 07 AND #&07 # Pick random computer player for player one &2df4 85 9b STA &9b ; demo_player_one ; set_demo_players_loop &2df6 a2 0a LDX #&0a ; shuffle_rnd_loop &2df8 20 0d 30 JSR &300d ; rnd &2dfb ca DEX &2dfc d0 fa BNE &2df8 ; shuffle_rnd_loop &2dfe 20 0d 30 JSR &300d ; rnd &2e01 29 07 AND #&07 # Pick random different computer player for player two &2e03 c5 9b CMP &9b ; demo_player_one &2e05 f0 ef BEQ &2df6 ; set_demo_players_loop &2e07 85 9c STA &9c ; demo_player_two ; to_menu_screen &2e09 4c 3b 2d JMP &2d3b ; menu_screen ; set_sound_muted &2e0c 84 a8 STY &a8 ; sound_muted &2e0e 30 c2 BMI &2dd2 ; to_update_menu_screen # Always branches ; set_colour_scheme &2e10 b9 07 36 LDA &3607,Y ; palette_values &2e13 a2 03 LDX #&03 ; set_palette_value_loop &2e15 5d 03 36 EOR &3603,X ; palette_eors &2e18 8d 21 fe STA &fe21 ; video ULA palette register &2e1b ca DEX &2e1c 10 f7 BPL &2e15 ; set_palette_value_loop &2e1e c8 INY &2e1f 98 TYA &2e20 29 03 AND #&03 &2e22 d0 ec BNE &2e10 ; set_colour_scheme &2e24 f0 ac BEQ &2dd2 ; to_update_menu_screen # Always branches ; set_match_options &2e26 a9 8b LDA #&8b ; f5 &2e28 20 64 32 JSR &3264 ; check_for_keypress &2e2b 30 f9 BMI &2e26 ; set_match_options # Wait for f5 to be released &2e2d a5 87 LDA &87 ; match_type &2e2f c9 03 CMP #&03 ; MATCH_TYPE_PRACTICE &2e31 f0 52 BEQ &2e85 ; set_practice_player &2e33 b0 5e BCS &2e93 ; set_trick_number &2e35 c9 02 CMP #&02 ; MATCH_TYPE_DEMO &2e37 f0 b6 BEQ &2def ; set_demo_players ; is_tournament &2e39 20 e4 26 JSR &26e4 ; wipe_menu_area &2e3c 20 15 27 JSR &2715 ; plot_tournament_strings &2e3f 20 f5 2c JSR &2cf5 ; wait_for_space &2e42 4c 3b 2d JMP &2d3b ; menu_screen ; concede_frame # Concede frame if f3 pressed while frame is in progress &2e45 a9 00 LDA #&00 &2e47 85 98 STA &98 ; frame_in_progress # Set to positive to indicate no frame in progress &2e49 a5 87 LDA &87 ; match_type &2e4b d0 bc BNE &2e09 ; to_menu_screen ; is_tournament &2e4d e6 9a INC &9a ; players_frames_won + 1 # Conceded frame counts as opponent win &2e4f a6 96 LDX &96 ; tournament_stage &2e51 a5 9a LDA &9a ; players_frames_won + 1 &2e53 0a ASL A &2e54 dd 96 36 CMP &3696,X ; frames_per_stage_of_tournament &2e57 b0 16 BCS &2e6f ; new_tournament # End the tournament if the opponent has won the stage &2e59 90 ae BCC &2e09 ; to_menu_screen # Always branches ; new_tournament_or_edit_trick_layout &2e5b a9 e9 LDA #&e9 ; f7 &2e5d 20 64 32 JSR &3264 ; check_for_keypress &2e60 30 f9 BMI &2e5b ; new_tournament_or_edit_trick_layout # Wait for f7 to be released &2e62 a5 87 LDA &87 ; match_type &2e64 c9 04 CMP #&04 ; MATCH_TYPE_TRICK &2e66 d0 07 BNE &2e6f ; new_tournament ; start_placing_ball &2e68 a9 ff LDA #&ff &2e6a 85 50 STA &50 ; placing_ball # Set to negative to indicate placing ball &2e6c 4c bf 2d JMP &2dbf ; set_frame_in_progress ; new_tournament &2e6f a9 00 LDA #&00 &2e71 85 96 STA &96 ; tournament_stage &2e73 85 99 STA &99 ; players_frames_won # Human player &2e75 85 9a STA &9a ; players_frames_won + 1 # Computer player &2e77 85 3c STA &3c ; win_history &2e79 20 e4 26 JSR &26e4 ; wipe_menu_area &2e7c 20 a0 29 JSR &29a0 ; generate_tournament &2e7f 20 f5 2c JSR &2cf5 ; wait_for_space &2e82 4c 3b 2d JMP &2d3b ; menu_screen ; set_practice_player &2e85 a6 9d LDX &9d ; practice_player &2e87 e8 INX &2e88 e0 07 CPX #&07 ; PLAYER_MALTESE_JOE # Can't practice against Maltese Joe &2e8a 90 02 BCC &2e8e ; skip_wraparound &2e8c a2 00 LDX #&00 ; skip_wraparound &2e8e 86 9d STX &9d ; practice_player &2e90 4c 50 2d JMP &2d50 ; update_menu_screen ; set_trick_number &2e93 a6 a2 LDX &a2 ; trick_number &2e95 e8 INX &2e96 e0 0f CPX #&0f # actually CPX maximum_trick_number &2e98 90 02 BCC &2e9c ; skip_wraparound &2e9a a2 00 LDX #&00 ; skip_wraparound &2e9c 86 a2 STX &a2 ; trick_number &2e9e 4c 50 2d JMP &2d50 ; update_menu_screen ; string_data ; c addr s &2ea1 0f 10 00 18 ; &00 : at ( 2, 0), white on black, string &18 ("---------------------------- ") &2ea5 0f 50 01 16 ; &04 : at ( 2, 1), white on black, string &16 ("MALTESE JOE PLAYS 3-D POOL ") &2ea9 0f 90 02 18 ; &08 : at ( 2, 2), white on black, string &18 ("---------------------------- ") &2ead 0f 80 07 40 ; &0c : at ( 0, 6), white on black, string &40 ("QUARTER FINALS ") # String modified &2eb1 0f 00 08 48 ; &10 : at (16, 6), white on black, string &48 ("BEST OF 3 FRAMES ") # String modified &2eb5 0f 70 05 20 ; &14 : at (14, 4), white on black, string &20 ("-VS- ") # String modified &2eb9 0f d0 08 24 ; &18 : at ( 2, 7), white on black, string &24 ("F1 INPUT TYPE - ") &2ebd 0f 10 0a 26 ; &1c : at ( 2, 8), white on black, string &26 ("F3 MATCH TYPE - ") # String modified &2ec1 0f 50 0b 2c ; &20 : at ( 2, 9), white on black, string &2c ("F5 VIEW PAIRINGS ") &2ec5 0f 90 0c 34 ; &24 : at ( 2, 10), white on black, string &34 ("F7 ENTER NEW TOURNAMENT ") # String modified &2ec9 0f 28 0f 60 ; &28 : at ( 5, 12), white on black, string &60 ("PRESS SPACE TO START ") # String modified &2ecd 0f 88 11 1a ; &2c : at ( 1, 14), white on black, string &1a ("PROGRAMME + DESIGN - ORLANDO ") &2ed1 0f c0 12 1c ; &30 : at ( 0, 15), white on black, string &1c ("COPYRIGHT 1989 AARDVARK SOFTWARE ") &2ed5 0f 08 14 1e ; &34 : at ( 1, 16), white on black, string &1e ("PUBLISHED BY FIREBIRD SOFTWARE ") &2ed9 0f 08 05 10 ; &38 : at ( 1, 4), white on black, string &10 ("PLAYER ONE ") # String modified &2edd 0f a0 05 12 ; &3c : at (20, 4), white on black, string &12 ("PLAYER TWO ") # String modified &2ee1 0f 60 09 38 ; &40 : at (20, 7), white on black, string &38 ("KEYBOARD ") # String modified &2ee5 0f 50 09 54 ; &44 : at (18, 7), white on black, string &54 ("TOURNAMENT ") # Address and string modified &2ee9 0f e0 0c 5e ; &48 : at (12, 10), white on black, string &5e (" GAME IN PROGRESS ") &2eed 0f e0 01 10 ; &4c : at (20, 1), white on black, string &10 ("PLAYER ONE ") # String modified &2ef1 0f 60 04 00 ; &50 : at (20, 3), white on black, string &00 ("FLASH HARRY ") # String modified &2ef5 0f e0 06 02 ; &54 : at (20, 5), white on black, string &02 ("NO-GOOD NIK ") # String modified &2ef9 0f 60 09 04 ; &58 : at (20, 7), white on black, string &04 ("CATFORD KID ") # String modified &2efd 0f e0 0b 06 ; &5c : at (20, 9), white on black, string &06 ("FAST FREDDY ") # String modified &2f01 0f 60 0e 08 ; &60 : at (20, 11), white on black, string &08 ("MIGHTY MIKE ") # String modified &2f05 0f e0 10 0a ; &64 : at (20, 13), white on black, string &0a ("BILLY T KID ") # String modified &2f09 0f 60 13 0c ; &68 : at (20, 15), white on black, string &0c ("JAC DERRIDA ") # String modified &2f0d 0f e0 02 3c ; &6c : at (12, 2), white on black, string &3c (" - - - - - ") # String modified &2f11 0f e0 07 3c ; &70 : at (12, 6), white on black, string &3c (" - - - - - ") # String modified &2f15 0f e0 0c 3c ; &74 : at (12, 10), white on black, string &3c (" - - - - - ") # String modified &2f19 0f e0 11 3c ; &78 : at (12, 14), white on black, string &3c (" - - - - - ") # String modified &2f1d 0f 20 05 3c ; &7c : at ( 4, 4), white on black, string &3c (" - - - - - ") # String modified &2f21 0f 20 0f 3c ; &80 : at ( 4, 12), white on black, string &3c (" - - - - - ") # String modified &2f25 0f c8 08 54 ; &84 : at ( 1, 7), white on black, string &54 ("TOURNAMENT ") &2f29 0f 08 0a 3e ; &88 : at ( 1, 8), white on black, string &3e ("WINNER CHALLENGES ") &2f2d 0f 48 0b 0e ; &8c : at ( 1, 9), white on black, string &0e ("MALTESE JOE ") &2f31 0f 08 00 40 ; &90 : at ( 1, 0), white on black, string &40 ("QUARTER FINALS ") # String modified &2f35 0f 08 14 48 ; &94 : at ( 1, 16), white on black, string &48 ("BEST OF 3 FRAMES ") &2f39 00 b0 00 4a ; &98 : at (22, 0), black on white, string &4a (power gauge) &2f3d 00 38 00 10 ; &9c : at ( 7, 0), black on white, string &10 ("PLAYER ONE ") # String modified &2f41 0f a0 00 4c ; &a0 : at (20, 0), white on black, string &4c ("PLACE THE BALL ") &2f45 0f 70 01 4e ; &a4 : at ( 6, 1), white on black, string &4e ("PRESS S TO ") &2f49 0f e8 01 50 ; &a8 : at (21, 1), white on black, string &50 ("SWAP COLOURS ") &2f4d 0f 80 02 52 ; &ac : at ( 0, 2), white on black, string &52 ("FREE BALL ") &2f51 0f 78 03 52 ; &b0 : at (31, 2), white on black, string &52 ("FREE BALL ") &2f55 0f e0 02 64 ; &b4 : at (12, 2), white on black, string &64 ("WELL DONE ") &2f59 0f 98 06 10 ; &b8 : at (11, 5), white on black, string &10 ("PLAYER ONE ") &2f5d 0f a8 11 62 ; &bc : at ( 5, 14), white on black, string &62 ("PRESS SPACE TO CONTINUE ") &2f61 0f a0 01 64 ; &c0 : at (12, 1), white on black, string &64 ("WELL DONE ") &2f65 0f 18 04 10 ; &c4 : at (11, 3), white on black, string &10 ("PLAYER ONE ") &2f69 0f 58 06 6c ; &c8 : at ( 3, 5), white on black, string &6c ("YOU HAVE BEATEN ") &2f6d 0f d8 06 0e ; &cc : at (19, 5), white on black, string &0e ("MALTESE JOE ") &2f71 0f 68 0b 6e ; &d0 : at ( 5, 9), white on black, string &6e ("YOUR WIN-CODE IS ------ ") &2f75 0f e8 0d 70 ; &d4 : at ( 5, 11), white on black, string &70 ("MAKE A NOTE OF IT NOW!! ") &2f79 0f e8 12 60 ; &d8 : at ( 5, 15), white on black, string &60 ("PRESS SPACE TO START ") &2f7d 0f a8 16 62 ; &dc : at ( 5, 18), white on black, string &62 ("PRESS SPACE TO CONTINUE ") &2f81 0f 60 0f 64 ; &e0 : at (12, 12), white on black, string &64 ("WELL DONE ") &2f85 0f 20 04 66 ; &e4 : at (12, 3), white on black, string &66 ("HARD LUCK ") &2f89 0f d8 07 10 ; &e8 : at (11, 6), white on black, string &10 ("PLAYER ONE ") &2f8d 0f a8 11 62 ; &ec : at ( 5, 14), white on black, string &62 ("PRESS SPACE TO CONTINUE ") &2f91 00 90 00 68 ; &f0 : at (18, 0), black on white, string &68 ("HMMMMMM.... ") &2f95 00 90 00 6a ; &f4 : at (18, 0), black on white, string &6a ("THINKING... ") ; string_addresses &2f99 ff 32 ; &00 = &32ff = string_00 &2f9b 0a 33 ; &02 = &330a = string_02 &2f9d 15 33 ; &04 = &3315 = string_04 &2f9f 20 33 ; &06 = &3320 = string_06 &2fa1 2b 33 ; &08 = &332b = string_08 &2fa3 36 33 ; &0a = &3336 = string_0a &2fa5 41 33 ; &0c = &3341 = string_0c &2fa7 4c 33 ; &0e = &334c = string_0e &2fa9 e9 32 ; &10 = &32e9 = string_10 &2fab f4 32 ; &12 = &32f4 = string_12 &2fad 57 33 ; &14 = &3357 = string_14 &2faf a8 32 ; &16 = &32a8 = string_16 &2fb1 c4 32 ; &18 = &32c4 = string_18 &2fb3 a4 34 ; &1a = &34a4 = string_1a &2fb5 c2 34 ; &1c = &34c2 = string_1c &2fb7 e2 34 ; &1e = &34e2 = string_1e &2fb9 e0 32 ; &20 = &32e0 = string_20 &2fbb e4 32 ; &22 = &32e4 = string_22 &2fbd 62 33 ; &24 = &3362 = string_24 &2fbf 72 33 ; &26 = &3372 = string_26 &2fc1 82 33 ; &28 = &3382 = string_28 &2fc3 9a 33 ; &2a = &339a = string_2a &2fc5 af 33 ; &2c = &33af = string_2c &2fc7 c0 33 ; &2e = &33c0 = string_2e &2fc9 d1 33 ; &30 = &33d1 = string_30 &2fcb e3 33 ; &32 = &33e3 = string_32 &2fcd f4 33 ; &34 = &33f4 = string_34 &2fcf 0c 34 ; &36 = &340c = string_36 &2fd1 9c 34 ; &38 = &349c = string_38 &2fd3 94 34 ; &3a = &3494 = string_3a &2fd5 00 35 ; &3c = &3500 = string_3c &2fd7 0b 35 ; &3e = &350b = string_3e &2fd9 1c 35 ; &40 = &351c = string_40 &2fdb 2a 35 ; &42 = &352a = string_42 &2fdd 35 35 ; &44 = &3535 = string_44 &2fdf 43 35 ; &46 = &3543 = string_46 &2fe1 51 35 ; &48 = &3551 = string_48 &2fe3 61 35 ; &4a = &3561 = string_4a &2fe5 6b 35 ; &4c = &356b = string_4c &2fe7 79 35 ; &4e = &3579 = string_4e &2fe9 86 35 ; &50 = &3586 = string_50 &2feb 92 35 ; &52 = &3592 = string_52 &2fed 62 34 ; &54 = &3462 = string_54 &2fef 6c 34 ; &56 = &346c = string_56 &2ff1 76 34 ; &58 = &3476 = string_58 &2ff3 80 34 ; &5a = &3480 = string_5a &2ff5 8a 34 ; &5c = &348a = string_5c &2ff7 26 34 ; &5e = &3426 = string_5e &2ff9 37 34 ; &60 = &3437 = string_60 &2ffb 4b 34 ; &62 = &344b = string_62 &2ffd ba 35 ; &64 = &35ba = string_64 &2fff b1 35 ; &66 = &35b1 = string_66 &3001 a6 35 ; &68 = &35a6 = string_68 &3003 9b 35 ; &6a = &359b = string_6a &3005 c3 35 ; &6c = &35c3 = string_6c &3007 d3 35 ; &6e = &35d3 = string_6e &3009 eb 35 ; &70 = &35eb = string_70 &300b 02 36 ; &72 = &3602 = string_72 ; rnd &300d a5 89 LDA &89 ; rnd_state &300f 18 CLC &3010 69 55 ADC #&55 &3012 4d 48 fe EOR &fe48 ; System VIA timer 2 counter LSB &3015 6d 64 fe ADC &fe64 ; User VIA timer 1 counter LSB &3018 c9 80 CMP #&80 &301a 2a ROL A &301b 85 89 STA &89 ; rnd_state &301d 45 28 EOR &28 ; vsync_counter &301f 60 RTS ; start_sound &3020 0a ASL A &3021 a8 TAY &3022 38 SEC &3023 d8 CLD &3024 08 PHP ; processor status &3025 78 SEI &3026 b9 10 3b LDA &3b10,Y ; sound_data_addresses &3029 8d d9 30 STA &30d9 ; sound_address_low &302c f9 12 3b SBC &3b12,Y ; sound_data_addresses + 2 &302f 85 6c STA &6c ; sound_length_low &3031 b9 11 3b LDA &3b11,Y ; sound_data_addresses + 1 &3034 8d da 30 STA &30da ; sound_address_high &3037 f9 13 3b SBC &3b13,Y ; sound_data_addresses + 3 &303a 85 6d STA &6d ; sound_length_high &303c a0 05 LDY #&05 ; delay_loop &303e 88 DEY &303f d0 fd BNE &303e ; delay_loop &3041 a0 ff LDY #&ff # Set all bits to to output &3043 8c 43 fe STY &fe43 ; System VIA data direction register A &3046 a0 01 LDY #&01 # Set to one to use top nibble first &3048 84 6e STY &6e ; sound_nibble &304a a9 ff LDA #&ff # Set channel 0 volume to 0 &304c 8d 41 fe STA &fe41 ; System VIA output register A # Write byte to sound chip &304f a9 00 LDA #&00 # Set sound chip write pin low &3051 8d 40 fe STA &fe40 ; System VIA port B input/output register &3054 a9 c0 LDA #&c0 # Enable interrupts for timer 1 &3056 8d 4e fe STA &fe4e ; System VIA interrupt enable register &3059 2c 44 fe BIT &fe44 ; System VIA timer 1 counter LSB # Clear interrupt &305c 28 PLP ; processor status &305d ea NOP &305e 60 RTS ; write_byte_to_sound_chip &305f 8d 41 fe STA &fe41 ; System VIA output register A # Write byte to sound chip &3062 a9 00 LDA #&00 # Set sound chip write pin low &3064 8d 40 fe STA &fe40 ; System VIA port B input/output register &3067 20 72 30 JSR &3072 ; push_and_pull # Short delay &306a 20 72 30 JSR &3072 ; push_and_pull &306d a9 08 LDA #&08 # Set sound chip write pin high &306f 8d 40 fe STA &fe40 ; System VIA port B input/output register ; push_and_pull &3072 48 PHA &3073 68 PLA &3074 60 RTS ; handle_adc_interrupt &3075 8e 89 30 STX &3089 ; tmp_x &3078 ad c1 fe LDA &fec1 ; ADC data high # or LDA &fe19 ; ADC data high on Master &307b a6 a3 LDX &a3 ; adc_channel &307d 95 a4 STA &a4,X ; adc_channel_values &307f e8 INX &3080 8a TXA &3081 29 03 AND #&03 &3083 8d c0 fe STA &fec0 ; ADC start conversion # Start 8 bit conversion on next channel # or STA &fe18 ; ADC start conversion on Master &3086 85 a3 STA &a3 ; adc_channel &3088 a2 00 LDX #&00 # actually LDX tmp_x &308a 2c 40 fe BIT &fe40 ; System VIA port B input/output register # Clear interrupt &308d a5 fc LDA &fc ; irq_accumulator &308f 40 RTI ; handle_vsync_interrupt &3090 20 62 31 JSR &3162 ; event_handler &3093 2c 41 fe BIT &fe41 ; System VIA output register A # Clear interrupt &3096 2c c0 fe BIT &fec0 ; ADC conversion status # or BIT &fe18 ; ADC conversion status on Master &3099 10 da BPL &3075 ; handle_adc_interrupt # &80 clear if conversion completed &309b 70 03 BVS &30a0 ; start_adc_conversion # &40 set if ADC not busy &309d a5 fc LDA &fc ; irq_accumulator &309f 40 RTI ; start_adc_conversion &30a0 8a TXA &30a1 48 PHA ; tmp_x &30a2 a6 a3 LDX &a3 ; adc_channel &30a4 e8 INX &30a5 8a TXA &30a6 29 03 AND #&03 &30a8 8d c0 fe STA &fec0 ; ADC start conversion # Start 8 bit conversion on next channel # or STA &fe18 ; ADC start conversion on Master &30ab 85 a3 STA &a3 ; adc_channel &30ad 68 PLA ; tmp_x &30ae aa TAX &30af a5 fc LDA &fc ; irq_accumulator &30b1 40 RTI ; not_timer_1_interrupt &30b2 ad 4d fe LDA &fe4d ; System VIA interrupt flag register &30b5 29 10 AND #&10 # &10 set if end of analogue conversion interrupt &30b7 d0 bc BNE &3075 ; handle_adc_interrupt &30b9 ad 4d fe LDA &fe4d ; System VIA interrupt flag register &30bc 29 02 AND #&02 # &02 set if v-sync interrupt &30be d0 d0 BNE &3090 ; handle_vsync_interrupt &30c0 a5 fc LDA &fc ; irq_accumulator &30c2 40 RTI ; jmp_to_previous_irq1_vector # Unused &30c3 4c ff ff JMP &ffff # actually JMP previous_irq1_vector ; irq1_handler &30c6 2c 4d fe BIT &fe4d ; System VIA interrupt flag register # &40 set if timer 1 interrupt occurred &30c9 50 e7 BVC &30b2 ; not_timer_1_interrupt &30cb 2c 4e fe BIT &fe4e ; System VIA interrupt enable register # &40 set if timer 1 interrupts enabled &30ce 50 e2 BVC &30b2 ; not_timer_1_interrupt ; handle_timer_1_interrupt &30d0 2c 44 fe BIT &fe44 ; System VIA timer 1 counter LSB # Clear interrupt &30d3 a9 08 LDA #&08 # Set sound chip write pin high &30d5 8d 40 fe STA &fe40 ; System VIA port B input/output register &30d8 ad ff ff LDA &ffff ; actually LDA sound_address &30db c6 6e DEC &6e ; sound_nibble &30dd 10 3c BPL &311b ; use_top_nibble ; use_bottom_nibble &30df 29 0f AND #&0f &30e1 49 9f EOR #&9f # Set channel 3 volume &30e3 8d 41 fe STA &fe41 ; System VIA output register A # Write byte to sound chip &30e6 48 PHA ; sound chip byte &30e7 a9 00 LDA #&00 # Set sound chip write pin low &30e9 8d 40 fe STA &fe40 ; System VIA port B input/output register &30ec a9 01 LDA #&01 # Set to one to use top nibble next &30ee 85 6e STA &6e ; sound_nibble &30f0 ee d9 30 INC &30d9 ; sound_address_low &30f3 f0 20 BEQ &3115 ; is_page ; skip_page &30f5 a9 08 LDA #&08 # Set sound chip write pin high &30f7 8d 40 fe STA &fe40 ; System VIA port B input/output register &30fa 68 PLA ; sound_chip_byte &30fb e6 6c INC &6c ; sound_length_low &30fd f0 32 BEQ &3131 ; check_for_end_of_sound &30ff 49 9f EOR #&9f # Remove bits for channel 3 volume &3101 4a LSR A # Use top two bits of nibble &3102 4a LSR A &3103 49 8b EOR #&8b # Set channel 3 frequency high &3105 8d 41 fe STA &fe41 ; System VIA output register A # Write byte to sound chip &3108 a9 00 LDA #&00 # Set sound chip write pin low &310a 8d 40 fe STA &fe40 ; System VIA port B input/output register &310d 2c c0 fe BIT &fec0 ; ADC conversion status # or BIT &fe18 ; ADC conversion status on Master &3110 10 4d BPL &315f ; to_handle_adc_interrupt # &80 clear if conversion completed &3112 a5 fc LDA &fc ; irq_accumulator &3114 40 RTI ; is_page &3115 ee da 30 INC &30da ; sound_address_high &3118 4c f5 30 JMP &30f5 ; skip_page ; use_top_nibble &311b 4a LSR A &311c 4a LSR A &311d 4a LSR A &311e 4a LSR A &311f 49 9f EOR #&9f # Set channel 3 volume &3121 8d 41 fe STA &fe41 ; System VIA output register A &3124 a9 00 LDA #&00 # Set sound chip write pin low &3126 8d 40 fe STA &fe40 ; System VIA port B input/output register ; leave_after_checking_adc &3129 2c c0 fe BIT &fec0 ; ADC conversion status # or BIT &fe18 ; ADC conversion status on Master &312c 10 31 BPL &315f ; to_handle_adc_interrupt # &80 clear if conversion completed &312e a5 fc LDA &fc ; irq_accumulator &3130 40 RTI ; check_for_end_of_sound &3131 e6 6d INC &6d ; sound_length_high &3133 d0 f4 BNE &3129 ; leave_after_checking_adc ; end_of_sound &3135 48 PHA # Short delay &3136 68 PLA &3137 48 PHA &3138 68 PLA &3139 48 PHA &313a 68 PLA &313b a9 9f LDA #&9f # Set channel 3 volume to 0 &313d 20 5f 30 JSR &305f ; write_byte_to_sound_chip &3140 a9 bf LDA #&bf # Set channel 2 volume to 0 &3142 20 5f 30 JSR &305f ; write_byte_to_sound_chip &3145 a9 df LDA #&df # Set channel 1 volume to 0 &3147 20 5f 30 JSR &305f ; write_byte_to_sound_chip &314a a9 ff LDA #&ff # Set channel 0 volume to 0 &314c 20 5f 30 JSR &305f ; write_byte_to_sound_chip &314f a9 40 LDA #&40 # Disable timer 1 interrupts &3151 8d 4e fe STA &fe4e ; System VIA interrupt enable register &3154 2c 44 fe BIT &fe44 ; System VIA timer 1 counter LSB # Clear interrupt &3157 2c c0 fe BIT &fec0 ; ADC conversion status # or BIT &fe18 ; ADC conversion status on Master &315a 10 03 BPL &315f ; to_handle_adc_interrupt # &80 clear if conversion completed &315c a5 fc LDA &fc ; irq_accumulator &315e 40 RTI ; to_handle_adc_interrupt &315f 4c 75 30 JMP &3075 ; handle_adc_interrupt ; event_handler &3162 08 PHP ; processor status &3163 d8 CLD &3164 85 92 STA &92 ; tmp_a &3166 86 93 STX &93 ; tmp_x &3168 84 94 STY &94 ; tmp_y &316a 24 40 BIT &40 ; crtc_start_address_high # Positive if screen start address needs changing &316c 30 1a BMI &3188 ; skip_changing_screen_start_address &316e 85 92 STA &92 ; tmp_a &3170 a9 0c LDA #&0c ; R12: Displayed screen start address register (high) &3172 8d 00 fe STA &fe00 ; video register number &3175 a5 40 LDA &40 ; crtc_start_address_high &3177 8d 01 fe STA &fe01 ; video register value &317a a9 0d LDA #&0d ; R13: Displayed screen start address register (low) &317c 8d 00 fe STA &fe00 ; video register number &317f a5 41 LDA &41 ; crtc_start_address_low &3181 8d 01 fe STA &fe01 ; video register value &3184 a9 ff LDA #&ff &3186 85 40 STA &40 ; crtc_start_address_high # Set to negative to indicate address has been changed ; skip_changing_screen_start_address &3188 e6 28 INC &28 ; vsync_counter &318a a5 28 LDA &28 ; vsync_counter &318c 29 3f AND #&3f &318e aa TAX &318f bc 81 07 LDY &0781,X ; pending_sounds # Positive if a sound is pending for this time &3192 30 0d BMI &31a1 ; skip_sound &3194 a9 ff LDA #&ff &3196 9d 81 07 STA &0781,X ; pending_sounds # Set to negative to remove pending sound &3199 98 TYA &319a 24 a8 BIT &a8 ; sound_muted # Negative if sound muted &319c 30 03 BMI &31a1 ; skip_sound &319e 20 20 30 JSR &3020 ; start_sound ; skip_sound &31a1 24 95 BIT &95 ; suppress_checking_for_return_or_fire # Negative if checking in progress &31a3 30 03 BMI &31a8 ; skip_checking_for_return_or_fire &31a5 20 e6 31 JSR &31e6 ; check_for_return_or_fire ; skip_checking_for_return_or_fire &31a8 a5 92 LDA &92 ; tmp_a &31aa a6 93 LDX &93 ; tmp_x &31ac a4 94 LDY &94 ; tmp_y &31ae 28 PLP ; processor status &31af 60 RTS ; check_for_player_movement &31b0 20 c5 31 JSR &31c5 ; check_for_directions &31b3 a5 54 LDA &54 ; return_or_fire_pressed &31b5 85 52 STA &52 ; previous_return_or_fire_pressed &31b7 a2 00 LDX #&00 &31b9 24 53 BIT &53 ; return_or_fire_state &31bb 10 05 BPL &31c2 ; set_return_or_fire_double_press &31bd a9 01 LDA #&01 &31bf 85 53 STA &53 ; return_or_fire_state # Set to one to indicate not recently pressed &31c1 ca DEX ; &ff ; set_return_or_fire_double_press &31c2 86 83 STX &83 ; return_or_fire_double_press &31c4 60 RTS ; check_for_directions &31c5 24 85 BIT &85 ; keyboard_or_joystick # Negative if using joystick &31c7 30 46 BMI &320f ; check_for_joystick_directions ; check_for_keyboard_directions &31c9 a9 9e LDA #&9e ; Z &31cb 20 64 32 JSR &3264 ; check_for_keypress # Returns A negative if key pressed &31ce 85 7f STA &7f ; left_pressed # Set to negative to indicate left pressed &31d0 a9 bd LDA #&bd ; X &31d2 20 64 32 JSR &3264 ; check_for_keypress # Returns A negative if key pressed &31d5 85 80 STA &80 ; right_pressed # Set to negative to indicate right pressed &31d7 a9 97 LDA #&97 ; / &31d9 20 64 32 JSR &3264 ; check_for_keypress # Returns A negative if key pressed &31dc 85 82 STA &82 ; down_pressed # Set to negative to indicate down pressed &31de a9 b7 LDA #&b7 ; : &31e0 20 64 32 JSR &3264 ; check_for_keypress # Returns A negative if key pressed &31e3 85 81 STA &81 ; up_pressed # Set to negative to indicate up pressed &31e5 60 RTS ; check_for_return_or_fire &31e6 24 85 BIT &85 ; keyboard_or_joystick # Negative if using joystick &31e8 30 58 BMI &3242 ; check_for_fire &31ea a9 b6 LDA #&b6 ; RETURN &31ec 20 64 32 JSR &3264 ; check_for_keypress ; consider_return_or_fire &31ef c5 54 CMP &54 ; return_or_fire_pressed &31f1 85 54 STA &54 ; return_or_fire_pressed &31f3 f0 09 BEQ &31fe ; skip_resetting_return_or_fire_timer &31f5 0a ASL A # Set carry if return has just been pressed &31f6 90 06 BCC &31fe ; skip_resetting_return_or_fire_timer &31f8 c6 53 DEC &53 ; return_or_fire_state &31fa a9 0f LDA #&0f &31fc 85 55 STA &55 ; return_or_fire_timer ; skip_resetting_return_or_fire_timer &31fe c6 55 DEC &55 ; return_or_fire_timer &3200 10 0c BPL &320e ; leave &3202 a9 80 LDA #&80 &3204 85 55 STA &55 ; return_or_fire_timer &3206 24 53 BIT &53 ; return_or_fire_state &3208 30 04 BMI &320e ; leave &320a a9 01 LDA #&01 &320c 85 53 STA &53 ; return_or_fire_state # Set to one to indicate not recently pressed ; leave &320e 60 RTS ; check_for_joystick_directions &320f a9 00 LDA #&00 # Set to zero to indicate no directions pressed &3211 85 7f STA &7f ; left_pressed &3213 85 80 STA &80 ; right_pressed &3215 85 81 STA &81 ; up_pressed &3217 85 82 STA &82 ; down_pressed ; check_joystick # &3219 - &3231 should be replaced on Master Compact &3219 a5 78 LDA &78 ; active_player &321b a6 87 LDX &87 ; match_type &321d e0 01 CPX #&01 ; MATCH_TYPE_TWO_PLAYER # If this isn't a two-player match, &321f f0 02 BEQ &3223 ; skip_setting_joystick &3221 a9 00 LDA #&00 # Use first joystick ; skip_setting_joystick &3223 0a ASL A # Otherwise use joystick corresponding to player &3224 aa TAX &3225 b5 a4 LDA &a4,X ; adc_channel_values &3227 c9 c0 CMP #&c0 &3229 90 02 BCC &322d ; joystick_not_left &322b c6 7f DEC &7f ; left_pressed # Set to negative to indicate left pressed ; joystick_not_left &322d c9 40 CMP #&40 &322f b0 02 BCS &3233 ; joystick_not_right &3231 c6 80 DEC &80 ; right_pressed # Set to negative to indicate right pressed ; joystick_not_right &3233 b5 a5 LDA &a5,X ; adc_channel_values + 1 &3235 c9 c0 CMP #&c0 &3237 90 02 BCC &323b ; joystick_not_up &3239 c6 81 DEC &81 ; up_pressed # Set to negative to indicate up pressed ; joystick_not_up &323b c9 40 CMP #&40 &323d b0 02 BCS &3241 ; joystick_not_down &323f c6 82 DEC &82 ; down_pressed # Set to negative to indicate down pressed ; joystick_not_down &3241 60 RTS ; check_for_fire # &3242 - &324c is replaced on Master Compact &3242 a9 cf LDA #&cf ; 11001111 # Set PB4 and PB5 (joystick buttons) as inputs &3244 8d 42 fe STA &fe42 ; System VIA data direction register B &3247 a6 78 LDX &78 ; active_player &3249 a5 87 LDA &87 ; match_type &324b c9 01 CMP #&01 ; MATCH_TYPE_TWO_PLAYER # If this isn't a two-player match, &324d f0 02 BEQ &3251 ; skip_setting_joystick &324f a2 00 LDX #&00 # Use first joystick ; skip_setting_joystick &3251 ad 40 fe LDA &fe40 ; System VIA port B input/output register # &10 or &20 clear if joystick fire buttons pressed &3254 e0 00 CPX #&00 &3256 d0 01 BNE &3259 ; not_joystick_one &3258 0a ASL A # &10 set if joystick one fire not pressed; becomes &20 ; not_joystick_one &3259 29 20 AND #&20 # &20 set if joystick two fire not pressed &325b 49 20 EOR #&20 &325d f0 02 BEQ &3261 ; fire_not_pressed &325f a9 ff LDA #&ff # Set to negative to indicate fire pressed ; fire_not_pressed &3261 4c ef 31 JMP &31ef ; consider_return_or_fire ; check_for_keypress &3264 c6 95 DEC &95 ; suppress_checking_for_return_or_fire # Set to negative to indicate checking in progress &3266 8e 93 32 STX &3293 ; tmp_x &3269 8c 95 32 STY &3295 ; tmp_y &326c 2c 4e fe BIT &fe4e ; System VIA interrupt enable register # &40 set if timer 1 interrupts enabled &326f 70 2a BVS &329b ; skip_checking_for_keypress # i.e. sound is being played; skip checking if so &3271 49 7f EOR #&7f &3273 a0 03 LDY #&03 ; 00000011 # Disable keyboard auto scan &3275 a2 7f LDX #&7f &3277 08 PHP &3278 78 SEI &3279 8c 40 fe STY &fe40 ; System VIA port B input/output register &327c 8e 43 fe STX &fe43 ; System VIA data direction register A # Set top bit as output, bottom seven bits as input &327f 8d 4f fe STA &fe4f ; System VIA input/output register A # Write key to check &3282 ad 4f fe LDA &fe4f ; System VIA input/output register A # Get result in top bit &3285 a0 0b LDY #&0b ; 00001011 # Enable keyboard auto scan &3287 8c 40 fe STY &fe40 ; System VIA port B input/output register &328a 28 PLP &328b ea NOP &328c 29 80 AND #&80 # Top bit set if key pressed &328e 10 02 BPL &3292 ; not_pressed &3290 09 7f ORA #&7f ; not_pressed &3292 a2 00 LDX #&00 # actually LDX tmp_x &3294 a0 00 LDY #&00 # actually LDY tmp_y &3296 e6 95 INC &95 ; suppress_checking_for_return_or_fire # Set to positive to indicate checking finished &3298 09 00 ORA #&00 &329a 60 RTS ; skip_checking_for_keypress &329b e6 95 INC &95 ; suppress_checking_for_return_or_fire # Set to positive to indicate checking finished &329d a9 00 LDA #&00 &329f 60 RTS ; unused # Unused code &32a0 c6 95 DEC &95 ; suppress_checking_for_return_or_fire # Set to negative to suppress checking &32a2 20 f4 ff JSR &fff4 ; OSBYTE &32a5 e6 95 INC &95 ; suppress_checking_for_return_or_fire # Set to positive to permit checking &32a7 60 RTS ; strings ; string_16 &32a8 17 0b 16 1e 0f 1d 0f 00 14 19 0f 00 00 1a 16 0b ; "MALTESE JOE PLAYS 3-D POOL" &32b8 23 1d 00 00 04 2a 0e 00 1a 19 19 96 ; string_18 &32c4 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a ; "----------------------------" &32d4 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a aa ; string_20 &32e0 2a 20 1d aa ; "-VS-" ; string_22 # Numbers are overwritten &32e4 01 2a 2a 01 80 ; "0--0 " ; string_10 &32e9 1a 16 0b 23 0f 1c 00 00 19 18 8f ; "PLAYER ONE" ; string_12 &32f4 1a 16 0b 23 0f 1c 00 00 1e 21 99 ; "PLAYER TWO" ; string_00 &32ff 10 16 0b 1d 12 00 12 0b 1c 1c a3 ; "FLASH HARRY" ; string_02 &330a 18 19 2a 11 19 19 0e 00 18 13 95 ; "NO-GOOD NIK" ; string_04 &3315 0d 0b 1e 10 19 1c 0e 00 15 13 8e ; "CATFORD KID" ; string_06 &3320 10 0b 1d 1e 00 10 1c 0f 0e 0e a3 ; "FAST FREDDY" ; string_08 &332b 17 13 11 12 1e 23 00 17 13 15 8f ; "MIGHTY MIKE" ; string_0a &3336 0c 13 16 16 23 00 1e 00 15 13 8e ; "BILLY T KID" ; string_0c &3341 14 0b 0d 00 0e 0f 1c 1c 13 0e 8b ; "JAC DERRIDA" ; string_0e &334c 17 0b 16 1e 0f 1d 0f 00 14 19 8f ; "MALTESE JOE" ; string_14 # Numbers are overwritten &3357 1e 1c 13 0d 15 00 00 2a 01 02 aa ; "TRICK -01-" ; string_24 &3362 10 02 00 00 13 18 1a 1f 1e 00 1e 23 1a 0f 00 aa ; "F1 INPUT TYPE -" ; string_26 &3372 10 04 00 00 17 0b 1e 0d 12 00 1e 23 1a 0f 00 aa ; "F3 MATCH TYPE -" ; string_28 &3382 10 04 00 00 0d 19 18 0d 0f 0e 0f 00 0d 1f 1c 1c ; "F3 CONCEDE CURRENT GAME" &3392 0f 18 1e 00 11 0b 17 8f ; string_2a &339a 10 04 00 00 1d 1e 19 1a 00 0d 1f 1c 1c 0f 18 1e ; "F3 STOP CURRENT GAME" &33aa 00 11 0b 17 8f ; string_2c &33af 10 06 00 00 20 13 0f 21 00 1a 0b 13 1c 13 18 11 ; "F5 VIEW PAIRINGS" &33bf 9d ; string_2e &33c0 10 06 00 00 0d 12 0b 18 11 0f 00 1a 16 0b 23 0f ; "F5 CHANGE PLAYER" &33d0 9c ; string_30 &33d1 10 06 00 00 1e 1c 23 00 18 0f 22 1e 00 1e 1c 13 ; "F5 TRY NEXT TRICK" &33e1 0d 95 ; string_32 &33e3 10 06 00 00 18 0f 21 00 19 1a 1a 19 18 0f 18 1e ; "F5 NEW OPPONENTS" &33f3 9d ; string_34 &33f4 10 08 00 00 0f 18 1e 0f 1c 00 18 0f 21 00 1e 19 ; "F7 ENTER NEW TOURNAMENT" &3404 1f 1c 18 0b 17 0f 18 9e ; string_36 &340c 10 08 00 00 0f 0e 13 1e 00 1e 1c 13 0d 15 00 1d ; "F7 EDIT TRICK SHOT LAYOUT" &341c 12 19 1e 00 16 0b 23 19 1f 9e ; string_5e &3426 00 11 0b 17 0f 00 13 18 00 1a 1c 19 11 1c 0f 1d ; " GAME IN PROGRESS" &3436 9d ; string_60 &3437 1a 1c 0f 1d 1d 00 1d 1a 0b 0d 0f 00 1e 19 00 1d ; "PRESS SPACE TO START" &3447 1e 0b 1c 9e ; string_62 &344b 1a 1c 0f 1d 1d 00 1d 1a 0b 0d 0f 00 1e 19 00 0d ; "PRESS SPACE TO CONTINUE" &345b 19 18 1e 13 18 1f 8f ; string_54 &3462 1e 19 1f 1c 18 0b 17 0f 18 9e ; "TOURNAMENT" ; string_56 &346c 1e 21 19 2a 1a 16 0b 23 0f 9c ; "TWO-PLAYER" ; string_58 &3476 0e 0f 17 19 00 17 19 0e 0f 80 ; "DEMO MODE " ; string_5a &3480 2a 1a 1c 0b 0d 1e 13 0d 0f aa ; "-PRACTICE-" ; string_5c &348a 1e 1c 13 0d 15 00 1a 16 0b a3 ; "TRICK PLAY" ; string_3a &3494 14 19 23 1d 1e 13 0d 95 ; "JOYSTICK" ; string_38 &349c 15 0f 23 0c 19 0b 1c 8e ; "KEYBOARD" ; string_1a &34a4 1a 1c 19 11 1c 0b 17 17 0f 00 29 00 0e 0f 1d 13 ; "PROGRAMME + DESIGN - ORLANDO" &34b4 11 18 00 00 2a 00 00 19 1c 16 0b 18 0e 99 ; string_1c &34c2 0d 19 1a 23 1c 13 11 12 1e 00 02 0a 09 0a 00 0b ; "COPYRIGHT 1989 AARDVARK SOFTWARE" &34d2 0b 1c 0e 20 0b 1c 15 00 1d 19 10 1e 21 0b 1c 8f ; string_1e &34e2 1a 1f 0c 16 13 1d 12 0f 0e 00 0c 23 00 10 13 1c ; "PUBLISHED BY FIREBIRD SOFTWARE" &34f2 0f 0c 13 1c 0e 00 1d 19 10 1e 21 0b 1c 8f ; string_3c &3500 00 2a 00 2a 00 2a 00 2a 00 2a 80 ; " - - - - - " ; string_3e &350b 21 13 18 18 0f 1c 00 0d 12 0b 16 16 0f 18 11 0f ; "WINNER CHALLENGES" &351b 9d ; string_40 &351c 1b 1f 0b 1c 1e 0f 1c 00 10 13 18 0b 16 9d ; "QUARTER FINALS" ; string_42 &352a 1d 0f 17 13 2a 10 13 18 0b 16 9d ; "SEMI-FINALS" ; string_44 &3535 15 18 19 0d 15 19 1f 1e 00 10 13 18 0b 96 ; "KNOCKOUT FINAL" ; string_46 &3543 1a 19 19 16 00 0d 12 0b 16 16 0f 18 11 8f ; "POOL CHALLENGE" ; string_48 # Number is overwritten &3551 0c 0f 1d 1e 00 19 10 00 04 00 10 1c 0b 17 0f 9d ; "BEST OF 3 FRAMES" ; string_4a # Power gauge; numbers are overwritten &3561 2c 31 32 33 34 35 36 37 38 ac ; ",12345678," ; string_4c &356b 1a 16 0b 0d 0f 00 1e 12 0f 00 0c 0b 16 96 ; "PLACE THE BALL" ; string_4e &3579 1a 1c 0f 1d 1d 00 00 1d 00 00 1e 19 80 ; "PRESS S TO " ; string_50 &3586 1d 21 0b 1a 00 0d 19 16 19 1f 1c 9d ; "SWAP COLOURS" ; string_52 &3592 10 1c 0f 0f 00 0c 0b 16 96 ; "FREE BALL" ; string_6a &359b 1e 12 13 18 15 13 18 11 25 25 a5 ; "THINKING..." ; string_68 &35a6 12 17 17 17 17 17 17 25 25 25 a5 ; "HMMMMMM...." ; string_66 &35b1 12 0b 1c 0e 00 16 1f 0d 95 ; "HARD LUCK" ; string_64 &35ba 21 0f 16 16 00 0e 19 18 8f ; "WELL DONE" ; string_6c &35c3 23 19 1f 00 12 0b 20 0f 00 0c 0f 0b 1e 0f 18 80 ; "YOU HAVE BEATEN " ; string_6e # Dashes are overwritten &35d3 23 19 1f 1c 00 21 13 18 2a 0d 19 0e 0f 00 13 1d ; "YOUR WIN-CODE IS ------ " &35e3 00 2a 2a 2a 2a 2a 2a 80 ; string_70 &35eb 17 0b 15 0f 00 0b 00 18 19 1e 0f 00 19 10 00 13 ; "MAKE A NOTE OF IT NOW!!" &35fb 1e 00 18 19 21 26 a6 ; string_72 &3602 80 ; " " ; palette_eors &3603 10 40 10 07 ; palette_values &3607 02 21 87 a0 ; &00 : GRWK (colour) &360b 04 26 87 a0 ; &04 : BCWK (black and white) ; left_fill_masks &360f 00 ; 0000 &3610 88 ; 3000 &3611 cc ; 3300 &3612 ee ; 3330 ; right_fill_masks &3613 00 ; 0000 &3614 77 ; 0333 &3615 33 ; 0033 &3616 11 ; 0003 ; polygon_colours_pixel_values &3617 00 00 ; &00 : 0000 0000 (solid green) &3619 03 0c ; &01 ; 0011 1100 (red and green dither) &361b 0f 00 ; &02 ; 1111 0000 (red and green stripes) &361d 5a a5 ; &03 ; 1313 3131 (red and white dither) # Unused &361f ff ff ; &04 ; 3333 3333 (solid black) &3621 55 aa ; &05 ; 0303 3030 (green and black dither) &3623 af fa ; &06 ; 3131 3232 (red/white and black stripes) # Unused &3625 fa a5 ; &07 ; 3232 3131 (red, white and black dither) # Unused ; bit_table # Unused &3627 01 02 04 08 10 20 40 80 ; vertical_rotation_to_z_offset_table &362f 74 74 75 75 76 77 77 78 78 79 7a 7a 7b 7b 7c 7d &363f 7d 7e 7e 7f 80 80 81 81 82 83 83 84 84 85 86 86 &364f 87 87 88 89 89 8a 8a 8b 8c ; vertical_strike_point_to_power_table &3658 25 23 20 1e 1b 19 16 14 11 0f 0c 0a 07 05 02 00 &3668 02 05 07 0a 0c 0f 11 14 16 19 1b 1e 20 23 25 28 &3678 2a 2d 2f 32 34 37 39 3c 3e ; horizontal_strike_point_to_power_table &3681 18 15 13 10 0e 0c 09 07 04 02 00 02 04 07 09 0c &3691 0e 10 13 15 18 ; frames_per_stage_of_tournament &3696 03 03 05 05 ; computer_players_accuracy # Percentage chance of not changing angle ; 0 1 2 3 4 5 6 7 &369a 66 80 8c 99 b3 cc d9 e6 ; computer_players_strike_power ; 0 1 2 3 4 5 6 7 &36a2 09 09 09 0a 09 0a 0a 0b ; computer_players_skill # Maximum score for an acceptable move ; 0 1 2 3 4 5 6 7 &36aa 04 04 05 05 06 06 07 08 ; table_points_coordinates ; x z y &36b2 de 00 36 ; &00 &36b5 da 00 3d ; &01 &36b8 e3 00 46 ; &02 &36bb ea 00 42 ; &03 &36be 16 00 42 ; &04 &36c1 1d 00 46 ; &05 &36c4 26 00 3d ; &06 &36c7 22 00 36 ; &07 &36ca 22 00 ca ; &08 &36cd 26 00 c3 ; &09 &36d0 1d 00 ba ; &0a &36d3 16 00 be ; &0b &36d6 ea 00 be ; &0c &36d9 e3 00 ba ; &0d &36dc da 00 c3 ; &0e &36df de 00 ca ; &0f &36e2 df 00 f7 ; &10 &36e5 d8 00 fa ; &11 &36e8 d8 00 06 ; &12 &36eb df 00 09 ; &13 &36ee 21 00 09 ; &14 &36f1 28 00 06 ; &15 &36f4 28 00 fa ; &16 &36f7 21 00 f7 ; &17 &36fa e5 18 3c ; &18 &36fd 1b 18 3c ; &19 &3700 1b 18 c4 ; &1a &3703 e5 18 c4 ; &1b &3706 f6 00 db ; &1c &3709 0a 00 db ; &1d &370c f8 00 d2 ; &1e &370f 08 00 d2 ; &1f &3712 00 00 cf ; &20 ; table_polygon_data # Top bit of colour set to always plot polygon ; p c 1 2 3 4 5 6 7 8 &3715 04 01 18 19 04 03 # Base top red and green dither &371b 03 02 19 07 04 # Base top right red and green stripes &3720 04 01 19 1a 08 07 # Base right red and green dither &3726 03 02 1a 0b 08 # Base bottom right red and green stripes &372b 04 01 1a 1b 0c 0b # Base bottom red and green dither &3731 03 02 1b 0f 0c # Base bottom left red and green stripes &3736 04 01 1b 18 00 0f # Base left red and green dither &373c 03 02 18 03 00 # Base top left red and green stripes &3741 04 84 00 01 02 03 # Top left pocket black, always plot &3747 04 84 04 05 06 07 # Top right pocket black, always plot &374d 04 84 08 09 0a 0b # Bottom right pocket black, always plot &3753 04 84 0c 0d 0e 0f # Bottom left pocket black, always plot &3759 04 84 10 11 12 13 # Middle left pocket black, always plot &375f 04 84 14 15 16 17 # Middle right pocket black, always plot &3765 08 80 00 03 04 07 08 0b 0c 0f # Green green, always plot &376f 05 85 1c 1d 1f 20 1e # D green and black dither, always plot ; three_times_table &3776 00 03 06 09 0c 0f 12 15 18 1b 1e 21 24 27 2a 2d &3786 30 33 36 39 3c 3f 42 45 48 4b 4e 51 54 57 5a 5d &3796 60 63 ; five_times_table # Unused &3798 00 05 0a 0f 14 19 1e 23 28 2d 32 37 3c 41 46 4b ; even_colour_table_addresses &37a8 1b 09 ; &091b = colour_table_solid_shift_0 : &00 : BALL_TYPE_SOLID shifted 0 pixels &37aa c4 08 ; &08c4 = colour_table_solid_shift_1 : &02 shifted 1 pixel &37ac 6d 08 ; &086d = colour_table_solid_shift_2 : &04 shifted 2 pixels &37ae 16 08 ; &0816 = colour_table_solid_shift_3 : &06 shifted 3 pixels &37b0 77 0a ; &0a77 = colour_table_dithered_even_shift_0 : &08 : BALL_TYPE_DITHERED shifted 0 pixels &37b2 20 0a ; &0a20 = colour_table_dithered_even_shift_1 : &0a shifted 1 pixel &37b4 c9 09 ; &09c9 = colour_table_dithered_even_shift_2 : &0c shifted 2 pixels &37b6 72 09 ; &0972 = colour_table_dithered_even_shift_3 : &0e shifted 3 pixels &37b8 d3 0b ; &0bd3 = colour_table_cue_shift_0 : &10 : BALL_TYPE_CUE shifted 0 pixels &37ba 7c 0b ; &0b7c = colour_table_cue_shift_1 : &12 shifted 1 pixel &37bc 25 0b ; &0b25 = colour_table_cue_shift_2 : &14 shifted 2 pixels &37be ce 0a ; &0ace = colour_table_cue_shift_3 : &16 shifted 3 pixels &37c0 2f 0d ; &0d2f = colour_table_black_shift_0 : &18 : BALL_TYPE_BLACK shifted 0 pixels &37c2 d8 0c ; &0cd8 = colour_table_black_shift_1 : &1a shifted 1 pixel &37c4 81 0c ; &0c81 = colour_table_black_shift_2 : &1c shifted 2 pixels &37c6 2a 0c ; &0c2a = colour_table_black_shift_3 : &1e shifted 3 pixels ; odd_colour_table_addresses &37c8 8b 0e ; &0e8b = colour_table_dithered_odd_shift_0 : &08 : BALL_TYPE_DITHERED shifted 0 pixels &37ca 34 0e ; &0e34 = colour_table_dithered_odd_shift_1 : &0a shifted 1 pixel &37cc dd 0d ; &0ddd = colour_table_dithered_odd_shift_2 : &0c shifted 2 pixels &37ce 86 0d ; &0d86 = colour_table_dithered_odd_shift_3 : &0e shifted 3 pixels ; plot_row_routine_addresses &37d0 6b 22 ; &226b = plot_row_of_ball_0_even &37d2 59 22 ; &2259 = plot_row_of_ball_1_even &37d4 47 22 ; &2247 = plot_row_of_ball_2_even &37d6 35 22 ; &2235 = plot_row_of_ball_3_even &37d8 23 22 ; &2223 = plot_row_of_ball_4_even ; plot_row_routines_first_colour_table_address_offsets &37da 06 18 2a 3c 4e ; balls_colour ; 0 1 2 3 4 5 6 7 8 9 a b c d e f ; W D D S S B D D S D S S S D S D &37df 02 01 01 00 00 03 01 01 00 01 00 00 00 01 00 01 ; group_offsets_table &37ef 00 00 ; &0000 &37f1 40 01 ; &0140 &37f3 80 02 ; &0280 &37f5 c0 03 ; &03c0 &37f7 00 05 ; &0500 &37f9 40 06 ; &0640 &37fb 80 07 ; &0780 &37fd c0 08 ; &08c0 &37ff 00 0a ; &0a00 &3801 40 0b ; &0b40 &3803 80 0c ; &0c80 &3805 c0 0d ; &0dc0 &3807 00 0f ; &0f00 &3809 40 10 ; &1040 &380b 80 11 ; &1180 &380d c0 12 ; &12c0 &380f 00 14 ; &1400 &3811 40 15 ; &1540 &3813 80 16 ; &1680 &3815 c0 17 ; &17c0 &3817 00 19 ; &1900 &3819 40 1a ; &1a40 &381b 80 1b ; &1b80 &381d c0 1c ; &1cc0 &381f 00 1e ; &1e00 &3821 40 1f ; &1f40 &3823 80 20 ; &2080 &3825 c0 21 ; &21c0 &3827 00 23 ; &2300 &3829 40 24 ; &2440 &382b 80 25 ; &2580 &382d c0 26 ; &26c0 ; cosine_table # 65 byte cosine table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f # &FF * COS(RAD(X * 90 / 64) &382f ff ff fe fe fe fd fc fb fa f9 f7 f6 f4 f2 f0 ee ; &00 # i.e. low byte of cos(x * 90 degrees / 64) &383f eb e9 e6 e4 e1 de da d7 d4 d0 cd c9 c5 c1 bd b8 ; &10 &384f b4 b0 ab a6 a1 9d 98 93 8d 88 83 7d 78 72 6d 67 ; &20 &385f 61 5b 56 50 4a 44 3e 37 31 2b 25 1f 19 12 0c 06 ; &30 &386f 00 ; &40 ; velocity_dampening_table # 256 byte table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f # signed X * 0.845 &3870 00 00 01 02 02 03 04 05 06 07 08 08 09 0a 0b 0c ; &00 &3880 0d 0d 0e 0f 10 11 12 13 13 14 15 16 17 18 19 19 ; &10 &3890 1a 1b 1c 1d 1e 1e 1f 20 21 22 23 24 24 25 26 27 ; &20 &38a0 28 29 2a 2a 2b 2c 2d 2e 2f 2f 30 31 32 33 34 35 ; &30 &38b0 35 36 37 38 39 3a 3b 3b 3c 3d 3e 3f 40 40 41 42 ; &40 &38c0 43 44 45 46 46 47 48 49 4a 4b 4c 4c 4d 4e 4f 50 ; &50 &38d0 51 51 52 53 54 55 56 57 57 58 59 5a 5b 5c 5d 5d ; &60 &38e0 5e 5f 60 61 62 62 63 64 65 66 67 68 68 69 6a 6b ; &70 &38f0 94 95 96 97 98 98 99 9a 9b 9c 9d 9e 9e 9f a0 a1 ; &80 &3900 a2 a3 a3 a4 a5 a6 a7 a8 a9 a9 aa ab ac ad ae af ; &90 &3910 af b0 b1 b2 b3 b4 b4 b5 b6 b7 b8 b9 ba ba bb bc ; &a0 &3920 bd be bf c0 c0 c1 c2 c3 c4 c5 c5 c6 c7 c8 c9 ca ; &b0 &3930 cb cb cc cd ce cf d0 d1 d1 d2 d3 d4 d5 d6 d6 d7 ; &c0 &3940 d8 d9 da db dc dc dd de df e0 e1 e2 e2 e3 e4 e5 ; &d0 &3950 e6 e7 e7 e8 e9 ea eb ec ed ed ee ef f0 f1 f2 f3 ; &e0 &3960 f3 f4 f5 f6 f7 f8 f8 f9 fa fb fc fd fe fe ff 00 ; &f0 ; font_data &3970 f0 f0 f0 f0 f0 f0 f0 f0 ; &00 = " " &3978 f0 a2 f5 f5 f5 f5 f5 a2 ; &01 = "0" &3980 f0 b2 f6 f2 f2 f2 a2 f7 ; &02 = "1" &3988 f0 a7 f5 d1 a2 f4 c4 f7 ; &03 = "2" &3990 f0 a7 d5 f1 e3 f1 d5 a7 ; &04 = "3" &3998 f0 f4 f4 d4 d6 f7 f2 f2 ; &05 = "4" &39a0 f0 f7 f4 f6 d1 f1 d5 a7 ; &06 = "5" &39a8 f0 a6 f5 f4 e6 d7 f5 a7 ; &07 = "6" &39b0 f0 f7 f1 d1 e2 f2 f2 f2 ; &08 = "7" &39b8 f0 a2 f5 f5 a2 f5 f5 a2 ; &09 = "8" &39c0 f0 a2 f5 f5 b3 f1 f5 a6 ; &0a = "9" &39c8 f0 a2 f5 d5 f7 f5 f5 f5 ; &0b = "A" &39d0 f0 e6 f5 e6 d5 f5 d7 e6 ; &0c = "B" &39d8 f0 a2 f5 e4 f4 e4 f5 a2 ; &0d = "C" &39e0 f0 e6 d7 f5 f5 f5 d7 e6 ; &0e = "D" &39e8 f0 f7 e4 f4 f6 f4 e4 f7 ; &0f = "E" &39f0 f0 f7 f4 f4 f6 f4 f4 f4 ; &10 = "F" &39f8 f0 a3 f5 f4 d7 d7 f5 b3 ; &11 = "G" &3a00 f0 f5 f5 f5 f7 f5 f5 f5 ; &12 = "H" &3a08 f0 a7 f2 f2 f2 f2 f2 a7 ; &13 = "I" &3a10 f0 7f f2 f2 f2 f2 fa 5e ; &14 = "J" &3a18 f0 f5 d7 e6 d6 e6 d7 f5 ; &15 = "K" &3a20 f0 f4 f4 f4 f4 f4 f4 f7 ; &16 = "L" &3a28 f0 d5 f7 a7 d7 f5 f5 f5 ; &17 = "M" &3a30 f0 f5 d7 e7 f7 b7 d7 f5 ; &18 = "N" &3a38 f0 a7 f5 f5 f5 f5 f5 a7 ; &19 = "O" &3a40 f0 e6 f5 f5 e6 f4 f4 f4 ; &1a = "P" &3a48 f0 a7 d5 f5 f5 d5 e2 f3 ; &1b = "Q" &3a50 f0 e7 d5 f5 e7 f6 d7 f5 ; &1c = "R" &3a58 f0 a6 f5 f4 a7 f1 f5 a3 ; &1d = "S" &3a60 f0 f7 f2 f2 f2 f2 f2 f2 ; &1e = "T" &3a68 f0 f5 f5 f5 f5 f5 d5 a7 ; &1f = "U" &3a70 f0 f5 f5 d5 d7 a2 f2 f2 ; &20 = "V" &3a78 f0 f5 f5 f5 d7 a7 f7 d5 ; &21 = "W" &3a80 f0 f5 d5 a7 f2 a7 d5 f5 ; &22 = "X" &3a88 f0 f5 f5 d5 f7 a7 f2 f2 ; &23 = "Y" &3a90 f0 f7 d1 e3 f2 b6 d4 f7 ; &24 = "Z" &3a98 f0 f0 f0 f0 f0 f0 d2 f2 ; &25 = "." &3aa0 f0 f2 f2 f2 f2 d0 d2 f2 ; &26 = "!" &3aa8 f0 a3 f5 d1 e3 d0 f0 f2 ; &27 = "?" &3ab0 f0 f0 f0 f0 f0 f2 b6 f4 ; &28 = "," &3ab8 f0 f2 f2 f7 f7 f2 f2 f0 ; &29 = "+" &3ac0 f0 f0 f0 f7 f7 f0 f0 f0 ; &2a = "-" &3ac8 f4 b6 f2 d2 f0 f0 f0 f0 ; &2b = "`" &3ad0 ff ff 99 ff ff 99 ff ff ; &2c = POWER_GAUGE_BORDER &3ad8 ff ff 0f 0f 0f 0f ff ff ; &2d = POWER_GAUGE_FULL &3ae0 ff ff 7c 7c 7c 7c ff ff ; &2e = POWER_GAUGE_HALF_END &3ae8 ff ff 1f 1f 1f 1f ff ff ; &2f = POWER_GAUGE_FULL_END &3af0 ff ff f0 f0 f0 f0 ff ff ; &30 = POWER_GAUGE_EMPTY ; strike_point_left_sprites &3af8 44 ee 44 00 ; 0300 3330 0300 0000 &3afc 22 77 22 00 ; 0030 0333 0030 0000 &3b00 11 33 11 00 ; 0003 0033 0003 0000 &3b04 00 11 00 00 ; 0000 0003 0000 0000 ; strike_point_right_sprites &3b08 00 88 00 00 ; 0000 3000 0000 0000 &3b0c 88 cc 88 00 ; 3000 3300 3000 0000 ; sound_data # Offsets from &3b10 (see &437c) &3b10 08 00 ; &0008 = sound_0_data - sound_data &3b12 df 00 ; &00df = sound_1_data - sound_data &3b14 3a 01 ; &013a = sound_2_data - sound_data &3b16 ea 03 ; &03ea = end_of_sound_data - sound_data ; sound_0_data (SOUND_BOUNCE) &3b18 77 87 77 78 9a 37 65 d8 6a 57 96 a9 7a 65 55 87 &3b28 78 56 75 78 77 87 b9 8a 88 88 88 77 77 67 67 66 &3b38 87 78 56 44 43 76 77 66 97 99 a9 8a 88 77 a9 89 &3b48 78 57 65 76 77 67 77 76 78 77 76 99 88 88 88 67 &3b58 65 66 77 66 77 77 87 a9 aa 99 bb 89 67 77 77 56 &3b68 76 78 76 66 76 77 77 77 88 89 98 99 88 88 77 67 &3b78 66 98 88 88 a9 89 88 88 77 78 66 66 66 87 78 88 &3b88 a9 89 77 99 88 77 77 98 78 87 88 88 77 87 89 87 &3b98 88 99 9a 99 99 89 67 66 66 65 77 66 66 76 77 77 &3ba8 87 88 98 a9 aa 89 98 89 77 67 66 66 55 76 87 99 &3bb8 88 a9 89 88 77 67 77 87 89 99 89 78 67 66 66 77 &3bc8 88 88 99 99 99 88 88 98 88 78 88 77 77 77 77 77 &3bd8 87 88 88 88 88 98 99 99 99 88 77 77 76 77 67 77 &3be8 77 77 87 98 88 77 77 ; sound_1_data (SOUND_COLLISION) &3bef 08 77 61 1f f0 78 48 87 96 b5 e2 e0 d1 e2 b3 97 &3bff 87 78 79 4a 2f 5e 78 88 96 67 4a 78 97 86 86 68 &3c0f 6a a9 a9 89 68 79 89 88 87 98 99 87 98 78 86 87 &3c1f 98 8a 79 78 68 47 59 79 69 57 87 87 66 68 7a ab &3c2f ad 7a 69 85 55 76 74 66 aa 98 88 69 9b 9a 99 88 &3c3f 36 57 75 57 67 76 67 78 88 76 65 ; sound_2_data (SOUND_POT) &3c4a 66 79 78 88 77 3c f3 0c e3 1e b2 af 8a 00 f4 2c &3c5a e4 43 bf 61 cf 31 d7 bf 30 ba 69 54 a4 59 63 cd &3c6a 26 85 bb 68 b9 46 9a f7 2c b6 05 c7 8e 62 9b 75 &3c7a ca aa 68 98 56 66 96 6a a6 57 69 82 ae 35 a3 ac &3c8a 87 aa 88 bb ab 69 56 52 ab 77 97 37 97 65 48 d7 &3c9a 8e 74 ba 69 a5 7b 76 44 66 67 42 ba 8a 65 98 79 &3caa fb 7d 77 65 37 71 9b 64 89 46 75 78 c8 9d 86 59 &3cba 84 8a 03 83 68 35 93 ac 98 bf 84 8b 75 78 66 77 &3cca 77 66 44 86 78 87 8a 76 89 87 a9 bc 45 98 25 96 &3cda 58 76 77 48 94 9d 86 8a 97 69 87 47 75 86 69 73 &3cea 9c 65 a9 58 65 78 a7 bb 67 79 75 79 54 76 a8 9b &3cfa 46 97 68 76 87 89 87 46 b8 68 87 88 77 98 88 78 &3d0a 89 65 78 66 87 47 85 99 98 69 85 58 a5 7b 97 69 &3d1a 85 78 87 88 88 78 99 77 67 76 99 88 78 76 78 98 &3d2a 67 87 77 87 89 67 76 78 87 88 87 88 67 76 78 86 &3d3a 89 99 88 89 b9 8a 67 a8 99 98 89 77 76 66 87 88 &3d4a 67 a8 89 88 88 87 89 98 78 98 67 87 87 99 98 a9 &3d5a 9a 88 99 99 99 89 88 78 66 77 66 87 88 99 78 88 &3d6a a8 aa 88 88 78 88 88 78 87 88 88 77 98 78 87 88 &3d7a 87 89 88 88 77 88 88 88 88 88 78 87 99 99 89 77 &3d8a 78 77 77 78 76 88 77 76 87 98 99 78 87 98 88 98 &3d9a 88 98 89 88 78 87 88 78 76 88 68 76 77 77 67 76 &3daa 67 76 87 67 66 77 88 88 77 77 88 88 67 76 77 77 &3dba 77 67 66 87 88 78 66 87 88 77 87 78 67 76 67 66 &3dca 66 66 66 76 78 87 77 98 89 77 77 77 77 77 77 67 &3dda 66 77 88 78 87 88 78 87 78 77 66 76 77 77 67 77 &3dea 77 77 77 77 87 88 78 76 87 78 88 78 77 77 87 88 &3dfa 88 88 88 98 88 77 77 77 77 77 77 77 77 77 88 88 &3e0a b8 7a 37 30 fc 9c 49 10 fa 7c 65 87 47 85 78 99 &3e1a c9 ff 8d 23 75 58 64 87 a9 aa aa 68 44 64 a8 dc &3e2a 7a 66 a8 ac 78 67 43 65 66 97 aa ba ab 89 78 25 &3e3a 73 a9 ab 78 35 63 77 88 aa aa aa 99 ba aa aa 79 &3e4a 66 55 76 87 67 43 66 66 86 b9 dd cc bb 8a 77 66 &3e5a 45 54 66 45 75 99 89 88 b9 cc dd ad 47 22 22 64 &3e6a 98 89 67 66 66 b7 cd 8a 98 88 98 57 45 33 54 65 &3e7a 77 98 ba cc aa 79 67 66 87 88 78 56 43 87 88 78 &3e8a 87 77 88 99 99 78 66 87 88 77 67 55 65 87 98 9a &3e9a 99 99 9a 78 56 54 56 65 77 98 89 99 89 68 55 76 &3eaa a9 ab 79 66 66 66 76 77 88 88 b9 9b 78 56 86 9a &3eba 67 55 76 88 88 99 99 aa 99 78 66 55 66 66 66 76 &3eca 87 a9 9a 67 86 88 99 99 aa 9a 78 67 77 76 77 77 &3eda 98 aa 9a 88 88 77 87 88 88 78 67 66 76 77 87 88 &3eea 77 a8 aa ba cb 8a 56 55 65 87 88 78 77 77 98 a9 ; end_of_sound_data ; unused &3efa aa aa 0a ; ball_sprite_data # Unprocessed sprites stored as raw MODE 5 pixel data ; ball_sprite_0 # Unpacked to &3efd &78bc 02 01 04 ; 2 pixels (1 byte ) wide, 4 pixels high &78bf 84 0c 0c cc ; ball_sprite_1 # Unpacked to &3f05 &78c3 03 01 06 ; 3 pixels (1 byte ) wide, 6 pixels high &78c6 04 0e 0e 0e 0e 66 ; ball_sprite_2 # Unpacked to &3f11 &78cc 04 01 08 ; 4 pixels (1 byte ) wide, 8 pixels high &78cf 06 4b 0f 0f 0f 0f 06 77 ; ball_sprite_3 # Unpacked to &3f21 &78d7 05 02 0a ; 5 pixels (2 bytes) wide, 10 pixels high &78da 07 00 43 00 0f 08 0f 08 0f 08 0f 08 0f 08 07 00 &78ea 07 00 77 88 ; ball_sprite_4 # Unpacked to &3f3f &78ee 06 02 0c ; 6 pixels (2 bytes) wide, 12 pixels high &78f1 07 00 61 08 69 0c 0f 0c 0f 0c 0f 0c 0f 0c 0f 0c &7901 0f 0c 07 08 47 cc 77 cc ; ball_sprite_5 # Unpacked to &3f63 &7909 07 02 0e ; 7 pixels (2 bytes) wide, 14 pixels high &790c 03 08 25 0c 25 0c 0f 0e 0f 0e 0f 0e 0f 0e 0f 0e &791c 0f 0e 07 0e 07 0c 07 0c 23 6e 33 ee ; ball_sprite_6 # Unpacked to &3f8d &7928 08 02 10 ; 8 pixels (2 bytes) wide, 16 pixels high &792b 03 0c 25 0e 25 0e 07 0e 0f 0f 0f 0f 0f 0f 0f 0f &793b 0f 0f 0f 0f 0f 0f 07 0e 07 0e 03 0c 33 ff 11 ee ; ball_sprite_7 # Unpacked to &3fbd &794b 09 03 12 ; 9 pixels (3 bytes) wide, 18 pixels high &794e 01 0c 00 03 0e 00 25 0f 00 34 0f 00 0f 0f 08 0f &795e 0f 08 0f 0f 08 0f 0f 08 0f 0f 08 0f 0f 08 0f 0f &796e 08 0f 0f 08 07 0f 00 07 0f 00 03 0e 00 03 1f 00 &797e 33 ff 88 11 ff 00 ; ball_sprite_8 # Unpacked to &4005 &7984 0a 03 15 ; 10 pixels (3 bytes) wide, 21 pixels high &7987 01 0e 00 03 0f 00 25 87 08 16 0f 08 25 0f 08 0f &7997 0f 0c 0f 0f 0c 0f 0f 0c 0f 0f 0c 0f 0f 0c 0f 0f &79a7 0c 0f 0f 0c 0f 0f 0c 0f 0f 0c 07 0f 08 07 0f 08 &79b7 07 0f 08 03 0f 00 01 1f cc 33 ff cc 11 ff 88 ; ball_sprite_9 # Unpacked to &4059 &79c6 0b 03 17 ; 11 pixels (3 bytes) wide, 23 pixels high &79c9 01 0f 00 03 0f 08 12 87 08 34 87 0c 34 87 0c 0f &79d9 0f 0e 0f 0f 0e 0f 0f 0e 0f 0f 0e 0f 0f 0e 0f 0f &79e9 0e 0f 0f 0e 0f 0f 0e 0f 0f 0e 0f 0f 0e 07 0f 0c &79f9 07 0f 0c 07 0f 0c 03 0f 08 01 0f cc 33 1f ee 33 &7a09 ff ee 00 ff cc ; ball_sprite_a # Unpacked to &40b5 in sideways RAM version &7a0e 0c 03 19 ; 12 pixels (3 bytes) wide, 25 pixels high &7a11 01 0f 08 01 0f 08 12 87 0c 16 4b 0e 16 87 0e 07 &7a21 87 0e 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f &7a31 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f &7a41 0f 0f 0f 07 0f 0e 07 0f 0e 03 0f 0c 03 0f 0c 01 &7a51 0f 6e 11 ff ff 11 ff ff 00 ff ee ; ball_sprite_b # Unpacked to &4119 in sideways RAM version &7a5c 0d 04 1b ; 13 pixels (4 bytes) wide, 27 pixels high &7a5f 00 0f 08 00 01 0f 0c 00 03 c3 0e 00 12 4b 0e 00 &7a6f 07 87 0f 00 16 4b 0f 00 0f 0f 0f 08 0f 0f 0f 08 &7a7f 0f 0f 0f 08 0f 0f 0f 08 0f 0f 0f 08 0f 0f 0f 08 &7a8f 0f 0f 0f 08 0f 0f 0f 08 0f 0f 0f 08 0f 0f 0f 08 &7a9f 0f 0f 0f 08 0f 0f 0f 08 07 0f 0f 00 07 0f 0f 00 &7aaf 07 0f 0f 00 03 0f 0e 00 01 0f 0c 00 11 0f 7f 88 &7abf 11 ff ff 88 11 ff ff 88 00 ff ff 00 ; ball_sprite_c # Unpacked to &41a0 in sideways RAM version &7acb 0e 04 1d ; 14 pixels (4 bytes) wide, 29 pixels high &7ace 00 0f 0c 00 01 0f 0e 00 01 c3 0f 00 12 a5 0f 00 &7ade 03 c3 0f 00 16 c3 0f 08 16 4b 0f 08 07 0f 0f 08 &7aee 07 0f 0f 08 0f 0f 0f 0c 0f 0f 0f 0c 0f 0f 0f 0c &7afe 0f 0f 0f 0c 0f 0f 0f 0c 0f 0f 0f 0c 0f 0f 0f 0c &7b0e 0f 0f 0f 0c 07 0f 0f 08 07 0f 0f 08 07 0f 0f 08 &7b1e 07 0f 0f 08 03 0f 0f 00 03 0f 0f 00 01 0f 0f 00 &7b2e 01 0f 0e 00 00 0f 3f 88 11 ff ff cc 11 ff ff cc &7b3e 00 77 ff 00 ; end_of_ball_sprite_data ; unrelocated_initial_ball_layout_data &7b42 ff ff # Initial table, moved to &40b5 or &8c9d ; xf x yf y &7b44 00 00 9a d9 ; W &7b48 00 00 41 13 ; D &7b4c 53 fc a0 19 ; D &7b50 ad 03 a0 19 ; S &7b54 a5 f8 ff 1f ; S &7b58 00 00 ff 1f ; B &7b5c 5b 07 ff 1f ; D &7b60 f7 f4 5f 26 ; D &7b64 53 fc 5f 26 ; S &7b68 ad 03 5f 26 ; D &7b6c 09 0b 5f 26 ; S &7b70 4a f1 be 2c ; S &7b74 a5 f8 be 2c ; S &7b78 00 00 be 2c ; D &7b7c 5b 07 be 2c ; S &7b80 b6 0e be 2c ; D ; unrelocated_trick_ball_layout_data &7b84 7b 53 # Trick 1, moved to &4139 or &8d21 ; xf x yf y &7b86 a4 17 4c ff ; W &7b8a bc e1 0a d1 ; D &7b8e 45 e1 e7 d5 ; D (not present) &7b92 e2 02 53 02 ; S &7b96 20 e1 e3 ca ; S &7b9a a2 e7 9b f8 ; B &7b9e 1a ed 11 c1 ; D &7ba2 9c f8 02 10 ; D (not present) &7ba6 3b e1 52 fc ; S &7baa a8 ed dd f6 ; D &7bae dd f9 6a dc ; S (not present) &7bb2 1f ff b8 d5 ; S (not present) &7bb6 ff 10 77 03 ; S &7bba aa 03 65 d2 ; D (not present) &7bbe 3b 05 99 f7 ; S &7bc2 4e 05 5d d9 ; D (not present) &7bc6 ef 23 # Trick 2, moved to &417b or &8d63 ; xf x yf y &7bc8 b5 ea 96 d1 ; W &7bcc c3 0e 40 e5 ; D &7bd0 00 13 fe db ; D &7bd4 03 1a a6 c3 ; S &7bd8 00 00 00 09 ; S (not present) &7bdc 82 0d 4f 15 ; B &7be0 07 0c c7 c6 ; D &7be4 a4 f9 1c d0 ; D &7be8 00 eb 40 04 ; S &7bec c7 02 9b cb ; D &7bf0 a3 f9 a3 f9 ; S (not present) &7bf4 8f fc b0 f7 ; S (not present) &7bf8 00 00 17 e0 ; S (not present) &7bfc b7 16 a4 d3 ; D &7c00 5d 06 a3 f9 ; S (not present) &7c04 50 08 8f fc ; D (not present) &7c08 ef b2 # Trick 3, moved to &41bd or &8da5 ; xf x yf y &7c0a bb 01 57 d5 ; W &7c0e 18 10 38 c9 ; D &7c12 00 11 48 d3 ; D &7c16 aa 1b cc c1 ; S &7c1a b8 01 38 02 ; S (not present) &7c1e f4 10 5e dd ; B &7c22 7f 11 5a e7 ; D &7c26 f1 11 a2 f3 ; D &7c2a 00 f6 00 00 ; S (not present) &7c2e b5 12 92 ff ; D &7c32 e3 01 b5 f0 ; S (not present) &7c36 2d fc c3 f6 ; S (not present) &7c3a ff 1f c3 c7 ; S &7c3e 45 10 2a c1 ; D &7c42 12 07 ee f8 ; S (not present) &7c46 c2 13 b0 0b ; D &7c4a ff a7 # Trick 4, moved to &41ff or &8de7 ; xf x yf y &7c4c 61 e9 f9 f4 ; W &7c50 86 0f c8 08 ; D &7c54 f5 0b 12 0d ; D &7c58 56 e3 36 fd ; S &7c5c 03 f1 82 29 ; S &7c60 2c 0d 2a 29 ; B &7c64 52 15 7e ff ; D &7c68 ed 0f b8 fc ; D &7c6c 4f 03 e7 11 ; S &7c70 d3 0b 52 f9 ; D &7c74 94 1f cd 00 ; S &7c78 cb fb d7 f5 ; S (not present) &7c7c 00 00 00 f5 ; S (not present) &7c80 2a 1a d1 02 ; D &7c84 1d 0a 77 00 ; S (not present) &7c88 0c 15 e5 05 ; D &7c8c ff f7 # Trick 5, moved to &4241 or &8e29 ; xf x yf y &7c8e b5 ff ea 3f ; W &7c92 a6 08 1f c9 ; D &7c96 e7 0e 8b c3 ; D &7c9a b7 05 12 39 ; S &7c9e 25 f9 fb 04 ; S &7ca2 28 19 2c 33 ; B &7ca6 16 fc be cc ; D &7caa dc 02 cf cc ; D &7cae e9 f9 c1 3a ; S &7cb2 8a e6 fe 30 ; D &7cb6 c2 05 22 07 ; S &7cba 0d 1a 30 e7 ; S (not present) &7cbe 89 e8 a7 c2 ; S &7cc2 a1 ee 07 c6 ; D &7cc6 be 14 03 c1 ; S &7cca 11 f5 a7 c9 ; D &7cce ff ef # Trick 6, moved to &4283 or &8e6b ; xf x yf y &7cd0 93 17 97 13 ; W &7cd4 1c 1f 68 fc ; D &7cd8 63 1e 4b f1 ; D &7cdc f9 1f 52 d4 ; S &7ce0 b0 fd 20 e9 ; S &7ce4 e0 00 66 ed ; B &7ce8 1d 1f 10 e7 ; D &7cec 76 1f 71 dc ; D &7cf0 d0 17 29 c7 ; S &7cf4 ca e7 a2 f4 ; D &7cf8 83 e1 36 fc ; S &7cfc 9f fa dc f7 ; S &7d00 4d fd b0 06 ; S (not present) &7d04 24 f3 dd f1 ; D &7d08 85 1f 85 02 ; S &7d0c 4e 05 e9 e7 ; D &7d10 bf a7 # Trick 7, moved to &42c5 or &83ad ; xf x yf y &7d12 85 e1 35 d9 ; W &7d16 14 0f 26 1b ; D &7d1a 94 17 2a 19 ; D &7d1e b2 1d 99 38 ; S &7d22 78 e5 00 3b ; S &7d26 a2 1e 88 ff ; B &7d2a 7d 01 01 3b ; D (not present) &7d2e 64 ee 53 0d ; D &7d32 78 e7 08 e7 ; S &7d36 28 f7 18 15 ; D &7d3a 45 1f 66 f4 ; S &7d3e c3 e4 cf 33 ; S (not present) &7d42 00 00 00 f2 ; S (not present) &7d46 20 04 bc 1a ; D &7d4a e6 09 1a f6 ; S (not present) &7d4e 7f 1f 00 14 ; D &7d52 ef ff # Trick 8, moved to &4307 or &8eef ; xf x yf y &7d54 26 e9 7c 14 ; W &7d58 ff e9 a3 1f ; D &7d5c 8d 0c 15 1e ; D &7d60 a3 1f d2 16 ; S &7d64 00 00 12 fd ; S (not present) &7d68 8c 19 da f9 ; B &7d6c bc ff 1b cf ; D &7d70 bd 08 7b cb ; D &7d74 69 e1 85 0b ; S &7d78 13 11 0a c8 ; D &7d7c 1b e3 62 f8 ; S &7d80 5c e1 fd 19 ; S &7d84 e0 1f e7 09 ; S &7d88 c9 ec fc d9 ; D &7d8c e0 19 e4 c3 ; S &7d90 60 f7 5d d4 ; D &7d94 e7 f7 # Trick 9, moved to &4349 or &8f31 ; xf x yf y &7d96 8a 0e 5b e4 ; W &7d9a e7 10 0d 2f ; D &7d9e 81 14 cc 29 ; D &7da2 4a ef 00 e7 ; S (not present) &7da6 1d f4 58 e1 ; S (not present) &7daa 5e f4 e8 04 ; B &7dae 4d 06 43 1e ; D &7db2 c6 fc be 11 ; D &7db6 11 f8 29 18 ; S &7dba f2 ed eb f2 ; D &7dbe a9 fc fa f9 ; S &7dc2 9b f4 e1 e4 ; S (not present) &7dc6 c8 16 6d 34 ; S &7dca ff 1a d5 2d ; D &7dce 3f 03 b9 21 ; S &7dd2 0e 12 13 3a ; D &7dd6 f7 e7 # Trick 10, moved to &438b or &8f73 ; xf x yf y &7dd8 21 ec d0 f7 ; W &7ddc 89 ec 69 1b ; D &7de0 be f1 4c ff ; D &7de4 da 06 9b ed ; S (not present) &7de8 04 e1 58 39 ; S &7dec ef fc 2f 1b ; B &7df0 b7 13 dc 37 ; D &7df4 51 e8 8d 30 ; D &7df8 f1 18 c9 3c ; S &7dfc 1d 04 bc 1a ; D &7e00 30 1f e2 03 ; S &7e04 7f f9 4c f0 ; S (not present) &7e08 00 00 00 ef ; S (not present) &7e0c 05 0c 0c 1b ; D &7e10 05 e1 1e 03 ; S &7e14 49 f5 3e 1b ; D &7e18 e7 e3 # Trick 11, moved to &8fb5 if using sideways RAM ; xf x yf y &7e1a 8d 1a ce ff ; W &7e1e d1 fe 0a f5 ; D &7e22 d7 f9 cd 03 ; D &7e26 e3 f7 e6 1e ; S (not present) &7e2a 0a f6 7f 19 ; S (not present) &7e2e f3 ff fc 03 ; B &7e32 6c 11 4a 13 ; D &7e36 55 fe 54 12 ; D &7e3a d9 06 d4 03 ; S &7e3e 85 f1 ee 11 ; D &7e42 46 f3 5e db ; S (not present) &7e46 0f 07 74 da ; S (not present) &7e4a 3e fe 24 dc ; S (not present) &7e4e 9e 0d a4 f2 ; D &7e52 98 ea f8 00 ; S &7e56 e8 f0 f1 f5 ; D &7e5a ef a7 # Trick 12, moved to &8ff7 if using sideways RAM ; xf x yf y &7e5c db 0f 18 24 ; W &7e60 e1 fa c6 e2 ; D &7e64 21 02 7e dd ; D &7e68 c3 18 cf c6 ; S &7e6c 00 00 00 13 ; S (not present) &7e70 95 17 bb 03 ; B &7e74 94 11 d3 cd ; D &7e78 d8 09 6b d6 ; D &7e7c e5 07 ce 31 ; S &7e80 c5 11 6b 06 ; D &7e84 44 0e e2 3f ; S &7e88 e0 fb 4c f2 ; S (not present) &7e8c 00 00 00 ed ; S (not present) &7e90 1d 0f 3b 39 ; D &7e94 89 e6 e9 1b ; S (not present) &7e98 71 0b 95 08 ; D &7e9c e7 e2 # Trick 13, moved to &9039 if using sideways RAM ; xf x yf y &7e9e 48 00 3b e3 ; W &7ea2 0a e1 d4 fc ; D &7ea6 b4 e4 7c c2 ; D &7eaa fd 0b eb 14 ; S (not present) &7eae 00 00 00 14 ; S (not present) &7eb2 36 e3 f7 02 ; B &7eb6 7a 1c b8 3b ; D &7eba b6 1d 96 fa ; D &7ebe 00 ec 00 00 ; S (not present) &7ec2 b9 1e b4 c4 ; D &7ec6 dc f1 dc f1 ; S (not present) &7eca 4d 04 5d 16 ; S (not present) &7ece fd 02 00 ec ; S (not present) &7ed2 09 e2 66 3c ; D &7ed6 7a 01 fb f0 ; S &7eda ee 19 18 ff ; D &7ede e7 a7 # Trick 14, moved to &907b if using sideways RAM ; xf x yf y &7ee0 f8 1c 3a c6 ; W &7ee4 e6 11 24 d6 ; D &7ee8 d0 ed 5c de ; D &7eec 99 fb 8b c1 ; S (not present) &7ef0 60 0b b4 c1 ; S (not present) &7ef4 34 ea 20 34 ; B &7ef8 29 ef f8 ef ; D &7efc 6e 18 0c 05 ; D &7f00 bb 1f 59 19 ; S &7f04 9a ec ee 00 ; D &7f08 39 e6 3e 3d ; S &7f0c f7 f7 9a ec ; S (not present) &7f10 00 00 00 eb ; S (not present) &7f14 04 f2 64 28 ; D &7f18 d9 0e 27 f1 ; S (not present) &7f1c 15 07 67 0e ; D &7f20 ef a2 # Trick 15, moved to &90bd if using sideways RAM ; xf x yf y &7f22 05 e1 43 c9 ; W &7f26 7b f4 ef 07 ; D &7f2a ec ff 62 00 ; D &7f2e 25 e1 75 00 ; S &7f32 7c f8 38 fd ; S (not present) &7f36 1b e1 33 d3 ; B &7f3a 14 f4 5a f2 ; D &7f3e dd ed 73 e6 ; D &7f42 00 ea 00 00 ; S (not present) &7f46 6b e7 b3 06 ; D &7f4a 72 f0 72 f0 ; S (not present) &7f4e 95 f7 ad eb ; S (not present) &7f52 24 00 fa ec ; S (not present) &7f56 d7 02 e5 f3 ; D &7f5a 8e 0f 72 f0 ; S (not present) &7f5e 8d e7 d7 dc ; D # &7f62 - &7f69 is moved to &0100 - &0107 at &41fc ; sprite_status_ball_solid_top_left &0100 03 07 16 3c 2d 0f 0f 0f # &7f6a - &7f71 is moved to &0110 - &0107 at &4202 ; sprite_status_ball_solid_bottom_left &0110 0f 0f 0f 0f 07 07 03 00 # &7f72 - &7f79 is moved to &0108 - &010f at &4208 ; sprite_status_ball_solid_top_right &0108 0c 0e 0e 0f 0f 0f 0f 0f # &7f7a - &7f81 is moved to &0118 - &011f at &420e ; sprite_status_ball_solid_bottom_right &0118 0f 0f 0f 0f 0e 0e 0c 00