Castle Quest disassembly ======================== Castle Quest was written by Tony Sothcott and published by Micropower for the BBC Micro in 1985. It is a puzzle platformer which was billed as "Probably the most challenging game ever devised for the BBC Micro." 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 =============== A custom tape loader loads the main game binary. The game has no random number generator, and so is completely deterministic. Interesting pokes ================= &2995 = &a9 infinite lives &2311 = &ff, &2849 = &ff player is invulnerable to guards &235d = &60 player is invulnerable to troll &27b0 = &ff player is invulnerable to spiders &2650 = &60 player is invulnerable to witch &2e65 = &ff player can breathe underwater Tape protection disassembly =========================== ; QUEST ; 000940 0021c0 000b06 ; event_handler &0940 c9 04 CMP #&04 &0942 d0 40 BNE &0984 ; leave_via_previous_vector # Is this a v-sync event? &0944 a5 fc LDA &fc ; irq_accumulator &0946 48 PHA &0947 08 PHP &0948 8a TXA &0949 48 PHA &094a 98 TYA &094b 48 PHA &094c a9 72 LDA #&72 # Set logical colour 1 to magenta &094e 8d 21 fe STA &fe21 ; video ULA palette register &0951 a9 62 LDA #&62 &0953 8d 21 fe STA &fe21 ; video ULA palette register &0956 a9 32 LDA #&32 &0958 8d 21 fe STA &fe21 ; video ULA palette register &095b a9 22 LDA #&22 &095d 8d 21 fe STA &fe21 ; video ULA palette register &0960 a9 85 LDA #&85 # Set logical colour 2 to green &0962 8d 21 fe STA &fe21 ; video ULA palette register &0965 a9 95 LDA #&95 &0967 8d 21 fe STA &fe21 ; video ULA palette register &096a a9 c5 LDA #&c5 &096c 8d 21 fe STA &fe21 ; video ULA palette register &096f a9 d5 LDA #&d5 &0971 8d 21 fe STA &fe21 ; video ULA palette register &0974 a9 28 LDA #&28 # Set timer 1 to time out partway down screen &0976 8d 67 fe STA &fe67 ; User VIA timer 1 latch MSB &0979 8d 65 fe STA &fe65 ; User VIA timer 1 counter MSB &097c 68 PLA &097d a8 TAY &097e 68 PLA &097f aa TAX &0980 28 PLP &0981 68 PLA &0982 85 fc STA &fc ; irq_accumulator ; leave_via_previous_vector &0984 6c 0f 0a JMP (&0a0f) ; previous_event_vector ; play_tune &0987 a0 00 LDY #&00 &0989 b1 f8 LDA (&f8),Y ; tune_address # Get first of two bytes of tune data &098b c8 INY &098c c9 ff CMP #&ff # &ff marks end of tune &098e f0 4e BEQ &09de ; restart_tune &0990 aa TAX &0991 29 03 AND #&03 &0993 8d 1a 0a STA &0a1a ; tune_sound + 1 (channel high) # ......21 channel high &0996 8a TXA &0997 29 fc AND #&fc &0999 09 01 ORA #&01 &099b 8d 1d 0a STA &0a1d ; tune_sound + 4 (pitch low) # 842184.. pitch &099e b1 f8 LDA (&f8),Y ; tune_address # Get second of two bytes of tune data &09a0 aa TAX &09a1 29 03 AND #&03 &09a3 8d 19 0a STA &0a19 ; tune_sound (channel low) # ......21 channel low &09a6 8a TXA &09a7 4a LSR A &09a8 4a LSR A &09a9 aa TAX &09aa 29 07 AND #&07 &09ac 8d 1b 0a STA &0a1b ; tune_sound + 2 (volume low) # ...184.. volume &09af 8a TXA &09b0 4a LSR A &09b1 4a LSR A &09b2 4a LSR A &09b3 aa TAX &09b4 bd 13 0a LDA &0a13,X ; note_durations # 842..... duration, via lookup table &09b7 8d 1f 0a STA &0a1f ; tune_sound + 6 (duration low) &09ba a9 07 LDA #&07 &09bc a9 fb LDA #&fb ; sound buffer 0 &09be 38 SEC &09bf ed 19 0a SBC &0a19 ; tune_sound (channel low) &09c2 aa TAX &09c3 a9 80 LDA #&80 ; Read I/O device or buffer status &09c5 20 f4 ff JSR &fff4 ; OSBYTE # Is the channel ready to play the next note? &09c8 e0 00 CPX #&00 &09ca f0 11 BEQ &09dd ; leave &09cc a9 07 LDA #&07 ; Generate a sound (SOUND) &09ce a2 19 LDX #&19 &09d0 a0 0a LDY #&0a ; &0a19 = tune_sound &09d2 20 f1 ff JSR &fff1 ; OSWORD # If so, play the note &09d5 e6 f8 INC &f8 ; tune_address_low &09d7 e6 f8 INC &f8 ; tune_address_low # and move to next pair of bytes &09d9 d0 02 BNE &09dd ; leave &09db e6 f9 INC &f9 ; tune_address_high ; leave &09dd 60 RTS ; restart_tune &09de a9 00 LDA #&00 &09e0 85 f8 STA &f8 ; tune_address_low &09e2 a9 10 LDA #&10 ; &1000 = tune_data &09e4 85 f9 STA &f9 ; tune_address_high &09e6 d0 f5 BNE &09dd ; leave # Always branches ; irq2_handler &09e8 a5 fc LDA &fc ; irq_accumulator &09ea 48 PHA &09eb 08 PHP &09ec 8a TXA &09ed 48 PHA &09ee 98 TYA &09ef 48 PHA &09f0 ad 6d fe LDA &fe6d ; User VIA interrupt flag register &09f3 29 c0 AND #&c0 # Is this a timer 1 interrupt? &09f5 c9 c0 CMP #&c0 &09f7 d0 0b BNE &0a04 ; leave_via_previous_vector &09f9 8d 6d fe STA &fe6d ; User VIA interrupt flag register # If so, clear interrupt &09fc a9 14 LDA #&14 # and restore default logical colours &09fe 20 ee ff JSR &ffee ; OSWRCH &0a01 20 87 09 JSR &0987 ; play_tune ; leave_via_previous_vector &0a04 68 PLA &0a05 a8 TAY &0a06 68 PLA &0a07 aa TAX &0a08 28 PLP &0a09 68 PLA &0a0a 85 fc STA &fc ; irq_accumulator &0a0c 6c 11 0a JMP (&0a11) ; previous_irq2_vector ; previous_event_vector_low &0a0f ea ; previous_event_vector_high &0a10 ea ; previous_irq2_vector_low &0a11 ea ; previous_irq2_vector_high &0a12 ea ; note_durations ; 0 1 2 3 4 5 &0a13 04 08 0c 18 30 78 ; tune_sound ; chan vol pitch dur &0a19 00 00 00 00 00 00 00 00 ; initialise_event_and_irq_handlers &0a21 78 SEI &0a22 ad 20 02 LDA &0220 ; event_vector_low &0a25 8d 0f 0a STA &0a0f ; previous_event_vector_low &0a28 ad 21 02 LDA &0221 ; event_vector_high &0a2b 8d 10 0a STA &0a10 ; previous_event_vector_high &0a2e a9 40 LDA #&40 &0a30 8d 20 02 STA &0220 ; event_vector_low &0a33 a9 09 LDA #&09 ; &0940 = event_handler &0a35 8d 21 02 STA &0221 ; event_vector_high &0a38 a9 00 LDA #&00 &0a3a 85 f8 STA &f8 ; tune_address_low &0a3c a9 10 LDA #&10 ; &1000 = tune_data &0a3e 85 f9 STA &f9 ; tune_address_high &0a40 ad 06 02 LDA &0206 ; irq2_vector_low &0a43 8d 11 0a STA &0a11 ; previous_irq2_vector_low &0a46 ad 07 02 LDA &0207 ; irq2_vector_high &0a49 8d 12 0a STA &0a12 ; previous_irq2_vector_high &0a4c a9 e8 LDA #&e8 &0a4e 8d 06 02 STA &0206 ; irq2_vector_low &0a51 a9 09 LDA #&09 ; &09e8 = irq2_handler &0a53 8d 07 02 STA &0207 ; irq2_vector_high &0a56 a9 80 LDA #&80 &0a58 8d 6b fe STA &fe6b ; User VIA auxiliary control register &0a5b a9 00 LDA #&00 &0a5d 8d 64 fe STA &fe64 ; User VIA timer 1 counter LSB &0a60 8d 66 fe STA &fe66 ; User VIA timer 1 latch LSB &0a63 a9 28 LDA #&28 &0a65 8d 67 fe STA &fe67 ; User VIA timer 1 latch MSB &0a68 8d 65 fe STA &fe65 ; User VIA timer 1 counter MSB &0a6b a9 c0 LDA #&c0 # Enable timer 1 interrupts &0a6d 8d 6e fe STA &fe6e ; User VIA interrupt enable register &0a70 58 CLI &0a71 60 RTS ; restore_previous_event_and_irq_handlers &0a72 78 SEI &0a73 a9 40 LDA #&40 # Disable timer 1 interrupts &0a75 8d 6e fe STA &fe6e ; User VIA interrupt enable register &0a78 ad 11 0a LDA &0a11 ; previous_irq2_vector_low &0a7b 8d 06 02 STA &0206 ; irq2_vector_low &0a7e ad 12 0a LDA &0a12 ; previous_irq2_vector_high &0a81 8d 07 02 STA &0207 ; irq2_vector_high &0a84 ad 0f 0a LDA &0a0f ; previous_event_vector_low &0a87 8d 20 02 STA &0220 ; event_vector_low &0a8a ad 10 0a LDA &0a10 ; previous_event_vector_high &0a8d 8d 21 02 STA &0221 ; event_vector_high &0a90 58 CLI &0a91 60 RTS ; fade_out_sound &0a92 a2 7e LDX #&7e &0a94 a0 00 LDY #&00 ; fade_out_sound_loop # For each envelope, &0a96 a9 ff LDA #&ff &0a98 2c cb 08 BIT &08cb ; envelope_1 + 11 &0a9b f0 03 BEQ &0aa0 ; skip_envelope_1_11 &0a9d ce cb 08 DEC &08cb ; envelope_1 + 11 # Reduce attack phase target to zero ; skip_envelope_1_11 &0aa0 2c cc 08 BIT &08cc ; envelope_1 + 12 &0aa3 f0 03 BEQ &0aa8 ; skip_envelope_1_12 &0aa5 ce cc 08 DEC &08cc ; envelope_1 + 12 # Reduce decay phase target to zero ; skip_envelope_1_12 &0aa8 2c db 08 BIT &08db ; envelope_2 + 11 &0aab f0 03 BEQ &0ab0 ; skip_envelope_2_11 &0aad ce db 08 DEC &08db ; envelope_2 + 11 ; skip_envelope_2_11 &0ab0 2c dc 08 BIT &08dc ; envelope_2 + 12 &0ab3 f0 03 BEQ &0ab8 ; skip_envelope_2_12 &0ab5 ce dc 08 DEC &08dc ; envelope_2 + 12 ; skip_envelope_2_12 &0ab8 2c eb 08 BIT &08eb ; envelope_3 + 11 &0abb f0 03 BEQ &0ac0 ; skip_envelope_3_11 &0abd ce eb 08 DEC &08eb ; envelope_3 + 11 ; skip_envelope_3_11 &0ac0 2c ec 08 BIT &08ec ; envelope_3 + 12 &0ac3 f0 03 BEQ &0ac8 ; skip_envelope_3_12 &0ac5 ce ec 08 DEC &08ec ; envelope_3 + 12 ; skip_envelope_3_12 &0ac8 2c fb 08 BIT &08fb ; envelope_4 + 11 &0acb f0 03 BEQ &0ad0 ; skip_envelope_4_11 &0acd ce fb 08 DEC &08fb ; envelope_4 + 11 ; skip_envelope_4_11 &0ad0 2c fc 08 BIT &08fc ; envelope_4 + 12 &0ad3 f0 03 BEQ &0ad8 ; skip_envelope_4_12 &0ad5 ce fc 08 DEC &08fc ; envelope_4 + 12 ; skip_envelope_4_12 &0ad8 2c 0b 09 BIT &090b ; envelope_5 + 11 &0adb f0 03 BEQ &0ae0 ; skip_envelope_5_11 &0add ce 0b 09 DEC &090b ; envelope_5 + 11 ; skip_envelope_5_11 &0ae0 2c 0c 09 BIT &090c ; envelope_5 + 12 &0ae3 f0 03 BEQ &0ae8 ; skip_envelope_5_12 &0ae5 ce 0c 09 DEC &090c ; envelope_5 + 12 ; skip_envelope_5_12 &0ae8 2c 1b 09 BIT &091b ; envelope_6 + 11 &0aeb f0 03 BEQ &0af0 ; skip_envelope_6_11 &0aed ce 1b 09 DEC &091b ; envelope_6 + 11 ; skip_envelope_6_11 &0af0 2c 1c 09 BIT &091c ; envelope_6 + 12 &0af3 f0 03 BEQ &0af8 ; skip_envelope_6_12 &0af5 ce 1c 09 DEC &091c ; envelope_6 + 12 ; skip_envelope_6_12 &0af8 8a TXA &0af9 a2 30 LDX #&30 ; delay_loop &0afb 88 DEY &0afc d0 fd BNE &0afb ; delay_loop &0afe ca DEX &0aff d0 fa BNE &0afb ; delay_loop &0b01 aa TAX &0b02 ca DEX &0b03 d0 91 BNE &0a96 ; fade_out_sound_loop &0b05 60 RTS ; entry_point &0b06 a2 fe LDX #&fe &0b08 9a TXS &0b09 a9 0c LDA #&0c ; CLS # Clear the screen &0b0b 20 ee ff JSR &ffee ; OSWRCH &0b0e a9 0c LDA #&0c # R12: Displayed screen start address register (high) &0b10 8d 00 fe STA &fe00 ; video register number &0b13 a9 07 LDA #&07 &0b15 8d 01 fe STA &fe01 ; video register value &0b18 a9 0d LDA #&0d # R13: Displayed screen start address register (low) &0b1a 8d 00 fe STA &fe00 ; video register number &0b1d a9 e0 LDA #&e0 # Set screen start address to &3f00 &0b1f 8d 01 fe STA &fe01 ; video register value &0b22 a9 00 LDA #&00 &0b24 85 70 STA &70 ; source_address_low &0b26 a9 16 LDA #&16 ; &1600 = packed_screen_data &0b28 85 71 STA &71 ; source_address_high &0b2a 20 d8 2a JSR &2ad8 ; unpack_screen &0b2d 20 21 0a JSR &0a21 ; initialise_event_and_irq_handlers &0b30 a9 0e LDA #&0e ; Enable event &0b32 a2 04 LDX #&04 ; v-sync event &0b34 20 f4 ff JSR &fff4 ; OSBYTE &0b37 a2 60 LDX #&60 ; move_envelopes_loop # Move &15a1 - &1600 to &08c1 - &0920 &0b39 bd a0 15 LDA &15a0,X ; unrelocated_envelopes - 1 &0b3c 9d c0 08 STA &08c0,X ; os_envelope_storage &0b3f ca DEX &0b40 d0 f7 BNE &0b39 ; move_envelopes_loop &0b42 a9 81 LDA #&81 &0b44 8d c0 08 STA &08c0 ; envelope_1 &0b47 a2 0c LDX #&0c ; move_check_if_mover_should_be_updated_loop # Move &0bbf - &0bcb to &00c0 - &00cc &0b49 bd bf 0b LDA &0bbf,X ; unrelocated_check_if_mover_should_be_updated &0b4c 95 c0 STA &c0,X ; check_if_mover_should_be_updated &0b4e ca DEX &0b4f 10 f8 BPL &0b49 ; move_check_if_mover_should_be_updated_loop &0b51 20 fa 0e JSR &0efa ; tape_loader # Load main binary &0b54 a2 00 LDX #&00 ; write_press_space_to_begin_loop &0b56 bd cb 0b LDA &0bcb,X ; press_space_to_begin_string &0b59 e8 INX &0b5a 20 ee ff JSR &ffee ; OSWRCH # Write "Press SPACE to begin..." &0b5d c9 00 CMP #&00 &0b5f d0 f5 BNE &0b56 ; write_press_space_to_begin_loop ; wait_for_space &0b61 a9 81 LDA #&81 ; Scan for a particular key &0b63 a2 9d LDX #&9d ; SPACE &0b65 a0 ff LDY #&ff &0b67 20 f4 ff JSR &fff4 ; OSBYTE # Returns X = &ff and Y = &ff if SPACE pressed &0b6a e8 INX &0b6b d0 f4 BNE &0b61 ; wait_for_space &0b6d c8 INY &0b6e d0 f1 BNE &0b61 ; wait_for_space &0b70 a2 00 LDX #&00 ; write_the_quest_begins_here_loop &0b72 bd e6 0b LDA &0be6,X ; the_quest_begins_here_string &0b75 e8 INX &0b76 20 ee ff JSR &ffee ; OSWRCH # Write "The Quest begins here..." &0b79 c9 00 CMP #&00 &0b7b d0 f5 BNE &0b72 ; write_the_quest_begins_here_loop &0b7d 20 92 0a JSR &0a92 ; fade_out_sound &0b80 20 72 0a JSR &0a72 ; restore_previous_event_and_irq_handlers &0b83 a9 0d LDA #&0d ; Disable event &0b85 a2 04 LDX #&04 ; v-sync event &0b87 20 f4 ff JSR &fff4 ; OSBYTE &0b8a a2 00 LDX #&00 ; move_3e00_loop # Move &3e00 - &3ecf to &0100 - &01cf &0b8c bd 00 3e LDA &3e00,X ; unrelocated_move_object_left_or_right &0b8f 9d 00 01 STA &0100,X ; move_object_left_or_right &0b92 e8 INX &0b93 e0 d0 CPX #&d0 &0b95 d0 f5 BNE &0b8c ; move_3e00_loop &0b97 a9 00 LDA #&00 # Initialise various game variables &0b99 85 99 STA &99 ; selected_pocket &0b9b 85 9a STA &9a ; previous_selected_pocket &0b9d 85 9d STA &9d ; screen_scrolling_direction &0b9f 85 9e STA &9e ; player_facing &0ba1 a9 ff LDA #&ff &0ba3 85 9b STA &9b ; pocket_to_empty &0ba5 85 9c STA &9c ; carrying &0ba7 85 9f STA &9f ; unused &0ba9 a9 0f LDA #&0f ; Flush all buffers &0bab a2 00 LDX #&00 &0bad 20 f4 ff JSR &fff4 ; OSBYTE &0bb0 a9 d2 LDA #&d2 ; Read/Write sound suppression flag &0bb2 a2 00 LDX #&00 # Enable sound &0bb4 20 f4 ff JSR &fff4 ; OSBYTE &0bb7 4c d0 3e JMP &3ed0 ; main_binary_entry_point ; unused &0bba fc ff ff ff ff # &0bbf - &0bca is moved to &00c0 - &00cb at &0b49 ; check_if_mover_should_be_updated # Used in game &00c0 a5 67 LDA &67 ; time_low &00c2 29 01 AND #&01 &00c4 85 81 STA &81 ; time_lowest_bit &00c6 8a TXA # X is object &00c7 65 79 ADC &79 ; tmp # Would stop guards, monkeys and spiders being updated, # actually AND #&01 # but changed by load_address of final block (see &0129) &00c9 c5 81 CMP &81 ; time_lowest_bit &00cb 60 RTS ; press_space_to_begin_string &0bcb 1f 09 19 ; TAB(&09, &19) &0bce 50 72 65 73 73 20 53 50 41 43 45 20 74 6f 20 62 ; "Press SPACE to begin..." &0bde 65 67 69 6e 2e 2e 2e 00 ; the_quest_begins_here_string &0be6 1f 09 19 ; TAB(&09, &19) &0be9 54 68 65 20 ; "The " &0bed 11 01 ; COLOUR 1 &0bef 51 75 65 73 74 20 ; "Quest " &0bf5 11 03 ; COLOUR 3 &0bf7 62 65 67 69 6e 73 20 68 65 72 65 2e 2e 2e 00 ; "begins here..." ; unused # &0c06 - &0c3f is similar to &0c46 - &0c7f &0c06 0c ... &0c.. # Would be STA &0c96 ; previous_irq1_vector_low &0c07 ad 05 02 LDA &0205 ; irq1_vector_high &0c0a 8d 57 0c STA &0c57 ; unused_previous_irq1_vector_high # Would be STA &0c97 ; previous_irq1_vector_high &0c0d a9 19 LDA #&19 # Would be LDA #&59 &0c0f 8d 04 02 STA &0204 ; irq1_vector_low &0c12 a9 0c LDA #&0c ; &0c19 = unused_irq1_handler &0c14 8d 05 02 STA &0205 ; irq1_vector_high &0c17 58 CLI &0c18 60 RTS ; unused_irq1_handler &0c19 a5 fc LDA &fc ; irq_accumulator &0c1b 48 PHA &0c1c 8a TXA &0c1d 48 PHA &0c1e 98 TYA &0c1f 48 PHA &0c20 ad 08 fe LDA &fe08 ; Cassette ACIA status register &0c23 10 27 BPL &0c4c &0c25 8d 58 0c STA &0c58 # Would be STA &0c98 ; acia_status &0c28 29 04 AND #&04 &0c2a f0 1d BEQ &0c49 &0c2c 8c 59 0c STY &0c59 # Would be STY &0c99 ; acia_y &0c2f a2 d7 LDX #&d7 ; 11010111 &0c31 a0 00 LDY #&00 &0c33 a9 9c LDA #&9c ; Read/write 6850 ACIA registers &0c35 20 f4 ff JSR &fff4 ; OSBYTE &0c38 a2 d5 LDX #&d5 &0c3a 20 f4 ff JSR &fff4 ; OSBYTE &0c3d a9 5a LDA #&5a # Would be LDA #&9a &0c3f 8d ; initialise_irq1_handler &0c40 78 SEI &0c41 ad 04 02 LDA &0204 ; irq1_vector_low &0c44 8d 96 0c STA &0c96 ; previous_irq1_vector_low &0c47 ad 05 02 LDA &0205 ; irq1_vector_high &0c4a 8d 97 0c STA &0c97 ; previous_irq1_vector_high &0c4d a9 59 LDA #&59 &0c4f 8d 04 02 STA &0204 ; irq1_vector_low &0c52 a9 0c LDA #&0c ; &0c59 = wait_for_carrier_irq1_handler &0c54 8d 05 02 STA &0205 ; irq1_vector_high &0c57 58 CLI &0c58 60 RTS ; wait_for_carrier_irq1_handler &0c59 a5 fc LDA &fc ; irq_accumulator &0c5b 48 PHA &0c5c 8a TXA &0c5d 48 PHA &0c5e 98 TYA &0c5f 48 PHA &0c60 ad 08 fe LDA &fe08 ; Cassette ACIA status register &0c63 10 27 BPL &0c8c ; leave_via_previous_irq1_vector # Is this an interrupt from the cassette system? &0c65 8d 98 0c STA &0c98 ; acia_status &0c68 29 04 AND #&04 # &04 set if data carrier detect interrupt &0c6a f0 1d BEQ &0c89 ; not_carrier_interrupt &0c6c 8c 99 0c STY &0c99 ; acia_y # Value stored, but not used &0c6f a2 d7 LDX #&d7 ; 11010111 # Reset cassette system &0c71 a0 00 LDY #&00 &0c73 a9 9c LDA #&9c ; Read/write 6850 ACIA registers &0c75 20 f4 ff JSR &fff4 ; OSBYTE &0c78 a2 d5 LDX #&d5 ; 11010101 # 1200 baud, odd parity 1 stop bit 8 bit word, RTS high &0c7a 20 f4 ff JSR &fff4 ; OSBYTE # disable transmit interrupts, enable receive interrupts &0c7d a9 9a LDA #&9a &0c7f 8d 04 02 STA &0204 ; irq1_vector_low &0c82 a9 0c LDA #&0c ; &0c9a = wait_for_first_byte_irq1_handler # Wait for start of block header next &0c84 8d 05 02 STA &0205 ; irq1_vector_high &0c87 d0 03 BNE &0c8c ; leave_via_previous_irq1_vector # Always branches ; not_carrier_interrupt &0c89 ac 09 fe LDY &fe09 ; Cassette ACIA data register ; leave_via_previous_irq1_vector &0c8c 68 PLA &0c8d a8 TAY &0c8e 68 PLA &0c8f aa TAX &0c90 68 PLA &0c91 85 fc STA &fc ; irq_accumulator &0c93 6c 96 0c JMP (&0c96) ; previous_irq1_vector ; previous_irq1_vector_low &0c96 00 ; previous_irq1_vector_low &0c97 00 ; acia_status &0c98 00 # Written to, but not used ; acia_y &0c99 00 # Written to, but not used ; wait_for_first_byte_irq1_handler &0c9a a5 fc LDA &fc ; irq_accumulator &0c9c 48 PHA &0c9d 8a TXA &0c9e 48 PHA &0c9f 98 TYA &0ca0 48 PHA &0ca1 ad 08 fe LDA &fe08 ; Cassette ACIA status register &0ca4 10 e6 BPL &0c8c ; leave_via_previous_irq1_vector # Is this an interrupt from the cassette system? &0ca6 8d 98 0c STA &0c98 ; acia_status &0ca9 4a LSR A # &01 set if receiver interrupt &0caa b0 0d BCS &0cb9 ; is_receiver_interrupt ; wait_for_carrier &0cac a9 59 LDA #&59 # If not, return to waiting for carrier &0cae 8d 04 02 STA &0204 ; irq1_vector_low &0cb1 a9 0c LDA #&0c ; &0c59 = wait_for_carrier_irq1_handler &0cb3 8d 05 02 STA &0205 ; irq1_vector_high &0cb6 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; is_receiver_interrupt &0cb9 ac 09 fe LDY &fe09 ; Cassette ACIA data register # Get a byte of data &0cbc a9 00 LDA #&00 &0cbe 8d 99 0c STA &0c99 ; acia_y &0cc1 8c e8 0c STY &0ce8 ; acia_data &0cc4 c0 40 CPY #&40 # Block header starts with &40 byte &0cc6 d0 e4 BNE &0cac ; wait_for_carrier # If not, return to waiting for carrier &0cc8 a9 e9 LDA #&e9 &0cca 8d 04 02 STA &0204 ; irq1_vector_low &0ccd a9 0c LDA #&0c ; &0ce9 = read_block_header_irq1_handler # Read block header next &0ccf 8d 05 02 STA &0205 ; irq1_vector_high &0cd2 a9 04 LDA #&04 &0cd4 8d e0 0d STA &0de0 ; block_header_offset &0cd7 a9 00 LDA #&00 &0cd9 8d f9 0e STA &0ef9 ; checksum + 1 &0cdc 8d f8 0e STA &0ef8 ; checksum &0cdf 8d 42 0e STA &0e42 ; checksum_byte_to_check # Set to zero to check first byte of checksum &0ce2 8d 43 0e STA &0e43 ; block_status # Set to zero to indicate block header incomplete &0ce5 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; acia_data &0ce8 00 # Written to, but not used ; read_block_header_irq1_handler &0ce9 a5 fc LDA &fc ; irq_accumulator &0ceb 48 PHA &0cec 8a TXA &0ced 48 PHA &0cee 98 TYA &0cef 48 PHA &0cf0 ad 08 fe LDA &fe08 ; Cassette ACIA status register &0cf3 10 97 BPL &0c8c ; leave_via_previous_irq1_vector # Is this an interrupt from the cassette system? &0cf5 8d 98 0c STA &0c98 ; acia_status &0cf8 4a LSR A # &01 set if receiver interrupt &0cf9 90 b1 BCC &0cac ; wait_for_carrier # If not, return to waiting for carrier &0cfb ac 09 fe LDY &fe09 ; Cassette ACIA data register &0cfe ad 43 0e LDA &0e43 ; block_status # Non-zero if block header finished &0d01 d0 03 BNE &0d06 ; check_block_header &0d03 4c b8 0d JMP &0db8 ; process_block_header_byte ; check_block_header # When all the block header has been read, &0d06 20 0b 0e JSR &0e0b ; check_checksum # Doesn't return if checksum is invalid &0d09 ad 0a 0e LDA &0e0a ; block_header + 4 # Fifth byte of block header is block number &0d0c 48 PHA &0d0d 48 PHA &0d0e 29 f0 AND #&f0 &0d10 4a LSR A &0d11 4a LSR A &0d12 4a LSR A &0d13 4a LSR A &0d14 20 d2 0d JSR &0dd2 ; convert_nibble_to_hexadecimal_character &0d17 8d e2 0d STA &0de2 ; block_number_as_characters + 1 &0d1a 68 PLA &0d1b 29 0f AND #&0f &0d1d 20 d2 0d JSR &0dd2 ; convert_nibble_to_hexadecimal_character &0d20 8d e1 0d STA &0de1 ; block_number_as_characters &0d23 68 PLA ; block_number &0d24 c9 00 CMP #&00 # actually CMP expected_block &0d26 f0 22 BEQ &0d4a ; is_expected_block # Is this the expected block? If not, &0d28 a9 00 LDA #&00 # actually LDA searching_for_block # Non-zero if searching for block &0d2a f0 08 BEQ &0d34 ; start_searching_for_block ; continue_searching_for_block &0d2c a9 00 LDA #&00 &0d2e 8d 4b 0d STA &0d4b ; block_is_loading # Set to zero to indicate not loading block &0d31 4c 66 0d JMP &0d66 ; write_block_number ; start_searching_for_block &0d34 a2 00 LDX #&00 &0d36 8e 4b 0d STX &0d4b ; block_is_loading # Set to zero to indicate not loading block ; write_searching_loop &0d39 bd f9 0d LDA &0df9,X ; searching_string &0d3c 20 e3 ff JSR &ffe3 ; OSASCI # Write "Searching" &0d3f e8 INX &0d40 c9 3a CMP #&3a ; ":" &0d42 d0 f5 BNE &0d39 ; write_searching_loop &0d44 8e 29 0d STX &0d29 ; searching_for_block # Set to non-zero to indicate searching for block &0d47 4c 66 0d JMP &0d66 ; write_block_number ; is_expected_block # If this is the expected block, &0d4a a9 00 LDA #&00 # actually LDA block_is_loading # Non-zero if loading block &0d4c f0 08 BEQ &0d56 ; start_loading_block ; continue_loading_block &0d4e a9 00 LDA #&00 &0d50 8d 29 0d STA &0d29 ; searching_for_block # Set to zero to indicate not searching for block &0d53 4c 66 0d JMP &0d66 ; write_block_number ; start_loading_block &0d56 a2 00 LDX #&00 ; write_loading_loop &0d58 bd e3 0d LDA &0de3,X ; loading_block_string &0d5b 20 e3 ff JSR &ffe3 ; OSASCI # Write "Loading" &0d5e e8 INX &0d5f c9 3a CMP #&3a ; ":" &0d61 d0 f5 BNE &0d58 ; write_loading_loop &0d63 8e 4b 0d STX &0d4b ; block_is_loading # Set to non-zero to indicate loading block ; write_block_number &0d66 ad e2 0d LDA &0de2 ; block_number_as_characters + 1 &0d69 20 ee ff JSR &ffee ; OSWRCH # Write block number &0d6c ad e1 0d LDA &0de1 ; block_number_as_characters &0d6f 20 ee ff JSR &ffee ; OSWRCH &0d72 a9 08 LDA #&08 ; BACKSPACE &0d74 20 ee ff JSR &ffee ; OSWRCH # and backspace over it &0d77 20 ee ff JSR &ffee ; OSWRCH &0d7a ad 4b 0d LDA &0d4b ; block_is_loading &0d7d d0 03 BNE &0d82 ; start_reading_block # Non-zero if loading block &0d7f 4c ac 0c JMP &0cac ; wait_for_carrier # Otherwise, return to waiting for carrier ; start_reading_block &0d82 a9 52 LDA #&52 &0d84 8d 04 02 STA &0204 ; irq1_vector_low &0d87 a9 0e LDA #&0e ; &0e52 = read_data_irq1_handler # Read block data next &0d89 8d 05 02 STA &0205 ; irq1_vector_high &0d8c a9 00 LDA #&00 &0d8e 8d f9 0e STA &0ef9 ; checksum + 1 &0d91 8d f8 0e STA &0ef8 ; checksum &0d94 8d 43 0e STA &0e43 ; block_status # Set to zero to indicate block incomplete &0d97 8d 42 0e STA &0e42 ; checksum_byte_to_check # Set to zero to check first byte of checksum &0d9a 8d ca 0e STA &0eca ; block_data_offset &0d9d ad 06 0e LDA &0e06 ; block_header # First byte of block header is load address high &0da0 85 c8 STA &c8 ; load_address_high &0da2 c9 2f CMP #&2f &0da4 d0 0a BNE &0db0 ; skip_shrinking_screen &0da6 a9 06 LDA #&06 # R6: Vertical displayed register &0da8 8d 00 fe STA &fe00 ; video register number &0dab a9 1a LDA #&1a # Hide bottom of screen &0dad 8d 01 fe STA &fe01 ; video register value ; skip_shrinking_screen &0db0 ad 07 0e LDA &0e07 ; block_header + 1 # Second byte of block header is load address low &0db3 85 c7 STA &c7 ; load_address_low &0db5 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; process_block_header_byte # If the block header is still being read, &0db8 ae e0 0d LDX &0de0 ; block_header_offset &0dbb 98 TYA # Y is byte read from tape &0dbc 9d 06 0e STA &0e06,X ; block_header &0dbf 20 cb 0e JSR &0ecb ; update_checksum &0dc2 ce e0 0d DEC &0de0 ; block_header_offset &0dc5 30 03 BMI &0dca ; finished_block_status &0dc7 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; finished_block_status &0dca a9 ff LDA #&ff # Set to non-zero to indicate block complete &0dcc 8d 43 0e STA &0e43 ; block_status &0dcf 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; convert_nibble_to_hexadecimal_character &0dd2 c9 0a CMP #&0a &0dd4 b0 04 BCS &0dda ; is_alpha &0dd6 18 CLC &0dd7 69 30 ADC #&30 ; "0" &0dd9 60 RTS ; is_alpha &0dda e9 0a SBC #&0a &0ddc 18 CLC &0ddd 69 41 ADC #&41 ; "A" &0ddf 60 RTS ; block_header_offset &0de0 00 ; block_number_as_characters &0de1 00 00 ; loading_block_string &0de3 1f 0a 19 ; TAB(&0a, &19) &0de6 4c 6f 61 64 69 6e 67 20 20 20 20 20 20 42 6c 6f ; "Loading Block:" &0df6 63 6b 3a ; searching_string &0df9 1f 0a 19 ; TAB(&0a, &19) &0dfc 53 65 61 72 63 68 69 6e 67 3a ; "Searching:" ; block_header ; 0 1 2 3 4 &0e06 00 00 00 00 00 ; check_checksum &0e0b ad 42 0e LDA &0e42 ; checksum_byte_to_check &0e0e f0 06 BEQ &0e16 ; check_first_byte_of_checksum ; check_second_byte_of_checksum &0e10 cc f9 0e CPY &0ef9 ; checksum + 1 &0e13 d0 10 BNE &0e25 ; invalid_checksum &0e15 60 RTS ; check_first_byte_of_checksum &0e16 cc f8 0e CPY &0ef8 ; checksum &0e19 d0 0a BNE &0e25 ; invalid_checksum &0e1b a9 ff LDA #&ff # Set to non-zero to check second byte of checksum &0e1d 8d 42 0e STA &0e42 ; checksum_byte_to_check &0e20 68 PLA # Pop calling routine off stack &0e21 68 PLA # (check the second byte of the checksum next time) &0e22 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; invalid_checksum &0e25 a2 00 LDX #&00 &0e27 20 e3 ff JSR &ffe3 ; OSASCI # Writes &00 or &ff; unclear &0e2a e8 INX # Unnecessary code &0e2b c9 00 CMP #&00 &0e2d a2 00 LDX #&00 &0e2f 20 e7 ff JSR &ffe7 ; OSNEWL ; write_rewind_loop &0e32 bd 44 0e LDA &0e44,X ; rewind_string &0e35 20 e3 ff JSR &ffe3 ; OSASCI # Write "Rewind" &0e38 e8 INX &0e39 c9 00 CMP #&00 &0e3b d0 f5 BNE &0e32 ; write_rewind_loop &0e3d 68 PLA # Pop calling routine off stack &0e3e 68 PLA &0e3f 4c ac 0c JMP &0cac ; wait_for_carrier ; checksum_byte_to_check &0e42 00 ; block_status &0e43 00 ; rewind_string &0e44 1f 0a 19 ; TAB(&0a, &19) &0e47 52 65 77 69 6e 64 20 20 20 20 00 ; "Rewind " ; read_data_irq1_handler &0e52 a5 fc LDA &fc ; irq_accumulator &0e54 48 PHA &0e55 8a TXA &0e56 48 PHA &0e57 98 TYA &0e58 48 PHA &0e59 ad 08 fe LDA &fe08 ; Cassette ACIA status register &0e5c 30 03 BMI &0e61 ; is_cassette_interrupt # Is this an interrupt from the cassette system? &0e5e 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; is_cassette_interrupt &0e61 8d 98 0c STA &0c98 ; acia_status &0e64 4a LSR A # &01 set if receiver interrupt &0e65 b0 03 BCS &0e6a ; is_receiver_interrupt &0e67 4c ac 0c JMP &0cac ; wait_for_carrier # If not, return to waiting for carrier ; is_receiver_interrupt &0e6a ac 09 fe LDY &fe09 ; Cassette ACIA data register &0e6d ad 43 0e LDA &0e43 ; block_status # Zero if block is still being read &0e70 f0 38 BEQ &0eaa ; process_data_byte &0e72 20 0b 0e JSR &0e0b ; check_checksum # Doesn't return if checksum is invalid &0e75 ee 25 0d INC &0d25 ; expected_block &0e78 ad 25 0d LDA &0d25 ; expected_block &0e7b c9 32 CMP #&32 # Was this the final block? &0e7d f0 03 BEQ &0e82 ; end_of_binary &0e7f 4c ac 0c JMP &0cac ; wait_for_carrier # If not, return to waiting for carrier ; end_of_binary &0e82 a2 56 LDX #&56 ; 01010110 # Disable transmit and receive interrupts &0e84 a0 00 LDY #&00 &0e86 a9 9c LDA #&9c ; Read/write 6850 ACIA registers &0e88 20 f4 ff JSR &fff4 ; OSBYTE &0e8b a2 10 LDX #&10 # &fe10 ; Serial ULA control register &0e8d a0 00 LDY #&00 # Switch off cassette motor &0e8f a9 97 LDA #&97 ; Write SHEILA &0e91 20 f4 ff JSR &fff4 ; OSBYTE &0e94 ad 96 0c LDA &0c96 ; previous_irq1_vector_low &0e97 8d 04 02 STA &0204 ; irq1_vector_low &0e9a ad 97 0c LDA &0c97 ; previous_irq1_vector_low &0e9d 8d 05 02 STA &0205 ; irq1_vector_high &0ea0 68 PLA &0ea1 a8 TAY &0ea2 68 PLA &0ea3 aa TAX &0ea4 68 PLA &0ea5 85 fc STA &fc ; irq_accumulator &0ea7 6c 96 0c JMP (&0c96) ; previous_irq1_vector ; process_data_byte &0eaa 98 TYA &0eab ac ca 0e LDY &0eca ; block_data_offset &0eae 91 c7 STA (&c7),Y ; load_address &0eb0 c8 INY &0eb1 cc 09 0e CPY &0e09 ; block_header + 3 # Fourth byte of block header is size of block &0eb4 d0 0b BNE &0ec1 ; not_end_of_block &0eb6 a2 ff LDX #&ff # Set to non-zero to indicate block complete &0eb8 8e 43 0e STX &0e43 ; block_status &0ebb 20 cb 0e JSR &0ecb ; update_checksum &0ebe 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; not_end_of_block &0ec1 8c ca 0e STY &0eca ; block_data_offset &0ec4 20 cb 0e JSR &0ecb ; update_checksum &0ec7 4c 8c 0c JMP &0c8c ; leave_via_previous_irq1_vector ; block_data_offset &0eca 00 ; update_checksum &0ecb 8d d2 0e STA &0ed2 ; byte &0ece ad f9 0e LDA &0ef9 ; checksum + 1 &0ed1 49 00 EOR #&00 # actually EOR byte &0ed3 8d f9 0e STA &0ef9 ; checksum + 1 &0ed6 a2 08 LDX #&08 ; update_checksum_loop &0ed8 ad f9 0e LDA &0ef9 ; checksum + 1 &0edb 2a ROL A &0edc 90 10 BCC &0eee ; skip_bit &0ede ad f9 0e LDA &0ef9 ; checksum + 1 &0ee1 49 08 EOR #&08 &0ee3 8d f9 0e STA &0ef9 ; checksum + 1 &0ee6 ad f8 0e LDA &0ef8 ; checksum &0ee9 49 10 EOR #&10 &0eeb 8d f8 0e STA &0ef8 ; checksum ; skip_bit &0eee 2e f8 0e ROL &0ef8 ; checksum &0ef1 2e f9 0e ROL &0ef9 ; checksum + 1 &0ef4 ca DEX &0ef5 d0 e1 BNE &0ed8 ; update_checksum_loop &0ef7 60 RTS ; checksum &0ef8 00 00 ; tape_loader &0efa a2 00 LDX #&00 # Y is zero, so clear mask &0efc a9 e8 LDA #&e8 ; Read/Write 6850 IRQ Mask &0efe 20 f4 ff JSR &fff4 ; OSBYTE &0f01 20 40 0c JSR &0c40 ; initialise_irq1_handler &0f04 a2 00 LDX #&00 &0f06 20 e7 ff JSR &ffe7 ; OSNEWL ; write_searching_loop &0f09 bd 37 0f LDA &0f37,X ; first_searching_string &0f0c 20 e3 ff JSR &ffe3 ; OSASCI # Write "Searching" &0f0f e8 INX &0f10 c9 00 CMP #&00 &0f12 d0 f5 BNE &0f09 ; write_searching_loop &0f14 a2 d7 LDX #&d7 ; 11010111 # Reset cassette system &0f16 a0 00 LDY #&00 &0f18 a9 9c LDA #&9c ; Read/write 6850 ACIA registers &0f1a 20 f4 ff JSR &fff4 ; OSBYTE &0f1d a2 10 LDX #&10 # &fe10 ; Serial ULA control register &0f1f a0 ad LDY #&ad # Switch on cassette motor, use cassette system, 300 baud &0f21 a9 97 LDA #&97 ; Write SHEILA &0f23 20 f4 ff JSR &fff4 ; OSBYTE &0f26 a2 d5 LDX #&d5 ; 11010101 # 1200 baud, odd parity 1 stop bit 8 bit word, RTS high &0f28 a0 00 LDY #&00 # disable transmit interrupts, enable receive interrupts &0f2a a9 9c LDA #&9c ; Read/write 6850 ACIA registers &0f2c 20 f4 ff JSR &fff4 ; OSBYTE ; wait_loop &0f2f ad 25 0d LDA &0d25 ; expected_block &0f32 c9 32 CMP #&32 # Wait until the main binary is completely loaded &0f34 d0 f9 BNE &0f2f ; wait_loop &0f36 60 RTS ; first_searching_string &0f37 1f 0a 19 ; TAB(&0a, &19) &0f3a 53 65 61 72 63 68 69 6e 67 00 ; "Searching" ; unused &0f44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0f54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0f64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0f74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0f84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0f94 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0fa4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0fb4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0fc4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0fd4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0fe4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0ff4 00 00 00 00 00 00 00 00 00 00 00 00 ; tune_data &1000 02 81 02 22 1a 0f 00 03 55 0a 3d 0f 01 22 19 0f &1010 00 03 55 0a 3d 0f 01 22 19 0f 00 03 55 0a 3d 0f &1020 01 22 19 0f 00 03 55 0a 3d 0f 7a 25 02 22 1a 0f &1030 00 03 02 01 56 0a 4a 0f 96 25 02 22 1a 0f 00 03 &1040 02 01 56 0a 4a 0f 66 05 02 22 1a 0f 6d 05 01 03 &1050 76 05 52 0a 5e 0f 7a 05 02 22 1a 0f 01 01 01 03 &1060 86 05 4a 0a 4a 0f 7a 05 02 22 1a 0f 01 01 01 03 &1070 86 05 4a 0a 5e 0f 82 05 02 22 1a 0f 79 05 01 03 &1080 76 05 52 0a 5e 0f 7a 05 02 22 1a 0f 01 01 01 03 &1090 86 05 4a 0a 4a 0f 7a 05 02 22 1a 0f 01 01 01 03 &10a0 86 05 4a 0a 4a 0f 82 05 02 22 1a 0f 79 05 01 03 &10b0 76 05 52 0a 5e 0f 7a 05 02 22 1a 0f 01 01 01 03 &10c0 86 05 4a 0a 66 0f 7a 05 02 22 1a 0f 85 05 01 03 &10d0 82 05 56 0a 66 0f 7a 05 02 22 26 0f 81 05 01 03 &10e0 86 05 66 0a 56 0f 82 05 02 22 2e 0f 8d 05 01 03 &10f0 86 05 7a 0a 6a 0f 82 05 02 22 32 0f 01 01 01 03 &1100 8e 05 7a 0a 6a 0f 7a 05 02 22 32 0f 01 01 01 03 &1110 86 05 7a 0a 6e 0f 82 05 02 22 2e 0f 8d 05 01 03 &1120 86 05 7a 0a 6a 0f 82 05 02 22 32 0f 01 01 01 03 &1130 92 05 7a 0a 6a 0f 7a 05 02 22 32 0f 01 01 01 03 &1140 86 05 7a 0a 6e 0f 82 05 02 22 3a 0f 85 05 01 03 &1150 8e 05 8e 0a 76 0f 96 05 02 22 3e 0f 95 05 01 03 &1160 96 05 8e 0a 6e 0f 96 05 02 22 46 0f 95 05 01 03 &1170 96 05 8e 0a 66 0f 96 05 02 82 66 0f 8d 05 5d 0f &1180 85 05 55 0f 81 05 51 0f 8d 05 5d 0f 85 05 55 0f &1190 81 05 51 0f 79 05 49 0f 71 05 41 0f 71 05 41 0f &11a0 6d 05 3d 0f 65 05 35 0f 5e 05 02 82 2e 0f 55 05 &11b0 25 0f 51 05 21 0f 49 05 19 0f 41 05 11 0f 3d 05 &11c0 0d 0f 35 05 05 0f 01 21 01 23 01 61 05 53 80 53 &11d0 cc 53 86 19 76 0a 66 0f 02 01 02 02 02 03 96 19 &11e0 76 0a 66 0f 86 19 76 0a 6a 0f 02 01 02 02 02 03 &11f0 96 19 76 0a 6e 0f 8e 19 7e 0a 6e 0f 86 19 7e 0a &1200 6e 0f 7e 19 7e 0a 6e 0f 86 19 76 0a 66 0f 02 01 &1210 02 02 02 03 96 19 76 0a 66 0f 86 19 76 0a 6a 0f &1220 02 01 02 02 02 03 96 19 76 0a 6e 0f 8e 19 7e 0a &1230 6e 0f 86 19 7e 0a 6e 0f 7e 19 7e 0a 6e 0f 86 19 &1240 76 0a 66 0f 02 21 02 22 02 23 02 61 02 42 0e 53 &1250 89 52 01 63 d5 51 01 42 96 19 76 0a 86 0f 02 01 &1260 02 02 02 03 a6 19 76 0a 8a 0f 96 19 76 0a 86 0f &1270 02 01 02 02 02 03 a6 19 76 0a 8a 0f 9e 19 7e 0a &1280 8e 0f 96 19 7e 0a 8a 0f 8e 19 7e 0a 92 0f 96 19 &1290 76 0a 86 0f 02 01 02 02 02 03 a6 19 76 0a 8a 0f &12a0 96 19 76 0a 86 0f 02 01 02 02 02 03 a6 19 76 0a &12b0 8a 0f 9e 19 7e 0a 8e 0f 96 19 7e 0a 8a 0f 8e 19 &12c0 7e 0a 92 0f 96 19 76 0a 86 0f 02 21 02 22 02 23 &12d0 02 61 02 42 16 53 91 52 01 63 dd 51 01 42 ce 05 &12e0 7e 0a 3e 0f 02 01 02 22 02 23 c4 05 c6 05 7e 0a &12f0 3e 0f be 05 02 22 02 23 c4 05 ce 05 7e 0a 3e 0f &1300 02 01 02 22 02 23 c4 05 c6 05 8e 0a 52 0f 02 01 &1310 02 22 02 23 bc 05 be 05 7e 0a 3e 0f 02 01 02 22 &1320 02 23 b8 05 ba 05 7a 0a 2e 0f 02 01 02 22 02 23 &1330 b0 05 b2 05 8e 0a 46 0f 02 01 02 22 02 23 ac 05 &1340 ae 05 8a 0a 4a 0f a6 05 02 22 02 23 a8 05 ae 05 &1350 8a 0a 4a 0f b2 05 02 22 02 23 a0 05 a2 05 7a 0a &1360 2e 0f 9e 05 02 22 02 23 94 05 9e 05 7a 0a 2e 0f &1370 aa 05 02 22 02 23 bc 05 ce 05 8e 0a 2e 0f 02 21 &1380 02 22 02 23 96 05 8e 0a 36 0f a6 05 02 22 02 23 &1390 b0 05 c6 05 8e 0a 36 0f 02 21 02 22 02 23 8e 05 &13a0 76 0a 06 0f 96 05 02 22 02 23 a4 05 b2 05 8e 0a &13b0 06 0f 02 21 02 22 02 23 7a 25 7a 26 c6 0f c0 0f &13c0 02 01 02 02 be 0f 96 25 96 26 b6 0f b0 0f 02 01 &13d0 02 02 aa 0f 66 05 66 06 a6 0f 6e 05 6e 06 a2 0f &13e0 76 05 76 06 9e 0f 7a 05 7a 06 9a 0f 02 01 02 02 &13f0 96 0f 86 05 86 06 92 0f 7a 05 7a 06 8e 0f 02 01 &1400 02 02 8a 0f 86 05 86 06 86 0f 82 05 82 06 8e 0f &1410 7a 05 7a 06 92 0f 76 05 76 06 96 0f 7a 05 7a 06 &1420 9a 0f 02 01 02 02 96 0f 86 05 86 06 92 0f 7a 05 &1430 7a 06 8e 0f 02 01 02 02 8a 0f 86 05 86 06 86 0f &1440 82 05 82 06 8e 0f 7a 05 7a 06 92 0f 76 05 76 06 &1450 96 0f 7a 05 7a 06 9a 0f 02 01 02 02 96 0f 86 05 &1460 86 06 9a 0f 7a 05 7a 06 9e 0f 86 05 86 06 a2 0f &1470 82 05 82 06 a6 0f 7a 05 7a 06 aa 0f 82 05 82 06 &1480 a2 0f 86 05 86 06 9e 0f 82 05 82 06 9a 0f 8e 05 &1490 8e 06 96 0f 86 05 86 06 92 0f 82 05 82 06 8e 0f &14a0 02 01 02 02 8a 0f 92 05 92 06 86 0f 76 05 76 06 &14b0 82 0f 02 01 02 02 7e 0f 86 05 86 06 7a 0f 82 05 &14c0 82 06 9a 0f 8e 05 8e 06 96 0f 86 05 86 06 92 0f &14d0 82 05 82 06 8e 0f 02 01 02 02 8a 0f 92 05 92 06 &14e0 86 0f 7a 05 7a 06 82 0f 02 01 02 02 7e 0f 86 05 &14f0 86 06 7a 0f a2 19 02 82 72 0f a5 19 75 0f a9 19 &1500 79 0f ad 19 7d 0f b1 19 81 0f b9 19 89 0f bd 19 &1510 8d 0f b9 15 89 0f b5 15 85 0f b1 15 81 0f b5 15 &1520 85 0f b9 15 89 0f be 15 02 a2 8e 0f c1 15 91 0f &1530 c5 15 95 0f cd 15 9d 0f c9 15 99 0f c5 15 95 0f &1540 8d 15 8d 0f 91 15 91 0f 95 15 95 0f 85 0d 55 17 &1550 8d 0d 5d 17 95 0d 65 17 81 0d 51 17 85 0d 55 17 &1560 8d 0d 5d 17 79 0d 49 17 81 0d 51 17 85 0d 55 17 &1570 71 0d 41 17 79 0d 49 17 81 0d 51 17 69 0d 39 17 &1580 79 0d 49 17 85 0d 55 17 65 0d 35 17 75 0d 45 17 &1590 81 0d 51 17 65 0d 35 17 6d 0d 3d 17 75 0d 45 17 &15a0 ff # &15a1 - &15ff is moved to &08c1 - &091f at &0b39 ; envelope_1 + 1 # &08c0 is set at &0b44 &08c1 f8 02 00 01 04 00 0f 00 00 81 7e 7e 00 00 00 ; envelope_2 &08d0 01 00 00 00 00 00 00 7e 50 00 f6 7e 50 00 00 00 ; envelope_3 &08e0 81 f8 02 00 01 04 00 0a 00 00 da 5a 28 00 00 00 ; envelope_4 &08f0 06 0a ff 00 01 0a 00 78 ec 00 fe 78 64 00 00 00 ; envelope_5 &0900 81 fc 02 00 01 02 00 64 02 00 ff 64 46 00 00 00 ; envelope_6 &0910 81 f8 02 00 01 04 00 14 00 00 ff 78 78 00 00 00 ; packed_screen_data &1600 77 08 ff 02 bb 01 99 02 bb 01 ff 02 88 01 cc 01 &1610 ee 03 cc 02 88 01 00 05 ee 01 ff 02 00 05 ff 03 &1620 00 05 11 01 33 01 77 01 00 05 ff 02 bb 01 00 02 &1630 11 04 99 01 dd 01 00 02 ee 04 ff 02 00 05 ee 01 &1640 ff 02 00 05 11 01 33 01 77 01 00 05 bb 01 ff 02 &1650 00 02 11 03 dd 03 00 02 ee 04 ff 02 00 05 ee 01 &1660 ff 02 00 02 33 06 00 02 cc 03 dd 02 cc 01 00 05 &1670 ee 02 ff 01 00 05 33 02 77 01 00 05 ee 01 cc 01 &1680 88 01 00 0c 33 02 ff 02 00 04 cc 02 ff 02 00 02 &1690 77 06 00 02 88 03 bb 01 ff 02 00 05 88 01 cc 01 &16a0 ee 01 00 05 33 01 77 01 ff 01 00 05 ee 01 ff 01 &16b0 33 01 00 07 88 01 00 05 11 03 00 05 ee 01 ff 02 &16c0 00 05 cc 01 ee 01 ff 01 00 05 66 01 ff 02 00 06 &16d0 11 01 bb 01 00 05 ff 02 dd 01 00 05 88 01 cc 01 &16e0 ee 01 00 05 77 01 ff 02 00 05 ee 01 77 01 00 05 &16f0 11 02 77 02 00 04 ee 02 ff 02 00 06 88 02 00 06 &1700 11 01 33 01 00 05 ff 02 ee 01 00 05 cc 01 ee 02 &1710 00 02 ff 06 00 05 77 01 ff 02 00 06 88 01 dd 01 &1720 00 05 66 01 ff 02 00 05 ff 03 00 02 33 06 00 02 &1730 cc 06 00 02 ff 06 00 05 11 01 33 01 77 01 00 05 &1740 ff 02 99 01 00 05 11 01 99 01 dd 01 00 05 ee 01 &1750 ff 02 00 05 cc 01 ee 01 ff 01 00 06 11 01 33 01 &1760 00 05 dd 01 ff 01 dd 01 00 05 ee 03 00 01 ff 03 &1770 00 01 ff 03 00 05 33 03 00 05 dd 01 ff 02 00 05 &1780 88 01 cc 01 ee 01 00 05 33 01 77 01 ff 01 00 05 &1790 77 01 ff 01 77 01 00 05 88 03 00 05 11 01 33 01 &17a0 77 01 00 05 bb 01 ff 01 bb 01 00 05 cc 03 00 05 &17b0 33 01 77 01 ff 01 00 05 77 01 ff 02 00 05 bb 03 &17c0 00 05 dd 01 ff 02 00 05 88 01 dd 01 ff 01 00 05 &17d0 cc 01 ee 01 ff 01 00 05 11 01 33 01 77 01 00 05 &17e0 ff 02 99 01 00 06 88 01 cc 01 00 08 77 06 00 02 &17f0 88 06 00 0a ff 06 00 02 88 01 00 07 77 04 33 01 &1800 11 01 00 02 11 03 bb 01 ff 02 00 02 dd 04 99 01 &1810 11 01 00 02 ee 03 ff 02 ee 01 00 02 77 03 ff 02 &1820 ee 01 00 02 77 04 33 01 11 01 00 02 bb 01 33 01 &1830 bb 01 ff 02 bb 01 00 02 dd 06 00 02 ee 03 ff 02 &1840 ee 01 00 02 77 03 ff 02 ee 01 00 02 33 06 00 02 &1850 cc 06 00 02 ff 01 77 02 33 04 77 02 ff 02 ee 01 &1860 cc 02 88 03 00 0f 33 06 00 02 cc 06 00 02 77 06 &1870 00 02 99 06 00 02 ee 06 00 02 ff 04 77 01 33 01 &1880 00 02 33 01 ff 01 00 01 33 01 ff 02 00 02 88 02 &1890 00 02 88 01 00 03 11 06 00 02 ee 06 00 02 ff 06 &18a0 00 02 77 06 00 02 bb 04 99 01 88 01 00 02 88 03 &18b0 dd 01 ff 02 00 02 ee 04 cc 01 88 01 00 02 77 01 &18c0 00 01 66 01 ff 02 77 01 00 02 ee 01 ff 01 77 02 &18d0 ff 01 ee 01 00 02 11 02 99 02 11 02 00 02 ee 06 &18e0 00 0a 33 04 11 01 00 03 cc 03 ee 01 ff 02 00 02 &18f0 ee 01 00 02 ee 02 cc 01 00 02 ff 06 00 02 33 06 &1900 00 02 dd 04 cc 02 00 02 ee 01 cc 01 ee 01 ff 02 &1910 66 01 00 02 ff 06 00 02 33 06 00 02 cc 06 00 02 &1920 ff 06 00 02 77 04 33 01 11 01 00 02 99 01 ff 01 &1930 88 01 99 01 ff 02 00 02 dd 02 11 01 99 01 dd 01 &1940 99 01 00 02 ee 06 00 02 ff 06 00 02 33 05 11 01 &1950 00 01 33 01 99 03 dd 01 ff 01 cc 01 00 01 99 01 &1960 ee 08 ff 06 00 02 33 06 00 02 dd 06 00 02 ee 06 &1970 00 02 ee 03 ff 02 77 01 00 01 ee 01 77 04 ff 01 &1980 33 02 77 01 88 08 77 05 33 01 00 01 77 01 33 03 &1990 bb 01 ff 01 99 01 11 01 33 01 cc 08 ff 01 ee 01 &19a0 ff 02 77 01 33 01 00 02 77 03 ff 02 77 01 00 02 &19b0 bb 06 00 02 dd 06 00 02 ee 06 00 02 ff 06 00 02 &19c0 77 04 33 01 11 01 00 02 99 01 ff 01 88 01 99 01 &19d0 ff 02 00 02 cc 02 00 01 88 01 cc 01 88 01 00 30 &19e0 11 01 33 01 00 05 ff 02 cc 01 00 05 88 01 cc 01 &19f0 ee 01 00 05 ff 02 77 01 00 05 11 02 bb 01 00 05 &1a00 ee 02 dd 01 00 05 77 01 ff 01 ee 01 00 05 cc 01 &1a10 ee 01 77 01 00 05 33 03 00 05 bb 01 ff 02 00 05 &1a20 cc 03 00 05 11 01 33 02 00 02 11 03 dd 01 ff 02 &1a30 00 02 ee 06 00 05 33 01 77 01 ff 01 00 05 ee 01 &1a40 ff 01 33 01 00 05 33 02 99 01 00 05 cc 02 ee 01 &1a50 00 05 77 02 ff 01 00 01 33 03 00 01 bb 02 33 01 &1a60 00 01 cc 03 00 01 cc 01 dd 02 00 05 ff 01 ee 02 &1a70 00 05 cc 01 ee 01 00 06 11 01 33 01 77 01 00 05 &1a80 ff 02 99 01 00 06 99 01 dd 01 00 05 ee 01 ff 02 &1a90 00 02 ff 06 00 06 11 02 00 02 11 01 33 02 77 01 &1aa0 ff 02 00 02 ee 02 88 02 ee 02 00 05 33 01 77 01 &1ab0 ff 01 00 05 ee 01 ff 01 77 01 00 05 11 02 99 01 &1ac0 00 05 dd 01 ff 02 00 05 ee 03 00 06 33 02 00 04 &1ad0 ff 04 00 02 11 04 dd 02 00 02 ee 04 ff 02 00 05 &1ae0 ee 01 ff 02 00 06 11 01 bb 01 00 05 ff 02 cc 01 &1af0 00 05 88 01 cc 01 ee 01 11 08 ff 02 ee 04 ff 02 &1b00 ee 01 ff 02 77 02 ff 03 00 02 88 03 00 02 88 01 &1b10 ff 0a 77 01 33 02 77 01 ff 02 00 01 88 01 cc 03 &1b20 88 02 cc 01 11 01 33 01 77 06 ff 03 bb 01 11 01 &1b30 00 03 33 01 99 01 cc 03 00 03 ff 02 00 06 cc 01 &1b40 88 01 00 03 ff 03 00 05 66 01 ff 02 00 05 33 01 &1b50 77 01 ff 01 00 01 11 03 00 01 11 01 99 01 dd 01 &1b60 00 01 ee 03 00 01 ee 03 ff 01 77 01 00 03 33 01 &1b70 77 01 ff 02 ee 01 00 03 ff 02 bb 01 00 05 11 01 &1b80 99 02 77 01 33 01 00 03 dd 01 ff 04 00 03 ee 03 &1b90 88 01 00 04 33 01 77 01 ff 01 00 05 ee 01 ff 01 &1ba0 77 01 00 07 88 01 00 60 33 04 11 01 00 03 cc 01 &1bb0 ff 01 cc 02 ff 02 00 02 ee 02 00 01 cc 01 ee 01 &1bc0 cc 01 00 02 77 01 33 02 11 02 00 03 bb 01 ff 04 &1bd0 ee 01 00 02 dd 01 99 02 11 01 00 04 ee 01 ff 01 &1be0 ee 02 ff 01 77 01 00 02 77 01 ff 01 00 01 66 01 &1bf0 ff 01 ee 01 00 02 33 06 00 02 ee 01 cc 05 00 0a &1c00 33 05 11 01 00 02 99 03 ff 02 dd 01 00 02 ee 06 &1c10 00 02 ff 04 77 01 33 01 00 02 33 01 ff 01 00 01 &1c20 33 01 ff 02 00 02 99 01 88 01 00 02 88 01 00 03 &1c30 ee 01 ff 02 77 02 33 01 00 02 ff 01 ee 02 cc 02 &1c40 88 01 00 02 33 06 00 02 cc 03 dd 02 cc 01 00 02 &1c50 ff 01 11 01 cc 01 ee 01 ff 02 00 02 cc 01 ee 01 &1c60 ff 02 ee 01 cc 01 00 02 77 04 33 01 11 01 00 02 &1c70 99 01 ff 01 88 01 99 01 ff 02 00 02 dd 02 11 01 &1c80 99 01 dd 01 88 01 00 02 cc 03 ff 02 ee 01 00 02 &1c90 ff 06 00 0a 77 06 00 02 88 06 00 02 ee 03 ff 01 &1ca0 77 01 33 01 00 02 33 03 77 01 ff 01 ee 01 00 02 &1cb0 99 04 11 02 00 02 ff 01 ee 05 00 12 ff 06 00 02 &1cc0 11 06 00 02 ee 06 00 02 77 06 00 02 bb 04 99 01 &1cd0 88 01 00 02 cc 01 ff 01 cc 02 ff 02 00 02 ee 02 &1ce0 00 01 cc 01 ee 01 cc 01 00 02 11 06 00 02 ee 04 &1cf0 ff 02 00 02 77 01 33 02 77 01 ff 02 00 02 cc 04 &1d00 88 01 00 03 ff 06 00 02 33 01 11 02 33 01 ff 02 &1d10 00 02 ee 04 cc 01 88 01 00 02 77 04 33 01 11 01 &1d20 00 02 11 02 bb 01 ff 03 00 02 cc 04 88 01 00 0b &1d30 ff 06 00 02 77 06 00 02 bb 06 00 02 dd 06 00 02 &1d40 ee 06 00 02 ff 04 77 01 33 01 00 02 33 01 00 02 &1d50 bb 01 ff 02 00 02 99 01 11 02 99 02 11 01 00 02 &1d60 ff 01 ee 05 00 0a ee 03 ff 01 77 01 33 01 00 02 &1d70 33 03 77 01 ff 01 ee 01 00 02 88 03 bb 01 33 02 &1d80 00 05 88 03 00 ff 00 ff 00 ff 00 ff 00 ff 00 f6 &1d90 33 01 00 07 ff 01 00 06 11 01 ee 01 00 06 ff 01 &1da0 00 07 ff 01 00 06 33 01 cc 01 00 06 ff 01 00 07 &1db0 ff 01 00 07 ff 01 00 06 ff 01 00 07 ff 01 00 07 &1dc0 ff 01 00 07 ff 01 00 07 ff 01 00 07 ff 01 00 06 &1dd0 77 01 88 01 00 06 ff 01 00 07 ff 01 00 07 ff 01 &1de0 00 07 ff 01 00 07 cc 01 33 01 00 07 ff 01 00 07 &1df0 ff 01 00 07 ff 01 00 07 ff 01 00 07 ff 01 00 07 &1e00 ff 01 00 08 ff 01 00 07 ff 01 00 07 ff 01 00 07 &1e10 cc 01 33 01 00 07 ff 01 00 07 ff 01 00 08 ff 01 &1e20 00 07 ff 01 00 07 88 01 00 ff 00 08 33 01 00 06 &1e30 77 01 88 01 00 05 11 01 ee 01 00 06 ff 01 00 06 &1e40 ff 01 00 06 33 01 cc 01 00 06 ff 01 00 06 ff 01 &1e50 00 06 11 01 ee 01 00 06 ff 01 00 06 33 01 cc 01 &1e60 00 06 ff 01 00 07 cc 01 00 ff 00 18 77 01 00 07 &1e70 ff 01 00 07 88 01 77 01 00 07 ff 01 00 07 88 01 &1e80 77 01 00 07 ee 01 11 01 00 07 ff 01 00 07 88 01 &1e90 77 01 00 07 ee 01 11 01 00 07 ff 01 00 07 88 01 &1ea0 77 01 00 07 cc 01 33 01 00 07 88 01 00 a0 22 02 &1eb0 44 04 88 02 00 ff 00 d1 88 01 44 05 22 02 00 9a &1ec0 11 05 22 01 88 02 00 ff 00 d7 22 02 11 05 00 08 &1ed0 88 01 00 90 22 05 44 03 00 ff 00 e1 88 05 44 03 &1ee0 00 90 44 03 88 05 00 ff 00 e1 44 03 22 05 00 8a &1ef0 11 06 88 02 00 49 0f 05 00 03 0f 05 00 03 0f 05 &1f00 00 03 0f 05 00 03 0f 05 00 03 0f 05 00 04 0c 01 &1f10 0e 01 0f 02 00 03 01 05 00 03 0f 05 00 03 0f 05 &1f20 00 03 0f 05 00 03 0f 05 00 03 0f 05 00 03 0e 01 &1f30 0f 04 00 04 08 01 0c 01 0e 02 00 03 03 05 00 03 &1f40 0f 05 00 03 0f 05 00 03 0f 05 00 03 0f 05 00 03 &1f50 0f 05 00 03 0f 05 00 03 0e 05 00 03 0f 05 00 03 &1f60 0f 05 00 03 0f 05 00 03 0f 05 00 03 0f 05 00 03 &1f70 0f 05 00 03 0f 05 00 03 0d 05 00 03 0f 05 00 03 &1f80 0f 05 00 03 38 05 00 03 f0 05 00 03 d0 05 00 03 &1f90 f0 05 00 03 e0 05 00 03 07 05 00 03 0f 05 00 03 &1fa0 0f 05 00 03 0f 05 00 03 0f 05 00 03 0f 05 00 03 &1fb0 0f 05 00 03 0c 05 00 30 22 02 11 06 00 88 11 02 &1fc0 22 06 00 48 0f 13 0c 01 1c 04 0f 03 00 01 f0 04 &1fd0 0f 03 03 01 83 04 0f 10 01 01 09 07 0f 13 08 01 &1fe0 0b 04 0f 03 00 01 0f 07 01 01 0f 14 03 05 01 02 &1ff0 00 01 0f 0a 0e 01 0f 07 00 01 0f 07 00 01 0f 07 &2000 00 01 0c 01 0f 06 00 02 0c 01 0f 03 0e 02 00 03 &2010 08 01 0c 02 0f 03 00 01 70 04 0f 03 00 01 f0 04 &2020 0f 03 03 01 83 04 0f 13 00 01 70 04 0f 03 00 01 &2030 f0 04 0d 03 01 01 81 04 0f 10 38 08 f0 08 d0 08 &2040 f0 08 e0 08 07 08 0f 0b 0c 01 0f 07 00 01 0f 07 &2050 00 01 0f 07 00 01 0f 07 00 01 0f 04 0c 03 00 01 &2060 0c 04 00 30 11 02 00 08 88 06 00 80 22 06 44 02 &2070 00 48 0f 10 1c 08 f0 08 83 03 80 01 f0 04 0f 03 &2080 00 01 f0 04 0f 03 00 01 f0 04 09 03 01 01 81 04 &2090 0f 10 0b 03 08 01 38 04 0f 03 00 01 f0 04 0f 03 &20a0 07 05 0f 10 00 04 30 04 07 01 01 01 00 02 f0 04 &20b0 0f 02 01 01 00 01 f0 04 0f 03 00 01 f0 04 0f 03 &20c0 00 01 f0 04 0f 03 07 05 0f 08 0e 08 70 08 f0 08 &20d0 83 08 0f 10 70 08 f0 08 81 08 0f 10 38 08 f0 08 &20e0 d0 08 f0 08 e0 08 07 08 0f 0b 0e 05 0f 03 00 01 &20f0 f0 04 0f 03 00 01 f0 04 0f 03 00 01 f0 04 0f 03 &2100 00 01 f0 04 0c 03 00 01 80 04 00 38 88 06 44 02 &2110 00 80 44 08 00 48 0f 10 1c 08 f0 08 80 01 83 07 &2120 00 01 0f 07 00 01 0f 07 01 01 09 07 0f 10 38 08 &2130 f0 08 07 08 0f 10 30 08 f0 20 07 08 0f 08 0e 08 &2140 70 08 f0 08 83 08 0f 10 70 08 f0 08 81 08 0f 10 &2150 38 08 f0 08 d0 08 f0 08 e0 08 07 08 0f 08 0e 08 &2160 f0 20 80 08 00 38 44 08 00 80 44 08 00 48 0f 04 &2170 07 02 03 01 01 01 0f 08 0c 01 0f 07 00 01 0f 07 &2180 03 01 0f 13 0e 01 0c 01 08 01 00 01 09 02 01 06 &2190 0f 10 38 08 f0 08 07 08 0f 10 00 01 03 07 00 01 &21a0 0f 07 00 01 0f 07 00 01 0f 07 00 01 0f 07 07 01 &21b0 0f 0e 0e 05 0c 01 08 01 00 02 70 08 f0 08 83 08 &21c0 0f 10 70 08 f0 08 81 08 0f 10 08 01 0f 07 00 01 &21d0 0f 07 00 01 0f 07 00 01 0f 07 00 01 0e 07 07 04 &21e0 03 02 01 01 00 01 0f 08 0e 01 0f 07 00 01 0f 07 &21f0 00 01 0f 07 00 01 0f 07 00 01 0f 07 00 01 0c 07 &2200 00 38 44 08 00 80 44 08 00 50 07 01 00 07 0f 01 &2210 00 07 0f 01 00 02 03 05 0f 01 00 02 0f 05 0c 01 &2220 00 02 0f 05 00 03 0f 05 01 01 00 02 0f 06 00 02 &2230 0c 01 0f 05 00 03 0c 01 0f 03 38 01 00 05 08 01 &2240 0c 01 f0 01 00 02 07 06 00 02 0f 06 00 02 0f 06 &2250 00 02 70 05 03 01 00 02 e0 05 0f 01 00 02 0f 06 &2260 00 02 0f 06 00 02 0e 05 0f 01 00 02 07 05 0f 01 &2270 00 02 0f 05 08 01 00 02 0f 05 00 03 0f 05 70 01 &2280 00 02 0f 05 f0 01 00 02 0f 05 83 01 00 02 0f 06 &2290 00 02 0c 05 0f 01 00 02 0f 05 70 01 00 02 0f 05 &22a0 f0 01 00 02 0f 05 81 01 00 02 0f 06 00 02 0f 06 &22b0 00 02 0f 06 00 02 0f 06 00 02 09 05 0f 01 00 02 &22c0 0f 06 00 02 0f 05 0e 01 00 02 0f 05 00 03 0f 05 &22d0 03 01 00 02 0f 06 00 02 0f 06 00 02 0f 06 00 07 &22e0 0f 01 00 07 0f 01 00 07 0c 01 00 3f 44 08 00 80 &22f0 44 08 00 60 03 08 0f 14 08 01 38 03 0f 04 00 01 &2300 f0 03 0f 04 07 04 0f 08 0c 01 0e 07 07 08 0f 10 &2310 70 08 e0 08 0f 10 0e 08 07 08 0f 0b 0c 01 0f 07 &2320 00 01 0f 07 00 01 0f 07 00 01 0f 07 00 01 0f 04 &2330 0c 03 00 01 0c 04 0f 06 07 02 0f 0b 00 01 0f 07 &2340 00 01 0f 07 00 01 0f 07 00 02 0f 06 00 02 08 01 &2350 0c 01 0f 01 09 03 01 01 00 01 10 03 0f 04 00 01 &2360 f0 03 0f 04 00 01 e0 03 0f 14 0e 04 0f 04 00 01 &2370 f0 03 0f 04 00 01 e0 03 00 58 44 08 00 80 44 06 &2380 22 02 00 60 03 08 0f 10 38 08 f0 08 07 08 0f 08 &2390 0e 08 07 08 0f 10 70 08 e0 08 0f 10 0e 08 07 08 &23a0 0f 0b 0e 05 0f 03 00 01 f0 04 0f 03 00 01 f0 04 &23b0 0f 03 00 01 f0 04 0f 03 00 01 f0 04 0c 03 00 01 &23c0 80 04 03 01 01 01 00 02 f0 04 0f 02 07 01 00 01 &23d0 f0 04 0f 03 00 01 f0 04 0f 03 00 01 f0 04 0f 03 &23e0 01 01 81 04 0f 10 10 01 18 07 f0 08 e0 08 0f 10 &23f0 0e 08 f0 08 e0 08 00 58 44 06 88 02 00 80 22 08 &2400 00 60 03 08 0f 10 38 08 f0 08 07 08 0f 08 0e 08 &2410 07 08 0f 10 70 08 e0 08 0f 10 0e 08 07 08 0f 08 &2420 0e 08 f0 20 80 08 f0 20 81 08 0f 10 18 08 f0 08 &2430 e0 08 0f 10 0e 08 f0 08 e0 08 00 58 88 08 00 80 &2440 22 02 11 06 00 60 03 03 01 03 00 02 0f 07 07 01 &2450 0f 08 08 01 0f 07 00 01 0f 07 07 01 0f 0f 0e 03 &2460 0c 03 08 01 00 01 07 04 03 02 01 01 00 01 0f 10 &2470 00 01 0f 07 00 01 0f 17 0e 08 07 05 03 01 01 01 &2480 00 01 0f 08 0e 01 0f 07 00 01 0f 07 00 01 0f 07 &2490 00 01 0f 07 00 01 0f 07 00 01 0c 07 00 01 0f 07 &24a0 00 01 0f 07 00 01 0f 07 00 01 0f 07 01 01 0f 15 &24b0 0e 01 0c 01 18 04 10 04 f0 08 e0 08 0f 10 0e 08 &24c0 f0 08 e0 08 00 52 11 06 88 02 00 86 11 02 00 08 &24d0 88 06 00 60 01 01 00 07 0f 01 00 07 0f 04 00 04 &24e0 0f 04 00 04 0f 01 0c 03 00 04 0e 01 00 17 03 01 &24f0 01 01 00 06 0f 02 00 06 0f 02 00 06 0f 02 00 06 &2500 0f 02 00 06 0f 02 00 06 0e 02 00 0e 07 01 03 01 &2510 00 06 0f 02 00 06 0f 02 00 06 0f 02 00 06 0f 02 &2520 00 06 0f 02 00 06 0c 02 00 06 0f 02 00 06 0f 02 &2530 00 06 0f 02 00 06 0f 02 00 06 0f 02 00 06 0f 01 &2540 0e 01 00 06 08 01 00 07 10 01 00 07 f0 01 00 07 &2550 e0 01 00 07 0f 02 00 06 0f 02 00 06 0e 02 00 06 &2560 f0 01 00 07 e0 01 00 57 11 02 22 06 00 90 88 01 &2570 44 06 22 01 00 ff 00 e1 22 01 44 06 88 01 00 90 &2580 22 05 11 03 00 ff 00 de 11 03 88 05 00 93 11 02 &2590 00 08 88 04 44 02 00 ff 00 d1 11 02 22 04 44 02 &25a0 00 a0 44 03 22 01 33 01 00 07 88 01 77 01 00 07 &25b0 88 01 77 01 00 07 88 01 77 01 00 07 88 01 00 ff &25c0 00 98 77 01 00 06 33 01 cc 01 00 05 33 01 cc 01 &25d0 00 05 33 01 cc 01 00 02 44 02 88 03 00 c3 77 01 &25e0 00 07 cc 01 33 01 00 07 ee 01 11 01 00 07 ff 01 &25f0 00 08 ff 01 00 07 cc 01 33 01 00 07 ff 01 00 08 &2600 ff 01 00 07 ee 01 11 01 00 07 ff 01 00 07 cc 01 &2610 33 01 00 07 ff 01 00 07 cc 01 00 5a 11 01 33 01 &2620 66 01 45 03 00 01 77 01 88 01 38 01 29 04 00 01 &2630 ff 01 00 01 f0 01 3c 01 96 01 d2 01 3c 01 00 01 &2640 ff 01 00 01 f0 01 69 03 96 01 00 01 cc 01 22 01 &2650 a2 05 00 57 ff 01 00 07 ff 01 00 06 77 01 88 01 &2660 00 06 ff 01 00 06 ff 01 00 06 11 01 ee 01 00 06 &2670 ff 01 00 06 77 01 88 01 00 05 33 01 cc 01 00 05 &2680 11 01 ee 01 00 06 ff 01 00 06 ff 01 00 07 88 01 &2690 00 ff 00 48 33 01 00 07 ff 01 00 07 ff 01 00 08 &26a0 ff 01 00 07 ff 01 00 07 ff 01 00 07 cc 01 33 01 &26b0 00 07 ff 01 00 07 ff 01 00 07 ff 01 00 07 ff 01 &26c0 00 07 ff 01 00 05 45 08 29 03 38 02 0c 01 0f 02 &26d0 d2 02 1e 01 f0 02 00 01 0f 02 96 03 f0 02 00 01 &26e0 0f 01 0c 01 a2 05 20 01 40 01 c4 01 00 02 ff 01 &26f0 00 07 ff 01 00 07 ff 01 00 07 ff 01 00 06 77 01 &2700 88 01 00 06 ff 01 00 07 ff 01 00 06 33 01 cc 01 &2710 00 06 ff 01 00 07 ff 01 00 ff 00 7c 11 05 33 01 &2720 66 01 cc 01 8a 01 06 03 ff 01 00 01 f0 01 c0 04 &2730 80 01 ff 01 00 01 f0 01 e0 03 40 02 ee 01 11 01 &2740 e0 01 60 04 20 01 00 01 11 01 aa 01 cc 01 8a 01 &2750 06 03 ff 01 00 01 f0 06 ff 01 00 01 f0 01 30 05 &2760 ee 01 11 01 e0 06 00 01 33 01 ee 01 cc 01 8a 01 &2770 06 03 ff 01 00 01 f0 01 e0 01 c0 01 80 01 90 02 &2780 ff 01 00 01 f0 01 00 02 e0 01 f0 02 ff 01 11 01 &2790 e0 02 60 01 20 01 60 01 e0 01 00 01 99 01 aa 01 &27a0 cc 01 8a 01 06 03 ff 01 00 01 f0 01 c0 05 ff 01 &27b0 00 01 f0 01 00 02 e0 02 00 01 ff 01 11 01 e0 02 &27c0 60 03 e0 01 00 01 99 01 ee 01 cc 01 8a 01 06 03 &27d0 ff 01 00 01 f0 01 e0 01 c0 01 80 01 90 02 ee 01 &27e0 00 01 f0 01 00 02 e0 01 f0 02 00 01 11 01 e0 02 &27f0 60 01 20 03 00 01 ff 01 22 01 cc 01 8a 01 06 03 &2800 10 01 00 02 30 05 ff 01 00 02 f0 02 10 02 f0 01 &2810 ff 01 11 01 00 02 80 04 00 01 99 01 ee 01 cc 01 &2820 8a 01 06 03 ff 01 00 02 10 01 30 01 70 01 60 02 &2830 ff 01 00 02 f0 02 10 01 00 02 ff 01 11 01 00 02 &2840 80 01 c0 03 00 01 99 01 ee 01 cc 01 8a 01 06 03 &2850 ff 01 00 02 60 04 70 01 ff 01 00 03 40 02 e0 01 &2860 f0 01 ee 01 11 01 00 01 c0 05 11 01 33 01 ee 01 &2870 cc 01 88 01 00 01 06 02 ff 01 00 02 30 05 ff 01 &2880 00 02 f0 02 00 01 f0 02 ee 01 11 01 00 06 11 01 &2890 33 01 ee 01 cc 01 8a 01 06 03 ff 01 00 02 30 05 &28a0 ff 01 00 02 f0 02 10 02 f0 01 ee 01 10 01 00 02 &28b0 80 03 00 03 88 06 00 ff 00 31 11 08 06 05 07 03 &28c0 90 04 f0 01 00 01 0f 02 10 02 b0 02 f0 01 00 01 &28d0 0f 02 20 04 e0 01 00 01 1d 01 3b 01 06 05 07 03 &28e0 f0 05 00 01 0f 02 30 04 f0 01 00 01 0f 02 e0 05 &28f0 00 01 1d 01 3b 01 06 05 07 03 90 01 80 01 c0 01 &2900 e0 01 f0 01 00 01 0f 02 f0 01 e0 01 00 02 f0 01 &2910 00 01 0f 02 60 01 20 01 60 01 e0 02 00 01 1d 01 &2920 3b 01 06 05 07 03 c0 04 f0 01 00 01 0f 02 10 01 &2930 80 01 c0 01 e0 01 f0 01 00 01 0f 02 e0 02 60 01 &2940 20 01 e0 01 00 01 1d 01 3b 01 06 05 07 03 90 01 &2950 80 01 c0 01 e0 01 f0 01 00 01 0f 02 f0 01 e0 01 &2960 00 02 f0 01 00 01 0f 02 20 02 60 01 e0 02 00 01 &2970 1d 01 3b 01 06 05 07 03 30 04 00 02 0f 02 f0 01 &2980 00 05 0f 02 00 06 1d 01 3b 01 06 05 07 03 60 01 &2990 70 01 30 01 10 01 00 02 0f 02 00 01 10 01 f0 02 &29a0 00 02 0f 02 c0 02 80 01 00 03 1d 01 3b 01 06 05 &29b0 07 03 30 04 00 02 0f 02 b0 01 10 03 00 02 0f 02 &29c0 80 04 00 02 1d 01 3b 01 06 05 07 01 03 02 30 04 &29d0 00 02 0f 02 00 02 f0 02 00 02 0f 02 00 06 1f 01 &29e0 3f 01 06 05 07 03 30 04 00 02 0f 02 e0 01 70 01 &29f0 30 01 10 01 00 02 0f 02 00 02 80 01 c0 01 00 02 &2a00 1d 01 39 01 88 06 80 01 00 ff 00 32 11 01 00 07 &2a10 80 01 ff 01 00 07 ff 01 00 07 ff 01 00 06 66 01 &2a20 cc 01 00 06 88 01 ff 01 00 07 ff 01 00 07 ff 01 &2a30 00 06 66 01 cc 01 00 06 88 01 ff 01 00 07 ff 01 &2a40 00 07 ff 01 00 06 55 01 88 01 00 06 88 01 77 01 &2a50 00 07 ff 01 00 07 ff 01 00 06 55 01 88 01 00 06 &2a60 88 01 77 01 00 07 ff 01 00 07 ff 01 00 06 44 01 &2a70 88 01 00 06 88 01 77 01 00 07 ff 01 00 07 ff 01 &2a80 00 06 66 01 cc 01 00 06 88 01 77 01 00 07 ff 01 &2a90 00 07 ff 01 00 06 66 01 cc 01 00 06 88 01 77 01 &2aa0 00 07 ff 01 00 07 ff 01 00 06 44 01 cc 01 00 06 &2ab0 88 01 77 01 00 07 ff 01 00 07 ff 01 00 06 66 01 &2ac0 cc 01 00 06 88 01 77 01 00 07 ff 01 00 07 ff 01 &2ad0 00 06 62 01 cc 01 00 00 ; unpack_screen &2ad8 a9 00 LDA #&00 &2ada 85 72 STA &72 ; target_address_low &2adc a9 30 LDA #&30 &2ade 85 73 STA &73 ; target_address_high ; unpack_screen_loop &2ae0 a0 01 LDY #&01 &2ae2 b1 70 LDA (&70),Y ; source_address # Second of two bytes is run length &2ae4 f0 19 BEQ &2aff ; leave &2ae6 aa TAX &2ae7 88 DEY &2ae8 b1 70 LDA (&70),Y ; source_address # First of two bytes is value ; unpack_screen_run_loop &2aea 91 72 STA (&72),Y ; target_address &2aec e6 72 INC &72 ; target_address_low &2aee d0 02 BNE &2af2 &2af0 e6 73 INC &73 ; target_address_high &2af2 ca DEX &2af3 d0 f5 BNE &2aea ; unpack_run_loop &2af5 e6 70 INC &70 ; source_address_low &2af7 e6 70 INC &70 ; source_address_low &2af9 d0 e5 BNE &2ae0 ; unpack_screen_loop &2afb e6 71 INC &71 ; source_address_high &2afd d0 e1 BNE &2ae0 ; unpack_screen_loop ; leave &2aff 60 RTS Game disassembly ================ # &0000 - &0099 is loaded in 1 block of &9a bytes (block &00) ; objects_state # Values are overwritten ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0000 04 04 04 04 04 04 04 04 04 04 04 04 00 00 00 00 ; &00 # &0000 - &000b are object states &0010 00 00 00 00 00 18 3c 00 30 32 34 36 38 3a 3c 3e ; &10 # &0010 - &0014 are variables, see below &0020 40 42 00 00 80 80 12 12 12 12 ff 00 00 00 00 00 ; &20 # &0018 - &0029 are mover targets &0010 ; tile_chunk_offset &0011 ; tile_y &0012 ; player_must_stop_fighting &0013 ; animate_guard_less_frequently &0014 ; saved_carrying &0030 00 ; mover_offset &0031 00 ; mover_to_consider &0032 00 ; timer_at_vsync &0033 00 ; movers_replot_stage &0034 ff ; wizard_state # Value is used &0035 00 ; bucket_contains_water &0036 00 ; player_air # Value is used &0037 00 ; saved_bucket_contains_water ; movers_horizontal_direction &0038 ff ff ff ff ff ff &003e ff ; prison_bed_is_on_fire # Value is used &003f ff ; object_to_dislodge # Value is used ; movers_vertical_direction &0040 ff ff ff ff ff ff &0046 64 ; lives &0047 ff ; starvation_timer_high ; u r d l ; screen_address_deltas_high # Values are used &0048 fd 00 02 ff ; screen_address_deltas_low &004c 80 08 80 f8 &0050 00 ; slope_flags # All values are overwritten &0051 00 ; (unused) &0052 00 ; player_has_jumped &0053 ff ; player_is_jumping_or_falling &0054 ff ; object_being_dropped_or_thrown &0055 00 ; throw_direction &0056 00 ; throw_or_drop_timer &0057 ff ; score &0058 00 ; (unused) &0059 ff ; object_carried_by_troll &005a 00 ; suppress_timer_check &005b 06 ; columns_to_plot, sprite_offset &005c 1e ; (unused) &005d ff ; prison_escort_state &005e ff ; suppress_top_support_check &005f 00 ; (unused) &0060 00 ; fighting_cooldown, starvation_timer_low &0061 ff ; object_player_is_fighting &0062 00 ; player_is_fighting &0063 ff ; player_was_killed &0064 00 ; object_to_update &0065 00 ; mover_offset &0066 00 ; sprite_is_foreground &0067 00 ; time_low &0068 00 ; time_high &0069 00 ; time_bonus &006a 00 ; vertical_cutoff &006b 00 ; unsupported_horizontal_direction &006c ff ; distance_fallen &006d ff ; jump_stage &006e 00 ; object_direction_for_slopes &006f 00 ; jump_direction &0070 00 ; horizontal_direction &0071 00 ; vertical_direction &0072 00 ; object_edge_being_checked, count, tmp_y &0073 00 ; object_height &0074 00 ; object_width &0075 00 ; death_timer &0076 00 ; y &0077 00 ; x_low &0078 00 ; x_high &0079 00 ; relative_x_low, x_trailing_low, tmp &007a 00 ; relative_x_high, x_trailing_high &007b 00 ; y_subtile, various &007c 00 ; x_subtile, bottom_of_tile_y &007d 00 ; tile_address_low &007e 00 ; tile_address_high &007f 00 ; object_sprite, chunk_address_low &0080 00 ; chunk_address_high &0081 00 ; screen_address_low, previous_horizontal_direction &0082 00 ; screen_address_high, previous_vertical_direction &0083 00 ; screen_start_address_low &0084 30 ; screen_start_address_high &0085 d0 ; screen_start_x_low &0086 02 ; screen_start_x_high &0087 00 ; crtc_start_address_low &0088 06 ; crtc_start_address_high &0089 00 ; saved_level &008a 00 ; object_tile_type &008b 00 ; tile_type, tmp &008c 00 ; (unused) &008d 00 ; tile_chunk_address_low &008e 00 ; tile_chunk_address_high &008f 00 ; sprite_address_low &0090 00 ; sprite_address_high &0091 00 ; tile_sprite_address_low &0092 00 ; tile_sprite_address_high &0093 00 ; (unused) &0094 00 ; (unused) &0095 00 ; width &0096 00 ; height, object_to_update, tmp_x &0097 00 ; initial_x_low &0098 00 ; initial_x_high &0099 00 ; selected_pocket &009a ; previous_selected_pocket &009b ; pocket_to_empty &009c ; carrying &009d ; screen_scrolling_direction &009e ; player_facing # &0380 - &0802 is loaded in 5 blocks of &e7 bytes (blocks &01 - &05) ; calculate_screen_address &0380 a9 1f LDA #&1f &0382 38 SEC &0383 e5 76 SBC &76 ; y &0385 0a ASL A &0386 a8 TAY &0387 a5 77 LDA &77 ; x_low &0389 38 SEC &038a e5 85 SBC &85 ; screen_start_x_low &038c 85 79 STA &79 ; relative_x_low &038e a5 78 LDA &78 ; x_high &0390 e5 86 SBC &86 ; screen_start_x_high &0392 85 7a STA &7a ; relative_x_high &0394 a5 79 LDA &79 ; relative_x_low &0396 0a ASL A &0397 26 7a ROL &7a ; relative_x_high &0399 0a ASL A &039a 26 7a ROL &7a ; relative_x_high &039c 0a ASL A &039d 26 7a ROL &7a ; relative_x_high &039f be 76 c3 LDX &c376,Y ; os_640_multiplication_table_high # Use multiplication table from OS ROM &03a2 86 79 STX &79 ; relative_x_low &03a4 65 79 ADC &79 ; relative_x_low &03a6 85 81 STA &81 ; screen_address_low &03a8 b9 75 c3 LDA &c375,Y ; os_640_multiplication_table_low &03ab 65 7a ADC &7a ; relative_x_high &03ad 85 82 STA &82 ; screen_address_high &03af a5 81 LDA &81 ; screen_address_low &03b1 18 CLC &03b2 65 83 ADC &83 ; screen_start_address_low &03b4 85 81 STA &81 ; screen_address_low &03b6 a5 82 LDA &82 ; screen_address_high &03b8 65 84 ADC &84 ; screen_start_address_high &03ba c9 80 CMP #&80 &03bc 90 02 BCC &03c0 ; skip_overflow &03be e9 50 SBC #&50 &03c0 85 82 STA &82 ; screen_address_high &03c2 60 RTS ; alter_screen_address # Called with X = direction &03c3 a5 81 LDA &81 ; screen_address_low &03c5 18 CLC &03c6 75 4c ADC &4c,X ; screen_address_deltas_low &03c8 85 81 STA &81 ; screen_address_low &03ca a5 82 LDA &82 ; screen_address_high &03cc 75 48 ADC &48,X ; screen_address_deltas_high &03ce c9 80 CMP #&80 &03d0 90 04 BCC &03d6 ; skip_overflow &03d2 e9 50 SBC #&50 &03d4 10 06 BPL &03dc ; skip_underflow # Always branches ; skip_overflow &03d6 c9 30 CMP #&30 &03d8 b0 02 BCS &03dc ; skip_underflow &03da 69 50 ADC #&50 ; skip_underflow &03dc 85 82 STA &82 ; screen_address_high &03de 60 RTS ; unused &03df 00 &03e0 47 41 4d 45 43 4f 50 22 0d ; "GAMECOP\"\r" &03e9 52 55 4e 0d ; "RUN\r" &03ed 43 41 4c 4c 26 34 33 34 30 0d ; "CALL&4340\r" &03f7 22 20 47 41 7f 7f 7f 7f 22 ; "\" GA....\"" ; map_data &0400 11 11 11 11 11 99 11 11 11 11 11 11 99 11 00 00 # Seven bytes per two columns, starting at bottom &0410 00 10 11 99 00 05 08 00 00 60 40 40 06 07 00 00 # High nibble is first column, low nibble is second &0420 00 00 00 11 95 16 10 16 10 10 11 66 56 66 56 00 &0430 00 11 56 66 56 65 00 00 11 60 50 60 60 00 00 11 ; x 0 1 &0440 00 00 00 66 66 77 11 66 65 65 66 65 80 11 66 65 ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f &0450 66 65 00 00 11 65 66 65 66 00 00 11 66 56 66 65 ; y 0808080808080808080808080808080808080808080808080808080808080808 &0460 00 00 11 65 66 66 66 06 00 11 90 10 10 10 10 00 ; 18 #### | # ___ ______ ______=______==_#### &0470 11 31 03 00 00 00 00 00 00 10 31 07 00 00 11 09 ; 14 ======| # ~~~T ~# ######T#######~~~~~~##T#### &0480 01 11 79 01 07 11 00 11 11 00 11 77 11 00 11 12 ; 10 ######~ #~T~~T~ ~~~~~T~~~T~~# __= = |####### ##|#### &0490 90 11 77 11 00 11 00 04 15 80 11 09 11 00 11 11 ; c ##### # ~~T~~ ~T~~~T~~~~# /######\ = # ##T#### &04a0 77 27 00 11 09 11 11 77 99 11 20 00 11 11 77 99 ; 8 #### #~T~~~T ~T~T~~T~~~# /# ###########\ =~ B##|#### &04b0 11 96 10 10 16 97 99 11 00 00 00 66 77 99 11 00 ; 4 #### _ _=T~~T~~ ~~~~~T~~~T= /# = = ###########|#### &04c0 00 00 66 77 99 11 a1 01 01 61 79 94 14 14 15 14 ; 0 #### T ~######################## ##########\_===========|#### &04d0 15 98 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ; &04e0 00 00 00 00 00 00 00 31 05 04 04 05 00 00 11 01 ; x 2 3 &04f0 09 01 61 01 01 11 11 00 00 00 11 11 11 11 00 00 ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f &0500 00 00 11 11 11 00 00 00 01 11 11 11 00 00 00 00 ; y 0808080808080808080808080808080808080808080808080808080808080808 &0510 11 11 11 09 01 01 01 11 11 20 66 66 66 99 11 11 ; &0520 60 56 65 66 99 11 11 56 66 66 66 78 00 11 66 56 ; 18 ############### T ~######## # # &0530 66 56 04 05 11 66 65 56 66 78 06 11 56 65 65 56 ; 14 ### # #====__ |__ _____ __ ____ # # &0540 07 11 11 06 66 65 66 77 11 11 65 56 66 66 78 11 ; 10 T~# #~~~~~~T~~~T~~~~~T~~T T~~~~T = # ______ &0550 11 66 65 66 56 07 11 11 56 66 65 65 80 00 11 99 ; c | # #~~~T~~~~T~~T~T~~~~~T | | /#T = T~~~## &0560 11 04 05 00 00 11 01 11 00 66 77 00 11 00 00 00 ; 8 | = =~~T~~~T~~T~T~~T~~T~~#### | /##|#~~~~~T#T###T## &0570 66 78 00 11 40 40 40 50 00 00 11 31 03 00 00 00 ; 4 T ###########\ ~ T~~~~~T~ ~~T~~T~== # | /##### |=| |## &0580 00 11 11 11 31 09 01 01 11 11 41 50 00 00 00 00 ; 0 /############################################### T######## &0590 00 66 00 00 00 00 00 00 66 00 00 00 00 05 04 65 ; &05a0 00 00 00 00 11 94 15 90 10 10 10 11 00 11 56 77 ; x 4 5 &05b0 00 00 11 04 15 66 77 00 00 11 11 11 11 77 00 00 ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f &05c0 40 50 00 60 80 00 00 10 10 90 10 80 66 00 00 66 ; y 0808080808080808080808080808080808080808080808080808080808080808 &05d0 04 65 85 00 00 00 60 01 10 66 78 00 01 10 04 04 ; &05e0 05 00 00 00 10 01 00 06 07 00 04 04 04 14 65 80 ; 18 ###### ######## ## T########| # # | &05f0 11 00 04 04 04 05 00 11 01 01 01 00 66 77 11 00 ; 14 ~~ __ __ ___ __ __= ~T## |#__ __| # ~~T~# #~T~ &0600 00 00 00 60 80 00 01 01 01 05 05 00 11 11 12 20 ; 10 _ _ _T~~ T ~~T T~~~ T~~T~######## |#~~~~T~~| # T# #| &0610 66 66 78 11 11 40 51 56 56 07 11 11 00 11 77 11 ; c ~ # ~T# | #| | T~~T~___= ## |# ~ = T~# #~T~ &0620 79 11 11 00 11 79 11 00 00 11 04 65 00 11 65 00 ; 8 = | # | # | | # #\ T#####~T## |############# #T# &0630 11 11 11 11 11 11 11 11 cc 00 00 00 00 00 11 cc ; 4 T # ~~~ # # | | # ##\| |##WWWWWXWWWWWWWWWWWWWWWWWWWWWWXW &0640 00 00 00 00 00 11 cb 04 04 04 04 05 11 cc 11 10 ; 0 | # # | # ########################################### &0650 16 17 11 11 cc 11 00 66 80 11 11 cc 11 06 65 00 ; &0660 11 11 cc 11 00 66 78 11 11 cc 11 00 40 40 40 11 ; x 6 7 &0670 cc 11 90 10 10 10 11 cc 10 56 00 66 00 11 cc 00 ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b &0680 10 51 56 00 11 cc 00 00 00 10 01 11 cc 00 00 01 ; y 08080808080808080808080808080808080808080808080808080808 &0690 16 00 11 cc 01 16 40 56 04 11 bc 51 56 00 00 00 ; &06a0 11 cc 11 11 11 11 01 11 cc 00 00 00 00 00 11 cc ; 18 # ######################T##########|====|#### /##### &06b0 01 01 01 01 01 11 cc 11 40 51 00 11 11 b1 51 01 ; 14 ## # #### |~~~~~~~~~~~~~~~~~~~~ /###### &06c0 11 00 11 15 10 11 11 11 00 11 11 04 14 14 15 00 ; 10 ## #T######T#### | /####### &06d0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ; c ## #| ####|####T~ ~~T~ ~T # # # # # # T T ######### &06e0 04 65 56 00 00 11 11 00 00 06 00 00 11 11 09 01 ; 8 ## ###T####|####~T # # # # # # # # # T T########## &06f0 65 00 00 11 11 09 01 60 00 00 11 11 09 01 65 04 ; 4 WWWWWWWWX## |#### | = = = # # # # # # # # T ##### &0700 04 15 11 01 00 01 00 66 11 11 01 10 01 00 66 11 ; 0 ###########T####################W#W#W#W#W#W############# &0710 c1 01 01 01 00 66 11 c1 01 01 01 00 66 11 c1 01 &0720 01 01 00 66 11 c1 01 01 01 00 66 49 c1 01 01 05 &0730 00 66 99 c1 01 05 05 00 66 94 11 05 05 00 00 66 &0740 11 11 00 11 01 00 66 11 11 00 11 11 31 03 00 11 &0750 01 11 11 11 11 31 11 11 11 11 11 11 11 11 11 11 &0760 11 11 11 11 11 11 11 11 11 ; get_map_tile &0769 a5 76 LDA &76 ; y &076b 4a LSR A # Four subtiles to a tile vertically &076c 4a LSR A &076d a8 TAY &076e 84 11 STY &11 ; tile_y &0770 a5 77 LDA &77 ; x_low &0772 85 7d STA &7d ; tile_address_low &0774 a5 78 LDA &78 ; x_high &0776 4a LSR A &0777 85 7e STA &7e ; tile_address_high &0779 08 PHP &077a 66 7d ROR &7d ; tile_address_low &077c 4a LSR A # Eight subtiles to a tile horizontally &077d 66 7d ROR &7d ; tile_address_low &077f 4a LSR A &0780 66 7d ROR &7d ; tile_address_low &0782 4a LSR A &0783 66 7d ROR &7d ; tile_address_low &0785 a5 77 LDA &77 ; x_low &0787 28 PLP &0788 6a ROR A &0789 29 f8 AND #&f8 &078b 38 SEC &078c e5 7d SBC &7d ; tile_address_low # stored in columns of 7 bytes &078e 85 7d STA &7d ; tile_address_low &0790 a5 7e LDA &7e ; tile_address_high &0792 e9 00 SBC #&00 &0794 18 CLC &0795 69 04 ADC #&04 ; &0400 = map_data &0797 85 7e STA &7e ; tile_address_high ; get_next_map_tile &0799 a5 77 LDA &77 ; x_low &079b 29 08 AND #&08 &079d f0 07 BEQ &07a6 ; use_high_nibble ; use_low_nibble &079f b1 7d LDA (&7d),Y ; tile_address &07a1 29 0f AND #&0f &07a3 85 8b STA &8b ; tile_type &07a5 60 RTS ; use_high_nibble &07a6 b1 7d LDA (&7d),Y ; tile_address &07a8 4a LSR A &07a9 4a LSR A &07aa 4a LSR A &07ab 4a LSR A &07ac 85 8b STA &8b ; tile_type &07ae 60 RTS ; get_direction_and_distance_from_object_X_to_object_Y &07af a9 ff LDA #&ff &07b1 85 70 STA &70 ; horizontal_direction # Negative to indicate no movement by default &07b3 85 71 STA &71 ; vertical_direction &07b5 b9 a0 0b LDA &0ba0,Y ; objects_x_low &07b8 38 SEC &07b9 fd a0 0b SBC &0ba0,X ; objects_x_low &07bc 85 77 STA &77 ; x_low # x_low is horizontal distance between the two objects &07be b9 e8 0b LDA &0be8,Y ; objects_x_high &07c1 fd e8 0b SBC &0be8,X ; objects_x_high &07c4 f0 11 BEQ &07d7 ; skip_comparing_x_high # horizontal_direction is &ff if objects aligned &07c6 c9 ff CMP #&ff &07c8 d0 31 BNE &07fb ; leave_with_negative_x &07ca a9 00 LDA #&00 ; HORIZONTAL_LEFT # &00 if object Y is left of object X &07cc 85 70 STA &70 ; horizontal_direction &07ce 38 SEC &07cf e5 77 SBC &77 ; x_low # Invert x_low to keep it positive &07d1 85 77 STA &77 ; x_low &07d3 f0 26 BEQ &07fb ; leave_with_negative &07d5 d0 08 BNE &07df ; consider_vertical_difference ; skip_comparing_x_high &07d7 a5 77 LDA &77 ; x_low &07d9 f0 04 BEQ &07df ; consider_vertical_difference &07db a9 02 LDA #&02 ; HORIZONTAL_RIGHT # &02 if object Y is right of object X &07dd 85 70 STA &70 ; horizontal_direction ; consider_vertical_difference &07df bd 30 0c LDA &0c30,X ; objects_y &07e2 38 SEC &07e3 f9 30 0c SBC &0c30,Y ; objects_y &07e6 85 76 STA &76 ; y # y is vertical distance between the two objects &07e8 f0 10 BEQ &07fa ; leave # vertical_direction is &ff if objects aligned &07ea b0 0a BCS &07f6 ; set_moving_down &07ec a9 00 LDA #&00 ; VERTICAL_UP # &00 if object Y is above object X &07ee 85 71 STA &71 ; vertical_direction &07f0 38 SEC &07f1 e5 76 SBC &76 ; y # Invert y to keep it positive &07f3 85 76 STA &76 ; y &07f5 60 RTS ; set_moving_down &07f6 a9 01 LDA #&01 ; VERTICAL_DOWN # &01 if object Y is below object X &07f8 85 71 STA &71 ; vertical_direction ; leave &07fa 60 RTS ; leave_with_negative &07fb a9 ff LDA #&ff # Leave with negative if objects are on different levels &07fd 85 77 STA &77 ; x_low &07ff 60 RTS ; unused &0800 ff 00 00 # Three bytes loaded into OS sound workspace, unused # &1680 - &3efa is loaded in 43 blocks of &f1 bytes (blocks &06 - &30) &1680 69 07 JSR &0769 ; get_map_tile # Continuation of consider_climbing_ladder, see &1621 &1682 c9 0b CMP #&0b ; TILE_WATER_LADDER # Is the tile a ladder? &1684 f0 08 BEQ &168e ; is_ladder &1686 c9 06 CMP #&06 ; TILE_PLATFORM # (matches &04 TILE_LADDER and &05 TILE_LADDER_PLATFORM) &1688 10 15 BPL &169f ; clear_vertical_direction_and_leave_with_carry_set &168a c9 04 CMP #&04 ; TILE_LADDER &168c 30 11 BMI &169f ; clear_vertical_direction_and_leave_with_carry_set ; is_ladder &168e bd 30 0c LDA &0c30,X ; objects_y &1691 29 01 AND #&01 # Animate sprite depending on position on ladder &1693 18 CLC &1694 69 04 ADC #&04 ; FRAME_UP_AND_DOWN &1696 9d 18 0d STA &0d18,X ; objects_moving - &18 &1699 a9 ff LDA #&ff ; HORIZONTAL_NONE &169b 85 70 STA &70 ; horizontal_direction &169d 18 CLC # Leave with carry clear to indicate climbing &169e 60 RTS ; clear_vertical_direction_and_leave_with_carry_set &169f a9 ff LDA #&ff ; VERTICAL_NONE &16a1 85 71 STA &71 ; vertical_direction &16a3 38 SEC # Leave with carry set to indicate not climbing &16a4 60 RTS ; check_if_carried_object_stops_movement &16a5 a5 9e LDA &9e ; player_facing # Negative if player is facing vertically; if so, leave &16a7 30 35 BMI &16de ; leave_with_carry_clear &16a9 a4 9c LDY &9c ; carrying # Leave if player isn't carrying anything &16ab 30 31 BMI &16de ; leave_with_carry_clear &16ad a5 50 LDA &50 ; slope_flags # Non-zero if tile is a slope &16af d0 2d BNE &16de ; leave_with_carry_clear # Carried object is never blocked by slope ; update_carried_object &16b1 b9 00 00 LDA &0000,Y ; objects_state &16b4 c9 04 CMP #&04 ; OBJECT_STATE_IN_WORLD # Is the object being carried? &16b6 f0 1f BEQ &16d7 ; stop_movement &16b8 48 PHA &16b9 a5 70 LDA &70 ; horizontal_direction &16bb 99 00 00 STA &0000,Y ; objects_state # Temporarily set the object's state from direction &16be 20 dc 2e JSR &2edc ; offset_object_Y_from_object_X # to position the object left or right of the player &16c1 68 PLA ; object_state &16c2 99 00 00 STA &0000,Y ; objects_state # Restore previous state &16c5 84 72 STY &72 ; tmp_y &16c7 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &16ca 20 dc 2e JSR &2edc ; offset_object_Y_from_object_X &16cd 20 50 1c JSR &1c50 ; calculate_object_edges &16d0 20 3f 1c JSR &1c3f ; check_if_tile_is_wall_or_offscreen # Returns carry set if object would be in complete wall &16d3 a4 72 LDY &72 ; tmp_y &16d5 90 07 BCC &16de ; leave_with_carry_clear ; stop_movement &16d7 a9 ff LDA #&ff ; HORIZONTAL_AND_VERTICAL_NONE # If so, stop the movement &16d9 85 71 STA &71 ; vertical_direction &16db 85 70 STA &70 ; horizontal_direction &16dd 60 RTS # and leave with carry set to indicate object blocked ; leave_with_carry_clear &16de 18 CLC # Leave with carry clear to indicate no obstacle &16df 60 RTS ; update_newly_retrieved_object &16e0 a5 9e LDA &9e ; player_facing # Offset object depending on direction of player &16e2 85 70 STA &70 ; horizontal_direction &16e4 a2 2f LDX #&2f ; OBJECT_PLAYER &16e6 10 c9 BPL &16b1 ; update_carried_object # Always branches ; keep_player_on_screen &16e8 a2 2f LDX #&2f ; OBJECT_PLAYER &16ea a5 9d LDA &9d ; screen_scrolling_direction &16ec 10 14 BPL &1702 ; skip_forcing_scroll # Positive if screen is already scrolling &16ee 20 98 21 JSR &2198 ; get_object_variables_for_object_X &16f1 20 10 09 JSR &0910 ; check_if_object_is_on_screen &16f4 a5 79 LDA &79 ; relative_x_low &16f6 c9 10 CMP #&10 # Force scroll if player too close to left &16f8 30 04 BMI &16fe ; force_scroll &16fa c9 3b CMP #&3b # or right of screen &16fc 30 04 BMI &1702 ; skip_forcing_scroll ; force_scroll &16fe a5 70 LDA &70 ; horizontal_direction # Set screen scrolling in direction of player movement &1700 85 9d STA &9d ; screen_scrolling_direction ; skip_forcing_scroll &1702 ad 47 0d LDA &0d47 ; objects_moving - &18 + OBJECT_PLAYER # Use player sprite &1705 85 7f STA &7f ; object_sprite &1707 20 cc 2c JSR &2ccc ; add_active_mover &170a 60 RTS ; calculate_sprite_from_direction &170b a5 70 LDA &70 ; horizontal_direction &170d 30 11 BMI &1720 ; not_moving_horizontally &170f bd a0 0b LDA &0ba0,X ; objects_x_low &1712 29 01 AND #&01 &1714 a4 50 LDY &50 ; slope_flags # Zero if tile isn't a slope &1716 f0 02 BEQ &171a ; not_slope &1718 49 01 EOR #&01 # Use different animation on slope ; not_slope &171a 18 CLC &171b 65 70 ADC &70 ; horizontal_direction # Use left or right sprites depending on direction &171d 9d 18 0d STA &0d18,X ; objects_moving - &18 ; not_moving_horizontally &1720 bd 18 0d LDA &0d18,X ; objects_moving - &18 # Use previous sprite if not moving horizontally &1723 60 RTS ; check_if_player_is_standing_on_stool &1724 a5 09 LDA &09 ; objects_state + OBJECT_STOOL # Is the stool in the world? &1726 c9 04 CMP #&04 ; OBJECT_STATE_IN_WORLD &1728 d0 2d BNE &1757 ; leave &172a ad 17 0c LDA &0c17 ; objects_x_high + OBJECT_PLAYER # Is the player standing on the stool? &172d cd f1 0b CMP &0bf1 ; objects_x_high + OBJECT_STOOL &1730 d0 25 BNE &1757 ; leave &1732 ac 5f 0c LDY &0c5f ; objects_y + OBJECT_PLAYER &1735 88 DEY &1736 cc 39 0c CPY &0c39 ; objects_y + OBJECT_STOOL &1739 d0 1c BNE &1757 ; leave &173b ad a9 0b LDA &0ba9 ; objects_x_low + OBJECT_STOOL &173e 38 SEC &173f ed cf 0b SBC &0bcf ; objects_x_low + OBJECT_PLAYER &1742 90 13 BCC &1757 ; leave &1744 c9 03 CMP #&03 &1746 b0 0f BCS &1757 ; leave &1748 a9 ff LDA #&ff &174a 85 6d STA &6d ; jump_stage &174c 85 53 STA &53 ; player_is_jumping_or_falling # Set to negative to indicate player is supported &174e 85 6c STA &6c ; distance_fallen &1750 a2 68 LDX #&68 ; sound_2 # Silence channel 2 &1752 20 35 0a JSR &0a35 ; play_sound &1755 68 PLA # Leave update_jumping_or_falling_player on return &1756 68 PLA &1757 60 RTS ; update_player &1758 a2 2f LDX #&2f ; OBJECT_PLAYER &175a 20 75 20 JSR &2075 ; check_for_object_changing_level # Returns carry set if object changing level &175d 90 03 BCC &1762 ; not_changing_level &175f 4c 35 1f JMP &1f35 ; change_player_level ; not_changing_level &1762 a5 63 LDA &63 ; player_was_killed # Negative if player hasn't been killed &1764 30 03 BMI &1769 ; not_killed &1766 4c b5 27 JMP &27b5 ; update_dead_or_stunned_player ; not_killed &1769 a9 00 LDA #&00 &176b a4 ec LDY &ec ; os_most_recently_pressed_key &176d c0 c9 CPY #&c9 ; ENTER # Is the player wanting to jump? &176f f0 02 BEQ &1773 ; skip_resetting_player_has_jumped &1771 85 52 STA &52 ; player_has_jumped # If not, set to zero to indicate player can jump ; skip_resetting_player_has_jumped &1773 a5 ed LDA &ed ; os_first_pressed_key &1775 20 24 2f JSR &2f24 ; check_for_function_keys # Returns positive if function key pressed &1778 10 05 BPL &177f ; skip_check &177a a5 ec LDA &ec ; os_most_recently_pressed_key &177c 20 24 2f JSR &2f24 ; check_for_function_keys ; skip_check &177f a5 9e LDA &9e ; player_facing # Negative if player is facing vertically &1781 30 0f BMI &1792 ; check_for_scrolling # Can't do anything with objects if facing vertically &1783 20 18 1d JSR &1d18 ; check_for_throwing_or_dropping &1786 a5 ed LDA &ed ; os_first_pressed_key &1788 20 34 2f JSR &2f34 ; check_for_pickup_store_and_retrieve &178b 30 05 BMI &1792 ; check_for_scrolling &178d a5 ec LDA &ec ; os_most_recently_pressed_key &178f 20 34 2f JSR &2f34 ; check_for_pickup_store_and_retrieve ; check_for_scrolling &1792 a9 ff LDA #&ff ; HORIZONTAL_AND_VERTICAL_NONE # Player isn't moving unless keys are pressed &1794 85 70 STA &70 ; horizontal_direction &1796 85 71 STA &71 ; vertical_direction &1798 a2 2f LDX #&2f ; OBJECT_PLAYER &179a a5 53 LDA &53 ; player_is_jumping_or_falling # Zero if player is jumping or falling &179c 30 03 BMI &17a1 ; check_for_scrolling_right &179e 4c ce 1a JMP &1ace ; update_jumping_or_falling_player ; check_for_scrolling_right # If the player is not jumping or falling &17a1 20 98 21 JSR &2198 ; get_object_variables_for_object_X # Get player's position &17a4 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns relative position in relative_x_low &17a7 a5 ec LDA &ec ; os_most_recently_pressed_key &17a9 c9 d2 CMP #&d2 ; C # Does the player want to scroll the screen right? &17ab d0 0a BNE &17b7 ; check_for_scrolling_left &17ad a5 79 LDA &79 ; relative_x_low &17af c9 10 CMP #&10 &17b1 30 17 BMI &17ca ; skip_scrolling # Don't allow scroll if player is close to left edge &17b3 a9 02 LDA #&02 ; HORIZONTAL_RIGHT &17b5 10 0e BPL &17c5 ; set_screen_scrolling_direction # Always branches ; check_for_scrolling_left &17b7 a5 ec LDA &ec ; os_most_recently_pressed_key &17b9 c9 e3 CMP #&e3 ; V # Does the player want to scroll the screen left? &17bb d0 0d BNE &17ca ; skip_scrolling &17bd a5 79 LDA &79 ; relative_x_low &17bf c9 3b CMP #&3b &17c1 10 07 BPL &17ca ; skip_scrolling # Don't allow scroll if player is close to right edge &17c3 a9 00 LDA #&00 ; HORIZONTAL_LEFT ; set_screen_scrolling_direction &17c5 85 9d STA &9d ; screen_scrolling_direction &17c7 4c 75 18 JMP &1875 ; finish_player_movement ; skip_scrolling &17ca a5 62 LDA &62 ; player_is_fighting # Negative if player is fighting enemy &17cc 10 01 BPL &17cf ; check_for_player_jumping # Can't jump if fighting enemy &17ce 60 RTS ; check_for_player_jumping &17cf a5 52 LDA &52 ; player_has_jumped # Non-zero if player is pressing jump key &17d1 d0 21 BNE &17f4 ; check_for_player_moving &17d3 a5 ec LDA &ec ; os_most_recently_pressed_key &17d5 c9 c9 CMP #&c9 ; ENTER # Does the player want to jump? &17d7 d0 1b BNE &17f4 ; check_for_player_moving ; start_jump &17d9 a9 00 LDA #&00 &17db 85 6d STA &6d ; jump_stage # Set to zero to start jump &17dd 85 53 STA &53 ; player_is_jumping_or_falling # Set to zero to indicate player is jumping &17df a9 01 LDA #&01 &17e1 85 52 STA &52 ; player_has_jumped # Set to non-zero to prevent jump auto-repeat &17e3 a5 ed LDA &ed ; os_first_pressed_key &17e5 20 85 2e JSR &2e85 ; check_for_movement_keys # Check keyboard for direction of jump &17e8 a5 70 LDA &70 ; horizontal_direction &17ea 85 6f STA &6f ; jump_direction &17ec a2 70 LDX #&70 ; sound_3 # Play sound for jumping &17ee 20 35 0a JSR &0a35 ; play_sound &17f1 4c 08 1b JMP &1b08 ; update_jump ; check_for_player_moving &17f4 a5 ed LDA &ed ; os_first_pressed_key &17f6 20 85 2e JSR &2e85 ; check_for_movement_keys # Returns positive if movement key pressed &17f9 10 05 BPL &1800 ; skip_check &17fb a5 ec LDA &ec ; os_most_recently_pressed_key &17fd 20 85 2e JSR &2e85 ; check_for_movement_keys ; skip_check &1800 a5 70 LDA &70 ; horizontal_direction &1802 c5 62 CMP &62 ; player_is_fighting # &ff if fighting &1804 d0 06 BNE &180c ; not_stopped_by_guard &1806 a9 ff LDA #&ff ; HORIZONTAL_NONE # Stop player moving into guard at start of fight &1808 85 70 STA &70 ; horizontal_direction &180a 30 69 BMI &1875 ; finish_player_movement # Always branches ; not_stopped_by_guard &180c a5 70 LDA &70 ; horizontal_direction # Negative if player isn't moving horizontally &180e 30 27 BMI &1837 ; consider_vertical_movement &1810 20 98 21 JSR &2198 ; get_object_variables_for_object_X # Never returns negative &1813 30 22 BMI &1837 ; consider_vertical_movement # Bug / unnecessary code; never branches &1815 20 8b 1c JSR &1c8b ; consider_slope_and_support # Returns carry set if player not supported &1818 b0 10 BCS &182a ; not_supported &181a 20 a5 16 JSR &16a5 ; check_if_carried_object_stops_movement # Returns carry set if carried object hits an obstacle &181d b0 56 BCS &1875 ; finish_player_movement ; update_walking_player &181f a2 b8 LDX #&b8 ; sound_12 # Play sound for player walking &1821 20 35 0a JSR &0a35 ; play_sound &1824 20 0b 17 JSR &170b ; calculate_sprite_from_direction &1827 4c 6d 18 JMP &186d ; set_facing_and_scrolling_from_direction ; not_supported &182a a5 9e LDA &9e ; player_facing # Negative if player facing vertically &182c 30 17 BMI &1845 ; shift_sideways_on_ladder &182e a5 6b LDA &6b ; unsupported_horizontal_direction # Move player even though not supported &1830 85 70 STA &70 ; horizontal_direction &1832 30 41 BMI &1875 ; finish_player_movement # Negative if not slipping sideways &1834 4c 60 18 JMP &1860 ; set_falling # Set player falling off platform ; consider_vertical_movement &1837 20 21 16 JSR &1621 ; consider_climbing_ladder &183a a5 71 LDA &71 ; vertical_direction &183c 30 37 BMI &1875 ; finish_player_movement &183e a2 a0 LDX #&a0 ; sound_9 # Play sound for player climbing &1840 20 35 0a JSR &0a35 ; play_sound &1843 10 28 BPL &186d ; set_facing_and_scrolling_from_direction # Always branches ; shift_sideways_on_ladder &1845 a5 67 LDA &67 ; time_low &1847 29 01 AND #&01 # Player moves sideways on ladder at half speed &1849 d0 2a BNE &1875 ; finish_player_movement &184b a5 6b LDA &6b ; unsupported_horizontal_direction # Move player even though not supported &184d 85 70 STA &70 ; horizontal_direction &184f ad 47 0d LDA &0d47 ; objects_moving - &18 + OBJECT_PLAYER &1852 49 01 EOR #&01 # Animate player sprite &1854 8d 47 0d STA &0d47 ; objects_moving - &18 + OBJECT_PLAYER &1857 ad cf 0b LDA &0bcf ; objects_x_low + OBJECT_PLAYER &185a 29 07 AND #&07 &185c c9 05 CMP #&05 &185e 30 15 BMI &1875 ; finish_player_movement # Has the player moved off the ladder? ; set_falling &1860 a2 60 LDX #&60 ; sound_1 # Play sound for falling player &1862 20 35 0a JSR &0a35 ; play_sound &1865 a9 00 LDA #&00 &1867 85 53 STA &53 ; player_is_jumping_or_falling # Set to zero to indicate player is falling &1869 85 6c STA &6c ; distance_fallen &186b f0 04 BEQ &1871 ; set_scrolling_from_direction # Always branches ; set_facing_and_scrolling_from_direction &186d a5 70 LDA &70 ; horizontal_direction &186f 85 9e STA &9e ; player_facing ; set_scrolling_from_direction &1871 a5 70 LDA &70 ; horizontal_direction &1873 85 9d STA &9d ; screen_scrolling_direction ; finish_player_movement &1875 20 ac 2e JSR &2eac ; update_object_carried_by_player &1878 20 e8 16 JSR &16e8 ; keep_player_on_screen &187b a2 2f LDX #&2f ; OBJECT_PLAYER &187d 86 62 STX &62 ; player_is_fighting # Set positive to indicate player isn't fighting &187f 60 RTS ; update_green_guards &1880 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &1882 a2 a2 LDX #&a2 ; G # Set colour 10 (guard body) to green &1884 20 f4 ff JSR &fff4 ; OSBYTE &1887 a9 03 LDA #&03 # Four guards &1889 85 65 STA &65 ; mover_offset &188b a2 1b LDX #&1b ; OBJECT_LAST_GREEN_GUARD ; update_guards_loop &188d 20 9a 1a JSR &1a9a ; update_guard &1890 c6 64 DEC &64 ; object_to_update &1892 a6 64 LDX &64 ; object_to_update &1894 c6 65 DEC &65 ; mover_offset &1896 10 f5 BPL &188d ; update_guards_loop &1898 60 RTS ; update_fighting_guard &1899 a5 12 LDA &12 ; player_must_stop_fighting # Zero if player was stunned &189b f0 61 BEQ &18fe ; stop_fighting_guard # If so, stop fighting &189d c6 60 DEC &60 ; fighting_cooldown # Has the player fought the guard for long enough? &189f d0 06 BNE &18a7 ; is_fighting &18a1 20 ad 19 JSR &19ad ; set_guard_falling_off_screen # If so, set the guard falling off screen &18a4 4c fe 18 JMP &18fe ; stop_fighting_guard ; is_fighting &18a7 a5 9c LDA &9c ; carrying # Is the player carrying the sword? &18a9 d0 53 BNE &18fe ; stop_fighting_guard # If not, stop fighting &18ab a9 ff LDA #&ff ; HORIZONTAL_NONE &18ad 85 70 STA &70 ; horizontal_direction # Player doesn't move by default &18af a5 ec LDA &ec ; os_most_recently_pressed_key &18b1 20 85 2e JSR &2e85 ; check_for_movement_keys # Check keyboard for player movement during fight &18b4 a2 2f LDX #&2f ; OBJECT_PLAYER &18b6 a5 70 LDA &70 ; horizontal_direction &18b8 30 04 BMI &18be ; skip_facing_check &18ba c5 9e CMP &9e ; player_facing # Has the player turned away from the guard? &18bc d0 40 BNE &18fe ; stop_fighting_guard # If so, stop fighting ; skip_facing_check &18be a5 60 LDA &60 ; fighting_cooldown &18c0 29 01 AND #&01 &18c2 d0 35 BNE &18f9 ; prevent_movement # Stop the player moving 1 in 2 frames while fighting &18c4 a5 60 LDA &60 ; fighting_cooldown &18c6 29 08 AND #&08 &18c8 d0 06 BNE &18d0 ; move_player_backwards &18ca a5 70 LDA &70 ; horizontal_direction # For 1 in 8 of the remaining frames, move forwards &18cc 30 2b BMI &18f9 ; prevent_movement &18ce 10 06 BPL &18d6 ; move_player_during_fight # Always branches ; guard_tries_to_push_player_backwards &18d0 a5 9e LDA &9e ; player_facing &18d2 49 02 EOR #&02 ; HORIZONTAL_RIGHT # Otherwise, move backwards &18d4 85 70 STA &70 ; horizontal_direction ; move_player_during_fight &18d6 a2 2f LDX #&2f ; OBJECT_PLAYER &18d8 20 98 21 JSR &2198 ; get_object_variables_for_object_X &18db 20 8b 1c JSR &1c8b ; consider_slope_and_support # Returns carry set if player not supported &18de b0 19 BCS &18f9 ; stop_guard_moving &18e0 a5 50 LDA &50 ; slope_flags # Zero if not on slope, &80 clear if above slope &18e2 10 06 BPL &18ea ; not_on_slope &18e4 20 c5 19 JSR &19c5 ; attack_guard_when_guard_has_upper_hand # Guard has an advantage when fighting down a slope &18e7 4c fe 18 JMP &18fe ; stop_fighting_guard ; not_on_slope &18ea a6 64 LDX &64 ; object_to_update &18ec 20 98 21 JSR &2198 ; get_object_variables_for_object_X &18ef 20 8b 1c JSR &1c8b ; consider_slope_and_support # Returns carry set if guard not supported &18f2 b0 05 BCS &18f9 ; stop_guard_moving &18f4 a5 50 LDA &50 ; slope_flags # Zero if not on slope, &80 set if not above slope &18f6 30 06 BMI &18fe ; stop_fighting_guard # Can't fight guard up slope &18f8 60 RTS ; stop_guard_moving &18f9 a9 ff LDA #&ff ; HORIZONTAL_NONE &18fb 85 70 STA &70 ; horizontal_direction &18fd 60 RTS ; stop_fighting_guard &18fe a0 0f LDY #&0f ; OBJECT_CROSSED_SWORDS &1900 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &1903 20 9d 22 JSR &229d ; unplot_object # Unplot crossed swords &1906 a9 40 LDA #&40 &1908 85 61 STA &61 ; object_player_is_fighting # Set &40 to indicate player isn't fighting &190a 85 12 STA &12 ; player_must_stop_fighting # Set to non-zero to allow future fighting &190c 85 62 STA &62 ; player_is_fighting # Set positive to indicate player isn't fighting &190e a6 64 LDX &64 ; object_to_update &1910 4c 4e 24 JMP &244e ; move_mover # Move guard ; move_guard_towards_target &1913 a9 01 LDA #&01 # Set to non-zero to animate guard less frequently &1915 85 13 STA &13 ; animate_guard_less_frequently &1917 b4 00 LDY &00,X ; objects_state # Consider the guard's target &1919 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &191c a5 77 LDA &77 ; x_low # x_low is the horizontal distance from guard to target &191e d0 0a BNE &192a ; not_at_target &1920 a5 76 LDA &76 ; y # y is the vertical distance from guard to target &1922 d0 0d BNE &1931 ; to_move_mover ; guard_is_at_target # If the guard is at the target, &1924 98 TYA &1925 49 01 EOR #&01 &1927 95 00 STA &00,X ; objects_state # Set them moving towards their other target &1929 60 RTS ; not_at_target &192a c9 60 CMP #&60 # If the guard is too far away from their target, &192c 90 03 BCC &1931 ; to_move_mover &192e 20 48 24 JSR &2448 ; stop_mover_moving # stop them moving ; to_move_mover &1931 4c 4e 24 JMP &244e ; move_mover # Otherwise move guard towards target ; update_not_fighting_guard &1934 a5 63 LDA &63 ; player_was_killed # Positive if player is stunned or dead &1936 10 db BPL &1913 ; move_guard_towards_target # If the player is dead, guard moves towards target &1938 ad 17 0c LDA &0c17 ; objects_x_high + OBJECT_PLAYER &193b dd 40 0b CMP &0b40,X ; initial_objects_x_high &193e d0 d3 BNE &1913 ; move_guard_towards_target # Is the player on the same level as the guard? &1940 a0 2f LDY #&2f ; OBJECT_PLAYER # If so, consider if the player is close to the guard &1942 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &1945 a5 77 LDA &77 ; x_low # x_low is the horizontal distance from guard to player &1947 dd 4d 0a CMP &0a4d,X ; guards_sensitivity_x_low - OBJECT_FIRST_GREEN_GUARD &194a b0 c7 BCS &1913 ; move_guard_towards_target &194c a5 76 LDA &76 ; y # y is the vertical distance from guard to player &194e dd 58 0a CMP &0a58,X ; guards_sensitivity_y - OBJECT_FIRST_GREEN_GUARD &1951 b0 c0 BCS &1913 ; move_guard_towards_target ; player_is_close_to_guard &1953 a9 00 LDA #&00 # Set to zero to indicate guard should chase player &1955 85 50 STA &50 ; guard_aggressiveness &1957 a5 9e LDA &9e ; player_facing &1959 30 0a BMI &1965 ; not_threatened &195b c5 70 CMP &70 ; horizontal_direction &195d f0 06 BEQ &1965 ; not_threatened # Is the player facing the guard? &195f a5 9c LDA &9c ; carrying &1961 d0 02 BNE &1965 ; not_threatened # If so, is the player carrying the sword? &1963 c6 50 DEC &50 ; guard_aggressiveness # Set to &ff to indicate guard shouldn't chase ; not_threatened &1965 bd 18 0d LDA &0d18,X ; objects_moving - &18 &1968 c9 04 CMP #&04 &196a 30 07 BMI &1973 ; moving_horizontally # If the guard is climbing a ladder, &196c a5 9e LDA &9e ; player_facing &196e 30 09 BMI &1979 ; consider_chasing_on_ladder # consider chasing only if the player is too &1970 4c 4e 24 JMP &244e ; move_mover ; moving_horizontally &1973 29 02 AND #&02 # Is the guard facing the player's back? &1975 c5 70 CMP &70 ; horizontal_direction &1977 d0 04 BNE &197d ; not_facing_player ; consider_chasing_on_ladder &1979 e6 50 INC &50 ; guard_aggressiveness # Becomes &00 if threatened or &01 if chasing &197b 10 07 BPL &1984 ; consider_engaging # Always branches ; not_facing_player &197d a5 50 LDA &50 ; guard_aggressiveness &197f d0 03 BNE &1984 ; consider_engaging &1981 4c 07 1a JMP &1a07 ; move_guard ; consider_engaging &1984 a4 9e LDY &9e ; player_facing &1986 a5 50 LDA &50 ; guard_aggressiveness # Zero if guard is threatened &1988 d0 0f BNE &1999 ; not_engaging &198a a5 76 LDA &76 ; y # y is the vertical distance from guard to player &198c d0 0b BNE &1999 ; not_engaging &198e a5 77 LDA &77 ; x_low # x_low is the horizontal distance from guard to player &1990 d9 e6 09 CMP &09e6,Y ; guard_fighting_offsets # Is the guard close enough to start fighting? &1993 f0 3a BEQ &19cf ; start_fight_with_guard # If so, start fighting &1995 10 70 BPL &1a07 ; move_guard # If not, move guard towards player &1997 30 53 BMI &19ec ; set_guard_retreating # Guard retreats if player is too close; always branches ; not_engaging &1999 a5 76 LDA &76 ; y # y is the vertical distance from guard to player &199b c9 04 CMP #&04 &199d 10 68 BPL &1a07 ; move_guard &199f a5 77 LDA &77 ; x_low # x_low is the horizontal distance from guard to player &19a1 c9 04 CMP #&04 &19a3 10 62 BPL &1a07 ; move_guard ; player_jumped_on_guard &19a5 a5 50 LDA &50 ; guard_aggressiveness # If the guard is very close to the player, &19a7 f0 1c BEQ &19c5 ; attack_guard_when_guard_has_upper_hand &19a9 10 0c BPL &19b7 ; stun_player &19ab 30 00 BMI &19ad ; set_guard_falling_off_screen # Unnecessary code; always branches ; set_guard_falling_off_screen &19ad a9 80 LDA #&80 # Set state to &80 to indicate falling off screen &19af 95 00 STA &00,X ; objects_state &19b1 a2 80 LDX #&80 ; sound_5 # Play sound for falling guard &19b3 20 35 0a JSR &0a35 ; play_sound &19b6 60 RTS ; stun_player &19b7 a9 00 LDA #&00 ; KILLED_UNCONSCIOUS # Not dead really &19b9 85 63 STA &63 ; player_was_killed &19bb a2 60 LDX #&60 ; sound_1 # Play sound for stunned player &19bd 20 35 0a JSR &0a35 ; play_sound &19c0 a6 64 LDX &64 ; object_to_update &19c2 4c 4e 24 JMP &244e ; move_mover # Move guard ; attack_guard_when_guard_has_upper_hand &19c5 a5 6d LDA &6d ; jump_stage # Is the player jumping? &19c7 10 23 BPL &19ec ; set_guard_retreating &19c9 a5 71 LDA &71 ; vertical_direction # Is the guard moving up? &19cb f0 e0 BEQ &19ad ; set_guard_falling_off_screen # If so, player wins; otherwise, guard wins &19cd d0 e8 BNE &19b7 ; stun_player # Always branches ; start_fight_with_guard &19cf 24 61 BIT &61 ; object_player_is_fighting # &40 set if not fighting &19d1 70 06 BVS &19d9 ; not_already_fighting &19d3 a9 00 LDA #&00 # Otherwise, the player is already fighting a guard &19d5 85 12 STA &12 ; player_must_stop_fighting # End that fight, because the player is outnumbered &19d7 f0 de BEQ &19b7 ; stun_player # Always branches ; not_already_fighting &19d9 a5 6d LDA &6d ; jump_stage # Is the player jumping? &19db 10 2a BPL &1a07 ; move_guard &19dd a9 32 LDA #&32 # If not, start fight; fight lasts 50 frames &19df 85 60 STA &60 ; fighting_cooldown &19e1 a9 ff LDA #&ff ; HORIZONTAL_AND_VERTICAL_NONE &19e3 85 62 STA &62 ; player_is_fighting # Set to &ff, negative to indicate player is fighting &19e5 85 71 STA &71 ; vertical_direction &19e7 85 70 STA &70 ; horizontal_direction &19e9 86 61 STX &61 ; object_player_is_fighting # Note which guard the player is fighting &19eb 60 RTS ; set_guard_retreating &19ec a5 70 LDA &70 ; horizontal_direction &19ee 49 02 EOR #&02 # Flip horizontal direction &19f0 85 70 STA &70 ; horizontal_direction &19f2 85 62 STA &62 ; player_is_fighting # Set positive to indicate player isn't fighting &19f4 20 98 21 JSR &2198 ; get_object_variables_for_object_X # X is the guard &19f7 20 8b 1c JSR &1c8b ; consider_slope_and_support # Returns carry set if guard is not supported &19fa 90 17 BCC &1a13 ; end_fight_after_guard_retreats # If the guard is supported, end the fight &19fc a2 2f LDX #&2f ; OBJECT_PLAYER &19fe a5 70 LDA &70 ; horizontal_direction &1a00 29 02 AND #&02 # Ensure a sensible scrolling direction if scrolling &1a02 85 70 STA &70 ; horizontal_direction &1a04 4c e8 16 JMP &16e8 ; keep_player_on_screen ; move_guard &1a07 a5 5d LDA &5d ; prison_escort_state &1a09 c9 ff CMP #&ff ; ESCORT_OUT_OF_PRISON &1a0b f0 03 BEQ &1a10 ; to_move_mover &1a0d 4c 13 19 JMP &1913 ; move_guard_towards_target ; to_move_mover &1a10 4c 4e 24 JMP &244e ; move_mover ; end_fight_after_guard_retreats &1a13 a9 ff LDA #&ff # Set &80 to keep sprite for a frame &1a15 85 61 STA &61 ; object_player_is_fighting # and &40 to indicate player isn't fighting guard &1a17 60 RTS ; animate_guard &1a18 a6 64 LDX &64 ; object_to_update &1a1a e4 61 CPX &61 ; object_player_is_fighting # Is this the guard that the player is fighting? &1a1c d0 25 BNE &1a43 ; not_fighting_guard &1a1e 20 55 1a JSR &1a55 ; update_crossed_swords # If so, animate swords &1a21 a9 ff LDA #&ff ; VERTICAL_NONE &1a23 85 71 STA &71 ; vertical_direction # Stop guard moving vertically when fighting &1a25 a6 64 LDX &64 ; object_to_update &1a27 bd 18 0d LDA &0d18,X ; objects_moving - &18 &1a2a 49 01 EOR #&01 # Animate fighting guard's body &1a2c 9d 18 0d STA &0d18,X ; objects_moving - &18 &1a2f 18 CLC &1a30 69 06 ADC #&06 ; SPRITE_GUARD &1a32 85 7f STA &7f ; object_sprite &1a34 20 cc 2c JSR &2ccc ; add_active_mover &1a37 ad 47 0d LDA &0d47 ; objects_moving - &18 + OBJECT_PLAYER &1a3a 49 01 EOR #&01 # Animate fighting player's body &1a3c 8d 47 0d STA &0d47 ; objects_moving - &18 + OBJECT_PLAYER &1a3f 20 e8 16 JSR &16e8 ; keep_player_on_screen &1a42 60 RTS ; not_fighting_guard &1a43 a5 61 LDA &61 ; object_player_is_fighting # If &80 set, use existing sprite &1a45 30 03 BMI &1a4a ; skip_calculating_sprite &1a47 20 0b 17 JSR &170b ; calculate_sprite_from_direction # Otherwise, change direction ; skip_calculating_sprite &1a4a bd 18 0d LDA &0d18,X ; objects_moving - &18 &1a4d 18 CLC &1a4e 69 06 ADC #&06 ; SPRITE_GUARD &1a50 85 7f STA &7f ; object_sprite &1a52 4c cc 2c JMP &2ccc ; add_active_mover ; update_crossed_swords &1a55 bd 18 0d LDA &0d18,X ; objects_moving - &18 # Use direction of guard &1a58 29 02 AND #&02 &1a5a a8 TAY &1a5b bd a0 0b LDA &0ba0,X ; objects_x_low &1a5e 18 CLC &1a5f 79 e2 09 ADC &09e2,Y ; crossed_swords_offsets # to set position of swords relative to guard &1a62 8d af 0b STA &0baf ; objects_x_low + OBJECT_CROSSED_SWORDS &1a65 bd e8 0b LDA &0be8,X ; objects_x_high &1a68 79 e3 09 ADC &09e3,Y ; crossed_swords_offsets + 1 &1a6b 8d f7 0b STA &0bf7 ; objects_x_high + OBJECT_CROSSED_SWORDS &1a6e bd 30 0c LDA &0c30,X ; objects_y &1a71 8d 3f 0c STA &0c3f ; objects_y + OBJECT_CROSSED_SWORDS &1a74 ee 3f 0c INC &0c3f ; objects_y + OBJECT_CROSSED_SWORDS &1a77 a5 60 LDA &60 ; fighting_cooldown &1a79 29 07 AND #&07 &1a7b d0 05 BNE &1a82 ; skip_sound &1a7d a2 a0 LDX #&a0 ; sound_9 # Play sound for sword fighting every eight frames &1a7f 20 35 0a JSR &0a35 ; play_sound ; skip_sound &1a82 a5 60 LDA &60 ; fighting_cooldown &1a84 29 04 AND #&04 # Animate swords every four frames &1a86 f0 04 BEQ &1a8c ; use_uncrossed_swords &1a88 a9 ba LDA #&ba ; crossed_swords_crossed_chunks MOD 256 &1a8a d0 02 BNE &1a8e ; set_swords ; use_uncrossed_swords &1a8c a9 b2 LDA #&b2 ; crossed_swords_uncrossed_chunks MOD 256 ; set_swords &1a8e 8d 57 0d STA &0d57 ; objects_chunk_address_low_table + OBJECT_CROSSED_SWORDS &1a91 a2 0f LDX #&0f ; OBJECT_CROSSED_SWORDS &1a93 a9 ff LDA #&ff ; VERTICAL_NONE &1a95 85 71 STA &71 ; vertical_direction &1a97 4c cc 2c JMP &2ccc ; add_active_mover ; update_guard &1a9a 86 64 STX &64 ; object_to_update &1a9c b5 00 LDA &00,X ; objects_state # Positive if guard is alive &1a9e 10 06 BPL &1aa6 ; is_active ; is_falling_or_absent &1aa0 20 5d 25 JSR &255d ; update_dead_or_dying_mover # Returns zero if guard is on screen &1aa3 f0 1d BEQ &1ac2 ; update_guard_animation &1aa5 60 RTS ; is_active &1aa6 e4 61 CPX &61 ; object_player_is_fighting # Is the player fighting the guard? &1aa8 d0 06 BNE &1ab0 ; not_fighting &1aaa 20 99 18 JSR &1899 ; update_fighting_guard &1aad 4c c2 1a JMP &1ac2 ; update_guard_animation ; not_fighting &1ab0 20 34 19 JSR &1934 ; update_not_fighting_guard &1ab3 a5 3e LDA &3e ; prison_bed_is_on_fire # Zero if prison bed is on fire &1ab5 f0 0b BEQ &1ac2 ; update_guard_animation # Guard is animated more frequently if bed is on fire &1ab7 a5 13 LDA &13 ; animate_guard_less_frequently &1ab9 f0 07 BEQ &1ac2 ; update_guard_animation &1abb 46 13 LSR &13 ; animate_guard_less_frequently # Set to zero to clear less frequent animation &1abd 20 c0 00 JSR &00c0 ; check_if_mover_should_be_updated # Returns non-zero if object shouldn't be updated now &1ac0 d0 0b BNE &1acd ; leave ; update_guard_animation &1ac2 20 18 1a JSR &1a18 ; animate_guard &1ac5 a5 61 LDA &61 ; object_player_is_fighting # &80 set if keeping previous sprite &1ac7 10 04 BPL &1acd ; leave &1ac9 a9 40 LDA #&40 # Clear &80 to allow sprite to change in future &1acb 85 61 STA &61 ; object_player_is_fighting # Set &40 to indicate player isn't fighting ; leave &1acd 60 RTS ; update_jumping_or_falling_player &1ace a5 6c LDA &6c ; distance_fallen &1ad0 10 05 BPL &1ad7 ; is_falling &1ad2 a5 6d LDA &6d ; jump_stage &1ad4 10 32 BPL &1b08 ; update_jump &1ad6 60 RTS ; is_falling &1ad7 20 24 17 JSR &1724 ; check_if_player_is_standing_on_stool # Leaves update_jumping_or_falling_player if on stool &1ada 20 b3 25 JSR &25b3 ; check_if_object_X_is_supported # Returns carry set if player is supported &1add 90 18 BCC &1af7 ; still_falling &1adf a5 6c LDA &6c ; distance_fallen &1ae1 c9 10 CMP #&10 &1ae3 90 04 BCC &1ae9 ; not_fallen_too_far &1ae5 a9 02 LDA #&02 ; KILLED_BY_FALLING # Kill player if player falls too far &1ae7 85 63 STA &63 ; player_was_killed ; not_fallen_too_far &1ae9 a9 ff LDA #&ff &1aeb 85 6c STA &6c ; distance_fallen &1aed 85 53 STA &53 ; player_is_jumping_or_falling # Set to negative to indicate player is supported &1aef a2 68 LDX #&68 ; sound_2 # Silence channel 2 &1af1 20 35 0a JSR &0a35 ; play_sound &1af4 4c 92 17 JMP &1792 ; check_for_scrolling ; still_falling &1af7 20 eb 1c JSR &1ceb ; check_for_clinging # Returns carry set if clinging to ladder &1afa 90 03 BCC &1aff ; not_clinging &1afc 4c 75 18 JMP &1875 ; finish_player_movement ; not_clinging &1aff e6 6c INC &6c ; distance_fallen &1b01 a9 01 LDA #&01 ; VERTICAL_DOWN # Player continues to fall if not clinging to ladder &1b03 85 71 STA &71 ; vertical_direction ; to_finish_player_movement &1b05 4c 75 18 JMP &1875 ; finish_player_movement ; update_jump &1b08 ad 5f 0c LDA &0c5f ; objects_y + OBJECT_PLAYER &1b0b c9 1c CMP #&1c &1b0d 10 29 BPL &1b38 ; hit_obstacle # Can't jump above top of screen &1b0f a5 6f LDA &6f ; jump_direction &1b11 85 70 STA &70 ; horizontal_direction &1b13 a5 6d LDA &6d ; jump_stage &1b15 a0 00 LDY #&00 ; VERTICAL_UP # Move up in stages 0 to 2 &1b17 c9 03 CMP #&03 &1b19 30 0b BMI &1b26 ; set_vertical_direction &1b1b a0 ff LDY #&ff ; VERTICAL_NONE # Maintain vertical position in stages 3 and 4 &1b1d c9 05 CMP #&05 &1b1f 30 05 BMI &1b26 ; set_vertical_direction &1b21 20 24 17 JSR &1724 ; check_if_player_is_standing_on_stool &1b24 a0 01 LDY #&01 ; VERTICAL_DOWN # Otherwise move down ; set_vertical_direction &1b26 84 71 STY &71 ; vertical_direction &1b28 20 a5 16 JSR &16a5 ; check_if_carried_object_stops_movement # Returns carry set if carried object hits an obstacle &1b2b b0 0b BCS &1b38 ; hit_obstacle &1b2d 20 98 21 JSR &2198 ; get_object_variables_for_object_X &1b30 20 50 1c JSR &1c50 ; calculate_object_edges &1b33 20 5e 1b JSR &1b5e ; check_object_for_support_or_obstacle &1b36 90 12 BCC &1b4a ; no_obstacle ; hit_obstacle &1b38 a5 6d LDA &6d ; jump_stage &1b3a 38 SEC &1b3b e9 04 SBC #&04 # Keep some momentum from bouncing off obstacle &1b3d 10 02 BPL &1b41 ; skip_floor &1b3f a9 00 LDA #&00 ; skip_floor &1b41 85 6c STA &6c ; distance_fallen &1b43 a9 ff LDA #&ff &1b45 85 6d STA &6d ; jump_stage # Set to negative to indicate player isn't jumping &1b47 4c d7 1a JMP &1ad7 ; is_falling ; no_obstacle &1b4a 20 eb 1c JSR &1ceb ; check_for_clinging # Returns carry set if clinging to ladder &1b4d 90 03 BCC &1b52 ; not_clinging &1b4f 4c 75 18 JMP &1875 ; finish_player_movement ; not_clinging &1b52 e6 6d INC &6d ; jump_stage &1b54 a5 6f LDA &6f ; jump_direction &1b56 30 ad BMI &1b05 ; to_finish_player_movement # Is the player jumping straight up? &1b58 20 0b 17 JSR &170b ; calculate_sprite_from_direction &1b5b 4c 6d 18 JMP &186d ; set_facing_and_scrolling_from_direction # If not, set facing and scrolling from direction ; check_object_for_support_or_obstacle &1b5e a5 70 LDA &70 ; horizontal_direction &1b60 10 02 BPL &1b64 ; is_moving_horizontally &1b62 a9 00 LDA #&00 ; HORIZONTAL_LEFT # If not moving horizontally, treat as moving left &1b64 85 6e STA &6e ; object_direction_for_slopes ; is_moving_horizontally &1b66 a5 71 LDA &71 ; vertical_direction &1b68 f0 38 BEQ &1ba2 ; is_moving_up &1b6a 30 02 BMI &1b6e ; not_moving_vertically ; is_moving_down # If the object is moving down or not moving vertically, &1b6c c6 76 DEC &76 ; y ; not_moving_vertically &1b6e a9 01 LDA #&01 # Set to non-zero to indicate leading edge of object &1b70 85 72 STA &72 ; object_edge_being_checked &1b72 20 c4 1b JSR &1bc4 ; check_point_for_obstacle_or_support # Returns carry set if point is in wall &1b75 b0 4c BCS &1bc3 ; leave # Leave with carry set if object blocked at bottom &1b77 a5 70 LDA &70 ; horizontal_direction # Is the object moving horizontally? &1b79 30 0c BMI &1b87 ; skip_top_check &1b7b a5 76 LDA &76 ; y # If so, check the top of the object &1b7d 18 CLC &1b7e 65 73 ADC &73 ; object_height &1b80 85 76 STA &76 ; y &1b82 20 3f 1c JSR &1c3f ; check_if_tile_is_wall_or_offscreen # Returns carry set if in wall or off screen &1b85 b0 3c BCS &1bc3 ; leave # Leave with carry set if object blocked at top ; skip_top_check &1b87 a5 71 LDA &71 ; vertical_direction # Is the object moving vertically? &1b89 30 38 BMI &1bc3 ; leave # Leave with carry clear if not &1b8b a5 79 LDA &79 ; x_trailing_low &1b8d 85 77 STA &77 ; x_low &1b8f a5 7a LDA &7a ; x_trailing_high &1b91 85 78 STA &78 ; x_high &1b93 bd 30 0c LDA &0c30,X ; objects_y &1b96 85 76 STA &76 ; y # Consider trailing edge , one subtile below bottom &1b98 c6 76 DEC &76 ; y &1b9a c6 72 DEC &72 ; object_edge_being_checked # Set to zero to indicate trailing edge of object &1b9c 20 c4 1b JSR &1bc4 ; check_point_for_obstacle_or_support # Returns carry set if point is in wall &1b9f b0 22 BCS &1bc3 ; leave &1ba1 60 RTS ; is_moving_up # If the object is moving up. &1ba2 e6 76 INC &76 ; y # Check bottom left subtile &1ba4 20 3f 1c JSR &1c3f ; check_if_tile_is_wall_or_offscreen # Returns carry set if tile is a wall &1ba7 b0 1a BCS &1bc3 ; leave # Leave with carry set if tile is a wall &1ba9 a5 76 LDA &76 ; y &1bab 18 CLC &1bac 65 73 ADC &73 ; object_height # Check top leading subtile &1bae 85 76 STA &76 ; y &1bb0 20 3f 1c JSR &1c3f ; check_if_tile_is_wall_or_offscreen # Returns carry set if tile is a wall &1bb3 b0 0e BCS &1bc3 ; leave # Leave with carry set if tile is a wall &1bb5 a5 79 LDA &79 ; x_trailing_low &1bb7 85 77 STA &77 ; x_low # Check top trailing subtile &1bb9 a5 7a LDA &7a ; x_trailing_high &1bbb 85 78 STA &78 ; x_high &1bbd 20 3f 1c JSR &1c3f ; check_if_tile_is_wall_or_offscreen # Returns carry set if tile is a wall &1bc0 b0 01 BCS &1bc3 ; leave # Leave with carry set if tile is a wall &1bc2 18 CLC # Otherwise leave with carry clear, object not blocked ; leave &1bc3 60 RTS ; check_point_for_obstacle_or_support &1bc4 a5 76 LDA &76 ; y &1bc6 30 75 BMI &1c3d ; leave_with_carry_set # Leave with carry set if y is below bottom of screen &1bc8 20 69 07 JSR &0769 ; get_map_tile &1bcb a8 TAY &1bcc b9 45 0a LDA &0a45,Y ; tiles_support_type &1bcf 30 66 BMI &1c37 ; leave_with_carry_clear # &80 set if no obstacle or support anywhere in tile &1bd1 c0 01 CPY #&01 ; TILE_WALL &1bd3 f0 68 BEQ &1c3d ; leave_with_carry_set # TILE_WALL is always an obstacle, always supports &1bd5 c9 40 CMP #&40 # &40 set if tile is a platform that can support &1bd7 d0 1d BNE &1bf6 ; is_slope # Otherwise, the tile is a slope ; is_platform # TILE_PLATFORM_LADDER, TILE_PLATFORM or TILE_PASSAGE &1bd9 a5 5e LDA &5e ; suppress_top_support_check # Positive if checking for obstacle, not support &1bdb 10 5a BPL &1c37 ; leave_with_carry_clear &1bdd a5 76 LDA &76 ; y # Is this a check for support? IF so, &1bdf 29 03 AND #&03 &1be1 c9 03 CMP #&03 # Is this the top row of the tile? &1be3 f0 58 BEQ &1c3d ; leave_with_carry_set # If so, it provides support &1be5 a4 71 LDY &71 ; vertical_direction &1be7 f0 04 BEQ &1bed ; not_moving_straight_down &1be9 a4 70 LDY &70 ; horizontal_direction &1beb 30 4a BMI &1c37 ; leave_with_carry_clear ; not_moving_straight_down # If the object isn't moving straight down, &1bed 18 CLC &1bee 65 73 ADC &73 ; object_height &1bf0 c9 04 CMP #&04 # Is the top of the object in a different tile? &1bf2 10 49 BPL &1c3d ; leave_with_carry_set # If so, block the object &1bf4 30 41 BMI &1c37 ; leave_with_carry_clear # Always branches ; is_slope &1bf6 48 PHA ; slope_direction # &00 if slope up to left, &02 if slope up to right &1bf7 a5 76 LDA &76 ; y &1bf9 29 fc AND #&fc &1bfb 85 7c STA &7c ; bottom_of_tile_y &1bfd 68 PLA ; slope_direction &1bfe c5 6e CMP &6e ; object_direction_for_slopes # Is the object moving towards an upward slope? &1c00 f0 06 BEQ &1c08 ; upward_slope ; is_downward_slope &1c02 a4 72 LDY &72 ; object_edge_being_checked # Non-zero if checking leading edge of object &1c04 d0 31 BNE &1c37 ; leave_with_carry_clear # Don't check leading edge on downward slope &1c06 f0 04 BEQ &1c0c ; check_slope # Always branches ; is_upward_slope &1c08 a4 72 LDY &72 ; object_edge_being_checked # Zero if checking trailing edge of object &1c0a f0 2b BEQ &1c37 ; leave_with_carry_clear # Don't check trailing edge on upwards slope ; check_slope &1c0c 48 PHA &1c0d a5 77 LDA &77 ; x_low &1c0f 29 07 AND #&07 &1c11 a8 TAY &1c12 c8 INY &1c13 98 TYA &1c14 4a LSR A &1c15 a8 TAY # Y = ((x_low % 7) + 1) / 2 &1c16 68 PLA ; slope direction &1c17 f0 05 BEQ &1c1e ; slopes_up_to_left ; slopes_up_to_right &1c19 b9 1a 0d LDA &0d1a,Y ; right_slope_offsets &1c1c 10 03 BPL &1c21 ; use_slope # Always branches ; slopes_up_to_left &1c1e b9 1f 0d LDA &0d1f,Y ; left_slope_offsets ; use_slope &1c21 18 CLC &1c22 65 7c ADC &7c ; bottom_of_tile_y &1c24 dd 30 0c CMP &0c30,X ; objects_y &1c27 30 08 BMI &1c31 ; above_slope &1c29 d0 0e BNE &1c39 ; below_slope &1c2b a9 ff LDA #&ff # Set &80 and &40 to indicate on slope &1c2d 85 50 STA &50 ; slope_flags &1c2f 38 SEC &1c30 60 RTS ; above_slope &1c31 a9 40 LDA #&40 # Clear &80 to indicate above slope &1c33 85 50 STA &50 ; slope_flags # (non-zero to indicate on slope) &1c35 18 CLC # Leave with carry clear to indicate no obstacle &1c36 60 RTS ; leave_with_carry_clear &1c37 18 CLC # Leave with carry clear to indicate no obstacle &1c38 60 RTS ; below_slope &1c39 a9 80 LDA #&80 # Clear &40 to indicate below slope &1c3b 85 50 STA &50 ; slope_flags # (non-zero to indicate on slope) ; leave_with_carry_set &1c3d 38 SEC # Leave with carry set to indicate obstacle &1c3e 60 RTS ; check_if_tile_is_wall_or_offscreen &1c3f a5 76 LDA &76 ; y &1c41 c9 1c CMP #&1c &1c43 10 09 BPL &1c4e ; leave_with_carry_set # Leave with carry set if off top or bottom of screen &1c45 20 69 07 JSR &0769 ; get_map_tile &1c48 c9 01 CMP #&01 ; TILE_WALL # Leave with carry set if tile is complete wall &1c4a f0 02 BEQ &1c4e ; leave_with_carry_set:w &1c4c 18 CLC # Otherwise, leave with carry clear &1c4d 60 RTS ; leave_with_carry_set &1c4e 38 SEC &1c4f 60 RTS ; calculate_object_edges &1c50 c6 73 DEC &73 ; object_height &1c52 c6 74 DEC &74 ; object_width &1c54 a5 70 LDA &70 ; horizontal_direction &1c56 30 0a BMI &1c62 ; ; not_moving_horizontally &1c58 d0 16 BNE &1c70 ; is_moving_left ; is_moving_left &1c5a a5 77 LDA &77 ; x_low &1c5c d0 02 BNE &1c60 ; skip_underflow &1c5e c6 78 DEC &78 ; x_high ; skip_underflow &1c60 c6 77 DEC &77 ; x_low ; not_moving_horizontally &1c62 a5 77 LDA &77 ; x_low &1c64 18 CLC &1c65 65 74 ADC &74 ; object_width &1c67 85 79 STA &79 ; x_trailing_low &1c69 a5 78 LDA &78 ; x_high &1c6b 69 00 ADC #&00 &1c6d 85 7a STA &7a ; x_trailing_high &1c6f 60 RTS ; is_moving_right &1c70 a5 77 LDA &77 ; x_low &1c72 18 CLC &1c73 69 01 ADC #&01 &1c75 85 79 STA &79 ; x_trailing_low &1c77 a5 78 LDA &78 ; x_high &1c79 69 00 ADC #&00 &1c7b 85 7a STA &7a ; x_trailing_high &1c7d a5 79 LDA &79 ; x_trailing_low &1c7f 18 CLC &1c80 65 74 ADC &74 ; object_width &1c82 85 77 STA &77 ; x_low &1c84 a5 7a LDA &7a ; x_trailing_high &1c86 69 00 ADC #&00 &1c88 85 78 STA &78 ; x_high &1c8a 60 RTS ; consider_slope_and_support &1c8b a5 70 LDA &70 ; horizontal_direction &1c8d 30 38 BMI &1cc7 ; clear_horizontal_and_vertical_movement &1c8f 85 6e STA &6e ; object_direction_for_slopes &1c91 20 50 1c JSR &1c50 ; calculate_object_edges # Returns leading edge in x, trailing edge in x_trailing &1c94 a9 01 LDA #&01 # Set to non-zero to indicate leading edge of object &1c96 85 72 STA &72 ; object_edge_being_checked &1c98 a9 00 LDA #&00 # Set to zero to indicate not on slope by default &1c9a 85 50 STA &50 ; slope_flags &1c9c a9 ff LDA #&ff ; HORIZONTAL_NONE # Not moving sideways by default &1c9e 85 6b STA &6b ; unsupported_horizontal_direction &1ca0 20 c4 1b JSR &1bc4 ; check_point_for_obstacle_or_support # Returns carry set if point is in wall &1ca3 a5 50 LDA &50 ; slope_flags # Non-zero if tile is a sloping wall &1ca5 d0 32 BNE &1cd9 ; follow_slope_vertically &1ca7 b0 1e BCS &1cc7 ; clear_horizontal_and_vertical_movement &1ca9 c6 76 DEC &76 ; y &1cab 20 c4 1b JSR &1bc4 ; check_point_for_obstacle_or_support # Returns carry set if point is in wall &1cae b0 23 BCS &1cd3 ; clear_vertical_movement &1cb0 a5 79 LDA &79 ; x_trailing_low # Use trailing edge &1cb2 85 77 STA &77 ; x_low &1cb4 a5 7a LDA &7a ; x_trailing_high &1cb6 85 78 STA &78 ; x_high &1cb8 c6 72 DEC &72 ; object_edge_being_checked # Set to zero to indicate trailing edge of object &1cba 20 c4 1b JSR &1bc4 ; check_point_for_obstacle_or_support # Returns carry set if point is in wall &1cbd a5 50 LDA &50 ; slope_flags # Non-zero if tile is a sloping wall &1cbf d0 18 BNE &1cd9 ; follow_slope_vertically # If so, follow the slope &1cc1 b0 10 BCS &1cd3 ; clear_vertical_movement &1cc3 a5 70 LDA &70 ; horizontal_direction &1cc5 85 6b STA &6b ; unsupported_horizontal_direction # Set player moving sideways on ladder or off platform ; clear_horizontal_and_vertical_movement &1cc7 a9 ff LDA #&ff ; HORIZONTAL_AND_VERTICAL_NONE &1cc9 85 70 STA &70 ; horizontal_direction &1ccb 85 71 STA &71 ; vertical_direction &1ccd 38 SEC # Leave with carry set to indicate not supported &1cce 60 RTS ; set_vertical_direction &1ccf 85 71 STA &71 ; vertical_direction &1cd1 18 CLC # Leave with carry clear to indicate supported &1cd2 60 RTS ; clear_vertical_movement &1cd3 a9 ff LDA #&ff ; VERTICAL_NONE &1cd5 85 71 STA &71 ; vertical_direction &1cd7 18 CLC # Leave with carry clear to indicate supported &1cd8 60 RTS ; follow_slope_vertically &1cd9 24 50 BIT &50 ; slope_flags # &80 clear if above slope, &40 clear if below slope &1cdb 10 0a BPL &1ce7 ; move_down_to_slope &1cdd 70 04 BVS &1ce3 ; stay_on_slope ; move_up_to_slope &1cdf a9 00 LDA #&00 ; VERTICAL_UP &1ce1 10 ec BPL &1ccf ; set_vertical_direction ; stay_on_slope &1ce3 a9 ff LDA #&ff ; VERTICAL_NONE &1ce5 30 e8 BMI &1ccf ; set_vertical_direction ; move_down_to_slope &1ce7 a9 01 LDA #&01 ; VERTICAL_DOWN &1ce9 10 e4 BPL &1ccf ; set_vertical_direction # Always branches ; check_for_clinging &1ceb a5 ec LDA &ec ; os_most_recently_pressed_key &1ced c9 c8 CMP #&c8 ; * # Does the player want to cling to a ladder? &1cef d0 25 BNE &1d16 ; leave_with_carry_clear &1cf1 a5 8b LDA &8b ; tile_type &1cf3 c9 04 CMP #&04 ; TILE_LADDER &1cf5 d0 1f BNE &1d16 ; leave_with_carry_clear # Is there a ladder to cling to? &1cf7 bd a0 0b LDA &0ba0,X ; objects_x_low &1cfa 29 07 AND #&07 &1cfc c9 05 CMP #&05 &1cfe 10 16 BPL &1d16 ; leave_with_carry_clear &1d00 a9 ff LDA #&ff &1d02 85 9e STA &9e ; player_facing # Set to &ff to indicate player facing vertically &1d04 85 6d STA &6d ; jump_stage &1d06 85 6c STA &6c ; distance_fallen &1d08 85 53 STA &53 ; player_is_jumping_or_falling # Set to negative to indicate player is supported &1d0a a9 05 LDA #&05 # Set player sprite to up &1d0c 8d 47 0d STA &0d47 ; objects_moving - &18 + OBJECT_PLAYER &1d0f a2 68 LDX #&68 ; sound_2 # Silence channel 2 &1d11 20 35 0a JSR &0a35 ; play_sound &1d14 38 SEC # Leave with carry set to indicate clinging to ladder &1d15 60 RTS ; leave_with_carry_clear &1d16 18 CLC # Leave with carry clear to indicate not clinging &1d17 60 RTS ; check_for_throwing_or_dropping &1d18 a5 54 LDA &54 ; object_being_dropped_or_thrown &1d1a 10 51 BPL &1d6d ; leave # Leave if an object is already in motion &1d1c a5 ec LDA &ec ; os_most_recently_pressed_key &1d1e 20 61 1d JSR &1d61 ; check_for_throw_and_drop &1d21 f0 08 BEQ &1d2b ; throw_or_drop_object &1d23 a5 ed LDA &ed ; os_first_pressed_key &1d25 20 61 1d JSR &1d61 ; check_for_throw_and_drop &1d28 f0 01 BEQ &1d2b ; throw_or_drop_object &1d2a 60 RTS ; throw_or_drop_object &1d2b a4 9c LDY &9c ; carrying # Negative if player isn't carrying anything &1d2d 30 3e BMI &1d6d ; leave &1d2f 84 54 STY &54 ; object_being_dropped_or_thrown &1d31 a9 00 LDA #&00 &1d33 85 56 STA &56 ; throw_or_drop_timer &1d35 a9 0e LDA #&0e ; OBJECT_STATE_THROWN &1d37 99 00 00 STA &0000,Y ; objects_state # Mark the object as being thrown &1d3a c0 0b CPY #&0b ; OBJECT_BUCKET &1d3c d0 19 BNE &1d57 ; not_throwing_water &1d3e e0 04 CPX #&04 ; THROWING_DROP &1d40 f0 15 BEQ &1d57 ; not_throwing_water &1d42 a5 35 LDA &35 ; bucket_contains_water # Non-zero if bucket contains water &1d44 f0 11 BEQ &1d57 ; not_throwing_water &1d46 a9 00 LDA #&00 &1d48 85 35 STA &35 ; bucket_contains_water # Set to zero to indicate bucket is now empty &1d4a a0 0c LDY #&0c ; OBJECT_WATER &1d4c 84 54 STY &54 ; object_being_dropped_or_thrown &1d4e a2 2f LDX #&2f ; OBJECT_PLAYER &1d50 a5 9e LDA &9e ; player_facing &1d52 85 0c STA &0c ; objects_state + OBJECT_WATER &1d54 4c dc 2e JMP &2edc ; offset_object_Y_from_object_X ; not_throwing_water &1d57 a2 98 LDX #&98 ; sound_8 # Play sound for throwing object &1d59 20 35 0a JSR &0a35 ; play_sound &1d5c a9 ff LDA #&ff # Set to negative to indicate player not carrying object &1d5e 85 9c STA &9c ; carrying &1d60 60 RTS ; check_for_throw_and_drop &1d61 a2 05 LDX #&05 ; check_for_throw_and_drop_loop &1d63 ca DEX &1d64 30 07 BMI &1d6d ; leave &1d66 dd d4 09 CMP &09d4,X ; throw_and_drop_key_codes &1d69 d0 f8 BNE &1d63 ; check_for_throw_and_drop_loop &1d6b 86 55 STX &55 ; throw_direction ; leave &1d6d 60 RTS ; update_thrown_object &1d6e a4 54 LDY &54 ; object_being_dropped_or_thrown # Is an object being thrown? &1d70 30 45 BMI &1db7 ; leave &1d72 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &1d75 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns zero if object is fully off screen &1d78 f0 08 BEQ &1d82 ; skip_unplot &1d7a 20 9d 22 JSR &229d ; unplot_object # Unplot thrown object &1d7d a4 54 LDY &54 ; object_being_dropped_or_thrown &1d7f 20 9a 21 JSR &219a ; get_object_variables_for_object_Y ; skip_unplot &1d82 a6 54 LDX &54 ; object_being_dropped_or_thrown &1d84 a9 ff LDA #&ff ; HORIZONTAL_AND_VERTICAL_NONE # Thrown object doesn't move by default &1d86 85 70 STA &70 ; horizontal_direction &1d88 85 71 STA &71 ; vertical_direction &1d8a a5 55 LDA &55 ; throw_direction &1d8c d0 2a BNE &1db8 ; not_left ; throwing_left &1d8e 85 70 STA &70 ; horizontal_direction # Set thrown object moving left &1d90 a5 77 LDA &77 ; x_low &1d92 d0 02 BNE &1d96 ; skip_underflow &1d94 c6 78 DEC &78 ; x_high ; skip_underflow &1d96 c6 77 DEC &77 ; x_low # Move left one subtile ; going_left_or_right &1d98 a5 56 LDA &56 ; throw_or_drop_timer &1d9a d0 03 BNE &1d9f ; skip_climb &1d9c fe 30 0c INC &0c30,X ; objects_y # Object thrown left or right rises in first frame ; skip_climb &1d9f 20 50 1c JSR &1c50 ; calculate_object_edges &1da2 a5 56 LDA &56 ; throw_or_drop_timer &1da4 29 07 AND #&07 &1da6 c9 07 CMP #&07 &1da8 d0 04 BNE &1dae ; skip_fall &1daa a9 01 LDA #&01 ; VERTICAL_DOWN # When throwing left or right, fall every eight frames &1dac 85 71 STA &71 ; vertical_direction ; skip_fall &1dae 20 5e 1b JSR &1b5e ; check_object_for_support_or_obstacle # Returns carry set if object hit obstacle &1db1 90 78 BCC &1e2b ; going_up_or_down &1db3 a9 04 LDA #&04 ; THROWING_DROP # Thrown object falls down when it hits an obstacle &1db5 85 55 STA &55 ; throw_direction ; leave &1db7 60 RTS ; not_left &1db8 c9 01 CMP #&01 ; THROWING_RIGHT &1dba d0 0c BNE &1dc8 ; not_right ; throwing_right &1dbc e6 77 INC &77 ; x_low # Move right one subtile &1dbe d0 02 BNE &1dc2 ; skip_overflow &1dc0 e6 78 INC &78 ; x_high ; skip_overflow &1dc2 a9 02 LDA #&02 ; HORIZONTAL_RIGHT # Set thrown object moving right &1dc4 85 70 STA &70 ; horizontal_direction &1dc6 10 d0 BPL &1d98 ; going_left_or_right # Always branches ; not_right &1dc8 c9 02 CMP #&02 ; THROWING_UP &1dca d0 1f BNE &1deb ; not_up ; throwing_up &1dcc a5 56 LDA &56 ; throw_or_drop_timer &1dce c9 08 CMP #&08 &1dd0 30 05 BMI &1dd7 ; before_top ; coming_down &1dd2 a9 04 LDA #&04 ; THROWING_DROP &1dd4 85 55 STA &55 ; throw_direction &1dd6 60 RTS ; before_top &1dd7 a5 76 LDA &76 ; y &1dd9 c9 1b CMP #&1b # Thrown object bounces down off top of screen &1ddb 10 f5 BPL &1dd2 ; coming_down &1ddd a9 00 LDA #&00 ; VERTICAL_UP # Set thrown object moving up &1ddf 85 71 STA &71 ; vertical_direction &1de1 20 50 1c JSR &1c50 ; calculate_object_edges &1de4 20 5e 1b JSR &1b5e ; check_object_for_support_or_obstacle &1de7 b0 e9 BCS &1dd2 ; coming_down &1de9 90 40 BCC &1e2b ; going_up_or_down # Always branches ; not_up &1deb c9 03 CMP #&03 ; THROWING_DOWN &1ded d0 30 BNE &1e1f ; is_dropping ; throwing_down &1def a5 56 LDA &56 ; throw_or_drop_timer &1df1 c9 04 CMP #&04 &1df3 30 05 BMI &1dfa ; going_down &1df5 a9 04 LDA #&04 ; THROWING_DROP &1df7 85 55 STA &55 ; throw_direction &1df9 60 RTS ; going_down &1dfa a9 01 LDA #&01 ; VERTICAL_DOWN &1dfc 85 71 STA &71 ; vertical_direction &1dfe 20 50 1c JSR &1c50 ; calculate_object_edges &1e01 c6 76 DEC &76 ; y &1e03 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object has hit obstacle &1e06 90 23 BCC &1e2b ; going_up_or_down ; stop_throw &1e08 a2 88 LDX #&88 ; sound_6 # Silence channel 3 &1e0a 20 35 0a JSR &0a35 ; play_sound &1e0d a4 54 LDY &54 ; object_being_dropped_or_thrown &1e0f a9 ff LDA #&ff # Set to negative to indicate no object being thrown &1e11 85 54 STA &54 ; object_being_dropped_or_thrown &1e13 a9 04 LDA #&04 ; OBJECT_STATE_IN_WORLD &1e15 99 00 00 STA &0000,Y ; objects_state &1e18 c0 0c CPY #&0c ; OBJECT_WATER &1e1a d0 3a BNE &1e56 ; leave &1e1c 4c 2e 2e JMP &2e2e ; unplot_object_if_on_screen # Unplot thrown water when it hits an obstacle ; is_dropping &1e1f a9 01 LDA #&01 ; VERTICAL_DOWN &1e21 85 71 STA &71 ; vertical_direction &1e23 20 50 1c JSR &1c50 ; calculate_object_edges &1e26 20 5e 1b JSR &1b5e ; check_object_for_support_or_obstacle # Returns carry set if object has hit obstacle &1e29 b0 dd BCS &1e08 ; stop_throw ; going_up_or_down &1e2b e6 56 INC &56 ; throw_or_drop_timer &1e2d 20 00 01 JSR &0100 ; move_object_left_or_right &1e30 20 00 01 JSR &0100 ; move_object_left_or_right &1e33 a5 71 LDA &71 ; vertical_direction &1e35 30 0a BMI &1e41 ; skip_vertical_movement &1e37 f0 05 BEQ &1e3e ; going_up ; going_down &1e39 de 30 0c DEC &0c30,X ; objects_y # Move down a subtile &1e3c 10 03 BPL &1e41 ; skip_vertical_movement ; going_up &1e3e fe 30 0c INC &0c30,X ; objects_y # Move up a subtile ; skip_vertical_movement &1e41 20 98 21 JSR &2198 ; get_object_variables_for_object_X &1e44 20 75 20 JSR &2075 ; check_for_object_changing_level # Returns carry set if object changing level &1e47 b0 0e BCS &1e57 ; to_change_object_level &1e49 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns negative if object is fully on screen &1e4c 10 08 BPL &1e56 ; leave &1e4e bd 48 0d LDA &0d48,X ; objects_chunk_address_low_table # Use object sprit &1e51 85 7f STA &7f ; chunk_address_low &1e53 20 c0 21 JSR &21c0 ; plot_object # Plot thrown object ; leave &1e56 60 RTS ; to_change_object_level &1e57 4c 3d 20 JMP &203d ; change_object_level ; check_for_information &1e5a a5 ec LDA &ec ; os_most_recently_pressed_key &1e5c c9 a5 CMP #&a5 ; I # Does the player want information? &1e5e f0 01 BEQ &1e61 ; i_pressed &1e60 60 RTS ; i_pressed &1e61 a2 88 LDX #&88 ; sound_6 # Silence channel 3 &1e63 20 35 0a JSR &0a35 ; play_sound &1e66 a2 68 LDX #&68 ; sound_2 # Silence channel 2 &1e68 20 35 0a JSR &0a35 ; play_sound &1e6b 20 7e 1e JSR &1e7e ; display_object_information &1e6e 20 20 1f JSR &1f20 ; wait_for_i_and_backspace_over_text &1e71 20 f2 1e JSR &1ef2 ; display_score_information &1e74 20 20 1f JSR &1f20 ; wait_for_i_and_backspace_over_text ; suppress_auto_repeat &1e77 a5 ec LDA &ec ; os_most_recently_pressed_key &1e79 c9 a5 CMP #&a5 ; I &1e7b f0 fa BEQ &1e77 ; suppress_auto_repeat &1e7d 60 RTS ; display_object_information &1e7e a2 00 LDX #&00 ; 0 # TAB(&01, &00) &1e80 a0 00 LDY #&00 &1e82 20 a4 1e JSR &1ea4 ; set_cursor_position &1e85 a2 00 LDX #&00 ; search_for_object_in_list &1e87 bd af 0c LDA &0caf,X ; object_names &1e8a c5 9c CMP &9c ; carrying &1e8c f0 03 BEQ &1e91 ; found_object &1e8e e8 INX &1e8f d0 f6 BNE &1e87 ; search_for_object_in_list ; found_object &1e91 a0 ff LDY #&ff # Y is the number of characters written ; write_object_name &1e93 e8 INX &1e94 c8 INY &1e95 bd af 0c LDA &0caf,X ; object_names &1e98 30 09 BMI &1ea3 ; leave &1e9a c9 14 CMP #&14 &1e9c 90 05 BCC &1ea3 ; leave &1e9e 20 ee ff JSR &ffee ; OSWRCH &1ea1 d0 f0 BNE &1e93 ; write_object_name ; leave &1ea3 60 RTS ; set_cursor_position # Called with X = crtc_offset_high, Y = crtc_offset_low &1ea4 a9 1e LDA #&1e ; HOME &1ea6 20 ee ff JSR &ffee ; OSWRCH &1ea9 98 TYA &1eaa 18 CLC &1eab 65 87 ADC &87 ; crtc_start_address_low &1ead 85 77 STA &77 ; x_low &1eaf 8a TXA &1eb0 65 88 ADC &88 ; crtc_start_address_high &1eb2 38 SEC &1eb3 e9 06 SBC #&06 ; check_overflow &1eb5 c9 0a CMP #&0a &1eb7 30 05 BMI &1ebe ; skip_overflow &1eb9 38 SEC &1eba e9 0a SBC #&0a &1ebc 10 f7 BPL &1eb5 ; check_overflow ; skip_overflow &1ebe 4a LSR A &1ebf 66 77 ROR &77 ; x_low &1ec1 4a LSR A &1ec2 66 77 ROR &77 ; x_low &1ec4 c9 02 CMP #&02 &1ec6 d0 14 BNE &1edc ; move_cursor &1ec8 48 PHA &1ec9 a5 77 LDA &77 ; x_low &1ecb c9 70 CMP #&70 &1ecd 90 0c BCC &1edb ; move_cursor_after_pla &1ecf 98 TYA &1ed0 18 CLC &1ed1 69 50 ADC #&50 &1ed3 a8 TAY &1ed4 8a TXA &1ed5 69 00 ADC #&00 &1ed7 aa TAX &1ed8 68 PLA &1ed9 d0 c9 BNE &1ea4 ; set_cursor_position ; move_cursor_after_pla &1edb 68 PLA ; move_cursor &1edc a8 TAY &1edd a9 09 LDA #&09 ; RIGHT &1edf a6 77 LDX &77 ; x_low &1ee1 f0 06 BEQ &1ee9 ; next_high ; move_cursor_loop &1ee3 20 ee ff JSR &ffee ; OSWRCH &1ee6 ca DEX &1ee7 d0 fa BNE &1ee3 ; move_cursor_loop ; next_high &1ee9 88 DEY &1eea 10 f7 BPL &1ee3 ; skip_moving_cursor_right &1eec a9 09 LDA #&09 ; RIGHT &1eee 20 ee ff JSR &ffee ; OSWRCH &1ef1 60 RTS ; display_score_information &1ef2 a0 00 LDY #&00 ; 0 # TAB(&01, &00) &1ef4 a2 00 LDX #&00 &1ef6 20 a4 1e JSR &1ea4 ; set_cursor_position &1ef9 a2 00 LDX #&00 # Write "SCORE=" &1efb 20 15 2b JSR &2b15 ; write_string &1efe a2 00 LDX #&00 &1f00 a4 57 LDY &57 ; score &1f02 f0 0c BEQ &1f10 ; write_score &1f04 ca DEX ; convert_score_loop # Convert score into BCD, A = low, X = high &1f05 18 CLC &1f06 69 01 ADC #&01 &1f08 90 01 BCC &1f0b ; skip_overflow &1f0a e8 INX ; skip_overflow &1f0b 88 DEY &1f0c f8 SED # Cleared in write_number &1f0d d0 f6 BNE &1f05 ; convert_score_loop &1f0f a8 TAY ; write_score &1f10 8a TXA &1f11 20 fa 2f JSR &2ffa ; write_number &1f14 98 TYA &1f15 4a LSR A &1f16 4a LSR A &1f17 4a LSR A &1f18 4a LSR A &1f19 20 fa 2f JSR &2ffa ; write_number &1f1c 98 TYA &1f1d 4c 28 2a JMP &2a28 ; write_number_times_ten ; wait_for_i_and_backspace_over_text ; suppress_auto_repeat &1f20 a5 ec LDA &ec ; os_most_recently_pressed_key &1f22 c9 a5 CMP #&a5 ; I &1f24 f0 fa BEQ &1f20 ; suppress_auto_repeat ; wait_for_i &1f26 a5 ec LDA &ec ; os_most_recently_pressed_key &1f28 c9 a5 CMP #&a5 ; I &1f2a d0 fa BNE &1f26 ; wait_for_i ; delete_text_loop &1f2c a9 7f LDA #&7f ; DELETE &1f2e 20 ee ff JSR &ffee ; OSWRCH &1f31 88 DEY &1f32 d0 f8 BNE &1f2c ; delete_text_loop &1f34 60 RTS ; change_player_level &1f35 a5 86 LDA &86 ; screen_start_x_high &1f37 85 78 STA &78 ; x_high &1f39 a5 85 LDA &85 ; screen_start_x_low &1f3b 85 77 STA &77 ; x_low &1f3d ad 5f 0c LDA &0c5f ; objects_y + OBJECT_PLAYER &1f40 f0 61 BEQ &1fa3 ; was_at_bottom_of_level ; was_at_top_of_level &1f42 a9 1c LDA #&1c &1f44 85 76 STA &76 ; y &1f46 20 80 03 JSR &0380 ; calculate_screen_address &1f49 a2 2f LDX #&2f ; OBJECT_PLAYER &1f4b 20 3d 20 JSR &203d ; change_object_level # Move player up a level &1f4e a5 85 LDA &85 ; screen_start_x_low &1f50 38 SEC &1f51 e9 80 SBC #&80 &1f53 85 85 STA &85 ; screen_start_x_low &1f55 a5 86 LDA &86 ; screen_start_x_high &1f57 f9 2c 0a SBC &0a2c,Y ; going_up_delta_x_high &1f5a 85 86 STA &86 ; screen_start_x_high &1f5c a9 04 LDA #&04 # Plot four groups over status area without scrolling &1f5e 85 72 STA &72 ; count &1f60 a9 04 LDA #&04 &1f62 85 76 STA &76 ; y ; plot_over_status_area_loop &1f64 20 fe 1f JSR &1ffe ; plot_row_of_tile_chunks &1f67 a2 00 LDX #&00 # Move up eight pixels &1f69 20 c3 03 JSR &03c3 ; alter_screen_address &1f6c 20 c3 03 JSR &03c3 ; alter_screen_address # Move up sixteen pixels in total &1f6f e6 76 INC &76 ; y &1f71 c6 72 DEC &72 ; count &1f73 d0 ef BNE &1f64 ; plot_over_status_area_loop &1f75 a9 18 LDA #&18 # Plot twenty four groups with scrolling &1f77 85 72 STA &72 ; count ; scroll_screen_up_loop &1f79 a5 87 LDA &87 ; crtc_start_address_low &1f7b 38 SEC &1f7c e9 50 SBC #&50 &1f7e 85 87 STA &87 ; crtc_start_address_low &1f80 b0 02 BCS &1f84 ; skip_page &1f82 c6 88 DEC &88 ; crtc_start_address_high ; skip_page &1f84 20 1f 21 JSR &211f ; calculate_screen_from_crtc_address &1f87 20 4f 21 JSR &214f ; set_screen_address &1f8a 20 fe 1f JSR &1ffe ; plot_row_of_tile_chunks &1f8d a2 00 LDX #&00 # Move up eight pixels &1f8f 20 c3 03 JSR &03c3 ; alter_screen_address &1f92 20 c3 03 JSR &03c3 ; alter_screen_address # Move up sixteen pixels in total &1f95 e6 76 INC &76 ; y &1f97 c6 72 DEC &72 ; count &1f99 d0 de BNE &1f79 ; scroll_screen_up_loop &1f9b a2 02 LDX #&02 # Move down eight pixels &1f9d 20 c3 03 JSR &03c3 ; alter_screen_address &1fa0 4c df 1f JMP &1fdf ; clear_status_area ; was_at_bottom_of_level &1fa3 a9 1f LDA #&1f &1fa5 85 76 STA &76 ; y &1fa7 20 80 03 JSR &0380 ; calculate_screen_address &1faa a2 2f LDX #&2f ; OBJECT_PLAYER &1fac 20 3d 20 JSR &203d ; change_object_level # Move player down a level &1faf a5 85 LDA &85 ; screen_start_x_low &1fb1 18 CLC &1fb2 69 80 ADC #&80 &1fb4 85 85 STA &85 ; screen_start_x_low &1fb6 a5 86 LDA &86 ; screen_start_x_high &1fb8 79 10 0d ADC &0d10,Y ; going_down_delta_x_high &1fbb 85 86 STA &86 ; screen_start_x_high &1fbd a9 18 LDA #&18 # Plot twenty four groups with scrolling &1fbf 85 72 STA &72 ; count &1fc1 a9 17 LDA #&17 &1fc3 85 76 STA &76 ; y ; scroll_screen_down_loop &1fc5 20 fe 1f JSR &1ffe ; plot_row_of_tile_chunks &1fc8 a5 87 LDA &87 ; crtc_start_address_low &1fca 18 CLC &1fcb 69 50 ADC #&50 &1fcd 85 87 STA &87 ; crtc_start_address_low &1fcf 90 02 BCC &1fd3 ; skip_page &1fd1 e6 88 INC &88 ; crtc_start_address_high ; skip_page &1fd3 20 1f 21 JSR &211f ; calculate_screen_from_crtc_address &1fd6 20 4f 21 JSR &214f ; set_screen_address &1fd9 c6 76 DEC &76 ; y &1fdb c6 72 DEC &72 ; count &1fdd d0 e6 BNE &1fc5 ; scroll_screen_down_loop ; clear_status_area &1fdf a5 85 LDA &85 ; screen_start_x_low &1fe1 85 77 STA &77 ; x_low &1fe3 a5 86 LDA &86 ; screen_start_x_high &1fe5 85 78 STA &78 ; x_high &1fe7 a9 50 LDA #&50 &1fe9 85 74 STA &74 ; object_width ; clear_status_area_loop &1feb 20 69 21 JSR &2169 ; wipe_status_area_column &1fee e6 77 INC &77 ; x_low &1ff0 d0 02 BNE &1ff4 ; skip_overflow &1ff2 e6 78 INC &78 ; x_high ; skip_overflow &1ff4 c6 74 DEC &74 ; object_width &1ff6 d0 f3 BNE &1feb ; clear_status_area_loop &1ff8 20 01 2c JSR &2c01 ; replot_pockets &1ffb 4c 6b 29 JMP &296b ; stop_all_movers_moving ; plot_row_of_tile_chunks &1ffe a5 85 LDA &85 ; screen_start_x_low &2000 85 77 STA &77 ; x_low &2002 a5 86 LDA &86 ; screen_start_x_high &2004 85 78 STA &78 ; x_high &2006 a5 76 LDA &76 ; y &2008 c9 10 CMP #&10 &200a d0 05 BNE &2011 ; skip_changing_wall_colour &200c 20 6a 01 JSR &016a ; set_wall_colour # Change wall colour halfway through the level change &200f a5 76 LDA &76 ; y ; skip_changing_wall_colour &2011 29 03 AND #&03 &2013 85 7b STA &7b ; y_subtile &2015 a9 50 LDA #&50 &2017 85 5b STA &5b ; columns_to_plot &2019 20 69 07 JSR &0769 ; get_map_tile ; plot_row_of_tile_chunks_loop &201c a5 77 LDA &77 ; x_low &201e 29 07 AND #&07 &2020 85 7c STA &7c ; x_subtile &2022 d0 03 BNE &2027 ; not_new_tile &2024 20 69 07 JSR &0769 ; get_map_tile ; not_new_tile &2027 20 1b 01 JSR &011b ; get_tile_chunk &202a 20 8e 21 JSR &218e ; plot_tile_chunk &202d a2 01 LDX #&01 # Move right two pixels &202f 20 c3 03 JSR &03c3 ; alter_screen_address &2032 e6 77 INC &77 ; x_low &2034 d0 02 BNE &2038 ; skip_overflow &2036 e6 78 INC &78 ; x_high ; skip_overflow &2038 c6 5b DEC &5b ; columns_to_plot &203a d0 e0 BNE &201c ; plot_row_of_tile_chunks_loop &203c 60 RTS ; change_object_level &203d bc e8 0b LDY &0be8,X ; objects_x_high &2040 bd 30 0c LDA &0c30,X ; objects_y &2043 f0 18 BEQ &205d ; move_object_down_a_level ; move_object_up_a_level &2045 bd a0 0b LDA &0ba0,X ; objects_x_low &2048 38 SEC &2049 e9 80 SBC #&80 &204b 9d a0 0b STA &0ba0,X ; objects_x_low &204e bd e8 0b LDA &0be8,X ; objects_x_high &2051 f9 2c 0a SBC &0a2c,Y ; going_up_delta_x_high &2054 9d e8 0b STA &0be8,X ; objects_x_high &2057 a9 01 LDA #&01 &2059 9d 30 0c STA &0c30,X ; objects_y &205c 60 RTS ; move_object_down_a_level &205d bd a0 0b LDA &0ba0,X ; objects_x_low &2060 18 CLC &2061 69 80 ADC #&80 &2063 9d a0 0b STA &0ba0,X ; objects_x_low &2066 bd e8 0b LDA &0be8,X ; objects_x_high &2069 79 10 0d ADC &0d10,Y ; going_down_delta_x_high &206c 9d e8 0b STA &0be8,X ; objects_x_high &206f a9 18 LDA #&18 &2071 9d 30 0c STA &0c30,X ; objects_y &2074 60 RTS ; check_for_object_changing_level &2075 bd 30 0c LDA &0c30,X ; objects_y &2078 f0 06 BEQ &2080 ; at_top_or_bottom_of_level &207a c9 19 CMP #&19 &207c 10 02 BPL &2080 ; at_top_or_bottom_of_level ; leave_with_carry_clear &207e 18 CLC # Leave with carry clear to indicate not changing level &207f 60 RTS ; at_top_or_bottom_of_level &2080 bc e8 0b LDY &0be8,X ; objects_x_high &2083 bd a0 0b LDA &0ba0,X ; objects_x_low &2086 d9 23 0a CMP &0a23,Y ; level_openings_left &2089 90 f3 BCC &207e ; leave_with_carry_clear &208b d9 1a 0a CMP &0a1a,Y ; level_openings_right &208e b0 ee BCS &207e ; leave_with_carry_clear &2090 38 SEC # Leave with carry set to indicate changing level &2091 60 RTS ; update_screen_address_and_plot_edge_of_screen &2092 20 45 21 JSR &2145 ; set_screen_address_after_vsync &2095 a5 9d LDA &9d ; screen_scrolling_direction # Positive if scrolling screen &2097 10 0a BPL &20a3 ; is_scrolling ; short_delay # Short delay if not scrolling screen &2099 a5 32 LDA &32 ; timer_at_vsync &209b ed 79 fe SBC &fe79 ; User VIA timer 2 counter MSB &209e c9 50 CMP #&50 &20a0 30 f7 BMI &2099 ; short_delay ; leave &20a2 60 RTS ; is_scrolling &20a3 f0 0f BEQ &20b4 ; plot_left_edge # Zero if scrolling left ; plot_right_edge &20a5 a5 85 LDA &85 ; screen_start_x_low &20a7 18 CLC &20a8 69 4f ADC #&4f &20aa 85 77 STA &77 ; x_low &20ac a5 86 LDA &86 ; screen_start_x_high &20ae 69 00 ADC #&00 &20b0 85 78 STA &78 ; x_high &20b2 10 08 BPL &20bc ; plot_edge # Always branches ; plot_left_edge &20b4 a5 85 LDA &85 ; screen_start_x_low &20b6 85 77 STA &77 ; x_low &20b8 a5 86 LDA &86 ; screen_start_x_high &20ba 85 78 STA &78 ; x_high ; plot_edge &20bc 20 69 21 JSR &2169 ; wipe_status_area_column &20bf a5 77 LDA &77 ; x_low &20c1 29 07 AND #&07 &20c3 85 7c STA &7c ; x_subtile &20c5 20 69 07 JSR &0769 ; get_map_tile &20c8 4c d7 20 JMP &20d7 ; next_edge_subtile ; next_edge_tile &20cb 20 1b 01 JSR &011b ; get_tile_chunk ; plot_edge_chunk &20ce a0 07 LDY #&07 ; plot_edge_chunk_loop &20d0 b1 91 LDA (&91),Y ; tile_sprite_address &20d2 91 81 STA (&81),Y ; screen_address &20d4 88 DEY &20d5 10 f9 BPL &20d0 ; plot_edge_chunk_loop ; next_edge_subtile &20d7 c6 76 DEC &76 ; y &20d9 30 c7 BMI &20a2 ; leave &20db 20 c3 03 JSR &03c3 ; alter_screen_address # Move down eight pixels (X = 2 here) &20de a5 76 LDA &76 ; y &20e0 29 03 AND #&03 &20e2 85 7b STA &7b ; y_subtile &20e4 c9 03 CMP #&03 &20e6 f0 09 BEQ &20f1 ; end_of_tile &20e8 c6 10 DEC &10 ; tile_chunk_offset &20ea a4 10 LDY &10 ; tile_chunk_offset &20ec 20 34 01 JSR &0134 ; get_tile_chunk_from_previous_tile_using_offset &20ef d0 dd BNE &20ce ; plot_edge_chunk ; end_of_tile &20f1 c6 11 DEC &11 ; tile_y &20f3 a4 11 LDY &11 ; tile_y &20f5 20 99 07 JSR &0799 ; get_next_map_tile &20f8 4c cb 20 JMP &20cb ; next_edge_tile ; adjust_crtc_and_screen_addresses_if_scrolling &20fb a5 9d LDA &9d ; screen_scrolling_direction &20fd 30 69 BMI &2168 ; leave # Leave if not scrolling left or right &20ff f0 0e BEQ &210f ; adjust_crtc_and_screen_addresses_for_scrolling_left ; adjust_crtc_and_screen_addresses_for_scrolling_right &2101 e6 85 INC &85 ; screen_start_x_low &2103 d0 02 BNE &2107 ; skip_overflow &2105 e6 86 INC &86 ; screen_start_x_high ; skip_overflow &2107 e6 87 INC &87 ; crtc_start_address_low &2109 d0 02 BNE &210d ; skip_page &210b e6 88 INC &88 ; crtc_start_address_high ; skip_page &210d d0 10 BNE &211f ; calculate_screen_from_crtc_address # Always branches ; adjust_crtc_and_screen_addresses_for_scrolling_left &210f a5 85 LDA &85 ; screen_start_x_low &2111 d0 02 BNE &2115 ; skip_underflow &2113 c6 86 DEC &86 ; screen_start_x_high ; skip_underflow &2115 c6 85 DEC &85 ; screen_start_x_low &2117 a5 87 LDA &87 ; crtc_start_address_low &2119 d0 02 BNE &211d ; skip_page &211b c6 88 DEC &88 ; crtc_start_address_high ; skip_page &211d c6 87 DEC &87 ; crtc_start_address_low ; calculate_screen_from_crtc_address &211f a5 88 LDA &88 ; crtc_start_address_high &2121 c9 06 CMP #&06 &2123 10 06 BPL &212b ; skip_low_wraparound &2125 a9 0f LDA #&0f &2127 85 88 STA &88 ; crtc_start_address_high &2129 10 08 BPL &2133 ; skip_high_wraparound ; skip_low_wraparound &212b c9 10 CMP #&10 &212d 30 04 BMI &2133 ; skip_high_wraparound &212f a9 06 LDA #&06 &2131 85 88 STA &88 ; crtc_start_address_high ; skip_high_wraparound &2133 a5 88 LDA &88 ; crtc_start_address_high &2135 85 84 STA &84 ; screen_start_address_high &2137 a5 87 LDA &87 ; crtc_start_address_low &2139 0a ASL A &213a 26 84 ROL &84 ; screen_start_address_high &213c 0a ASL A &213d 26 84 ROL &84 ; screen_start_address_high &213f 0a ASL A &2140 26 84 ROL &84 ; screen_start_address_high &2142 85 83 STA &83 ; screen_start_address_low &2144 60 RTS ; set_screen_address_after_vsync &2145 a5 32 LDA &32 ; timer_at_vsync &2147 38 SEC &2148 ed 79 fe SBC &fe79 ; User VIA timer 2 counter MSB &214b c9 3b CMP #&3b &214d 10 05 BPL &2154 ; skip_vsync ; set_screen_address &214f a9 13 LDA #&13 ; Wait for Vertical Retrace &2151 20 f4 ff JSR &fff4 ; OSBYTE ; skip_vsync &2154 a9 0c LDA #&0c # R12: Displayed screen start address register (high) &2156 8d 00 fe STA &fe00 ; video register number &2159 a5 88 LDA &88 ; crtc_start_address_high &215b 8d 01 fe STA &fe01 ; video register value &215e a9 0d LDA #&0d # R13: Displayed screen start address register (low) &2160 8d 00 fe STA &fe00 ; video register number &2163 a5 87 LDA &87 ; crtc_start_address_low &2165 8d 01 fe STA &fe01 ; video register value ; leave &2168 60 RTS ; wipe_status_area_column &2169 a9 1f LDA #&1f &216b 85 76 STA &76 ; y &216d 20 80 03 JSR &0380 ; calculate_screen_address &2170 a2 02 LDX #&02 # Move down eight pixels ; wipe_column_loop &2172 a0 07 LDY #&07 &2174 a9 00 LDA #&00 ; wipe_chunk_loop &2176 91 81 STA (&81),Y ; screen_address &2178 88 DEY &2179 10 fb BPL &2176 ; wipe_chunk_loop &217b 20 c3 03 JSR &03c3 ; alter_screen_address &217e c6 76 DEC &76 ; y &2180 a5 76 LDA &76 ; y &2182 c9 1c CMP #&1c &2184 d0 ec BNE &2172 ; wipe_column_loop &2186 a9 12 LDA #&12 ; &1220 = chunk_sprite_data + &30 * 8 # Plot white bottom border of status area &2188 85 92 STA &92 ; tile_sprite_address_high &218a a9 20 LDA #&20 &218c 85 91 STA &91 ; tile_sprite_address_low ; plot_tile_chunk &218e a0 07 LDY #&07 ; plot_tile_chunk_loop &2190 b1 91 LDA (&91),Y ; tile_sprite_address &2192 91 81 STA (&81),Y ; screen_address &2194 88 DEY &2195 10 f9 BPL &2190 ; plot_tile_chunk_loop &2197 60 RTS ; get_object_variables_for_object_X &2198 8a TXA &2199 a8 TAY ; get_object_variables_for_object_Y &219a b9 30 0c LDA &0c30,Y ; objects_y &219d 85 76 STA &76 ; y &219f b9 a0 0b LDA &0ba0,Y ; objects_x_low &21a2 85 77 STA &77 ; x_low &21a4 b9 e8 0b LDA &0be8,Y ; objects_x_high &21a7 85 78 STA &78 ; x_high ; get_object_width_and_height_for_object_Y &21a9 b9 78 0c LDA &0c78,Y ; objects_size &21ac 4a LSR A &21ad 4a LSR A &21ae 85 74 STA &74 ; object_width &21b0 b9 78 0c LDA &0c78,Y ; objects_size &21b3 29 03 AND #&03 &21b5 85 73 STA &73 ; object_height &21b7 a9 0e LDA #&0e &21b9 85 80 STA &80 ; chunk_address_high &21bb 60 RTS ; plot_pocket &21bc a9 06 LDA #&06 # Use plot_sprite_chunk &21be 10 35 BPL &21f5 ; set_plotting_plotting_method_jump_offset # Then plot as object, ignoring tiles; always branches ; plot_object &21c0 20 69 07 JSR &0769 ; get_map_tile &21c3 85 8a STA &8a ; object_tile_type # Store tile at bottom left of object &21c5 a5 77 LDA &77 ; x_low &21c7 29 07 AND #&07 &21c9 85 8b STA &8b ; start_x_subtile &21cb a9 08 LDA #&08 &21cd 38 SEC &21ce e5 8b SBC &8b ; start_x_subtile &21d0 85 7b STA &7b ; subtiles_to_next_tile &21d2 a5 74 LDA &74 ; object_width &21d4 38 SEC &21d5 e5 7b SBC &7b ; subtiles_to_next_tile &21d7 85 7b STA &7b ; object_width_minus_subtiles_to_next_tile # Store for use when considering foregrounds &21d9 a5 77 LDA &77 ; x_low &21db 29 f8 AND #&f8 &21dd 18 CLC &21de 69 08 ADC #&08 &21e0 85 77 STA &77 ; x_low &21e2 90 02 BCC &21e6 ; skip_overflow &21e4 e6 78 INC &78 ; x_high ; skip_overflow &21e6 20 69 07 JSR &0769 ; get_map_tile &21e9 bd a0 0b LDA &0ba0,X ; objects_x_low &21ec 85 77 STA &77 ; x_low &21ee bd e8 0b LDA &0be8,X ; objects_x_high &21f1 85 78 STA &78 ; x_high &21f3 a9 00 LDA #&00 # Use plot_sprite_chunk_considering_foreground ; set_plotting_plotting_method_jump_offset &21f5 8d 10 22 STA &2210 ; plotting_method_jump_offset &21f8 a5 76 LDA &76 ; y &21fa 18 CLC &21fb 65 73 ADC &73 ; object_height &21fd 85 76 STA &76 ; y &21ff c6 76 DEC &76 ; y &2201 a2 01 LDX #&01 # Unnecessary code; set at &2220 &2203 a9 00 LDA #&00 &2205 85 5b STA &5b ; sprite_offset &2207 a5 74 LDA &74 ; object_width &2209 85 95 STA &95 ; width ; plot_object_y_loop &220b 20 80 03 JSR &0380 ; calculate_screen_address ; plot_object_x_loop &220e 18 CLC &220f 90 fe BCC &220f # actually BCC &2211 + plotting_method_jump_offset # Always branches # either BCC consider_foreground # if plotting_method_jump_offset = 0 # or BCC ignore_foreground # if plotting_method_jump_offset = 6 ; consider_foreground &2211 20 39 22 JSR &2239 ; plot_sprite_chunk_considering_foreground &2214 4c 1a 22 JMP &221a ; next_width ; ignore_foreground &2217 20 6b 22 JSR &226b ; plot_sprite_chunk ; next_width &221a e6 5b INC &5b ; sprite_offset &221c c6 95 DEC &95 ; width &221e f0 08 BEQ &2228 ; next_height &2220 a2 01 LDX #&01 # Move right two pixels &2222 20 c3 03 JSR &03c3 ; alter_screen_address &2225 4c 0e 22 JMP &220e ; plot_object_x_loop ; next_height &2228 c6 73 DEC &73 ; object_height &222a f0 08 BEQ &2234 ; leave_after_setting_sprite_is_foreground &222c a5 74 LDA &74 ; object_width &222e 85 95 STA &95 ; width &2230 c6 76 DEC &76 ; y &2232 10 d7 BPL &220b ; plot_object_y_loop ; leave_after_setting_sprite_is_foreground &2234 a9 ff LDA #&ff # Set to non-zero to allow background sprite plotting &2236 85 66 STA &66 ; sprite_is_foreground &2238 60 RTS ; plot_sprite_chunk_considering_foreground &2239 20 4e 01 JSR &014e ; calculate_sprite_address_from_chunk &223c a5 66 LDA &66 ; sprite_is_foreground # If zero, plot sprite over tiles regardless &223e f0 1f BEQ &225f ; plot_foreground_sprite_tile_chunk &2240 a5 7b LDA &7b ; object_width_minus_subtiles_to_next_tile # Is the sprite still in the first tile? &2242 c5 95 CMP &95 ; width &2244 10 04 BPL &224a ; use_tile_type &2246 a4 8a LDY &8a ; object_tile_type # If so, use first tile &2248 10 02 BPL &224c ; check_for_foreground ; use_tile_type &224a a4 8b LDY &8b ; tile_type # Otherwise, second tile ; check_for_foreground &224c b9 55 0a LDA &0a55,Y ; tiles_foreground_flags # Otherwise, use type of tile to determine plot method &224f f0 0e BEQ &225f ; plot_foreground_tile_chunk ; plot_background_sprite_tile_chunk # Plot sprite behind existing sprites &2251 a0 07 LDY #&07 ; plot_background_sprite_tile_chunk_loop &2253 b1 81 LDA (&81),Y ; screen_address &2255 d0 04 BNE &225b ; skip_background_sprite_byte # Don't overwrite non-empty screen bytes &2257 b1 8f LDA (&8f),Y ; sprite_address &2259 91 81 STA (&81),Y ; screen_address ; skip_background_sprite_byte &225b 88 DEY &225c 10 f5 BPL &2253 ; plot_background_sprite_tile_chunk_loop &225e 60 RTS ; plot_foreground_sprite_tile_chunk # Plot sprite in front of existing sprites &225f a0 07 LDY #&07 ; plot_foreground_sprite_tile_chunk_loop &2261 b1 8f LDA (&8f),Y ; sprite_address &2263 f0 02 BEQ &2267 ; skip_foreground_sprite_byte # Don't plot empty sprite bytes &2265 91 81 STA (&81),Y ; screen_address ; skip_foreground_sprite_byte &2267 88 DEY &2268 10 f7 BPL &2261 ; plot_foreground_sprite_tile_chunk_loop &226a 60 RTS ; plot_sprite_chunk &226b 20 4e 01 JSR &014e ; calculate_sprite_address_from_chunk &226e a0 07 LDY #&07 ; plot_sprite_chunk_loop &2270 b1 8f LDA (&8f),Y ; sprite_address &2272 91 81 STA (&81),Y ; screen_address &2274 88 DEY &2275 10 f9 BPL &2270 ; plot_sprite_chunk_loop &2277 60 RTS ; unplot_pocket &2278 a5 74 LDA &74 ; object_width &227a 85 95 STA &95 ; width &227c 20 80 03 JSR &0380 ; calculate_screen_address ; unplot_pocket_x_loop &227f a0 07 LDY #&07 &2281 a9 00 LDA #&00 ; unplot_pocket_group_loop &2283 91 81 STA (&81),Y ; screen_address &2285 88 DEY &2286 10 fb BPL &2283 ; unplot_pocket_group_loop &2288 c6 95 DEC &95 ; width &228a f0 08 BEQ &2294 ; next_group &228c a2 01 LDX #&01 # Move right two pixels &228e 20 c3 03 JSR &03c3 ; alter_screen_address &2291 4c 7f 22 JMP &227f ; unplot_pocket_x_loop ; next_group &2294 c6 73 DEC &73 ; object_height &2296 f0 04 BEQ &229c ; leave &2298 e6 76 INC &76 ; y &229a 10 dc BPL &2278 ; unplot_pocket # Always branches ; leave &229c 60 RTS ; unplot_object &229d a5 77 LDA &77 ; x_low &229f 85 97 STA &97 ; initial_x_low &22a1 a5 78 LDA &78 ; x_high &22a3 85 98 STA &98 ; initial_x_high &22a5 a5 73 LDA &73 ; object_height &22a7 85 96 STA &96 ; height &22a9 18 CLC &22aa 65 76 ADC &76 ; y &22ac 85 76 STA &76 ; y ; unplot_object_y_loop &22ae c6 76 DEC &76 ; y &22b0 a5 76 LDA &76 ; y &22b2 29 03 AND #&03 &22b4 85 7b STA &7b ; y_subtile &22b6 a5 77 LDA &77 ; x_low &22b8 29 07 AND #&07 &22ba 85 7c STA &7c ; x_subtile &22bc a5 74 LDA &74 ; object_width &22be 85 95 STA &95 ; width &22c0 20 80 03 JSR &0380 ; calculate_screen_address ; unplot_object_x_loop &22c3 20 69 07 JSR &0769 ; get_map_tile &22c6 20 1b 01 JSR &011b ; get_tile_chunk ; unplot_object_chunk_loop &22c9 a0 07 LDY #&07 &22cb b1 91 LDA (&91),Y ; tile_sprite_address_high &22cd 91 81 STA (&81),Y ; screen_address &22cf 88 DEY &22d0 10 f9 BPL &22cb ; unplot_object_chunk_loop &22d2 c6 95 DEC &95 ; width &22d4 f0 19 BEQ &22ef ; next_column &22d6 e6 77 INC &77 ; x_low &22d8 d0 02 BNE &22dc ; skip_page &22da e6 78 INC &78 ; x_high ; skip_page &22dc a2 01 LDX #&01 # Move right two pixels &22de 20 c3 03 JSR &03c3 ; alter_screen_address &22e1 a5 77 LDA &77 ; x_low &22e3 29 07 AND #&07 &22e5 85 7c STA &7c ; x_subtile &22e7 f0 da BEQ &22c3 ; unplot_object_x_loop &22e9 20 2a 01 JSR &012a ; get_tile_chunk_from_previous_tile &22ec 4c c9 22 JMP &22c9 ; unplot_object_chunk_loop ; next_column &22ef a5 97 LDA &97 ; initial_x_low &22f1 85 77 STA &77 ; x_low &22f3 a5 98 LDA &98 ; initial_x_high &22f5 85 78 STA &78 ; x_high &22f7 c6 96 DEC &96 ; height &22f9 d0 b3 BNE &22ae ; unplot_object_y_loop &22fb 60 RTS ; update_red_guards &22fc a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &22fe a2 a1 LDX #&a1 ; R # Set colour 10 (guard body) to red &2300 20 f4 ff JSR &fff4 ; OSBYTE &2303 a2 1f LDX #&1f ; OBJECT_LAST_RED_GUARD ; update_two_guards &2305 a9 01 LDA #&01 # Two guards &2307 85 65 STA &65 ; mover_offset &2309 20 8d 18 JSR &188d ; update_guards_loop &230c a5 63 LDA &63 ; player_was_killed # Zero if KILLED_UNCONSCIOUS because of touching guards &230e d0 04 BNE &2314 ; leave &2310 a9 05 LDA #&05 ; KILLED_ARE_DEAD # Red and yellow guards kill player &2312 85 63 STA &63 ; player_was_killed ; leave &2314 60 RTS ; update_yellow_guards &2315 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &2317 a2 a3 LDX #&a3 ; Y # Set colour 10 (guard body) to yellow &2319 20 f4 ff JSR &fff4 ; OSBYTE &231c a2 21 LDX #&21 ; OBJECT_LAST_YELLOW_GUARD &231e d0 e5 BNE &2305 ; update_two_guards # Always branches ; check_for_treasure &2320 ad aa 0b LDA &0baa ; objects_x_low + OBJECT_WAND # Is the wand at the treasure? &2323 c9 aa CMP #&aa &2325 30 0f BMI &2336 ; leave &2327 c9 ac CMP #&ac &2329 10 0b BPL &2336 ; leave &232b ad 3a 0c LDA &0c3a ; objects_y + OBJECT_WAND &232e c9 10 CMP #&10 &2330 10 04 BPL &2336 ; leave &2332 c9 0c CMP #&0c &2334 10 01 BPL &2337 ; found_treasure ; leave &2336 60 RTS ; found_treasure &2337 a9 ff LDA #&ff # Set to &ff to indicate treasure found &2339 85 75 STA &75 ; death_timer &233b a2 2a LDX #&2a ; OBJECT_TREASURE # Display treasure &233d a9 1d LDA #&1d ; SPRITE_TREASURE &233f 85 7f STA &7f ; object_sprite &2341 4c cc 2c JMP &2ccc ; add_active_mover ; update_troll &2344 a9 05 LDA #&05 &2346 85 65 STA &65 ; mover_offset &2348 a2 22 LDX #&22 ; OBJECT_TROLL &234a 86 64 STX &64 ; object_to_update &234c a0 2f LDY #&2f ; OBJECT_PLAYER &234e 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2351 a5 77 LDA &77 ; x_low # x_low is the horizontal distance from troll to player &2353 c9 03 CMP #&03 &2355 b0 0a BCS &2361 ; troll_not_close_to_player &2357 a5 76 LDA &76 ; y # y is the vertical distance from troll to player &2359 c9 03 CMP #&03 &235b b0 04 BCS &2361 ; troll_not_close_to_player &235d a9 06 LDA #&06 ; KILLED_BY_TROLL # Kill the player if the troll is too close &235f 85 63 STA &63 ; player_was_killed ; troll_not_close_to_player &2361 a4 22 LDY &22 ; objects_state + OBJECT_TROLL &2363 c0 02 CPY #&02 &2365 30 6e BMI &23d5 ; troll_is_not_carrying_object ; troll_is_carrying_object # Troll state is hoard target if carrying object &2367 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &236a a5 77 LDA &77 ; x_low # Is the troll at the hoard? &236c d0 41 BNE &23af ; move_troll_with_sound &236e a5 76 LDA &76 ; y &2370 d0 3d BNE &23af ; move_troll_with_sound &2372 a4 59 LDY &59 ; object_carried_by_troll &2374 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2377 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns zero if object is fully off screen &237a f0 03 BEQ &237f ; skip_unplot &237c 20 9d 22 JSR &229d ; unplot_object # Unplot the object from the troll ; skip_unplot &237f a6 59 LDX &59 ; object_carried_by_troll &2381 a9 04 LDA #&04 ; OBJECT_STATE_IN_WORLD &2383 9d 30 0c STA &0c30,X ; objects_y # Put object on floor &2386 95 00 STA &00,X ; objects_state &2388 a5 59 LDA &59 ; object_carried_by_troll &238a 0a ASL A # Space objects in hoard &238b 6d c2 0b ADC &0bc2 ; objects_x_low + OBJECT_TROLL &238e 9d a0 0b STA &0ba0,X ; objects_x_low &2391 a9 ff LDA #&ff # Set to &ff to indicate troll not carrying object &2393 85 59 STA &59 ; object_carried_by_troll &2395 a9 00 LDA #&00 # Set to &00 to set troll returning to passage &2397 85 22 STA &22 ; objects_state + OBJECT_TROLL ; leave &2399 60 RTS ; move_troll_towards_target &239a a2 22 LDX #&22 ; OBJECT_TROLL &239c a0 16 LDY #&16 ; OBJECT_TROLL_PASSAGE_TARGET &239e 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &23a1 a5 77 LDA &77 ; x_low # Is the troll at the target? &23a3 d0 11 BNE &23b6 ; move_troll &23a5 a5 76 LDA &76 ; y &23a7 d0 0d BNE &23b6 ; move_troll &23a9 46 22 LSR &22 ; objects_state + OBJECT_TROLL # Set to &00 to set troll returning to passage &23ab 20 48 24 JSR &2448 ; stop_mover_moving &23ae 60 RTS ; move_troll_with_sound &23af a2 58 LDX #&58 ; sound_0 # Play sound for troll moving towards player &23b1 20 35 0a JSR &0a35 ; play_sound &23b4 a2 22 LDX #&22 ; OBJECT_TROLL ; move_troll &23b6 20 4e 24 JSR &244e ; move_mover &23b9 20 0b 17 JSR &170b ; calculate_sprite_from_direction &23bc 18 CLC &23bd 69 0c ADC #&0c ; SPRITE_TROLL &23bf 85 7f STA &7f ; object_sprite &23c1 20 cc 2c JSR &2ccc ; add_active_mover &23c4 a4 59 LDY &59 ; object_carried_by_troll # Negative if the troll isn't carrying anything &23c6 30 d1 BMI &2399 ; leave &23c8 ad 3a 0d LDA &0d3a ; objects_moving - 18 + OBJECT_TROLL # Convert state into horizontal direction &23cb 29 06 AND #&06 &23cd c9 04 CMP #&04 &23cf d0 01 BNE &23d2 ; to_update_carried_object &23d1 4a LSR A ; to_update_carried_object &23d2 4c c1 2e JMP &2ec1 ; update_carried_object ; troll_is_not_carrying_object &23d5 a2 16 LDX #&16 ; OBJECT_TROLL_PASSAGE_TARGET &23d7 a0 04 LDY #&04 ; OBJECT_GOLD # For each of the three valuables, gold, ruby and coin: ; check_for_valuables_loop &23d9 b9 00 00 LDA &0000,Y ; objects_state &23dc c9 06 CMP #&06 ; OBJECT_STATE_IN_POCKET &23de f0 14 BEQ &23f4 ; consider_next_valuable # If it isn't in a pocket, &23e0 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &23e3 30 0f BMI &23f4 ; consider_next_valuable # and it isn't on a different level &23e5 a5 77 LDA &77 ; x_low &23e7 a6 22 LDX &22 ; objects_state + OBJECT_TROLL # X = 1 if approaching object, 0 if returning to passage &23e9 d5 15 CMP &15,X ; objects_state + OBJECT_TROLL_HOARD_TARGET &23eb b0 07 BCS &23f4 ; consider_next_valuable # and it isn't already in the hoard (X = 0) &23ed b9 30 0c LDA &0c30,Y ; objects_y &23f0 c9 0c CMP #&0c &23f2 10 18 BPL &240c ; target_object # then make the troll move towards it ; consider_next_valuable &23f4 a2 16 LDX #&16 ; OBJECT_TROLL_PASSAGE_TARGET &23f6 88 DEY &23f7 c0 01 CPY #&01 &23f9 d0 de BNE &23d9 ; check_for_valuables_loop &23fb a5 63 LDA &63 ; player_was_killed # Positive if the player was killed &23fd 10 9b BPL &239a ; move_troll_towards_target # If so, set the troll returning to the passage &23ff a0 2f LDY #&2f ; OBJECT_PLAYER &2401 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2404 a5 77 LDA &77 ; x_low &2406 a6 22 LDX &22 ; objects_state + OBJECT_TROLL &2408 d5 15 CMP &15,X ; objects_state + OBJECT_TROLL_HOARD_TARGET &240a b0 8e BCS &239a ; move_troll_towards_target ; target_object # Y is the player or one of the three valuables here &240c a2 22 LDX #&22 ; OBJECT_TROLL &240e a9 01 LDA #&01 # Set to &01 to indicate troll is approaching object &2410 85 22 STA &22 ; objects_state + OBJECT_TROLL &2412 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2415 a5 77 LDA &77 ; x_low &2417 c9 02 CMP #&02 # If the troll isn't close to the targeted object, &2419 b0 94 BCS &23af ; move_troll_with_sound # make the troll move towards the targeted object &241b a5 76 LDA &76 ; y &241d c9 03 CMP #&03 &241f 10 8e BPL &23af ; move_troll_with_sound &2421 a2 ff LDX #&ff &2423 84 59 STY &59 ; object_carried_by_troll # Set the troll carrying the targeted object &2425 b9 00 00 LDA &0000,Y ; objects_state &2428 c9 03 CMP #&03 ; OBJECT_STATE_CARRYING_LEFT_OR_RIGHT # Was the player carrying the targeted object? &242a 30 08 BMI &2434 ; take_object_from_player &242c c9 0e CMP #&0e ; OBJECT_STATE_THROWN &242e d0 06 BNE &2436 ; set_troll_moving_towards_hoard &2430 86 54 STX &54 ; object_being_dropped_or_thrown # Set to &ff to indicate no object being thrown &2432 30 02 BMI &2436 ; set_troll_moving_towards_hoard # Always branches ; take_object_from_player &2434 86 9c STX &9c ; carrying # Set to &ff to indicate player not carrying object ; set_troll_moving_towards_hoard &2436 a9 08 LDA #&08 ; OBJECT_STATE_NEEDS_UNPLOTTING # Mark the object as needing unplotting &2438 99 00 00 STA &0000,Y ; objects_state &243b a9 15 LDA #&15 ; OBJECT_TROLL_HOARD_TARGET # Set the troll moving towards the hoard &243d 85 22 STA &22 ; objects_state + OBJECT_TROLL &243f 20 48 24 JSR &2448 ; stop_mover_moving &2442 a2 88 LDX #&88 ; sound_6 # Silence channel 3 &2444 20 35 0a JSR &0a35 ; play_sound &2447 60 RTS ; stop_mover_moving &2448 20 97 24 JSR &2497 ; stop_mover_moving_horizontally &244b 4c 9f 24 JMP &249f ; stop_mover_moving_vertically ; move_mover &244e 20 28 25 JSR &2528 ; get_mover_direction # Returns negative if not moving, carry set if &2451 30 04 BMI &2457 ; not_moving # moving vertically, carry clear if moving horizontally &2453 90 1c BCC &2471 ; is_moving_horizontally &2455 b0 2e BCS &2485 ; is_moving_vertically ; not_moving &2457 20 44 25 JSR &2544 ; check_if_mover_can_climb_ladder # Returns carry clear if climbing ladder &245a b0 08 BCS &2464 ; not_on_ladder &245c a4 65 LDY &65 ; mover_offset &245e a5 71 LDA &71 ; vertical_direction &2460 99 40 00 STA &0040,Y ; movers_vertical_direction # Store climbing direction &2463 60 RTS ; not_on_ladder &2464 20 57 25 JSR &2557 ; consider_slope_and_support_for_object_X # Returns carry set if not supported &2467 90 2d BCC &2496 ; skip_flip &2469 20 b3 24 JSR &24b3 ; flip_mover_horizontal_direction # Stop mover falling off platform ; skip_flip &246c a5 82 LDA &82 ; previous_vertical_direction &246e 30 37 BMI &24a7 ; flip_mover_vertical_direction &2470 60 RTS ; is_moving_horizontally &2471 b9 40 00 LDA &0040,Y ; movers_vertical_direction &2474 30 02 BMI &2478 ; wasn't_moving_vertically &2476 85 71 STA &71 ; vertical_direction ; wasn't_moving_vertically &2478 20 44 25 JSR &2544 ; check_if_mover_can_climb_ladder # Returns carry clear if climbing ladder &247b 90 1a BCC &2497 ; stop_mover_moving_horizontally &247d 20 57 25 JSR &2557 ; consider_slope_and_support_for_object_X # Returns carry set if not supported &2480 90 14 BCC &2496 ; leave &2482 4c b3 24 JMP &24b3 ; flip_mover_horizontal_direction ; is_moving_vertically &2485 20 57 25 JSR &2557 ; consider_slope_and_support_for_object_X # Returns carry set if not supported &2488 90 15 BCC &249f ; stop_mover_moving_vertically &248a a4 65 LDY &65 ; mover_offset &248c b9 40 00 LDA &0040,Y ; movers_vertical_direction # Use stored climbing direction &248f 85 71 STA &71 ; vertical_direction &2491 20 44 25 JSR &2544 ; check_if_mover_can_climb_ladder # Returns carry clear if climbing ladder &2494 b0 09 BCS &249f ; stop_mover_moving_vertically ; leave &2496 60 RTS ; stop_mover_moving_horizontally &2497 a4 65 LDY &65 ; mover_offset &2499 a9 ff LDA #&ff ; HORIZONTAL_NONE &249b 99 38 00 STA &0038,Y ; movers_horizontal_direction &249e 60 RTS ; stop_mover_moving_vertically &249f a4 65 LDY &65 ; mover_offset &24a1 a9 ff LDA #&ff ; VERTICAL_NONE &24a3 99 40 00 STA &0040,Y ; movers_vertical_direction &24a6 60 RTS ; flip_mover_vertical_direction &24a7 a4 65 LDY &65 ; mover_offset &24a9 a5 82 LDA &82 ; previous_vertical_direction &24ab 29 01 AND #&01 # VERTICAL_NONE becomes VERTICAL_UP &24ad 49 01 EOR #&01 &24af 99 40 00 STA &0040,Y ; movers_vertical_direction &24b2 60 RTS ; flip_mover_horizontal_direction &24b3 a4 65 LDY &65 ; mover_offset &24b5 b9 38 00 LDA &0038,Y ; movers_horizontal_direction &24b8 10 02 BPL &24bc ; use_movers_direction &24ba a5 81 LDA &81 ; previous_horizontal_direction ; use_movers_direction &24bc 29 02 AND #&02 # HORIZONTAL_NONE becomes HORIZONTAL_LEFT &24be 49 02 EOR #&02 &24c0 99 38 00 STA &0038,Y ; movers_horizontal_direction &24c3 60 RTS ; move_witch &24c4 20 28 25 JSR &2528 ; get_mover_direction # Returns negative if not moving, carry set if &24c7 30 19 BMI &24e2 ; not_moving # moving vertically, carry clear if moving horizontally &24c9 90 2e BCC &24f9 ; is_moving_horizontally ; is_moving_vertically &24cb a9 ff LDA #&ff ; VERTICAL_NONE &24cd 85 71 STA &71 ; vertical_direction &24cf 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object has hit obstacle &24d2 90 cb BCC &249f ; stop_mover_moving_vertically &24d4 a5 40 LDA &40 ; movers_vertical_direction &24d6 85 71 STA &71 ; vertical_direction &24d8 a9 ff LDA #&ff ; HORIZONTAL_NONE &24da 85 70 STA &70 ; horizontal_direction &24dc 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object has hit obstacle &24df b0 c6 BCS &24a7 ; flip_mover_vertical_direction &24e1 60 RTS ; not_moving &24e2 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object has hit obstacle &24e5 90 40 BCC &2527 ; leave &24e7 a5 70 LDA &70 ; horizontal_direction &24e9 30 c8 BMI &24b3 ; flip_mover_horizontal_direction &24eb a9 ff LDA #&ff ; VERTICAL_NONE &24ed 85 71 STA &71 ; vertical_direction &24ef 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object has hit obstacle &24f2 90 33 BCC &2527 ; leave &24f4 a9 00 LDA #&00 ; VERTICAL_UP # Witch rises over obstacles &24f6 85 40 STA &40 ; movers_vertical_direction &24f8 60 RTS ; is_moving_horizontally &24f9 a5 40 LDA &40 ; movers_vertical_direction &24fb 30 02 BMI &24ff ; skip_movers_direction &24fd 85 71 STA &71 ; vertical_direction ; skip_movers_direction &24ff a9 ff LDA #&ff ; HORIZONTAL_NONE &2501 85 70 STA &70 ; horizontal_direction &2503 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object has hit obstacle &2506 90 8f BCC &2497 ; stop_mover_moving_horizontally &2508 a5 38 LDA &38 ; movers_horizontal_direction &250a 85 70 STA &70 ; horizontal_direction &250c a9 ff LDA #&ff ; VERTICAL_NONE &250e 85 71 STA &71 ; vertical_direction &2510 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object has hit obstacle &2513 b0 9e BCS &24b3 ; flip_mover_horizontal_direction &2515 60 RTS ; check_object_X_for_obstacles &2516 a9 01 LDA #&01 # Set positive to check for obstacles, not support &2518 85 5e STA &5e ; suppress_top_support_check &251a 20 98 21 JSR &2198 ; get_object_variables_for_object_X &251d 20 50 1c JSR &1c50 ; calculate_object_edges &2520 20 5e 1b JSR &1b5e ; check_object_for_support_or_obstacle &2523 a9 ff LDA #&ff # Set negative to check for support, not obstacles &2525 85 5e STA &5e ; suppress_top_support_check ; leave &2527 60 RTS ; get_mover_direction &2528 a4 65 LDY &65 ; mover_offset &252a 18 CLC &252b a5 70 LDA &70 ; horizontal_direction &252d 85 81 STA &81 ; previous_horizontal_direction &252f a5 71 LDA &71 ; vertical_direction &2531 85 82 STA &82 ; previous_vertical_direction &2533 b9 38 00 LDA &0038,Y ; movers_horizontal_direction &2536 10 09 BPL &2541 ; use_horizontal_direction &2538 b9 40 00 LDA &0040,Y ; movers_vertical_direction &253b 30 03 BMI &2540 ; leave # Leave with negative if not moving in any direction &253d 38 SEC # Leave with carry set if moving vertically &253e 85 71 STA &71 ; vertical_direction ; leave &2540 60 RTS ; use_horizontal_direction &2541 85 70 STA &70 ; horizontal_direction &2543 60 RTS ; check_if_mover_can_climb_ladder &2544 bd a0 0b LDA &0ba0,X ; objects_x_low &2547 29 07 AND #&07 &2549 c9 03 CMP #&03 &254b d0 08 BNE &2555 ; leave_with_carry_set # Is the mover in a position to climb a ladder? &254d 8a TXA &254e a8 TAY &254f 20 a9 21 JSR &21a9 ; get_object_width_and_height_for_object_Y &2552 4c 21 16 JMP &1621 ; consider_climbing_ladder # Leaves with carry clear if climbing ladder ; leave_with_carry_set &2555 38 SEC # Leave with carry set to indicate not climbing &2556 60 RTS ; consider_slope_and_support_for_object_X &2557 20 98 21 JSR &2198 ; get_object_variables_for_object_X &255a 4c 8b 1c JMP &1c8b ; consider_slope_and_support ; update_dead_or_dying_mover # Called with object state &255d c9 ff CMP #&ff # &ff if mover has gone &255f f0 29 BEQ &258a ; consider_resurrecting_mover &2561 a9 ff LDA #&ff ; HORIZONTAL_NONE # &80 if mover is falling off screen &2563 85 70 STA &70 ; horizontal_direction &2565 a9 01 LDA #&01 ; VERTICAL_DOWN &2567 85 71 STA &71 ; vertical_direction &2569 bd 30 0c LDA &0c30,X ; objects_y &256c f0 03 BEQ &2571 ; remove_object # Has the mover reached the bottom of the screen? &256e a9 00 LDA #&00 # If not, leave with zero to indicate still on screen &2570 60 RTS ; remove_object &2571 a9 ff LDA #&ff # Set object state to &ff to indicate mover has gone &2573 95 00 STA &00,X ; objects_state &2575 20 98 21 JSR &2198 ; get_object_variables_for_object_X &2578 e6 73 INC &73 ; object_height # Unnecessary code; object_height reset at &22a7 &257a 20 9d 22 JSR &229d ; unplot_object &257d a6 64 LDX &64 ; object_to_update &257f a5 68 LDA &68 ; time_high # Note time of removal &2581 9d 18 0d STA &0d18,X ; objects_moving - &18 &2584 a2 88 LDX #&88 ; sound_6 # Silence channel 3 &2586 20 35 0a JSR &0a35 ; play_sound ; leave &2589 60 RTS # Leave with non-zero to indicate object removed ; consider_resurrecting_mover &258a a5 68 LDA &68 ; time_high &258c 38 SEC &258d fd 18 0d SBC &0d18,X ; objects_moving - &18 &2590 c9 02 CMP #&02 # Movers return after 257 to 512 frames &2592 b0 02 BCS &2596 ; initialise_mover_position &2594 90 f3 BCC &2589 ; leave ; initialise_mover_position &2596 a9 03 LDA #&03 # Mover returns facing right, frame 1 &2598 9d 18 0d STA &0d18,X ; objects_moving - &18 ; initialise_object_position &259b bd 10 0b LDA &0b10,X ; initial_objects_x_low # Return mover to initial position &259e 9d a0 0b STA &0ba0,X ; objects_x_low &25a1 bd 40 0b LDA &0b40,X ; initial_objects_x_high &25a4 9d e8 0b STA &0be8,X ; objects_x_high &25a7 bd 70 0b LDA &0b70,X ; initial_objects_y &25aa 9d 30 0c STA &0c30,X ; objects_y ; initialise_object_state &25ad bd 80 0e LDA &0e80,X ; initial_objects_state &25b0 95 00 STA &00,X ; objects_state &25b2 60 RTS ; check_if_object_X_is_supported &25b3 20 98 21 JSR &2198 ; get_object_variables_for_object_X &25b6 a9 01 LDA #&01 ; VERTICAL_DOWN &25b8 85 71 STA &71 ; vertical_direction &25ba a9 ff LDA #&ff ; HORIZONTAL_NONE &25bc 85 70 STA &70 ; horizontal_direction &25be 20 50 1c JSR &1c50 ; calculate_object_edges &25c1 20 5e 1b JSR &1b5e ; check_object_for_support_or_obstacle # Returns carry set if object is supported &25c4 60 RTS ; update_witch &25c5 a2 23 LDX #&23 ; OBJECT_WITCH &25c7 86 64 STX &64 ; object_to_update &25c9 a9 00 LDA #&00 # Witch is first moving object &25cb 85 65 STA &65 ; mover_offset &25cd a5 63 LDA &63 ; player_was_killed # Negative if player is alive &25cf 30 06 BMI &25d7 ; player_is_alive &25d1 20 02 2e JSR &2e02 ; set_screen_background_to_black &25d4 4c 5a 26 JMP &265a ; move_witch_towards_target ; player_is_alive &25d7 a5 23 LDA &23 ; objects_state + OBJECT_WITCH # Negative if witch is falling off screen or gone &25d9 30 36 BMI &2611 ; witch_is_dead_or_dying &25db a0 0c LDY #&0c ; OBJECT_WATER &25dd c4 54 CPY &54 ; object_being_dropped_or_thrown # Is the player throwing water? &25df d0 5a BNE &263b ; move_witch_towards_player &25e1 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &25e4 a5 70 LDA &70 ; horizontal_direction &25e6 29 02 AND #&02 &25e8 4a LSR A &25e9 a8 TAY # Y = 0 if water is left of witch, 1 if right &25ea a5 76 LDA &76 ; y # y is the vertical distance from witch to water &25ec c9 02 CMP #&02 &25ee 90 0c BCC &25fc ; skip_horizontal_check &25f0 c9 03 CMP #&03 &25f2 b0 47 BCS &263b ; move_witch_towards_player &25f4 a5 77 LDA &77 ; x_low # x_low is the horizontal distance from witch to water ; check_distance &25f6 c9 0c CMP #&0c # Is the water near the witch? &25f8 b0 41 BCS &263b ; move_witch_towards_player &25fa 90 1f BCC &261b ; change_witch_direction # If so, make the witch move away from the water ; skip_horizontal_check &25fc a5 71 LDA &71 ; vertical_direction &25fe c9 01 CMP #&01 ; VERTICAL_DOWN &2600 f0 f4 BEQ &25f6 ; check_distance &2602 a5 77 LDA &77 ; x_low &2604 d9 ed 09 CMP &09ed,Y ; witch_collision_sizes &2607 b0 ed BCS &25f6 ; check_distance &2609 a2 80 LDX #&80 ; sound_5 # Play sound for falling witch &260b 86 23 STX &23 ; objects_state + OBJECT_WITCH # Set witch state to &80 to make witch fall off screen &260d 20 35 0a JSR &0a35 ; play_sound ; leave &2610 60 RTS ; witch_is_dead_or_dying &2611 c9 ff CMP #&ff # &ff if witch has gone &2613 f0 fb BEQ &2610 ; leave &2615 20 5d 25 JSR &255d ; update_dead_or_dying_mover # Returns zero if witch still on screen &2618 f0 56 BEQ &2670 ; set_witch_sprite_and_update &261a 60 RTS ; change_witch_direction &261b a5 55 LDA &55 ; throw_direction &261d c9 02 CMP #&02 ; THROWING_UP &261f 10 0c BPL &262d ; vertical_throw ; horizontal_throw &2621 0a ASL A &2622 85 70 STA &70 ; horizontal_direction ; set_witch_moving_up &2624 a9 00 LDA #&00 ; VERTICAL_UP # Witch rises to avoid horizontally thrown water &2626 85 71 STA &71 ; vertical_direction &2628 20 48 24 JSR &2448 ; stop_mover_moving &262b 30 3c BMI &2669 ; move_witch # Always branches ; vertical_throw &262d a5 70 LDA &70 ; horizontal_direction &262f 10 02 BPL &2633 ; skip_set &2631 a9 00 LDA #&00 ; HORIZONTAL_LEFT ; skip_set &2633 49 02 EOR #&02 ; HORIZONTAL_RIGHT # Flip horizontal direction to avoid vertical water &2635 85 70 STA &70 ; horizontal_direction &2637 a5 55 LDA &55 ; throw_direction &2639 d0 e9 BNE &2624 ; set_witch_moving_up # Always branches ; move_witch_towards_player &263b a0 2f LDY #&2f ; OBJECT_PLAYER &263d 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2640 a5 77 LDA &77 ; x_low # x_low is the horizontal distance from witch to player &2642 c9 40 CMP #&40 &2644 b0 14 BCS &265a ; move_witch_towards_target &2646 c9 0a CMP #&0a &2648 b0 1a BCS &2664 ; move_witch_with_sound &264a a5 76 LDA &76 ; y # y is the vertical distance from witch to player &264c c9 04 CMP #&04 &264e b0 14 BCS &2664 ; move_witch_with_sound &2650 a9 08 LDA #&08 ; KILLED_BY_WITCH # Kill the player if the witch is too close &2652 85 63 STA &63 ; player_was_killed &2654 20 48 24 JSR &2448 ; stop_mover_moving &2657 4c 09 2e JMP &2e09 ; set_screen_background_to_white ; move_witch_towards_target &265a a2 23 LDX #&23 ; OBJECT_WITCH &265c a0 14 LDY #&14 ; OBJECT_WITCH_TARGET &265e 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2661 4c 69 26 JMP &2669 ; move_witch ; move_witch_with_sound &2664 a2 78 LDX #&78 ; sound_4 # Play sound for moving witch &2666 20 35 0a JSR &0a35 ; play_sound ; move_witch &2669 a2 23 LDX #&23 ; OBJECT_WITCH &266b 20 c4 24 JSR &24c4 ; move_witch &266e b0 a0 BCS &2610 ; leave ; set_witch_sprite_and_update &2670 20 0b 17 JSR &170b ; calculate_sprite_from_direction &2673 18 CLC &2674 69 12 ADC #&12 ; SPRITE_WITCH &2676 85 7f STA &7f ; object_sprite &2678 4c cc 2c JMP &2ccc ; add_active_mover ; update_monkeys_and_spiders &267b a9 03 LDA #&03 # Four monkeys &267d 85 65 STA &65 ; mover_offset &267f a2 29 LDX #&29 ; OBJECT_LAST_MONKEY &2681 86 64 STX &64 ; object_to_update ; update_monkeys_loop # For each monkey, &2683 20 c0 00 JSR &00c0 ; check_if_mover_should_be_updated # Should this monkey be updated this frame? &2686 d0 70 BNE &26f8 ; consider_next_monkey &2688 a0 08 LDY #&08 ; OBJECT_LAST_TORCH ; update_monkeys_torch_loop # For each torch, &268a b9 00 00 LDA &0000,Y ; objects_state &268d c9 06 CMP #&06 ; OBJECT_STATE_IN_POCKET # Is the torch in a pocket? If not, &268f f0 30 BEQ &26c1 ; consider_next_monkey &2691 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2694 a6 65 LDX &65 ; mover_offset &2696 a5 77 LDA &77 ; x_low # x_low is the horizontal distance from monkey to torch &2698 c9 04 CMP #&04 &269a b0 25 BCS &26c1 ; consider_next_torch &269c a5 76 LDA &76 ; y &269e c9 03 CMP #&03 # y is the vertical distance from monkey to torch &26a0 10 1f BPL &26c1 ; consider_next_torch &26a2 c9 02 CMP #&02 &26a4 30 08 BMI &26ae ; turn_monkey_horizontally # If the monkey isn't level with the torch, &26a6 a5 71 LDA &71 ; vertical_direction &26a8 49 01 EOR #&01 # Make monkey move away from torch vertically &26aa 95 40 STA &40,X ; movers_vertical_direction &26ac 10 1a BPL &26c8 ; update_monkey # Always branches ; turn_monkey_horizontally &26ae a5 70 LDA &70 ; horizontal_direction &26b0 49 02 EOR #&02 # Make monkey move away from torch horizontally &26b2 95 38 STA &38,X ; movers_horizontal_direction &26b4 bd 56 0c LDA &0c56,X ; objects_y + OBJECT_FIRST_MONKEY &26b7 c9 04 CMP #&04 # Has the monkey reached the floor? &26b9 d0 0d BNE &26c8 ; update_monkey &26bb a9 12 LDA #&12 ; OBJECT_TOP_MONKEY_TARGET # If so, set monkey moving towards top target &26bd 95 26 STA &26,X ; objects_state + OBJECTS_FIRST_MONKEY &26bf d0 07 BNE &26c8 ; update_monkey # Always branches ; consider_next_torch &26c1 a6 64 LDX &64 ; object_to_update &26c3 88 DEY &26c4 c0 04 CPY #&04 ; OBJECT_FIRST_TORCH - 1 &26c6 d0 c2 BNE &268a ; update_monkeys_torch_loop ; update_monkey &26c8 a6 64 LDX &64 ; object_to_update &26ca b4 00 LDY &00,X ; objects_state # Negative if monkey was eaten by spider &26cc 10 06 BPL &26d4 ; move_monkey_towards_target # Otherwise, Y is monkey target &26ce 20 8a 25 JSR &258a ; consider_resurrecting_mover &26d1 4c f8 26 JMP &26f8 ; consider_next_monkey ; move_monkey_towards_target &26d4 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &26d7 a5 77 LDA &77 ; x_low # Is the monkey at its target? &26d9 d0 0f BNE &26ea ; not_at_target &26db a5 76 LDA &76 ; y &26dd d0 0b BNE &26ea ; not_at_target &26df 20 48 24 JSR &2448 ; stop_mover_moving &26e2 b5 00 LDA &00,X ; objects_state &26e4 49 01 EOR #&01 # If so, make monkey move towards other target &26e6 95 00 STA &00,X ; objects_state &26e8 d0 0e BNE &26f8 ; consider_next_monkey # Always branches ; not_at_target &26ea 20 4e 24 JSR &244e ; move_mover &26ed 20 0b 17 JSR &170b ; calculate_sprite_from_direction &26f0 18 CLC &26f1 69 16 ADC #&16 ; SPRITE_MONKEY &26f3 85 7f STA &7f ; object_sprite &26f5 20 cc 2c JSR &2ccc ; add_active_mover ; consider_next_monkey &26f8 c6 64 DEC &64 ; object_to_update &26fa a6 64 LDX &64 ; object_to_update &26fc c6 65 DEC &65 ; mover_offset &26fe 30 03 BMI &2703 ; update_spiders &2700 4c 83 26 JMP &2683 ; update_monkeys_loop ; update_spiders &2703 a2 25 LDX #&25 ; OBJECT_LAST_SPIDER &2705 86 64 STX &64 ; object_to_update ; update_spiders_loop # For each spider, &2707 a9 ff LDA #&ff &2709 85 70 STA &70 ; horizontal_direction &270b b5 00 LDA &00,X ; objects_state # State is &80 if spider is invisible and waiting &270d 30 22 BMI &2731 ; consider_dropping_spider # State is &ff if spider is visible and waiting &270f d0 5d BNE &276e ; check_for_spider_killing # State is object if spider is targeting object &2711 bd 30 0c LDA &0c30,X ; objects_y # State is &00 if spider is returning to ceiling &2714 c9 16 CMP #&16 &2716 f0 14 BEQ &272c ; set_spider_waiting # Has the spider reached the ceiling? &2718 a9 00 LDA #&00 ; VERTICAL_UP ; set_spider_vertical_direction &271a 85 71 STA &71 ; vertical_direction # If not, make the spider move up &271c a9 1c LDA #&1c ; SPRITE_SPIDER &271e 85 7f STA &7f ; object_sprite &2720 20 cc 2c JSR &2ccc ; add_active_mover ; consider_next_spider &2723 c6 64 DEC &64 ; object_to_update &2725 a6 64 LDX &64 ; object_to_update &2727 e0 23 CPX #&23 ; OBJECT_FIRST_SPIDER - 1 &2729 d0 dc BNE &2707 ; update_spiders_loop &272b 60 RTS ; set_spider_waiting &272c a9 ff LDA #&ff # Set to &ff to indicate spider is visible and waiting &272e 95 00 STA &00,X ; objects_state &2730 60 RTS ; consider_dropping_spider &2731 a5 63 LDA &63 ; player_was_killed # Positive if player was killed &2733 10 0c BPL &2741 ; skip_player &2735 bc cb 09 LDY &09cb,X ; spider_targets - OBJECT_FIRST_SPIDER &2738 a2 2f LDX #&2f ; OBJECT_PLAYER # Is the player under the spider? &273a 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &273d a5 77 LDA &77 ; x_low &273f f0 1f BEQ &2760 ; target_object # If so, set the spider falling on the player ; skip_player &2741 a2 29 LDX #&29 ; OBJECT_LAST_MONKEY # For each monkey, ; consider_dropping_spider_on_monkeys_loop &2743 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2746 a5 77 LDA &77 ; x_low # Is the monkey under the spider? &2748 f0 16 BEQ &2760 ; target_object # If so, set the spider falling on the monkey &274a ca DEX &274b e0 25 CPX #&25 ; OBJECT_FIRST_MONKEY - 1 &274d d0 f4 BNE &2743 ; consider_dropping_spider_on_monkeys_loop &274f a6 64 LDX &64 ; object_to_update # X is spider &2751 20 c0 00 JSR &00c0 ; check_if_mover_should_be_updated &2754 d0 cd BNE &2723 ; consider_next_spider # Should the spider be updated now? &2756 b5 00 LDA &00,X ; objects_state &2758 85 70 STA &70 ; horizontal_direction # Stop spider moving horizontally if waiting &275a c9 ff CMP #&ff &275c d0 c5 BNE &2723 ; consider_next_spider &275e f0 ba BEQ &271a ; set_spider_vertical_direction # Always branches; set spider moving up ; target_object &2760 8a TXA &2761 a4 64 LDY &64 ; object_to_update &2763 99 00 00 STA &0000,Y ; objects_state # Set the spider's state to be the target object &2766 a2 80 LDX #&80 ; sound_5 # Play a sound for dropping spider &2768 20 35 0a JSR &0a35 ; play_sound &276b 4c 23 27 JMP &2723 ; consider_next_spider ; check_for_spider_killing &276e bd 30 0c LDA &0c30,X ; objects_y &2771 c9 08 CMP #&08 # Has the spider reached the floor? &2773 f0 19 BEQ &278e ; spider_killed_object &2775 b4 00 LDY &00,X ; objects_state # If not, move spider towards target &2777 fe a0 0b INC &0ba0,X ; objects_x_low # Temporarily use middle of spider for targeting &277a 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &277d de a0 0b DEC &0ba0,X ; objects_x_low # Revert temporary change &2780 a9 80 LDA #&80 ; VERTICAL_DOWN_DOUBLE # Revert temporary change &2782 85 71 STA &71 ; vertical_direction &2784 a9 1c LDA #&1c ; SPRITE_SPIDER &2786 85 7f STA &7f ; object_sprite &2788 20 cc 2c JSR &2ccc ; add_active_mover &278b 4c 23 27 JMP &2723 ; consider_next_spider ; spider_killed_object # When the spider reaches the floor, &278e b4 00 LDY &00,X ; objects_state &2790 c0 2f CPY #&2f ; OBJECT_PLAYER &2792 f0 1b BEQ &27af ; spider_killed_player # If the player was the target, kill the player &2794 a9 ff LDA #&ff &2796 99 00 00 STA &0000,Y ; objects_state # Otherwise, set monkey state to &ff to remove monkey &2799 a5 68 LDA &68 ; time_high &279b 99 18 0d STA &0d18,Y ; objects_moving - &18 # Note time monkey was eaten ; zero_spider_state &279e a9 00 LDA #&00 # Set state to &00 to set spider returning to ceiling &27a0 95 00 STA &00,X ; objects_state &27a2 a2 88 LDX #&88 ; sound_6 # Silence channel 3 &27a4 20 35 0a JSR &0a35 ; play_sound &27a7 a2 90 LDX #&90 ; sound_7 # Play sound for spider killing target &27a9 20 35 0a JSR &0a35 ; play_sound &27ac 4c 23 27 JMP &2723 ; consider_next_spider ; spider_killed_player &27af a9 07 LDA #&07 ; KILLED_BY_SPIDER # Indicate player was killed by spider &27b1 85 63 STA &63 ; player_was_killed &27b3 d0 e9 BNE &279e ; zero_spider_state # Always branches; set spider returning to ceiling ; update_dead_or_stunned_player # Called with A = player_was_killed &27b5 d0 37 BNE &27ee ; update_dying_player_if_supported # Zero if PLAYER_UNCONSCIOUS, non-zero if really dead &27b7 a5 5d LDA &5d ; prison_escort_state &27b9 30 03 BMI &27be ; not_in_prison_or_being_escorted # &80 ESCORT_IN_PRISON or &ff ESCORT_OUT_OF_PRISON &27bb 4c cd 28 JMP &28cd ; update_prison_guards_while_escorting ; not_in_prison_or_being_escorted &27be a9 01 LDA #&01 ; VERTICAL_DOWN &27c0 85 71 STA &71 ; vertical_direction &27c2 a9 ff LDA #&ff ; HORIZONTAL_NONE &27c4 85 70 STA &70 ; horizontal_direction &27c6 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object hit obstacle &27c9 b0 05 BCS &27d0 ; hit_obstacle &27cb e6 6c INC &6c ; distance_fallen # Make player fall until supported &27cd 4c e8 16 JMP &16e8 ; keep_player_on_screen ; hit_obstacle &27d0 a5 6c LDA &6c ; distance_fallen &27d2 30 09 BMI &27dd ; not_fallen_too_far &27d4 c9 0e CMP #&0e &27d6 90 05 BCC &27dd ; not_fallen_too_far &27d8 a9 02 LDA #&02 ; KILLED_BY_FALLING # Kill player if fallen too far when stunned &27da 85 63 STA &63 ; player_was_killed &27dc 60 RTS ; not_fallen_too_far &27dd a9 ff LDA #&ff &27df 85 6c STA &6c ; distance_fallen &27e1 a5 5d LDA &5d ; prison_escort_state &27e3 c9 80 CMP #&80 ; ESCORT_IN_PRISON # Is the player in the prison? &27e5 d0 5d BNE &2844 ; not_in_prison ; in_prison &27e7 a9 01 LDA #&01 ; KILLED_UNCONSCIOUS_IN_PRISON &27e9 85 63 STA &63 ; player_was_killed &27eb 4c 6b 29 JMP &296b ; stop_all_movers_moving ; update_dying_player_if_supported &27ee 20 b3 25 JSR &25b3 ; check_if_object_X_is_supported # Returns carry set if player is supported &27f1 b0 5a BCS &284d ; update_dying_player &27f3 4c e8 16 JMP &16e8 ; keep_player_on_screen ; start_escort_of_stunned_player &27f6 a2 1d LDX #&1d ; OBJECT_SECOND_PRISON_GUARD &27f8 20 96 25 JSR &2596 ; initialise_mover_position # Put the second prison guard in the prison door &27fb a2 1c LDX #&1c ; OBJECT_FIRST_PRISON_GUARD &27fd a5 1c LDA &1c ; objects_state + OBJECT_FIRST_PRISON_GUARD # Positive if first prison guard is already present &27ff 10 03 BPL &2804 ; skip_initialising_first_guard &2801 20 96 25 JSR &2596 ; initialise_mover_position # Put the first prison guard in the prison passage ; skip_initialising_first_guard &2804 a2 2f LDX #&2f ; OBJECT_PLAYER &2806 a9 00 LDA #&00 ; ESCORT_WAITING_FOR_FIRST_GUARD # Set to &00 to indicate player is unconscious, &2808 85 5d STA &5d ; prison_escort_state # first escort guard hasn't arrived at escort target &280a 85 99 STA &99 ; selected_pocket # Set to &00 to delay emptying pockets until near prison &280c ad cf 0b LDA &0bcf ; objects_x_low + OBJECT_PLAYER &280f 38 SEC &2810 e9 06 SBC #&06 # Left of player &2812 8d e4 0b STA &0be4 ; objects_x_low + OBJECT_LEFT_ESCORT_TARGET &2815 ad 17 0c LDA &0c17 ; objects_x_high + OBJECT_PLAYER &2818 e9 00 SBC #&00 &281a 8d 2c 0c STA &0c2c ; objects_x_high + OBJECT_LEFT_ESCORT_TARGET &281d ad cf 0b LDA &0bcf ; objects_x_low + OBJECT_PLAYER &2820 18 CLC &2821 69 06 ADC #&06 # Right of player &2823 8d e5 0b STA &0be5 ; objects_x_low + OBJECT_RIGHT_ESCORT_TARGET &2826 ad 17 0c LDA &0c17 ; objects_x_high + OBJECT_PLAYER &2829 69 00 ADC #&00 &282b 8d 2d 0c STA &0c2d ; objects_x_high + OBJECT_RIGHT_ESCORT_TARGET &282e ad 5f 0c LDA &0c5f ; objects_y + OBJECT_PLAYER &2831 8d 74 0c STA &0c74 ; objects_y + OBJECT_LEFT_ESCORT_TARGET &2834 8d 75 0c STA &0c75 ; objects_y + OBJECT_RIGHT_ESCORT_TARGET &2837 20 6b 29 JSR &296b ; stop_all_movers_moving &283a a9 45 LDA #&45 ; OBJECT_RIGHT_ESCORT_TARGET # Second guard goes to right of player &283c 85 1d STA &1d ; objects_state + OBJECT_SECOND_PRISON_GUARD &283e a9 44 LDA #&44 ; OBJECT_LEFT_ESCORT_TARGET # First guard goes to left of player &2840 85 1c STA &1c ; objects_state + OBJECT_FIRST_PRISON_GUARD &2842 10 aa BPL &27ee ; update_dying_player_if_supported # Always branches ; not_in_prison &2844 a5 47 LDA &47 ; starvation_timer_high # Has the player already been in prison? &2846 30 ae BMI &27f6 ; start_escort_of_stunned_player &2848 a9 05 LDA #&05 ; KILLED_ARE_DEAD # If so, kill the player if touching a guard &284a 85 63 STA &63 ; player_was_killed &284c 60 RTS ; update_dying_player &284d a4 75 LDY &75 ; death_timer # Zero if player has just died or been stunned &284f d0 08 BNE &2859 ; skip_sound_and_drop &2851 a2 90 LDX #&90 ; sound_7 # Play sound for player dying &2853 20 35 0a JSR &0a35 ; play_sound &2856 20 77 29 JSR &2977 ; make_player_drop_carried_object ; skip_sound_and_drop &2859 a4 75 LDY &75 ; death_timer &285b e6 75 INC &75 ; death_timer &285d a5 5d LDA &5d ; prison_escort_state # Zero if unconscious player waiting for first guard &285f f0 2d BEQ &288e ; skip_death_animation &2861 a5 63 LDA &63 ; player_was_killed &2863 c9 01 CMP #&01 ; KILLED_UNCONSCIOUS_IN_PRISON &2865 d0 06 BNE &286d ; not_unconscious &2867 c0 60 CPY #&60 &2869 f0 4b BEQ &28b6 ; regain_consciousness_in_prison &286b d0 21 BNE &288e ; skip_death_animation ; not_unconscious &286d 98 TYA &286e c9 20 CMP #&20 &2870 f0 1f BEQ &2891 ; use_dead_player &2872 10 37 BPL &28ab ; update_dead_player_object &2874 29 03 AND #&03 &2876 d0 0d BNE &2885 ; skip_dying_sound &2878 ad 74 09 LDA &0974 ; sound_3 + 4 &287b 69 02 ADC #&02 # Increase pitch &287d 8d 74 09 STA &0974 ; sound_3 + 4 &2880 a2 70 LDX #&70 ; sound_3 # Play sound for dying player &2882 20 35 0a JSR &0a35 ; play_sound ; skip_dying_sound &2885 a5 75 LDA &75 ; death_timer &2887 29 04 AND #&04 # Flip direction of dying player every four frames &2889 4a LSR A &288a 85 7f STA &7f ; object_sprite &288c 10 1f BPL &28ad ; update_player_object ; skip_death_animation &288e 98 TYA &288f d0 1a BNE &28ab ; update_dead_player_object ; use_dead_player &2891 20 98 21 JSR &2198 ; get_object_variables_for_object_X &2894 a5 77 LDA &77 ; x_low &2896 8d b7 0b STA &0bb7 ; objects_x + OBJECT_DEAD_PLAYER &2899 a5 78 LDA &78 ; x_high &289b 8d ff 0b STA &0bff ; objects_x_high + OBJECT_DEAD_PLAYER &289e a5 76 LDA &76 ; y &28a0 8d 47 0c STA &0c47 ; objects_y + OBJECT_DEAD_PLAYER &28a3 a9 64 LDA #&64 &28a5 8d 74 09 STA &0974 ; sound_3 + 4 # Restore pitch &28a8 20 9d 22 JSR &229d ; unplot_object # Unplot dying player ; update_dead_player_object &28ab a2 17 LDX #&17 ; OBJECT_DEAD_PLAYER ; update_player_object &28ad a9 ff LDA #&ff ; HORIZONTAL_AND_VERTICAL_NONE &28af 85 70 STA &70 ; horizontal_direction &28b1 85 71 STA &71 ; vertical_direction &28b3 4c cc 2c JMP &2ccc ; add_active_mover # Replace with dead player ; regain_consciousness_in_prison &28b6 a0 17 LDY #&17 ; OBJECT_DEAD_PLAYER &28b8 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &28bb 20 9d 22 JSR &229d ; unplot_object # Unplot stunned player &28be a9 00 LDA #&00 # Set to positive to indicate not end of life or game &28c0 85 75 STA &75 ; death_timer &28c2 a9 ff LDA #&ff # Set to negative to indicate player hasn't been killed &28c4 85 63 STA &63 ; player_was_killed &28c6 a9 02 LDA #&02 ; HORIZONTAL_RIGHT &28c8 85 70 STA &70 ; horizontal_direction &28ca 4c d9 17 JMP &17d9 ; start_jump ; update_prison_guards_while_escorting &28cd a5 99 LDA &99 ; selected_pocket # Zero if player has yet to reach prison passage &28cf f0 15 BEQ &28e6 ; skip_emptying_pockets # or pockets have already been emptied &28d1 a5 54 LDA &54 ; object_being_dropped_or_thrown &28d3 10 11 BPL &28e6 ; skip_emptying_pockets # Don't empty next pocket while previous being dropped &28d5 c6 99 DEC &99 ; selected_pocket &28d7 20 89 2f JSR &2f89 ; retrieve_object # Retrieve the contents of the next pocket &28da a4 9c LDY &9c ; carrying &28dc 30 08 BMI &28e6 ; skip_emptying_pockets # If the pocket contained an object, &28de a2 2f LDX #&2f ; OBJECT_PLAYER &28e0 20 d4 2e JSR &2ed4 ; offset_and_update_carried_object &28e3 20 77 29 JSR &2977 ; make_player_drop_carried_object # drop it ; skip_emptying_pockets &28e6 a9 05 LDA #&05 # For each of the prison guards, &28e8 85 65 STA &65 ; mover_offset &28ea a2 1d LDX #&1d ; OBJECT_SECOND_PRISON_GUARD ; update_prison_guards_loop &28ec 86 64 STX &64 ; object_to_update &28ee b4 00 LDY &00,X ; objects_state # Prison guard state is target, or &ff if waiting &28f0 30 19 BMI &290b ; skip_updating_prison_guard &28f2 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &28f5 a5 77 LDA &77 ; x_low # x_low is the horizontal distance from guard to target &28f7 d0 08 BNE &2901 ; not_at_target # If the guard is at the escort target, &28f9 e6 5d INC &5d ; prison_escort_state # move to next stage of escort &28fb a9 ff LDA #&ff &28fd 95 00 STA &00,X ; objects_state # Set prison guard state to &ff to indicate waiting &28ff 30 0a BMI &290b ; skip_updating_prison_guard ; not_at_target &2901 a9 01 LDA #&01 ; VERTICAL_DOWN # Encourage guard down slope &2903 85 71 STA &71 ; vertical_direction &2905 20 4e 24 JSR &244e ; move_mover # Move prison guard towards target &2908 20 18 1a JSR &1a18 ; animate_guard ; skip_updating_prison_guard &290b c6 65 DEC &65 ; mover_offset &290d a6 64 LDX &64 ; object_to_update &290f ca DEX &2910 e0 1b CPX #&1b ; OBJECT_FIRST_PRISON_GUARD - 1 &2912 d0 d8 BNE &28ec ; update_prison_guards_loop &2914 a5 5d LDA &5d ; prison_escort_state &2916 c9 02 CMP #&02 ; ESCORT_BOTH_GUARDS_IN_POSITION &2918 30 91 BMI &28ab ; update_dead_player_object # Player remains dead until both guards are in position &291a d0 13 BNE &292f ; both_guards_escorting &291c a0 17 LDY #&17 ; OBJECT_DEAD_PLAYER &291e 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2921 20 9d 22 JSR &229d ; unplot_object # Unplot dead player &2924 a9 46 LDA #&46 ; OBJECT_PRISON_GUARD_PASSAGE_TARGET # Set escorts moving back towards prison passage ; set_guard_targets &2926 85 1d STA &1d ; objects_state + OBJECT_SECOND_PRISON_GUARD &2928 85 1c STA &1c ; objects_state + OBJECT_FIRST_PRISON_GUARD &292a e6 5d INC &5d ; prison_escort_state # State 2 becomes 3, 3 becomes 4, 4 becomes 5 &292c 4c 6b 29 JMP &296b ; stop_all_movers_moving ; both_guards_escorting &292f c9 04 CMP #&04 ; ESCORT_RETURNING_AT_OBJECT_DROP_POINT &2931 d0 06 BNE &2939 ; not_at_drop_point ; at_drop_point &2933 85 99 STA &99 ; selected_pocket # Set to non-zero to start emptying pockets &2935 a9 47 LDA #&47 ; OBJECT_PRISON_GUARD_PRISON_TARGET &2937 d0 ed BNE &2926 ; set_guard_targets # Always branches; set guards moving into prison cell ; not_at_drop_point &2939 c9 06 CMP #&06 ; ESCORT_ARRIVED_IN_PRISON &293b d0 1d BNE &295a ; not_at_final_destination ; at_final_destination &293d a9 01 LDA #&01 ; KILLED_UNCONSCIOUS_IN_PRISON # Stun the player in the prison cell &293f 85 63 STA &63 ; player_was_killed &2941 a9 00 LDA #&00 # Start timer to awaken in prison &2943 85 75 STA &75 ; death_timer &2945 a9 18 LDA #&18 # Player is starting to become hungry &2947 85 47 STA &47 ; starvation_timer_high # (also indicates player has been stunned once) &2949 a2 1c LDX #&1c ; OBJECT_FIRST_PRISON_GUARD &294b 20 ad 25 JSR &25ad ; initialise_object_state # Return first guard to prison passage &294e a2 1d LDX #&1d ; OBJECT_SECOND_PRISON_GUARD &2950 20 ad 25 JSR &25ad ; initialise_object_state # Return second guard to prison door &2953 a9 80 LDA #&80 ; ESCORT_IN_PRISON &2955 85 5d STA &5d ; prison_escort_state &2957 4c 6b 29 JMP &296b ; stop_all_movers_moving ; not_at_final_destination &295a a4 1d LDY &1d ; objects_state + OBJECT_SECOND_PRISON_GUARD &295c a2 2f LDX #&2f ; OBJECT_PLAYER &295e 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2961 a9 ff LDA #&ff ; VERTICAL_NONE &2963 85 71 STA &71 ; vertical_direction &2965 20 4e 24 JSR &244e ; move_mover # Move second guard towards player &2968 4c 1f 18 JMP &181f ; update_walking_player ; stop_all_movers_moving &296b a9 05 LDA #&05 &296d 85 65 STA &65 ; mover_offset ; stop_all_movers_moving_loop &296f 20 48 24 JSR &2448 ; stop_mover_moving &2972 c6 65 DEC &65 ; mover_offset &2974 10 f9 BPL &296f ; stop_all_movers_moving_loop &2976 60 RTS ; make_player_drop_carried_object &2977 a2 2f LDX #&2f ; OBJECT_PLAYER &2979 a4 9c LDY &9c ; carrying # Is the player carrying an object? &297b 30 13 BMI &2990 ; leave &297d 84 54 STY &54 ; object_being_dropped_or_thrown &297f a9 00 LDA #&00 &2981 85 56 STA &56 ; throw_or_drop_timer &2983 a9 0e LDA #&0e ; OBJECT_STATE_THROWN # If so, make the player drop the object &2985 99 00 00 STA &0000,Y ; objects_state &2988 a9 ff LDA #&ff &298a 85 9c STA &9c ; carrying &298c a9 03 LDA #&03 ; THROWING_DOWN &298e 85 55 STA &55 ; throw_direction ; leave &2990 60 RTS ; end_of_life_or_game # Called with A = death_timer &2991 c9 ff CMP #&ff # &ff if treasure found, &80 if player died &2993 f0 78 BEQ &2a0d ; consider_bonus_items # Add bonus items to score if treasure was found &2995 c6 46 DEC &46 ; lives &2997 d0 03 BNE &299c ; end_of_life # Does the player have lives remaining? &2999 4c 34 2a JMP &2a34 ; game_over_screen # If not, game over ; end_of_life &299c 20 7b 2a JSR &2a7b ; write_death_text_and_delay # Otherwise, display cause of death &299f a2 0b LDX #&0b ; OBJECT_BUCKET ; restore_objects_loop # Restore object positions from last save &29a1 a5 37 LDA &37 ; saved_bucket_contains_water &29a3 85 35 STA &35 ; bucket_contains_water &29a5 bd 24 0d LDA &0d24,X ; saved_objects_x_low &29a8 9d a0 0b STA &0ba0,X ; objects_x_low &29ab bd f8 0c LDA &0cf8,X ; saved_objects_x_high &29ae 9d e8 0b STA &0be8,X ; objects_x_high &29b1 bd 04 0d LDA &0d04,X ; save_objects_y &29b4 9d 30 0c STA &0c30,X ; objects_y &29b7 a9 04 LDA #&04 ; OBJECT_STATE_IN_WORLD &29b9 95 00 STA &00,X ; objects_state &29bb ca DEX &29bc 10 e3 BPL &29a1 ; restore_objects_loop &29be a2 03 LDX #&03 ; restore_pockets_loop # Restore pocket contents from last save &29c0 bc f1 09 LDY &09f1,X ; saved_pockets &29c3 98 TYA &29c4 9d c0 09 STA &09c0,X ; pockets &29c7 30 05 BMI &29ce ; is_empty &29c9 a9 06 LDA #&06 ; OBJECT_STATE_IN_POCKET &29cb 99 00 00 STA &0000,Y ; objects_state ; is_empty &29ce ca DEX &29cf 10 ef BPL &29c0 ; restore_pockets_loop &29d1 a4 14 LDY &14 ; saved_carrying # Restore carried object from last save &29d3 84 9c STY &9c ; carrying &29d5 a9 02 LDA #&02 ; OBJECT_STATE_CARRYING_TO_RIGHT &29d7 99 00 00 STA &0000,Y ; objects_state &29da a6 89 LDX &89 ; saved_level # Use level of last save ; restart_level # (unless starting new game; called with X = 3) &29dc a9 ff LDA #&ff &29de 85 63 STA &63 ; player_was_killed # Set to negative to indicate player hasn't been killed &29e0 85 5d STA &5d ; prison_escort_state # Set to ESCORT_OUT_OF_PRISON, player not in prison &29e2 85 47 STA &47 ; starvation_timer_high # Set to &ff to indicate player isn't becoming hungry &29e4 85 6c STA &6c ; distance_fallen &29e6 85 53 STA &53 ; player_is_jumping_or_falling # Set to negative to indicate player is supported &29e8 a9 00 LDA #&00 &29ea 85 75 STA &75 ; death_timer # Set to positive to indicate not end of life or game &29ec 85 9e STA &9e ; player_facing # Set player facing left &29ee 8d 47 0d STA &0d47 ; objects_moving - &18 + OBJECT_PLAYER # Use left sprite frame 1 &29f1 bd ff 09 LDA &09ff,X ; level_save_positions_y # Restore player position from last save &29f4 8d 5f 0c STA &0c5f ; objects_y + OBJECT_PLAYER &29f7 bd f6 09 LDA &09f6,X ; level_save_positions_x_low &29fa 8d cf 0b STA &0bcf ; objects_x_low + OBJECT_PLAYER &29fd 38 SEC &29fe e9 78 SBC #&78 # Put player in middle of screen &2a00 85 85 STA &85 ; screen_start_x_low &2a02 8a TXA &2a03 8d 17 0c STA &0c17 ; objects_x_high + OBJECT_PLAYER &2a06 e9 00 SBC #&00 &2a08 85 86 STA &86 ; screen_start_x_high &2a0a 4c 31 15 JMP &1531 ; play_game ; consider_bonus_items &2a0d a0 03 LDY #&03 # For each pocket, ; count_bonus_items_loop &2a0f be c0 09 LDX &09c0,Y ; pockets &2a12 ca DEX &2a13 ca DEX &2a14 e0 03 CPX #&03 ; OBJECT_GOLD + 2 - 1 # Does it contain coin, ruby or gold? &2a16 b0 02 BCS &2a1a ; not_bonus_item &2a18 e6 57 INC &57 ; score # If so, increase score by 10 points ; not_bonus_item &2a1a 88 DEY &2a1b 10 f2 BPL &2a0f ; count_bonus_items_loop &2a1d 18 CLC &2a1e a5 57 LDA &57 ; score &2a20 65 69 ADC &69 ; time_bonus # Add 10 points for every 256 frames of time remaining &2a22 65 46 ADC &46 ; lives # Add 10 points for every life remaining &2a24 85 57 STA &57 ; score &2a26 d0 0c BNE &2a34 ; game_over_screen # Always branches ; write_number_times_ten &2a28 20 2f 2a JSR &2a2f ; write_low_nibble_as_number &2a2b a0 0a LDY #&0a # Unnecessary code &2a2d a9 00 LDA #&00 ; write_low_nibble_as_number &2a2f 29 0f AND #&0f &2a31 4c fa 2f JMP &2ffa ; write_number ; game_over_screen &2a34 20 7b 2a JSR &2a7b ; write_death_text_and_delay ; wait_for_space &2a37 a5 ec LDA &ec ; os_most_recently_pressed_key &2a39 c9 e2 CMP #&e2 ; SPACE &2a3b d0 fa BNE &2a37 ; wait_for_space ; start_game &2a3d a9 04 LDA #&04 # Player starts with four lives &2a3f 85 46 STA &46 ; lives &2a41 a2 08 LDX #&08 ; reset_level_save_positions_used_loop &2a43 a9 00 LDA #&00 &2a45 85 35 STA &35 ; bucket_contains_water # Set to zero to indicate bucket is empty &2a47 9d 08 0a STA &0a08,X ; level_save_positions_used # Set to zero to indicate save position not used &2a4a ca DEX &2a4b 10 f6 BPL &2a43 ; reset_level_save_positions_used_loop &2a4d a2 03 LDX #&03 &2a4f a9 ff LDA #&ff ; OBJECT_EMPTY ; empty_pockets_loop &2a51 9d c0 09 STA &09c0,X ; pockets # Player starts with empty pockets &2a54 ca DEX &2a55 10 fa BPL &2a51 ; empty_pockets_loop &2a57 85 9c STA &9c ; carrying # Player starts carrying nothing &2a59 85 57 STA &57 ; score # Player will start with zero score (increased by save) &2a5b a9 e8 LDA #&e8 &2a5d 85 69 STA &69 ; time_bonus # Time bonus starts at 2320 points &2a5f ea NOP &2a60 a2 2f LDX #&2f ; OBJECT_PLAYER ; initialise_movers_loop &2a62 20 96 25 JSR &2596 ; initialise_mover_position # Reset all movers to initial positions &2a65 ca DEX &2a66 e0 18 CPX #&18 &2a68 10 f8 BPL &2a62 ; initialise_movers_loop &2a6a a2 0b LDX #&0b ; OBJECT_BUCKET ; initialise_objects_loop &2a6c 20 9b 25 JSR &259b ; initialise_object_position # Reset all objects to initial positions &2a6f a9 04 LDA #&04 ; OBJECT_STATE_IN_WORLD &2a71 95 00 STA &00,X ; objects_state &2a73 ca DEX &2a74 10 f6 BPL &2a6c ; initialise_objects_loop &2a76 a2 03 LDX #&03 # Player starts on level 3 &2a78 4c dc 29 JMP &29dc ; restart_level ; write_death_text_and_delay &2a7b 20 8c 2a JSR &2a8c ; write_death_text &2a7e a9 80 LDA #&80 # Wait 128 frames &2a80 85 72 STA &72 ; count ; delay_loop &2a82 a9 13 LDA #&13 ; Wait for Vertical Retrace &2a84 20 f4 ff JSR &fff4 ; OSBYTE &2a87 c6 72 DEC &72 ; count &2a89 d0 f7 BNE &2a82 ; delay_loop &2a8b 60 RTS ; write_death_text &2a8c 20 f2 1e JSR &1ef2 ; display_score_information &2a8f a2 02 LDX #&02 ; &2e0 * 8 = &1700 # TAB(&05, &09) &2a91 a0 e0 LDY #&e0 &2a93 20 a4 1e JSR &1ea4 ; set_cursor_position &2a96 a5 75 LDA &75 ; death_timer &2a98 c9 ff CMP #&ff # &ff if treasure found &2a9a f0 64 BEQ &2b00 ; write_treasure_found_text &2a9c a4 63 LDY &63 ; player_was_killed &2a9e c0 06 CPY #&06 ; KILLED_BY_TROLL # Was the player killed by an enemy? If not, &2aa0 10 17 BPL &2ab9 ; killed_by_enemy &2aa2 a2 07 LDX #&07 # Write "YOU" &2aa4 20 15 2b JSR &2b15 ; write_string &2aa7 a2 02 LDX #&02 ; &2f0 * 8 = &1780 # TAB(&09, &09) &2aa9 a0 f0 LDY #&f0 &2aab 20 a4 1e JSR &1ea4 ; set_cursor_position &2aae a4 63 LDY &63 ; player_was_killed &2ab0 be a6 0c LDX &0ca6,Y ; causes_of_death - 2 # Write cause of death &2ab3 20 15 2b JSR &2b15 ; write_string &2ab6 4c d9 2a JMP &2ad9 ; write_lives_left_or_game_over ; killed_by_enemy &2ab9 a2 0b LDX #&0b # Write "THE" &2abb 20 15 2b JSR &2b15 ; write_string &2abe a2 02 LDX #&02 ; &2f0 * 8 = &1780 # TAB(&09, &09) &2ac0 a0 f0 LDY #&f0 &2ac2 20 a4 1e JSR &1ea4 ; set_cursor_position &2ac5 a4 63 LDY &63 ; player_was_killed &2ac7 be a6 0c LDX &0ca6,Y ; causes_of_death - 2 # Write enemy name &2aca 20 15 2b JSR &2b15 ; write_string &2acd a2 03 LDX #&03 ; &37c * 8 = &1be0 # TAB(&04, &0b) &2acf a0 7c LDY #&7c &2ad1 20 a4 1e JSR &1ea4 ; set_cursor_position &2ad4 a2 1f LDX #&1f # Write "HAS KILLED YOU" &2ad6 20 15 2b JSR &2b15 ; write_string ; write_lives_left_or_game_over &2ad9 a2 04 LDX #&04 ; &420 * 8 = &2100 # TAB(&05, &0d) &2adb a0 20 LDY #&20 &2add 20 a4 1e JSR &1ea4 ; set_cursor_position &2ae0 a5 46 LDA &46 ; lives &2ae2 f0 10 BEQ &2af4 ; no_lives_left &2ae4 a2 0f LDX #&0f # Write " LIFE LEFT" &2ae6 c9 01 CMP #&01 &2ae8 f0 02 BEQ &2aec &2aea a2 2e LDX #&2e # Write " LIVES LEFT" &2aec 09 30 ORA #&30 &2aee 20 ee ff JSR &ffee ; OSWRCH &2af1 4c 15 2b JMP &2b15 ; write_string ; no_lives_left &2af4 a2 04 LDX #&04 ; &04bc * 8 = &25e0 # TAB(&04, &0f) &2af6 a0 bc LDY #&bc &2af8 20 a4 1e JSR &1ea4 ; set_cursor_position &2afb a2 44 LDX #&44 # Write "PRESS SPACE BAR" &2afd 4c 02 2b JMP &2b02 ; write_game_over ; write_treasure_found_text &2b00 a2 54 LDX #&54 # Write "TREASURE FOUND" ; write_game_over &2b02 20 15 2b JSR &2b15 ; write_string &2b05 a2 04 LDX #&04 ; &428 * 8 = &2140 # TAB(&07, &0d) &2b07 a0 28 LDY #&28 &2b09 20 a4 1e JSR &1ea4 ; set_cursor_position &2b0c a2 3a LDX #&3a # Write "GAME OVER" &2b0e 4c 15 2b JMP &2b15 ; write_string ; write_string_loop &2b11 20 ee ff JSR &ffee ; OSWRCH &2b14 e8 INX ; write_string &2b15 bd 7c 0a LDA &0a7c,X ; strings &2b18 10 f7 BPL &2b11 ; write_string_loop &2b1a 60 RTS ; update_prison &2b1b a5 5d LDA &5d ; prison_escort_state # &ff if not in prison, &80 if in prison &2b1d 30 01 BMI &2b20 ; not_being_escorted &2b1f 60 RTS ; not_being_escorted &2b20 c9 ff CMP #&ff &2b22 f0 59 BEQ &2b7d ; update_prison_objects &2b24 a5 47 LDA &47 ; starvation_timer_high # &ff if player isn't becoming hungry &2b26 30 0c BMI &2b34 ; not_starved &2b28 c6 60 DEC &60 ; starvation_timer_low &2b2a d0 08 BNE &2b34 ; not_starved &2b2c c6 47 DEC &47 ; starvation_timer_high &2b2e d0 04 BNE &2b34 ; not_starved &2b30 a9 03 LDA #&03 ; KILLED_BY_STARVATION # Kill the player if stayed in prison for too long &2b32 85 63 STA &63 ; player_was_killed ; not_starved &2b34 ad 5f 0c LDA &0c5f ; objects_y + OBJECT_PLAYER &2b37 c9 08 CMP #&08 &2b39 90 07 BCC &2b42 ; leave_prison &2b3b ad cf 0b LDA &0bcf ; objects_x_low + OBJECT_PLAYER &2b3e c9 90 CMP #&90 # Has the player walked left of the prison door? &2b40 b0 06 BCS &2b48 ; check_bed ; leave_prison &2b42 a9 ff LDA #&ff ; ESCORT_OUT_OF_PRISON # Set to &ff to indicate player has left prison &2b44 85 5d STA &5d ; prison_escort_state &2b46 d0 35 BNE &2b7d ; update_prison_objects # Always branches ; check_bed &2b48 a5 3e LDA &3e ; prison_bed_is_on_fire # Zero if prison bed is on fire &2b4a f0 31 BEQ &2b7d ; update_prison_objects &2b4c a5 08 LDA &08 ; objects_state + OBJECT_LAST_TORCH &2b4e c9 04 CMP #&04 ; OBJECT_STATE_IN_WORLD # Has the prison torch been dislodged? &2b50 d0 15 BNE &2b67 ; check_for_dislodging_prison_torch &2b52 a2 2b LDX #&2b ; OBJECT_PRISON_BED_TARGET # If so, is it near the prison bed? &2b54 a0 08 LDY #&08 ; OBJECT_LAST_TORCH &2b56 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2b59 a5 77 LDA &77 ; x_low # x_low is the horizontal distance from torch to bed &2b5b c9 04 CMP #&04 &2b5d b0 08 BCS &2b67 ; check_for_dislodging_prison_torch &2b5f a9 00 LDA #&00 # Set to zero to indicate prison bed is on fire &2b61 85 3e STA &3e ; prison_bed_is_on_fire &2b63 86 1d STX &1d ; objects_state + OBJECT_SECOND_PRISON_GUARD # Set second guard moving towards bed &2b65 f0 16 BEQ &2b7d ; not_in_prison # Always branches ; check_for_dislodging_prison_torch &2b67 ad 39 0c LDA &0c39 ; objects_y + OBJECT_STOOL # Has the stool hit the prison torch? &2b6a c9 12 CMP #&12 &2b6c d0 0f BNE &2b7d ; update_prison_objects &2b6e ad a9 0b LDA &0ba9 ; objects_x_low + OBJECT_STOOL &2b71 c9 b0 CMP #&b0 &2b73 90 08 BCC &2b7d ; update_prison_objects &2b75 c9 b3 CMP #&b3 &2b77 b0 04 BCS &2b7d ; update_prison_objects &2b79 a9 08 LDA #&08 ; OBJECT_LAST_TORCH # If so, make prison torch fall &2b7b 85 3f STA &3f ; object_to_dislodge ; update_prison_objects &2b7d 20 e4 2b JSR &2be4 ; update_prison_torch &2b80 20 b8 2b JSR &2bb8 ; update_prison_bed_fire &2b83 20 8d 2b JSR &2b8d ; update_fire_extinguishing_guard &2b86 a2 1c LDX #&1c ; OBJECT_FIRST_PRISON_GUARD &2b88 c6 65 DEC &65 ; mover_offset &2b8a 4c 9a 1a JMP &1a9a ; update_guard ; update_fire_extinguishing_guard &2b8d a2 1d LDX #&1d ; OBJECT_SECOND_PRISON_GUARD &2b8f a9 05 LDA #&05 &2b91 85 65 STA &65 ; mover_offset &2b93 ad bd 0b LDA &0bbd ; objects_x_low + OBJECT_SECOND_PRISON_GUARD &2b96 c9 c3 CMP #&c3 # Has the guard reached the bed? &2b98 90 1b BCC &2bb5 ; to_update_guard &2b9a a9 01 LDA #&01 # Set to one to extinguish fire &2b9c 85 3e STA &3e ; prison_bed_is_on_fire &2b9e a0 08 LDY #&08 ; OBJECT_LAST_TORCH &2ba0 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2ba3 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns zero if object is fully off screen &2ba6 f0 03 BEQ &2bab ; skip_unplotting_torch &2ba8 20 9d 22 JSR &229d ; unplot_object # Unplot prison torch if it is on screen ; skip_unplotting_torch &2bab a9 0a LDA #&0a # Remove prison torch by moving to inaccessible level &2bad 8d f0 0b STA &0bf0 ; objects_x_high + OBJECT_LAST_TORCH &2bb0 a2 1d LDX #&1d ; OBJECT_SECOND_PRISON_GUARD &2bb2 20 ad 25 JSR &25ad ; initialise_object_state ; to_update_guard &2bb5 4c 9a 1a JMP &1a9a ; update_guard ; update_prison_bed_fire &2bb8 a5 3e LDA &3e ; prison_bed_is_on_fire # Negative if prison bed is not on fire &2bba 30 27 BMI &2be3 ; leave &2bbc d0 0e BNE &2bcc ; set_prison_bed_fire_colours_to_black # Zero to continue fire, one to extinguish fire &2bbe a5 67 LDA &67 ; time_low &2bc0 29 08 AND #&08 # Alternate fire palette every eight frames &2bc2 f0 04 BEQ &2bc8 ; use_first_set ; use_second_set &2bc4 a0 05 LDY #&05 ; W R Y &2bc6 10 0a BPL &2bd2 ; set_palette # Always branches ; use_first_set &2bc8 a0 02 LDY #&02 ; W Y R &2bca 10 06 BPL &2bd2 ; set_palette # Always branches ; set_prison_bed_fire_colours_to_black &2bcc a9 ff LDA #&ff # Set to negative to indicate bed is not on fire &2bce 85 3e STA &3e ; prison_bed_is_on_fire &2bd0 a0 08 LDY #&08 ; K K K ; set_palette &2bd2 a9 02 LDA #&02 &2bd4 85 72 STA &72 ; count &2bd6 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy ; set_palette_loop &2bd8 be 7f 0d LDX &0d7f,Y ; prison_bed_fire_palette_values &2bdb 20 f4 ff JSR &fff4 ; OSBYTE &2bde 88 DEY &2bdf c6 72 DEC &72 ; count &2be1 10 f5 BPL &2bd8 ; set_palette_loop ; leave &2be3 60 RTS ; update_prison_torch &2be4 a6 3f LDX &3f ; object_to_dislodge # Negative if prison torch isn't falling &2be6 30 18 BMI &2c00 ; leave &2be8 a9 01 LDA #&01 ; VERTICAL_DOWN &2bea 85 71 STA &71 ; vertical_direction &2bec a9 ff LDA #&ff ; HORIZONTAL_NONE &2bee 85 70 STA &70 ; horizontal_direction &2bf0 20 16 25 JSR &2516 ; check_object_X_for_obstacles # Returns carry set if object hit obstacle &2bf3 b0 03 BCS &2bf8 ; hit_floor # Has the torch hit the floor? &2bf5 4c cc 2c JMP &2ccc ; add_active_mover # If not, move the torch ; hit_floor &2bf8 a9 ff LDA #&ff # If so, set to negative to stop torch falling further &2bfa 85 3f STA &3f ; object_to_dislodge &2bfc 60 RTS ; unused &2bfd de 30 0c DEC &0c30,X ; objects_y # Unused code; would move object down a subtile ; leave &2c00 60 RTS ; replot_pockets &2c01 a9 1d LDA #&1d &2c03 85 76 STA &76 ; y &2c05 a6 9b LDX &9b ; pocket_to_empty # Does a pocket need unplotting? &2c07 30 1a BMI &2c23 ; wait_for_timer &2c09 bd c5 09 LDA &09c5,X ; pockets_x_low &2c0c 85 77 STA &77 ; x_low &2c0e bd ca 09 LDA &09ca,X ; pockets_x_high &2c11 85 78 STA &78 ; x_high &2c13 bc c0 09 LDY &09c0,X ; pockets &2c16 a9 ff LDA #&ff &2c18 85 9b STA &9b ; pocket_to_empty # Set to negative to indicate unplotting done &2c1a 9d c0 09 STA &09c0,X ; pockets # Set to &ff to empty pocket &2c1d 20 a9 21 JSR &21a9 ; get_object_width_and_height_for_object_Y &2c20 20 78 22 JSR &2278 ; unplot_pocket ; wait_for_timer &2c23 a5 32 LDA &32 ; timer_at_vsync &2c25 38 SEC &2c26 ed 79 fe SBC &fe79 ; User VIA timer 2 counter MSB &2c29 c9 0d CMP #&0d &2c2b 30 f6 BMI &2c23 ; wait_for_timer &2c2d a2 02 LDX #&02 &2c2f a0 03 LDY #&03 &2c31 a5 85 LDA &85 ; screen_start_x_low &2c33 18 CLC &2c34 69 46 ADC #&46 &2c36 8d c8 09 STA &09c8 ; pockets_x_low + 3 # Calculate position of last pocket from screen address &2c39 a5 86 LDA &86 ; screen_start_x_high &2c3b 69 00 ADC #&00 &2c3d 8d cd 09 STA &09cd ; pockets_x_high + 3 ; calculate_pocket_positions_loop &2c40 b9 c5 09 LDA &09c5,Y ; pockets_x_low &2c43 38 SEC &2c44 e9 0a SBC #&0a # Calculate position of other pockets incrementally &2c46 9d c5 09 STA &09c5,X ; pockets_x_low &2c49 b9 ca 09 LDA &09ca,Y ; pockets_x_high &2c4c e9 00 SBC #&00 &2c4e 9d ca 09 STA &09ca,X ; pockets_x_high &2c51 88 DEY &2c52 ca DEX &2c53 10 eb BPL &2c40 ; calculate_pocket_positions_loop &2c55 a2 03 LDX #&03 ; plot_pockets_loop &2c57 bc c0 09 LDY &09c0,X ; pockets # For each pocket, &2c5a 30 48 BMI &2ca4 ; consider_next_pocket # does it contain an object? &2c5c b9 48 0d LDA &0d48,Y ; objects_chunk_address_low_table &2c5f 85 7f STA &7f ; chunk_address_low # If so, use the sprite for that object &2c61 20 a9 21 JSR &21a9 ; get_object_width_and_height_for_object_Y &2c64 a9 1d LDA #&1d &2c66 85 76 STA &76 ; y &2c68 bd c5 09 LDA &09c5,X ; pockets_x_low &2c6b 85 77 STA &77 ; x_low &2c6d bd ca 09 LDA &09ca,X ; pockets_x_high &2c70 85 78 STA &78 ; x_high &2c72 86 96 STX &96 ; tmp_x &2c74 20 bc 21 JSR &21bc ; plot_pocket # Plot the contents of the pocket &2c77 a5 9d LDA &9d ; screen_scrolling_direction &2c79 30 27 BMI &2ca2 ; skip_unplotting # Negative if not scrolling &2c7b f0 0b BEQ &2c88 ; scrolling_left ; scrolling_right &2c7d a5 77 LDA &77 ; x_low &2c7f d0 02 BNE &2c83 ; skip_page &2c81 c6 78 DEC &78 ; x_high # If scrolling right, unplot left edge of pocket ; skip_page &2c83 c6 77 DEC &77 ; x_low &2c85 4c 93 2c JMP &2c93 ; unplot_edge_of_pocket ; scrolling_left &2c88 a5 77 LDA &77 ; x_low &2c8a 18 CLC &2c8b 65 74 ADC &74 ; object_width # If scrolling left, unplot right edge of pocket &2c8d 85 77 STA &77 ; x_low &2c8f 90 02 BCC &2c93 ; skip_page &2c91 e6 78 INC &78 ; x_high ; skip_page ; unplot_edge_of_pocket &2c93 a9 03 LDA #&03 &2c95 85 73 STA &73 ; object_height &2c97 a9 01 LDA #&01 # Unplot single column, three groups in height &2c99 85 74 STA &74 ; object_width &2c9b a9 1d LDA #&1d &2c9d 85 76 STA &76 ; y &2c9f 20 78 22 JSR &2278 ; unplot_pocket ; skip_unplotting &2ca2 a6 96 LDX &96 ; tmp_x ; consider_next_pocket &2ca4 ca DEX &2ca5 10 b0 BPL &2c57 ; plot_pockets_loop &2ca7 a6 99 LDX &99 ; selected_pocket &2ca9 e0 04 CPX #&04 &2cab 10 1e BPL &2ccb ; leave &2cad 20 92 01 JSR &0192 ; prepare_pocket_for_plotting &2cb0 a9 c6 LDA #&c6 ; &0ec6 = selected_pocket_chunks &2cb2 85 7f STA &7f ; chunk_address_low &2cb4 20 bc 21 JSR &21bc ; plot_pocket # Plot bar under selected pocket &2cb7 a6 9a LDX &9a ; previous_selected_pocket &2cb9 e4 99 CPX &99 ; selected_pocket &2cbb f0 0e BEQ &2ccb ; leave # Has which pocket is selected changed? &2cbd 20 92 01 JSR &0192 ; prepare_pocket_for_plotting &2cc0 a9 dc LDA #&dc ; &0edc = unselected_pocket_chunks &2cc2 85 7f STA &7f ; chunk_address_low &2cc4 20 bc 21 JSR &21bc ; plot_pocket # If so, remove bar from previously selected pocket &2cc7 a5 99 LDA &99 ; selected_pocket &2cc9 85 9a STA &9a ; previous_selected_pocket ; leave &2ccb 60 RTS ; add_active_mover &2ccc e6 30 INC &30 ; mover_offset &2cce a4 30 LDY &30 ; mover_offset &2cd0 a5 70 LDA &70 ; horizontal_direction &2cd2 99 88 08 STA &0888,Y ; movers_horizontal_direction &2cd5 a5 71 LDA &71 ; vertical_direction &2cd7 99 90 08 STA &0890,Y ; movers_vertical_direction &2cda a5 7f LDA &7f ; object_sprite &2cdc 99 98 08 STA &0898,Y ; movers_sprite &2cdf 8a TXA &2ce0 99 80 08 STA &0880,Y ; movers_object &2ce3 60 RTS ; replot_movers_without_time_limit &2ce4 a9 ff LDA #&ff # Negative to suppress timer check &2ce6 85 5a STA &5a ; suppress_timer_check &2ce8 30 0e BMI &2cf8 ; replot_movers_loop # Always branches ; replot_movers_with_time_limit &2cea a9 18 LDA #&18 &2cec 85 6a STA &6a ; y_limit &2cee a9 00 LDA #&00 # Positive to stop plotting movers after fixed time &2cf0 85 5a STA &5a ; suppress_timer_check ; replot_movers_stage_loop &2cf2 a5 30 LDA &30 ; mover_offset &2cf4 85 31 STA &31 ; mover_to_consider &2cf6 e6 31 INC &31 ; mover_to_consider ; replot_movers_loop &2cf8 a5 5a LDA &5a ; suppress_timer_check &2cfa 30 19 BMI &2d15 ; consider_replotting_mover &2cfc a5 32 LDA &32 ; timer_at_vsync &2cfe 38 SEC &2cff ed 79 fe SBC &fe79 ; User VIA timer 2 counter MSB &2d02 c9 3b CMP #&3b &2d04 30 01 BMI &2d07 ; not_out_of_time &2d06 60 RTS ; not_out_of_time &2d07 4a LSR A &2d08 85 79 STA &79 ; tmp &2d0a a9 32 LDA #&32 &2d0c 38 SEC &2d0d e5 79 SBC &79 ; tmp &2d0f e5 6a SBC &6a ; y_limit &2d11 c9 11 CMP #&11 &2d13 10 e3 BPL &2cf8 ; replot_movers_loop # Skip plotting mover ; consider_replotting_mover &2d15 c6 31 DEC &31 ; mover_to_consider &2d17 30 17 BMI &2d30 ; next_stage &2d19 a4 31 LDY &31 ; mover_to_consider &2d1b be 80 08 LDX &0880,Y ; movers_object &2d1e 30 f5 BMI &2d15 ; consider_next_mover &2d20 b9 88 08 LDA &0888,Y ; movers_horizontal_direction &2d23 c9 80 CMP #&80 ; HORIZONTAL_REMOVED &2d25 f0 4b BEQ &2d72 ; skip_unplotting_object &2d27 bd 30 0c LDA &0c30,X ; objects_y &2d2a c5 6a CMP &6a ; y_limit &2d2c 10 14 BPL &2d42 ; replot_mover &2d2e 30 e5 BMI &2d15 ; consider_next_mover ; next_stage &2d30 a5 33 LDA &33 ; movers_replot_stage # &ff for first stage, &00 for second &2d32 49 ff EOR #&ff &2d34 85 33 STA &33 ; movers_replot_stage &2d36 f0 ba BEQ &2cf2 ; replot_movers_stage_loop &2d38 a5 6a LDA &6a ; y_limit &2d3a 38 SEC &2d3b e9 04 SBC #&04 &2d3d 85 6a STA &6a ; y_limit &2d3f 10 b1 BPL &2cf2 ; replot_movers_stage_loop &2d41 60 RTS ; replot_mover &2d42 20 98 21 JSR &2198 ; get_object_variables_for_object_X &2d45 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns zero if object is fully off screen &2d48 08 PHP &2d49 f0 03 BEQ &2d4e ; skip_unplot &2d4b 20 9d 22 JSR &229d ; unplot_object ; skip_unplot &2d4e a4 31 LDY &31 ; mover_to_consider &2d50 be 80 08 LDX &0880,Y ; movers_object &2d53 28 PLP &2d54 30 05 BMI &2d5b ; skip_removing # Negative if object is fully on screen &2d56 a9 ff LDA #&ff &2d58 99 80 08 STA &0880,Y ; movers_object # Set to &ff to indicate mover isn't on screen ; skip_removing &2d5b b9 88 08 LDA &0888,Y ; movers_horizontal_direction &2d5e 85 70 STA &70 ; horizontal_direction &2d60 b9 90 08 LDA &0890,Y ; movers_vertical_direction &2d63 85 71 STA &71 ; vertical_direction &2d65 20 00 01 JSR &0100 ; move_object_left_or_right &2d68 20 3f 09 JSR &093f ; move_object_up_or_down &2d6b a9 80 LDA #&80 ; HORIZONTAL_USE_PREVIOUS # Set to negative to use previous direction &2d6d 99 88 08 STA &0888,Y ; movers_horizontal_direction &2d70 30 86 BMI &2cf8 ; replot_movers_loop # Always branches ; skip_unplotting_object &2d72 20 98 21 JSR &2198 ; get_object_variables_for_object_X &2d75 a4 31 LDY &31 ; mover_to_consider &2d77 be 80 08 LDX &0880,Y ; movers_object &2d7a a9 ff LDA #&ff &2d7c 99 80 08 STA &0880,Y ; movers_object # Set to &ff to indicate mover isn't on screen &2d7f e0 18 CPX #&18 &2d81 10 07 BPL &2d8a ; is_mover # Is this an object, not a mover? &2d83 bd 48 0d LDA &0d48,X ; objects_chunk_address_low_table # If so, use object sprite &2d86 85 7f STA &7f ; chunk_address_low &2d88 d0 15 BNE &2d9f ; plot_mover # Always branches ; is_mover &2d8a b9 98 08 LDA &0898,Y ; movers_sprite # Otherwise, use mover sprite &2d8d a8 TAY &2d8e b9 60 0d LDA &0d60,Y ; movers_chunk_address_low_table &2d91 85 7f STA &7f ; chunk_address_low &2d93 c0 0c CPY #&0c &2d95 10 04 BPL &2d9b ; use_page_e &2d97 a9 0d LDA #&0d # Mover sprites &00 - &0b use &0d00 &2d99 d0 02 BNE &2d9d ; plot ; use_page_e &2d9b a9 0e LDA #&0e # Mover sprites &0c - &1d use &0e00 &2d9d 85 80 STA &80 ; chunk_address_high ; plot_mover &2d9f b5 00 LDA &00,X ; objects_state # Is the mover falling off screen? &2da1 10 04 BPL &2da7 ; skip_forcing_foreground &2da3 a9 00 LDA #&00 # If so, set to zero to plot sprite in the foreground &2da5 85 66 STA &66 ; sprite_is_foreground ; skip_forcing_foreground &2da7 20 c0 21 JSR &21c0 ; plot_object &2daa 4c f8 2c JMP &2cf8 ; replot_movers_loop ; update_wizard &2dad a5 34 LDA &34 ; wizard_state # Negative if wizard isn't active &2daf 30 42 BMI &2df3 ; leave &2db1 c6 34 DEC &34 ; wizard_state &2db3 a5 34 LDA &34 ; wizard_state &2db5 f0 63 BEQ &2e1a ; remove_wizard &2db7 c9 20 CMP #&20 # Display wizard for last 32 frames &2db9 f0 03 BEQ &2dbe ; display_wizard &2dbb 10 37 BPL &2df4 ; update_wizard_lightning &2dbd 60 RTS ; display_wizard &2dbe ad 17 0c LDA &0c17 ; objects_x_high + OBJECT_PLAYER &2dc1 8d f6 0b STA &0bf6 ; objects_x_high + OBJECT_WIZARD &2dc4 8d f5 0b STA &0bf5 ; objects_x_high + OBJECT_WIZARD_SIGN &2dc7 4a LSR A &2dc8 a8 TAY &2dc9 b9 89 0c LDA &0c89,Y ; wizards_x_low # objects_size + (&11 to &13) stores x_low for wizard &2dcc 8d ae 0b STA &0bae ; objects_x_low + OBJECT_WIZARD &2dcf 18 CLC &2dd0 69 07 ADC #&07 &2dd2 8d ad 0b STA &0bad ; objects_x_low + OBJECT_WIZARD_SIGN &2dd5 b9 8c 0c LDA &0c8c,Y ; wizards_y # objects_size + (&14 to &16) stores y for wizard &2dd8 8d 3e 0c STA &0c3e ; objects_y + OBJECT_WIZARD &2ddb 18 CLC &2ddc 69 02 ADC #&02 &2dde 8d 3d 0c STA &0c3d ; objects_y + OBJECT_WIZARD_SIGN &2de1 b9 5c 0d LDA &0d5c,Y ; wizard_sign_chunk_addresses_low &2de4 8d 55 0d STA &0d55 ; objects_chunk_address_low_table + OBJECT_WIZARD_SIGN &2de7 f0 05 BEQ &2dee ; skip_sign &2de9 a2 0d LDX #&0d ; OBJECT_WIZARD_SIGN &2deb 20 cc 2c JSR &2ccc ; add_active_mover ; skip_sign &2dee a2 0e LDX #&0e ; OBJECT_WIZARD &2df0 4c cc 2c JMP &2ccc ; add_active_mover ; leave &2df3 60 RTS ; update_wizard_lightning &2df4 c9 28 CMP #&28 &2df6 10 06 BPL &2dfe ; flash_background_every_four_frames # Background flashing slower at start, then faster &2df8 29 02 AND #&02 # Change screen colour every two frames &2dfa d0 0d BNE &2e09 ; set_screen_background_to_white &2dfc f0 04 BEQ &2e02 ; set_screen_background_to_black # Always branches ; flash_background_every_four_frames &2dfe 29 04 AND #&04 &2e00 d0 07 BNE &2e09 ; set_screen_background_to_white # Change screen colour every four frames ; set_screen_background_to_black &2e02 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &2e04 a2 00 LDX #&00 ; K # Set colour 0 (background) to black &2e06 4c f4 ff JMP &fff4 ; OSBYTE ; set_screen_background_to_white &2e09 a2 a8 LDX #&a8 ; sound_10 # Play sounds for wizard lightning &2e0b 20 35 0a JSR &0a35 ; play_sound &2e0e a2 b0 LDX #&b0 ; sound_11 &2e10 20 35 0a JSR &0a35 ; play_sound &2e13 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &2e15 a2 07 LDX #&07 ; W # Set colour 0 (background) to white &2e17 4c f4 ff JMP &fff4 ; OSBYTE ; remove_wizard &2e1a a2 0e LDX #&0e ; OBJECT_WIZARD &2e1c 20 98 21 JSR &2198 ; get_object_variables_for_object_X &2e1f 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns zero if object is fully off screen &2e22 f0 03 BEQ &2e27 ; skip_unplot &2e24 20 9d 22 JSR &229d ; unplot_object # Unplot wizard ; skip_unplot &2e27 a0 0d LDY #&0d ; OBJECT_WIZARD_SIGN &2e29 ad 55 0d LDA &0d55 ; objects_chunk_address_low_table + OBJECT_WIZARD_SIGN &2e2c f0 c5 BEQ &2df3 ; leave # Zero if wizard didn't have a sign ; unplot_object_if_on_screen &2e2e 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2e31 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns zero if object is fully off screen &2e34 f0 bd BEQ &2df3 ; leave &2e36 4c 9d 22 JMP &229d ; unplot_object # Unplot wizard sign ; check_for_player_in_water &2e39 a2 2f LDX #&2f ; OBJECT_PLAYER &2e3b 20 98 21 JSR &2198 ; get_object_variables_for_object_X &2e3e 20 69 07 JSR &0769 ; get_map_tile &2e41 c9 0b CMP #&0b ; TILE_WATER_LADDER &2e43 30 24 BMI &2e69 ; not_water &2e45 a5 63 LDA &63 ; player_was_killed &2e47 c9 04 CMP #&04 ; KILLED_BY_DROWNING &2e49 90 04 BCC &2e4f ; not_killed_by_drowning_guards_or_troll &2e4b c9 07 CMP #&07 ; KILLED_BY_SPIDER &2e4d 90 35 BCC &2e84 ; leave ; not_killed_by_drowning_guards_or_troll &2e4f a9 ff LDA #&ff # Set to negative to indicate player hasn't been killed &2e51 85 63 STA &63 ; player_was_killed &2e53 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &2e55 a2 94 LDX #&94 ; B # Set colour 9 (player edges) to blue &2e57 20 f4 ff JSR &fff4 ; OSBYTE &2e5a a5 9c LDA &9c ; carrying &2e5c c9 01 CMP #&01 ; OBJECT_AIR &2e5e f0 10 BEQ &2e70 ; player_has_air # If the player isn't carrying the air, &2e60 c6 36 DEC &36 ; player_air &2e62 d0 10 BNE &2e74 ; not_drowned &2e64 a9 04 LDA #&04 ; KILLED_BY_DROWNING # kill the player by drowning &2e66 85 63 STA &63 ; player_was_killed &2e68 60 RTS ; not_water &2e69 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &2e6b a2 90 LDX #&90 ; K # Set colour 9 (player edges) to black &2e6d 20 f4 ff JSR &fff4 ; OSBYTE ; player_has_air &2e70 a9 1e LDA #&1e # Carrying the air allows the player to breathe in water &2e72 85 36 STA &36 ; player_air # for 30 frames after the air is no longer being carried ; not_drowned &2e74 a0 0b LDY #&0b ; OBJECT_BUCKET &2e76 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2e79 20 69 07 JSR &0769 ; get_map_tile &2e7c c9 0b CMP #&0b ; TILE_WATER_LADDER # Is the bucket in a watery tile? &2e7e 30 04 BMI &2e84 ; leave &2e80 a9 01 LDA #&01 &2e82 85 35 STA &35 ; bucket_contains_water # Set to non-zero to indicate bucket contains water ; leave &2e84 60 RTS ; check_for_movement_keys &2e85 c9 e1 CMP #&e1 ; Z &2e87 d0 05 BNE &2e8e ; left_not_pressed &2e89 a9 00 LDA #&00 ; HORIZONTAL_LEFT &2e8b 85 70 STA &70 ; horizontal_direction &2e8d 60 RTS ; left_not_pressed &2e8e c9 c2 CMP #&c2 ; X &2e90 d0 05 BNE &2e97 ; right_not_pressed &2e92 a9 02 LDA #&02 ; HORIZONTAL_RIGHT &2e94 85 70 STA &70 ; horizontal_direction &2e96 60 RTS ; right_not_pressed &2e97 c9 c8 CMP #&c8 ; * &2e99 d0 05 BNE &2ea0 ; up_not_pressed &2e9b a9 00 LDA #&00 ; VERTICAL_UP &2e9d 85 71 STA &71 ; vertical_direction &2e9f 60 RTS ; up_not_pressed &2ea0 c9 e8 CMP #&e8 ; / &2ea2 d0 05 BNE &2ea9 ; down_not_pressed &2ea4 a9 01 LDA #&01 ; VERTICAL_DOWN &2ea6 85 71 STA &71 ; vertical_direction &2ea8 60 RTS ; down_not_pressed &2ea9 a9 ff LDA #&ff # Negative to indicate no movement key pressed &2eab 60 RTS ; update_object_carried_by_player &2eac a4 9c LDY &9c ; carrying &2eae 30 73 BMI &2f23 ; leave &2eb0 a5 9e LDA &9e ; player_facing # Positive if player is facing left or right &2eb2 10 0d BPL &2ec1 ; update_carried_object &2eb4 b9 00 00 LDA &0000,Y ; objects_state &2eb7 c9 06 CMP #&06 ; OBJECT_STATE_IN_POCKET &2eb9 f0 21 BEQ &2edc ; offset_object_Y_from_object_X &2ebb a9 08 LDA #&08 ; OBJECT_STATE_NEEDS_UNPLOTTING &2ebd 99 00 00 STA &0000,Y ; objects_state # Mark as needing unplotting &2ec0 60 RTS ; update_carried_object # Called with A = horizontal direction &2ec1 d9 00 00 CMP &0000,Y ; objects_state # Object may be carried by player or troll &2ec4 f0 0e BEQ &2ed4 ; offset_and_update_carried_object &2ec6 99 00 00 STA &0000,Y ; objects_state # Set object as being carried &2ec9 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2ecc 20 10 09 JSR &0910 ; check_if_object_is_on_screen # Returns negative if object is fully on screen &2ecf 10 03 BPL &2ed4 ; offset_and_update_carried_object &2ed1 4c 9d 22 JMP &229d ; unplot_object ; offset_and_update_carried_object # X is player or troll, Y is carried object &2ed4 20 dc 2e JSR &2edc ; offset_object_Y_from_object_X &2ed7 98 TYA &2ed8 aa TAX &2ed9 4c cc 2c JMP &2ccc ; add_active_mover # Update carried object ; offset_object_Y_from_object_X &2edc c0 02 CPY #&02 # Is the object OBJECT_SWORD or OBJECT_AIR? &2ede 10 0f BPL &2eef ; offset_object &2ee0 a5 9e LDA &9e ; player_facing # Use directional sprites for sword and air &2ee2 f0 05 BEQ &2ee9 ; facing_left ; facing_right &2ee4 b9 dd 09 LDA &09dd,Y ; right_chunks_for_flippable_objects &2ee7 d0 03 BNE &2eec ; set_objects_chunk_address_low_table ; facing_left &2ee9 b9 da 09 LDA &09da,Y ; left_chunks_for_flippable_objects ; set_objects_chunk_address_low_table &2eec 99 48 0d STA &0d48,Y ; objects_chunk_address_low_table ; offset_object &2eef bd 30 0c LDA &0c30,X ; objects_y &2ef2 18 CLC &2ef3 69 01 ADC #&01 &2ef5 99 30 0c STA &0c30,Y ; objects_y &2ef8 b9 00 00 LDA &0000,Y ; objects_state &2efb d0 14 BNE &2f11 ; offset_to_right ; offset_to_left &2efd bd a0 0b LDA &0ba0,X ; objects_x_low &2f00 38 SEC &2f01 f9 a0 08 SBC &08a0,Y ; carried_objects_left_offset &2f04 99 a0 0b STA &0ba0,Y ; objects_x_low &2f07 bd e8 0b LDA &0be8,X ; objects_x_high &2f0a e9 00 SBC #&00 &2f0c 99 e8 0b STA &0be8,Y ; objects_x_high &2f0f 10 12 BPL &2f23 ; leave # Always branches ; offset_to_right &2f11 bd a0 0b LDA &0ba0,X ; objects_x_low &2f14 18 CLC &2f15 79 b0 08 ADC &08b0,Y ; carried_objects_right_offset &2f18 99 a0 0b STA &0ba0,Y ; objects_x_low &2f1b bd e8 0b LDA &0be8,X ; objects_x_high &2f1e 69 00 ADC #&00 &2f20 99 e8 0b STA &0be8,Y ; objects_x_high ; leave &2f23 60 RTS ; check_for_function_keys &2f24 a2 03 LDX #&03 ; check_for_function_keys_loop &2f26 dd cf 09 CMP &09cf,X ; select_pocket_key_codes &2f29 f0 05 BEQ &2f30 ; function_key_pressed &2f2b ca DEX &2f2c 30 05 BMI &2f33 ; leave &2f2e 10 f6 BPL &2f26 ; check_for_function_keys_loop ; function_key_pressed &2f30 8a TXA &2f31 85 99 STA &99 ; selected_pocket ; leave &2f33 60 RTS # Leave with positive if function key pressed ; check_for_pickup_store_and_retrieve &2f34 c9 b7 CMP #&b7 ; P # Does the player want to pick up an object? &2f36 d0 4d BNE &2f85 ; check_for_retrieving_object ; is_picking_up &2f38 a0 0b LDY #&0b ; OBJECT_BUCKET ; check_for_picking_up_objects_loop # For each object, &2f3a a2 2f LDX #&2f ; OBJECT_PLAYER &2f3c b9 00 00 LDA &0000,Y ; objects_state &2f3f c9 04 CMP #&04 ; OBJECT_STATE_IN_WORLD # Is it in the world? &2f41 d0 19 BNE &2f5c ; consider_next_object &2f43 20 af 07 JSR &07af ; get_direction_and_distance_from_object_X_to_object_Y &2f46 a5 71 LDA &71 ; vertical_direction &2f48 c9 01 CMP #&01 ; VERTICAL_DOWN &2f4a f0 10 BEQ &2f5c ; consider_next_object # Can't pick up object above player &2f4c a5 76 LDA &76 ; y # y is the vertical distance from player to object &2f4e c9 02 CMP #&02 &2f50 10 0a BPL &2f5c ; consider_next_object &2f52 a6 77 LDX &77 ; x_low # x_low is the horizontal distance from player to object &2f54 a5 70 LDA &70 ; horizontal_direction &2f56 f0 08 BEQ &2f60 ; facing_left ; facing_right &2f58 e0 05 CPX #&05 &2f5a 90 0c BCC &2f68 ; pick_up_object ; consider_next_object &2f5c 88 DEY &2f5d 10 db BPL &2f3a ; check_for_picking_up_objects_loop &2f5f 60 RTS ; facing_left &2f60 20 a9 21 JSR &21a9 ; get_object_width_and_height_for_object_Y &2f63 ca DEX &2f64 e4 74 CPX &74 ; object_width &2f66 b0 f4 BCS &2f5c ; consider_next_object ; pick_up_object &2f68 a5 9c LDA &9c ; carrying &2f6a 10 03 BPL &2f6f ; put_object_in_pocket # Is the player already carrying an object? &2f6c 84 9c STY &9c ; carrying # If not, carry the picked up object &2f6e 60 RTS ; put_object_in_pocket # Otherwise, try to pocket the picked up object &2f6f a2 03 LDX #&03 ; find_empty_pocket_loop # For each pocket, &2f71 bd c0 09 LDA &09c0,X ; pockets &2f74 10 0b BPL &2f81 ; consider_next_pocket # Is there an object in the pocket? &2f76 98 TYA &2f77 9d c0 09 STA &09c0,X ; pockets # If not, store the picked up object in the pocket &2f7a a9 08 LDA #&08 ; OBJECT_STATE_NEEDS_UNPLOTTING &2f7c 99 00 00 STA &0000,Y ; objects_state # Mark as needing unplotting &2f7f 10 03 BPL &2f84 ; leave # Always branches &2f81 ca DEX &2f82 10 ed BPL &2f71 ; find_empty_pocket_loop ; leave &2f84 60 RTS ; check_for_retrieving_object &2f85 c9 b3 CMP #&b3 ; R # Does the player want to retrieve an object? &2f87 d0 19 BNE &2fa2 ; check_for_storing_object ; retrieve_object &2f89 a6 99 LDX &99 ; selected_pocket &2f8b a5 9c LDA &9c ; carrying # Is the player already carrying an object? &2f8d 10 12 BPL &2fa1 ; leave &2f8f bc c0 09 LDY &09c0,X ; pockets # If not, does the selected pocket contain an object? &2f92 30 0d BMI &2fa1 ; leave &2f94 20 e0 16 JSR &16e0 ; update_newly_retrieved_object # Returns carry set if object would be in a wall &2f97 b0 08 BCS &2fa1 ; leave &2f99 a6 99 LDX &99 ; selected_pocket &2f9b 86 9b STX &9b ; pocket_to_empty # Otherwise, mark pocket as needing emptying &2f9d 84 9c STY &9c ; carrying # and carry object &2f9f a9 ff LDA #&ff # Leave with negative to stop further key checking ; leave &2fa1 60 RTS ; check_for_storing_object &2fa2 c9 d1 CMP #&d1 ; S # Does the player want to store an object? &2fa4 d0 0e BNE &2fb4 ; leave_with_zero &2fa6 a4 9c LDY &9c ; carrying # Is the player carrying an object? &2fa8 30 0a BMI &2fb4 ; leave_with_zero &2faa 20 6f 2f JSR &2f6f ; put_object_in_pocket # If so, try to put it in a pocket &2fad 8a TXA # If an empty pocket was found, &2fae 30 04 BMI &2fb4 ; leave_with_zero &2fb0 a9 ff LDA #&ff # Set to negative to indicate player not carrying object &2fb2 85 9c STA &9c ; carrying ; leave_with_zero &2fb4 a9 00 LDA #&00 # Leave with positive to allow further key checking &2fb6 60 RTS ; update_objects &2fb7 a0 0b LDY #&0b ; OBJECT_BUCKET &2fb9 84 96 STY &96 ; object_to_update ; update_objects_loop # For each object, &2fbb b9 48 0d LDA &0d48,Y ; objects_chunk_address_low_table # Use sprite for object &2fbe 85 7f STA &7f ; chunk_address_low &2fc0 b9 00 00 LDA &0000,Y ; objects_state &2fc3 8d c7 2f STA &2fc7 ; jump_offset # Branch depending on the state of the object &2fc6 10 ff BPL &2fc7 # actually BPL &2fc8 + jump_offset # Always branches, to one of eight branches: ; is_in_state_0 # OBJECT_STATE_CARRYING_TO_LEFT &2fc8 10 1b BPL &2fe5 ; consider_next_object ; is_in_state_2 # OBJECT_STATE_CARRYING_TO_RIGHT &2fca 10 19 BPL &2fe5 ; consider_next_object ; is_in_state_4 # OBJECT_STATE_IN_WORLD &2fcc 10 0a BPL &2fd8 ; is_in_world ; is_in_state_6 # OBJECT_STATE_IN_POCKET &2fce 10 15 BPL &2fe5 ; consider_next_object ; is_in_state_8 # OBJECT_STATE_NEEDS_UNPLOTTING &2fd0 10 1a BPL &2fec ; needs_unplotting ; is_in_state_a # Unused &2fd2 10 11 BPL &2fe5 ; consider_next_object ; is_in_state_c # Unused &2fd4 10 de BPL &2fb4 ; leave_with_zero ; is_in_state_e # OBJECT_STATE_THROWN &2fd6 10 0d BPL &2fe5 ; consider_next_object ; is_in_world # If the object is in the world, &2fd8 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2fdb 98 TYA &2fdc aa TAX &2fdd 20 10 09 JSR &0910 ; check_if_object_is_on_screen # and it is at least partially on screen, &2fe0 10 03 BPL &2fe5 ; consider_next_object &2fe2 20 c0 21 JSR &21c0 ; plot_object # then replot the object ; consider_next_object &2fe5 c6 96 DEC &96 ; object_to_update &2fe7 a4 96 LDY &96 ; object_to_update &2fe9 10 d0 BPL &2fbb ; update_objects_loop &2feb 60 RTS ; needs_unplotting # If the object has just been pocketed, &2fec a9 06 LDA #&06 ; OBJECT_STATE_IN_POCKET &2fee 99 00 00 STA &0000,Y ; objects_state &2ff1 20 9a 21 JSR &219a ; get_object_variables_for_object_Y &2ff4 20 9d 22 JSR &229d ; unplot_object # unplot the object &2ff7 4c e5 2f JMP &2fe5 ; consider_next_object ; write_number &2ffa d8 CLD &2ffb 09 30 ORA #&30 ; "0" &2ffd 4c ee ff JMP &ffee ; OSWRCH # &3000 - &3dff is moved to &0880 - &167f at &3ee2 ; initialise_mode # Overwritten after start of game &0880 a9 16 LDA #&16 &0882 20 ee ff JSR &ffee ; OSWRCH &0885 a9 02 LDA #&02 &0887 20 ee ff JSR &ffee ; OSWRCH &088a a9 08 LDA #&08 # R8: Interlace and delay register &088c 8d 00 fe STA &fe00 ; video register number &088f a9 c0 LDA #&c0 &0891 8d 01 fe STA &fe01 ; video register value &0894 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &0896 a2 90 LDX #&90 ; K # Set colour 9 (player edges) to black &0898 20 f4 ff JSR &fff4 ; OSBYTE &089b a2 f0 LDX #&f0 ; K # Set colour 15 (wall shadow) to black &089d 4c f4 ff JMP &fff4 ; OSBYTE &0880 - &0887 ; movers_object &0888 - &088f ; movers_horizontal_direction &0890 - &0897 ; movers_vertical_direction &0898 - &089f ; movers_sprite ; carried_objects_left_offset ; 0 1 2 3 4 5 6 7 8 9 a b c &08a0 01 01 02 02 03 01 01 01 01 02 04 02 05 ; unused &08ad 00 00 00 ; carried_objects_right_offset ; 0 1 2 3 4 5 6 7 8 9 a b c &08b0 04 03 04 04 04 04 04 04 04 04 04 04 05 ; unused &08bd 00 00 00 ; envelope_1 # Troll moving, sword fighting, climbing &08c0 81 00 00 00 00 00 00 55 ec 00 00 55 00 00 00 00 ; envelope_2 # Falling player and movers, stunned, throwing &08d0 81 ff 00 00 c8 00 00 7f 00 00 81 7e 00 00 00 00 ; envelope_3 # Wizard lightning &08e0 81 fd 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 ; envelope_4 # Spider killing, dying player &08f0 83 00 00 00 00 00 00 3c ec 00 00 3c 00 00 00 00 ; envelope_5 # Jumping, dying player &0900 81 02 02 ff 0c 1e 96 7f ff 00 81 7e 00 00 00 00 ; check_if_object_is_on_screen &0910 a9 51 LDA #&51 # Width of screen in columns + 1 &0912 38 SEC &0913 e5 74 SBC &74 ; object_width &0915 85 7c STA &7c ; object_right_edge_distance_from_right_edge &0917 e9 03 SBC #&03 &0919 85 7b STA &7b ; object_left_edge_distance_from_right_edge &091b a5 77 LDA &77 ; x_low &091d 38 SEC &091e e5 85 SBC &85 ; screen_start_x_low &0920 85 79 STA &79 ; relative_x_low &0922 a5 78 LDA &78 ; x_high &0924 e5 86 SBC &86 ; screen_start_x_high &0926 d0 14 BNE &093c ; leave_with_zero &0928 a5 79 LDA &79 ; relative_x_low &092a c9 03 CMP #&03 &092c 90 0b BCC &0939 ; leave_with_one &092e c5 7c CMP &7c ; object_right_edge_distance_from_right_edge &0930 b0 0a BCS &093c ; leave_with_zero &0932 c5 7b CMP &7b ; object_left_edge_distance_from_right_edge &0934 b0 03 BCS &0939 ; leave_with_one ; leave_with_minus_one &0936 a9 ff LDA #&ff # Leave with negative if object is fully on screen &0938 60 RTS ; leave_with_one &0939 a9 01 LDA #&01 # Leave with &01 if object straddles edge of screen &093b 60 RTS ; leave_with_zero &093c a9 00 LDA #&00 # Leave with zero if object is fully off screen &093e 60 RTS ; move_object_up_or_down &093f a5 71 LDA &71 ; vertical_direction &0941 30 0a BMI &094d ; consider_moving_down_twice &0943 f0 04 BEQ &0949 ; move_up ; move_down &0945 de 30 0c DEC &0c30,X ; objects_y # Move down one subtile for VERTICAL_DOWN &0948 60 RTS ; move_up &0949 fe 30 0c INC &0c30,X ; objects_y # Move up one subtile for VERTICAL_UP &094c 60 RTS ; consider_moving_down_twice &094d c9 ff CMP #&ff ; VERTICAL_NONE &094f f0 06 BEQ &0957 ; leave &0951 de 30 0c DEC &0c30,X ; objects_y # Move down two subtiles for VERTICAL_DOWN_DOUBLE &0954 de 30 0c DEC &0c30,X ; objects_y ; leave &0957 60 RTS ; chan vol pitch dur ; sound_0 # Troll moving towards player &0958 11 00 01 00 14 00 02 00 ; sound_1 # Falling player, stunned player &0960 12 00 02 00 b0 00 23 00 ; sound_2 # Silence channel 2 &0968 12 00 00 00 00 00 01 00 ; sound_3 # Jumping, dying player (pitch modified) &0970 12 00 05 00 64 00 28 00 ; sound_4 # Witch moving towards player &0978 10 00 ff ff 04 00 05 00 ; sound_5 # Dropping spider, falling witch, falling guard &0980 13 00 02 00 a0 00 28 00 ; sound_6 # Silence channel 3 &0988 13 00 00 00 00 00 01 00 ; sound_7 # Spider killing, player dying &0990 12 00 04 00 95 00 0f 00 ; sound_8 # Throwing object &0998 13 00 02 00 dc 00 28 00 ; sound_9 # Sword fighting, player climbing &09a0 13 00 01 00 f0 00 02 00 ; sound_10 # Wizard lightning &09a8 11 00 03 00 f0 00 20 00 ; sound_11 # Wizard lightning &09b0 10 00 f1 ff 07 00 10 00 ; sound_12 # Player walking &09b8 12 00 01 00 60 00 02 00 ; pockets &09c0 ff ff ff ff ; unused &09c4 ff ; pockets_x_low &09c5 00 00 00 00 ; unused &09c9 00 ; pockets_x_high &09ca 00 00 00 00 ; unused &09ce 00 ; select_pocket_key_codes &09cf a0 ; f0 &09d0 f1 ; f1 &09d1 f2 ; f2 &09d2 f3 ; f3 ; unused &09d3 00 ; throw_and_drop_key_codes &09d4 99 ; LEFT ; &00 : THROWING_LEFT &09d5 f9 ; RIGHT ; &01 : THROWING_RIGHT &09d6 b9 ; UP ; &02 : THROWING_UP &09d7 a9 ; DOWN ; &03 : THROWING_DOWN &09d7 b2 ; D ; &04 : THROWING_DROP ; unused &09d9 00 ; left_chunks_for_flippable_objects &09da cb ; sword_left_chunks MOD 256 &09db f8 ; air_left_chunks MOD 256 ; unused &09dc 00 ; right_chunks_for_flippable_objects &09dd cd ; sword_right_chunks MOD 256 &09ee f4 ; air_right_chunks MOD 256 ; unused &09df 00 00 00 ; crossed_swords_offsets ; l r &09e2 fd ff 02 00 ; -3, +2 ; guard_fighting_offsets ; l r &09e6 06 00 07 ; unused # Unused; could be inverse of guard fighting offsets? &09e9 07 00 fa ff ; +7, -6 ; witch_collision_sizes ; l r &09ed 02 04 ; spider_targets &09ef 10 ; OBJECT_LEFT_SPIDER_TARGET &09f0 11 ; OBJECT_RIGHT_SPIDER_TARGET ; saved_pockets &09f1 00 00 00 00 ; unused &09f5 00 ; level_save_positions_x_low ; 0 1 2 3 4 5 6 7 8 &09f6 e8 ce 22 48 22 ca 4a 0a 00 ; level_save_positions_y ; 0 1 2 3 4 5 6 7 8 &09ff 04 18 04 04 10 04 14 10 00 ; level_save_positions_used ; 0 1 2 3 4 5 6 7 8 &0a08 00 00 00 00 00 00 00 00 00 ; level_update_handlers_jump_offsets ; 0 1 2 3 4 5 6 7 8 &0a11 00 03 09 0c 12 18 24 24 21 ; level_openings_right ; 0 1 2 3 4 5 6 7 8 &0a1a 50 1d d0 c0 b0 ff e0 a0 00 ; level_openings_left ; 0 1 2 3 4 5 6 7 8 &0a23 20 10 00 90 00 10 10 80 00 ; going_up_delta_x_high ; 0 1 2 3 4 5 6 7 8 &0a2c 00 00 02 00 03 01 00 05 02 ; play_sound &0a35 a0 09 LDY #&09 &0a37 a9 07 LDA #&07 ; Generate a sound (SOUND) &0a39 20 f1 ff JSR &fff1 ; OSWORD &0a3c a2 2f LDX #&2f ; OBJECT_PLAYER &0a3e 60 RTS ; unused &0a3f 00 00 00 00 00 00 ; tiles_support_type # &80 if tile offers no support ; 0 1 2 3 4 5 6 7 8 9 a b c # &40 if top of tile offers support &0a45 80 40 00 02 80 40 40 80 80 40 80 80 80 # &00 or &02 if sloping up to left or right ; unused &0a52 80 00 00 ; tiles_foreground_flags ; 0 1 2 3 4 5 6 7 8 9 a b c &0a55 00 00 00 00 00 00 00 01 01 01 00 00 00 # 1 if tiles are plotted in front of movers and objects ; unused &0a62 00 00 00 ; guards_sensitivity_x_low ; 18 19 1a 1b 1c 1d 1e 1f 20 21 &0a65 14 08 20 0e 08 08 28 28 20 20 # Maximum horizontal distance at which guard chases ; unused &0a66 00 ; guards_sensitivity_y ; 18 19 1a 1b 1c 1d 1e 1f 20 21 &0a70 03 03 08 06 03 03 20 20 03 03 # Maximum vertical distance at which guard chases ; unused &0a7a 00 ; unused &0a7b 00 ; strings &0a7c 53 43 4f 52 45 3d ff ; &00: "SCORE=" &0a83 59 4f 55 ff ; &07: "YOU" &0a87 54 48 45 ff ; &0b: "THE" &0a8b 20 4c 49 46 45 20 4c 45 46 54 ff ; &0f: " LIFE LEFT" &0a96 0d 54 48 45 ff ; &1a: "\rTHE" &0a9b 48 41 53 20 4b 49 4c 4c 45 44 20 59 4f 55 ff ; &1f: "HAS KILLED YOU" &0aaa 20 4c 49 56 45 53 20 4c 45 46 54 ff ; &2e: " LIVES LEFT" &0ab6 47 41 4d 45 20 4f 56 45 52 ff ; &3a: "GAME OVER" &0ac0 50 52 45 53 53 20 53 50 41 43 45 20 42 41 52 ff ; &44: "PRESS SPACE BAR" &0ad0 54 52 45 41 53 55 52 45 20 46 4f 55 4e 44 ff ; &54: "TREASURE FOUND" &0adf 46 45 4c 4c ff ; &63: "FELL" &0ae4 53 54 41 52 56 45 44 ff ; &68: "STARVED" &0aec 44 52 4f 57 4e 45 44 ff ; &70: "DROWNED" &0af4 41 52 45 20 44 45 41 44 ff ; &78: "ARE DEAD" &0afd 54 52 4f 4c 4c ff ; &81: "TROLL" &0b03 53 50 49 44 45 52 ff ; &87: "SPIDER" &0b0a 57 49 54 43 48 ff ; &8e: "WITCH" # Objects # ======= # x y s # &00: i (&0256, &08), &04 : OBJECT_SWORD # &01: i (&04fd, &14), &04 : OBJECT_AIR # &02: i (&0650, &14), &04 : OBJECT_COIN # &03: i (&009a, &18), &04 : OBJECT_RUBY # &04: i (&044a, &04), &04 : OBJECT_GOLD # &05: i (&02e2, &0c), &04 : OBJECT_FIRST_TORCH # &06: i (&005a, &14), &04 : OBJECT_SECOND_TORCH # &07: i (&048c, &0c), &04 : OBJECT_THIRD_TORCH # &08: i (&01b2, &12), &04 : OBJECT_LAST_TORCH # &09: i (&01b0, &08), &04 : OBJECT_STOOL # &0a: i (&06f2, &0c), &04 : OBJECT_WAND # &0b: i (&049e, &01), &04 : OBJECT_BUCKET # &0c: : OBJECT_WATER # &0d: : OBJECT_WIZARD_SIGN # &0e: : OBJECT_WIZARD # &0f: : OBJECT_CROSSED_SWORDS # &10: (&0248, &08) : OBJECT_LEFT_SPIDER_TARGET # &11: (&026b, &08) : OBJECT_RIGHT_SPIDER_TARGET # &12: (&0280, &14) : OBJECT_TOP_MONKEY_TARGET # &13: (&032d, &04) : OBJECT_BOTTOM_MONKEY_TARGET # &14: (&06f1, &0c) : OBJECT_WITCH_TARGET # &15: (&03d8, &04) : OBJECT_TROLL_HOARD_TARGET # &16: (&03c3, &0c) : OBJECT_TROLL_PASSAGE_TARGET # &17: : OBJECT_DEAD_PLAYER # &18: i (&0058, &04), &30 : OBJECT_FIRST_GREEN_GUARD # Left platform # &19: i (&00ee, &04), &32 : OBJECT_SECOND_GREEN_GUARD # Right platform # &1a: i (&00f7, &04), &34 : OBJECT_THIRD_GREEN_GUAR # Right platform # &1b: i (&011c, &10), &36 : OBJECT_LAST_GREEN_GUARD # Top of slope to prison # &1c: i (&0140, &10), &38 : OBJECT_FIRST_PRISON_GUARD # Prison passage # &1d: i (&0193, &08), &3a : OBJECT_SECOND_PRISON_GUARD # Prison door # &1e: i (&04e0, &14), &3c : OBJECT_FIRST_RED_GUARD # &1f: i (&04e8, &0c), &3e : OBJECT_LAST_RED_GUARD # &20: i (&0568, &0c), &40 : OBJECT_FIRST_YELLOW_GUARD # &21: i (&05a8, &0c), &42 : OBJECT_LAST_YELLOW_GUARD # &22: i (&03c4, &0c), &00 : OBJECT_TROLL # &23: i (&06f1, &0c), &00 : OBJECT_WITCH # &24: i (&0246, &16), &80 : OBJECT_FIRST_SPIDER # Left # &25: i (&0266, &16), &80 : OBJECT_LAST_SPIDER # Right # &26: i (&0280, &14), &12 : OBJECT_FIRST_MONKEY # &27: i (&02a0, &10), &12 : OBJECT_SECOND_MONKEY # &28: i (&02c0, &0c), &12 : OBJECT_THIRD_MONKEY # &29: i (&02e0, &08), &12 : OBJECT_LAST_MONKEY # &2a: i (&05b2, &0c), &00 : OBJECT_TREASURE # &2b: i (&01c4, &08), &00 : OBJECT_PRISON_BED_TARGET # &2c: i (&0000, &00), &00 : (unused) # &2d: i (&0000, &00), &00 : (unused) # &2e: i (&0000, &00), &00 : (unused) # &2f: i (&0000, &00), &00 : OBJECT_PLAYER # &30: (&0060, &08) : OBJECT_FIRST_GREEN_GUARD_BOTTOM_TARGET # &31: (&0080, &14) : OBJECT_FIRST_GREEN_GUARD_TOP_TARGET # &32: (&00d8, &14) : OBJECT_SECOND_GREEN_GUARD_BOTTOM_TARGET # &33: (&0098, &18) : OBJECT_SECOND_GREEN_GUARD_TOP_TARGET # &34: (&00d8, &14) : OBJECT_THIRD_GREEN_GUARD_BOTTOM_TARGET # &35: (&00b8, &0c) : OBJECT_THIRD_GREEN_GUARD_TOP_TARGET # &36: (&011b, &10) : OBJECT_FOURTH_GREEN_GUARD_TARGET # &37: (&011b, &10) : OBJECT_FOURTH_GREEN_GUARD_TARGET + 1 # &38: (&0130, &10) : OBJECT_FIRST_PRISON_GUARD_LEFT_TARGET # &39: (&0180, &0c) : OBJECT_FIRST_PRISON_GUARD_RIGHT_TARGET # &3a: (&018b, &08) : OBJECT_SECOND_PRISON_GUARD_TARGET # &3b: (&018b, &08) : OBJECT_SECOND_PRISON_GUARD_TARGET + 1 # &3c: (&04c0, &14) : OBJECT_FIRST_RED_GUARD_LEFT_TARGET # &3d: (&04e8, &14) : OBJECT_FIRST_RED_GUARD_RIGHT_TARGET # &3e: (&04c0, &14) : OBJECT_SECOND_RED_GUARD_LEFT_TARGET # &3f: (&04e8, &0c) : OBJECT_SECOND_RED_GUARD_RIGHT_TARGET # &40: (&0568, &0c) : OBJECT_FIRST_YELLOW_GUARD_LEFT_TARGET # &41: (&05a0, &0c) : OBJECT_FIRST_YELLOW_GUARD_RIGHT_TARGET # &42: (&0568, &0c) : OBJECT_LAST_YELLOW_GUARD_LEFT_TARGET # &43: (&05a0, &0c) : OBJECT_LAST_YELLOW_GUARD_RIGHT_TARGET # &44: (&0000, &00) : OBJECT_LEFT_ESCORT_TARGET # &45: (&0000, &00) : OBJECT_RIGHT_ESCORT_TARGET # &46: (&0134, &10) : OBJECT_PRISON_GUARD_PASSAGE_TARGET # &47: (&01a8, &08) : OBJECT_PRISON_GUARD_PRISON_TARGET ; initial_objects_x_low # &00 - &0b and &18 - &2f are used ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0b10 56 fd 50 9a 4a e2 5a 8c b2 b0 f2 9e 00 00 00 00 ; &00 &0b20 00 00 00 00 00 00 00 00 58 ee f7 1c 40 93 e0 e8 ; &10 &0b30 68 a8 c4 f1 46 66 80 a0 c0 e0 b2 c4 00 00 00 00 ; &20 ; initial_objects_x_high # &00 - &0b and &18 - &2f are used ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0b40 02 04 06 00 04 02 00 04 01 01 06 04 00 00 00 00 ; &00 &0b50 00 00 00 00 00 00 00 00 00 00 00 01 01 01 04 04 ; &10 &0b60 05 05 03 06 02 02 02 02 02 02 05 01 00 00 00 00 ; &20 ; initial_objects_y # &00 - &0b and &18 - &2f are used ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0b70 08 14 14 18 04 0c 14 0c 12 08 0c 01 00 00 00 00 ; &00 &0b80 00 00 00 00 00 00 00 00 04 04 04 10 10 08 14 0c ; &10 &0b90 0c 0c 0c 0c 16 16 14 10 0c 08 0c 08 00 00 00 00 ; &20 ; objects_x_low # &00 - &0b and &18 - &2f are reset to initial values ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0ba0 30 14 26 24 22 20 18 16 b2 b0 28 34 00 00 00 00 ; &00 &0bb0 48 6b 80 2d f1 d8 c3 c6 60 e0 a0 20 39 91 e0 e8 ; &10 &0bc0 68 a4 c4 f1 46 66 80 88 90 98 b2 c4 00 00 00 48 ; &20 &0bd0 60 80 d8 98 d8 b8 1b 1b 30 80 8b 8b c0 e8 c0 e8 ; &30 &0be0 68 a0 68 a0 00 00 34 a8 ; &40 ; objects_x_high # &00 - &0b and &18 - &2f are reset to initial values ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0be8 03 03 03 03 03 03 03 03 01 01 03 03 00 00 00 00 ; &00 &0bf8 02 02 02 03 06 03 03 01 00 00 00 01 01 01 04 04 ; &10 &0c08 05 05 03 06 02 02 02 02 02 02 05 01 00 00 00 03 ; &20 &0c18 00 00 00 00 00 00 01 01 01 01 01 01 04 04 04 04 ; &30 &0c28 05 05 05 05 00 00 01 01 ; &40 ; objects_y # &00 - &0b and &18 - &2f are reset to initial values ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0c30 04 04 04 04 04 04 04 04 12 08 04 04 00 00 00 00 ; &00 &0c40 08 08 14 04 0c 04 0c 08 14 14 18 10 10 08 14 0c ; &10 &0c50 0c 0c 0c 0c 16 16 14 14 14 14 0d 08 00 00 00 04 ; &20 &0c60 08 14 14 18 14 0c 10 10 10 0c 08 08 14 14 14 0c ; &30 &0c70 0c 0c 0c 0c 00 00 10 08 ; &40 ; objects_size # 842184.. width ; 0 1 2 3 4 5 6 7 8 9 a b c d e f # ......21 height &0c78 06 0a 09 09 0d 0a 0a 0a 0a 09 11 09 11 11 1f 12 ; &00 &0c88 00 e8 21 18 18 14 18 1a 0f 0f 0f 0f 0f 0f 0f 0f ; &10 # &11 - &16 are used for positions of wizard &0c98 0f 0f 13 1a 16 16 0e 0e 0e 0e 12 00 00 00 00 13 ; &20 &0c89 - &0c8b ; wizards_x_low &0c8c - &0cde ; wizards_y ; causes_of_death # &00: KILLED_UNCONSCIOUS # &01: KILLED_UNCONSCIOUS_IN_PRISON &0ca8 63 ; &02: "FELL", KILLED_BY_FALLING &0ca9 68 ; &03: "STARVED", KILLED_BY_STARVATION &0caa 70 ; &04: "DROWNED", KILLED_BY_DROWNING &0cab 78 ; &05: "ARE DEAD", KILLED_ARE_DEAD &0cac 81 ; &06: "TROLL", KILLED_BY_TROLL &0cad 87 ; &07: "SPIDER", KILLED_BY_SPIDER &0cae 8e ; &08: "WITCH", KILLED_BY_WITCH ; object_names &0caf 00 53 57 4f 52 44 ; &00: "SWORD" &0cb5 01 41 49 52 ; &01: "AIR" &0cb9 02 43 4f 49 4e ; &02: "COIN" &0cbe 03 52 55 42 59 ; &03: "RUBY" &0cc3 04 47 4f 4c 44 ; &04: "GOLD" &0cc8 0b 42 55 43 4b 45 54 ; &0b: "BUCKET" &0ccf 06 54 4f 52 43 48 ; &06: "TORCH" &0cd5 07 54 4f 52 43 48 ; &07: "TORCH" &0cdb 08 54 4f 52 43 48 ; &08: "TORCH" &0ce1 09 53 54 4f 4f 4c ; &09: "STOOL" &0ce7 0a 57 41 4e 44 ; &0a: "WAND" &0cec ff 45 4d 50 54 59 ; &ff: "EMPTY" &0cf2 05 54 4f 52 43 48 ; &05: "TORCH" ; saved_objects_x_high &0cf8 00 00 00 00 00 00 00 00 00 00 00 00 ; save_objects_y &0d04 00 00 00 00 00 00 00 00 00 00 00 00 ; going_down_delta_x_high ; 0 1 2 3 4 5 6 7 8 &0d10 02 03 05 01 01 00 00 00 00 ; unused &0d19 00 ; right_slope_offsets &0d1a 00 01 02 03 04 ; left_slope_offsets &0d1f 04 03 02 01 00 ; saved_objects_x_low &0d24 00 00 00 00 00 00 00 00 00 00 00 00 ; objects_moving ; 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 &0d30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; 28 29 2a 2b 2c 2d 2e 2f &0d40 00 00 00 00 00 00 00 00 ; objects_chunk_address_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0d48 cd f4 cf d1 d3 d8 d8 d8 d8 e1 c2 d6 fc 00 7c 00 ; &00 &0d58 00 00 00 00 f0 00 c2 e4 ; &10 # &14 - &16 used for wizard_sign_chunk_addresses_low &0d5c - &0d5e ; wizard_sign_chunk_addresses_low ; movers_chunk_address_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0d60 94 88 ac a0 b8 c4 d0 d9 e2 eb f4 fd 06 12 1e 2a ; &00 # Addresses of sprites, not objects &0d70 1e 2a 36 36 42 42 4e 54 5a 60 66 6c 72 90 ; &10 ; unused &0d7e 00 ; prison_bed_fire_palette_values &0d7f c7 d3 e1 ; W Y R &0d82 c7 d1 e3 ; W R Y &0d85 c0 d0 e0 ; K K K ; sprite_01_chunks # Player facing left, frame 1 &0d88 0a 0d 0c 59 0e 0f 10 11 00 14 15 00 ; sprite_00_chunks # Player facing left, frame 0 &0d94 0a 0d 0c 59 0e 0f 10 11 18 19 1b 1a ; sprite_03_chunks # Player facing right, frame 1 &0da0 59 5b 0b 5a 11 12 0f 13 00 17 16 00 ; sprite_02_chunks # Player facing right, frame 0 &0dac 59 5b 0b 5a 11 12 0f 13 1c 1b 19 1d ; sprite_04_chunks # Player climbing, frame 0 &0db8 1e 1f 1f 20 21 22 23 24 00 24 25 00 ; sprite_05_chunks # Player climbing, frame 1 &0dc4 20 1f 1f 1e 24 22 23 21 00 25 24 00 ; sprite_06_chunks # Guard facing left, frame 0 &0dd0 34 27 26 33 28 29 00 18 2a ; sprite_07_chunks # Guard facing left, frame 1 &0dd9 34 27 26 33 28 29 18 2a 2a ; sprite_08_chunks # Guard facing right, frame 0 &0de2 26 27 2d 2b 45 2c 2a 1d 00 ; sprite_09_chunks # Guard facing right, frame 1 &0deb 26 27 2d 2b 45 2c 2a 2a 1d ; sprite_0a_chunks # Guard climbing, frame 0 &0df4 46 26 26 26 26 26 24 00 2a ; sprite_0b_chunks # Guard climbing, frame 1 &0dfd 26 26 46 26 26 26 2a 00 24 ; sprite_0c_chunks # Troll facing left, frame 0 &0e06 3c 3b 3a 00 40 47 48 49 00 41 44 00 ; sprite_0d_chunks # Troll facing left, frame 1 &0e12 3c 3b 3a 00 40 47 48 49 41 42 43 44 ; sprite_0e_chunks # Troll facing right, frame 0 ; sprite_10_chunks # Troll climbing, frame 0 &0e1e 00 3a 3b 3c 3d 3e 3f 40 00 41 44 00 ; sprite_0f_chunks # Troll facing right, frame 1 ; sprite_11_chunks # Troll climbing, frame 0 &0e2a 00 3a 3b 3c 3d 3e 3f 40 41 4a 41 44 ; sprite_12_chunks # Witch facing left, frame 0 ; sprite_13_chunks # Witch facing left, frame 0 &0e36 00 4d 4e 4f 00 00 4c 4c 50 51 52 53 ; sprite_14_chunks # Witch facing right, frame 0 ; sprite_15_chunks # Witch facing right, frame 1 &0e42 00 00 4f 56 4d 00 53 58 57 50 4c 4c ; sprite_16_chunks # Monkey facing left, frame 0 &0e4e 5f 60 61 62 63 66 ; sprite_17_chunks # Monkey facing left, frame 0 &0e54 5f 60 61 66 62 63 ; sprite_18_chunks # Monkey facing right, frame 0 &0e5a 64 60 5f 67 65 62 ; sprite_19_chunks # Monkey facing right, frame 0 &0e60 64 60 5f 65 62 67 ; sprite_1a_chunks # Monkey climbing, frame 0 &0e66 5f 60 5f 66 65 62 ; sprite_1b_chunks # Monkey climbing, frame 1 &0e6c 5f 60 5f 62 63 67 ; sprite_1c_chunks # Spider &0e72 69 6a 6b 6c 6d 64 00 68 00 61 ; unused &0e7c 00 00 81 82 ; initial_objects_state ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0e80 00 00 00 83 84 80 80 85 86 04 00 00 80 80 00 00 ; &00 # &00 - &0f unused &0e90 00 30 37 35 35 37 38 39 30 32 34 36 38 3a 3c 3e ; &10 # &10 - &17 used for treasure sprite &0ea0 40 42 00 00 80 80 12 12 12 12 00 00 00 00 00 00 ; &20 # &18 - &2f used for initial mover states &0e90 - &0e97 ; sprite_1d_chunks # Treasure ; unused # &0eb0 - &0eb1 is a copy of &0ecd - &0ece, &0eb0 2d 2c # sword_right_chunks ; crossed_swords_uncrossed_chunks &0eb2 2d 00 00 34 2c 00 00 33 ; crossed_swords_crossed_chunks &0eba 7b 2e 2f 7b 2c 00 00 33 ; wand_chunks &0ec2 30 31 31 30 ; selected_pocket_chunks &0ec6 30 32 32 32 30 ; sword_left_chunks &0ecb 34 33 ; sword_right_chunks &0ecd 2d 2c ; coin_chunks &0ecf 37 35 ; ruby_chunks &0ed1 38 39 ; gold_chunks &0ed3 35 36 37 ; bucket_chunks &0ed6 54 55 ; torch_chunks &0ed8 5d 5e 5c 00 ; unselected_pocket_chunks &0edc 30 30 30 30 30 ; stool_chunks &0ee1 7f 8e ; unused &0ee3 ff ; dead_player_chunks &0ee4 6f 00 00 75 76 77 6e 70 71 72 73 74 ; wizard_cross_sign_chunks &0ef0 69 87 6d 00 ; air_right_chunks &0ef4 89 8d 00 88 ; air_left_chunks &0ef8 89 8d 88 00 ; thrown_bucket_chunks &0efc 6f 89 6f 89 ; tile_chunks # Chunks start at bottom left of tile, then go up ; tile_0_chunks # TILE_EMPTY &0f00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0f10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; tile_1_chunks # TILE_WALL &0f20 01 02 01 02 01 01 01 01 02 01 02 01 01 01 01 01 &0f30 01 02 01 02 01 01 01 01 02 01 02 01 01 01 01 01 ; tile_2_chunks # TILE_SLOPE_UP_TO_LEFT &0f40 01 02 01 02 01 01 01 03 02 01 02 00 01 01 03 00 &0f50 01 02 00 00 01 03 00 00 02 00 00 00 03 00 00 00 ; tile_3_chunks # TILE_SLOPE_UP_TO_RIGHT &0f60 03 00 00 00 01 00 00 00 02 03 00 00 01 01 00 00 &0f70 01 02 03 00 01 01 01 00 02 01 02 03 01 01 01 01 ; tile_4_chunks # TILE_LADDER &0f80 00 00 00 00 05 05 05 05 04 04 04 04 04 04 04 04 &0f90 04 04 04 04 04 04 04 04 06 06 06 06 00 00 00 00 ; tile_5_chunks # TILE_LADDER_PLATFORM &0fa0 00 00 00 07 05 05 05 8f 04 04 04 4b 04 04 04 4b &0fb0 04 04 04 4b 04 04 04 4b 06 06 06 90 00 00 00 08 ; tile_6_chunks # TILE_PLATFORM &0fc0 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 08 &0fd0 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 ; tile_7_chunks # TILE_RAILING_LEFT &0fe0 07 07 00 00 00 09 00 00 00 09 00 00 00 09 00 00 &0ff0 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 ; tile_8_chunks # TILE_RAILING_RIGHT &1000 07 07 00 00 00 09 00 00 00 09 00 00 00 09 00 00 &1010 00 09 00 00 00 09 00 00 00 09 00 00 07 07 00 00 ; tile_9_chunks # TILE_PASSAGE &1020 03 09 00 08 01 07 07 07 02 01 02 01 01 01 01 01 &1030 01 02 01 02 01 01 01 01 02 07 07 07 03 09 00 08 ; tile_a_chunks # TILE_BED &1040 05 00 00 00 78 7a 00 00 78 7b 00 00 78 7c 00 00 &1050 78 7d 00 00 78 7e 00 00 78 79 00 00 06 06 00 00 ; tile_b_chunks # TILE_WATER_LADDER &1060 80 80 80 80 8a 8a 8a 8a 8c 8c 8c 8c 8c 8c 8c 8c &1070 8c 8c 8c 8c 8c 8c 8c 8c 8b 8b 8b 8b 80 80 80 80 ; tile_c_chunks # TILE_WATER &1080 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 &1090 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ; chunk_sprite_data &10a0 00 00 00 00 00 00 00 00 ; &00 &10a8 3f c0 c0 c0 c0 c0 ff c0 ; &01 &10b0 3f 6a 7f 7f 7f 7f 7f 6a ; &02 &10b8 00 00 00 00 3f c0 c0 c0 ; &03 &10c0 3f 3c 00 00 00 00 00 00 ; &04 &10c8 3d 3d 3d 3d 3d 3d 3d 3d ; &05 &10d0 3d 3d 3d 3d 3d 3d 3d 3d ; &06 &10d8 07 07 07 07 07 07 07 07 ; &07 &10e0 0f 0f 0f 03 00 00 00 00 ; &08 &10e8 00 00 0f 03 00 00 00 00 ; &09 &10f0 00 00 0c 00 93 00 00 00 ; &0a &10f8 0c 0c 0c 37 33 33 33 6b ; &0b &1100 0c 0c 0c 0f 0f 27 33 3f ; &0c &1108 0c 0c 0c 3b 33 33 33 97 ; &0d &1110 00 00 00 23 23 23 00 00 ; &0e &1118 03 03 c3 03 03 03 c3 03 ; &0f &1120 03 03 03 03 03 83 03 03 ; &10 &1128 0c 0c 3f 0c 0c 0c 0c 00 ; &11 &1130 03 03 03 03 03 43 03 03 ; &12 &1138 00 00 00 13 13 13 00 00 ; &13 &1140 0c 0c 86 86 83 03 03 03 ; &14 &1148 0c 0c 49 49 43 43 43 43 ; &15 &1150 0c 0c 49 49 43 03 03 03 ; &16 &1158 0c 0c 86 86 83 83 83 83 ; &17 &1160 00 00 00 00 00 83 83 83 ; &18 &1168 0c 0c 0c 0c 03 03 03 03 ; &19 &1170 00 03 03 03 03 83 83 00 ; &1a &1178 0c 0c 0c 0c 0c 00 00 00 ; &1b &1180 00 03 03 03 03 43 43 00 ; &1c &1188 00 00 00 00 00 43 43 43 ; &1d &1190 00 00 0c 00 33 33 03 03 ; &1e &1198 0c 0c 0c 0f 0f 0f 33 3f ; &1f &11a0 33 33 0c 03 03 03 03 03 ; &20 &11a8 03 03 03 03 03 03 00 00 ; &21 &11b0 06 06 17 06 06 06 06 03 ; &22 &11b8 09 09 2b 09 09 09 09 03 ; &23 &11c0 03 03 03 03 00 00 00 00 ; &24 &11c8 0c 0c 0c 0c 03 03 03 03 ; &25 &11d0 cc cc cc cc cc cc cc cc ; &26 &11d8 cc cc c3 cc c3 cc c3 cc ; &27 &11e0 cc c9 c6 cc cc c9 c6 cc ; &28 &11e8 cc cc cc cc c6 cc cc cc ; &29 &11f0 cc cc cc cc cc cc 03 03 ; &2a &11f8 cc cc cc cc c9 cc cc cc ; &2b &1200 15 15 03 03 03 03 03 03 ; &2c &1208 15 15 15 15 15 15 15 15 ; &2d &1210 2a 2a 15 15 15 15 2a 2a ; &2e &1218 15 15 2a 2a 2a 2a 15 15 ; &2f &1220 00 00 00 00 00 3f 3f 00 ; &30 &1228 00 00 00 00 00 30 30 00 ; &31 &1230 00 00 c0 c0 00 3f 3f 00 ; &32 &1238 2a 2a 03 03 03 03 03 03 ; &33 &1240 2a 2a 2a 2a 2a 2a 2a 2a ; &34 &1248 00 00 0a 0f 0f 0f 0a 00 ; &35 &1250 00 00 00 0f 0f 0f 00 00 ; &36 &1258 00 00 05 0f 0f 0f 05 00 ; &37 &1260 00 00 00 01 03 03 01 00 ; &38 &1268 00 00 00 02 03 03 02 00 ; &39 &1270 00 0c 0c 0c 0c 0c 0c 3f ; &3a &1278 0c 0c 0c 09 0c 00 0c 00 ; &3b &1280 0c 0c 0c 00 00 00 00 00 ; &3c &1288 00 04 04 04 04 04 04 14 ; &3d &1290 0c 0c 0c 0c 86 49 0c 3c ; &3e &1298 08 0c 86 49 0c 0c c3 3c ; &3f &12a0 00 00 00 00 0c 0c 00 00 ; &40 &12a8 14 14 14 04 04 0c 0c 04 ; &41 &12b0 3c 3c 69 3c 1c 08 08 00 ; &42 &12b8 69 96 3c 04 04 04 04 00 ; &43 &12c0 28 28 08 08 0c 0c 08 08 ; &44 &12c8 cc c6 c9 cc cc c6 c9 cc ; &45 &12d0 00 00 00 00 00 cc cc cc ; &46 &12d8 04 0c 49 86 0c 0c c3 3c ; &47 &12e0 0c 0c 0c 0c 49 86 0c 3c ; &48 &12e8 00 08 08 08 08 08 08 28 ; &49 &12f0 96 69 3c 28 08 08 08 00 ; &4a &12f8 0f 0f 0f 03 00 00 00 00 ; &4b &1300 00 00 33 00 00 00 00 00 ; &4c &1308 00 00 00 00 0c 00 03 00 ; &4d &1310 0c 0c 0c 0c 0c 2b 03 12 ; &4e &1318 00 00 00 00 0c 00 30 30 ; &4f &1320 30 30 30 30 00 00 00 0c ; &50 &1328 20 20 31 30 30 18 08 08 ; &51 &1330 00 11 33 11 00 20 20 00 ; &52 &1338 00 33 33 33 00 00 00 00 ; &53 &1340 00 15 2a 2a 03 03 03 03 ; &54 &1348 00 2a 15 15 03 03 03 03 ; &55 &1350 0c 0c 0c 0c 0c 17 03 21 ; &56 &1358 10 10 32 30 30 24 04 04 ; &57 &1360 00 22 33 22 00 10 10 00 ; &58 &1368 00 00 0c 00 00 00 00 00 ; &59 &1370 00 00 0c 00 63 00 00 00 ; &5a &1378 0c 0c 0c 0f 0f 1b 33 3f ; &5b &1380 04 04 04 04 04 04 04 00 ; &5c &1388 00 45 cf 8b 17 17 1d 0c ; &5d &1390 00 00 00 8a 00 02 08 08 ; &5e &1398 00 00 00 00 03 00 00 00 ; &5f &13a0 0c 03 03 03 03 03 03 03 ; &60 &13a8 08 08 08 03 01 01 02 02 ; &61 &13b0 00 00 00 00 00 00 00 03 ; &62 &13b8 02 02 02 02 02 02 02 02 ; &63 &13c0 04 04 04 03 02 02 01 01 ; &64 &13c8 01 01 01 01 01 01 01 01 ; &65 &13d0 01 01 01 03 00 00 00 00 ; &66 &13d8 02 02 02 03 00 00 00 00 ; &67 &13e0 0c 00 00 00 00 00 00 00 ; &68 &13e8 02 02 01 00 00 01 02 02 ; &69 &13f0 00 00 00 0c 10 18 04 0c ; &6a &13f8 2a 2a 0c 0c 0c 0c 0c 0c ; &6b &1400 00 00 00 0c 20 24 08 0c ; &6c &1408 01 01 02 00 00 02 01 01 ; &6d &1410 0c 0c 0c 0c 0c 0c 86 86 ; &6e &1418 00 00 00 00 00 00 86 86 ; &6f &1420 93 3b 33 1b 0f 0f 00 00 ; &70 &1428 83 23 23 23 23 0e 86 86 ; &71 &1430 21 21 03 03 03 2e 2e 2e ; &72 &1438 12 12 21 03 03 49 49 49 ; &73 &1440 0c 0c 0c 0c 49 00 00 00 ; &74 &1448 00 00 00 00 00 93 93 83 ; &75 &1450 00 83 83 00 00 63 63 43 ; &76 &1458 00 03 03 03 0c 0c 0c 0c ; &77 &1460 3f 3f 3f 3c 3c 00 00 00 ; &78 &1468 00 00 00 00 00 00 3f 3f ; &79 &1470 00 51 51 f6 f6 f8 f6 51 ; &7a &1478 a2 f9 f9 f4 f0 f0 f4 f1 ; &7b &1480 00 00 00 a2 f9 f9 f6 00 ; &7c &1488 00 51 f6 f6 f8 f8 f0 f8 ; &7d &1490 00 00 a2 a2 a8 f9 f1 a8 ; &7e &1498 0f 0f 0a 0a 0a 0f 0a 0a ; &7f &14a0 30 30 30 30 30 30 30 30 ; &80 &14a8 10 10 10 10 30 01 01 01 ; &81 &14b0 20 20 20 20 30 2b 02 02 ; &82 &14b8 00 00 10 10 30 30 05 05 ; &83 &14c0 30 30 20 20 00 00 00 00 ; &84 &14c8 30 30 10 00 00 00 00 00 ; &85 &14d0 30 30 30 30 10 00 00 00 ; &86 &14d8 00 00 00 03 03 00 00 00 ; &87 &14e0 3c 3c 3c 3c 3c 3c 3c 3c ; &88 &14e8 00 00 00 00 00 69 3c 69 ; &89 &14f0 3c 3c 3c 3c 3c 3c 3c 3c ; &8a &14f8 3c 3c 3c 3c 3c 3c 3c 3c ; &8b &1500 3c 3c 30 30 30 30 30 30 ; &8c &1508 00 00 00 00 00 96 3c 96 ; &8d &1510 0f 0f 05 05 05 0f 05 05 ; &8e &1518 0f 0f 0f 03 3d 3d 3d 3d ; &8f &1520 0f 0f 0f 03 3d 3d 3d 3d ; &90 ; relocated_entry_point &1528 20 80 08 JSR &0880 ; initialise_mode &152b 20 cc 2b JSR &2bcc ; set_prison_bed_fire_colours_to_black &152e 4c 3d 2a JMP &2a3d ; start_game ; play_game &1531 20 6a 01 JSR &016a ; set_wall_colour &1534 a9 50 LDA #&50 # Scroll into screen in 80 steps &1536 85 72 STA &72 ; count ; scroll_into_screen_loop &1538 20 01 21 JSR &2101 ; adjust_crtc_and_screen_addresses_for_scrolling_right &153b 20 4f 21 JSR &214f ; set_screen_address &153e 20 a5 20 JSR &20a5 ; plot_right_edge &1541 c6 72 DEC &72 ; count &1543 d0 f3 BNE &1538 ; scroll_into_screen_loop ; main_game_loop &1545 a5 75 LDA &75 ; death_timer # &ff if treasure found, &80 after player finishes dying &1547 10 03 BPL &154c ; not_end_of_life_or_game &1549 4c 91 29 JMP &2991 ; end_of_life_or_game ; not_end_of_life_or_game &154c a5 ec LDA &ec ; os_most_recently_pressed_key &154e c9 f0 CMP #&f0 ; ESCAPE &1550 d0 03 BNE &1555 ; escape_not_pressed &1552 4c 3d 2a JMP &2a3d ; start_game # If ESCAPE is pressed, restart game ; escape_not_pressed &1555 e6 67 INC &67 ; time_low &1557 d0 0a BNE &1563 ; skip_decreasing_time_bonus &1559 e6 68 INC &68 ; time_high &155b a5 69 LDA &69 ; time_bonus &155d c9 01 CMP #&01 &155f f0 02 BEQ &1563 ; skip_decreasing_time_bonus &1561 c6 69 DEC &69 ; time_bonus # Reduce time bonus by 10 points every 256 frames ; skip_decreasing_time_bonus &1563 ae 17 0c LDX &0c17 ; objects_x_high + OBJECT_PLAYER # What level is the player on? &1566 ad cf 0b LDA &0bcf ; objects_x_low + OBJECT_PLAYER &1569 dd f6 09 CMP &09f6,X ; level_save_positions_x_low # Is the player at that level's save position? &156c d0 48 BNE &15b6 ; skip_save_position &156e 86 89 STX &89 ; saved_level # If so, use the save position &1570 bd 08 0a LDA &0a08,X ; level_save_positions_used # Has the save position already been used? &1573 30 17 BMI &158c ; save_position_already_used &1575 a9 ff LDA #&ff # Set to negative to indicate save position used &1577 9d 08 0a STA &0a08,X ; level_save_positions_used &157a e6 57 INC &57 ; score # Score 10 points for every save position used &157c e0 00 CPX #&00 &157e f0 08 BEQ &1588 ; summon_wizard # Wizard appears on levels 0, 2 and 4 &1580 e0 02 CPX #&02 &1582 f0 04 BEQ &1588 ; summon_wizard &1584 e0 04 CPX #&04 &1586 d0 04 BNE &158c ; save_position_already_used ; summon_wizard &1588 a9 30 LDA #&30 # Set positive to make wizard appear &158a 85 34 STA &34 ; wizard_state ; save_position_already_used # Store state of objects at save position &158c a5 35 LDA &35 ; bucket_contains_water &158e 85 37 STA &37 ; saved_bucket_contains_water &1590 a2 03 LDX #&03 ; save_pockets_loop &1592 bd c0 09 LDA &09c0,X ; pockets &1595 9d f1 09 STA &09f1,X ; saved_pockets &1598 ca DEX &1599 10 f7 BPL &1592 ; save_pockets_loop &159b a5 9c LDA &9c ; carrying &159d 85 14 STA &14 ; saved_carrying &159f a2 0b LDX #&0b ; OBJECT_BUCKET ; save_objects_loop &15a1 bd a0 0b LDA &0ba0,X ; objects_x_low &15a4 9d 24 0d STA &0d24,X ; saved_objects_x_low &15a7 bd e8 0b LDA &0be8,X ; objects_x_high &15aa 9d f8 0c STA &0cf8,X ; saved_objects_x_high &15ad bd 30 0c LDA &0c30,X ; objects_y &15b0 9d 04 0d STA &0d04,X ; save_objects_y &15b3 ca DEX &15b4 10 eb BPL &15a1 ; save_objects_loop ; skip_save_position &15b6 a9 ff LDA #&ff &15b8 85 9d STA &9d ; screen_scrolling_direction # Set to negative to indicate not scrolling &15ba 85 30 STA &30 ; mover_offset &15bc 85 33 STA &33 ; movers_replot_stage # Set to &ff to start replotting in first stage &15be a9 13 LDA #&13 ; Wait for Vertical Retrace &15c0 20 f4 ff JSR &fff4 ; OSBYTE &15c3 ad 79 fe LDA &fe79 ; User VIA timer 2 counter MSB &15c6 85 32 STA &32 ; timer_at_vsync &15c8 20 5a 1e JSR &1e5a ; check_for_information &15cb 20 ec 15 JSR &15ec ; update_level &15ce 20 ad 2d JSR &2dad ; update_wizard &15d1 20 58 17 JSR &1758 ; update_player &15d4 20 fb 20 JSR &20fb ; adjust_crtc_and_screen_addresses_if_scrolling &15d7 20 01 2c JSR &2c01 ; replot_pockets &15da 20 ea 2c JSR &2cea ; replot_movers_with_time_limit &15dd 20 92 20 JSR &2092 ; update_screen_address_and_plot_edge_of_screen &15e0 20 e4 2c JSR &2ce4 ; replot_movers_without_time_limit &15e3 20 6e 1d JSR &1d6e ; update_thrown_object &15e6 20 b7 2f JSR &2fb7 ; update_objects &15e9 4c 45 15 JMP &1545 ; main_game_loop ; update_level &15ec ac 17 0c LDY &0c17 ; objects_x_high + OBJECT_PLAYER &15ef b9 11 0a LDA &0a11,Y ; level_update_handlers_jump_offsets &15f2 8d f6 15 STA &15f6 ; level_update_handler_jump_offset &15f5 10 ff BPL &15f6 # actually BPL &15f7 + level_update_handler_jump_offset # Branch to handler for player's level ; update_level_0 &15f7 4c 80 18 JMP &1880 ; update_green_guards ; update_level_1 &15fa 20 80 18 JSR &1880 ; update_green_guards &15fd 4c 1b 2b JMP &2b1b ; update_prison ; update_level_2 &1600 4c 7b 26 JMP &267b ; update_monkeys_and_spiders ; update_level_3 &1603 20 7b 26 JSR &267b ; update_monkeys_and_spiders &1606 4c 44 23 JMP &2344 ; update_troll ; update_level_4 &1609 20 44 23 JSR &2344 ; update_troll &160c 4c fc 22 JMP &22fc ; update_red_guards ; update_level_5 &160f 20 44 23 JSR &2344 ; update_troll &1612 20 15 23 JSR &2315 ; update_yellow_guards &1615 20 20 23 JSR &2320 ; check_for_treasure ; update_level_8 &1618 4c 39 2e JMP &2e39 ; check_for_player_in_water ; update_level_6 ; update_level_7 &161b 20 39 2e JSR &2e39 ; check_for_player_in_water &161e 4c c5 25 JMP &25c5 ; update_witch ; consider_climbing_ladder # Called for player and movers &1621 a5 71 LDA &71 ; vertical_direction # Is the mover moving vertically? &1623 30 7a BMI &169f ; clear_vertical_direction_and_leave_with_carry_set &1625 bd 18 0d LDA &0d18,X ; objects_moving - &18 &1628 c9 04 CMP #&04 ; FRAME_UP_AND_DOWN &162a 30 0d BMI &1639 ; consider_climbing # Was the mover moving horizontally? &162c 20 c0 00 JSR &00c0 ; check_if_mover_should_be_updated &162f f0 08 BEQ &1639 ; consider_climbing # If not, is it scheduled to move this frame? &1631 a9 ff LDA #&ff ; HORIZONTAL_AND_VERTICAL_NONE &1633 85 71 STA &71 ; vertical_direction &1635 85 70 STA &70 ; horizontal_direction &1637 18 CLC # Leave with carry clear to indicate not moving &1638 60 RTS ; consider_climbing &1639 bd a0 0b LDA &0ba0,X ; objects_x_low &163c 85 77 STA &77 ; x_low &163e 29 07 AND #&07 # Can't climb ladder at very left of tile &1640 f0 5d BEQ &169f ; clear_vertical_direction_and_leave_with_carry_set &1642 18 CLC &1643 65 74 ADC &74 ; object_width &1645 c9 08 CMP #&08 # Can't climb ladder if beyond right of tile &1647 10 56 BPL &169f ; clear_vertical_direction_and_leave_with_carry_set &1649 bd e8 0b LDA &0be8,X ; objects_x_high &164c 85 78 STA &78 ; x_high &164e a5 71 LDA &71 ; vertical_direction &1650 f0 15 BEQ &1667 ; consider_tile_for_climbing # Is the mover moving up? &1652 bd 30 0c LDA &0c30,X ; objects_y &1655 85 76 STA &76 ; y &1657 c6 76 DEC &76 ; y # If not, can't climb down below bottom of screen &1659 30 44 BMI &169f ; clear_vertical_direction_and_leave_with_carry_set &165b 20 69 07 JSR &0769 ; get_map_tile # Is the tile below TILE_EMPTY? &165e d0 1f BNE &167f ; consider_tile_for_climbing # If not, consider whether it can be climbed &1660 68 PLA # If so, remove consider_climbing_ladder from stack &1661 68 PLA &1662 4c 60 18 JMP &1860 ; set_falling ; unused &1665 30 38 BMI &169f ; clear_vertical_direction_and_leave_with_carry_set ; consider_tile_for_climbing_up &1667 bd 30 0c LDA &0c30,X ; objects_y # Consider the tile above the player &166a 18 CLC &166b 65 73 ADC &73 ; object_height &166d 85 76 STA &76 ; y &166f 20 69 07 JSR &0769 ; get_map_tile &1672 c9 01 CMP #&01 ; TILE_WALL &1674 f0 29 BEQ &169f ; clear_vertical_direction_and_leave_with_carry_set &1676 c9 04 CMP #&04 ; TILE_LADDER &1678 f0 14 BEQ &168e ; is_ladder &167a bd 30 0c LDA &0c30,X ; objects_y &167d 85 76 STA &76 ; y ; consider_tile_for_climbing &167f 20 # Unrelocated code continues at start of block &06 #1680 69 07 JSR &0769 ; get_map_tile #1682 c9 0b CMP #&0b ; TILE_WATER_LADDER # Is the tile a ladder? #1684 f0 08 BEQ &168e ; is_ladder #1686 c9 06 CMP #&06 ; TILE_PLATFORM # (matches &04 TILE_LADDER and &05 TILE_LADDER_PLATFORM) #1688 10 15 BPL &169f ; clear_vertical_direction_and_leave_with_carry_set #168a c9 04 CMP #&04 ; TILE_LADDER #168c 30 11 BMI &169f ; clear_vertical_direction_and_leave_with_carry_set ; is_ladder #168e bd 30 0c LDA &0c30,X ; objects_y #1691 29 01 AND #&01 # Animate sprite depending on position on ladder #1693 18 CLC #1694 69 04 ADC #&04 ; FRAME_UP_AND_DOWN #1696 9d 18 0d STA &0d18,X ; objects_moving - &18 #1699 a9 ff LDA #&ff ; HORIZONTAL_NONE #169b 85 70 STA &70 ; horizontal_direction #169d 18 CLC # Leave with carry clear to indicate climbing #169e 60 RTS ; clear_vertical_direction_and_leave_with_carry_set #169f a9 ff LDA #&ff ; VERTICAL_NONE #16a1 85 71 STA &71 ; vertical_direction #16a3 38 SEC # Leave with carry set to indicate not climbing #16a4 60 RTS # &3e00 - &3ecf is moved to &0100 - &01cf at &0b8f in loader ; move_object_left_or_right &0100 a5 70 LDA &70 ; horizontal_direction &0102 30 16 BMI &011a ; leave &0104 d0 0c BNE &0112 ; move_object_right ; move_object_right &0106 bd a0 0b LDA &0ba0,X ; objects_x_low &0109 d0 03 BNE &010e ; skip_overflow_left &010b de e8 0b DEC &0be8,X ; objects_x_high ; skip_overflow_left &010e de a0 0b DEC &0ba0,X ; objects_x_low # Move left one subtile for HORIZONTAL_LEFT &0111 60 RTS ; move_object_right &0112 fe a0 0b INC &0ba0,X ; objects_x_low # Move right one subtile for HORIZONTAL_RIGHT &0115 d0 03 BNE &011a ; skip_overflow &0117 fe e8 0b INC &0be8,X ; objects_x_high ; skip_overflow_right ; leave &011a 60 RTS ; get_tile_chunk &011b a5 8b LDA &8b ; tile_type &011d 0a ASL A &011e 0a ASL A &011f 0a ASL A &0120 0a ASL A &0121 0a ASL A &0122 85 8d STA &8d ; tile_chunk_address_low &0124 a9 0f LDA #&0f ; &0f00 = tile_chunks + tile_type * 32 &0126 69 00 ADC #&00 &0128 85 8e STA &8e ; tile_chunk_address_high ; get_tile_chunk_from_previous_tile &012a a5 7c LDA &7c ; x_subtile &012c 0a ASL A &012d 0a ASL A &012e 18 CLC &012f 65 7b ADC &7b ; y_subtile &0131 a8 TAY &0132 84 10 STY &10 ; tile_chunk_offset ; get_tile_chunk_from_previous_tile_using_offset &0134 a9 00 LDA #&00 &0136 85 79 STA &79 ; tmp &0138 b1 8d LDA (&8d),Y ; tile_chunk_address &013a 0a ASL A &013b 26 79 ROL &79 ; tmp &013d 0a ASL A &013e 26 79 ROL &79 ; tmp &0140 0a ASL A &0141 26 79 ROL &79 ; tmp &0143 69 a0 ADC #&a0 &0145 85 91 STA &91 ; tile_sprite_address_low &0147 a9 10 LDA #&10 ; &10a0 = chunk_sprite_data &0149 65 79 ADC &79 ; tmp &014b 85 92 STA &92 ; tile_sprite_address_high &014d 60 RTS ; calculate_sprite_address_from_chunk &014e a9 00 LDA #&00 &0150 85 79 STA &79 ; tmp &0152 a4 5b LDY &5b ; sprite_offset &0154 b1 7f LDA (&7f),Y ; chunk_address &0156 0a ASL A &0157 26 79 ROL &79 ; tmp &0159 0a ASL A &015a 26 79 ROL &79 ; tmp &015c 0a ASL A &015d 26 79 ROL &79 ; tmp &015f 69 a0 ADC #&a0 &0161 85 8f STA &8f ; sprite_address_low &0163 a9 10 LDA #&10 ; &10a0 = chunk_sprite_data &0165 65 79 ADC &79 ; tmp &0167 85 90 STA &90 ; sprite_address_high &0169 60 RTS ; set_wall_colour &016a ad 17 0c LDA &0c17 ; objects_x_high + OBJECT_PLAYER &016d a2 81 LDX #&81 ; R # Set colour 8 (wall body) to red &016f c9 02 CMP #&02 &0171 30 15 BMI &0188 ; set_colour &0173 a2 85 LDX #&85 ; M # Set colour 8 (wall body) to magenta &0175 c9 06 CMP #&06 &0177 30 0f BMI &0188 ; set_colour &0179 a2 82 LDX #&82 ; G # Set colour 8 (wall body) to green &017b c9 06 CMP #&06 &017d d0 09 BNE &0188 ; set_colour &017f ad cf 0b LDA &0bcf ; objects_x_low + OBJECT_PLAYER &0182 c9 80 CMP #&80 &0184 10 02 BPL &0188 &0186 a2 85 LDX #&85 ; M # Set colour 8 (wall body) to magenta ; set_colour &0188 a9 9b LDA #&9b ; Write to Video ULA palette register and RAM copy &018a 20 f4 ff JSR &fff4 ; OSBYTE &018d a2 90 LDX #&90 ; K # Set colour 9 (player edges) to black &018f 4c f4 ff JMP &fff4 ; OSBYTE ; prepare_pocket_for_plotting &0192 a9 1c LDA #&1c &0194 85 76 STA &76 ; y &0196 bd c5 09 LDA &09c5,X ; pockets_x_low &0199 38 SEC &019a e9 01 SBC #&01 &019c 85 77 STA &77 ; x_low &019e bd ca 09 LDA &09ca,X ; pockets_x_high &01a1 e9 00 SBC #&00 &01a3 85 78 STA &78 ; x_high &01a5 a9 01 LDA #&01 &01a7 85 73 STA &73 ; object_height &01a9 a9 05 LDA #&05 &01ab 85 74 STA &74 ; object_width &01ad a9 0e LDA #&0e &01af 85 80 STA &80 ; chunk_address_high &01b1 60 RTS ; unused # &01b2 - &01ce is a copy of &2075 - &2091 &01b2 bd 30 0c LDA &0c30,X ; objects_y # (check_for_object_changing_level) &01b5 f0 06 BEQ &01bd &01b7 c9 19 CMP #&19 &01b9 10 02 BPL &01bd &01bb 18 CLC &01bc 60 RTS &01bd bc e8 0b LDY &0be8,X ; objects_x_high &01c0 bd a0 0b LDA &0ba0,X ; objects_x_low &01c3 d9 23 0a CMP &0a23,Y ; level_openings_left &01c6 90 f3 BCC &01bb ; leave_with_carry_clear &01c8 d9 1a 0a CMP &0a1a,Y ; level_openings_right &01cb b0 ee BCS &01bb ; leave_with_carry_clear &01cd 38 SEC &01ce 60 RTS ; unused &01cf c5 ; entry_point ; move_3000_to_0880_loop # Move &3000 - &3dff to &0880 - &167f &3ed0 a9 80 LDA #&80 &3ed2 85 ae STA &ae ; target_address_low &3ed4 a9 08 LDA #&08 &3ed6 85 af STA &af ; target_address_high &3ed8 a0 00 LDY #&00 &3eda 84 ac STY &ac ; source_address_low &3edc a9 30 LDA #&30 &3ede 85 ad STA &ad ; source_address_high &3ee0 b1 ac LDA (&ac),Y ; source_address &3ee2 91 ae STA (&ae),Y ; target_address &3ee4 88 DEY &3ee5 d0 f9 BNE &3ee0 ; move_3000_to_0880_loop &3ee7 e6 ad INC &ad ; source_address_high &3ee9 e6 af INC &af ; target_address_high &3eeb a5 ad LDA &ad ; source_address_high &3eed c9 3e CMP #&3e &3eef d0 ef BNE &3ee0 ; move_3000_to_0880_loop &3ef1 4c 28 15 JMP &1528 ; relocated_entry_point ; unused # &3ef4 - &3efa is a copy of &0b9a - &0ba0 from loader &3ef4 99 ... &99 ; selected_pocket &3ef5 85 9a STA &9a ; previous_selected_pocket &3ef7 85 9d STA &9d ; screen_scrolling_direction &3ef9 85 9e STA &9e ; player_facing # &0129 - &012a is loaded in 1 block of &02 bytes (block &31) ; unused # Values are unused, and overwritten at &0b8f in loader &0129 75 67 # &00c7 - &00c8 are set by the load address (29 01)