Knight Lore disassembly ======================= Published by Ultimate Play the Game in 1984, Knight Lore is widely regarded as an influential work in gaming history. The first game to employ the Filmation game engine, it used novel graphics techniques to present an isometric 3D maze containing puzzles and traps for the player to solve. Originally released for the ZX Spectrum, it was converted to the BBC Micro in 1985 by Paul Proctor. The following disassembly was created by reverse engineering binary images for the latter system, without access to any source code. It is nevertheless reasonably complete, allowing the technical approaches used to be understood. The author of this disassembly imposes no additional copyright restrictions beyond those already present on the game itself. It is provided for educational purposes only, and it is hoped that the original authors will accept it in the good faith it was intended - as a tribute to their skills. Technical notes =============== The game and its custom tape loader are protected by a VIA-based decryption routine written by Kevin Edwards. The disassembly analyses each stage after decryption has taken place. At the lowest level, the plotting routine uses an AND/OR approach for image masking. Although using an eight pixels per byte graphics mode, sprites can be shifted by an arbitrary number of pixels using bit rotation, as well as flipped horizontally by means of a pre-calculated lookup table. Rather than copying to screen memory directly, sprite and mask staging areas and a screen buffer are used. The latter is divided into a series of eight pixel wide slices, carefully tracked so that only those known to have changed are updated. The screen is conveniently 256 bytes as well as 256 pixels wide when the system's use of eight line blocks is taken into account, making this approach particularly neat. There is use of self-modifying code, plus unofficial OS routines. Each room can have up to forty objects, although between twelve and sixteen of these are taken by background scenery. A further two are reserved for the player's feet (object 0) and head (object 1), and two more (objects 2 and 3) for any charms that may be in the room. Consequently, no more than two charms may be present in any one room. There are ninety combinations of objects and sprites, taking into account the various frames used for animation. Although the rooms are arranged on a 16x16 map, only 128 rooms have objects defined. Internally, the game keeps track of an x dimension running from the bottom left to the top right of the screen (corresponding to south-north on the map), a z dimension running from the top left to the bottom right of the screen (corresponding to west-east on the map), and a y dimension running from the bottom to the top of the screen. Two different ways of representing direction are used, one allowing combination of movements in the x and z dimensions. position map room number player facing direction y+ z- x+ W N -01 -10 1 2 1 2 | \ / \ / \ / \ / \ / | x x x x x | / \ / \ / \ / \ / \ y- x- z+ S E +10 +01 0 3 8 4 Map === 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +--+--+--+--+ +--+--+--+--+ +--+--+--+ 00 |C3 C2| |C1 C3| |C6 C3| 0f + +--+ + + + + + + + + +--+ + 10 | | | | | | C2 | | | | | 1f + +--+ + + + + + + + + +--+ + 20 |C1 C4| | |C5 | | C5| 2f +--+--+--+ + +--+ +--+--+ +--+--+ + 30 | | | | | | 3f + +--+ + + +--+--+ + + 40 |** C1| | | |C7 C3| | | 4f + +--+ + +--+ + + + + + 50 | | | |C1| | | | | 5f + + + + + +--+ + + + 60 | | | | | | | | | 6f + +--+--+--+ + +--+--+ +--+--+--+ + 70 | C5 ## C8 **| 7f N +--+--+--+--+ + +--+--+--+--+--+--+--+ 80 | |C7 C8| 8f W-+-E + +--+--+ + +--+ +--+--+--+--+--+ 90 | | | | | | | C5 C7| 9f S + + + + + +--+--+--+--+ + + a0 | | | | | |C2 | af +--+--+--+--+ +--+--+ + + +--+ + b0 |C6 C6 ** **| | | | bf + +--+--+--+ +--+--+ + + + + c0 | | | | | |C8| | | cf + +--+--+ + + + + + +--+--+ + d0 | C6| | | |C2| | | **| df + +--+ + + + +--+ + + +--+ + e0 | | | | | | | | | | | | ef + +--+ +--+ + + +--+--+--+--+ +--+ + f0 |C7 C4| |C8 C4 C4| ff +--+--+--+--+--+ +--+--+--+--+--+--+--+--+ f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff Cx = charm type x, ** = starting room, ## = cauldron A screenshot map may be found at: http://www.level7.org.uk/miscellany/knightlore-map.png Interesting pokes ================= &143b = &a9, &143c = &01 infinite lives &1696 = &a9, &1697 = &01 infinite time &182f = &60 no spasms or transformations &1751 = x set height of jumps to x (default = &07; &0c is enough to clear most obstacles) &2647 = &ea, &2648 = &ea, &2649 = &ea don't kill the player if they move into something deadly &2d64 = &a9, &2d65 = &00 don't kill the player if they fall onto something deadly &26bb = &60 don't kill the player under other otherwise deadly circumstances (must be combined with the previous two for the game to be playable) &1591 = &91 allow any charm to be accepted by the cauldron &15d7 = &a9, &15d8 = &00 require only one charm to be deposited in order to win the game &14e5 a0 0c LDY #&0c # R12: screen start address, high &14e7 a9 0d LDA #&0d # &0d for screen buffer, &0a for screen memory &14e9 8c 00 fe STY &fe00 # Write to video controller (register number) &14ec 8d 01 fe STA &fe01 # Write to video controller (register value) &14ef c8 INY # R13; screen start address, low &14f0 a9 60 LDA #&60 # &60 for screen buffer, &80 for screen memory &14f2 8c 00 fe STY &fe00 # Write to video controller (register number) &14f5 8d 01 fe STA &fe01 # Write to video controller (register value) display screen buffer instead of screen memory (no sun or moon update). This reveals how the screen buffer is upside-down compared to the screen, as well as the constant wiping and redrawing that takes place behind the scenes. Tape protection disassembly =========================== ; Knight ; 000c00 000cea 000301 ; unused &0c00 54 61 70 65 20 70 72 6f 74 65 63 74 69 6f 6e 20 ; "Tape protection " &0c10 73 79 73 74 65 6d 20 64 65 73 69 67 6e 65 64 20 ; "system designed " &0c20 61 6e 64 20 69 6d 70 6c 65 6d 65 6e 74 65 64 20 ; "and implemented " &0c30 62 79 20 4b 65 76 69 6e 20 45 64 77 61 72 64 73 ; "by Kevin Edwards" &0c40 20 28 63 29 20 31 39 38 35 2e 20 54 61 70 65 20 ; " (c) 1985. Tape " &0c50 74 6f 20 64 69 73 63 20 74 72 61 6e 73 66 65 72 ; "to disc transfer" &0c60 20 69 73 20 6d 61 64 65 20 76 65 72 79 20 76 65 ; " is made very ve" &0c70 72 79 20 76 65 72 79 20 76 65 72 79 20 61 77 6b ; "ry very very awk" &0c80 77 61 72 64 2e 20 49 66 20 79 6f 75 20 70 6c 61 ; "ward. If you pla" &0c90 6e 20 74 6f 20 74 72 61 6e 73 66 65 72 20 74 68 ; "n to transfer th" &0ca0 69 73 20 70 72 6f 67 72 61 6d 20 74 6f 20 64 69 ; "is program to di" &0cb0 73 63 20 79 6f 75 20 77 69 6c 6c 20 73 70 65 6e ; "sc you will spen" &0cc0 64 20 6d 61 6e 79 20 68 6f 75 72 73 20 61 6e 64 ; "d many hours and" &0cd0 20 79 6f 75 27 6c 6c 20 66 61 69 6c 20 2e 2e 62 ; " you'll fail ..b" &0ce0 79 65 20 2e 2e 2e 4b 65 76 2e ; "ye ...Kev." ; entry_point ; via_decryption &0cea 78 SEI &0ceb a9 df LDA #&df # Set User VIA timer 2 to timed interrupt &0ced 2d 6b fe AND &fe6b ; User VIA auxiliary control register &0cf0 8d 6b fe STA &fe6b ; User VIA auxiliary control register &0cf3 a9 a0 LDA #&a0 # Enable interrupts for User VIA timer 2 &0cf5 8d 6e fe STA &fe6e ; User VIA interrupt enable register &0cf8 a9 ff LDA #&ff &0cfa 8d 68 fe STA &fe68 ; User VIA timer 2 counter LSB &0cfd 8d 69 fe STA &fe69 ; User VIA timer 2 counter MSB &0d00 a2 00 LDX #&00 ; via_decryption_loop &0d02 ad 00 0d LDA &0d00 # Runs from &0d00 to &0dff, # actually LDA &0d00 + via_decryption_offset # EORs all of &0e00 - &0eff on every loop &0d05 ee 1d 0d INC &0d1d + via_decryption_eor &0d08 18 CLC &0d09 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0d0c a8 TAY &0d0d ad 1d 0d LDA &0d1d ; via_decryption_eor &0d10 4d fc ff EOR &fffc ; os_reset_address_low # Ensure 6502 reset vector hasn't been changed &0d13 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0d16 8d 1b 0d STA &0d1b ; via_decryption_add &0d19 98 TYA &0d1a 69 ff ADC #&ff # actually ADC via_decryption_add &0d1c 49 00 EOR #&00 # actually EOR via_decryption_eor &0d1e 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0d21 4d 40 d9 EOR &d940 ; os_default_vector_table # Ensure OS default vector table hasn't been changed # actually EOR &d900 + via_decryption_rom_offset_one &0d24 ee 1d 0d INC &0d1d ; via_decryption_eor &0d27 4d 69 fe EOR &fe69 ; User VIA timer 2 counter MSB &0d2a 4d cd d9 EOR &d9cd ; os_reset_handler # Ensure OS reset handler hasn't been changed # actually EOR &d900 + via_decryption_rom_offset_two &0d2d 5d 02 0d EOR &0d02,X ; via_decryption_loop &0d30 4d 1c dc EOR &dc1c ; os_irq_handler # Ensure OS main IRQ handler hasn't been changed # actually EOR &dc00 + via_decryption_rom_offset_three &0d33 5d 00 0e EOR &0e00,X ; payload &0d36 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0d39 4d d9 ea EOR &ead9 ; os_break_intercept_handler # Ensure OS break intercept handler hasn't been changed # actually EOR &ea00 + via_decryption_rom_offset_four # (OSBYTE 247 (&f7), calls &0287 after BREAK) &0d3c 38 SEC &0d3d 6d 03 0d ADC &0d03 ; via_decryption_offset &0d40 4d fd ff EOR &fffd ; os_reset_address_high &0d43 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0d46 18 CLC &0d47 7d 01 0e ADC &0e01,X ; payload + 1 # Runs from &0e01 to &0f00 &0d4a 4d 93 dc EOR &dc93 ; os_irq1v_handler # Ensure OS IRQ1 handler hasn't been changed # actually EOR &dc00 + via_decryption_rom_offset_five &0d4d ee 1b 0d INC &0d1b ; via_decryption_add &0d50 a8 TAY &0d51 ad 1b 0d LDA &0d1b ; via_decryption_add &0d54 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0d57 8d 1b 0d STA &0d1b ; via_decryption_add &0d5a 98 TYA &0d5b 4d b0 da EOR &dab0 ; ? # Runs over &da00 - &daff # actually EOR &da00 + via_decryption_rom_offset_six # (System VIA setup, OS sideways ROM checking) &0d5e 4d 69 fe EOR &fe69 ; User VIA timer 2 counter MSB &0d61 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0d64 9d 00 0e STA &0e00,X ; payload &0d67 e8 INX &0d68 d0 98 BNE &0d02 ; via_decryption_loop &0d6a a9 03 LDA #&03 &0d6c 8d 58 02 STA &0258 ; ESCAPE/BREAK effect &0d6f a9 4c LDA #&4c ; JMP # Set BREAK intercept code to JMP &0287, endless loop &0d71 8d 87 02 STA &0287 ; BREAK intercept code &0d74 a9 87 LDA #&87 &0d76 8d 88 02 STA &0288 ; BREAK intercept code + 1 &0d79 a9 02 LDA #&02 &0d7b 8d 89 02 STA &0289 ; BREAK intercept code + 2 &0d7e ee 31 0d INC &0d31 ; via_decryption_rom_offset_three &0d81 ee 2b 0d INC &0d2b ; via_decryption_rom_offset_two &0d84 ee 3a 0d INC &0d3a ; via_decryption_rom_offset_four &0d87 a0 35 LDY #&35 # Reset all vectors to OS defaults ; reset_vector_table_loop &0d89 b9 40 d9 LDA &d940,Y ; os_default_vector_table &0d8c 99 00 02 STA &0200,Y ; os_vector_table &0d8f 88 DEY &0d90 10 f7 BPL &0d89 ; reset_vector_table_loop &0d92 ee 22 0d INC &0d22 ; via_decryption_rom_offset_one &0d95 ee 4b 0d INC &0d4b ; via_decryption_rom_offset_five &0d98 ee 5c 0d INC &0d5c ; via_decryption_rom_offset_six &0d9b ad 1d 0d LDA &0d1d ; via_decryption_eor &0d9e 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &0da1 8d 1d 0d STA &0d1d ; via_decryption_eor &0da4 ee 1d 0d INC &0d1d ; via_decryption_eor &0da7 ee 03 0d INC &0d03 ; via_decryption_offset &0daa ad 03 0d LDA &0d03 ; via_decryption_offset &0dad c9 00 CMP #&00 &0daf f0 03 BEQ &0db4 ; calculate_checksum &0db1 4c 02 0d JMP &0d02 ; via_decryption_loop ; calculate_checksum &0db4 a9 00 LDA #&00 # Checksum &0e00 - &0efd &0db6 85 70 STA &70 ; calculated_checksum_one &0db8 85 71 STA &71 ; calculated_checksum_two &0dba a8 TAY ; calculate_checksum_loop &0dbb a5 71 LDA &71 ; calculated_checksum_two &0dbd 59 00 0e EOR &0e00,Y ; payload &0dc0 85 71 STA &71 ; calculated_checksum_two &0dc2 a2 08 LDX #&08 ; calculate_checksum_inner_loop &0dc4 a5 71 LDA &71 ; calculated_checksum_two &0dc6 2a ROL A &0dc7 90 0c BCC &0dd5 ; clear_set &0dc9 a5 71 LDA &71 ; calculated_checksum_two &0dcb 49 08 EOR #&08 &0dcd 85 71 STA &71 ; calculated_checksum_two &0dcf a5 70 LDA &70 ; calculated_checksum_one &0dd1 49 10 EOR #&10 &0dd3 85 70 STA &70 ; calculated_checksum_one ; clear_set &0dd5 26 70 ROL &70 ; calculated_checksum_one &0dd7 26 71 ROL &71 ; calculated_checksum_two &0dd9 ca DEX &0dda d0 e8 BNE &0dc4 ; calculate_checksum_inner_loop &0ddc c8 INY &0ddd c0 fe CPY #&fe &0ddf d0 da BNE &0dbb ; calculate_checksum_loop &0de1 a5 70 LDA &70 ; calculated_checksum_one &0de3 cd fe 0e CMP &0efe ; valid_checksum_one &0de6 d0 07 BNE &0def ; invalid_checksum &0de8 a5 71 LDA &71 ; calculated_checksum_two &0dea cd ff 0e CMP &0eff ; valid_checksum_two &0ded f0 11 BEQ &0e00 ; payload # If the checksum matches, run the decrypted code ; invalid_checksum &0def a9 c8 LDA #&c8 ; Read/Write BREAK/ESCAPE effect # This is handled by the OS OSBYTE handler at &e99c, &0df1 a2 03 LDX #&03 ; Clear memory on next RESET # which isn't checked in the decryption routine, &0df3 a0 00 LDY #&00 # so could be intercepted with a custom ROM &0df5 20 f4 ff JSR &fff4 ; OSBYTE ; endless_wiping_loop # Otherwise, if the checksum doesn't match, &0df8 99 00 0e STA &0e00,Y ; payload # Wipe &0e00 - &0eff (failed decryption) with &c8 &0dfb c8 INY &0dfc d0 fa BNE &0df8 ; endless_wiping_loop &0dfe f0 f8 BEQ &0df8 ; endless_wiping_loop ; payload &0e00 20 0e 0e JSR &0e0e ; move_tape_loader &0e03 a2 ff LDX #&ff ; wipe_0e0f_to_0f0d_loop &0e05 9d 0e 0e STA &0e0e,X ; move_tape_loader # Wipe &0e0f - &0f0d &0e08 ca DEX &0e09 d0 fa BNE &0e05 ; wipe_0e0f_to_0f0d_loop &0e0b 4c 00 04 JMP &0400 ; tape_loader ; move_tape_loader &0e0e a2 0f LDX #&0f ; remove_roms_loop &0e10 9d a1 02 STA &02a1,X ; os_paged_rom_type_table # Remove paged ROMs from ROM information table &0e13 ca DEX &0e14 10 fa BPL &0e10 ; remove_roms_loop &0e16 e8 INX ; move_tape_loader_loop &0e19 bd 25 0e LDA &0e25,X ; unrelocated_tape_loader # Move &0e25 - &0efd to &0400 - &04d8 &0e1c 9d 00 04 STA &0400,X ; tape_loader &0e1f e8 INX &0e20 e0 d9 CPX #&d9 &0e22 d0 f5 BNE &0e19 ; move_tape_loader_loop &0e24 60 RTS ; tape_loader &0400 a9 03 LDA #&03 &0402 85 f8 STA &f8 ; waiting_for_start_of_data # Top bit clear to indicate waiting for start of data &0404 8d 08 fe STA &fe08 ; Cassette ACIA control register # Disable transmit and receiver interrupts &0407 a9 05 LDA #&05 # Switch off cassette motor &0409 8d 10 fe STA &fe10 ; Serial ULA control register &040c a2 ff LDX #&ff ; delay_loop &040e ca DEX &040f d0 fd BNE &040e ; delay_loop &0411 a9 85 LDA #&85 # Set to 2400 baud, switch on cassette motor &0413 8d 10 fe STA &fe10 ; Serial ULA control register &0416 a9 d5 LDA #&d5 # 1200 baud, odd parity, 8 bit words, &0418 8d 08 fe STA &fe08 ; Cassette ACIA control register # disable transmit interrupts ; get_data_from_tape # enable all receiver interrupts &041b ad 08 fe LDA &fe08 ; Cassette ACIA status register &041e 10 fb BPL &041b ; get_data_from_tape # Wait for interrupt from the cassette system &0420 a8 TAY &0421 29 01 AND #&01 &0423 f0 f6 BEQ &041b ; get_data_from_tape # Is it a receiver interrupt? If so, &0425 98 TYA &0426 29 70 AND #&70 # Is there a framing, receiver overrun or parity error? &0428 f0 07 BEQ &0431 ; received_data_from_tape # If not, it's data &042a 24 f8 BIT &f8 ; waiting_for_start_of_data &042c 10 ed BPL &041b ; get_data_from_tape # Top bit clear if still waiting for start of data &042e 4c 80 04 JMP &0480 ; load_error # Otherwise, abort the load ; received_data_from_tape &0431 ad 09 fe LDA &fe09 ; Cassette ACIA data register &0434 49 9d EOR #&9d # Data is obfuscated on tape &0436 24 f8 BIT &f8 ; waiting_for_start_of_data &0438 30 08 BMI &0442 ; leave # Top bit set if already reading data &043a c9 cd CMP #&cd &043c d0 dd BNE &041b ; get_data_from_tape # Otherwise, wait for &cd byte &043e 85 f8 STA &f8 ; waiting_for_start_of_data # Set top bit to indicate data is being read &0440 f0 01 BEQ &0443 ; read_addresses_from_tape ; leave &0442 60 RTS ; read_addresses_from_tape &0443 a2 00 LDX #&00 ; decrypt_addresses_loop # Read six bytes of addresses from tape &0445 20 1b 04 JSR &041b ; get_data_from_tape # for load address, length and run address &0448 38 SEC &0449 fd 7a 04 SBC &047a,X ; addresses_sub # and decrypt them &044c 5d 74 04 EOR &0474,X ; addresses_eor &044f 95 60 STA &60,X ; addresses &0451 e8 INX &0452 e0 06 CPX #&06 &0454 d0 ef BNE &0445 ; decrypt_addresses_loop &0456 a2 00 LDX #&00 ; read_data_from_tape_loop &0458 20 1b 04 JSR &041b ; get_data_from_tape # Get a byte of data from the tape &045b 81 60 STA (&60,X) ; write_address # Write it to memory &045d e6 60 INC &60 ; write_address_low &045f d0 02 BNE &0463 ; not_new_page &0461 e6 61 INC &61 ; write_address_high ; not_new_page &0463 a5 62 LDA &62 ; length_low # Reduce the bytes still needing to be read by one &0465 d0 02 BNE &0469 ; not_end_of_page &0467 c6 63 DEC &63 ; length_high ; not_end_of_page &0469 c6 62 DEC &62 ; length_low &046b d0 eb BNE &0458 ; read_data_from_tape_loop &046d a5 63 LDA &63 ; length_high &046f d0 e7 BNE &0458 ; read_data_from_tape_loop # When all the data is loaded from tape to memory, &0471 6c 64 00 JMP (&0064) ; run_address # call the run address to start the loaded binary ; addresses_eor &0474 af 78 3d 7d 9a e5 ; addresses_sub &047a 3d cc 0f 2b 52 3f ; load_error &0480 a2 00 LDX #&00 ; wipe_memory_loop &0482 9d 00 05 STA &0500,X # Wipe &0500 - &7fff (main memory, i.e. loaded data) # actually STA wipe_address &0485 e8 INX &0486 d0 fa BNE &0482 ; wipe_memory_loop &0488 ee 84 04 INC &0484 ; wipe_address_high &048b 10 f5 BPL &0482 ; wipe_memory_loop ; wipe_zero_page_and_loader_loop &048d 95 00 STA &00,X # Wipe &0000 - &00ff (zero page) &048f 9d 80 03 STA &0380,X # Wipe &0380 - &047f (includes tape_loader) &0492 e8 INX &0493 d0 f8 BNE &048d ; wipe_zero_page_and_loader_loop &0495 78 SEI &0496 a9 07 LDA #&07 # MODE 7 &0498 20 1d cb JSR &cb1d ; os_rom_set_mode &049b 78 SEI &049c a9 03 LDA #&03 # Clear memory on break &049e 8d 58 02 STA &0258 ; ESCAPE/BREAK effect ; write_tape_error &04a1 a2 00 LDX #&00 ; write_tape_error_loop &04a3 bd ae 04 LDA &04ae,X ; tape_error_string # Endlessly write "Tape Load Error. Try again" &04a6 f0 f9 BEQ &04a1 ; write_tape_error &04a8 20 ee ff JSR &ffee ; OSWRCH &04ab e8 INX &04ac d0 f5 BNE &04a3 ; write_tape_error_loop ; tape_error_string &04ae 54 61 70 65 20 4c 6f 61 64 20 45 72 72 6f 72 2e ; "Tape Load Error." &04be 20 54 72 79 20 61 67 61 69 6e 0d 0a 00 ; " Try again\r\n" ; unused &04cb 00 &04cc 20 20 20 20 20 48 69 2c 20 4b 65 76 2e ; " Hi, Kev." ; valid_checksum_one &0efe f9 ; valid_checksum_two &0eff 0d &0f00 00 # Used at &0d47 in final round of via_decryption Game disassembly ================ ; (no filename) # First chunk loaded by stream loader ; 0006d2 0006d2 004d98 ; After initialisation, memory is used as follows: ; ; &0000 - &0043 push_sprite_to_screen_buffer ; &0044 number_of_objects ; &0045 - &0049 system_time_buffer ; &0045 - &0050 various temporary variables ; &0051 (unused) ; &0052 - &0056 sprite_slices_should_plot ; &0052 room_slot_picking_up_from ; &0053 number_of_charm_being_picked_up ; &0056 object_above_player ; &0057 room_colour_scheme ; &0058 player_new_position_y, loop_position ; &0059 last_z_order ; &005a first_slice_address ; &005b last_slice_address ; &005c player_facing ; &005d man_or_wolf : &00 = man, &0c = wolf ; &005e previous_rising_or_falling_object ; &005f (unused) ; &0060 spasm_countdown_low ; &0061 room_number ; &0062 player_is_jumping ; &0063 spasm_jumping_or_phasing_stage ; &0064 upward_jump ; &0065 completely_redraw_room_if_zero ; &0066 - &0069 door_heights ; &0066 door_height_north ; &0067 door_height_east ; &0068 door_height_south ; &0069 door_height_west ; &006a room_minimum_z ; &006b room_minimum_x ; &006c room_maximum_z ; &006d room_maximum_x ; &006e spasm_sprite_update_delay ; &006f room_is_outside ; &0070 start_of_background_objects ; &0071 facing_on_entering_room ; &0072 turn_delay ; &0073 falling_charm_has_hit_player ; &0074 jump_key_held ; &0075 spasm_countdown_high ; &0076 rnd_1 ; &0077 rnd_2 ; &0078 rnd_3 ; &0079 steps_to_take_into_room ; &007a rising_or_falling_object ; &007b object_to_update ; &007c is_phasing_in_or_out : &00 = normal, &01 = phasing out, &ff = phasing in ; &007d room_layout : &00 square_room, &04 north_south_room, &08 unused, &0c east_west_room ; &007e trigger_spiked_ball_falling ; &007f player_has_touched_deadly_thing ; &0080 turn_counter ; &0081 walking_sound_delay ; &0082 charm_room_slot_one ; &0083 charm_room_slot_two ; &0084 charm_pocket_slot_one ; &0085 charm_pocket_slot_two ; &0086 charm_pocket_slot_three ; &0087 shift_held ; &0088 room_charm_changed_state_one ; &0089 room_charm_changed_state_two ; &008a life_counter ; &008b day_counter_low ; &008c day_counter_high ; &008d npc_walking_sound_delay ; &008e previous_movement_single ; &008f (unused) ; &0090 charms_required ; &0091 type_of_charm_dropped_in_cauldron, charm_collection_countdown ; &0092 portcullis_grace ; &0093 cauldron_magic_state ; &0095 - &0097 cauldron_magic_type_table ; &0097 next_charm_required ; &0098 - &009b cauldron_magic_flipped_table ; &009c spasms_counter ; &009d sun_or_moon_address_low ; &009e sun_or_moon_address_high ; &009f current_sun_or_moon_address_low ; &00a0 current_sun_or_moon_address_high ; &00a1 impending_spasm_warning ; &00a2 - &00a5 room_27_fire_movement_table : north, east, west, south ; &00a6 maximum_height_of_balls_in_room ; ; &0100 - &011f charms_position_x ; &0120 - &013f charms_position_y ; &0140 - &015f charms_position_z ; &0160 - &017f charms_type ; &0180 - &019f charms_position_room ; &01ff - &01a0 stack ; ; these arrays allow for 40 (&28) regular and background objects ; &0300 - &0327 objects_position_x ; &0328 - &034f objects_position_y ; &0350 - &0377 objects_position_z ; &0378 - &039f objects_flipped ; &03a0 - &03c7 objects_bytes_per_line_of_sprite ; &03c8 - &03ef objects_direction ; ; &0400 - &041f slices_of_screen_changed ; ; these arrays allow for 28 (&1c) regular objects ; &0428 - &0443 objects_about_to_disappear ; &0460 - &047b objects_overlap_results ; ; these arrays allow for 27 (&1b) regular objects - one not needed for temporary copy object ; &047c - &0497 objects_induced_direction, objects_need_order_considering ; &0497 - &04b2 objects_induced_speed ; ; &04ff - &0400 sprite_staging_area ; ; &05ff - &0500 sprite_mask_staging_area ; ; these arrays allow for 28 (&1c) regular objects ; &0600 - &061b objects_first_slice_address ; &061c - &0637 objects_last_slice_address ; &0638 - &0653 objects_buffer_start_address_high ; &0654 - &067f objects_buffer_end_address_high ; ; these arrays allow for 28 (&1c) regular objects ; &068c - &06a7 objects_previous_first_slice_address ; &06a8 - &06c3 objects_previous_last_slice_address ; &06c4 - &06df objects_previous_buffer_start_address_high ; &06e0 - &06fb objects_previous_buffer_end_address_high ; &06fc - &0717 objects_size_z ; &0718 - &0733 objects_size_x ; &0734 - &074f objects_size_y ; ; &5400 - &6aff screen memory - room is &5400 - &68ff, &1500 in size ; ; &6b00 - &7fff screen buffer - &1500 in size ; ; these arrays allow for 28 (&1c) regular objects ; &6b00 - &6b1b objects_movement_xz ; &6b1c - &6b37 objects_horizontal_speed ; &6bc8 - &6be3 objects_movement_y ; &6be4 - &6bff objects_maximum_position ; &6c00 - &6c1b objects_vertical_speed ; &6c1c - &6c37 objects_support ; &6cc8 - &6ce4 objects_previous_movement_xz ; ; these arrays allow for 40 (&28) regular and background objects ; &6cd8 - &6cff objects_needs_plotting ; &6d00 - &6d27 objects_needs_unbuffering ; ; this array allows for 28 (&1c) regular objects ; &6de4 - &6dff object_plotting_order ; entry_point &06d2 a9 04 LDA #&04 # MODE 4 &06d4 20 1d cb JSR &cb1d ; os_rom_set_mode &06d7 78 SEI &06d8 a9 0a LDA #&0a # R10: Cursor start register &06da 8d 00 fe STA &fe00 ; video register number &06dd a9 20 LDA #&20 # Disable cursor &06df 8d 01 fe STA &fe01 ; video register value &06e2 a9 06 LDA #&06 # R6: Vertical displayed register &06e4 8d 00 fe STA &fe00 ; video register number &06e7 a9 0a LDA #&0a # Set screen to be 10 characters (80 pixels) high &06e9 8d 01 fe STA &fe01 ; video register value &06ec a9 01 LDA #&01 # R1: Number of characters per line &06ee 8d 00 fe STA &fe00 ; video register number &06f1 a9 20 LDA #&20 # Set screen to be 32 characters (256 pixels) wide &06f3 8d 01 fe STA &fe01 ; video register value &06f6 a9 02 LDA #&02 # R2: Horizontal sync position register &06f8 8d 00 fe STA &fe00 ; video register number &06fb a9 2d LDA #&2d &06fd 8d 01 fe STA &fe01 ; video register value &0700 a9 07 LDA #&07 # R7: Vertical sync position &0702 8d 00 fe STA &fe00 ; video register number &0705 a9 1e LDA #&1e &0707 8d 01 fe STA &fe01 ; video register value &070a a2 37 LDX #&37 ; plot_loading_sprite_loop &070c bd 18 07 LDA &0718,X ; loading_sprite &070f 9d 60 60 STA &6060,X &0712 ca DEX &0713 10 f7 BPL &070c ; plot_loading_sprite_loop &0715 4c 00 04 JMP &0400 ; tape_loader # Load and run second chunk ; loading_sprite &0718 e0 60 60 60 60 60 62 fe ; "L" &0720 38 6c c6 c6 c6 c6 6c 38 ; "O" &0728 0c 1c 2e 66 46 ce d6 66 ; "A" &0730 60 70 68 6c 66 66 66 fc ; "D" &0738 7c 18 18 18 18 18 18 7c ; "I" &0740 cc d6 d6 e6 e4 c4 c8 de ; "N" &0748 1e 30 60 c6 ce f6 66 0e ; "G" # &0750 - &5469 is decrypted by decrypt_main_code at &6d25 ; sound_table ; chan vol pitch dur &0750 10 00 f1 ff 03 00 01 00 ; sound_1 &0758 10 00 f1 ff 07 00 01 00 ; sound_2 &0760 11 00 00 00 00 00 01 00 ; sound_3 # pitch is modified &0768 11 00 01 00 4f 00 03 00 ; sound_4 &0770 10 00 f1 ff 03 00 03 00 ; sound_5 &0778 12 00 f7 ff 00 00 01 00 ; sound_6 # pitch is modified &0780 11 00 02 00 00 00 02 00 ; sound_7 # pitch is modified &0788 11 00 f1 ff 92 00 01 00 ; sound_8 &0790 13 00 f6 ff 00 00 01 00 ; sound_9 # pitch is modified &0798 10 00 f1 ff 04 00 01 00 ; sound_10 &07a0 13 00 03 00 32 00 01 00 ; sound_11 ; door_height_table &07a8 00 30 ; sun_and_moon_address_table &07aa a8 e8 ; ghost_random_movement_table &07ac 03 06 09 0c ; pitch_table &07b0 50 50 64 64 ; starting_rooms &07b4 43 7f b4 b7 df # One of these is picked at random when the game starts ; colour_schemes &07b9 05 04 02 01 # Green, yellow, magenta, cyan ; check_if_key_pressed &07bd a9 81 LDA #&81 ; Perform keyboard scan &07bf a0 ff LDY #&FF ; for internal key number X &07c1 20 f4 ff JSR &fff4; OSBYTE &07c4 e0 ff CPX #&ff &07c6 60 RTS ; random_number &07c7 a5 76 LDA &76 ; rnd_1 &07c9 29 48 AND #&48 &07cb 69 38 ADC #&38 &07cd 0a ASL A &07ce 0a ASL A &07cf 26 78 ROL &78 ; rnd_3 &07d1 26 77 ROL &77 ; rnd_2 &07d3 26 76 ROL &76 ; rnd_1 &07d5 a5 76 LDA &76 ; rnd_1 &07d7 60 RTS ; set_palette &07d8 a0 08 LDY #&08 &07da 18 CLC &07db 69 80 ADC #&80 ; palette_loop &07dd 8d 21 fe STA &fe21 ; video ULA palette register &07e0 18 CLC &07e1 69 10 ADC #&10 &07e3 88 DEY &07e4 d0 f7 BNE &07dd ; palette_loop &07e6 60 RTS ; play_sound ; X = offset into sound_table, base &0700 &07e7 a9 07 LDA #&07; Generate a sound (SOUND) &07e9 a8 TAY &07ea 4c f1 ff JMP &fff1; OSWORD ; delay_loop ; A = duration &07ed 85 01 STA &01 ; tmp &07ef 20 b6 e9 JSR &e9b6 ; os_delay # OS routine to wait 1/50s &07f2 c6 01 DEC &01 ; tmp &07f4 d0 f9 BNE &07ef &07f6 58 CLI &07f7 60 RTS ; unused &07f8 00 00 00 00 00 00 00 00 ; OS sound workspace (unused) &0800 ff 00 00 00 00 00 00 00 c0 c0 c0 c0 04 04 04 04 &0810 00 00 00 64 00 00 00 ff 00 00 00 00 00 00 00 00 &0820 00 00 00 05 00 00 00 ff 00 00 00 00 00 00 00 00 &0830 00 00 00 00 00 00 00 00 ff 00 00 00 00 f0 00 0e ; OS channel buffers (unused) &0840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0870 64 06 00 00 00 00 00 00 00 00 00 00 00 00 00 90 ; player_type_by_facing &0880 27 2d 2d 27 # SPRITE_MAN_FEET_FRONT, SPRITE_MAN_FEET_BACK ; y_positions_table &0884 00 0c 18 24 30 3c 48 54 ; facing_flipped_table &088c 00 00 07 07 ; room_size_table ; x+ z+ x- z- &0890 84 84 11 11 ; square_room &0894 84 64 11 31 ; north_south_room &0898 00 00 00 00 ; unused &089c 64 84 31 11 ; east_west_room ; player_position_x_on_entering_from_facing_table &08a0 8f 4c 08 4c ; player_position_z_on_entering_from_facing_table &08a4 4c 8f 4c 08 ; facing_to_movement_xz &08a8 08 01 02 04 ; wedge_starts &08ac 1f 2f 3f 4f 5f ; wedge_widths &08b1 c0 a0 80 60 40 ; rooms_in_which_balls_do_not_move_towards_player &08b6 0e 13 26 74 7d 89 98 b3 d1 ef ; OS envelope storage area &08c0 00 0e 00 00 13 00 00 00 00 00 81 5a 50 00 00 00 ; envelope 1 &08d0 01 ae 00 00 64 00 00 7e fb 00 82 7e 6e 00 00 00 ; envelope 2 &08e0 01 a7 00 00 64 00 00 7e f8 f8 f8 7e 64 00 00 00 ; envelope 3 &08f0 01 00 00 00 00 00 00 7e fe 00 f6 7e 6e 00 00 00 ; envelope 4 ; Room data ; ========= ; +--+--+--+--+ +--+--+--+--+ +--+--+--+ ; |00 01 02 03| |06 07 08 09| |0d 0e 0f| ; + +--+ + + + + + + + + +--+ + ; |10| |12|13| |16 17 18 19| |1d| |1f| ; + +--+ + + + + + + + + +--+ + ; |20 21 22|23| |26 27 28 29| |2d 2e 2f| ; +--+--+--+ + +--+ +--+--+ +--+--+ + ; |33| |37| |3f| ; + +--+ + + +--+--+ + + ; |43 44| |47| |4a 4b| |4f| ; + +--+ + +--+ + + + + + ; |53| |57|58| |5a 5b| |5f| ; + + + + + +--+ + + + ; |63| |67|68| |6b| |6f| ; + +--+--+--+ + +--+--+ +--+--+--+ + ; |73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f| ; N +--+--+--+--+ + +--+--+--+--+--+--+--+ ; | |84 85 86 87 88 89 8a| ; W-+-E + +--+--+ + +--+ +--+--+--+--+--+ ; | |94| |97|98| |9a 9b 9c 9d 9e 9f| ; S + + + + + +--+--+--+--+ + + ; |a4| |a7|a8| |ae af| ; +--+--+--+--+ +--+--+ + + +--+ + ; |b0 b1 b2 b3 b4 b5 b6 b7|b8| |bf| ; + +--+--+--+ +--+--+ + + + + ; |c0| |c4| |c7|c8| |cf| ; + +--+--+ + + + + + +--+--+ + ; |d0 d1 d2| |d4| |d7|d8| |dd de df| ; + +--+ + + + +--+ + + +--+ + ; |e0| |e2| |e4| |e8| |ed| |ef| ; + +--+ +--+ + + +--+--+--+--+ +--+ + ; |f0 f1 f2 f3 f4| |f8 f9 fa fb fc fd fe ff| ; +--+--+--+--+--+ +--+--+--+--+--+--+--+--+ ; ; Room data starts at &0900. Each room has a two byte header: ; ; room_data_byte_one & &03 : colour scheme ; &00 = green, &01 = yellow, &02 = magenta, &03 = cyan ; room_data_byte_one & &0c : room layout ; &00 = square, &04 = north south, &08 = unused, &0c = east west ; room_data_byte_one & &10 : inside or outside ; &00 = inside, &10 = outside (forces square layout) ; room_data_byte_one & &60 : room has south door if either bit set ; south door is high if &40 is set ; room_data_byte_one & &80 : room has west door ; ; room_data_byte_two & &1f : number of objects in room ; ; room_data_byte_two & &60 : room has east door if either bit set ; east door is high if &40 is set ; room_data_byte_two & &80 : room has north door ; ; For each object, there are two further bytes: ; ; object_byte_one & &0f : x position ; object_position_x = ((object_byte_one & &0f) * 8) + &10 ; object_byte_one & &f0 : z position ; object_position_z = ((object_byte_one & &f0) / 2) + &10 ; object_byte_two & &07 : y position ; object_position_y = (object_byte_two & &07) * &0c ; object_byte_two & &f8 : type ; object_type = ((object_byte_two & &f8) / 8) + &0a ; ; Valid object types are as follows: ; ; &0b OBJECT_BLOCK ; &0c OBJECT_SPIKED_BALL ; &0d OBJECT_SPIKES ; &0e OBJECT_TABLE ; &0f OBJECT_CHEST ; &10 OBJECT_CAULDRON ; &11 OBJECT_GARGOYLE ; &12 OBJECT_PORTCULLIS_X ; &13 OBJECT_BALL ; &15 OBJECT_GHOST ; &19 OBJECT_GUARD_HEAD ; &1b OBJECT_WIZARD_HEAD ; &1d OBJECT_FIRE ; &1f OBJECT_PORTCULLIS_Z ; &20 OBJECT_PORTCULLIS_Z_2 ; &21 OBJECT_PORTCULLIS_X_2 ; &22 OBJECT_FEET ; &23 OBJECT_MAGIC ; &24 OBJECT_DESCENDING_BLOCK ; &25 OBJECT_DISAPPEARING_BLOCK ; &26 OBJECT_MOVING_BLOCK_X ; &27 OBJECT_MOVING_BLOCK_Z ; &28 OBJECT_CARRIED_BLOCK &0900 63 6f 00 0b 20 0b 40 0b 60 0b 80 0b 04 0b 0a 0a 0e 09 2e 18 6e 18 6e eb ce 0b ee 0b e8 0b e6 0b ; room &00, &20 bytes, cyan, square, inside, 15 objects ; object &0b @ (&10, &24, &10) OBJECT_BLOCK ; object &0b @ (&10, &24, &20) OBJECT_BLOCK ; object &0b @ (&10, &24, &30) OBJECT_BLOCK ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0b @ (&30, &24, &10) OBJECT_BLOCK ; object &0b @ (&60, &18, &10) OBJECT_BLOCK ; object &0b @ (&80, &0c, &10) OBJECT_BLOCK ; object &0d @ (&80, &00, &20) OBJECT_SPIKES ; object &0d @ (&80, &00, &40) OBJECT_SPIKES ; object &27 @ (&80, &24, &40) OBJECT_MOVING_BLOCK_Z ; object &0b @ (&80, &24, &70) OBJECT_BLOCK ; object &0b @ (&80, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK ; object &0b @ (&40, &24, &80) OBJECT_BLOCK &0920 8e 23 77 48 06 aa e6 b2 ; room &01, &08 bytes, magenta, east west, inside, 3 objects ; object &13 @ (&48, &00, &48) OBJECT_BALL ; object &1f @ (&40, &18, &10) OBJECT_PORTCULLIS_Z ; object &20 @ (&40, &18, &80) OBJECT_PORTCULLIS_Z_2 &0928 a3 20 ; room &02, &02 bytes, cyan, square, inside, 0 objects &092a a2 0d 4c 08 4c 09 4e 08 4e 09 8e 08 8e 09 8c 08 8c 09 6c 0a 6e 0a 4a 28 4a 29 6c 58 ; room &03, &1c bytes, magenta, square, inside, 13 objects ; object &0b @ (&70, &00, &30) OBJECT_BLOCK ; object &0b @ (&70, &0c, &30) OBJECT_BLOCK ; object &0b @ (&80, &00, &30) OBJECT_BLOCK ; object &0b @ (&80, &0c, &30) OBJECT_BLOCK ; object &0b @ (&80, &00, &50) OBJECT_BLOCK ; object &0b @ (&80, &0c, &50) OBJECT_BLOCK ; object &0b @ (&70, &00, &50) OBJECT_BLOCK ; object &0b @ (&70, &0c, &50) OBJECT_BLOCK ; object &0b @ (&70, &18, &40) OBJECT_BLOCK ; object &0b @ (&80, &18, &40) OBJECT_BLOCK ; object &0f @ (&60, &00, &30) OBJECT_CHEST ; object &0f @ (&60, &0c, &30) OBJECT_CHEST ; object &15 @ (&70, &00, &40) OBJECT_GHOST &0946 31 27 66 08 66 09 66 0a 66 0b 86 d8 24 28 8c 20 ; room &06, &10 bytes, yellow, square, outside, 7 objects ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &24, &40) OBJECT_BLOCK ; object &25 @ (&40, &00, &50) OBJECT_DISAPPEARING_BLOCK ; object &0f @ (&30, &00, &20) OBJECT_CHEST ; object &0e @ (&70, &00, &50) OBJECT_TABLE &0956 b2 2a 44 08 64 08 84 08 46 08 86 08 48 08 68 08 88 08 46 29 66 48 ; room &07, &16 bytes, magenta, square, outside, 10 objects ; object &0b @ (&30, &00, &30) OBJECT_BLOCK ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &30) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0f @ (&40, &0c, &30) OBJECT_CHEST ; object &13 @ (&40, &00, &40) OBJECT_BALL &096c b2 20 ; room &08, &02 bytes, magenta, square, outside, 0 objects &096e b1 0a 06 17 08 17 60 17 80 17 ae 17 ce 17 ee 17 cc 17 ec 17 ea 17 ; room &09, &16 bytes, yellow, square, outside, 10 objects ; object &0c @ (&40, &54, &10) OBJECT_SPIKED_BALL ; object &0c @ (&50, &54, &10) OBJECT_SPIKED_BALL ; object &0c @ (&10, &54, &40) OBJECT_SPIKED_BALL ; object &0c @ (&10, &54, &50) OBJECT_SPIKED_BALL ; object &0c @ (&80, &54, &60) OBJECT_SPIKED_BALL ; object &0c @ (&80, &54, &70) OBJECT_SPIKED_BALL ; object &0c @ (&80, &54, &80) OBJECT_SPIKED_BALL ; object &0c @ (&70, &54, &70) OBJECT_SPIKED_BALL ; object &0c @ (&70, &54, &80) OBJECT_SPIKED_BALL ; object &0c @ (&60, &54, &80) OBJECT_SPIKED_BALL &0984 21 29 0a 08 2a 08 4a 08 0c 09 2c 09 4c 08 0e 0a 2e 09 4e 08 ; room &0d, &14 bytes, yellow, square, inside, 9 objects ; object &0b @ (&60, &00, &10) OBJECT_BLOCK ; object &0b @ (&60, &00, &20) OBJECT_BLOCK ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0b @ (&70, &0c, &10) OBJECT_BLOCK ; object &0b @ (&70, &0c, &20) OBJECT_BLOCK ; object &0b @ (&70, &00, &30) OBJECT_BLOCK ; object &0b @ (&80, &18, &10) OBJECT_BLOCK ; object &0b @ (&80, &0c, &20) OBJECT_BLOCK ; object &0b @ (&80, &00, &30) OBJECT_BLOCK &0998 8e 29 46 18 48 18 a6 18 a8 18 64 38 84 38 6a 38 8a 38 77 48 ; room &0e, &14 bytes, magenta, east west, inside, 9 objects ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &11 @ (&30, &00, &40) OBJECT_GARGOYLE ; object &11 @ (&30, &00, &50) OBJECT_GARGOYLE ; object &11 @ (&60, &00, &40) OBJECT_GARGOYLE ; object &11 @ (&60, &00, &50) OBJECT_GARGOYLE ; object &13 @ (&48, &00, &48) OBJECT_BALL &09ac a1 04 ca 18 ac 18 ce 18 ec 18 ; room &0f, &0a bytes, yellow, square, inside, 4 objects ; object &0d @ (&60, &00, &70) OBJECT_SPIKES ; object &0d @ (&70, &00, &60) OBJECT_SPIKES ; object &0d @ (&80, &00, &70) OBJECT_SPIKES ; object &0d @ (&70, &00, &80) OBJECT_SPIKES &09b6 25 89 40 18 a0 18 64 18 84 18 6a 18 8a 18 4e 18 ae 18 66 c8 ; room &10, &14 bytes, yellow, north south, inside, 9 objects ; object &0d @ (&10, &00, &30) OBJECT_SPIKES ; object &0d @ (&10, &00, &60) OBJECT_SPIKES ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0d @ (&80, &00, &30) OBJECT_SPIKES ; object &0d @ (&80, &00, &60) OBJECT_SPIKES ; object &23 @ (&40, &00, &40) OBJECT_MAGIC &09ca 25 8e 42 10 46 10 4a 10 4e 10 64 10 68 10 6c 10 82 10 86 10 8a 10 a0 10 a4 10 a8 10 ac 10 ; room &12, &1e bytes, yellow, north south, inside, 14 objects ; object &0c @ (&20, &00, &30) OBJECT_SPIKED_BALL ; object &0c @ (&40, &00, &30) OBJECT_SPIKED_BALL ; object &0c @ (&60, &00, &30) OBJECT_SPIKED_BALL ; object &0c @ (&80, &00, &30) OBJECT_SPIKED_BALL ; object &0c @ (&30, &00, &40) OBJECT_SPIKED_BALL ; object &0c @ (&50, &00, &40) OBJECT_SPIKED_BALL ; object &0c @ (&70, &00, &40) OBJECT_SPIKED_BALL ; object &0c @ (&20, &00, &50) OBJECT_SPIKED_BALL ; object &0c @ (&40, &00, &50) OBJECT_SPIKED_BALL ; object &0c @ (&60, &00, &50) OBJECT_SPIKED_BALL ; object &0c @ (&10, &00, &60) OBJECT_SPIKED_BALL ; object &0c @ (&30, &00, &60) OBJECT_SPIKED_BALL ; object &0c @ (&50, &00, &60) OBJECT_SPIKED_BALL ; object &0c @ (&70, &00, &60) OBJECT_SPIKED_BALL &09e8 25 91 40 08 42 d1 44 d2 46 db 48 db 4a d2 4c d1 4e 08 a0 08 a2 d1 a4 d2 a6 db a8 db aa d2 ac d1 ae 08 78 48 ; room &13, &24 bytes, yellow, north south, inside, 17 objects ; object &0b @ (&10, &00, &30) OBJECT_BLOCK ; object &24 @ (&20, &0c, &30) OBJECT_DESCENDING_BLOCK ; object &24 @ (&30, &18, &30) OBJECT_DESCENDING_BLOCK ; object &25 @ (&40, &24, &30) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &24, &30) OBJECT_DISAPPEARING_BLOCK ; object &24 @ (&60, &18, &30) OBJECT_DESCENDING_BLOCK ; object &24 @ (&70, &0c, &30) OBJECT_DESCENDING_BLOCK ; object &0b @ (&80, &00, &30) OBJECT_BLOCK ; object &0b @ (&10, &00, &60) OBJECT_BLOCK ; object &24 @ (&20, &0c, &60) OBJECT_DESCENDING_BLOCK ; object &24 @ (&30, &18, &60) OBJECT_DESCENDING_BLOCK ; object &25 @ (&40, &24, &60) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &24, &60) OBJECT_DISAPPEARING_BLOCK ; object &24 @ (&60, &18, &60) OBJECT_DESCENDING_BLOCK ; object &24 @ (&70, &0c, &60) OBJECT_DESCENDING_BLOCK ; object &0b @ (&80, &00, &60) OBJECT_BLOCK ; object &13 @ (&50, &00, &48) OBJECT_BALL &0a0c 32 a0 ; room &16, &02 bytes, magenta, square, outside, 0 objects &0a0e b1 a8 62 18 82 18 26 18 28 18 c6 18 c8 18 6c 18 8c 18 ; room &17, &12 bytes, yellow, square, outside, 8 objects ; object &0d @ (&20, &00, &40) OBJECT_SPIKES ; object &0d @ (&20, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &20) OBJECT_SPIKES ; object &0d @ (&50, &00, &20) OBJECT_SPIKES ; object &0d @ (&40, &00, &70) OBJECT_SPIKES ; object &0d @ (&50, &00, &70) OBJECT_SPIKES ; object &0d @ (&70, &00, &40) OBJECT_SPIKES ; object &0d @ (&70, &00, &50) OBJECT_SPIKES &0a20 b1 ac 64 08 66 18 28 08 48 18 88 18 a8 08 6a 18 6c 08 68 09 68 0a 68 0b 68 08 ; room &18, &1a bytes, yellow, square, outside, 12 objects ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0b @ (&50, &00, &20) OBJECT_BLOCK ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0b @ (&50, &00, &60) OBJECT_BLOCK ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0b @ (&70, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &18, &40) OBJECT_BLOCK ; object &0b @ (&50, &24, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK &0a3a b2 80 ; room &19, &02 bytes, magenta, square, outside, 0 objects &0a3c 24 8c 46 08 46 09 46 0a 66 08 66 09 66 0a 86 08 86 09 86 0a a6 08 a6 09 a6 0a ; room &1d, &1a bytes, green, north south, inside, 12 objects ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0b @ (&40, &0c, &30) OBJECT_BLOCK ; object &0b @ (&40, &18, &30) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&40, &0c, &50) OBJECT_BLOCK ; object &0b @ (&40, &18, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &0b @ (&40, &18, &60) OBJECT_BLOCK &0a56 27 80 ; room &1f, &02 bytes, cyan, north south, inside, 0 objects &0a58 03 b0 00 0b 20 0a 40 09 60 08 02 0b 04 0b 06 0b 08 0b 84 18 66 18 88 18 a6 18 86 08 86 09 86 0a 86 0b ; room &20, &22 bytes, cyan, square, inside, 16 objects ; object &0b @ (&10, &24, &10) OBJECT_BLOCK ; object &0b @ (&10, &18, &20) OBJECT_BLOCK ; object &0b @ (&10, &0c, &30) OBJECT_BLOCK ; object &0b @ (&10, &00, &40) OBJECT_BLOCK ; object &0b @ (&20, &24, &10) OBJECT_BLOCK ; object &0b @ (&30, &24, &10) OBJECT_BLOCK ; object &0b @ (&40, &24, &10) OBJECT_BLOCK ; object &0b @ (&50, &24, &10) OBJECT_BLOCK ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&40, &0c, &50) OBJECT_BLOCK ; object &0b @ (&40, &18, &50) OBJECT_BLOCK ; object &0b @ (&40, &24, &50) OBJECT_BLOCK &0a7a 8c 2a 26 18 28 18 66 18 68 18 86 18 88 18 c6 18 c8 18 c4 c0 c4 79 ; room &21, &16 bytes, green, east west, inside, 10 objects ; object &0d @ (&40, &00, &20) OBJECT_SPIKES ; object &0d @ (&50, &00, &20) OBJECT_SPIKES ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &70) OBJECT_SPIKES ; object &0d @ (&50, &00, &70) OBJECT_SPIKES ; object &22 @ (&30, &00, &70) OBJECT_FEET ; object &19 @ (&30, &0c, &70) OBJECT_GUARD_HEAD &0a90 83 8c 60 08 80 09 a0 0a c0 0b e0 0b c0 14 c2 0b e2 0b e2 14 e4 0a e6 09 e8 08 ; room &22, &1a bytes, cyan, square, inside, 12 objects ; object &0b @ (&10, &00, &40) OBJECT_BLOCK ; object &0b @ (&10, &0c, &50) OBJECT_BLOCK ; object &0b @ (&10, &18, &60) OBJECT_BLOCK ; object &0b @ (&10, &24, &70) OBJECT_BLOCK ; object &0b @ (&10, &24, &80) OBJECT_BLOCK ; object &0c @ (&10, &30, &70) OBJECT_SPIKED_BALL ; object &0b @ (&20, &24, &70) OBJECT_BLOCK ; object &0b @ (&20, &24, &80) OBJECT_BLOCK ; object &0c @ (&20, &30, &80) OBJECT_SPIKED_BALL ; object &0b @ (&30, &18, &80) OBJECT_BLOCK ; object &0b @ (&40, &0c, &80) OBJECT_BLOCK ; object &0b @ (&50, &00, &80) OBJECT_BLOCK &0aaa 27 89 46 18 4a 08 4a 19 a6 18 aa 08 aa 19 6a b8 a8 c0 a8 79 ; room &23, &14 bytes, cyan, north south, inside, 9 objects ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0d @ (&60, &0c, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0d @ (&60, &0c, &60) OBJECT_SPIKES ; object &21 @ (&60, &00, &40) OBJECT_PORTCULLIS_X_2 ; object &22 @ (&50, &00, &60) OBJECT_FEET ; object &19 @ (&50, &0c, &60) OBJECT_GUARD_HEAD &0abe 11 ab 84 08 84 09 84 0a 86 08 88 08 8a 08 8a 09 8a 0a 8a 0b 67 48 a7 49 ; room &26, &18 bytes, yellow, square, outside, 11 objects ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&30, &0c, &50) OBJECT_BLOCK ; object &0b @ (&30, &18, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &50) OBJECT_BLOCK ; object &0b @ (&60, &18, &50) OBJECT_BLOCK ; object &0b @ (&60, &24, &50) OBJECT_BLOCK ; object &13 @ (&48, &00, &40) OBJECT_BALL ; object &13 @ (&48, &0c, &60) OBJECT_BALL &0ad6 b2 a4 66 98 68 98 86 98 88 98 ; room &27, &0a bytes, magenta, square, outside, 4 objects ; object &1d @ (&40, &00, &40) OBJECT_FIRE ; object &1d @ (&50, &00, &40) OBJECT_FIRE ; object &1d @ (&40, &00, &50) OBJECT_FIRE ; object &1d @ (&50, &00, &50) OBJECT_FIRE &0ae0 92 a0 ; room &28, &02 bytes, magenta, square, outside, 0 objects &0ae2 91 80 ; room &29, &02 bytes, yellow, square, outside, 0 objects &0ae4 01 ea e4 0c c6 0c e6 0b c8 0c e8 0b ea 0c 46 20 46 21 46 22 46 23 ; room &2d, &16 bytes, yellow, square, inside, 10 objects ; object &0b @ (&30, &30, &80) OBJECT_BLOCK ; object &0b @ (&40, &30, &70) OBJECT_BLOCK ; object &0b @ (&40, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &30, &70) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK ; object &0b @ (&60, &30, &80) OBJECT_BLOCK ; object &0e @ (&40, &00, &30) OBJECT_TABLE ; object &0e @ (&40, &0c, &30) OBJECT_TABLE ; object &0e @ (&40, &18, &30) OBJECT_TABLE ; object &0e @ (&40, &24, &30) OBJECT_TABLE &0afa 8e 20 ; room &2e, &02 bytes, magenta, east west, inside, 0 objects &0afc a1 8c 44 d8 64 18 84 d9 46 18 66 08 86 18 48 0b 68 18 88 da 66 09 66 0a 66 0b ; room &2f, &1a bytes, yellow, square, inside, 12 objects ; object &25 @ (&30, &00, &30) OBJECT_DISAPPEARING_BLOCK ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &25 @ (&30, &0c, &50) OBJECT_DISAPPEARING_BLOCK ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0b @ (&50, &24, &30) OBJECT_BLOCK ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &25 @ (&50, &18, &50) OBJECT_DISAPPEARING_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &24, &40) OBJECT_BLOCK &0b16 26 8c 46 08 46 09 46 0a 66 08 66 09 66 0a 86 08 86 09 86 0a a6 08 a6 09 a6 0a ; room &33, &1a bytes, magenta, north south, inside, 12 objects ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0b @ (&40, &0c, &30) OBJECT_BLOCK ; object &0b @ (&40, &18, &30) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&40, &0c, &50) OBJECT_BLOCK ; object &0b @ (&40, &18, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &0b @ (&40, &18, &60) OBJECT_BLOCK &0b30 63 82 66 58 66 f1 ; room &37, &06 bytes, cyan, square, inside, 2 objects ; object &15 @ (&40, &00, &40) OBJECT_GHOST ; object &28 @ (&40, &0c, &40) OBJECT_CARRIED_BLOCK &0b36 24 83 60 42 6e ba 77 58 ; room &3f, &08 bytes, green, north south, inside, 3 objects ; object &12 @ (&10, &18, &40) OBJECT_PORTCULLIS_X ; object &21 @ (&80, &18, &40) OBJECT_PORTCULLIS_X_2 ; object &15 @ (&48, &00, &48) OBJECT_GHOST &0b3e 21 a0 ; room &43, &02 bytes, yellow, square, inside, 0 objects &0b40 80 0b 64 08 84 08 a4 08 66 08 68 08 68 09 68 0a 68 0b 84 29 ca 20 ca 21 ; room &44, &18 bytes, green, square, inside, 11 objects ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&30, &00, &60) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &18, &40) OBJECT_BLOCK ; object &0b @ (&50, &24, &40) OBJECT_BLOCK ; object &0f @ (&30, &0c, &50) OBJECT_CHEST ; object &0e @ (&60, &00, &70) OBJECT_TABLE ; object &0e @ (&60, &0c, &70) OBJECT_TABLE &0b58 24 86 62 08 82 08 6c 08 8c 08 86 58 68 58 ; room &47, &0e bytes, green, north south, inside, 6 objects ; object &0b @ (&20, &00, &40) OBJECT_BLOCK ; object &0b @ (&20, &00, &50) OBJECT_BLOCK ; object &0b @ (&70, &00, &40) OBJECT_BLOCK ; object &0b @ (&70, &00, &50) OBJECT_BLOCK ; object &15 @ (&40, &00, &50) OBJECT_GHOST ; object &15 @ (&50, &00, &40) OBJECT_GHOST &0b66 23 30 46 18 66 08 86 18 48 18 88 18 4a 18 6a 08 8a 18 48 19 48 1a 6a 09 6a 0a 66 09 66 0a 88 19 88 1a ; room &4a, &22 bytes, cyan, square, inside, 16 objects ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &30) OBJECT_SPIKES ; object &0b @ (&60, &00, &40) OBJECT_BLOCK ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0d @ (&50, &0c, &30) OBJECT_SPIKES ; object &0d @ (&50, &18, &30) OBJECT_SPIKES ; object &0b @ (&60, &0c, &40) OBJECT_BLOCK ; object &0b @ (&60, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0d @ (&50, &0c, &50) OBJECT_SPIKES ; object &0d @ (&50, &18, &50) OBJECT_SPIKES &0b88 a1 03 69 f1 69 f2 69 58 ; room &4b, &08 bytes, yellow, square, inside, 3 objects ; object &28 @ (&58, &0c, &40) OBJECT_CARRIED_BLOCK ; object &28 @ (&58, &18, &40) OBJECT_CARRIED_BLOCK ; object &15 @ (&58, &00, &40) OBJECT_GHOST &0b90 62 91 82 18 84 18 a4 18 a6 18 a8 18 aa 18 ca 18 ea 18 ec 18 ee 18 ae 08 ce 09 ce 0a ee f2 60 0b 80 0b ee 49 ; room &4f, &24 bytes, magenta, square, inside, 17 objects ; object &0d @ (&20, &00, &50) OBJECT_SPIKES ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0d @ (&30, &00, &60) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0d @ (&60, &00, &60) OBJECT_SPIKES ; object &0d @ (&60, &00, &70) OBJECT_SPIKES ; object &0d @ (&60, &00, &80) OBJECT_SPIKES ; object &0d @ (&70, &00, &80) OBJECT_SPIKES ; object &0d @ (&80, &00, &80) OBJECT_SPIKES ; object &0b @ (&80, &00, &60) OBJECT_BLOCK ; object &0b @ (&80, &0c, &70) OBJECT_BLOCK ; object &0b @ (&80, &18, &70) OBJECT_BLOCK ; object &28 @ (&80, &18, &80) OBJECT_CARRIED_BLOCK ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &13 @ (&80, &0c, &80) OBJECT_BALL &0bb4 66 90 60 0b 80 0b 8c 08 8c 09 ac f1 ae 08 ae 09 44 18 44 11 68 18 68 11 84 18 84 11 a8 18 a8 11 ac 48 ; room &53, &22 bytes, magenta, north south, inside, 16 objects ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0b @ (&70, &00, &50) OBJECT_BLOCK ; object &0b @ (&70, &0c, &50) OBJECT_BLOCK ; object &28 @ (&70, &0c, &60) OBJECT_CARRIED_BLOCK ; object &0b @ (&80, &00, &60) OBJECT_BLOCK ; object &0b @ (&80, &0c, &60) OBJECT_BLOCK ; object &0d @ (&30, &00, &30) OBJECT_SPIKES ; object &0c @ (&30, &0c, &30) OBJECT_SPIKED_BALL ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0c @ (&50, &0c, &40) OBJECT_SPIKED_BALL ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0c @ (&30, &0c, &50) OBJECT_SPIKED_BALL ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0c @ (&50, &0c, &60) OBJECT_SPIKED_BALL ; object &13 @ (&70, &00, &60) OBJECT_BALL &0bd6 22 80 ; room &57, &02 bytes, magenta, square, inside, 0 objects &0bd8 21 10 4a 08 4a 09 4c 08 4c 09 4c 0a 4c 0b ac 18 cc 08 cc 09 cc 0a cc 0b c6 18 c4 08 c4 09 c4 0a c4 0b ; room &58, &22 bytes, yellow, square, inside, 16 objects ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0b @ (&60, &0c, &30) OBJECT_BLOCK ; object &0b @ (&70, &00, &30) OBJECT_BLOCK ; object &0b @ (&70, &0c, &30) OBJECT_BLOCK ; object &0b @ (&70, &18, &30) OBJECT_BLOCK ; object &0b @ (&70, &24, &30) OBJECT_BLOCK ; object &0d @ (&70, &00, &60) OBJECT_SPIKES ; object &0b @ (&70, &00, &70) OBJECT_BLOCK ; object &0b @ (&70, &0c, &70) OBJECT_BLOCK ; object &0b @ (&70, &18, &70) OBJECT_BLOCK ; object &0b @ (&70, &24, &70) OBJECT_BLOCK ; object &0d @ (&40, &00, &70) OBJECT_SPIKES ; object &0b @ (&30, &00, &70) OBJECT_BLOCK ; object &0b @ (&30, &0c, &70) OBJECT_BLOCK ; object &0b @ (&30, &18, &70) OBJECT_BLOCK ; object &0b @ (&30, &24, &70) OBJECT_BLOCK &0bfa 02 ae 00 08 02 09 04 0a 06 08 06 09 06 0a 06 0b 28 08 28 09 28 1a 0a 08 0a 09 0a 1a 08 d3 ; room &5a, &1e bytes, magenta, square, inside, 14 objects ; object &0b @ (&10, &00, &10) OBJECT_BLOCK ; object &0b @ (&20, &0c, &10) OBJECT_BLOCK ; object &0b @ (&30, &18, &10) OBJECT_BLOCK ; object &0b @ (&40, &00, &10) OBJECT_BLOCK ; object &0b @ (&40, &0c, &10) OBJECT_BLOCK ; object &0b @ (&40, &18, &10) OBJECT_BLOCK ; object &0b @ (&40, &24, &10) OBJECT_BLOCK ; object &0b @ (&50, &00, &20) OBJECT_BLOCK ; object &0b @ (&50, &0c, &20) OBJECT_BLOCK ; object &0d @ (&50, &18, &20) OBJECT_SPIKES ; object &0b @ (&60, &00, &10) OBJECT_BLOCK ; object &0b @ (&60, &0c, &10) OBJECT_BLOCK ; object &0d @ (&60, &18, &10) OBJECT_SPIKES ; object &24 @ (&50, &24, &10) OBJECT_DESCENDING_BLOCK &0c18 a0 80 ; room &5b, &02 bytes, green, square, inside, 0 objects &0c1a 64 85 66 08 86 08 6c 08 8c 08 6c 29 ; room &5f, &0c bytes, green, north south, inside, 5 objects ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&70, &00, &40) OBJECT_BLOCK ; object &0b @ (&70, &00, &50) OBJECT_BLOCK ; object &0f @ (&70, &0c, &40) OBJECT_CHEST &0c26 24 8b 46 08 46 09 46 0a a6 08 a6 09 a6 0a 66 08 86 08 46 3b a6 3b 66 99 ; room &63, &18 bytes, green, north south, inside, 11 objects ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0b @ (&40, &0c, &30) OBJECT_BLOCK ; object &0b @ (&40, &18, &30) OBJECT_BLOCK ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &0b @ (&40, &18, &60) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &11 @ (&40, &24, &30) OBJECT_GARGOYLE ; object &11 @ (&40, &24, &60) OBJECT_GARGOYLE ; object &1d @ (&40, &0c, &40) OBJECT_FIRE &0c3e 24 88 46 08 66 08 86 08 a6 08 46 39 66 39 86 39 a6 39 ; room &67, &12 bytes, green, north south, inside, 8 objects ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &11 @ (&40, &0c, &30) OBJECT_GARGOYLE ; object &11 @ (&40, &0c, &40) OBJECT_GARGOYLE ; object &11 @ (&40, &0c, &50) OBJECT_GARGOYLE ; object &11 @ (&40, &0c, &60) OBJECT_GARGOYLE &0c50 26 90 82 08 84 d1 66 da 86 da 68 da 88 da 6a d1 6c 08 46 18 66 18 86 18 a6 18 a8 18 88 18 68 18 48 18 ; room &68, &22 bytes, magenta, north south, inside, 16 objects ; object &0b @ (&20, &00, &50) OBJECT_BLOCK ; object &24 @ (&30, &0c, &50) OBJECT_DESCENDING_BLOCK ; object &25 @ (&40, &18, &40) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&40, &18, &50) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &18, &40) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &18, &50) OBJECT_DISAPPEARING_BLOCK ; object &24 @ (&60, &0c, &40) OBJECT_DESCENDING_BLOCK ; object &0b @ (&70, &00, &40) OBJECT_BLOCK ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES &0c72 66 8c 60 0b 80 0b 76 eb a6 e3 a6 18 86 18 ac 08 ac 09 ac 0a ac 0b ae 08 ae 09 ; room &6b, &1a bytes, magenta, north south, inside, 12 objects ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &27 @ (&40, &24, &48) OBJECT_MOVING_BLOCK_Z ; object &26 @ (&40, &24, &60) OBJECT_MOVING_BLOCK_X ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0b @ (&70, &00, &60) OBJECT_BLOCK ; object &0b @ (&70, &0c, &60) OBJECT_BLOCK ; object &0b @ (&70, &18, &60) OBJECT_BLOCK ; object &0b @ (&70, &24, &60) OBJECT_BLOCK ; object &0b @ (&80, &00, &60) OBJECT_BLOCK ; object &0b @ (&80, &0c, &60) OBJECT_BLOCK &0c8c 27 8f 46 08 46 09 46 0a 66 08 66 09 66 0a 86 08 86 09 86 0a a6 08 a6 09 a6 0a 66 1b 86 1b a6 1b ; room &6f, &20 bytes, cyan, north south, inside, 15 objects ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0b @ (&40, &0c, &30) OBJECT_BLOCK ; object &0b @ (&40, &18, &30) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&40, &0c, &50) OBJECT_BLOCK ; object &0b @ (&40, &18, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &0b @ (&40, &18, &60) OBJECT_BLOCK ; object &0d @ (&40, &24, &40) OBJECT_SPIKES ; object &0d @ (&40, &24, &50) OBJECT_SPIKES ; object &0d @ (&40, &24, &60) OBJECT_SPIKES &0cac 01 a0 ; room &73, &02 bytes, yellow, square, inside, 0 objects &0cae 8f 2e 44 08 44 09 4a 08 4a 09 a4 08 a4 09 aa 08 aa 09 a7 48 47 4a 44 3a 4a 3a a4 3a aa 3a ; room &74, &1e bytes, cyan, east west, inside, 14 objects ; object &0b @ (&30, &00, &30) OBJECT_BLOCK ; object &0b @ (&30, &0c, &30) OBJECT_BLOCK ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0b @ (&60, &0c, &30) OBJECT_BLOCK ; object &0b @ (&30, &00, &60) OBJECT_BLOCK ; object &0b @ (&30, &0c, &60) OBJECT_BLOCK ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0b @ (&60, &0c, &60) OBJECT_BLOCK ; object &13 @ (&48, &00, &60) OBJECT_BALL ; object &13 @ (&48, &18, &30) OBJECT_BALL ; object &11 @ (&30, &18, &30) OBJECT_GARGOYLE ; object &11 @ (&60, &18, &30) OBJECT_GARGOYLE ; object &11 @ (&30, &18, &60) OBJECT_GARGOYLE ; object &11 @ (&60, &18, &60) OBJECT_GARGOYLE &0ccc 8c 6f 66 18 86 18 a6 18 68 18 88 18 a8 18 c6 18 c8 18 0a 08 2a 09 4a 0a 6a 0b 66 e3 e6 0b e8 0b ; room &75, &20 bytes, green, east west, inside, 15 objects ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0d @ (&40, &00, &70) OBJECT_SPIKES ; object &0d @ (&50, &00, &70) OBJECT_SPIKES ; object &0b @ (&60, &00, &10) OBJECT_BLOCK ; object &0b @ (&60, &0c, &20) OBJECT_BLOCK ; object &0b @ (&60, &18, &30) OBJECT_BLOCK ; object &0b @ (&60, &24, &40) OBJECT_BLOCK ; object &26 @ (&40, &24, &40) OBJECT_MOVING_BLOCK_X ; object &0b @ (&40, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK &0cec 8e 62 a8 f1 a8 48 ; room &76, &06 bytes, magenta, east west, inside, 2 objects ; object &28 @ (&50, &0c, &60) OBJECT_CARRIED_BLOCK ; object &13 @ (&50, &00, &60) OBJECT_BALL &0cf2 a3 ac 44 08 44 19 a4 08 a4 19 4a 08 4a 19 aa 08 aa 19 46 a8 a6 a8 64 b8 6a b8 ; room &77, &1a bytes, cyan, square, inside, 12 objects ; object &0b @ (&30, &00, &30) OBJECT_BLOCK ; object &0d @ (&30, &0c, &30) OBJECT_SPIKES ; object &0b @ (&30, &00, &60) OBJECT_BLOCK ; object &0d @ (&30, &0c, &60) OBJECT_SPIKES ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0d @ (&60, &0c, &30) OBJECT_SPIKES ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0d @ (&60, &0c, &60) OBJECT_SPIKES ; object &1f @ (&40, &00, &30) OBJECT_PORTCULLIS_Z ; object &1f @ (&40, &00, &60) OBJECT_PORTCULLIS_Z ; object &21 @ (&30, &00, &40) OBJECT_PORTCULLIS_X_2 ; object &21 @ (&60, &00, &40) OBJECT_PORTCULLIS_X_2 &0d0c a1 ac 42 08 24 08 2a 08 4c 08 ac 08 ca 08 c4 08 a2 08 77 30 a4 c0 a4 89 77 ca ; room &78, &1a bytes, yellow, square, inside, 12 objects ; object &0b @ (&20, &00, &30) OBJECT_BLOCK ; object &0b @ (&30, &00, &20) OBJECT_BLOCK ; object &0b @ (&60, &00, &20) OBJECT_BLOCK ; object &0b @ (&70, &00, &30) OBJECT_BLOCK ; object &0b @ (&70, &00, &60) OBJECT_BLOCK ; object &0b @ (&60, &00, &70) OBJECT_BLOCK ; object &0b @ (&30, &00, &70) OBJECT_BLOCK ; object &0b @ (&20, &00, &60) OBJECT_BLOCK ; object &10 @ (&48, &00, &48) OBJECT_CAULDRON ; object &22 @ (&30, &00, &60) OBJECT_FEET ; object &1b @ (&30, &0c, &60) OBJECT_WIZARD_HEAD ; object &23 @ (&48, &18, &48) OBJECT_MAGIC &0d26 8f 2b 84 08 84 09 84 0a 8a 08 8a 09 8a 0a 86 08 88 08 84 3b 8a 3b 88 99 ; room &79, &18 bytes, cyan, east west, inside, 11 objects ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&30, &0c, &50) OBJECT_BLOCK ; object &0b @ (&30, &18, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &50) OBJECT_BLOCK ; object &0b @ (&60, &18, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &11 @ (&30, &24, &50) OBJECT_GARGOYLE ; object &11 @ (&60, &24, &50) OBJECT_GARGOYLE ; object &1d @ (&50, &0c, &50) OBJECT_FIRE &0d3e 8e 30 44 13 46 13 48 13 4a 13 44 0c 46 0c 48 0c 4a 0c a4 13 a6 13 a8 13 aa 13 a4 0c a6 0c a8 0c aa 0c ; room &7a, &22 bytes, magenta, east west, inside, 16 objects ; object &0c @ (&30, &24, &30) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &30) OBJECT_SPIKED_BALL ; object &0c @ (&50, &24, &30) OBJECT_SPIKED_BALL ; object &0c @ (&60, &24, &30) OBJECT_SPIKED_BALL ; object &0b @ (&30, &30, &30) OBJECT_BLOCK ; object &0b @ (&40, &30, &30) OBJECT_BLOCK ; object &0b @ (&50, &30, &30) OBJECT_BLOCK ; object &0b @ (&60, &30, &30) OBJECT_BLOCK ; object &0c @ (&30, &24, &60) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &60) OBJECT_SPIKED_BALL ; object &0c @ (&50, &24, &60) OBJECT_SPIKED_BALL ; object &0c @ (&60, &24, &60) OBJECT_SPIKED_BALL ; object &0b @ (&30, &30, &60) OBJECT_BLOCK ; object &0b @ (&40, &30, &60) OBJECT_BLOCK ; object &0b @ (&50, &30, &60) OBJECT_BLOCK ; object &0b @ (&60, &30, &60) OBJECT_BLOCK &0d60 83 a0 ; room &7b, &02 bytes, cyan, square, inside, 0 objects &0d62 8c 30 44 08 44 09 44 1a 4a 08 4a 09 4a 1a aa 08 aa 09 aa 1a a4 08 a4 09 a4 1a 46 a8 a6 a8 67 c0 67 79 ; room &7c, &22 bytes, green, east west, inside, 16 objects ; object &0b @ (&30, &00, &30) OBJECT_BLOCK ; object &0b @ (&30, &0c, &30) OBJECT_BLOCK ; object &0d @ (&30, &18, &30) OBJECT_SPIKES ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0b @ (&60, &0c, &30) OBJECT_BLOCK ; object &0d @ (&60, &18, &30) OBJECT_SPIKES ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0b @ (&60, &0c, &60) OBJECT_BLOCK ; object &0d @ (&60, &18, &60) OBJECT_SPIKES ; object &0b @ (&30, &00, &60) OBJECT_BLOCK ; object &0b @ (&30, &0c, &60) OBJECT_BLOCK ; object &0d @ (&30, &18, &60) OBJECT_SPIKES ; object &1f @ (&40, &00, &30) OBJECT_PORTCULLIS_Z ; object &1f @ (&40, &00, &60) OBJECT_PORTCULLIS_Z ; object &22 @ (&48, &00, &40) OBJECT_FEET ; object &19 @ (&48, &0c, &40) OBJECT_GUARD_HEAD &0d84 83 2e 88 18 8c 08 8c 09 8a 09 8c 0a 8e 0b 8e 0c 6e 0b 6c 0b 6a 0b ae 0b ac 0b aa 0b 8a 4a ; room &7d, &1e bytes, cyan, square, inside, 14 objects ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0b @ (&70, &00, &50) OBJECT_BLOCK ; object &0b @ (&70, &0c, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &50) OBJECT_BLOCK ; object &0b @ (&70, &18, &50) OBJECT_BLOCK ; object &0b @ (&80, &24, &50) OBJECT_BLOCK ; object &0b @ (&80, &30, &50) OBJECT_BLOCK ; object &0b @ (&80, &24, &40) OBJECT_BLOCK ; object &0b @ (&70, &24, &40) OBJECT_BLOCK ; object &0b @ (&60, &24, &40) OBJECT_BLOCK ; object &0b @ (&80, &24, &60) OBJECT_BLOCK ; object &0b @ (&70, &24, &60) OBJECT_BLOCK ; object &0b @ (&60, &24, &60) OBJECT_BLOCK ; object &13 @ (&60, &18, &50) OBJECT_BALL &0da2 8e 63 68 20 68 21 6b 58 ; room &7e, &08 bytes, magenta, east west, inside, 3 objects ; object &0e @ (&50, &00, &40) OBJECT_TABLE ; object &0e @ (&50, &0c, &40) OBJECT_TABLE ; object &15 @ (&68, &00, &40) OBJECT_GHOST &0daa 81 80 ; room &7f, &02 bytes, yellow, square, inside, 0 objects &0dac 20 2f 0c 18 2c 18 2e 18 0c da 2c da 0e da 2e da 0a 08 0a 09 2a 08 2a 09 4c 08 4c 09 4e 08 4e 09 ; room &84, &20 bytes, green, square, inside, 15 objects ; object &0d @ (&70, &00, &10) OBJECT_SPIKES ; object &0d @ (&70, &00, &20) OBJECT_SPIKES ; object &0d @ (&80, &00, &20) OBJECT_SPIKES ; object &25 @ (&70, &18, &10) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&70, &18, &20) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&80, &18, &10) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&80, &18, &20) OBJECT_DISAPPEARING_BLOCK ; object &0b @ (&60, &00, &10) OBJECT_BLOCK ; object &0b @ (&60, &0c, &10) OBJECT_BLOCK ; object &0b @ (&60, &00, &20) OBJECT_BLOCK ; object &0b @ (&60, &0c, &20) OBJECT_BLOCK ; object &0b @ (&70, &00, &30) OBJECT_BLOCK ; object &0b @ (&70, &0c, &30) OBJECT_BLOCK ; object &0b @ (&80, &00, &30) OBJECT_BLOCK ; object &0b @ (&80, &0c, &30) OBJECT_BLOCK &0dcc 8e 25 66 18 86 08 88 18 68 08 7a c8 ; room &85, &0c bytes, magenta, east west, inside, 5 objects ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &23 @ (&60, &00, &48) OBJECT_MAGIC &0dd8 8d 6d a4 18 a6 18 a8 18 c4 18 c6 18 c8 18 8a 08 aa 09 ca 0a ea 0b e8 0b e6 0b e4 0b ; room &86, &1c bytes, yellow, east west, inside, 13 objects ; object &0d @ (&30, &00, &60) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0d @ (&30, &00, &70) OBJECT_SPIKES ; object &0d @ (&40, &00, &70) OBJECT_SPIKES ; object &0d @ (&50, &00, &70) OBJECT_SPIKES ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &60) OBJECT_BLOCK ; object &0b @ (&60, &18, &70) OBJECT_BLOCK ; object &0b @ (&60, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK ; object &0b @ (&40, &24, &80) OBJECT_BLOCK ; object &0b @ (&30, &24, &80) OBJECT_BLOCK &0df4 a2 a0 ; room &87, &02 bytes, magenta, square, inside, 0 objects &0df6 a0 af 2e 18 0a 18 24 18 42 18 64 18 68 18 8a 18 ac 18 ee 18 ea 18 a6 18 a2 18 c2 18 e4 c0 e4 79 ; room &88, &20 bytes, green, square, inside, 15 objects ; object &0d @ (&80, &00, &20) OBJECT_SPIKES ; object &0d @ (&60, &00, &10) OBJECT_SPIKES ; object &0d @ (&30, &00, &20) OBJECT_SPIKES ; object &0d @ (&20, &00, &30) OBJECT_SPIKES ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0d @ (&70, &00, &60) OBJECT_SPIKES ; object &0d @ (&80, &00, &80) OBJECT_SPIKES ; object &0d @ (&60, &00, &80) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&20, &00, &60) OBJECT_SPIKES ; object &0d @ (&20, &00, &70) OBJECT_SPIKES ; object &22 @ (&30, &00, &80) OBJECT_FEET ; object &19 @ (&30, &0c, &80) OBJECT_GUARD_HEAD &0e16 8e 2d 64 18 66 18 68 18 6a 18 46 d8 48 d8 84 18 86 18 88 18 8a 18 a6 d8 a8 d8 77 4a ; room &89, &1c bytes, magenta, east west, inside, 13 objects ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &25 @ (&40, &00, &30) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &00, &30) OBJECT_DISAPPEARING_BLOCK ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &25 @ (&40, &00, &60) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &00, &60) OBJECT_DISAPPEARING_BLOCK ; object &13 @ (&48, &18, &48) OBJECT_BALL &0e32 a3 0d 0a 08 0c 09 0e 0a 2e 0a 4e 1a 6e d3 8e 1a ae d3 ce 1a ee 0b ec 18 ea 18 e8 18 ; room &8a, &1c bytes, cyan, square, inside, 13 objects ; object &0b @ (&60, &00, &10) OBJECT_BLOCK ; object &0b @ (&70, &0c, &10) OBJECT_BLOCK ; object &0b @ (&80, &18, &10) OBJECT_BLOCK ; object &0b @ (&80, &18, &20) OBJECT_BLOCK ; object &0d @ (&80, &18, &30) OBJECT_SPIKES ; object &24 @ (&80, &24, &40) OBJECT_DESCENDING_BLOCK ; object &0d @ (&80, &18, &50) OBJECT_SPIKES ; object &24 @ (&80, &24, &60) OBJECT_DESCENDING_BLOCK ; object &0d @ (&80, &18, &70) OBJECT_SPIKES ; object &0b @ (&80, &24, &80) OBJECT_BLOCK ; object &0d @ (&70, &00, &80) OBJECT_SPIKES ; object &0d @ (&60, &00, &80) OBJECT_SPIKES ; object &0d @ (&50, &00, &80) OBJECT_SPIKES &0e4e 65 89 60 08 80 08 82 08 62 08 68 08 88 08 6a 08 8a 08 48 29 ; room &94, &14 bytes, yellow, north south, inside, 9 objects ; object &0b @ (&10, &00, &40) OBJECT_BLOCK ; object &0b @ (&10, &00, &50) OBJECT_BLOCK ; object &0b @ (&20, &00, &50) OBJECT_BLOCK ; object &0b @ (&20, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &40) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0f @ (&50, &0c, &30) OBJECT_CHEST &0e62 24 89 46 18 4a 08 4a 19 a6 18 aa 08 aa 19 6a b8 a8 c0 a8 79 ; room &97, &14 bytes, green, north south, inside, 9 objects ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0d @ (&60, &0c, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0d @ (&60, &0c, &60) OBJECT_SPIKES ; object &21 @ (&60, &00, &40) OBJECT_PORTCULLIS_X_2 ; object &22 @ (&50, &00, &60) OBJECT_FEET ; object &19 @ (&50, &0c, &60) OBJECT_GUARD_HEAD &0e76 26 8f 4e 08 4e 09 4e 0a 4e 0b ae 08 ae 09 ae 0a ae 0b 4c 08 4c 19 6c 08 ac 08 ac 19 8c 08 7a 48 ; room &98, &20 bytes, magenta, north south, inside, 15 objects ; object &0b @ (&80, &00, &30) OBJECT_BLOCK ; object &0b @ (&80, &0c, &30) OBJECT_BLOCK ; object &0b @ (&80, &18, &30) OBJECT_BLOCK ; object &0b @ (&80, &24, &30) OBJECT_BLOCK ; object &0b @ (&80, &00, &60) OBJECT_BLOCK ; object &0b @ (&80, &0c, &60) OBJECT_BLOCK ; object &0b @ (&80, &18, &60) OBJECT_BLOCK ; object &0b @ (&80, &24, &60) OBJECT_BLOCK ; object &0b @ (&70, &00, &30) OBJECT_BLOCK ; object &0d @ (&70, &0c, &30) OBJECT_SPIKES ; object &0b @ (&70, &00, &40) OBJECT_BLOCK ; object &0b @ (&70, &00, &60) OBJECT_BLOCK ; object &0d @ (&70, &0c, &60) OBJECT_SPIKES ; object &0b @ (&70, &00, &50) OBJECT_BLOCK ; object &13 @ (&60, &00, &48) OBJECT_BALL &0e96 01 a0 ; room &9a, &02 bytes, yellow, square, inside, 0 objects &0e98 8c 68 86 08 86 09 e6 0b 88 08 88 09 e8 0b b6 9a 9a 9a ; room &9b, &12 bytes, green, east west, inside, 8 objects ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&40, &0c, &50) OBJECT_BLOCK ; object &0b @ (&40, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &0c, &50) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK ; object &1d @ (&40, &18, &68) OBJECT_FIRE ; object &1d @ (&60, &18, &58) OBJECT_FIRE &0eaa 8e 30 44 28 44 29 46 28 46 29 48 28 48 29 4a 28 4a 29 64 16 64 15 66 16 66 15 68 16 68 15 6a 16 6a 15 ; room &9c, &22 bytes, magenta, east west, inside, 16 objects ; object &0f @ (&30, &00, &30) OBJECT_CHEST ; object &0f @ (&30, &0c, &30) OBJECT_CHEST ; object &0f @ (&40, &00, &30) OBJECT_CHEST ; object &0f @ (&40, &0c, &30) OBJECT_CHEST ; object &0f @ (&50, &00, &30) OBJECT_CHEST ; object &0f @ (&50, &0c, &30) OBJECT_CHEST ; object &0f @ (&60, &00, &30) OBJECT_CHEST ; object &0f @ (&60, &0c, &30) OBJECT_CHEST ; object &0c @ (&30, &48, &40) OBJECT_SPIKED_BALL ; object &0c @ (&30, &3c, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &48, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &3c, &40) OBJECT_SPIKED_BALL ; object &0c @ (&50, &48, &40) OBJECT_SPIKED_BALL ; object &0c @ (&50, &3c, &40) OBJECT_SPIKED_BALL ; object &0c @ (&60, &48, &40) OBJECT_SPIKED_BALL ; object &0c @ (&60, &3c, &40) OBJECT_SPIKED_BALL &0ecc 91 2d 84 08 84 09 84 0a 8a 08 8a 09 8a 0a 86 0a 88 0a 22 20 84 3b 8a 3b c7 c0 c7 79 ; room &9d, &1c bytes, yellow, square, outside, 13 objects ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&30, &0c, &50) OBJECT_BLOCK ; object &0b @ (&30, &18, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &50) OBJECT_BLOCK ; object &0b @ (&60, &18, &50) OBJECT_BLOCK ; object &0b @ (&40, &18, &50) OBJECT_BLOCK ; object &0b @ (&50, &18, &50) OBJECT_BLOCK ; object &0e @ (&20, &00, &20) OBJECT_TABLE ; object &11 @ (&30, &24, &50) OBJECT_GARGOYLE ; object &11 @ (&60, &24, &50) OBJECT_GARGOYLE ; object &22 @ (&48, &00, &70) OBJECT_FEET ; object &19 @ (&48, &0c, &70) OBJECT_GUARD_HEAD &0ee8 b2 20 ; room &9e, &02 bytes, magenta, square, outside, 0 objects &0eea b1 0a aa 08 ca 08 ea 08 ac 14 ac 15 ae 14 ae 15 aa 39 ca 39 ea 39 ; room &9f, &16 bytes, yellow, square, outside, 10 objects ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0b @ (&60, &00, &70) OBJECT_BLOCK ; object &0b @ (&60, &00, &80) OBJECT_BLOCK ; object &0c @ (&70, &30, &60) OBJECT_SPIKED_BALL ; object &0c @ (&70, &3c, &60) OBJECT_SPIKED_BALL ; object &0c @ (&80, &30, &60) OBJECT_SPIKED_BALL ; object &0c @ (&80, &3c, &60) OBJECT_SPIKED_BALL ; object &11 @ (&60, &0c, &60) OBJECT_GARGOYLE ; object &11 @ (&60, &0c, &70) OBJECT_GARGOYLE ; object &11 @ (&60, &0c, &80) OBJECT_GARGOYLE &0f00 27 8c 46 18 46 19 62 10 64 10 82 08 85 e0 68 e0 6c 08 88 10 8a 10 a8 18 a8 19 ; room &a4, &1a bytes, cyan, north south, inside, 12 objects ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &0c, &30) OBJECT_SPIKES ; object &0c @ (&20, &00, &40) OBJECT_SPIKED_BALL ; object &0c @ (&30, &00, &40) OBJECT_SPIKED_BALL ; object &0b @ (&20, &00, &50) OBJECT_BLOCK ; object &26 @ (&38, &00, &50) OBJECT_MOVING_BLOCK_X ; object &26 @ (&50, &00, &40) OBJECT_MOVING_BLOCK_X ; object &0b @ (&70, &00, &40) OBJECT_BLOCK ; object &0c @ (&50, &00, &50) OBJECT_SPIKED_BALL ; object &0c @ (&60, &00, &50) OBJECT_SPIKED_BALL ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &0c, &60) OBJECT_SPIKES &0f1a 27 8c 44 08 44 09 44 0a 66 08 66 09 66 0a 88 08 88 09 88 0a aa 08 aa 09 aa 0a ; room &a7, &1a bytes, cyan, north south, inside, 12 objects ; object &0b @ (&30, &00, &30) OBJECT_BLOCK ; object &0b @ (&30, &0c, &30) OBJECT_BLOCK ; object &0b @ (&30, &18, &30) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &0c, &50) OBJECT_BLOCK ; object &0b @ (&50, &18, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0b @ (&60, &0c, &60) OBJECT_BLOCK ; object &0b @ (&60, &18, &60) OBJECT_BLOCK &0f34 67 82 88 f1 88 58 ; room &a8, &06 bytes, cyan, north south, inside, 2 objects ; object &28 @ (&50, &0c, &50) OBJECT_CARRIED_BLOCK ; object &15 @ (&50, &00, &50) OBJECT_GHOST &0f3a 11 a9 42 08 24 08 2a 08 4c 08 ac 08 ca 08 c4 08 a2 08 aa c8 ; room &ae, &14 bytes, yellow, square, outside, 9 objects ; object &0b @ (&20, &00, &30) OBJECT_BLOCK ; object &0b @ (&30, &00, &20) OBJECT_BLOCK ; object &0b @ (&60, &00, &20) OBJECT_BLOCK ; object &0b @ (&70, &00, &30) OBJECT_BLOCK ; object &0b @ (&70, &00, &60) OBJECT_BLOCK ; object &0b @ (&60, &00, &70) OBJECT_BLOCK ; object &0b @ (&30, &00, &70) OBJECT_BLOCK ; object &0b @ (&20, &00, &60) OBJECT_BLOCK ; object &23 @ (&60, &00, &60) OBJECT_MAGIC &0f4e b2 80 ; room &af, &02 bytes, magenta, square, outside, 0 objects &0f50 61 69 0e f2 ee 08 c0 08 60 0b 80 0b e6 0b e8 0b 0e c0 0e 79 ; room &b0, &14 bytes, yellow, square, inside, 9 objects ; object &28 @ (&80, &18, &10) OBJECT_CARRIED_BLOCK ; object &0b @ (&80, &00, &80) OBJECT_BLOCK ; object &0b @ (&10, &00, &70) OBJECT_BLOCK ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0b @ (&40, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK ; object &22 @ (&80, &00, &10) OBJECT_FEET ; object &19 @ (&80, &0c, &10) OBJECT_GUARD_HEAD &0f64 8c 2e 44 08 84 08 c4 08 4a 08 8a 08 ca 08 44 39 84 39 c4 39 4a 39 8a 39 ca 39 a4 98 68 98 ; room &b1, &1e bytes, green, east west, inside, 14 objects ; object &0b @ (&30, &00, &30) OBJECT_BLOCK ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&30, &00, &70) OBJECT_BLOCK ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &70) OBJECT_BLOCK ; object &11 @ (&30, &0c, &30) OBJECT_GARGOYLE ; object &11 @ (&30, &0c, &50) OBJECT_GARGOYLE ; object &11 @ (&30, &0c, &70) OBJECT_GARGOYLE ; object &11 @ (&60, &0c, &30) OBJECT_GARGOYLE ; object &11 @ (&60, &0c, &50) OBJECT_GARGOYLE ; object &11 @ (&60, &0c, &70) OBJECT_GARGOYLE ; object &1d @ (&30, &00, &60) OBJECT_FIRE ; object &1d @ (&50, &00, &40) OBJECT_FIRE &0f82 83 2c 44 18 46 18 48 18 6a 18 8a 18 66 08 84 18 a6 18 a8 18 68 d1 88 d2 86 0b ; room &b2, &1a bytes, cyan, square, inside, 12 objects ; object &0d @ (&30, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &24 @ (&50, &0c, &40) OBJECT_DESCENDING_BLOCK ; object &24 @ (&50, &18, &50) OBJECT_DESCENDING_BLOCK ; object &0b @ (&40, &24, &50) OBJECT_BLOCK &0f9c 8d 31 26 08 28 08 46 09 48 09 64 08 64 19 84 08 84 19 a6 09 c6 08 c8 08 a8 09 8a 08 8a 19 6a 08 6a 19 77 48 ; room &b3, &24 bytes, yellow, east west, inside, 17 objects ; object &0b @ (&40, &00, &20) OBJECT_BLOCK ; object &0b @ (&50, &00, &20) OBJECT_BLOCK ; object &0b @ (&40, &0c, &30) OBJECT_BLOCK ; object &0b @ (&50, &0c, &30) OBJECT_BLOCK ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0d @ (&30, &0c, &40) OBJECT_SPIKES ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0d @ (&30, &0c, &50) OBJECT_SPIKES ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &0b @ (&40, &00, &70) OBJECT_BLOCK ; object &0b @ (&50, &00, &70) OBJECT_BLOCK ; object &0b @ (&50, &0c, &60) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0d @ (&60, &0c, &50) OBJECT_SPIKES ; object &0b @ (&60, &00, &40) OBJECT_BLOCK ; object &0d @ (&60, &0c, &40) OBJECT_SPIKES ; object &13 @ (&48, &00, &48) OBJECT_BALL &0fc0 a0 a0 ; room &b4, &02 bytes, green, square, inside, 0 objects &0fc2 83 32 64 08 64 09 66 09 68 08 68 09 88 09 a8 08 a8 09 a4 08 86 18 a4 09 84 09 a6 09 86 da 88 16 84 16 66 16 a6 16 ; room &b5, &26 bytes, cyan, square, inside, 18 objects ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0b @ (&30, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &0c, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &60) OBJECT_BLOCK ; object &0b @ (&50, &0c, &60) OBJECT_BLOCK ; object &0b @ (&30, &00, &60) OBJECT_BLOCK ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0b @ (&30, &0c, &60) OBJECT_BLOCK ; object &0b @ (&30, &0c, &50) OBJECT_BLOCK ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &25 @ (&40, &18, &50) OBJECT_DISAPPEARING_BLOCK ; object &0c @ (&50, &48, &50) OBJECT_SPIKED_BALL ; object &0c @ (&30, &48, &50) OBJECT_SPIKED_BALL ; object &0c @ (&40, &48, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &48, &60) OBJECT_SPIKED_BALL &0fe8 8d 33 66 08 68 08 87 11 8a 08 8a 09 84 08 84 09 86 08 88 08 86 da 86 db a6 08 88 da 88 db a8 08 66 39 68 39 a6 39 a8 39 ; room &b6, &28 bytes, yellow, east west, inside, 19 objects ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0c @ (&48, &0c, &50) OBJECT_SPIKED_BALL ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &50) OBJECT_BLOCK ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&30, &0c, &50) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &25 @ (&40, &18, &50) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&40, &24, &50) OBJECT_DISAPPEARING_BLOCK ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &25 @ (&50, &18, &50) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &24, &50) OBJECT_DISAPPEARING_BLOCK ; object &0b @ (&50, &00, &60) OBJECT_BLOCK ; object &11 @ (&40, &0c, &40) OBJECT_GARGOYLE ; object &11 @ (&50, &0c, &40) OBJECT_GARGOYLE ; object &11 @ (&40, &0c, &60) OBJECT_GARGOYLE ; object &11 @ (&50, &0c, &60) OBJECT_GARGOYLE &1010 a2 80 ; room &b7, &02 bytes, magenta, square, inside, 0 objects &1012 65 8c 60 0b 80 0b 82 0b 62 18 64 e1 84 18 8a 08 8a 09 8a 0a aa 08 aa 09 a8 08 ; room &b8, &1a bytes, yellow, north south, inside, 12 objects ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0b @ (&20, &24, &50) OBJECT_BLOCK ; object &0d @ (&20, &00, &40) OBJECT_SPIKES ; object &26 @ (&30, &0c, &40) OBJECT_MOVING_BLOCK_X ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &50) OBJECT_BLOCK ; object &0b @ (&60, &18, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0b @ (&60, &0c, &60) OBJECT_BLOCK ; object &0b @ (&50, &00, &60) OBJECT_BLOCK &102c 31 8c 60 17 80 17 6e 17 8e 17 06 17 26 17 46 17 66 17 86 17 a6 17 c6 17 e6 17 ; room &bf, &1a bytes, yellow, square, outside, 12 objects ; object &0c @ (&10, &54, &40) OBJECT_SPIKED_BALL ; object &0c @ (&10, &54, &50) OBJECT_SPIKED_BALL ; object &0c @ (&80, &54, &40) OBJECT_SPIKED_BALL ; object &0c @ (&80, &54, &50) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &10) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &20) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &30) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &50) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &60) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &70) OBJECT_SPIKED_BALL ; object &0c @ (&40, &54, &80) OBJECT_SPIKED_BALL &1046 27 8d 62 18 82 18 44 18 a4 18 46 18 a6 18 48 18 a8 18 4a 18 aa 18 6c 18 8c 18 66 49 ; room &c0, &1c bytes, cyan, north south, inside, 13 objects ; object &0d @ (&20, &00, &40) OBJECT_SPIKES ; object &0d @ (&20, &00, &50) OBJECT_SPIKES ; object &0d @ (&30, &00, &30) OBJECT_SPIKES ; object &0d @ (&30, &00, &60) OBJECT_SPIKES ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0d @ (&60, &00, &30) OBJECT_SPIKES ; object &0d @ (&60, &00, &60) OBJECT_SPIKES ; object &0d @ (&70, &00, &40) OBJECT_SPIKES ; object &0d @ (&70, &00, &50) OBJECT_SPIKES ; object &13 @ (&40, &0c, &40) OBJECT_BALL &1062 25 90 46 20 46 21 46 12 46 13 66 20 66 21 66 12 66 13 86 20 86 21 86 12 86 13 a6 20 a6 21 a6 12 a6 13 ; room &c4, &22 bytes, yellow, north south, inside, 16 objects ; object &0e @ (&40, &00, &30) OBJECT_TABLE ; object &0e @ (&40, &0c, &30) OBJECT_TABLE ; object &0c @ (&40, &18, &30) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &30) OBJECT_SPIKED_BALL ; object &0e @ (&40, &00, &40) OBJECT_TABLE ; object &0e @ (&40, &0c, &40) OBJECT_TABLE ; object &0c @ (&40, &18, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &40) OBJECT_SPIKED_BALL ; object &0e @ (&40, &00, &50) OBJECT_TABLE ; object &0e @ (&40, &0c, &50) OBJECT_TABLE ; object &0c @ (&40, &18, &50) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &50) OBJECT_SPIKED_BALL ; object &0e @ (&40, &00, &60) OBJECT_TABLE ; object &0e @ (&40, &0c, &60) OBJECT_TABLE ; object &0c @ (&40, &18, &60) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &60) OBJECT_SPIKED_BALL &1084 27 84 84 e0 8a 08 46 58 a8 58 ; room &c7, &0a bytes, cyan, north south, inside, 4 objects ; object &26 @ (&30, &00, &50) OBJECT_MOVING_BLOCK_X ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &15 @ (&40, &00, &30) OBJECT_GHOST ; object &15 @ (&50, &00, &60) OBJECT_GHOST &108e 66 8f 42 18 44 18 46 18 48 18 4a 18 4e 09 40 0b 60 0b 80 0b 42 db 44 db 46 0b 48 db 4a db 4c 0b ; room &c8, &20 bytes, magenta, north south, inside, 15 objects ; object &0d @ (&20, &00, &30) OBJECT_SPIKES ; object &0d @ (&30, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&60, &00, &30) OBJECT_SPIKES ; object &0b @ (&80, &0c, &30) OBJECT_BLOCK ; object &0b @ (&10, &24, &30) OBJECT_BLOCK ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &25 @ (&20, &24, &30) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&30, &24, &30) OBJECT_DISAPPEARING_BLOCK ; object &0b @ (&40, &24, &30) OBJECT_BLOCK ; object &25 @ (&50, &24, &30) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&60, &24, &30) OBJECT_DISAPPEARING_BLOCK ; object &0b @ (&70, &24, &30) OBJECT_BLOCK &10ae 32 8f 06 08 26 08 46 08 06 19 26 19 46 09 46 1a a6 08 c6 08 e6 08 e6 19 c6 19 a6 09 a6 1a 66 b8 ; room &cf, &20 bytes, magenta, square, outside, 15 objects ; object &0b @ (&40, &00, &10) OBJECT_BLOCK ; object &0b @ (&40, &00, &20) OBJECT_BLOCK ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0d @ (&40, &0c, &10) OBJECT_SPIKES ; object &0d @ (&40, &0c, &20) OBJECT_SPIKES ; object &0b @ (&40, &0c, &30) OBJECT_BLOCK ; object &0d @ (&40, &18, &30) OBJECT_SPIKES ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &0b @ (&40, &00, &70) OBJECT_BLOCK ; object &0b @ (&40, &00, &80) OBJECT_BLOCK ; object &0d @ (&40, &0c, &80) OBJECT_SPIKES ; object &0d @ (&40, &0c, &70) OBJECT_SPIKES ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &0d @ (&40, &18, &60) OBJECT_SPIKES ; object &21 @ (&40, &00, &40) OBJECT_PORTCULLIS_X_2 &10ce 62 a7 60 0b 80 0b 40 18 00 d3 02 d2 04 d1 06 08 ; room &d0, &10 bytes, magenta, square, inside, 7 objects ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0d @ (&10, &00, &30) OBJECT_SPIKES ; object &24 @ (&10, &24, &10) OBJECT_DESCENDING_BLOCK ; object &24 @ (&20, &18, &10) OBJECT_DESCENDING_BLOCK ; object &24 @ (&30, &0c, &10) OBJECT_DESCENDING_BLOCK ; object &0b @ (&40, &00, &10) OBJECT_BLOCK &10de 8d 70 28 08 28 09 48 0a 28 2b 68 0a 88 1a 88 09 88 08 a8 08 a8 09 c8 1a c8 09 c8 08 e6 0b e8 0b a8 4a ; room &d1, &22 bytes, yellow, east west, inside, 16 objects ; object &0b @ (&50, &00, &20) OBJECT_BLOCK ; object &0b @ (&50, &0c, &20) OBJECT_BLOCK ; object &0b @ (&50, &18, &30) OBJECT_BLOCK ; object &0f @ (&50, &24, &20) OBJECT_CHEST ; object &0b @ (&50, &18, &40) OBJECT_BLOCK ; object &0d @ (&50, &18, &50) OBJECT_SPIKES ; object &0b @ (&50, &0c, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &60) OBJECT_BLOCK ; object &0b @ (&50, &0c, &60) OBJECT_BLOCK ; object &0d @ (&50, &18, &70) OBJECT_SPIKES ; object &0b @ (&50, &0c, &70) OBJECT_BLOCK ; object &0b @ (&50, &00, &70) OBJECT_BLOCK ; object &0b @ (&40, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK ; object &13 @ (&50, &18, &60) OBJECT_BALL &1100 a2 12 0c 08 0e 09 2e 0a 4e 0b 6e d3 2e 18 4e 18 66 18 68 18 6a 18 86 18 88 18 8a 18 6c 18 8c 18 ae 18 ce 18 ee 18 ; room &d2, &26 bytes, magenta, square, inside, 18 objects ; object &0b @ (&70, &00, &10) OBJECT_BLOCK ; object &0b @ (&80, &0c, &10) OBJECT_BLOCK ; object &0b @ (&80, &18, &20) OBJECT_BLOCK ; object &0b @ (&80, &24, &30) OBJECT_BLOCK ; object &24 @ (&80, &24, &40) OBJECT_DESCENDING_BLOCK ; object &0d @ (&80, &00, &20) OBJECT_SPIKES ; object &0d @ (&80, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0d @ (&70, &00, &40) OBJECT_SPIKES ; object &0d @ (&70, &00, &50) OBJECT_SPIKES ; object &0d @ (&80, &00, &60) OBJECT_SPIKES ; object &0d @ (&80, &00, &70) OBJECT_SPIKES ; object &0d @ (&80, &00, &80) OBJECT_SPIKES &1126 22 90 04 18 0a 18 26 18 40 18 42 18 4a 18 4e 18 66 18 86 18 8a 18 a0 18 a4 18 ae 18 ca 18 e2 18 e6 18 ; room &d4, &22 bytes, magenta, square, inside, 16 objects ; object &0d @ (&30, &00, &10) OBJECT_SPIKES ; object &0d @ (&60, &00, &10) OBJECT_SPIKES ; object &0d @ (&40, &00, &20) OBJECT_SPIKES ; object &0d @ (&10, &00, &30) OBJECT_SPIKES ; object &0d @ (&20, &00, &30) OBJECT_SPIKES ; object &0d @ (&60, &00, &30) OBJECT_SPIKES ; object &0d @ (&80, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0d @ (&10, &00, &60) OBJECT_SPIKES ; object &0d @ (&30, &00, &60) OBJECT_SPIKES ; object &0d @ (&80, &00, &60) OBJECT_SPIKES ; object &0d @ (&60, &00, &70) OBJECT_SPIKES ; object &0d @ (&20, &00, &80) OBJECT_SPIKES ; object &0d @ (&40, &00, &80) OBJECT_SPIKES &1148 01 88 66 08 86 08 68 08 88 08 44 58 4a 58 a4 58 aa 58 ; room &d7, &12 bytes, yellow, square, inside, 8 objects ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &15 @ (&30, &00, &30) OBJECT_GHOST ; object &15 @ (&60, &00, &30) OBJECT_GHOST ; object &15 @ (&30, &00, &60) OBJECT_GHOST ; object &15 @ (&60, &00, &60) OBJECT_GHOST &115a 65 86 60 0b 80 0b 62 18 82 18 68 20 68 21 ; room &d8, &0e bytes, yellow, north south, inside, 6 objects ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0d @ (&20, &00, &40) OBJECT_SPIKES ; object &0d @ (&20, &00, &50) OBJECT_SPIKES ; object &0e @ (&50, &00, &40) OBJECT_TABLE ; object &0e @ (&50, &0c, &40) OBJECT_TABLE &1168 20 6d 64 08 66 08 66 09 68 08 68 09 68 0a 68 eb 48 18 88 18 c6 18 c8 18 e6 0b e8 0b ; room &dd, &1c bytes, green, square, inside, 13 objects ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &18, &40) OBJECT_BLOCK ; object &27 @ (&50, &24, &40) OBJECT_MOVING_BLOCK_Z ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &70) OBJECT_SPIKES ; object &0d @ (&50, &00, &70) OBJECT_SPIKES ; object &0b @ (&40, &24, &80) OBJECT_BLOCK ; object &0b @ (&50, &24, &80) OBJECT_BLOCK &1184 8f 2a 64 18 84 18 a6 18 a8 18 8a 18 6a 18 46 18 48 18 86 c0 86 79 ; room &de, &16 bytes, cyan, east west, inside, 10 objects ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0d @ (&40, &00, &60) OBJECT_SPIKES ; object &0d @ (&50, &00, &60) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &22 @ (&40, &00, &50) OBJECT_FEET ; object &19 @ (&40, &0c, &50) OBJECT_GUARD_HEAD &119a a0 80 ; room &df, &02 bytes, green, square, inside, 0 objects &119c 67 8c 4c 99 40 d3 60 0b 80 0b a0 0c a0 15 42 0c 42 15 62 0c 82 0c 62 15 82 15 ; room &e0, &1a bytes, cyan, north south, inside, 12 objects ; object &1d @ (&70, &0c, &30) OBJECT_FIRE ; object &24 @ (&10, &24, &30) OBJECT_DESCENDING_BLOCK ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0b @ (&10, &30, &60) OBJECT_BLOCK ; object &0c @ (&10, &3c, &60) OBJECT_SPIKED_BALL ; object &0b @ (&20, &30, &30) OBJECT_BLOCK ; object &0c @ (&20, &3c, &30) OBJECT_SPIKED_BALL ; object &0b @ (&20, &30, &40) OBJECT_BLOCK ; object &0b @ (&20, &30, &50) OBJECT_BLOCK ; object &0c @ (&20, &3c, &40) OBJECT_SPIKED_BALL ; object &0c @ (&20, &3c, &50) OBJECT_SPIKED_BALL &11b6 24 90 40 13 a0 13 62 13 82 13 64 13 84 13 66 13 86 13 68 13 88 13 6a 13 8a 13 6c 13 8c 13 4e 13 ae 13 ; room &e2, &22 bytes, green, north south, inside, 16 objects ; object &0c @ (&10, &24, &30) OBJECT_SPIKED_BALL ; object &0c @ (&10, &24, &60) OBJECT_SPIKED_BALL ; object &0c @ (&20, &24, &40) OBJECT_SPIKED_BALL ; object &0c @ (&20, &24, &50) OBJECT_SPIKED_BALL ; object &0c @ (&30, &24, &40) OBJECT_SPIKED_BALL ; object &0c @ (&30, &24, &50) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &24, &50) OBJECT_SPIKED_BALL ; object &0c @ (&50, &24, &40) OBJECT_SPIKED_BALL ; object &0c @ (&50, &24, &50) OBJECT_SPIKED_BALL ; object &0c @ (&60, &24, &40) OBJECT_SPIKED_BALL ; object &0c @ (&60, &24, &50) OBJECT_SPIKED_BALL ; object &0c @ (&70, &24, &40) OBJECT_SPIKED_BALL ; object &0c @ (&70, &24, &50) OBJECT_SPIKED_BALL ; object &0c @ (&80, &24, &30) OBJECT_SPIKED_BALL ; object &0c @ (&80, &24, &60) OBJECT_SPIKED_BALL &11d8 65 8f 40 d3 60 0b 80 0b 62 18 82 18 42 d3 44 d3 46 d3 66 d3 86 d3 a6 d3 a8 d3 aa d2 ac d1 ae 08 ; room &e4, &20 bytes, yellow, north south, inside, 15 objects ; object &24 @ (&10, &24, &30) OBJECT_DESCENDING_BLOCK ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0d @ (&20, &00, &40) OBJECT_SPIKES ; object &0d @ (&20, &00, &50) OBJECT_SPIKES ; object &24 @ (&20, &24, &30) OBJECT_DESCENDING_BLOCK ; object &24 @ (&30, &24, &30) OBJECT_DESCENDING_BLOCK ; object &24 @ (&40, &24, &30) OBJECT_DESCENDING_BLOCK ; object &24 @ (&40, &24, &40) OBJECT_DESCENDING_BLOCK ; object &24 @ (&40, &24, &50) OBJECT_DESCENDING_BLOCK ; object &24 @ (&40, &24, &60) OBJECT_DESCENDING_BLOCK ; object &24 @ (&50, &24, &60) OBJECT_DESCENDING_BLOCK ; object &24 @ (&60, &18, &60) OBJECT_DESCENDING_BLOCK ; object &24 @ (&70, &0c, &60) OBJECT_DESCENDING_BLOCK ; object &0b @ (&80, &00, &60) OBJECT_BLOCK &11f8 27 89 44 18 64 18 84 18 4a 18 6a 18 8a 18 a4 18 aa 18 86 48 ; room &e8, &14 bytes, cyan, north south, inside, 9 objects ; object &0d @ (&30, &00, &30) OBJECT_SPIKES ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &30) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0d @ (&30, &00, &60) OBJECT_SPIKES ; object &0d @ (&60, &00, &60) OBJECT_SPIKES ; object &13 @ (&40, &00, &50) OBJECT_BALL &120c 65 8f 60 0b 80 0b 82 0c 82 0b 82 0a 82 09 82 08 84 18 84 e1 86 18 88 08 88 09 8a 08 8a 09 8c 08 ; room &ed, &20 bytes, yellow, north south, inside, 15 objects ; object &0b @ (&10, &24, &40) OBJECT_BLOCK ; object &0b @ (&10, &24, &50) OBJECT_BLOCK ; object &0b @ (&20, &30, &50) OBJECT_BLOCK ; object &0b @ (&20, &24, &50) OBJECT_BLOCK ; object &0b @ (&20, &18, &50) OBJECT_BLOCK ; object &0b @ (&20, &0c, &50) OBJECT_BLOCK ; object &0b @ (&20, &00, &50) OBJECT_BLOCK ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &26 @ (&30, &0c, &50) OBJECT_MOVING_BLOCK_X ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &0c, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &0c, &50) OBJECT_BLOCK ; object &0b @ (&70, &00, &50) OBJECT_BLOCK &122c 26 8e 44 08 44 19 64 18 84 18 a4 08 a4 19 4a 08 4a 19 6a 18 8a 18 aa 08 aa 19 7a 49 74 4a ; room &ef, &1e bytes, magenta, north south, inside, 14 objects ; object &0b @ (&30, &00, &30) OBJECT_BLOCK ; object &0d @ (&30, &0c, &30) OBJECT_SPIKES ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0d @ (&30, &00, &50) OBJECT_SPIKES ; object &0b @ (&30, &00, &60) OBJECT_BLOCK ; object &0d @ (&30, &0c, &60) OBJECT_SPIKES ; object &0b @ (&60, &00, &30) OBJECT_BLOCK ; object &0d @ (&60, &0c, &30) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0b @ (&60, &00, &60) OBJECT_BLOCK ; object &0d @ (&60, &0c, &60) OBJECT_SPIKES ; object &13 @ (&60, &0c, &48) OBJECT_BALL ; object &13 @ (&30, &18, &48) OBJECT_BALL &124a 02 b0 40 08 40 09 40 0a 42 08 42 09 42 0a 24 08 24 09 24 0a 04 08 04 09 04 0a 00 0b 20 0b 02 0b 22 d3 ; room &f0, &22 bytes, magenta, square, inside, 16 objects ; object &0b @ (&10, &00, &30) OBJECT_BLOCK ; object &0b @ (&10, &0c, &30) OBJECT_BLOCK ; object &0b @ (&10, &18, &30) OBJECT_BLOCK ; object &0b @ (&20, &00, &30) OBJECT_BLOCK ; object &0b @ (&20, &0c, &30) OBJECT_BLOCK ; object &0b @ (&20, &18, &30) OBJECT_BLOCK ; object &0b @ (&30, &00, &20) OBJECT_BLOCK ; object &0b @ (&30, &0c, &20) OBJECT_BLOCK ; object &0b @ (&30, &18, &20) OBJECT_BLOCK ; object &0b @ (&30, &00, &10) OBJECT_BLOCK ; object &0b @ (&30, &0c, &10) OBJECT_BLOCK ; object &0b @ (&30, &18, &10) OBJECT_BLOCK ; object &0b @ (&10, &24, &10) OBJECT_BLOCK ; object &0b @ (&10, &24, &20) OBJECT_BLOCK ; object &0b @ (&20, &24, &10) OBJECT_BLOCK ; object &24 @ (&20, &24, &20) OBJECT_DESCENDING_BLOCK &126c 8c 2b 64 08 84 08 6a 08 8a 08 64 39 84 39 6a 39 8a 39 2a 58 87 c0 87 79 ; room &f1, &18 bytes, green, east west, inside, 11 objects ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0b @ (&30, &00, &50) OBJECT_BLOCK ; object &0b @ (&60, &00, &40) OBJECT_BLOCK ; object &0b @ (&60, &00, &50) OBJECT_BLOCK ; object &11 @ (&30, &0c, &40) OBJECT_GARGOYLE ; object &11 @ (&30, &0c, &50) OBJECT_GARGOYLE ; object &11 @ (&60, &0c, &40) OBJECT_GARGOYLE ; object &11 @ (&60, &0c, &50) OBJECT_GARGOYLE ; object &15 @ (&60, &00, &20) OBJECT_GHOST ; object &22 @ (&48, &00, &50) OBJECT_FEET ; object &19 @ (&48, &0c, &50) OBJECT_GUARD_HEAD &1284 82 a0 ; room &f2, &02 bytes, magenta, square, inside, 0 objects &1286 8d 30 64 10 84 10 6a 10 8a 10 46 08 66 18 86 18 48 08 68 18 88 18 a6 08 a8 08 66 d9 86 d9 68 d9 88 d9 ; room &f3, &22 bytes, yellow, east west, inside, 16 objects ; object &0c @ (&30, &00, &40) OBJECT_SPIKED_BALL ; object &0c @ (&30, &00, &50) OBJECT_SPIKED_BALL ; object &0c @ (&60, &00, &40) OBJECT_SPIKED_BALL ; object &0c @ (&60, &00, &50) OBJECT_SPIKED_BALL ; object &0b @ (&40, &00, &30) OBJECT_BLOCK ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0b @ (&50, &00, &30) OBJECT_BLOCK ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0d @ (&50, &00, &50) OBJECT_SPIKES ; object &0b @ (&40, &00, &60) OBJECT_BLOCK ; object &0b @ (&50, &00, &60) OBJECT_BLOCK ; object &25 @ (&40, &0c, &40) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&40, &0c, &50) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &0c, &40) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&50, &0c, &50) OBJECT_DISAPPEARING_BLOCK &12a8 83 8a 64 18 46 18 46 d9 68 18 68 09 86 18 64 d9 86 d9 66 0a 66 0b ; room &f4, &16 bytes, cyan, square, inside, 10 objects ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &25 @ (&40, &0c, &30) OBJECT_DISAPPEARING_BLOCK ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0b @ (&50, &0c, &40) OBJECT_BLOCK ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &25 @ (&30, &0c, &40) OBJECT_DISAPPEARING_BLOCK ; object &25 @ (&40, &0c, &50) OBJECT_DISAPPEARING_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &24, &40) OBJECT_BLOCK &12be 12 ae 42 f1 42 48 46 18 46 11 68 18 68 11 64 18 66 08 86 18 64 11 86 11 66 09 66 0a 66 0b ; room &f8, &1e bytes, magenta, square, outside, 14 objects ; object &28 @ (&20, &0c, &30) OBJECT_CARRIED_BLOCK ; object &13 @ (&20, &00, &30) OBJECT_BALL ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0c @ (&40, &0c, &30) OBJECT_SPIKED_BALL ; object &0d @ (&50, &00, &40) OBJECT_SPIKES ; object &0c @ (&50, &0c, &40) OBJECT_SPIKED_BALL ; object &0d @ (&30, &00, &40) OBJECT_SPIKES ; object &0b @ (&40, &00, &40) OBJECT_BLOCK ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0c @ (&30, &0c, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &0c, &50) OBJECT_SPIKED_BALL ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &18, &40) OBJECT_BLOCK ; object &0b @ (&40, &24, &40) OBJECT_BLOCK &12dc 91 23 06 aa e6 b2 88 58 ; room &f9, &08 bytes, yellow, square, outside, 3 objects ; object &1f @ (&40, &18, &10) OBJECT_PORTCULLIS_Z ; object &20 @ (&40, &18, &80) OBJECT_PORTCULLIS_Z_2 ; object &15 @ (&50, &00, &50) OBJECT_GHOST &12e4 92 2f 46 18 66 18 86 18 4a 18 6a 18 8a 18 48 08 88 08 48 09 48 0a 6a 19 c2 20 66 19 88 09 88 0a ; room &fa, &20 bytes, magenta, square, outside, 15 objects ; object &0d @ (&40, &00, &30) OBJECT_SPIKES ; object &0d @ (&40, &00, &40) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&60, &00, &30) OBJECT_SPIKES ; object &0d @ (&60, &00, &40) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &0b @ (&50, &00, &30) OBJECT_BLOCK ; object &0b @ (&50, &00, &50) OBJECT_BLOCK ; object &0b @ (&50, &0c, &30) OBJECT_BLOCK ; object &0b @ (&50, &18, &30) OBJECT_BLOCK ; object &0d @ (&60, &0c, &40) OBJECT_SPIKES ; object &0e @ (&20, &00, &70) OBJECT_TABLE ; object &0d @ (&40, &0c, &40) OBJECT_SPIKES ; object &0b @ (&50, &0c, &50) OBJECT_BLOCK ; object &0b @ (&50, &18, &50) OBJECT_BLOCK &1304 91 20 ; room &fb, &02 bytes, yellow, square, outside, 0 objects &1306 92 2d 04 18 0a 18 44 18 48 18 4c 18 80 18 a2 18 86 18 e4 18 ea 18 ae 18 8a 18 8c 48 ; room &fc, &1c bytes, magenta, square, outside, 13 objects ; object &0d @ (&30, &00, &10) OBJECT_SPIKES ; object &0d @ (&60, &00, &10) OBJECT_SPIKES ; object &0d @ (&30, &00, &30) OBJECT_SPIKES ; object &0d @ (&50, &00, &30) OBJECT_SPIKES ; object &0d @ (&70, &00, &30) OBJECT_SPIKES ; object &0d @ (&10, &00, &50) OBJECT_SPIKES ; object &0d @ (&20, &00, &60) OBJECT_SPIKES ; object &0d @ (&40, &00, &50) OBJECT_SPIKES ; object &0d @ (&30, &00, &80) OBJECT_SPIKES ; object &0d @ (&60, &00, &80) OBJECT_SPIKES ; object &0d @ (&80, &00, &60) OBJECT_SPIKES ; object &0d @ (&60, &00, &50) OBJECT_SPIKES ; object &13 @ (&70, &00, &50) OBJECT_BALL &1322 80 a0 ; room &fd, &02 bytes, green, square, inside, 0 objects &1324 8f 24 44 98 68 98 8a 98 a7 98 ; room &fe, &0a bytes, cyan, east west, inside, 4 objects ; object &1d @ (&30, &00, &30) OBJECT_FIRE ; object &1d @ (&50, &00, &40) OBJECT_FIRE ; object &1d @ (&60, &00, &50) OBJECT_FIRE ; object &1d @ (&48, &00, &60) OBJECT_FIRE &132e 80 91 64 08 64 09 66 09 68 08 68 09 88 09 a8 08 a8 09 a4 08 a6 09 86 da 88 16 a4 09 84 09 84 16 66 16 a6 16 ; room &ff, &24 bytes, green, square, inside, 17 objects ; object &0b @ (&30, &00, &40) OBJECT_BLOCK ; object &0b @ (&30, &0c, &40) OBJECT_BLOCK ; object &0b @ (&40, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &00, &40) OBJECT_BLOCK ; object &0b @ (&50, &0c, &40) OBJECT_BLOCK ; object &0b @ (&50, &0c, &50) OBJECT_BLOCK ; object &0b @ (&50, &00, &60) OBJECT_BLOCK ; object &0b @ (&50, &0c, &60) OBJECT_BLOCK ; object &0b @ (&30, &00, &60) OBJECT_BLOCK ; object &0b @ (&40, &0c, &60) OBJECT_BLOCK ; object &25 @ (&40, &18, &50) OBJECT_DISAPPEARING_BLOCK ; object &0c @ (&50, &48, &50) OBJECT_SPIKED_BALL ; object &0b @ (&30, &0c, &60) OBJECT_BLOCK ; object &0b @ (&30, &0c, &50) OBJECT_BLOCK ; object &0c @ (&30, &48, &50) OBJECT_SPIKED_BALL ; object &0c @ (&40, &48, &40) OBJECT_SPIKED_BALL ; object &0c @ (&40, &48, &60) OBJECT_SPIKED_BALL ; game_over &1352 a2 00 LDX #&00 ; "GAME OVER" # Plot game over message &1354 a0 09 LDY #&09 &1356 20 59 1a JSR &1a59 ; plot_string &1359 a2 0b LDX #&0b ; "CHARMS COLLECTED 00" &135b a0 13 LDY #&13 &135d 20 59 1a JSR &1a59 ; plot_string &1360 a9 82 LDA #&82 &1362 20 ed 07 JSR &07ed ; delay_loop # Wait for a while, then start again ; game_start &1365 a2 ff LDX #&ff &1367 9a TXS &1368 20 da 22 JSR &22da ; copy_entire_room_from_buffer &136b a2 20 LDX #&20 ; "SPACE to play" &136d a0 0d LDY #&0d &136f 20 59 1a JSR &1a59 ; plot_string &1372 a2 2f LDX #&2f ; "KNIGHT LORE" &1374 a0 0b LDY #&0b &1376 20 59 1a JSR &1a59 ; plot_string ; wait_for_space_loop &1379 a5 ec LDA &ec ; Internal key number of most recently pressed key &137b c9 e2 CMP #&e2 ; SPACE &137d d0 fa BNE &1379 ; wait_for_space_loop # Wait for SPACE to be pressed &137f 20 f1 15 JSR &15f1 ; set_next_charm_required ; initialise_random_charm_order &1382 a2 07 LDX #&07 # Randomise order of charms ; initialise_random_charm_order_loop &1384 a9 ff LDA #&ff &1386 95 45 STA &45,X ; random_charm_order # &45 - &4c become random shuffle of 0 - 7 ; already_used &1388 8a TXA &1389 a8 TAY &138a 20 c7 07 JSR &07c7 ; random_number &138d 29 07 AND #&07 ; check_if_used_loop &138f d9 45 00 CMP &0045,Y ; random_charm_order &1392 f0 f4 BEQ &1388 ; already_used &1394 c8 INY &1395 c0 08 CPY #&08 &1397 d0 f6 BNE &138f ; check_if_used_loop &1399 95 45 STA &45,X ; random_charm_order &139b ca DEX &139c 10 e6 BPL &1384 ; initialise_random_charm_order_loop ; initialise_charms &139e a2 1f LDX #&1f ; initialise_charms_loop &13a0 bd 81 30 LDA &3081,X ; initial_charms_position_packed # Copy charm positions from initial state &13a3 a8 TAY &13a4 29 1c AND #&1c &13a6 0a ASL A &13a7 0a ASL A &13a8 69 12 ADC #&12 &13aa 9d 00 01 STA &0100,X ; charms_position_x # charm_position_x = (packed_byte & &1c) * 4 + &12 &13ad 98 TYA &13ae 29 e0 AND #&e0 &13b0 4a LSR A &13b1 69 12 ADC #&12 &13b3 9d 40 01 STA &0140,X ; charms_position_z # charm_position_z = (packed_byte & &e0) / 2 + &12 &13b6 98 TYA &13b7 29 03 AND #&03 &13b9 f0 04 BEQ &13bf &13bb a8 TAY &13bc b9 85 08 LDA &0885,Y ; y_positions_table + 1 &13bf 9d 20 01 STA &0120,X ; charms_position_y # charm_position_y = (packed_byte & 3) * &0c &13c2 bd 61 30 LDA &3061,X ; initial_charms_position_room &13c5 9d 80 01 STA &0180,X ; charms_position_room ; initialise_charms_position_special_cases # A handful of special case changes to position &13c8 c9 9d CMP #&9d &13ca f0 1e BEQ &13ea &13cc c9 77 CMP #&77 &13ce f0 11 BEQ &13e1 &13d0 c9 ae CMP #&ae &13d2 f0 0d BEQ &13e1 &13d4 c9 b0 CMP #&b0 &13d6 f0 09 BEQ &13e1 &13d8 c9 d7 CMP #&d7 &13da d0 19 BNE &13f5 &13dc a9 0c LDA #&0c &13de 9d 20 01 STA &0120,X ; charms_position_y &13e1 bd 40 01 LDA &0140,X ; charms_position_z &13e4 18 CLC &13e5 69 08 ADC #&08 &13e7 9d 40 01 STA &0140,X ; charms_position_z &13ea bd 00 01 LDA &0100,X ; charms_position_x &13ed 18 CLC &13ee 69 08 ADC #&08 &13f0 9d 00 01 STA &0100,X ; charms_position_x &13f3 d0 09 BNE &13fe ; end_of_initialise_charms_position_special_cases &13f5 c9 7d CMP #&7d &13f7 d0 05 BNE &13fe ; end_of_initialise_charms_position_special_cases &13f9 a9 3c LDA #&3c &13fb 9d 20 01 STA &0120,X ; charms_position_y ; end_of_initialise_charms_position_special_cases &13fe 8a TXA &13ff 29 07 AND #&07 &1401 a8 TAY &1402 b9 45 00 LDA &0045,Y ; random_charm_order &1405 18 CLC &1406 69 1f ADC #&1f ; SPRITE_CHARM_CUP # Set charm type from random order &1408 9d 60 01 STA &0160,X ; charms_type &140b ca DEX &140c 10 92 BPL &13a0 ; initialise_charms_loop ; shuffle_random_number_generator &140e ae 40 02 LDX &0240 ; os_cfs_timeout_counter # The CFS timeout counter changes every 1/50s ; shuffle_random_number_generator_loop &1411 20 c7 07 JSR &07c7 ; random_number # Ensuring random number generator is well shuffled! &1414 ca DEX &1415 d0 fa BNE &1411 ; shuffle_random_number_generator_loop &1417 20 fa 20 JSR &20fa ; reset_player_data &141a a2 47 LDX #&47 # Blank all three charm sprites on screen &141c 20 40 1a JSR &1a40 ; blank_charm_sprites_on_screen &141f a9 0e LDA #&0e &1421 85 90 STA &90 ; charms_required # Fourteen charms required to complete the game &1423 a9 00 LDA #&00 &1425 85 91 STA &91 ; type_of_charm_dropped_in_cauldron &1427 85 9c STA &9c ; spasms_counter &1429 8d df 30 STA &30df ; charm_counter_high &142c 8d e0 30 STA &30e0 ; charm_counter_low ; start_a_new_life &142f a2 00 LDX #&00 &1431 86 a1 STX &a1 ; impending_spasm_warning &1433 ca DEX &1434 9a TXS # Reset stack &1435 86 72 STX &72 ; turn_delay &1437 8a TXA &1438 20 bd 26 JSR &26bd; set_player_phasing # Set player phasing in &143b c6 8a DEC &8a ; life_counter &143d 10 03 BPL &1442 ; entering_room # Does the player still have lives left? &143f 4c 52 13 JMP &1352 ; game_over # If not, game over ; entering_room &1442 20 e9 1c JSR &1ce9 ; initialise_room # Initialise the room, ; initialise_object_special_cases # then consider a few special cases: &1445 a6 61 LDX &61 ; room_number &1447 e0 e0 CPX #&e0 # Is this room &e0? &1449 d0 05 BNE &1450 ; not_room_e0 &144b a9 08 LDA #&08 ; south &144d 8d 0a 6b STA &6b0a ; objects_movement_xz + 10 # If so, set the FIRE moving south ; not_room_e0 &1450 e0 27 CPX #&27 # Is this room &27? &1452 d0 0b BNE &145f ; not_room_27 &1454 a0 03 LDY #&03 ; room_27_fire_special_case_loop &1456 b9 a2 00 LDA &00a2,Y ; room_27_fire_movement_table # If so, set the FIREs moving in different directions &1459 99 0c 6b STA &6b0c,Y ; objects_movement_xz + 12 &145c 88 DEY &145d 10 f7 BPL &1456 ; room_27_fire_special_case_loop ; not_room_27 &145f e0 78 CPX #&78 # Is this the room with cauldron? (&78) &1461 d0 03 BNE &1466 ; not_room_78 &1463 20 5B 15 JSR &155b ; update_cauldron_magic_on_entry # If so, initialise cauldron ; not_room_78 &1466 a6 71 LDX &71 ; facing_on_entering_room &1468 30 17 BMI &1481 ; not_walked_into_room # Has the player walked into the room? &146a 86 5c STX &5c ; player_facing &146c bd a0 08 LDA &08a0,X ; player_position_x_on_entering_from_facing_table &146f 8d 00 03 STA &0300 ; player_feet_object_position_x &1472 bd a4 08 LDA &08a4,X ; player_position_z_on_entering_from_facing_table &1475 8d 50 03 STA &0350 ; player_feet_object_position_z &1478 b5 66 LDA &66,X ; door_heights &147a 8d 28 03 STA &0328 ; player_feet_object_position_y # If so, set player position to be by the door &147d a9 04 LDA #&04 &147f 85 79 STA &79 ; steps_to_take_into_room # And set the player walking into the room ; not_walked_into_room &1481 a9 00 LDA #&00 &1483 8d 70 06 STA &0670 ; player_feet_object_frame &1486 8d 71 06 STA &0671 ; player_head_object_frame &1489 85 62 STA &62 ; player_is_jumping &148b 85 7e STA &7e ; trigger_spiked_ball_falling &148d a2 1f LDX #&1f ; loop_over_all_objects &148f 9d 00 04 STA &0400,X ; slices_of_screen_changed # Mark all slices of screen as changed &1492 9d c8 03 STA &03c8,X ; objects_direction &1495 ca DEX &1496 10 f7 BPL &148f ; loop_over_all_objects &1498 86 7a STX &7a ; rising_or_falling_object &149a 8e e4 6b STX &6be4 ; player_feet_object_maximum_position &149d a9 01 LDA #&01 &149f 8d 1c 6c STA &6c1c ; player_feet_object_support # Player can be pushed ; remove_charms_that_are_overlapped &14a2 a0 02 LDY #&02 &14a4 84 07 STY &07 ; object_to_consider ; remove_charms_that_are_overlapped_loop &14a6 a4 07 LDY &07 ; object_to_consider &14a8 b9 80 00 LDA &0080,Y ; charm_room_slots &14ab 30 0a BMI &14b7 ; don't_hide_charm # Is there a charm in this room slot? &14ad 20 ab 25 JSR &25ab ; find_an_object_07_overlaps &14b0 f0 05 BEQ &14b7 ; don't_hide_charm # Is it overlapped by another object? &14b2 a9 56 LDA #&56 ; SPRITE_DISAPPEARED &14b4 99 00 05 STA &0500,Y ; objects_type # If so, make it disappear ; don't_hide_charm &14b7 e6 07 INC &07 ; object_to_consider &14b9 a5 07 LDA &07 ; object_to_consider &14bb c9 04 CMP #&04 &14bd d0 e7 BNE &14a6 ; remove_charms_that_are_overlapped_loop &14bf 20 4d 25 JSR &254d ; update_player_head &14c2 20 8e 21 JSR &218e ; update_screen # Plot the room &14c5 a9 06 LDA #&06 &14c7 85 92 STA &92 ; portcullis_grace # Portcullises don't immediately move on entry to room ; main_game_loop &14c9 a0 65 LDY #&65 ; &14cb a2 e8 LDX #&e8 ; &65e8, system_clock_zero &14cd a9 02 LDA #&02; Write system clock (TIME=) &14cf 20 f1 ff JSR &fff1; OSWORD # Reset the system clock to zero ; plot_lives &14d2 a0 67 LDY #&67 # Plot lives &14d4 a2 28 LDX #&28 ; &6728 &14d6 a5 8a LDA &8a ; life_counter &14d8 20 76 1a JSR &1a76 ; plot_character_at_screen_address ; plot_sun_or_moon &14db a5 9c LDA &9c ; spasms_counter # Plot sun or moon &14dd 45 a1 EOR &a1 ; impending_spasm_warning &14df 29 01 AND #&01 # 0 = sun, 1 = moon &14e1 aa TAX &14e2 bd aa 07 LDA &07aa,X ; sun_and_moon_address_table &14e5 85 9d STA &9d ; sun_or_moon_address_low &14e7 85 9f STA &9f ; current_sun_or_moon_address_low ; copy_sun_or_moon &14e9 a0 17 LDY #&17 # The only copy of these sprites is on screen ; copy_sun_or_moon_loop &14eb b1 9d LDA (&9d),Y ; sun_or_moon_address_low # &69a8 (sun) or &69e8 (moon) &14ed 99 c8 68 STA &68c8,Y &14f0 b1 9f LDA (&9f),Y ; current_sun_or_moon_address_low # &6aa8 (sun) or &6ae8 (moon) &14f2 99 c8 69 STA &69c8,Y &14f5 88 DEY &14f6 10 f3 BPL &14eb ; copy_sun_or_moon_loop ; check_if_tab_pressed &14f8 a2 9f LDX #&9f ; TAB # Temporarily pause game while TAB pressed &14fa 20 bd 07 JSR &07bd ; check_if_key_pressed &14fd f0 ca BEQ &14c9 ; main_game_loop &14ff a5 91 LDA &91 ; type_of_charm_dropped_in_cauldron &1501 f0 03 BEQ &1506 ; no_cauldron_drop # Has something been dropped in the cauldron? &1503 20 8e 15 JSR &158e ; handle_charm_dropped_in_cauldron # If so, handle it ; no_cauldron_drop &1506 a5 92 LDA &92 ; portcullis_grace &1508 f0 02 BEQ &150c &150a c6 92 DEC &92 ; portcullis_grace &150c 20 a2 16 JSR &16a2 ; plot_day_counter # Plot days &150f a9 00 LDA #&00 &1511 85 88 STA &88 ; room_charm_changed_state_one # Mark room charms as initially unchanged &1513 85 89 STA &89 ; room_charm_changed_state_two &1515 a2 1f LDX #&1f ; objects_loop &1517 a9 01 LDA #&01 &1519 9d 00 04 STA &0400,X ; slices_of_screen_changed # Mark all slices of screen as initially unchanged &151c e0 1c CPX #&1c &151e b0 08 BCS &1528 &1520 9d 00 6d STA &6d00,X ; objects_needs_unbuffering # Mark regular objects as needing unbuffering &1523 a9 00 LDA #&00 &1525 9d 28 04 STA &0428,X ; objects_about_to_disappear # and not about to disappear &1528 ca DEX &1529 10 ec BPL &1517 ; objects_loop &152b a9 03 LDA #&03 &152d 8d 58 02 STA &0258 ; ESCAPE/BREAK effect # Reset memory on BREAK &1530 20 61 26 JSR &2661 ; drop_spiked_ball_or_portcullis &1533 20 f2 26 JSR &26f2 ; update_objects # Move objects and players &1536 20 4e 15 JSR &154e ; update_cauldron_magic_state &1539 20 8e 21 JSR &218e ; update_screen # Replot anything that has changed ; small_delay_loop &153c a2 45 LDX #&45 &153e a0 00 LDY #&00 ; &0045 ; system_time_buffer # Read system time &1540 a9 01 LDA #&01; Read system clock (=TIME) &1542 20 f1 ff JSR &fff1; OSWORD &1545 a5 45 LDA &45 ; system_time_buffer &1547 c9 03 CMP #&03 &1549 90 f1 BCC &153c ; small_delay_loop # Wait until at least 3/100s have elapsed &154b 4c c9 14 JMP &14c9 ; main_game_loop ; update_cauldron_magic_state &154e a5 61 LDA &61 ; room_number &1550 c9 78 CMP #&78 # Is this the room with cauldron? (&78) &1552 d0 1c BNE &1570 ; not_in_cauldron_room &1554 ad 17 05 LDA &0517 ; objects_type + &17 &1557 c9 53 CMP #&53 ; SPRITE_HOMING_MAGIC # Is the cauldron magic already deadly? &1559 f0 0b BEQ &1566 ; is_wolf # If so, keep it so ; update_cauldron_magic_on_entry &155b ad 00 05 LDA &0500 ; player_feet_object_type # Is the player a wolf? &155e c9 33 CMP #&33 ; SPRITE_WOLF_FEET_FRONT &1560 f0 04 BEQ &1566 ; is_wolf &1562 c9 39 CMP #&39 ; SPRITE_WOLF_FEET_BACK &1564 d0 0b BNE &1571 ; not_wolf ; is_wolf &1566 a9 ff LDA #&ff # If so, make cauldron magic deadly &1568 8d 33 6c STA &6c33 ; objects_support + &17 &156b a9 53 LDA #&53 ; SPRITE_HOMING_MAGIC # and make it home in on the player ; set_cauldron_magic_sprite &156d 8d 17 05 STA &0517 ; objects_type + &17 ; not_in_cauldron_room &1570 60 RTS ; not_wolf &1571 e6 93 INC &93 ; cauldron_magic_state &1573 a5 93 LDA &93 ; cauldron_magic_state &1575 29 03 AND #&03 &1577 aa TAX &1578 b5 98 LDA &98,X ; cauldron_magic_flipped_table &157a 8d 8f 03 STA &038f ; objects_flipped + &17 &157d b5 94 LDA &94,X ; cauldron_magic_type_table # &97 is next_charm_required, displayed 1 in 4 cycles &157f ae 00 05 LDX &0500 ; player_feet_object_type # unless: &1582 e0 42 CPX #&42 ; SPRITE_MAGIC # Is the player phasing? &1584 f0 04 BEQ &158a ; cauldron_is_magic &1586 e0 3f CPX #&3f ; SPRITE_SPASMING_WOLF # or spasming? &1588 d0 e3 BNE &156d ; set_cauldron_magic_sprite ; cauldron_is_magic &158a a9 42 LDA #&42 ; SPRITE_MAGIC &158c d0 df BNE &156d ; set_cauldron_magic_sprite # if so, set cauldron magic to SPRITE_MAGIC ; handle_charm_dropped_in_cauldron &158e a5 91 LDA &91 ; type_of_charm_dropped_in_cauldron &1590 c5 97 CMP &97 ; next_charm_required # Does the dropped charm match what was required? &1592 d0 74 BNE &1608 ; leave # If not, leave &1594 a9 01 LDA #&01 &1596 85 4c STA &4c ; colour &1598 a9 3c LDA #&3c &159a 85 91 STA &91 ; charm_collection_countdown ; collection_sound_and_palette_loop &159c e6 4c INC &4c ; colour &159e a5 4c LDA &4c ; colour &15a0 29 07 AND #&07 &15a2 f0 f8 BEQ &159c ; collection_sound_and_palette_loop # Loop the palette, skipping black &15a4 20 d8 07 JSR &07d8 ; set_palette &15a7 a5 91 LDA &91 ; charm_collection_countdown &15a9 29 03 AND #&03 &15ab d0 05 BNE &15b2 ; no_sound &15ad a2 88 LDX #&88 ; sound_8 &15af 20 e7 07 JSR &07e7 ; play_sound # Play a sound every four cycles ; no_sound &15b2 a9 13 LDA #&13; Wait for vertical retrace # Two v-syncs between cycles &15b4 20 f4 ff JSR &fff4; OSBYTE &15b7 a9 13 LDA #&13; Wait for vertical retrace &15b9 20 f4 ff JSR &fff4; OSBYTE &15bc c6 91 DEC &91 ; charm_collection_countdown &15be d0 dc BNE &159c ; collection_sound_and_palette_loop # type_of_charm_dropped_in_cauldron is zero again ; increment_charm_counter &15c0 ee e0 30 INC &30e0 ; charm_counter_low # Increase the player's score by one &15c3 ad e0 30 LDA &30e0 ; charm_counter_low &15c6 c9 0a CMP #&0a &15c8 d0 08 BNE &15d2 ; don't_update_second_digit &15ca a9 00 LDA #&00 &15cc 8d e0 30 STA &30e0 ; charm_counter_low &15cf ee df 30 INC &30df ; charm_counter_high ; don't_update_second_digit &15d2 a9 04 LDA #&04 ; yellow # Restore the room colour to yellow &15d4 20 d8 07 JSR &07d8 ; set_palette &15d7 c6 90 DEC &90 ; charms_required &15d9 d0 16 BNE &15f1 ; insufficient_charms # Has the player collected enough? ; end_game &15db a2 3c LDX #&3c ; "THE SPELL HAS BROKEN" &15dd a0 14 LDY #&14 &15df 20 59 1a JSR &1a59 ; plot_string &15e2 a2 52 LDX #&52 ; "YOU ARE FREE" # Disappointing end message &15e4 a0 0c LDY #&0c &15e6 20 59 1a JSR &1a59 ; plot_string &15e9 a9 ff LDA #&ff &15eb 20 ed 07 JSR &07ed ; delay_loop # then a long delay &15ee 4c 65 13 JMP &1365 ; game_start # before restarting the game ; insufficient_charms ; set_next_charm_required &15f1 ae 40 02 LDX &0240 ; os_cfs_timeout_counter # The CFS timeout counter changes every 1/50s ; pick_a_really_random_charm_loop &15f4 20 c7 07 JSR &07c7 ; random_number &15f7 ca DEX &15f8 d0 fa BNE &15f4 ; pick_a_really_random_charm_loop # Ensuring random number generator is well shuffled! ; pick_a_random_charm_loop &15fa 20 c7 07 JSR &07c7 ; random_number # Pick a random number between 0 and 6 &15fd 29 07 AND #&07 &15ff c9 07 CMP #&07 &1601 f0 f7 BEQ &15fa ; pick_a_random_charm_loop &1603 18 CLC &1604 69 1f ADC #&1f ; SPRITE_CHARM_CUP # And use it to set the next charm required &1606 85 97 STA &97 ; next_charm_required ; leave &1608 60 RTS ; play_sound_from_position &1609 b9 00 03 LDA &0300,Y ; objects_position_x &160c 18 CLC &160d 79 28 03 ADC &0328,Y ; objects_position_y &1610 79 50 03 ADC &0350,Y ; objects_position_z &1613 0a ASL A ; play_sound_from_A &1614 8d 94 07 STA &0794 ; pitch_of_sound_9 &1617 a2 90 LDX #&90 ; sound_9 &1619 4c e7 07 JMP &07e7 ; play_sound ; animate_phasing ; A=7 out A=0 in &161c 45 63 EOR &63 ; spasm_jumping_or_phasing_stage &161e 0a ASL A &161f 0a ASL A &1620 85 01 STA &01 ; spasm_stage_times_four &1622 0a ASL A &1623 85 1e STA &1e ; spasm_stage_times_eight &1625 a9 c8 LDA #&c8 &1627 38 SEC &1628 e5 1e SBC &1e ; spasm_stage_times_eight &162a 8d 64 07 STA &0764 ; pitch_of_sound_3 &162d ad 78 03 LDA &0378 ; player_feet_object_flipped # Flip sprite &1630 49 07 EOR #&07 &1632 8d 78 03 STA &0378 ; player_feet_object_flipped &1635 c6 63 DEC &63 ; spasm_jumping_or_phasing_stage # Has the player finished phasing? &1637 30 20 BMI &1659 ; leave &1639 a2 50 LDX #&50 ; sound_1 &163b 20 e7 07 JSR &07e7 ; play_sound &163e a2 60 LDX #&60 ; sound_3 &1640 20 e7 07 JSR &07e7 ; play_sound # If not, play sounds (some descending in pitch) &1643 a9 fa LDA #&fa &1645 38 SEC &1646 e5 01 SBC &01 ; spasm_stage_times_four &1648 e5 1e SBC &1e ; spasm_stage_times_eight &164a 8d 64 07 STA &0764 ; pitch_of_sound_3 &164d a2 58 LDX #&58 ; sound_2 &164f 20 e7 07 JSR &07e7 ; play_sound &1652 a2 60 LDX #&60 ; sound_3 &1654 20 e7 07 JSR &07e7 ; play_sound &1657 68 PLA # Pull the return pointer off the stack &1658 68 PLA # effectively calling animate_phasing again on leaving ; leave &1659 60 RTS ; update_spasm_sprite &165a ad 70 06 LDA &0670 ; player_feet_object_frame # Animate between spasming man and wolf &165d 49 01 EOR #&01 &165f 8d 70 06 STA &0670 ; player_feet_object_frame &1662 20 c7 07 JSR &07c7 ; random_number &1665 29 01 AND #&01 &1667 a8 TAY &1668 b9 8d 08 LDA &088d,Y ; facing_flipped_table + 1 # Flip sprite at random &166b 8d 78 03 STA &0378 ; player_feet_object_flipped &166e 20 c7 07 JSR &07c7 ; random_number &1671 29 03 AND #&03 &1673 8d 84 07 STA &0784 ; pitch_of_sound_7 &1676 a2 80 LDX #&80 ; sound_7 &1678 c6 63 DEC &63 ; spasm_jumping_or_phasing_stage &167a 30 03 BMI &167f ; spasm_has_finished # Has the spasm finished? &167c 4c e7 07 JMP &07e7 ; play_sound # If not, play a sound ; spasm_has_finished &167f a9 00 LDA #&00 &1681 8d 70 06 STA &0670 ; player_feet_object_frame &1684 a5 5d LDA &5d ; man_or_wolf &1686 d0 17 BNE &169f ; update_sprite # If the player has become a man (sunrise), &1688 e6 8b INC &8b ; day_counter_low # Add a day to the counter &168a a5 8b LDA &8b ; day_counter_low &168c c9 0a CMP #&0a &168e d0 0f BNE &169f ; update_sprite &1690 a9 00 LDA #&00 &1692 85 8b STA &8b ; day_counter_low &1694 e6 8c INC &8c ; day_counter_high &1696 a5 8c LDA &8c ; day_counter_high &1698 c9 04 CMP #&04 &169a d0 03 BNE &169f ; update_sprite # Is it day 40? &169c 4c 52 13 JMP &1352 ; game_over # If so, game over ; update_sprite &169f 4c 33 21 JMP &2133 ; update_player_sprite_details ; plot_day_counter &16a2 a2 88 LDX #&88 &16a4 a0 6a LDY #&6a &16a6 a5 8c LDA &8c ; day_counter_high &16a8 20 76 1a JSR &1a76 ; plot_character_at_screen_address &16ab a5 8b LDA &8b ; day_counter_low &16ad 4c 7a 1a JMP &1a7a ; plot_character ; phase_player_in &16b0 a9 00 LDA #&00 &16b2 20 1c 16 JSR &161c ; animate_phasing &16b5 a9 00 LDA #&00 # Set the player to be no longer phasing &16b7 85 7c STA &7c ; is_phasing_in_or_out &16b9 20 33 21 JSR &2133 ; update_player_sprite_details &16bc 4c 4d 25 JMP &254d ; update_player_head ; phase_player_out &16bf a9 07 LDA #&07 &16c1 20 1c 16 JSR &161c ; animate_phasing &16c4 20 9d 18 JSR &189d ; store_room_charms_in_array &16c7 4c 2f 14 JMP &142f ; start_a_new_life ; leave &16ca 60 RTS ; player_movement_and_update &16cb e6 6e INC &6e ; spasm_sprite_update_delay &16cd a5 6e LDA &6e ; spasm_sprite_update_delay &16cf a6 7c LDX &7c ; is_phasing_in_or_out &16d1 f0 0c BEQ &16df ; not_phasing # Is the player phasing? &16d3 29 01 AND #&01 &16d5 85 6e STA &6e ; spasm_sprite_update_delay &16d7 d0 f1 BNE &16ca ; leave &16d9 e0 00 CPX #&00 &16db 30 d3 BMI &16b0 ; phase_player_in # If so, phase in or out &16dd d0 e0 BNE &16bf ; phase_player_out # with no further movement ; not_phasing &16df ae 00 05 LDX &0500 ; player_feet_object_type &16e2 e0 3f CPX #&3f ; SPRITE_SPASMING_WOLF &16e4 d0 0c BNE &16f2 ; not_spasming # Is the player spasming? &16e6 29 03 AND #&03 &16e8 85 6e STA &6e ; spasm_sprite_update_delay &16ea d0 de BNE &16ca ; leave # If so, update the sprite once every four cycles &16ec 4c 5a 16 JMP &165a ; update_spasm_sprite # with no further movement ; to_not_pressed_A &16ef 4c a4 17 JMP &17a4 ; not_pressed_A ; not_spasming &16f2 e6 22 INC &22 ; object_has_changed &16f4 a5 7b LDA &7b ; object_to_update # Is the player being moved by something else? &16f6 d0 d2 BNE &16ca ; leave # (e.g. a moving block) Leave if so. &16f8 ad c8 6b LDA &6bc8 ; player_feet_object_velocity_y &16fb d0 02 BNE &16ff ; is_moving_vertically &16fd 85 62 STA &62 ; player_is_jumping # Jump stops when vertical speed is zero ; is_moving_vertically &16ff 20 2f 18 JSR &182f ; handle_spasm_countdown &1702 a5 62 LDA &62 ; player_is_jumping &1704 d0 12 BNE &1718 ; shift_not_released # Can't drop if player is jumping &1706 a2 ff LDX #&ff ; SHIFT &1708 20 bd 07 JSR &07bd ; check_if_key_pressed &170b d0 09 BNE &1716 ; shift_not_pressed &170d a5 87 LDA &87 ; shift_held &170f 30 07 BMI &1718 ; shift_not_released &1711 86 87 STX &87 ; shift_held &1713 4c c6 18 JMP &18c6 ; process_shift_press # Need to press and release SHIFT ; shift_not_pressed &1716 86 87 STX &87 ; shift_held ; shift_not_released &1718 a5 79 LDA &79 ; steps_to_take_into_room &171a f0 03 BEQ &171f ; not_walking_into_room # Is the player walking into the room? &171c 4c fa 17 JMP &17fa ; walking_into_room # If so, no further movement possible ; not_walking_into_room &171f a5 62 LDA &62 ; player_is_jumping &1721 30 cc BMI &16ef ; to_not_pressed_A # Can't jump if player has had move &1723 d0 3c BNE &1761 ; is_jumping_already # Can't jump if already jumping &1725 a2 be LDX #&be ; A &1727 20 bd 07 JSR &07bd ; check_if_key_pressed &172a d0 78 BNE &17a4 ; not_pressed_A &172c a9 ff LDA #&ff &172e 85 72 STA &72 ; turn_delay &1730 a2 68 LDX #&68 ; sound_4 &1732 20 e7 07 JSR &07e7 ; play_sound &1735 a2 70 LDX #&70 ; sound_5 &1737 20 e7 07 JSR &07e7 ; play_sound &173a ad 50 03 LDA &0350 ; player_feet_object_position_z # Is the player outside the room boundaries? &173d c9 10 CMP #&10 &173f 90 4e BCC &178f ; to_take_a_step_forward_too # If so, don't let them jump &1741 c9 86 CMP #&86 &1743 b0 4a BCS &178f ; to_take_a_step_forward_too &1745 ad 00 03 LDA &0300 ; player_feet_object_position_x &1748 c9 10 CMP #&10 &174a 90 43 BCC &178f ; to_take_a_step_forward_too &174c c9 86 CMP #&86 &174e b0 3f BCS &178f ; to_take_a_step_forward_too &1750 a9 07 LDA #&07 &1752 85 62 STA &62 ; player_is_jumping # Mark player as jumping &1754 85 63 STA &63 ; spasm_jumping_or_phasing_stage &1756 85 64 STA &64 ; upward_jump &1758 a9 01 LDA #&01 &175a 8d c8 6b STA &6bc8 ; player_feet_object_velocity_y &175d 85 74 STA &74 ; jump_key_held &175f d0 25 BNE &1786 ; is_jumping_already &1761 a5 64 LDA &64 ; upward_jump &1763 30 2d BMI &1792 ; to_take_a_step_forward # Is the player still jumping upwards? &1765 c6 63 DEC &63 ; spasm_jumping_or_phasing_stage &1767 30 2c BMI &1795 ; downward_stage_of_jump # Set them falling if they're on their way down &1769 d0 04 BNE &176f ; still_jumping_upwards # Is the player at the top of the jump? &176b a5 74 LDA &74 ; jump_key_held # If so, are they still pressing A? &176d f0 26 BEQ &1795 ; downward_stage_of_jump # If not, set them falling ; still_jumping_upwards &176f a5 63 LDA &63 ; spasm_jumping_or_phasing_stage &1771 c9 06 CMP #&06 &1773 b0 11 BCS &1786 ; set_vertical_speed_from_jump_stage # Set player's vertical speed to 7, 2 1 or 0 ? &1775 c9 03 CMP #&03 &1777 90 0d BCC &1786 ; set_vertical_speed_from_jump_stage # Mid-jump, see if A is still pressed &1779 a2 be LDX #&be ; A &177b 20 bd 07 JSR &07bd ; check_if_key_pressed &177e f0 06 BEQ &1786 ; set_vertical_speed_from_jump_stage &1780 a9 02 LDA #&02 &1782 85 63 STA &63 ; spasm_jumping_or_phasing_stage # If not, bring the jump to a quicker end &1784 c6 74 DEC &74 ; jump_key_held ; set_vertical_speed_from_jump_stage &1786 a5 63 LDA &63 ; spasm_jumping_or_phasing_stage &1788 8d 00 6c STA &6c00 ; player_feet_object_vertical_speed &178b c9 07 CMP #&07 &178d f0 19 BEQ &17a8 ; consider_turn # Allow the player to turn at start of jump ; to_take_a_step_forward_too &178f 4c 02 18 JMP &1802 ; take_a_step_forward # Otherwise, the player moves forward as well ; to_take_a_step_forward &1792 4c 02 18 JMP &1802 ; take_a_step_forward ; downward_stage_of_jump &1795 a9 ff LDA #&ff &1797 85 64 STA &64 ; upward_jump &1799 8d c8 6b STA &6bc8 ; player_feet_object_velocity_y # Set player falling with speed 1 &179c a9 01 LDA #&01 &179e 8d 00 6c STA &6c00 ; player_feet_object_vertical_speed &17a1 4c 02 18 JMP &1802 ; take_a_step_forward ; not_pressed_A &17a4 a9 ff LDA #&ff # Mark player as having had move &17a6 85 62 STA &62 ; player_is_jumping ; consider_turn &17a8 a5 5c LDA &5c ; player_facing &17aa 85 01 STA &01 ; previous_player_facing &17ac a5 72 LDA &72 ; turn_delay # Has the player turned recently? &17ae 30 04 BMI &17b4 ; can_turn &17b0 c6 72 DEC &72; turn_delay # If so, a slight delay before they can turn again &17b2 10 29 BPL &17dd ; haven't_turned ; can_turn &17b4 a2 e6 LDX #&e6 ; LEFT &17b6 20 bd 07 JSR &07bd ; check_if_key_pressed &17b9 d0 06 BNE &17c1 ; no_left_turn # Otherwise, has LEFT been pressed? &17bb c6 5c DEC &5c ; player_facing # If so, rotate left &17bd a9 02 LDA #&02 &17bf 85 72 STA &72 ; turn_delay ; no_left_turn &17c1 a2 86 LDX #&86 ; RIGHT &17c3 20 bd 07 JSR &07bd ; check_if_key_pressed &17c6 d0 06 BNE &17ce ; no_right_turn # Has RIGHT been pressed? &17c8 e6 5c INC &5c ; player_facing # If so, rotate right &17ca a9 02 LDA #&02 &17cc 85 72 STA &72 ; turn_delay ; no_right_turn &17ce a5 5c LDA &5c ; player_facing &17d0 c5 01 CMP &01 ; previous_player_facing &17d2 f0 09 BEQ &17dd ; haven't_turned # Has the player turned? &17d4 e6 80 INC &80 ; turn_counter &17d6 a5 80 LDA &80 ; turn_counter # If so, play a sound based on their direction &17d8 29 03 AND #&03 &17da 20 23 18 JSR &1823 ; play_sound_with_pitch_from_A_in_table ; haven't_turned &17dd 20 33 21 JSR &2133 ; update_player_sprite_details &17e0 a5 62 LDA &62 ; player_is_jumping &17e2 f0 02 BEQ &17e6 ; no_step_forward &17e4 10 1c BPL &1802 ; take_a_step_forward # If the player is jumping, move them forward too ; no_step_forward &17e6 a2 9e LDX #&9e ; Z &17e8 20 bd 07 JSR &07bd ; check_if_key_pressed &17eb f0 15 BEQ &1802 ; take_a_step_forward # Has Z been pressed? &17ed ad 70 06 LDA &0670 ; player_feet_object_frame &17f0 f0 07 BEQ &17f9 ; leave &17f2 c9 02 CMP #&02 &17f4 f0 03 BEQ &17f9 ; leave &17f6 4c 3d 25 JMP &253d ; animate_player_feet # If not, bring their feet to a suitable frame ; leave &17f9 60 RTS ; walking_into_room &17fa c6 79 DEC &79 ; steps_to_take_into_room # Has the player finished walking into the room? &17fc d0 04 BNE &1802 ; take_a_step_forward &17fe a9 00 LDA #&00 &1800 85 92 STA &92 ; portcullis_grace # If so, allow portcullises to fall ; take_a_step_forward &1802 20 3d 25 JSR &253d ; animate_player_feet # If the player is moving forward, &1805 e6 81 INC &81 ; walking_sound_delay &1807 a5 81 LDA &81 ; walking_sound_delay &1809 29 02 AND #&02 &180b aa TAX &180c a5 81 LDA &81 ; walking_sound_delay &180e 29 01 AND #&01 &1810 d0 03 BNE &1815 ; no_sound # Play a sound every two steps &1812 20 24 18 JSR &1824 ; play_sound_with_pitch_from_X_in_table # Alternating between two pitches ; no_sound &1815 a9 03 LDA #&03 &1817 8d 1c 6b STA &6b1c ; player_feet_object_horizontal_speed # Player walks forward with speed 3 &181a a6 5c LDX &5c ; player_facing &181c bd a8 08 LDA &08a8,X ; facing_to_movement_xz &181f 8d 00 6b STA &6b00 ; player_feet_object_movement_xz # Movement based on the direction they are facing &1822 60 RTS ; play_sound_with_pitch_from_A_in_table &1823 aa TAX ; play_sound_with_pitch_from_X_in_table &1824 bd b0 07 LDA &07b0,X ; pitch_table &1827 8d 7c 07 STA &077c ; pitch_of_sound_6 &182a a2 78 LDX #&78 ; sound_6 &182c 4c e7 07 JMP &07e7 ; play_sound ; handle_spasm_countdown &182f c6 60 DEC &60 ; spasm_countdown_low # Tick down to spasm &1831 d0 37 BNE &186a ; no_spasm_yet &1833 c6 75 DEC &75 ; spasm_countdown_high &1835 10 33 BPL &186a ; no_spasm_yet &1837 a5 62 LDA &62 ; player_is_jumping &1839 d0 2b BNE &1866 ; stave_off_spasm_while_jumping # Don't start spasm while jumping &183b a9 01 LDA #&01 # Reset spasm countdown to &13f &183d 85 75 STA &75 ; spasm_countdown_high &183f a9 3f LDA #&3f ; SPRITE_SPASMING_WOLF &1841 85 60 STA &60 ; spasm_countdown_low &1843 8d 00 05 STA &0500 ; player_feet_object_type &1846 a9 08 LDA #&08 &1848 85 63 STA &63 ; spasm_jumping_or_phasing_stage &184a a0 00 LDY #&00 &184c 84 a1 STY &a1 ; impending_spasm_warning &184e c8 INY &184f 8c 70 06 STY &0670 ; player_feet_object_frame &1852 84 07 STY &07 ; object_to_consider &1854 20 10 25 JSR &2510 ; wipe_object_Y_that_still_needs_unbuffering &1857 c6 07 DEC &07 ; object_to_consider &1859 68 PLA # Skip the rest of player_movement_and_update &185a 68 PLA # when handle_spasm_countdown returns &185b a5 5d LDA &5d ; man_or_wolf &185d 49 0c EOR #&0c &185f 85 5d STA &5d ; man_or_wolf &1861 e6 9c INC &9c ; spasms_counter &1863 4c 5a 16 JMP &165a ; update_spasm_sprite ; stave_off_spasm_while_jumping &1866 e6 60 INC &60 ; spasm_countdown_low # Stave off the spasm while jumping &1868 e6 75 INC &75 ; spasm_countdown_high ; no_spasm_yet &186a a5 75 LDA &75 ; spasm_countdown_high &186c d0 0a BNE &1878 ; leave &186e a5 60 LDA &60 ; spasm_countdown_low &1870 f0 06 BEQ &1878 ; leave &1872 c9 20 CMP #&20 # Warm of impending spasm at &020 &1874 b0 02 BCS &1878 ; leave &1876 e6 a1 INC &a1 ; impending_spasm_warning ; leave &1878 60 RTS ; change_room &1879 18 CLC &187a 65 61 ADC &61 ; room_number # A will get added to room_number &187c 48 PHA &187d 20 9d 18 JSR &189d ; store_room_charms_in_array # Note where the charms in this room were &1880 68 PLA &1881 85 61 STA &61 ; room_number &1883 68 PLA &1884 68 PLA # Remove handle_object_movement &1885 68 PLA &1886 68 PLA # and update_objects from stack &1887 a5 8e LDA &8e ; previous_movement_single &1889 4a LSR A &188a 18 CLC &188b 69 01 ADC #&01 # Transform directions 1 2 4 8 into 1 2 3 0 &188d c9 05 CMP #&05 &188f d0 02 BNE &1893 &1891 a9 00 LDA #&00 &1893 85 71 STA &71 ; facing_on_entering_room &1895 85 5c STA &5c ; player_facing # Set the direction the player is facing based on this &1897 20 33 21 JSR &2133 ; update_player_sprite_details &189a 4c 42 14 JMP &1442 ; entering_room # When done, entering_room will return to &1536 ; store_room_charms_in_array &189d a0 02 LDY #&02 # Consider the room slots, 2 and 3 ; store_room_charms_loop &189f b6 80 LDX &80,Y &18a1 30 1d BMI &18c0 ; no_charm_here # Is there a charm in this room slot? &18a3 b9 00 03 LDA &0300,Y ; objects_position_x # If so, record its position &18a6 9d 00 01 STA &0100,X ; charms_position_x &18a9 b9 28 03 LDA &0328,Y ; objects_position_y &18ac 9d 20 01 STA &0120,X ; charms_position_y &18af b9 50 03 LDA &0350,Y ; objects_position_z &18b2 9d 40 01 STA &0140,X ; charms_position_z &18b5 b9 00 05 LDA &0500,Y ; objects_type &18b8 9d 60 01 STA &0160,X ; charms_type &18bb a5 61 LDA &61 ; room_number &18bd 9d 80 01 STA &0180,X ; charms_position_room ; no_charm_here &18c0 c8 INY &18c1 c0 04 CPY #&04 &18c3 d0 da BNE &189f ; store_room_charms_loop &18c5 60 RTS ; process_shift_press &18c6 ad 50 03 LDA &0350 ; player_feet_object_position_z # Is the player outside the room boundaries? &18c9 c9 10 CMP #&10 &18cb 90 0f BCC &18dc ; outside_room &18cd c9 86 CMP #&86 &18cf b0 0b BCS &18dc ; outside_room &18d1 ad 00 03 LDA &0300 ; player_feet_object_position_x &18d4 c9 10 CMP #&10 &18d6 90 04 BCC &18dc ; outside_room &18d8 c9 86 CMP #&86 &18da 90 06 BCC &18e2 ; not_outside_room ; outside_room &18dc a9 ff LDA #&ff # If so, there can be no object above them &18de 85 56 STA &56 ; object_above_player &18e0 30 15 BMI &18f7 ; create_new_object_where_player_is_standing ; not_outside_room &18e2 ad 28 03 LDA &0328 ; player_feet_object_position_y # Otherwise, &18e5 48 PHA &18e6 18 CLC &18e7 69 0c ADC #&0c # Add the height of an object to the player's position &18e9 85 58 STA &58 ; player_new_position_y &18eb 8d 28 03 STA &0328 ; player_feet_object_position_y &18ee 20 ab 25 JSR &25ab ; find_an_object_07_overlaps # And see whether anything now overlaps &18f1 85 56 STA &56 ; object_above_player &18f3 68 PLA &18f4 8d 28 03 STA &0328 ; player_feet_object_position_y # Having done so, reset the player's position ; create_new_object_where_player_is_standing &18f7 a6 44 LDX &44 ; number_of_objects &18f9 e8 INX &18fa 86 07 STX &07 ; new_object_number # Create a new object for the charm in next unused slot &18fc a9 14 LDA #&14 &18fe 9d 34 07 STA &0734,X ; objects_size_y &1901 ad 28 03 LDA &0328 ; player_feet_object_position_y &1904 9d 28 03 STA &0328,X ; objects_position_y &1907 f0 06 BEQ &190f ; on_floor &1909 fe 34 07 INC &0734,X ; objects_size_y # Slightly larger if it isn't on the floor &190c de 28 03 DEC &0328,X ; objects_position_y ; on_floor &190f fe 34 07 INC &0734,X ; objects_size_y &1912 bd 00 03 LDA &0300,X ; objects_position_x # This was set by final call to handle_object_movement &1915 38 SEC &1916 e9 04 SBC #&04 &1918 9d 00 03 STA &0300,X ; objects_position_x # (which copied object 0's x and z into this slot) &191b bd 50 03 LDA &0350,X ; objects_position_z &191e 38 SEC &191f e9 04 SBC #&04 &1921 9d 50 03 STA &0350,X ; objects_position_z &1924 a9 13 LDA #&13 &1926 9d fc 06 STA &06fc,X ; objects_size_z &1929 9d 18 07 STA &0718,X ; objects_size_x ; update_charm_slots &192c a2 02 LDX #&02 # Consider charms in the two room slots, 2 and 3 ; consider_room_charms_loop &192e bd 70 06 LDA &0670,X ; objects_frame &1931 30 12 BMI &1945 ; skip_this_room_charm # If the charm isn't hidden, &1933 bd 00 05 LDA &0500,X ; objects_type &1936 c9 26 CMP #&26 ; SPRITE_CHARM_LIFE &1938 f0 0b BEQ &1945 ; skip_this_room_charm # and isn't an extra life, &193a c9 56 CMP #&56 ; SPRITE_DISAPPEARED &193c f0 07 BEQ &1945 ; skip_this_room_charm # and hasn't already been collected, &193e a4 07 LDY &07 ; new_object_number &1940 20 16 23 JSR &2316 ; do_objects_overlap &1943 30 07 BMI &194c; pick_up_charm # then if the player is touching it, pick it up ; skip_this_room_charm &1945 e8 INX &1946 e0 04 CPX #&04 &1948 d0 e4 BNE &192e ; consider_room_charms_loop &194a f0 6a BEQ &19b6 ; drop_charm # If not, the player is only dropping a charm ; pick_up_charm &194c 86 52 STX &52 ; room_slot_picking_up_from &194e b4 80 LDY &80,X ; charm_room_slots &1950 84 53 STY &53 ; number_of_charm_being_picked_up &1952 f6 86 INC &86,X ; room_charms_changed_state # Note room object as having changed &1954 a4 86 LDY &86 ; charm_pocket_slot_three &1956 30 0a BMI &1962 ; pocket_three_is_empty # Is pocket three empty? &1958 94 80 STY &80,X ; charm_room_slots &195a b9 60 01 LDA &0160,Y ; charms_type &195d 9d 00 05 STA &0500,X ; objects_type # If not, swap its charm with this one &1960 10 06 BPL &1968 ; store_charm_in_pocket ; pocket_three_is_empty &1962 a9 ff LDA #&ff # Otherwise, clear the room slot &1964 95 86 STA &86,X ; room_charms_changed_state &1966 95 80 STA &80,X ; charm_room_slots ; store_charm_in_pocket &1968 20 22 1a JSR &1a22 ; rotate_charm_sprites_on_screen # Move pocket charms on screen &196b a6 53 LDX &53 ; number_of_charm_being_picked_up &196d 86 84 STX &84 ; charm_pocket_slot_one # Put room charm in pocket one ; plot_collected_charm &196f a9 01 LDA #&01 &1971 bc 60 01 LDY &0160,X ; charms_type &1974 b9 74 2f LDA &2f74,Y ; sprite_lines_table &1977 85 4a STA &4a ; lines_in_charm_sprite &1979 98 TYA &197a 0a ASL A &197b a8 TAY &197c b9 c1 2e LDA &2ec1,Y ; sprite_address_table + 1 &197f 8d 98 19 STA &1998 # Self-modifying code &1982 b9 c0 2e LDA &2ec0,Y ; sprite_address_table &1985 8d 97 19 STA &1997 # Self-modifying code &1988 a9 6a LDA #&6a &198a 85 4c STA &4c ; screen_address_high &198c 85 7e STA &7e ; trigger_spiked_ball_falling # Make spiked balls fall on collection of charm &198e a2 00 LDX #&00 &1990 86 4b STX &4b ; screen_address_low &1992 a0 07 LDY #&07 &1994 84 49 STY &49 ; bytes_per_row ; plot_charm_sprite_byte_loop &1996 bd ff ff LDA &ffff,X # actually LDA sprite_data, X &1999 91 4b STA (&4b),Y ; screen_address # Plot new pocket charm on screen &199b e8 INX &199c 98 TYA &199d 18 CLC &199e 69 08 ADC #&08 &19a0 a8 TAY &19a1 c9 18 CMP #&18 &19a3 90 f1 BCC &1996 ; plot_charm_sprite_loop &19a5 c6 49 DEC &49 ; bytes_per_row &19a7 10 06 BPL &19af &19a9 c6 4c DEC &4c ; screen_address_high &19ab a0 07 LDY #&07 &19ad 84 49 STY &49 ; bytes_per_row &19af a4 49 LDY &49 ; bytes_per_row &19b1 c6 4a DEC &4a ; lines_in_charm_sprite &19b3 d0 e1 BNE &1996 ; plot_charm_sprite_loop &19b5 60 RTS ; drop_charm # If the player is only dropping a charm, &19b6 a5 86 LDA &86 ; charm_pocket_slot_three &19b8 30 68 BMI &1a22 ; rotate_charm_sprites_on_screen &19ba a5 56 LDA &56 ; object_above_player &19bc 30 f7 BMI &19b5 ; leave # Can't drop a charm if this puts player in something ; find_free_charm_room_slot_loop &19be a2 02 LDX #&02 # Otherwise, find a free room slot &19c0 b5 80 LDA &80,X ; charm_room_slots &19c2 30 05 BMI &19c9 ; found_empty_slot &19c4 e8 INX &19c5 b5 80 LDA &80,X ; charm_room_slots &19c7 10 ec BPL &19b5 ; leave # Leave if there are none; maximum two charms per room ; found_empty_slot &19c9 ad 00 03 LDA &0300 ; player_feet_object_position_x # Copy position from player &19cc 9d 00 03 STA &0300,X ; objects_position_x &19cf ad 28 03 LDA &0328 ; player_feet_object_position_y &19d2 9d 28 03 STA &0328,X ; objects_position_y &19d5 ad 50 03 LDA &0350 ; player_feet_object_position_z &19d8 9d 50 03 STA &0350,X ; objects_position_z &19db a5 58 LDA &58 ; player_new_position_y &19dd 8d 28 03 STA &0328 ; player_feet_object_position_y &19e0 f6 86 INC &86,X ; room_charms_changed_state &19e2 a9 ff LDA #&ff &19e4 9d 38 06 STA &0638,X ; objects_buffer_start_address_high # This object hasn't been plotted yet, so no buffer &19e7 9d 54 06 STA &0654,X ; objects_buffer_end_address_high &19ea ad 1c 06 LDA &061c ; player_object_last_slice_address &19ed 9d 1c 06 STA &061c,X ; objects_last_slice_address &19f0 ad 00 06 LDA &0600 ; player_object_first_slice_address &19f3 9d 00 06 STA &0600,X ; objects_first_slice_address &19f6 a4 86 LDY &86 ; charm_pocket_slot_three # Put pocket three charm into room &19f8 b9 60 01 LDA &0160,Y ; charms_type &19fb 9d 00 05 STA &0500,X ; objects_type &19fe 94 80 STY &80,X ; charm_room_slots &1a00 a9 00 LDA #&00 &1a02 9d 70 06 STA &0670,X ; objects_frame ; check_if_standing_on_cauldron &1a05 a5 58 LDA &58 ; player_new_position_y &1a07 c9 24 CMP #&24 # Is the player at the height of the cauldron? &1a09 d0 17 BNE &1a22 ; not_standing_on_cauldron &1a0b a5 61 LDA &61 ; room_number &1a0d c9 78 CMP #&78 # And in the room with the cauldron? (&78) &1a0f d0 11 BNE &1a22 ; not_standing_on_cauldron &1a11 bd 00 05 LDA &0500,X ; objects_type &1a14 85 91 STA &91 ; type_of_charm_dropped_in_cauldron # If so, note an object has been dropped &1a16 a9 ff LDA #&ff &1a18 9d 70 06 STA &0670,X ; objects_frame # And make it disappear &1a1b 95 86 STA &86,X ; room_charms_changed_state &1a1d a9 56 LDA #&56 ; SPRITE_DISAPPEARED &1a1f 9d 00 05 STA &0500,X ; objects_type ; not_standing_on_cauldron ; rotate_charm_sprites_on_screen &1a22 a2 2f LDX #&2f ; rotate_charm_sprites_on_screen_loop &1a24 bd 00 68 LDA &6800,X # Shuffle three lines of screen memory to the right &1a27 9d 18 68 STA &6818,X &1a2a bd 00 69 LDA &6900,X &1a2d 9d 18 69 STA &6918,X &1a30 bd 00 6a LDA &6a00,X &1a33 9d 18 6a STA &6a18,X &1a36 ca DEX &1a37 10 eb BPL &1a24 ; rotate_charm_sprites_on_screen_loop &1a39 a2 88 LDX #&88 ; sound_8 &1a3b 20 e7 07 JSR &07e7 ; play_sound # Play a sound ; blank_first_charm_sprite_on_screen &1a3e a2 17 LDX #&17 # Wipe pocket one on screen ; blank_charm_sprites_on_screen &1a40 a9 00 LDA #&00 ; blank_first_charm_sprite_on_screen_loop &1a42 9d 00 68 STA &6800,X # Wipe three lines of screen memory &1a45 9d 00 69 STA &6900,X &1a48 9d 00 6a STA &6a00,X &1a4b ca DEX &1a4c 10 f4 BPL &1a42 ; blank_first_charm_sprite_on_screen_loop &1a4e a5 85 LDA &85 ; charm_pocket_slot_two # Put pocket two into pocket three &1a50 85 86 STA &86 ; charm_pocket_slot_three &1a52 a5 84 LDA &84 ; charm_pocket_slot_one # Put pocket one into pocket two &1a54 85 85 STA &85 ; charm_pocket_slot_two &1a56 86 84 STX &84 ; charm_pocket_slot_one # Empty pocket one &1a58 60 RTS ; plot_string ; X = offset in string table at &30c1 ; Y = length &1a59 bd c1 30 LDA &30c1,X ; string_table &1a5c 85 49 STA &49 ; screen_address_low &1a5e bd c2 30 LDA &30c2,X ; string_table + 1 &1a61 85 4a STA &4a ; screen_address_high &1a63 86 4d STX &4d ; string_offset &1a65 84 4e STY &4e ; string_length ; plot_string_loop &1a67 a6 4d LDX &4d ; string_offset &1a69 bd c3 30 LDA &30c3,X ; string_table + 2 &1a6c 20 7a 1a JSR &1a7a ; plot_character &1a6f e6 4d INC &4d ; string_offset &1a71 c6 4e DEC &4e ; string_length &1a73 d0 f2 BNE &1a67 plot_string_loop &1a75 60 RTS ; plot_character_at_screen_address ; A = character ; X, Y = screen address &1a76 86 49 STX &49 ; screen_address_low &1a78 84 4a STY &4a ; screen_address_high ; plot_character &1a7a 18 CLC &1a7b 69 10 ADC #&10 &1a7d 85 4b STA &4b ; font_address_low &1a7f a9 c0 LDA #&c0A # Use OS character font table at &c000 &1a81 06 4b ASL &4b ; font_address_low &1a83 06 4b ASL &4b ; font_address_low &1a85 69 00 ADC #&00 &1a87 06 4b ASL &4b ; font_address_low &1a89 69 00 ADC #&00 &1a8b 85 4c STA &4c ; font_address_high &1a8d a0 07 LDY #&07 ; plot_character_loop &1a8f b1 4b LDA (&4b),Y ; font_address &1a91 91 49 STA (&49),Y ; screen_address &1a93 88 DEY &1a94 10 f9 BPL &1a8f ; plot_character_loop &1a96 a5 49 LDA &49 ; screen_address_low &1a98 18 CLC &1a99 69 08 ADC #&08 &1a9b 85 49 STA &49 ; screen_address_low &1a9d 60 RTS ; to_leave_with_negative_buffer_address &1a9e 4c 8c 1b JMP &1b8c ; leave_with_negative_buffer_address ; don't_plot &1aa1 60 RTS ; plot_object &1aa2 a6 47 LDX &47 ; object_number &1aa4 bd d8 6c LDA &6cd8,X ; objects_needs_plotting # Does this object need plotting? &1aa7 f0 f8 BEQ &1aa1 ; don't_plot &1aa9 e4 70 CPX &70 ; start_of_background_objects &1aab b0 05 BCS &1ab2 ; is_background_object # Is it a background object? &1aad bd 70 06 LDA &0670,X ; objects_frame &1ab0 30 ec BMI &1a9e ; to_leave_with_negative_buffer_address # Or a regular object that isn't hidden? ; is_background_object &1ab2 bd a0 03 LDA &03a0,X ; objects_bytes_per_line_of_sprite &1ab5 85 45 STA &45 ; bytes_per_line_of_sprite &1ab7 bd 78 03 LDA &0378,X ; objects_flipped &1aba 48 PHA ; object_flipped &1abb bd 50 03 LDA &0350,X ; objects_position_z # Convert x and z position to pixel slice &1abe 18 CLC &1abf 7d 00 03 ADC &0300,X ; objects_position_x &1ac2 38 SEC &1ac3 e9 20 SBC #&20 &1ac5 48 PHA &1ac6 29 f8 AND #&f8 &1ac8 85 13 STA &13 ; slice_address &1aca 85 5a STA &5a ; first_slice_address &1acc 68 PLA &1acd 29 07 AND #&07 &1acf 85 48 STA &48 ; bits_to_shift_sprite &1ad1 f0 02 BEQ &1ad5 ; isn't_shifted &1ad3 e6 45 INC &45 ; bytes_per_line_of_sprite ; isn't_shifted &1ad5 a5 45 LDA &45 ; bytes_per_line_of_sprite &1ad7 0a ASL A &1ad8 0a ASL A &1ad9 0a ASL A &1ada 65 5a ADC &5a ; first_slice_address &1adc 85 5b STA &5b ; last_slice_address &1ade a2 00 LDX #&00 &1ae0 a0 e8 LDY #&e8 ; INX # Change direction of loop &1ae2 68 PLA ; object_flipped # depending on whether sprite is flipped &1ae3 f0 05 BEQ &1aea ; isn't_flipped &1ae5 a6 45 LDX &45 ; bytes_per_line_of_sprite &1ae7 ca DEX &1ae8 a0 ca LDY #&ca ; DEX ; isn't_flipped &1aea 8c 04 1b STY &1b04 # Self-modifying code &1aed a9 ea LDA #&ea ; NOP # Default to a 2 byte sprite &1aef 85 20 STA &20 ; inx_3 # Self-modifying code &1af1 85 21 STA &21 ; inx_4 # Self-modifying code &1af3 85 22 STA &22 ; inx_5 # Self-modifying code &1af5 a5 13 LDA &13 ; slice_address &1af7 4a LSR A &1af8 4a LSR A &1af9 4a LSR A &1afa a8 TAY # Y contains the eight-pixel slice of screen ; mark_sprite_slices_and_set_INXs_loop &1afb b9 00 04 LDA &0400,Y ; slices_of_screen_changed # Depending on whether that slice has changed, &1afe 95 52 STA &52,X ; sprite_slices_should_plot # mark the corresponding strip of the sprite &1b00 a9 e8 LDA #&e8 ; INX # Extend copying for sprites that are wider &1b02 95 1e STA &1e,X ; inx_1 # Self-modifying code &1b04 e8 INX # actually DEX for flipped sprites &1b05 c8 INY &1b06 c6 45 DEC &45 ; bytes_per_line_of_sprite &1b08 d0 f1 BNE &1afb ; mark_sprite_slices_and_set_INXs_loop &1b0a a6 47 LDX &47 ; object_number &1b0c bd 00 05 LDA &0500,X ; objects_type &1b0f c9 13 CMP #&13 ; SPRITE_BALL &1b11 90 04 BCC &1b17 ; doesn't_have_frame &1b13 18 CLC &1b14 7d 70 06 ADC &0670,X ; objects_frame # Select sprite based on frame ; doesn't_have_frame &1b17 a8 TAY # Y is sprite from object and frame &1b18 bd 00 03 LDA &0300,X ; objects_position_x # Calculate high byte of buffer addresses &1b1b 4a LSR A &1b1c 85 1c STA &1c ; tmp &1b1e a9 90 LDA #&90 &1b20 38 SEC &1b21 fd 50 03 SBC &0350,X ; objects_position_z &1b24 4a LSR A &1b25 18 CLC &1b26 65 1c ADC &1c ; tmp &1b28 7d 28 03 ADC &0328,X ; objects_position_y # using x, y and z positions &1b2b 38 SEC &1b2c f9 66 2e SBC &2e66,Y ; sprite_y_subtraction &1b2f 48 PHA &1b30 4a LSR A &1b31 4a LSR A &1b32 4a LSR A &1b33 85 1c STA &1c ; buffer_offset_high # (the low byte is the slice address) &1b35 a9 6a LDA #&6a # Calculate screen buffer address &1b37 18 CLC &1b38 65 1c ADC &1c ; buffer_offset_high &1b3a 30 4f BMI &1b8b ; leave_with_negative_buffer_address_pull # Leave if this would be outside of the buffer &1b3c 85 09 STA &09 ; buffer_address_high &1b3e 68 PLA &1b3f 29 07 AND #&07 &1b41 49 07 EOR #&07 &1b43 85 07 STA &07 ; location_in_eight_byte_screen_block &1b45 bd a0 03 LDA &03a0,X ; objects_bytes_per_line_of_sprite &1b48 85 46 STA &46 ; bytes_per_line_of_sprite &1b4a b9 74 2f LDA &2f74,Y ; sprite_lines_table &1b4d 85 0f STA &0f ; lines_in_sprite &1b4f 85 1c STA &1c ; lines_in_sprite &1b51 98 TYA &1b52 0a ASL A &1b53 a8 TAY ; calculate_sprite_address &1b54 b9 c0 2e LDA &2ec0,Y ; sprite_address_table # Calculate the address of the sprite data &1b57 85 49 STA &49 ; sprite_address_low &1b59 18 CLC &1b5a 69 c6 ADC #&c6 &1b5c 85 4b STA &4b ; sprite_mask_address_low &1b5e b9 c1 2e LDA &2ec1,Y ; sprite_address_table + 1 &1b61 85 4a STA &4a ; sprite_address_high &1b63 69 0f ADC #&0f &1b65 85 4c STA &4c ; sprite_mask_address_high # Sprite mask data is at + &0fc6 ; calculate_total_bytes_in_sprite &1b67 a4 46 LDY &46 ; bytes_per_line_of_sprite # Calculate total number of bytes in sprite &1b69 a9 00 LDA #&00 ; sprite_lines_loop &1b6b 38 SEC &1b6c e5 0f SBC &0f ; lines_in_sprite &1b6e 88 DEY &1b6f d0 fa BNE &1b6b ; sprite_lines_loop &1b71 85 4d STA &4d ; minus_total_bytes_in_sprite &1b73 a5 48 LDA &48 ; bits_to_shift_sprite &1b75 d0 1b BNE &1b92 ; copy_shifted_sprite # Does the sprite need shifting bitwise? &1b77 a6 4d LDX &4d ; minus_total_bytes_in_sprite &1b79 a0 00 LDY #&00 ; copy_sprite_data_loop # If not, copy it and its mask to staging areas &1b7b b1 49 LDA (&49),Y ; sprite_address &1b7d 9d 00 04 STA &0400,X ; sprite_staging_area &1b80 b1 4b LDA (&4b),Y ; sprite_mask_address &1b82 9d 00 05 STA &0500,X ; sprite_mask_staging_area &1b85 c8 INY &1b86 e8 INX &1b87 d0 f2 BNE &1b7b ; shift_sprite &1b89 f0 64 BEQ &1bef ; after_shifting ; leave_with_negative_buffer_address_pull &1b8b 68 PLA ; leave_with_negative_buffer_address &1b8c a9 ff LDA #&ff &1b8e 9d 38 06 STA &0638,X ; objects_buffer_start_address_high &1b91 60 RTS ; shift_sprite # If the sprite needs shifting bitwise, &1b92 bd 78 03 LDA &0378,X ; objects_flipped &1b95 45 48 EOR &48 ; bits_to_shift_sprite &1b97 c5 48 CMP &48 ; bits_to_shift_sprite &1b99 f0 03 BEQ &1b9e ; no_extra_bit &1b9b 18 CLC &1b9c 69 01 ADC #&01 # Calculate bits to shift if flipped ; no_extra_bit &1b9e 85 50 STA &50 ; bits_to_shift_sprite_given_flipping &1ba0 a5 46 LDA &46 ; bytes_per_line_of_sprite &1ba2 85 4e STA &4e ; bytes_per_line_of_sprite_also &1ba4 85 4f STA &4f ; bytes_per_line_of_sprite_too &1ba6 a5 4d LDA &4d ; minus_total_bytes_in_sprite &1ba8 38 SEC &1ba9 e5 0f SBC &0f ; lines_in_sprite # Allow for an extra line's worth of bytes &1bab 85 4d STA &4d ; minus_total_bytes_to_shift &1bad aa TAX &1bae a0 00 LDY #&00 ; copy_sprite_data_for_shifting_loop # Copy sprite data and mask to staging areas &1bb0 b1 49 LDA (&49),Y ; sprite_address &1bb2 9d 00 04 STA &0400,X ; sprite_staging_area &1bb5 b1 4b LDA (&4b),Y ; sprite_mask_address &1bb7 9d 00 05 STA &0500,X ; sprite_mask_staging_area &1bba e8 INX &1bbb c8 INY &1bbc c4 4f CPY &4f ; bytes_per_line_of_sprite_too &1bbe d0 f0 BNE &1bb0 ; copy_sprite_data_for_shifting_loop &1bc0 a9 00 LDA #&00 &1bc2 9d 00 04 STA &0400,X ; sprite_staging_area # Adding a blank byte on the end of every line &1bc5 a9 ff LDA #&ff &1bc7 9d 00 05 STA &0500,X ; sprite_mask_staging_area &1bca e8 INX &1bcb a5 4f LDA &4f ; bytes_per_line_of_sprite_too &1bcd 18 CLC &1bce 65 4e ADC &4e ; bytes_per_line_of_sprite_also &1bd0 85 4f STA &4f ; total_bytes_per_line_of_sprite &1bd2 c6 1c DEC &1c ; lines_in_sprite &1bd4 d0 da BNE &1bb0 ; copy_sprite_data_for_shifting_loop &1bd6 a4 50 LDY &50 ; bits_to_shift_sprite_given_flipping ; shift_sprite_bit_loop &1bd8 a6 4d LDX &4d ; minus_total_bytes_to_shift &1bda 18 CLC ; shift_sprite_byte_loop &1bdb 7e 00 04 ROR &0400,X ; sprite_staging_area # Rotate the sprite data one bit at a time &1bde e8 INX &1bdf d0 fa BNE &1bdb ; shift_sprite_byte_loop &1be1 a6 4d LDX &4d ; minus_total_bytes_to_shift &1be3 38 SEC ; shift_sprite_mask_byte_loop &1be4 7e 00 05 ROR &0500,X ; sprite_mask_staging_area # Rotate the sprite mask one bit at a time &1be7 e8 INX &1be8 d0 fa BNE &1be4 ; shift_sprite_mask_byte_loop &1bea 88 DEY &1beb d0 eb BNE &1bd8 ; shift_sprite_bit_loop &1bed e6 46 INC &46 ; bytes_per_line_of_sprite ; after_shifting &1bef a6 47 LDX &47 ; object_number &1bf1 a0 08 LDY #&08 &1bf3 bd 78 03 LDA &0378,X ; objects_flipped &1bf6 f0 24 BEQ &1c1c ; not_flipped # Is the sprite flipped? &1bf8 a4 4d LDY &4d ; minus_total_bytes_in_sprite ; flip_bytes_loop &1bfa be 00 04 LDX &0400,Y ; sprite_staging_area # If so, flip all of the bytes bitwise &1bfd bd 00 53 LDA &5300,X ; bit_reversed_bytes # using the lookup table bit_reversed_bytes &1c00 99 00 04 STA &0400,Y ; sprite_staging_area &1c03 be 00 05 LDX &0500,Y ; sprite_mask_staging_area &1c06 bd 00 53 LDA &5300,X ; bit_reversed_bytes &1c09 99 00 05 STA &0500,Y ; sprite_mask_staging_area &1c0c c8 INY &1c0d d0 eb BNE &1bfa ; flip_bytes_loop &1c0f a6 46 LDX &46 ; bytes_per_line_of_sprite # If the sprite is flipped, it'll be plotted backwards &1c11 ca DEX &1c12 8a TXA &1c13 0a ASL A &1c14 0a ASL A &1c15 0a ASL A &1c16 65 13 ADC &13 ; slice_address &1c18 85 13 STA &13 ; slice_address # so note the last, not the first slice &1c1a a0 f8 LDY #&f8 # adv_value is -8 for flipped sprites, 0 otherwise ; not_flipped &1c1c 84 38 STY &38 ; adc_value # Self-modifying code &1c1e a5 13 LDA &13 ; slice_address &1c20 85 1c STA &1c ; sprite_write_address_low &1c22 a9 52 LDA #&52 # Use &52 - &56 to note whether slices need plotting &1c24 85 01 STA &01 ; sprite_slice_to_plot_zero_page_byte # Self-modifying code &1c26 a5 4d LDA &4d ; minus_total_bytes_in_sprite &1c28 85 05 STA &05 ; slice_number # Self-modifying code &1c2a 20 00 00 JSR &0000 ; push_sprite_to_screen_buffer # Push the sprite from staging areas to screen buffer &1c2d a6 47 LDX &47 ; object_number &1c2f e4 70 CPX &70 ; start_of_background_objects # Is this a background object? &1c31 b0 14 BCS &1c47 ; leave # If not, store its buffer addresses &1c33 a5 09 LDA &09 ; buffer_address_high &1c35 9d 38 06 STA &0638,X ; objects_buffer_start_address_high &1c38 a5 14 LDA &14 ; sprite_read_address_high &1c3a 9d 54 06 STA &0654,X ; objects_buffer_end_address_high &1c3d a5 5a LDA &5a ; first_slice_address &1c3f 9d 00 06 STA &0600,X ; objects_first_slice_address &1c42 a5 5b LDA &5b ; last_slice_address &1c44 9d 1c 06 STA &061c,X ; objects_last_slice_address ; leave &1c47 60 RTS ; set_door_object_data &1c48 9d 78 03 STA &0378,X ; objects_flipped &1c4b 9d 79 03 STA &0379,X ; objects_flipped + 1 &1c4e a9 07 LDA #&07 ; SPRITE_ARCH_LEFT # Create the door in two objects, X and X+1 &1c50 9d 00 05 STA &0500,X ; objects_type &1c53 a9 06 LDA #&06 ; SPRITE_ARCH_RIGHT &1c55 9d 01 05 STA &0501,X ; objects_type + 1 &1c58 a9 22 LDA #&22 &1c5a 9d 34 07 STA &0734,X ; objects_size_y &1c5d a9 30 LDA #&30 &1c5f 9d 35 07 STA &0735,X ; objects_size_y + 1 &1c62 a9 02 LDA #&02 &1c64 9d a0 03 STA &03a0,X ; objects_bytes_per_line_of_sprite &1c67 a9 03 LDA #&03 &1c69 9d a1 03 STA &03a1,X ; objects_bytes_per_line_of_sprite + 1 &1c6c 9d 70 06 STA &0670,X ; objects_frame &1c6f 9d 71 06 STA &0671,X ; objects_frame + 1 &1c72 a5 6f LDA &6f ; room_is_outside &1c74 f0 0f BEQ &1c85 # Is this an outside room? &1c76 a9 08 LDA #&08 ; SPRITE_TREE_ARCH_LEFT # If so, use different sprites for the doors &1c78 9d 00 05 STA &0500,X ; objects_type &1c7b a9 09 LDA #&09 ; SPRITE_TREE_ARCH_RIGHT &1c7d 9d 01 05 STA &0501,X ; objects_type + 1 &1c80 a9 02 LDA #&02 &1c82 9d a1 03 STA &03a1,X ; objects_bytes_per_line_of_sprite + 1 &1c85 60 RTS ; set_size_of_x_doors &1c86 a9 07 LDA #&07 &1c88 9d 18 07 STA &0718,X ; objects_size_x &1c8b 9d 19 07 STA &0719,X ; objects_size_x + 1 &1c8e a9 05 LDA #&05 &1c90 9d fc 06 STA &06fc,X ; objects_size_z &1c93 a9 0f LDA #&0f &1c95 9d fd 06 STA &06fd,X ; objects_size_z + 1 &1c98 a5 6f LDA &6f ; room_is_outside &1c9a f0 e9 BEQ &1c85 &1c9c bd 29 03 LDA &0329,X ; objects_position_y + 1 &1c9f 18 CLC &1ca0 69 04 ADC #&04 &1ca2 9d 29 03 STA &0329,X ; objects_position_y + 1 &1ca5 60 RTS ; set_size_of_z_doors &1ca6 a9 07 LDA #&07 &1ca8 9d fc 06 STA &06fc,X ; objects_size_z &1cab 9d fd 06 STA &06fd,X ; objects_size_z + 1 &1cae a9 03 LDA #&03 &1cb0 9d 18 07 STA &0718,X ; objects_size_x &1cb3 9d 19 07 STA &0719,X ; objects_size_x + 1 &1cb6 a5 6f LDA &6f ; room_is_outside &1cb8 f0 cb BEQ &1c85 &1cba a9 48 LDA #&48 &1cbc 9d 01 03 STA &0301,X ; objects_position_x + 1 &1cbf 60 RTS ; create_block_under_high_door &1cc0 9d 50 03 STA &0350,X ; objects_position_z &1cc3 a9 24 LDA #&24 &1cc5 9d 28 03 STA &0328,X ; objects_position_y &1cc8 a9 04 LDA #&04 &1cca 9d a0 03 STA &03a0,X ; objects_bytes_per_line_of_sprite &1ccd a9 0b LDA #&0b ; SPRITE_BLOCK &1ccf 9d 00 05 STA &0500,X ; objects_type &1cd2 a9 0b LDA #&0b &1cd4 9d 34 07 STA &0734,X ; objects_size_y &1cd7 a9 0f LDA #&0f &1cd9 9d fc 06 STA &06fc,X ; objects_size_z &1cdc 9d 18 07 STA &0718,X ; objects_size_x &1cdf a9 00 LDA #&00 &1ce1 9d 78 03 STA &0378,X ; objects_flipped &1ce4 9d 70 06 STA &0670,X ; objects_frame &1ce7 e8 INX &1ce8 60 RTS ; initialise_room &1ce9 20 e8 20 JSR &20e8 ; mark_room_as_needing_to_be_redrawn &1cec a9 00 LDA #&00 &1cee 85 49 STA &49 ; room_data_pointer_low &1cf0 a9 09 LDA #&09 # Room data starts at &0900 &1cf2 85 4a STA &4a ; room_data_pointer_high ; count_existing_rooms # but not all of the rooms have data &1cf4 a9 80 LDA #&80 &1cf6 85 4b STA &4b ; bit_to_consider &1cf8 a0 00 LDY #&00 &1cfa 84 45 STY &45 ; number_in_list_of_existing_rooms &1cfc a6 61 LDX &61 ; room_number &1cfe f0 2c BEQ &1d2c ; calculated_room_data_pointer # If this is room &00, no calculation is needed ; count_existing_rooms_loop &1d00 b9 a1 30 LDA &30a1,Y ; room_map # Otherwise, consult room_map &1d03 25 4b AND &4b ; bit_to_consider # which has one bit per room, set if it has data &1d05 f0 02 BEQ &1d09 ; not_a_room &1d07 e6 45 INC &45 ; number_in_list_of_existing_rooms ; not_a_room &1d09 46 4b LSR &4b ; bit_to_consider &1d0b d0 03 BNE &1d10 &1d0d 66 4b ROR &4b ; bit_to_consider &1d0f c8 INY &1d10 ca DEX &1d11 d0 ed BNE &1d00 count_existing_rooms_loop ; calculate_room_data_pointer # &45 is the number of rooms with data prior to this one &1d13 a0 01 LDY #&01 ; calculate_room_data_pointer_loop # room_data_pointer starts at &900 &1d15 b1 49 LDA (&49),Y ; room_data_pointer # Consider b = ?(room_data_pointer + 1) &1d17 29 1f AND #&1f &1d19 18 CLC &1d1a 69 01 ADC #&01 &1d1c 0a ASL A # The next room occupies ((b & &1f) + 1) * 2 bytes &1d1d 18 CLC &1d1e 65 49 ADC &49 ; room_data_pointer_low &1d20 85 49 STA &49 ; room_data_pointer_low &1d22 a5 4a LDA &4a ; room_data_pointer_high &1d24 69 00 ADC #&00 &1d26 85 4a STA &4a ; room_data_pointer_high &1d28 c6 45 DEC &45 ; number_in_list_of_existing_rooms &1d2a d0 e9 BNE &1d15 ; calculate_room_data_pointer_loop # Skip rooms until this one is found ; calculated_room_data_pointer &1d2c a0 01 LDY #&01 &1d2e b1 49 LDA (&49),Y ; room_data_pointer &1d30 85 4c STA &4c ; room_data_byte_two # room_data_byte_two = ?(room_data_pointer + 1) &1d32 88 DEY &1d33 b1 49 LDA (&49),Y ; room_data_pointer &1d35 85 4b STA &4b ; room_data_byte_one # room_data_byte_one = ?(room_data_pointer) &1d37 29 03 AND #&03 # (room_data_byte_one & &03) defines room colour &1d39 aa TAX &1d3a bc b9 07 LDY &07b9,X ; colour_schemes # looked up in the colour scheme table &1d3d 84 57 STY &57 ; room_colour_scheme &1d3f a5 4b LDA &4b ; room_data_byte_one &1d41 29 10 AND #&10 # (room_data_byte_one & &10) set if room is outside &1d43 85 6f STA &6f ; room_is_outside &1d45 a5 4b LDA &4b ; room_data_byte_one &1d47 29 0c AND #&0c # (room_data_byte_one & &0c) defines room_layout &1d49 aa TAX &1d4a 85 7d STA &7d ; room_layout &1d4c 48 PHA ; copy_room_sizes &1d4d a0 03 LDY #&03 ; copy_room_sizes_loop &1d4f bd 90 08 LDA &0890,X ; room_size_table # room_layout in turn defines the size of the room &1d52 99 6a 00 STA &006a,Y ; room_sizes &1d55 e8 INX &1d56 88 DEY &1d57 10 f6 BPL &1d4f ; copy_room_sizes_loop ; background &1d59 68 PLA ; room_layout &1d5a c9 04 CMP #&04 ; north_south_room &1d5c f0 05 BEQ &1d63 # Y = &18 for north_south_room &1d5e a6 6f LDX &6f ; room_is_outside &1d60 d0 04 BNE &1d66 # Y = &24 for outside rooms &1d62 2c a9 18 BIT &18a9 #1d63 LDA #&18 &1d65 2c a9 24 BIT &24a9 # Otherwise Y = room_layout, i.e. &00 for square_room #1d66 LDA #&24 &1d68 a8 TAY # and &0c for east_west_room (&08 is unused) &1d69 a2 27 LDX #&27 &1d6b 20 93 1d JSR &1d93 ; copy_background_objects # Use Y to copy the right set of background objects &1d6e a5 4b LDA &4b ; room_data_byte_one &1d70 a4 6f LDY &6f ; room_is_outside &1d72 f0 1a BEQ &1d8e ; inside_room &1d74 29 80 AND #&80 &1d76 d0 08 BNE &1d80 ; has_west_door &1d78 a0 30 LDY #&30 # An outside room without a west door has extra objects &1d7a 20 93 1d JSR &1d93 ; copy_background_objects &1d7d 20 93 1d JSR &1d93 ; copy_background_objects ; has_west_door &1d80 a5 4c LDA &4c ; room_data_byte_two &1d82 29 80 AND #&80 &1d84 d0 08 BNE &1d8e ; has_north_door &1d86 a0 32 LDY #&32 # An outside room without a north door has extra objects &1d88 20 93 1d JSR &1d93 ; copy_background_objects &1d8b 20 93 1d JSR &1d93 ; copy_background_objects ; has_north_door ; inside_room &1d8e 86 70 STX &70 ; start_of_background_objects &1d90 4c c6 1d JMP &1dc6 ; create_doors ; copy_background_objects &1d93 b9 96 2d LDA &2d96,Y ; background_objects_position_x &1d96 9d 00 03 STA &0300,X ; objects_position_x &1d99 b9 ca 2d LDA &2dca,Y ; background_objects_position_y &1d9c 9d 28 03 STA &0328,X ; objects_position_y &1d9f b9 fe 2d LDA &2dfe,Y ; background_objects_position_z &1da2 9d 50 03 STA &0350,X ; objects_position_z &1da5 b9 32 2e LDA &2e32,Y ; background_objects_position_data &1da8 48 PHA &1da9 29 07 AND #&07 # (position_data & &07) defines background object type &1dab 9d 00 05 STA &0500,X ; objects_type &1dae 68 PLA &1daf 48 PHA &1db0 29 08 AND #&08 # (position_data & &08) set if background object flipped &1db2 9d 78 03 STA &0378,X ; objects_flipped &1db5 68 PLA ; position_data &1db6 29 70 AND #&70 # (position_data & &70) / 8 defines bytes per line &1db8 4a LSR A &1db9 4a LSR A &1dba 4a LSR A &1dbb 4a LSR A &1dbc 9d a0 03 STA &03a0,X ; objects_bytes_per_line_of_sprite &1dbf c8 INY &1dc0 ca DEX &1dc1 e0 1c CPX #&1c &1dc3 b0 ce BCS &1d93 ; copy_background_objects &1dc5 60 RTS ; create_doors &1dc6 a9 ff LDA #&ff &1dc8 85 a6 STA &a6 ; maximum_height_of_balls_in_room &1dca 85 66 STA &66 ; door_height_north &1dcc 85 67 STA &67 ; door_height_east &1dce 85 68 STA &68 ; door_height_south &1dd0 85 69 STA &69 ; door_height_west &1dd2 a5 4b LDA &4b ; room_data_byte_one &1dd4 a2 04 LDX #&04 ; object slot &1dd6 29 80 AND #&80 # (room_data_byte_one &80) is set if a west door exists &1dd8 f0 22 BEQ &1dfc ; no_door_at_west &1dda a9 08 LDA #&08 &1ddc 9d 50 03 STA &0350,X ; objects_position_z &1ddf 9d 51 03 STA &0351,X ; objects_position_z + 1 &1de2 9d 28 03 STA &0328,X ; objects_position_y &1de5 9d 29 03 STA &0329,X ; objects_position_y + 1 &1de8 a9 58 LDA #&58 &1dea 9d 00 03 STA &0300,X ; objects_position_x &1ded a9 40 LDA #&40 &1def 9d 01 03 STA &0301,X ; objects_position_x + 1 &1df2 20 48 1c JSR &1c48 ; set_door_object_data # West door is flipped &1df5 20 a6 1c JSR &1ca6 ; set_size_of_z_doors &1df8 e8 INX &1df9 e8 INX &1dfa e6 69 INC &69 ; door_height_west # West door height is always &00 ; no_door_at_west &1dfc a5 4c LDA &4c ; room_data_byte_two &1dfe 29 80 AND #&80 # (room_data_byte_two &80) is set if a north door exists &1e00 f0 28 BEQ &1e2a ; no_door_at_north &1e02 a9 90 LDA #&90 &1e04 9d 00 03 STA &0300,X ; objects_position_x &1e07 9d 01 03 STA &0301,X ; objects_position_x + 1 &1e0a a9 40 LDA #&40 &1e0c 9d 50 03 STA &0350,X ; objects_position_z &1e0f a9 50 LDA #&50 &1e11 9d 51 03 STA &0351,X ; objects_position_z + 1 &1e14 a9 08 LDA #&08 &1e16 9d 28 03 STA &0328,X ; objects_position_y &1e19 a9 04 LDA #&04 &1e1b 9d 29 03 STA &0329,X ; objects_position_y + 1 &1e1e a9 00 LDA #&00 &1e20 20 48 1c JSR &1c48 ; set_door_object_data # North door isn't flipped &1e23 20 86 1c JSR &1c86 ; set_size_of_x_doors &1e26 e8 INX &1e27 e8 INX &1e28 e6 66 INC &66 ; door_height_north # North door height is always &00 ; no_door_at_north &1e2a a5 4b LDA &4b ; room_data_byte_one &1e2c 29 60 AND #&60 # (room_data_byte_one &60) is set if a south door exists &1e2e f0 4e BEQ &1e7e ; no_door_at_south &1e30 29 40 AND #&40 # (room_data_byte_one &40) is set if this door is high &1e32 0a ASL A &1e33 0a ASL A &1e34 2a ROL A &1e35 a8 TAY &1e36 a9 08 LDA #&08 &1e38 9d 00 03 STA &0300,X ; objects_position_x &1e3b 9d 01 03 STA &0301,X ; objects_position_x + 1 &1e3e a9 40 LDA #&40 &1e40 9d 50 03 STA &0350,X ; objects_position_z &1e43 a9 50 LDA #&50 &1e45 9d 51 03 STA &0351,X ; objects_position_z + 1 &1e48 a9 50 LDA #&50 &1e4a 9d 51 03 STA &0351,X ; objects_position_z + 1 &1e4d b9 a8 07 LDA &07a8,Y ; door_height_table # South door height is &00 if low &1e50 85 68 STA &68 ; door_height_south # &30 if high &1e52 18 CLC &1e53 69 02 ADC #&02 &1e55 9d 29 03 STA &0329,X ; objects_position_y + 1 &1e58 18 CLC &1e59 69 04 ADC #&04 &1e5b 9d 28 03 STA &0328,X ; objects_position_y &1e5e a9 00 LDA #&00 &1e60 20 48 1c JSR &1c48 ; set_door_object_data # South door isn't flipped &1e63 20 86 1c JSR &1c86 ; set_size_of_x_doors &1e66 e8 INX &1e67 e8 INX &1e68 c0 00 CPY #&00 &1e6a f0 12 BEQ &1e7e ; no_door_at_south # Is the south door high? &1e6c a9 00 LDA #&00 # If so, create two blocks under it &1e6e 9d 00 03 STA &0300,X ; objects_position_x &1e71 9d 01 03 STA &0301,X ; objects_position_x + 1 &1e74 a9 40 LDA #&40 &1e76 20 c0 1c JSR &1cc0 ; create_block_under_high_door &1e79 a9 50 LDA #&50 &1e7b 20 c0 1c JSR &1cc0 ; create_block_under_high_door ; no_door_at_south &1e7e a5 4c LDA &4c ; room_data_byte_two &1e80 29 60 AND #&60 # (room_data_byte_two &60) is set if an east door exists &1e82 f0 46 BEQ &1eca ; no_door_at_east &1e84 29 40 AND #&40 # (room_data_byte_two &40) is set if this door is high &1e86 0a ASL A &1e87 0a ASL A &1e88 2a ROL A &1e89 a8 TAY &1e8a a9 58 LDA #&58 &1e8c 9d 00 03 STA &0300,X ; objects_position_x &1e8f a9 40 LDA #&40 &1e91 9d 01 03 STA &0301,X ; objects_position_x + 1 &1e94 a9 90 LDA #&90 &1e96 9d 50 03 STA &0350,X ; objects_position_z &1e99 9d 51 03 STA &0351,X ; objects_position_z + 1 &1e9c b9 a8 07 LDA &07a8,Y ; door_height_table # East door height is &00 if low &1e9f 85 67 STA &67 ; door_height_east # &30 if high &1ea1 18 CLC &1ea2 69 06 ADC #&06 &1ea4 9d 28 03 STA &0328,X ; objects_position_y &1ea7 9d 29 03 STA &0329,X ; objects_position_y + 1 &1eaa 20 48 1c JSR &1c48 ; set_door_object_data # East door is flipped &1ead 20 a6 1c JSR &1ca6 ; set_size_of_z_doors &1eb0 e8 INX &1eb1 e8 INX &1eb2 c0 00 CPY #&00 &1eb4 f0 14 BEQ &1eca ; no_door_at_east # Is the east door high? &1eb6 a9 50 LDA #&50 # If so, create two blocks under it &1eb8 9d 00 03 STA &0300,X ; objects_position_x &1ebb a9 40 LDA #&40 &1ebd 9d 01 03 STA &0301,X ; objects_position_x + 1 &1ec0 a9 90 LDA #&90 &1ec2 20 c0 1c JSR &1cc0 ; create_block_under_high_door &1ec5 a9 90 LDA #&90 &1ec7 20 c0 1c JSR &1cc0 ; create_block_under_high_door ; no_door_at_east &1eca ca DEX &1ecb a0 01 LDY #&01 &1ecd a5 4c LDA &4c ; room_data_byte_two &1ecf 29 1f AND #&1f # (room_data_byte_two & &1f) &1ed1 85 45 STA &45 ; number_of_objects # is the number of extra objects in the room &1ed3 d0 03 BNE &1ed8 ; room_has_objects # Are there any? &1ed5 4c 67 20 JMP &2067 ; finished_populating_objects ; room_has_objects ; populate_objects_loop &1ed8 e8 INX &1ed9 c8 INY &1eda b1 49 LDA (&49),Y ; room_data_pointer # object_byte_one is the next byte of room data &1edc 48 PHA &1edd 29 f0 AND #&f0 # (object_byte_one & &f0) / 2 + &10 &1edf 4a LSR A &1ee0 18 CLC &1ee1 69 10 ADC #&10 &1ee3 9d 50 03 STA &0350,X ; objects_position_z # is the object's z position &1ee6 68 PLA &1ee7 29 0f AND #&0f # (object_byte_one & &0f) * 8 + &10 &1ee9 0a ASL A &1eea 0a ASL A &1eeb 0a ASL A &1eec 18 CLC &1eed 69 10 ADC #&10 &1eef 9d 00 03 STA &0300,X ; objects_position_x # is the object's x position &1ef2 c8 INY &1ef3 84 21 STY &21 ; room_data_offset &1ef5 b1 49 LDA (&49),Y ; room_data_pointer # object_byte_two is the next byte of room data &1ef7 48 PHA &1ef8 29 07 AND #&07 # (object_byte_two & &07) * &0c &1efa a8 TAY &1efb b9 84 08 LDA &0884,Y ; y_positions_table # (actually calculated from a lookup table) &1efe 9d 28 03 STA &0328,X ; objects_position_y # is the object's y position &1f01 a9 00 LDA #&00 &1f03 9d 70 06 STA &0670,X ; objects_frame &1f06 9d 78 03 STA &0378,X ; objects_flipped &1f09 68 PLA ; object_byte_two &1f0a 4a LSR A &1f0b 4a LSR A &1f0c 4a LSR A &1f0d 18 CLC &1f0e 69 0a ADC #&0a # (object_byte_two & &f8) / 8 + &0a &1f10 48 PHA &1f11 a8 TAY # is the object type &1f12 c0 13 CPY #&13 ; OBJECT_BALL &1f14 d0 18 BNE &1f2e ; not_ball # Is this a BALL? &1f16 a9 ff LDA #&ff &1f18 9d c8 6b STA &6bc8,X ; objects_movement_y # If so, set falling &1f1b bd 28 03 LDA &0328,X ; objects_position_y &1f1e 18 CLC &1f1f 69 30 ADC #&30 &1f21 c5 a6 CMP &a6 ; maximum_height_of_balls_in_room &1f23 b0 04 BCS &1f29 ; too_high &1f25 85 a6 STA &a6 ; maximum_height_of_balls_in_room # And consider its height as a maximum &1f27 d0 02 BNE &1f2b ; not_too_high ; too_high &1f29 a5 a6 LDA &a6 ; maximum_height_of_balls_in_room ; not_too_high &1f2b 9d e4 6b STA &6be4,X ; objects_maximum_position # for it and any further balls in the room ; not_ball &1f2e b9 de 2f LDA &2fde,Y ; object_type_size_y - 11 # For all objects, set their sizes from tables &1f31 9d 34 07 STA &0734,X ; objects_size_y &1f34 b9 fc 2f LDA &2ffc,Y ; object_type_size_x - 11 &1f37 9d 18 07 STA &0718,X ; objects_size_x &1f3a b9 1a 30 LDA &301a,Y ; object_type_size_z - 11 &1f3d 9d fc 06 STA &06fc,X ; objects_size_z &1f40 b9 38 30 LDA &3038,Y ; object_type_support - 11 &1f43 9d 1c 6c STA &6c1c,X ; objects_support &1f46 c0 22 CPY #&22 ; OBJECT_FEET &1f48 f0 19 BEQ &1f63 ; is_feet &1f4a c0 1f CPY #&1f &1f4c b0 43 BCS &1f91 ; is_block_or_portcullis # If this is a FIRE, &1f4e c0 1d CPY #&1d &1f50 90 0d BCC &1f5f ; not_fire &1f52 a5 7d LDA &7d ; room_layout &1f54 c9 04 CMP #&04 ; north_south_room, east &1f56 f0 02 BEQ &1f5a ; not_north_south_room # move east by default &1f58 a9 02 LDA #&02 ; north # but north in north_south_room ; not_north_south_room &1f5a 9d 00 6b STA &6b00,X ; objects_movement_xz &1f5d d0 21 BNE &1f80 ; set_object_horizontal_speed_to_three # with speed 3 ; not_fire &1f5f c0 19 CPY #&19 ; OBJECT_GUARD_HEAD &1f61 90 17 BCC &1f7a ; not_head ; is_feet # If this is FEET, GUARD_HEAD or WIZARD_HEAD, &1f63 a9 02 LDA #&02 &1f65 20 bc 20 JSR &20bc ; add_to_object_position_x &1f68 a9 01 LDA #&01 ; west # move west by default &1f6a 9d 00 6b STA &6b00,X ; objects_movement_xz &1f6d 9d 70 06 STA &0670,X ; objects_frame &1f70 a9 02 LDA #&02 # with speed 2 &1f72 d0 0e BNE &1f82 ; set_object_horizontal_speed ; is_magic &1f74 68 PLA ; object_type # Add (0, 0, 4) to position of MAGIC &1f75 a9 53 LDA #&53 ; SPRITE_HOMING_MAGIC # OBJECT_MAGIC becomes SPRITE_HOMING_MAGIC &1f77 48 PHA &1f78 d0 3b BNE &1fb5 ; add_two_to_z ; not_head &1f7a a9 04 LDA #&04 &1f7c c0 15 CPY #&15 ; OBJECT_GHOST &1f7e b0 02 BCS &1f82 # GHOSTs move with speed 3 ; set_object_horizontal_speed_to_three &1f80 a9 03 LDA #&03 ; set_object_horizontal_speed &1f82 9d 1c 6b STA &6b1c,X ; objects_horizontal_speed &1f85 c0 1d CPY #&1d ; OBJECT_FIRE &1f87 f0 46 BEQ &1fcf ; is_fire &1f89 c0 0e CPY #&0e ; OBJECT_TABLE &1f8b f0 3b BEQ &1fc8 ; is_table &1f8d c0 0f CPY #&0f ; OBJECT_CHEST &1f8f f0 2b BEQ &1fbc ; is_chest ; is_block_or_portcullis &1f91 c0 22 CPY #&22 ; OBJECT_FEET &1f93 f0 43 BEQ &1fd8 ; is_feet_two &1f95 c0 26 CPY #&26 ; OBJECT_MOVING_BLOCK_X &1f97 f0 44 BEQ &1fdd ; is_moving_block_x &1f99 c0 27 CPY #&27 ; OBJECT_MOVING_BLOCK_Z &1f9b f0 51 BEQ &1fee ; is_moving_block_z &1f9d b0 6d BCS &200c ; is_carried_block &1f9f c0 23 CPY #&23 ; OBJECT_MAGIC &1fa1 f0 d1 BEQ &1f74 ; is_magic &1fa3 b0 68 BCS &200d ; is_descending_block &1fa5 c0 21 CPY #&21 ; OBJECT_PORTCULLIS_X_2 &1fa7 f0 6b BEQ &2014 ; is_portcullis_x_2 &1fa9 c0 20 CPY #&20 ; OBJECT_PORTCULLIS_Z_2 &1fab f0 7f BEQ &202c ; is_portcullis_z_2 &1fad c0 1f CPY #&1f ; OBJECT_PORTCULLIS_Z &1faf f0 77 BEQ &2028 ; is_portcullis_z &1fb1 c0 11 CPY #&11 ; OBJECT_GARGOYLE &1fb3 d0 11 BNE &1fc6 ; isn't_gargoyle ; add_two_to_z &1fb5 a9 02 LDA #&02 # Add (0, 0, 4) to position of GARGOYLE &1fb7 20 c4 20 JSR &20c4 ; add_to_object_position_z &1fba d0 05 BNE &1fc1 ; is_chest &1fbc a9 0e LDA #&0e # Add (2, 0, 14) to position of CHEST &1fbe 20 c4 20 JSR &20c4 ; add_to_object_position_z &1fc1 a9 02 LDA #&02 ; add_to_x &1fc3 20 bc 20 JSR &20bc ; add_to_object_position_x ; isn't_gargoyle &1fc6 d0 77 BNE &203f ; done_with_object_alterations ; is_table &1fc8 a9 fc LDA #&fc # Add (-4, 0, 4) to position of TABLE &1fca 20 bc 20 JSR &20bc ; add_to_object_position_x &1fcd d0 e6 BNE &1fb5 ; is_fire &1fcf a9 04 LDA #&04 # Add (0, 0, 8) to position of FIRE &1fd1 20 c4 20 JSR &20c4 ; add_to_object_position_z &1fd4 a9 04 LDA #&04 &1fd6 d0 eb BNE &1fc3 ; add_to_x ; is_feet_two &1fd8 68 PLA ; object_type &1fd9 a9 4d LDA #&4d ; SPRITE_GUARD_FEET_BACK # OBJECT_FEET becomes SPRITE_GUARD_FEET_BACK &1fdb d0 61 BNE &203e ; push_new_object_typ ; is_moving_block_x &1fdd a9 08 LDA #&08 ; south # MOVING_BLOCK_X moves south by default &1fdf 48 PHA &1fe0 bd 00 03 LDA &0300,X ; objects_position_x &1fe3 48 PHA &1fe4 18 CLC &1fe5 69 08 ADC #&08 &1fe7 29 f0 AND #&f0 # Increase and align position &1fe9 9d 00 03 STA &0300,X ; objects_position_x &1fec d0 0f BNE &1ffd ; set_position_and_movement ; is_moving_block_z &1fee a9 01 LDA #&01 ; west # MOVING_BLOCK_Z moves west by default &1ff0 48 PHA &1ff1 bd 50 03 LDA &0350,X ; objects_position_z &1ff4 48 PHA &1ff5 18 CLC &1ff6 69 08 ADC #&08 &1ff8 29 f0 AND #&f0 # Increase and align position &1ffa 9d 50 03 STA &0350,X ; objects_position_z ; set_position_and_movement &1ffd 68 PLA ; position &1ffe 29 f0 AND #&f0 &2000 9d e4 6b STA &6be4,X ; objects_maximum_position &2003 68 PLA ; movement &2004 9d 00 6b STA &6b00,X ; objects_movement_xz &2007 a9 01 LDA #&01 # MOVING_BLOCKs move with speed 1 &2009 9d 1c 6b STA &6b1c,X ; objects_horizontal_speed ; is_carried_block &200c c8 INY ; is_descending_block &200d 68 PLA &200e 98 TYA &200f 18 CLC &2010 69 30 ADC #&30 # Convert OBJECT types to SPRITE types for blocks &2012 d0 2a BNE &203e ; push_new_object_type ; is_portcullis_x_2 &2014 a9 06 LDA #&06 &2016 20 c4 20 JSR &20c4 ; add_to_object_position_z # Add (0, 0, 6) to position of PORTCULLIS_X_2 &2019 20 cc 20 JSR &20cc ; check_if_room_has_shifted_portcullises # Add (6, 0, 0) if room has shifted portcullises &201c d0 02 BNE &2020 ; not_shifted_portcullis_room &201e a9 0e LDA #&0e # (14, 0, 0) if not ; not_shifted_portcullis_room &2020 20 bc 20 JSR &20bc ; add_to_object_position_x &2023 68 PLA ; object_type &2024 a9 12 LDA #&12 ; SPRITE_PORTCULLIS_X # OBJECT_PORTCULLIS_X_2 becomes SPRITE_PORTCULLIS_X &2026 d0 16 BNE &203e ; push_new_object_type ; is_portcullis_z &2028 20 cc 20 JSR &20cc ; check_if_room_has_shifted_portcullises # If this is a PORTCULLIS_Z, &202b 2c a9 0e BIT &0ea9 # Add (0, 0, 6) if room has shifted portcullises ; is_portcullis_z_2 #202c LDA #&0e # Add (0, 0, 14) to position of PORTCULLIS_Z_2 &202e 20 c4 20 JSR &20c4 ; add_to_object_position_z &2031 a9 06 LDA #&06 &2033 20 bc 20 JSR &20bc ; add_to_object_position_x &2036 a9 07 LDA #&07 &2038 9d 78 03 STA &0378,X ; objects_flipped # z portcullises are flipped &203b 68 PLA ; object_type &203c a9 41 LDA #&41 ; SPRITE_PORTCULLIS_Z # OBJECT_PORTCULLIS_Z_2 becomes SPRITE_PORTCULLIS_Z ; push_new_object_type &203e 48 PHA ; done_with_object_alterations &203f a4 21 LDY &21 ; room_data_offset &2041 68 PLA ; object_type &2042 9d 00 05 STA &0500,X ; objects_type # Set object type &2045 c9 11 CMP #&11 &2047 90 0f BCC &2058 ; four_bytes_per_line &2049 c9 54 CMP #&54 &204b b0 0b BCS &2058 ; four_bytes_per_line &204d c9 1d CMP #&1d &204f 90 0a BCC &205b ; three_bytes_per_line &2051 c9 41 CMP #&41 &2053 b0 06 BCS &205b ; three_bytes_per_line &2055 a9 02 LDA #&02 &2057 2c a9 04 BIT &04a9 ; four_bytes_per_line #2058 LDA #&04 &205a 2c a9 03 BIT &03a9 ; three_bytes_per_line #205b LDA #&03 &205d 9d a0 03 STA &03a0,X ; objects_bytes_per_line_of_sprite # Set bytes per sprite depending on sprite &2060 c6 45 DEC &45 ; number_of_objects &2062 f0 03 BEQ &2067 ; finished_populating_objects &2064 4c d8 1e JMP &1ed8 ; populate_objects_loop ; finished_populating_objects &2067 86 44 STX &44 ; number_of_objects # Note the total number of objects ; add_charms &2069 a0 1f LDY #&1f &206b a2 02 LDX #&02 &206d a9 ff LDA #&ff &206f 85 82 STA &82 ; charm_room_slot_one &2071 85 83 STA &83 ; charm_room_slot_two # No charms in room by default &2073 8d 72 06 STA &0672 ; objects_frame + 2 &2076 8d 73 06 STA &0673 ; objects_frame + 3 &2079 a9 01 LDA #&01 # Mark charms as capable of being pushed and stood on &207b 8d 1e 6c STA &6c1e ; objects_support + 2 &207e 8d 1f 6c STA &6c1f ; objects_support + 3 ; consider_charms_loop # For each of the charms in the game, &2081 b9 80 01 LDA &0180,Y ; charms_position_room &2084 c5 61 CMP &61 ; room_number &2086 d0 30 BNE &20b8 ; skip_to_next_charm # Is it in this room? &2088 c4 84 CPY &84 ; charm_pocket_slot_one &208a f0 2c BEQ &20b8 ; skip_to_next_charm # not in the player's pockets? &208c c4 85 CPY &85 ; charm_pocket_slot_two &208e f0 28 BEQ &20b8 ; skip_to_next_charm &2090 c4 86 CPY &86 ; charm_pocket_slot_three &2092 f0 24 BEQ &20b8 ; skip_to_next_charm &2094 b9 60 01 LDA &0160,Y ; charms_type &2097 c9 56 CMP #&56 ; SPRITE_DISAPPEARED # and hasn't already been put in the cauldron? &2099 b0 1d BCS &20b8 ; skip_to_next_charm &209b 9d 00 05 STA &0500,X ; objects_type # If so, put its type and position in an object &209e b9 00 01 LDA &0100,Y ; charms_position_x &20a1 9d 00 03 STA &0300,X ; objects_position_x &20a4 b9 20 01 LDA &0120,Y ; charms_position_y &20a7 9d 28 03 STA &0328,X ; objects_position_y &20aa b9 40 01 LDA &0140,Y ; charms_position_z &20ad 9d 50 03 STA &0350,X ; objects_position_z &20b0 a9 00 LDA #&00 &20b2 9d 70 06 STA &0670,X ; objects_frame &20b5 94 80 STY &80,X ; charm_room_slots &20b7 e8 INX ; skip_to_next_charm &20b8 88 DEY &20b9 10 c6 BPL &2081 ; consider_charms_loop &20bb 60 RTS ; add_to_object_position_x &20bc 18 CLC &20bd 7d 00 03 ADC &0300,X ; objects_position_x &20c0 9d 00 03 STA &0300,X ; objects_position_x &20c3 60 RTS ; add_to_object_position_z &20c4 18 CLC &20c5 7d 50 03 ADC &0350,X ; objects_position_z &20c8 9d 50 03 STA &0350,X ; objects_position_z &20cb 60 RTS ; check_if_room_has_shifted_portcullises &20cc a5 61 LDA &61 ; room_number &20ce c9 77 CMP #&77 &20d0 f0 10 BEQ &20e2 ; leave_with_six &20d2 c9 7c CMP #&7c &20d4 f0 0c BEQ &20e2 ; leave_with_six &20d6 c9 97 CMP #&97 &20d8 f0 08 BEQ &20e2 ; leave_with_six &20da c9 cf CMP #&cf &20dc f0 04 BEQ &20e2 ; leave_with_six &20de c9 23 CMP #&23 &20e0 d0 03 BNE &20e5 ; leave_with_zero ; leave_with_six &20e2 a9 06 LDA #&06 &20e4 60 RTS ; leave_with_zero &20e5 a9 00 LDA #&00 &20e7 60 RTS ; mark_room_as_needing_to_be_redrawn &20e8 a9 b3 LDA #&b3 &20ea 8d 5d 03 STA &035d ; vdu_vector_low # Set OS general VDU vector to &ccb3 &20ed a9 cc LDA #&cc &20ef 8d 5e 03 STA &035e ; vdu_vector_high # (two bytes used by objects_position_z) &20f2 a9 00 LDA #&00 &20f4 aa TAX &20f5 85 65 STA &65 ; completely_redraw_room_if_zero &20f7 4c b3 cc JMP &ccb3 ; clear_screen_buffer # OS routine that zeros &6b00 - &7fff, using vector ; reset_player_data &20fa a2 ff LDX #&ff &20fc 86 71 STX &71 ; facing_on_entering_room &20fe 86 84 STX &84 ; charm_pocket_slot_one # Player starts with empty pockets &2100 86 85 STX &85 ; charm_pocket_slot_two &2102 a2 00 LDX #&00 &2104 8e 28 03 STX &0328 ; player_feet_object_position_y &2107 86 62 STX &62 ; player_is_jumping &2109 86 5d STX &5d ; man_or_wolf &210b 86 79 STX &79 ; steps_to_take_into_room &210d 86 8b STX &8b ; day_counter_low &210f 86 8c STX &8c ; day_counter_high &2111 e8 INX &2112 86 5c STX &5c ; player_facing # Player starts facing west &2114 86 75 STX &75 ; spasm_countdown_high &2116 a9 05 LDA #&05 # Player starts with 5 lives &2118 85 8a STA &8a ; life_counter &211a a9 4c LDA #&4c # Player starts at (&4c, 0, &4c) &211c 8d 50 03 STA &0350 ; player_feet_object_position_z &211f 8d 00 03 STA &0300 ; player_feet_object_position_x &2122 85 60 STA &60 ; spasm_countdown_low # Initial spasm countdown is &04c ; pick_starting_room_less_than_five_loop &2124 20 c7 07 JSR &07c7 ; random_number &2127 29 07 AND #&07 &2129 c9 05 CMP #&05 &212b b0 f7 BCS &2124 ; pick_starting_room_less_than_five_loop &212d a8 TAY &212e b9 b4 07 LDA &07b4,Y ; starting_rooms # Pick an initial starting room at random &2131 85 61 STA &61 ; room_number ; update_player_sprite_details &2133 a5 5c LDA &5c ; player_facing &2135 29 03 AND #&03 &2137 85 5c STA &5c ; player_facing &2139 aa TAX &213a bd 80 08 LDA &0880,X ; player_type_by_facing &213d 18 CLC &213e 65 5d ADC &5d ; man_or_wolf &2140 8d 00 05 STA &0500 ; player_feet_object_type # Set player sprite depending on whether man or wolf &2143 bd 8c 08 LDA &088c,X ; facing_flipped_table &2146 8d 78 03 STA &0378 ; player_feet_object_flipped # Flip player sprite depending on where they're facing &2149 8d 79 03 STA &0379 ; player_head_object_flipped &214c 60 RTS ; does_object_need_plotting &214d bd a0 03 LDA &03a0,X ; objects_bytes_per_line_of_sprite &2150 85 45 STA &45 ; bytes_per_sprite &2152 e4 70 CPX &70 ; start_of_background_objects # If this isn't a background object, then &2154 b0 09 BCS &215f ; determine_slice &2156 bd 70 06 LDA &0670,X ; objects_frame &2159 10 04 BPL &215f ; determine_slice # Is the object marked as hidden? &215b a9 01 LDA #&01 &215d d0 28 BNE &2187 ; set_needs_plotting # If so, mark object as not needing plotting ; determine_slice &215f bd 50 03 LDA &0350,X ; objects_position_z # Convert object x and z position into a vertical slice &2162 18 CLC &2163 7d 00 03 ADC &0300,X ; objects_position_x &2166 38 SEC &2167 e9 20 SBC #&20 &2169 48 PHA &216a 29 f8 AND #&f8 &216c 85 13 STA &13 ; slice_pixels &216e 68 PLA &216f 29 07 AND #&07 &2171 f0 02 BEQ &2175 ; sprite_isn't_shifted &2173 e6 45 INC &45 ; bytes_per_sprite ; sprite_isn't_shifted &2175 a5 13 LDA &13 ; slice_pixels &2177 4a LSR A &2178 4a LSR A &2179 4a LSR A &217a a8 TAY # Y contains the eight-pixel slice of screen ; consider_slice_for_each_byte_loop &217b b9 00 04 LDA &0400,Y ; slices_of_screen_changed # Has this slice of screen changed? &217e f0 07 BEQ &2187 ; set_needs_plotting # If so, mark object as needing plotting &2180 c8 INY &2181 c6 45 DEC &45 ; bytes_per_sprite &2183 d0 f6 BNE &217b ; consider_slice_for_each_byte_loop &2185 a9 01 LDA #&01 ; set_needs_plotting &2187 49 01 EOR #&01 &2189 9d d8 6c STA &6cd8,X ; objects_needs_plotting &218c ca DEX &218d 60 RTS ; update_screen &218e a6 44 LDX &44 ; number_of_objects # Determine which objects need plotting ; object_loop &2190 20 4d 21 JSR &214d ; does_object_need_plotting &2193 10 fb BPL &2190 ; object_loop &2195 a2 27 LDX #&27 # Ditto for background objects ; background_object_loop &2197 20 4d 21 JSR &214d ; does_object_need_plotting &219a e4 70 CPX &70 ; start_of_background_objects &219c d0 f9 BNE &2197 ; background_object_loop ; sort_objects_by_z_order # Sort objects by z-order &219e a6 44 LDX &44 ; number_of_objects &21a0 86 49 STX &49 ; object_z_order &21a2 86 48 STX &48 ; object_to_sort &21a4 a9 00 LDA #&00 &21a6 85 4e STA &4e ; sort_recursion ; mark_all_objects_as_needing_sorting &21a8 a9 01 LDA #&01 ; mark_objects_loop &21aa 9d 28 04 STA &0428,X ; objects_need_sorting &21ad 9d 7c 04 STA &047c,X ; objects_need_order_considering &21b0 ca DEX &21b1 10 f7 BPL &21aa ; mark_objects_loop ; sort_objects_loop &21b3 a6 48 LDX &48 ; object_to_sort ; sort_from_stack &21b5 bd 28 04 LDA &0428,X ; objects_need_sorting # Has this object already been sorted? &21b8 f0 58 BEQ &2212 ; skip_object &21ba bd d8 6c LDA &6cd8,X ; objects_needs_plotting # Does it actually need to be plotted? &21bd f0 53 BEQ &2212 ; skip_object ; sort_again &21bf a5 44 LDA &44 ; number_of_objects &21c1 85 4f STA &4f ; object_to_compare ; compare_loop &21c3 e4 4f CPX &4f ; object_to_compare &21c5 f0 3c BEQ &2203 ; objects_don't_obscure # Don't try to sort an object against itself &21c7 a4 4f LDY &4f ; object_to_compare &21c9 b9 28 04 LDA &0428,Y ; objects_need_sorting &21cc f0 35 BEQ &2203 ; objects_don't_obscure &21ce b9 d8 6c LDA &6cd8,Y ; objects_needs_plotting &21d1 f0 30 BEQ &2203 ; objects_don't_obscure &21d3 20 16 23 JSR &2316 ; do_objects_overlap &21d6 30 13 BMI &21eb ; objects_overlap &21d8 f0 29 BEQ &2203 ; objects_don't_obscure ; recurse_with_object &21da bd 7c 04 LDA &047c,X ; objects_need_order_considering &21dd f0 28 BEQ &2207 ; mark_object_as_sorted &21df de 7c 04 DEC &047c,X ; objects_need_order_considering &21e2 8a TXA &21e3 48 PHA &21e4 e6 4e INC &4e ; sort_recursion &21e6 a6 4f LDX &4f ; object_to_compare &21e8 4c bf 21 JMP &21bf ; sort_again ; objects_overlap &21eb a4 4f LDY &4f ; object_to_compare &21ed bd 50 03 LDA &0350,X ; objects_position_z &21f0 d9 50 03 CMP &0350,Y ; objects_position_z &21f3 90 0e BCC &2203 ; objects_don't_obscure &21f5 d0 e3 BNE &21da ; recurse_with_object &21f7 bd 28 03 LDA &0328,X ; objects_position_y &21fa d9 28 03 CMP &0328,Y ; objects_position_y &21fd 90 04 BCC &2203 ; objects_don't_obscure &21ff f0 02 BEQ &2203 ; objects_don't_obscure &2201 b0 d7 BCS &21da ; recurse_with_object ; objects_don't_obscure &2203 c6 4f DEC &4f ; object_to_compare &2205 10 bc BPL &21c3 ; compare_loop ; mark_object_as_sorted &2207 de 28 04 DEC &0428,X ; objects_need_sorting &220a 8a TXA &220b a4 49 LDY &49 ; object_z_order &220d 99 e4 6d STA &6de4,Y ; object_plotting_order &2210 c6 49 DEC &49 ; object_z_order ; skip_object &2212 a5 4e LDA &4e ; sort_recursion &2214 f0 0a BEQ &2220 ; no_more_recursion &2216 c6 4e DEC &4e ; sort_recursion &2218 68 PLA &2219 aa TAX &221a fe 7c 04 INC &047c,X ; objects_need_order_considering &221d 4c b5 21 JMP &21b5 ; sort_from_stack ; no_more_recursion &2220 c6 48 DEC &48 ; object_to_sort &2222 10 8f BPL &21b3 ; sort_objects_loop ; objects_have_been_sorted # Objects are now sorted by z-order &2224 a9 2c LDA #&2c ; BIT # Don't use mask for background objects &2226 85 15 STA &15 ; mask_instruction # Self-modifying code &2228 a5 49 LDA &49 ; object_z_order &222a 85 59 STA &59 ; last_z_order ; plot_background_objects # Plot background objects, without a mask &222c a9 27 LDA #&27 &222e 85 47 STA &47 ; object_number ; plot_background_objects_loop &2230 20 a2 1a JSR &1aa2 ; plot_object &2233 c6 47 DEC &47 ; object_number &2235 a5 47 LDA &47 ; object_number &2237 c5 70 CMP &70 ; start_of_background_objects &2239 d0 f5 BNE &2230 ; plot_background_objects_loop ; plot_objects # Plot regular objects, with a mask &223b a5 44 LDA &44 ; number_of_objects &223d 85 58 STA &58 ; loop_position &223f a9 3d LDA #&3d ; AND # Use mask for regular objects &2241 85 15 STA &15 ; mask_instruction # Self-modifying code ; plot_objects_loop &2243 a6 58 LDX &58 ; loop_position &2245 bd e4 6d LDA &6de4,X ; object_plotting_order # Get next object by z-order &2248 85 47 STA &47 ; object_number &224a 20 a2 1a JSR &1aa2 ; plot_object &224d c6 58 DEC &58 ; loop_position &224f a5 58 LDA &58 ; loop_position &2251 c5 59 CMP &59 ; last_z_order &2253 d0 ee BNE &2243 ; plot_objects_loop ; objects_plotted &2255 20 b6 e9 JSR &e9b6 ; os_delay # OS routine to wait 1/50s ; copy_changes_to_screen_from_buffer &2258 58 CLI &2259 a5 65 LDA &65 ; completely_redraw_room_if_zero &225b d0 03 BNE &2260 ; complete_redraw_not_needed # Does the room need completely redrawing? &225d 4c da 22 JMP &22da ; copy_entire_room_from_buffer ; complete_redraw_not_needed &2260 a5 44 LDA &44 ; number_of_objects &2262 85 47 STA &47 ; object_number ; unbuffer_objects_loop # If not, for every object: &2264 a6 47 LDX &47 ; object_number &2266 bd 00 6d LDA &6d00,X ; objects_needs_unbuffering &2269 d0 6a BNE &22d5 ; skip_object # Does it need copying from buffer to screen? &226b bd 38 06 LDA &0638,X ; objects_buffer_start_address_high &226e dd c4 06 CMP &06c4,X ; objects_previous_buffer_start_address_high &2271 90 03 BCC &2276 ; use_buffer_start # Use the lowest of current and previous start address &2273 bd c4 06 LDA &06c4,X ; objects_previous_buffer_start_address_high ; use_buffer_start &2276 48 PHA &2277 8d c1 22 STA &22c1 ; buffer_start_address_high # Self-modifying code &227a bd 54 06 LDA &0654,X ; objects_buffer_end_address_high &227d dd e0 06 CMP &06e0,X ; objects_previous_buffer_end_address_high &2280 b0 03 BCS &2285 ; use_buffer_end # Use the highest of current and previous end address &2282 bd e0 06 LDA &06e0,X ; objects_previous_buffer_end_address_high ; use_buffer_end &2285 38 SEC &2286 ed c1 22 SBC &22c1 ; buffer_start_address_high &2289 a8 TAY # Y contains number of slices to copy &228a 68 PLA &228b 30 48 BMI &22d5 ; skip_object &228d 38 SEC &228e e9 6b SBC #&6b &2290 85 13 STA &13 ; buffer_offset_high # Calculate corresponding screen address &2292 a9 68 LDA #&68 # &6b00 - &7fff is copied to &5400 - &68ff &2294 38 SEC &2295 e5 13 SBC &13 ; buffer_offset_high &2297 8d c4 22 STA &22c4 ; screen_start_address_high # Self-modifying code &229a bd 00 06 LDA &0600,X ; objects_first_slice_address &229d dd 8c 06 CMP &068c,X ; objects_previous_first_slice_address &22a0 90 03 BCC &22a5 ; use_first_slice # Use the lowest of current and previous first slice &22a2 bd 8c 06 LDA &068c,X ; objects_previous_first_slice_address ; use_first_slice &22a5 8d be 22 STA &22be ; first_slice # Self-modifying code &22a8 bd a8 06 LDA &06a8,X ; objects_previous_last_slice_address &22ab f0 0d BEQ &22ba ; use_last_slice &22ad bd 1c 06 LDA &061c,X ; objects_last_slice_address &22b0 f0 08 BEQ &22ba ; use_last_slice &22b2 dd a8 06 CMP &06a8,X ; objects_previous_last_slice_address &22b5 b0 03 BCS &22ba ; use_last_slice # Use the highest of current and previous last slice &22b7 bd a8 06 LDA &06a8,X ; objects_previous_last_slice_address ; use_last_slice &22ba 8d c7 22 STA &22c7 # self-modifying code ; unbuffer_lines_loop # Copy relevant parts of buffer to screen &22bd a2 00 LDX #&00 # actually LDX first_slice ; unbuffer_slices_loop &22bf bd 00 c0 LDA &c000,X # actually LDA (buffer_address),X &22c2 9d 00 ff STA &ff00,X # actually STA (screen_address),X &22c5 e8 INX &22c6 e0 00 CPX #&00 # actually CPX last_slice &22c8 d0 f5 BNE &22bf ; unbuffer_slices_loop &22ca ce c4 22 DEC &22c4 ; screen_address_high &22cd ee c1 22 INC &22c1 ; buffer_address_high # Buffer is upside-down to screen, in eight line groups &22d0 30 03 BMI &22d5 ; skip_object &22d2 88 DEY &22d3 10 e8 BPL &22bd ; unbuffer_lines_loop ; skip_object &22d5 c6 47 DEC &47 ; object_number &22d7 10 8b BPL &2264 ; unbuffer_objects_loop &22d9 60 RTS ; copy_entire_room_from_buffer &22da 78 SEI &22db e6 65 INC &65 ; completely_redraw_room_if_zero ; copy_bottom_wedge_from_buffer &22dd a2 04 LDX #&04 &22df a9 6b LDA #&6b &22e1 85 59 STA &59 ; buffer_address_high &22e3 a9 68 LDA #&68 &22e5 85 5b STA &5b ; screen_address_high ; copy_bottom_wedge_outer_loop &22e7 bc b1 08 LDY &08b1,X ; wedge_widths &22ea bd ac 08 LDA &08ac,X ; wedge_starts &22ed 85 58 STA &58 ; buffer_address_low &22ef 85 5a STA &5a ; screen_address_low ; copy_bottom_wedge_inner_loop &22f1 b1 58 LDA (&58),Y ; buffer_address &22f3 91 5a STA (&5a),Y ; screen_address &22f5 88 DEY &22f6 d0 f9 BNE &22f1 ; copy_bottom_wedge_inner_loop &22f8 e6 59 INC &59 ; buffer_address_high &22fa c6 5b DEC &5b ; screen_address_high &22fc ca DEX &22fd 10 e8 BPL &22e7 ; copy_bottom_wedge_outer_loop ; copy_top_block_from_buffer &22ff 84 58 STY &58 ; buffer_address_low &2301 84 5a STY &5a ; screen_address_low ; copy_top_block_loop &2303 b1 58 LDA (&58),Y ; buffer_address &2305 91 5a STA (&5a),Y ; screen_address &2307 c8 INY &2308 d0 f9 BNE &2303 ; copy_top_block_loop &230a c6 5b DEC &5b ; screen_address_high &230c e6 59 INC &59 ; buffer_address_high &230e 10 f3 BPL &2303 ; copy_top_block_loop &2310 a5 57 LDA &57 ; room_colour_scheme &2312 58 CLI &2313 4c d8 07 JMP &07d8 ; set_palette ; do_objects_overlap ; Y = object_to_consider; X = possibility ; returns &ff if objects overlap ; returns &01 if object X either overlaps or is above, east or south of object Y ; (i.e. could obscure it on screen) ; returns &00 otherwise ; &2316 bd 28 03 LDA &0328,X ; objects_position_y &2319 d9 28 03 CMP &0328,Y ; objects_position_y &231c f0 1e BEQ &233c ; y_overlap &231e 90 10 BCC &2330 ; y_less &2320 b9 28 03 LDA &0328,Y ; objects_position_y &2323 18 CLC &2324 79 34 07 ADC &0734,Y ; objects_size_y &2327 dd 28 03 CMP &0328,X ; objects_position_y &232a b0 10 BCS &233c ; y_overlap &232c a9 12 LDA #&12 # 18 if object X is completely above object Y &232e d0 0e BNE &233e ; finished_y_comparison ; y_less &2330 7d 34 07 ADC &0734,X ; objects_size_y &2333 d9 28 03 CMP &0328,Y ; objects_position_y &2336 b0 04 BCS &233c ; y_overlap &2338 a9 00 LDA #&00 # 0 if object X is completely below object Y &233a f0 02 BEQ &233e ; finished_y_comparison ; y_overlap &233c a9 09 LDA #&09 # 9 if objects overlap in y dimension ; finished_y_comparison &233e 85 47 STA &47 ; overlap_score &2340 bd 50 03 LDA &0350,X ; objects_position_z &2343 d9 50 03 CMP &0350,Y ; objects_position_z &2346 f0 1e BEQ &2366 ; z_overlap &2348 90 10 BCC &235a ; z_less &234a b9 50 03 LDA &0350,Y ; objects_position_z &234d 18 CLC &234e 79 fc 06 ADC &06fc,Y ; objects_size_z &2351 dd 50 03 CMP &0350,X ; objects_position_z &2354 b0 10 BCS &2366 ; z_overlap &2356 a9 02 LDA #&02 # +2 if object X is completely east of object Y &2358 d0 0e BNE &2368 ; finished_z_comparison ; z_less &235a 7d fc 06 ADC &06fc,X ; objects_size_z &235d d9 50 03 CMP &0350,Y ; objects_position_z &2360 b0 04 BCS &2366 &2362 a9 00 LDA #&00 # +0 if object X is completely west of object Y &2364 f0 02 BEQ &2368 ; finished_z_comparison ; z_overlap &2366 a9 01 LDA #&01 # +1 if objects overlap in z dimension ; finished_z_comparison &2368 18 CLC &2369 65 47 ADC &47 ; overlap_score &236b 85 47 STA &47 ; overlap_score &236d bd 00 03 LDA &0300,X ; objects_position_x &2370 d9 00 03 CMP &0300,Y ; objects_position_x &2373 f0 1e BEQ &2393 ; x_overlap &2375 90 10 BCC &2387 ; x_less &2377 b9 00 03 LDA &0300,Y ; objects_position_x &237a 18 CLC &237b 79 18 07 ADC &0718,Y ; objects_size_x &237e dd 00 03 CMP &0300,X ; objects_position_x &2381 b0 10 BCS &2393 ; x_overlap &2383 a9 06 LDA #&06 # +6 if object X is completely north of object Y &2385 d0 0e BNE &2395 ; finished_x_comparison ; x_less &2387 7d 18 07 ADC &0718,X ; objects_size_x &238a d9 00 03 CMP &0300,Y ; objects_position_x &238d b0 04 BCS &2393 ; x_overlap &238f a9 00 LDA #&00 # +0 if object X is completely south of object Y &2391 f0 02 BEQ &2395 ; finished_x_comparison ; x_overlap &2393 a9 03 LDA #&03 # +3 if objects overlap in x dimension ; finished_x_comparison &2395 18 CLC &2396 65 47 ADC &47 ; overlap_score &2398 a8 TAY &2399 b9 ce 2f LDA &2fce,Y ; overlap_lookup_table &239c 60 RTS ; wipe_buffer_occupied_by_object &239d b9 1c 06 LDA &061c,Y ; objects_last_slice_address &23a0 99 a8 06 STA &06a8,Y ; objects_previous_last_slice_address &23a3 8d ce 23 STA &23ce # Self-modifying code &23a6 b9 00 06 LDA &0600,Y ; objects_first_slice_address &23a9 99 8c 06 STA &068c,Y ; objects_previous_first_slice_address &23ac 8d c8 23 STA &23c8 # Self-modifying code &23af b9 54 06 LDA &0654,Y ; objects_buffer_end_address_high &23b2 99 e0 06 STA &06e0,Y ; objects_previous_buffer_end_address_high &23b5 38 SEC &23b6 f9 38 06 SBC &0638,Y ; objects_buffer_start_address_high &23b9 aa TAX # X contains number of lines of buffer to wipe &23ba b9 38 06 LDA &0638,Y ; objects_buffer_start_address_high &23bd 99 c4 06 STA &06c4,Y ; objects_previous_buffer_start_address_high &23c0 30 17 BMI &23d9 ; leave &23c2 8d cb 23 STA &23cb # Self-modifying code &23c5 a9 00 LDA #&00 ; wipe_lines_loop &23c7 a0 00 LDY #&00 # actually LDY object_first_slice_address ; wipe_slices_loop &23c9 99 00 ff STA &ff00,Y # actually STA (buffer_address_high),Y # Zero buffer for slices between start and end lines &23cc c8 INY &23cd c0 00 CPY #&00 # actually CPY object_last_slice_address &23cf d0 f8 BNE &23c9 ; wipe_slices_loop &23d1 ee cb 23 INC &23cb # Self-modifying code &23d4 30 03 BMI &23d9 &23d6 ca DEX &23d7 10 ee BPL &23c7 ; wipe_lines_loop ; leave &23d9 60 RTS ; move_object_towards_player &23da b9 c8 6b LDA &6bc8,Y ; objects_movement_y &23dd d0 12 BNE &23f1 ; move_object_towards_player_on_floor # If the object isn't already moving vertically, &23df b9 28 03 LDA &0328,Y ; objects_position_y &23e2 cd 28 03 CMP &0328 ; player_feet_object_position_y &23e5 90 0a BCC &23f1 ; move_object_towards_player_on_floor # Is the object above the player? &23e7 a9 01 LDA #&01 &23e9 99 00 6c STA &6c00,Y ; objects_vertical_speed # If so, make it fall (speed 1) &23ec a9 ff LDA #&ff &23ee 99 c8 6b STA &6bc8,Y ; objects_movement_y ; move_object_towards_player_on_floor &23f1 a9 00 LDA #&00 &23f3 99 00 6b STA &6b00,Y ; objects_movement_xz # By default, stop the object &23f6 b9 00 03 LDA &0300,Y ; objects_position_x &23f9 cd 00 03 CMP &0300 ; player_feet_object_position_x &23fc 90 05 BCC &2403 ; move_object_north &23fe f0 08 BEQ &2408 ; don't_move_object_north_or_south &2400 a9 08 LDA #&08 ; south # Set it moving south if north of player &2402 2c a9 02 BIT &02a9 ; move_object_north #2403 LDA #&02 ; north # And north if south of player &2405 99 00 6b STA &6b00,Y ; objects_movement_xz ; don't_move_object_north_or_south &2408 b9 50 03 LDA &0350,Y ; objects_position_z &240b cd 50 03 CMP &0350 ; player_feet_object_position_z &240e 90 05 BCC &2415 ; move_object_west &2410 f0 0b BEQ &241d ; don't_move_object_west_or_east &2412 a9 01 LDA #&01 ; west # Set it moving west if east of player &2414 2c a9 04 BIT &04a9 ; move_object_west #2415 LDA #&04 ; east # And east if west of player &2417 59 00 6b EOR &6b00,Y ; objects_movement_xz &241a 99 00 6b STA &6b00,Y ; objects_movement_xz ; don't_move_object_west_or_east &241d b9 00 05 LDA &0500,Y ; objects_type &2420 c9 13 CMP #&13 ; SPRITE_BALL # Is this a BALL? &2422 d0 1c BNE &2440 ; not_ball &2424 a5 5d LDA &5d ; man_or_wolf &2426 d0 08 BNE &2430 ; not_ball # If so, is the player a man? &2428 b9 00 6b LDA &6b00,Y ; objects_movement_xz &242b 49 0f EOR #&0f &242d 99 00 6b STA &6b00,Y ; objects_movement_xz # If so, move away rather than towards player &2430 20 c7 07 JSR &07c7 ; random_number &2433 29 18 AND #&18 &2435 69 0c ADC #&0c &2437 79 28 03 ADC &0328,Y ; objects_position_y # And give it a random maximum height &243a 99 e4 6b STA &6be4,Y ; objects_maximum_position &243d a9 02 LDA #&02 # BALL has speed 2 if player is a man, 4 if a wolf &243f 2c a9 04 BIT &04a9 ; not ball #2440 LDA #&04 # HOMING_MAGIC has speed 4 &2442 99 1c 6b STA &6b1c,Y ; objects_horizontal_speed &2445 60 RTS ; handle_active_object_movements &2446 b9 00 05 LDA &0500,Y ; objects_type &2449 c9 53 CMP #&53 ; SPRITE_HOMING_MAGIC # Is this a HOMING_MAGIC? If so, move it towards player &244b f0 8d BEQ &23da ; move_object_towards_player &244d c9 13 CMP #&13 ; SPRITE_BALL # Is this a BALL? &244f d0 1d BNE &246e ; not_ball &2451 b9 c8 6b LDA &6bc8,Y ; objects_movement_y &2454 d0 50 BNE &24a6 ; leave # Is it moving vertically? If so, leave. &2456 a9 01 LDA #&01 &2458 99 c8 6b STA &6bc8,Y ; objects_movement_y &245b a9 02 LDA #&02 &245d 99 00 6c STA &6c00,Y ; objects_vertical_speed # Otherwise, make it rise (speed 2) &2460 a5 61 LDA &61 ; room_number &2462 a2 09 LDX #&09 # Is this a room where a BALL moves towards the player? ; room_comparison_loop &2464 dd b6 08 CMP &08b6,X ; rooms_in_which_balls_do_not_move_towards_player &2467 f0 3d BEQ &24a6 ; leave &2469 ca DEX &246a 10 f8 BPL &2464 ; room_comparison_loop &246c 30 83 BMI &23f1 ; move_object_towards_player_on_floor # If so, make it do so ; not_ball &246e b9 00 6b LDA &6b00,Y ; objects_movement_xz # For all other kinds of objects, &2471 d0 33 BNE &24a6 ; leave # Leave if the object is already moving &2473 c0 00 CPY #&00 &2475 f0 2f BEQ &24a6 ; leave # Leave if it's the player &2477 b9 00 05 LDA &0500,Y ; objects_type &247a c9 53 CMP #&53 ; SPRITE_HOMING_MAGIC &247c b0 28 BCS &24a6 ; leave # Leave if it's homing magic or a special block &247e c9 47 CMP #&47 ; SPRITE_GUARD_FEET_FRONT &2480 b0 39 BCS &24bb ; is_guard_feet &2482 c9 1d CMP #&1d ; SPRITE_FIRE &2484 f0 21 BEQ &24a7 ; is_fire &2486 c9 19 CMP #&19 ; SPRITE_GUARD_HEAD_FRONT &2488 b0 1c BCS &24a6 ; leave &248a c9 15 CMP #&15 ; ghost &248c 90 18 BCC &24a6 ; leave # Is this a GHOST? &248e 20 c7 07 JSR &07c7 ; random_number &2491 29 03 AND #&03 &2493 aa TAX &2494 bd ac 07 LDA &07ac,X ; ghost_random_movement_table # If so, move it on a random diagonal &2497 99 00 6b STA &6b00,Y ; objects_movement_xz &249a a2 17 LDX #&17 ; SPRITE_GHOST_FRONT &249c c9 09 CMP #&09 &249e b0 02 BCS &24a2 ; ghost_facing_front &24a0 a2 15 LDX #&15 ; SPRITE_GHOST_BACKA ; ghost_facing_front &24a2 8a TXA &24a3 99 00 05 STA &0500,Y ; objects_type # And set its sprite depending on new direction ; leave &24a6 60 RTS ; is_fire # Is this a FIRE? &24a7 b9 c8 6c LDA &6cc8,Y ; objects_previous_movement_xz &24aa 29 05 AND #&05 ; west or east &24ac f0 06 BEQ &24b4 ; fire_moving_north_or_south # If so, toggle its direction &24ae 49 05 EOR #&05 # either west (1) / east (4) &24b0 99 00 6b STA &6b00,Y ; objects_movement_xz &24b3 60 RTSA ; fire_moving_north_or_south &24b4 b9 c8 6c LDA &6cc8,Y ; objects_previous_movement_xz &24b7 49 0a EOR #&0a ; north or south # or north (2) / south (8) &24b9 d0 f5 BNE &24b0 ; is_guard_feet # Is this a GUARD_FEET? &24bb b9 c8 6c LDA &6cc8,Y ; objects_previous_movement_xz &24be 0a ASL A &24bf a6 61 LDX &61 ; room_number # Is this a room where GUARDs walk back and forth? &24c1 e0 7c CPX #&7c &24c3 f0 09 BEQ &24ce ; back_and_forth_guard_room &24c5 e0 9d CPX #&9d &24c7 f0 05 BEQ &24ce ; back_and_forth_guard_room &24c9 e0 f1 CPX #&f1 &24cb f0 01 BEQ &24ce ; back_and_forth_guard_room # If not, transform direction &24cd 4a LSR A # W/N/E/S -> N/E/S/W ; back_and_forth_guard_room &24ce 0a ASL A # If so, transform direction &24cf 29 0f AND #&0f # W/N/E/S -> E/S/W/W &24d1 d0 02 BNE &24d5 &24d3 a9 01 LDA #&01 &24d5 99 00 6b STA &6b00,Y ; objects_movement_xz &24d8 aa TAX &24d9 29 06 AND #&06 ; north/east &24db f0 02 BEQ &24df ; not_north_or_east &24dd a9 07 LDA #&07 ; not_north_or_east &24df 99 78 03 STA &0378,Y ; objects_flipped # Set flipped depending on new direction &24e2 8a TXA &24e3 29 03 AND #&03 ; north/west &24e5 f0 02 BEQ &24e9 ; not_north_or_west &24e7 a9 06 LDA #&06 ; not_north_or_west &24e9 18 CLC &24ea 69 47 ADC #&47 ; SPRITE_GUARD_FEET_FRONT &24ec 99 00 05 STA &0500,Y ; objects_type # Set sprite depending on new direction ; leave &24ef 60 RTS ; wipe_object_from_screen &24f0 a4 07 LDY &07 ; object_to_consider &24f2 20 0b 25 JSR &250b ; wipe_object_Y &24f5 a4 07 LDY &07 ; object_to_consider # Is this the player? &24f7 d0 f6 BNE &24ef ; leave &24f9 ad 00 05 LDA &0500 ; player_feet_object_type &24fc c9 3f CMP #&3f ; SPRITE_SPASMING_WOLF &24fe f0 08 BEQ &2508 ; is_spasming # If the player isn't spasming, &2500 e6 07 INC &07 ; object_to_consider &2502 c8 INY &2503 20 0b 25 JSR &250b ; wipe_object_Y # then wipe head as well as the feet &2506 c6 07 DEC &07 ; object_to_consider ; is_spasming &2508 4c 4d 25 JMP &254d ; update_player_head # The player's head is always above their feet ; wipe_object_Y &250b a9 00 LDA #&00 &250d 99 00 6d STA &6d00,Y ; objects_needs_unbuffering # Mark object as no longer needing copying from buffer ; wipe_object_Y_that_still_needs_unbuffering &2510 20 18 25 JSR &2518 ; mark_slices_occupied_by_object_as_changed &2513 a4 07 LDY &07 ; object_to_consider &2515 4c 9d 23 JMP &239d ; wipe_buffer_occupied_by_object # Wipe buffer, having marked slices as changed ; mark_slices_occupied_by_object_as_changed &2518 b9 50 03 LDA &0350,Y ; objects_position_z # Convert x and z position into slice number &251b 18 CLC &251c 79 00 03 ADC &0300,Y ; objects_position_x &251f 38 SEC &2520 e9 20 SBC #&20 &2522 48 PHA &2523 29 f8 AND #&f8 &2525 4a LSR A &2526 4a LSR A &2527 4a LSR A &2528 aa TAX &2529 b9 a0 03 LDA &03a0,Y ; objects_bytes_per_line_of_sprite &252c a8 TAY &252d 68 PLA &252e 29 07 AND #&07 &2530 f0 01 BEQ &2533 ; byte_aligned # Add an extra slice if not byte aligned &2532 c8 INY ; byte_aligned &2533 a9 00 LDA #&00 ; mark_slice_loop &2535 9d 00 04 STA &0400,X ; slices_of_screen_changed # Mark slices as changed &2538 e8 INX &2539 88 DEY &253a d0 f9 BNE &2535 ; mark_slice_loop &253c 60 RTS ; animate_player_feet &253d ee 70 06 INC &0670 ; player_feet_object_frame &2540 ad 70 06 LDA &0670 ; player_feet_object_frame &2543 c9 06 CMP #&06 &2545 d0 02 BNE &2549 ; leave &2547 a9 00 LDA #&00 &2549 8d 70 06 STA &0670 ; player_feet_object_frame ; leave &254c 60 RTS ; update_player_head &254d ad 00 03 LDA &0300 ; player_feet_object_position_x # Copy position from player's feet &2550 8d 01 03 STA &0301 ; player_head_object_position_x &2553 ad 00 06 LDA &0600 ; player_feet_object_first_slice_address &2556 8d 01 06 STA &0601 ; player_head_object_first_slice_address &2559 ad 1c 06 LDA &061c ; player_feet_object_last_slice_address &255c 8d 1d 06 STA &061d ; player_head_object_last_slice_address &255f ad 78 03 LDA &0378 ; player_feet_object_flipped &2562 8d 79 03 STA &0379 ; player_head_object_flipped &2565 ad 50 03 LDA &0350 ; player_feet_object_position_z &2568 8d 51 03 STA &0351 ; player_head_object_position_z &256b a9 12 LDA #&12 &256d a6 7c LDX &7c ; is_phasing_in_or_out &256f f0 0a BEQ &257b ; isn't_phasing &2571 ad 79 03 LDA &0379 ; player_head_object_flipped # Flip every cycle when phasing &2574 49 07 EOR #&07 &2576 8d 79 03 STA &0379 ; player_head_object_flipped &2579 a9 0b LDA #&0b # Player's body is shorter when phasing ; isn't_phasing &257b 18 CLC &257c 6d 28 03 ADC &0328 ; player_feet_object_position_y &257f 8d 29 03 STA &0329 ; player_head_object_position_y # Position head above feet ; update_player_head_frame &2582 ae 00 05 LDX &0500 ; player_feet_object_type &2585 e0 3f CPX #&3f ; SPRITE_SPASMING_WOLF &2587 90 0a BCC &2593 ; isn't_spasming_or_phasing &2589 a9 00 LDA #&00 &258b e0 42 CPX #&42 ; SPRITE_MAGIC # Only one frame when phasing &258d f0 18 BEQ &25a7 ; set_player_head_object_frame &258f a9 ff LDA #&ff &2591 30 14 BMI &25a7 ; set_player_head_object_frame # Don't display player's head if spasming ; isn't_spasming_or_phasing &2593 a9 43 LDA #&43 ; SPRITE_MAN_HEAD_FRONT &2595 8d 01 05 STA &0501 ; player_head_object_type &2598 a5 5c LDA &5c ; player_facing &259a c9 02 CMP #&02 &259c 90 02 BCC &25a0 &259e 49 03 EOR #&03 # Set frame based on direction &25a0 a6 5d LDX &5d ; man_or_wolf &25a2 f0 03 BEQ &25a7 ; set_player_head_object_frame &25a4 18 CLC &25a5 69 02 ADC #&02 # and whether the player is man or wolf ; set_player_head_object_frame &25a7 8d 71 06 STA &0671 ; player_head_object_frame &25aa 60 RTS ; find_an_object_07_overlaps ; leave with X = target, Y = object_in_07, A = -1 for hit, 0 for miss &25ab a6 44 LDX &44 ; number_of_objects ; find_object_loop &25ad 20 bc 25 JSR &25bc ; check_target_object_for_overlap_with_object_07 &25b0 30 05 BMI &25b7 ; leave_with_hit &25b2 ca DEX &25b3 10 f8 BPL &25ad ; find_object_loop &25b5 a9 00 LDA #&00 ; leave_with_hit &25b7 08 PHP &25b8 a4 07 LDY &07 ; object_to_consider &25ba 28 PLP &25bb 60 RTS ; check_target_object_for_overlap_with_object_07 &25bc e4 07 CPX &07 ; object_to_consider &25be f0 07 BEQ &25c7 ; leave_with_zero # leave with 0 if the object is also the target &25c0 a4 07 LDY &07 ; object_to_consider &25c2 20 16 23 JSR &2316 ; do_objects_overlap &25c5 30 03 BMI &25ca ; check_target_object_type # 0 if the object and the target don't overlap ; leave_with_zero &25c7 a9 00 LDA #&00 &25c9 60 RTS ; check_target_object_type &25ca bd 00 05 LDA &0500,X ; objects_type &25cd c9 0a CMP #&0a &25cf 90 f6 BCC &25c7 ; leave_with_zero # 0 if the target is a door &25d1 c9 42 CMP #&42 ; SPRITE_MAGIC &25d3 f0 f2 BEQ &25c7 ; leave_with_zero # 0 if the target is SPRITE_MAGIC &25d5 c9 43 CMP #&43 ; SPRITE_MAN_HEAD_FRONT &25d7 f0 ee BEQ &25c7 ; leave_with_zero # 0 if the target is SPRITE_MAN_HEAD_FRONT &25d9 c9 19 CMP #&19 ; SPRITE_GUARD_HEAD_FRONT &25db f0 ea BEQ &25c7 ; leave_with_zero # 0 if the target is SPRITE_GUARD_HEAD_FRONT &25dd c9 1b CMP #&1b ; SPRITE_WIZARD_HEAD_FRONT &25df f0 e6 BEQ &25c7 ; leave_with_zero # 0 if the target is SPRITE_WIZARD_HEAD_FRONT &25e1 bd 70 06 LDA &0670,X ; objects_frame &25e4 30 e1 BMI &25c7 ; leave_with_zero # 0 if the target is hidden &25e6 e0 17 CPX #&17 &25e8 d0 0b BNE &25f5 ; leave_with_minus_one # -1 otherwise, unless &25ea bd 00 05 LDA &0500,X ; objects_type &25ed c9 27 CMP #&27 ; SPRITE_MAN_FEET_FRONT &25ef b0 04 BCS &25f5 ; leave_with_minus_one &25f1 c9 1f CMP #&1f ; SPRITE_CHARM_CUP &25f3 b0 d2 BCS &25c7 ; leave_with_zero # it's the cauldron charm, in which case, 0 ; leave_with_minus_one &25f5 a9 ff LDA #&ff &25f7 60 RTS ; find_objects_X_overlaps &25f8 86 4c STX &4c ; object_number &25fa a6 44 LDX &44 ; number_of_objects ; find_objects_X_overlaps_loop &25fc 20 bc 25 JSR &25bc ; check_target_object_for_overlap_with_object_07 &25ff 9d 60 04 STA &0460,X ; objects_overlap_results &2602 ca DEX &2603 10 f7 BPL &25fc ; find_objects_X_overlaps &2605 a4 07 LDY &07 ; object_to_consider &2607 a5 13 LDA &13 ; previous_position &2609 60 RTS ; consider_hit_object ; leaves with A = -1 if object Y has hit another, 0 if not ; leaves with X, Y = object hit &260a c0 00 CPY #&00 # Y is the moving object &260c d0 43 BNE &2651 ; isn't_player # Is the moving object the player's feet? &260e a9 ff LDA #&ff &2610 85 7f STA &7f ; player_has_touched_deadly_thing &2612 a6 44 LDX &44 ; number_of_objects &2614 a0 00 LDY #&00 # Y is set to zero ; object_loop &2616 bd 60 04 LDA &0460,X ; objects_overlap_results # If so, loop over all other objects for overlaps &2619 f0 23 BEQ &263e ; skip_object &261b bd 1c 6c LDA &6c1c,X ; objects_support &261e 30 1e BMI &263e ; skip_object # Skipping deadly ones &2620 f0 18 BEQ &263a ; fixed_object # Fixed objects stop the player being moved &2622 bd 00 05 LDA &0500,X ; objects_type &2625 c9 26 CMP #&26 ; SPRITE_CHARM_LIFE # Is this an extra life? &2627 d0 0b BNE &2634 ; not_extra_life &2629 c0 00 CPY #&00 &262b d0 0d BNE &263a ; fixed_object # being touched by the player? &262d fe 28 04 INC &0428,X ; objects_about_to_disappear # If so, collect it &2630 e6 7e INC &7e ; trigger_spiked_ball_falling &2632 e6 8a INC &8a ; life_counter # and gain an extra life ; not_extra_life &2634 c0 00 CPY #&00 &2636 d0 02 BNE &263a ; fixed_object &2638 8a TXA &2639 a8 TAY # Y stores object being hit ; fixed_object &263a a9 00 LDA #&00 # If a fixed and a deadly object stops the player, &263c 85 7f STA &7f ; player_has_touched_deadly_thing # the player doesn't die as a result ; skip_object &263e ca DEX &263f d0 d5 BNE &2616 ; object_loop &2641 a5 7f LDA &7f ; player_has_touched_deadly_thing &2643 f0 05 BEQ &264a ; not_touched_deadly_thing ; deadly_contact &2645 a9 01 LDA #&01 &2647 20 bd 26 JSR &26bd; set_player_phasing # Kill player if moving into something deadly ; not_touched_deadly_thing &264a 98 TYA &264b aa TAX # Leave with X = object moving &264c d0 10 BNE &265e ; leave_with_minus_one # A = -1 if object hit &264e a9 00 LDA #&00 # A = 0 otherwise &2650 60 RTS ; isn't_player # If the moving object isn't the player's feet, &2651 a6 4c LDX &4c ; object_being_pushed &2653 d0 09 BNE &265e ; leave_with_minus_one # Is the object hit the player's feet? &2655 b9 1c 6c LDA &6c1c,Y ; objects_support &2658 10 04 BPL &265e ; leave_with_minus_one # Is the moving object something deadly? &265a a0 00 LDY #&00 &265c f0 e7 BEQ &2645 ; deadly_contact # If so, kill the player ; leave_with_minus_one &265e a9 ff LDA #&ff # Otherwise, leave with -1 &2660 60 RTS ; drop_spiked_ball_or_portcullis &2661 a5 7a LDA &7a ; rising_or_falling_object &2663 10 21 BPL &2686 ; leave # Leave if something is already rising or falling ; pick_random_object &2665 20 c7 07 JSR &07c7 ; random_number # Pick an object at random &2668 29 1f AND #&1f &266a c5 44 CMP &44 ; number_of_objects &266c b0 f7 BCS &2665 ; pick_random_object &266e 69 01 ADC #&01 &2670 aa TAX &2671 86 7a STX &7a ; rising_or_falling_object &2673 bd 00 05 LDA &0500,X ; objects_type # See if it's something that can fall &2676 c9 0c CMP #&0c ; SPRITE_SPIKED_BALL &2678 f0 0d BEQ &2687 ; handle_spiked_ball_dropping &267a c9 12 CMP #&12 ; SPRITE_PORTCULLIS_X &267c f0 2a BEQ &26a8 ; handle_portcullis_dropping &267e c9 41 CMP #&41 ; SPRITE_PORTCULLIS_Z &2680 f0 26 BEQ &26a8 ; handle_portcullis_dropping ; no_object_dropping &2682 a2 ff LDX #&ff &2684 86 7a STX &7a ; rising_or_falling_object ; leave &2686 60 RTS ; handle_spiked_ball_dropping &2687 a5 61 LDA &61 ; room_number # Check if room has spiked balls that fall immediately &2689 c9 e2 CMP #&e2 &268b f0 10 BEQ &269d ; set_object_falling &268d c9 7a CMP #&7a &268f f0 0c BEQ &269d ; set_object_falling &2691 c9 9c CMP #&9c &2693 f0 08 BEQ &269d ; set_object_falling &2695 c9 c4 CMP #&c4 &2697 f0 04 BEQ &269d ; set_object_falling &2699 a5 7e LDA &7e ; trigger_spiked_ball_falling # Has the player just collected a charm or life? &269b f0 e5 BEQ &2682 ; no_object_dropping # If so, make spiked balls fall here too ; set_object_falling &269d a9 ff LDA #&ff # Set object falling ; set_object_moving_vertically &269f 9d c8 6b STA &6bc8,X ; objects_movement_y &26a2 a9 01 LDA #&01 &26a4 9d 00 6c STA &6c00,X ; objects_vertical_speed # with speed 1 &26a7 60 RTS ; handle_portcullis_dropping &26a8 a9 01 LDA #&01 &26aa bc 28 03 LDY &0328,X ; objects_position_y &26ad c0 18 CPY #&18 # Has the portcullis reached its topmost position? &26af d0 ee BNE &269f ; set_object_moving_vertically # If not, cause it to rise (speed 1) &26b1 a5 92 LDA &92 ; portcullis_grace &26b3 d0 cd BNE &2682 ; no_object_dropping # Forget falling portcullis if within grace period &26b5 a5 79 LDA &79 ; steps_to_take_into_room &26b7 d0 c9 BNE &2682 ; no_object_dropping # or if player is still walking into room &26b9 f0 e2 BEQ &269d ; set_object_falling # Otherwise, make it fall (speed 1) ; kill_player &26bb a9 01 LDA #&01 # Set player phasing out ; set_player_phasing &26bd 85 7c STA &7c ; is_phasing_in_or_out &26bf a9 42 LDA #&42 ; SPRITE_MAGIC &26c1 8d 00 05 STA &0500 ; player_feet_object_type &26c4 8d 01 05 STA &0501 ; player_head_object_type &26c7 a9 00 LDA #&00 &26c9 8d 78 03 STA &0378 ; player_feet_object_flipped &26cc 8d 70 06 STA &0670 ; player_feet_object_frame &26cf 8d 71 06 STA &0671 ; player_head_object_frame &26d2 a9 07 LDA #&07 &26d4 85 63 STA &63 ; spasm_jumping_or_phasing_stage &26d6 4c 4d 25 JMP &254d ; update_player_head ; return_direction_towards_centre_of_door ; returns &ff if A < &3c ; &02 if A > &3b && A < &4c ; &4c if A = &4c ; &08 if A > &4c && A < &58 ; &ff if A > &57 &26d9 c9 58 CMP #&58 &26db b0 0c BCS &26e9 ; leave_with_minus_one &26dd c9 4d CMP #&4d &26df b0 0b BCS &26ec ; leave_with_south &26e1 c9 4c CMP #&4c &26e3 f0 06 BEQ &26eb ; leave &26e5 c9 3c CMP #&3c &26e7 b0 06 BCS &26ef ; leave_with_north ; leave_with_minus_one &26e9 a9 ff LDA #&ff &26eb 60 RTS ; leave_with_south &26ec a9 08 LDA #&08 ; south &26ee 60 RTS ; leave_with_north &26ef a9 02 LDA #&02 ; north &26f1 60 RTS ; update_objects &26f2 a9 00 LDA #&00 &26f4 85 7b STA &7b ; object_to_update # Looping over all objects, ; update_objects_loop &26f6 a5 7b LDA &7b ; object_to_update # For each object, &26f8 85 07 STA &07 ; object_to_consider ; update_object_again &26fa 20 aa 28 JSR &28aa ; handle_object_movement # Handle its movement (Y = object_to_consider on return) &26fd 48 PHA &26fe 86 1e STX &1e ; object_being_pushed &2700 a5 61 LDA &61 ; room_number &2702 c9 78 CMP #&78 ; cauldron_room &2704 d0 04 BNE &270a ; not_cauldron_room &2706 c0 17 CPY #&17 # Is this object the cauldron magic? &2708 f0 0d BEQ &2717 ; handle_object_animation # If so, handle its animation regardless ; not_cauldron_room &270a c0 04 CPY #&04 # Alternatively, is this a regular object? &270c 90 4b BCC &2759 ; is_player_or_room_charm # (skip animation for player and room charms) &270e b9 70 06 LDA &0670,Y ; objects_frame &2711 10 04 BPL &2717 ; handle_object_animation # That isn't marked as hidden? &2713 68 PLA &2714 4c 58 28 JMP &2858 ; next_object ; handle_object_animation # If so, handle its animation &2717 98 TYA &2718 aa TAX ; object_to_consider &2719 fe 70 06 INC &0670,X ; objects_frame # Animate the object, but: &271c b9 70 06 LDA &0670,Y ; objects_frame &271f e6 22 INC &22 ; object_has_changed &2721 be 00 05 LDX &0500,Y ; objects_type &2724 e0 13 CPX #&13 ; SPRITE_BALL # No animation for passive objects &2726 90 2a BCC &2752 ; passive_object &2728 e0 1f CPX #&1f ; SPRITE_CHARM_CUP # BALL, GHOST, FIRE have two frames of animation &272a 90 18 BCC &2744 ; limit_frame # (GUARD_HEAD and WIZARD_HEAD are handled elsewhere) &272c e0 27 CPX #&27 ; SPRITE_MAN_FEET_FRONT # Charms have no animation &272e 90 24 BCC &2754 ; reset_frame &2730 e0 42 CPX #&42 ; SPRITE_MAGIC # MAGIC has no animation &2732 f0 20 BEQ &2754 ; reset_frame &2734 e0 53 CPX #&53 ; SPRITE_HOMING_MAGIC # HOMING_MAGIC has no animation, but flips each cycle &2736 f0 10 BEQ &2748 ; flip_object &2738 b0 18 BCS &2752 ; passive_object # All varieties of BLOCK have no animation &273a e0 47 CPX #&47 ; SPRITE_GUARD_FEET_FRONT &273c 90 14 BCC &2752 ; passive_object # Player FEET are handled elsewhere &273e c9 06 CMP #&06 &2740 90 14 BCC &2756 ; set_frame # GUARD_FEET have six frames of animation &2742 b0 10 BCS &2754 ; reset_frame ; limit_frame &2744 29 01 AND #&01 &2746 10 0e BPL &2756 ; set_frame ; flip_object &2748 b9 78 03 LDA &0378,Y ; objects_flipped &274b 49 07 EOR #&07 &274d 99 78 03 STA &0378,Y ; objects_flipped &2750 10 02 BPL &2754 ; reset_frame ; passive_object &2752 c6 22 DEC &22 ; object_has_changed # No change if frame hasn't changed ; reset_frame &2754 a9 00 LDA #&00 ; leave_frame_unaltered &2756 99 70 06 STA &0670,Y ; objects_frame # End of object animation ; is_player_or_room_charm &2759 a5 22 LDA &22 ; object_has_changed &275b f0 66 BEQ &27c3 ; no_change # Has the object changed? &275d a4 44 LDY &44 ; number_of_objects &275f c8 INY # Mark slices for object's previous position &2760 20 18 25 JSR &2518 ; mark_slices_occupied_by_object_as_changed &2763 a4 07 LDY &07 ; object_to_consider &2765 20 f0 24 JSR &24f0 ; wipe_object_from_screen # Remove object from screen &2768 a4 07 LDY &07 ; object_to_consider &276a c0 02 CPY #&02 # Is this the player? If so, sound is handled elsewhere &276c 90 52 BCC &27c0 ; no_sound &276e c0 04 CPY #&04 &2770 b0 0a BCS &277c ; handle_object_sounds # Is this a room charm? &2772 b9 86 00 LDA &0086,Y ; room_charms_changed_state &2775 10 05 BPL &277c ; handle_object_sounds # If so, has it been collected? &2777 99 70 06 STA &0670,Y ; objects_frame # If so, hide it &277a 30 44 BMI &27c0 ; no_change ; handle_object_sounds # Handle sounds for all other objects &277c b9 00 05 LDA &0500,Y ; objects_type &277f c9 19 CMP #&19 ; SPRITE_GUARD_HEAD_FRONT # GUARDs and WIZARD make a walking sound &2781 f0 1f BEQ &27a2 ; walking_sound &2783 c9 1b CMP #&1b ; SPRITE_WIZARD_HEAD_FRONT &2785 f0 1b BEQ &27a2 ; walking_sound &2787 c9 47 CMP #&47 ; SPRITE_GUARD_FEET_FRONT # (but not twice) &2789 f0 35 BEQ &27c0 ; no_sound &278b c9 4d CMP #&4d ; SPRITE_GUARD_FEET_BACK &278d f0 31 BEQ &27c0 ; no_sound &278f c9 56 CMP #&56 ; SPRITE_DISAPPEARED &2791 f0 2d BEQ &27c0 ; no_sound &2793 c4 7a CPY &7a ; rising_or_falling_object # Apart from falling portcullises, &2795 d0 24 BNE &27bb ; sound_from_position # other moving objects make a sound based on position. &2797 be c8 6b LDX &6bc8,Y ; objects_movement_y &279a 10 1f BPL &27bb ; sound_from_position &279c c9 0c CMP #&0c ; SPRITE_SPIKED_BALL &279e f0 1b BEQ &27bb ; sound_from_position &27a0 d0 1e BNE &27c0 ; no_sound ; walking_sound &27a2 e6 8d INC &8d ; npc_walking_sound_delay &27a4 a5 8d LDA &8d ; npc_walking_sound_delay &27a6 29 02 AND #&02 &27a8 aa TAX &27a9 a5 8d LDA &8d ; npc_walking_sound_delay &27ab 29 01 AND #&01 # GUARDs and WIZARD make a sound every two cycles &27ad d0 11 BNE &27c0 ; no_sound &27af bd b0 07 LDA &07b0,X ; pitch_table # That alternates in pitch &27b2 18 CLC &27b3 e9 14 SBC #&14 &27b5 20 14 16 JSR &1614 ; play_sound_from_A &27b8 4c be 27 JMP &27be ; end_of_handle_object_sound ; sound_from_position &27bb 20 09 16 JSR &1609 ; play_sound_from_position &27be a4 07 LDY &07 ; object_to_consider ; no_sound ; end_of_handle_object_sound # End of object sound handling &27c0 b9 28 04 LDA &0428,Y ; objects_about_to_disappear ; no_change &27c3 f0 24 BEQ &27e9 ; not_disappeared # Has this object been marked to disappear? &27c5 b9 00 05 LDA &0500,Y ; objects_type &27c8 c9 56 CMP #&56 ; SPRITE_DISAPPEARED # If it is already SPRITE_DISAPPEARED, &27ca d0 07 BNE &27d3 ; disappear_stage_one &27cc a9 ff LDA #&ff &27ce 99 70 06 STA &0670,Y ; objects_frame # then hide it. &27d1 30 12 BMI &27e5 ; disappearing_object ; disappear_stage_one &27d3 a9 56 LDA #&56 ; SPRITE_DISAPPEARED # Otherwise, set to SPRITE_DISAPPEARED &27d5 99 00 05 STA &0500,Y ; objects_type # (so it disappears in a puff of magic) &27d8 a9 03 LDA #&03 &27da 99 a0 03 STA &03a0,Y ; objects_bytes_per_line_of_sprite &27dd a9 0a LDA #&0a &27df 99 fc 06 STA &06fc,Y ; objects_size_z &27e2 99 18 07 STA &0718,Y ; objects_size_x ; disappearing_object &27e5 68 PLA &27e6 4c 37 28 JMP &2837 ; nothing_was_hit ; not disappeared &27e9 a6 1e LDX &1e ; object_being_pushed &27eb a4 07 LDY &07 ; object_to_consider &27ed 68 PLA ; result of handle_object_movement &27ee 99 e4 6c STA &6ce4,Y ; objects_hit_something &27f1 f0 44 BEQ &2837 ; nothing_was_hit # Was something being hit? &27f3 bd 1c 6c LDA &6c1c,X ; objects_support # Can that something be pushed? &27f6 c9 01 CMP #&01 &27f8 d0 38 BNE &2832 ; object_cannot_be_pushed &27fa 86 07 STX &07 ; object_to_consider # (X = pushed object, Y = pushing object) &27fc a5 8e LDA &8e ; previous_movement_single &27fe 9d 00 6b STA &6b00,X ; objects_movement_xz # If so, set its movement the same as the pushing object &2801 b9 00 05 LDA &0500,Y ; objects_type &2804 c9 53 CMP #&53 ; SPRITE_HOMING_MAGIC # Was it pushed by HOMING_MAGIC? &2806 f0 04 BEQ &280c ; set_horizontal_speed_to_one # If so, it gets pushed with speed 1 &2808 b9 1c 6b LDA &6b1c,Y ; objects_horizontal_speed # Otherwise, it gets the speed of the pushing object &280b 2c a9 01 BIT &01a9 #280c LDA #&01 &280e 9d 1c 6b STA &6b1c,X ; objects_horizontal_speed &2811 b9 00 05 LDA &0500,Y ; objects_type &2814 c9 57 CMP #&57 ; SPRITE_MOVING_BLOCK_X &2816 b0 17 BCS &282f ; is_moving_or_carried_block # Unless the pushing object is a moving block, &2818 c9 0f CMP #&0f ; SPRITE_CHEST &281a d0 0b BNE &2827 ; isn't_chest # Or it is a chest, &281c bd 00 05 LDA &0500,X ; objects_type &281f c9 0f CMP #&0f ; SPRITE_CHEST # pushing either another chest or a ball, &2821 f0 0c BEQ &282f ; is_chest_pushing_chest_or_ball &2823 c9 13 CMP #&13 ; SPRITE_BALL &2825 f0 08 BEQ &282f ; is_chest_pushing_chest_or_ball ; isn't_chest &2827 a9 00 LDA #&00 &2829 99 00 6b STA &6b00,Y ; objects_movement_xz # then stop the pushing object &282c 20 46 24 JSR &2446 ; handle_active_object_movements # and consider what its next move should be ; is_chest_pushing_chest_or_ball ; is_moving_or_carried_block &282f 4c fa 26 JMP &26fa ; update_object_again # Handle the movement for the pushed object too ; object_cannot_be_pushed &2832 b9 00 05 LDA &0500,Y ; objects_type &2835 d0 0b BNE &2842 ; not_player_moving ; nothing_was_hit &2837 c4 7a CPY &7a ; rising_or_falling_object &2839 f0 1a BEQ &2855 ; object_is_animate &283b b9 00 05 LDA &0500,Y ; objects_type &283e c9 0f CMP #&0f ; SPRITE_CHEST &2840 f0 13 BEQ &2855 ; object_is_animate ; not_player_moving &2842 c9 57 CMP #&57 # Is this a moving block? &2844 b0 12 BCS &2858 ; next_object &2846 b9 e4 6c LDA &6ce4,Y ; objects_hit_something # If not, did it hit something? &2849 d0 05 BNE &2850 ; stop_object # If so, stop it &284b b9 1c 6c LDA &6c1c,Y ; objects_support &284e 30 05 BMI &2855 ; object_is_animate ; stop_object &2850 a9 00 LDA #&00 &2852 99 00 6b STA &6b00,Y ; objects_movement_xz # Stop the object unless it is deadly ; object_is_animate &2855 20 46 24 JSR &2446 ; handle_active_object_movements # and consider what its next move should be ; next_object &2858 e6 7b INC &7b ; object_to_update &285a a5 44 LDA &44 ; number_of_objects &285c c5 7b CMP &7b ; object_to_update &285e 90 03 BCC &2863 ; leave &2860 4c f6 26 JMP &26f6 ; update_objects_loop ; leave &2863 60 RTS ; handle_npc_head &2864 e6 22 INC &22 ; object_has_changed &2866 b9 ff 02 LDA &02ff,Y ; objects_position_x - 1 # Copy x and z position from feet &2869 99 00 03 STA &0300,Y ; objects_position_x &286c b9 4f 03 LDA &034f,Y ; objects_position_z - 1 &286f 99 50 03 STA &0350,Y ; objects_position_z &2872 be ff 6a LDX &6aff,Y ; objects_movement_xz - 1 # Consider movement of feet &2875 a9 00 LDA #&00 &2877 e0 03 CPX #&03 ; west/north &2879 90 02 BCC &287d ; facing_forward &287b a9 01 LDA #&01 ; facing_forward &287d 99 70 06 STA &0670,Y ; objects_frame # Set frame from direction of feet &2880 8a TXA &2881 a2 00 LDX #&00 &2883 29 0a AND #&0a ; north/south &2885 f0 02 BEQ &2889 &2887 a2 07 LDX #&07 &2889 8a TXA &288a 99 78 03 STA &0378,Y ; objects_flipped # Flip sprite depending on direction of feet &288d a9 00 LDA #&00 &288f 60 RTS ; leave_marking_object_about_to_disappear &2890 99 28 04 STA &0428,Y ; objects_about_to_disappear ; leave_marking_object_changed &2893 e6 22 INC &22 ; object_has_changed ; leave_with_zero &2895 a9 00 LDA #&00 &2897 60 RTS ; player_feet_routine &2898 20 cb 16 JSR &16cb ; player_movement_and_update &289b a0 00 LDY #&00 &289d 84 07 STY &07 ; object_to_consider &289f a5 22 LDA &22 ; object_has_changed &28a1 f0 f0 BEQ &2893 ; leave_marking_object_changed &28a3 4c 18 29 JMP &2918 ; into_set_object_speeds # Handle movement if player has moved ; is_npc_head &28a6 4c 64 28 JMP &2864 ; handle_npc_head ; leave &28a9 60 RTS ; handle_object_movement ; leaves with -1 if an object is being pushed, 0 if no object being pushed &28aa a9 00 LDA #&00 &28ac 85 22 STA &22 ; object_has_changed &28ae a4 07 LDY &07 ; object_to_consider # Y is original object &28b0 99 c8 03 STA &03c8,Y ; objects_direction # No direction unless object actually moves &28b3 99 7c 04 STA &047c,Y ; objects_induced_direction # No induced direction unless another object acts &28b6 a5 7a LDA &7a ; rising_or_falling_object &28b8 85 5e STA &5e ; previous_rising_or_falling_object # Apparently unused &28ba a6 44 LDX &44 ; number_of_objects &28bc e8 INX # Use next unused slot to store original position &28bd b9 70 06 LDA &0670,Y ; objects_frame &28c0 30 e7 BMI &28a9 ; leave # Leave with -1 if object is hidden &28c2 b9 00 03 LDA &0300,Y ; objects_position_x &28c5 9d 00 03 STA &0300,X ; objects_position_x # Copy position from object prior to movement &28c8 b9 50 03 LDA &0350,Y ; objects_position_z # (only x and z are copied, as these are enough to &28cb 9d 50 03 STA &0350,X ; objects_position_z # determine which slices it occupied subsequently) &28ce b9 a0 03 LDA &03a0,Y ; objects_bytes_per_line_of_sprite &28d1 9d a0 03 STA &03a0,X ; objects_bytes_per_line_of_sprite &28d4 c0 01 CPY #&01 # Is this the player's head? &28d6 f0 bd BEQ &2895 ; leave_with_zero # If so, leave with zero &28d8 90 be BCC &2898 ; player_feet_routine # Is this the player's feet? &28da c0 04 CPY #&04 &28dc b0 05 BCS &28e3 ; not_room_charm # Is this a room charm? &28de b9 86 00 LDA &0086,Y ; room_charms_changed_state # If so, has it just been collected or dropped? &28e1 d0 b0 BNE &2893 ; leave_marking_object_changed # If so, leave with object marked as changed ; not_room_charm &28e3 b9 28 04 LDA &0428,Y ; objects_about_to_disappear # Is the object about to disappear? &28e6 d0 ab BNE &2893 ; leave_marking_object_changed # If so, leave with object marked as changed &28e8 b9 00 05 LDA &0500,Y ; objects_type &28eb c9 56 CMP #&56 ; SPRITE_DISAPPEARED # Is this a disappeared block? &28ed f0 a1 BEQ &2890 ; leave_marking_object_about_to_disappear # If so, mark it as about to disappear &28ef c9 19 CMP #&19 ; SPRITE_GUARD_HEAD_FRONT &28f1 f0 b3 BEQ &28a6 ; is_npc_head &28f3 c9 1b CMP #&1b ; SPRITE_WIZARD_HEAD_FRONT &28f5 f0 af BEQ &28a6 ; is_npc_head &28f7 c9 57 CMP #&57 ; SPRITE_MOVING_BLOCK_X # Handle moving blocks with their own routines &28f9 f0 45 BEQ &2940 ; is_moving_block_x # (mixed up in the following code) &28fb c9 58 CMP #&58 ; SPRITE_MOVING_BLOCK_Z &28fd d0 19 BNE &2918 ; into_set_object_speeds ; ; is_moving_block_z # If this is a MOVING_BLOCK_Z, &28ff b9 50 03 LDA &0350,Y ; objects_position_z &2902 d9 e4 6b CMP &6be4,Y ; objects_maximum_position # Has it reached its maximum z position? &2905 f0 0c BEQ &2913 ; set_moving_east &2907 38 SEC &2908 e9 10 SBC #&10 &290a d9 e4 6b CMP &6be4,Y ; objects_maximum_position # Has it reached its minimum z position? (&10 less) &290d d0 09 BNE &2918 ; no_change_to_objects_movement_xz &290f a9 01 LDA #&01 ; west ; set_moving_east &2911 d0 02 BNE &2915 ; set_movement_xz &2913 a9 04 LDA #&04 ; east # Set moving east or west, then handle movement ; set_movement_xz &2915 99 00 6b STA &6b00,Y ; objects_movement_xz ; ; into_set_object_speeds &2918 c0 00 CPY #&00 &291a d0 04 BNE &2920 ; isn't_player_feet &291c a5 7b LDA &7b ; object_to_update # Is this the player being moved by something else? &291e d0 03 BNE &2923 ; set_speeds ; isn't_player_feet &2920 20 bd 2b JSR &2bbd ; consider_object_y_and_extra_movement # If not, handle the object's vertical movement too ; set_speeds &2923 b9 1c 6b LDA &6b1c,Y ; objects_horizontal_speed &2926 85 1e STA &1e ; speed_z &2928 85 1f STA &1f ; speed_x &292a b9 00 6b LDA &6b00,Y ; objects_movement_xz &292d 99 c8 6c STA &6cc8,Y ; objects_previous_movement_xz &2930 d0 03 BNE &2935 ; is_it_moving_west &2932 99 00 6b STA &6b00,Y ; objects_movement_xz # Apparently unnecessary! ; is_it_moving_west &2935 85 0f STA &0f ; previous_movement_xz &2937 29 01 AND #&01 ; west &2939 85 8e STA &8e ; previous_movement_single &293b d0 1b BNE &2958 ; try_moving_west &293d 4c 0c 2a JMP &2a0c ; is_it_moving_east ; ; is_moving_block_x # If this is a MOVING_BLOCK_X &2940 b9 00 03 LDA &0300,Y ; objects_position_x &2943 d9 e4 6b CMP &6be4,Y ; objects_maximum_position # Has it reached its maximum x position? &2946 f0 0c BEQ &2954 ; set_moving_north &2948 38 SEC &2949 e9 10 SBC #&10 &294b d9 e4 6b CMP &6be4,Y ; objects_maximum_position # Has it reached its minimum x position? (&10 less) &294e d0 c8 BNE &2918 ; into_set_object_speeds &2950 a9 08 LDA #&08 ; south &2952 d0 c1 BNE &2915 ; set_movement_xz ; set_moving_north &2954 a9 02 LDA #&02 ; north # Set moving north or south, then handle movement &2956 d0 bd BNE &2915 ; set_movement_xz ; ; try_moving_west # Is the object moving west? &2958 b9 50 03 LDA &0350,Y ; objects_position_z &295b 85 13 STA &13 ; previous_position_z &295d c5 6a CMP &6a ; room_minimum_z # Is the object already at the west wall? &295f 90 54 BCC &29b5 ; at_west_wall # If so, consider player and doorways &2961 e5 1e SBC &1e ; speed_z &2963 aa TAX &2964 69 00 ADC #&00 &2966 c5 6a CMP &6a ; room_minimum_z # If not, would the move take it beyond the south wall? &2968 90 49 BCC &29b3 ; to_reduce_west_speed_and_retry # If so, see if it can move a little less &296a b9 00 03 LDA &0300,Y ; objects_position_x &296d c9 86 CMP #&86 ; north wall &296f b0 04 BCS &2975 ; trying_to_move_west_in_doorway # If not, is the object in the east or west doorway? &2971 c9 10 CMP #&10 ; south wall &2973 b0 04 BCS &2979 ; not_trying_to_move_west_in_doorway ; trying_to_move_west_in_doorway &2975 e0 48 CPX #&48 ; centre of east/west # If so, don't allow it to move west of door's centre &2977 90 68 BCC &29e1 ; reduce_west_speed_and_retry ; not_trying_to_move_west_in_doorway &2979 8a TXA ; new_position_z ; store_position_z &297a 99 50 03 STA &0350,Y ; objects_position_z # Otherwise, update the object's position &297d 20 ab 25 JSR &25ab ; find_an_object_07_overlaps # X = object hit, if any &2980 d0 05 BNE &2987 ; hit_something_moving_west # Has the object hit something? &2982 a9 01 LDA #&01 ; west # Keep the object moving west if it didn't hit anything &2984 4c 8c 2a JMP &2a8c ; set_object_direction ; hit_something_moving_west &2987 bd 00 05 LDA &0500,X ; objects_type &298a c9 47 CMP #&47 ; SPRITE_GUARD_FEET_FRONT &298c f0 0b BEQ &2999 ; stop_moving_east_or_west # Stop this object if it's hit a GUARD_FEET &298e c6 1e DEC &1e ; speed_z &2990 f0 07 BEQ &2999 ; stop_moving_east_or_west &2992 a5 13 LDA &13 ; previous_position_z # Otherwise, restore previous position &2994 99 50 03 STA &0350,Y ; objects_position_z # and see if it can move a little less &2997 d0 bf BNE &2958 ; try_moving_west ; stop_moving_east_or_west # If not, and the object has hit another &2999 20 f8 25 JSR &25f8 ; find_objects_X_overlaps # Find what the hit object overlaps &299c 99 50 03 STA &0350,Y ; objects_position_z # Restore previous position (A = previous_position_z) &299f a6 4c LDX &4c ; object_number # X = the hit object &29a1 bd 1c 6c LDA &6c1c,X ; objects_support &29a4 c9 01 CMP #&01 &29a6 f0 05 BEQ &29ad ; hit_object_can_be_pushed_west # Can it be pushed? &29a8 20 7e 2d JSR &2d7e ; check_if_object_can_carry # If not, can it carry something? &29ab f0 03 BEQ &29b0 ; hit_object_can_carry ; hit_object_can_be_pushed_west # If the hit object can be pushed, &29ad 4c 0a 26 JMP &260a ; consider_hit_object # consider the implications of this ; hit_object_can_carry &29b0 4c 91 2a JMP &2a91 ; is_it_moving_south # Consider north/south movements if being carried ; to_reduce_west_speed_and_retry &29b3 90 2c BCC &29e1 ; reduce_west_speed_and_retry ; at_west_wall # If the object is at the west wall, &29b5 c0 00 CPY #&00 # if not the player, reduce speed and retry &29b7 d0 28 BNE &29e1 ; reduce_west_speed_and_retry &29b9 c9 10 CMP #&10 # Otherwise, consider the west door &29bb 90 15 BCC &29d2 ; player_beyond_west_wall &29bd f0 02 BEQ &29c1 ; player_at_west_wall &29bf b0 20 BCS &29e1 ; reduce_west_speed_and_retry ; player_at_west_wall &29c1 ad 28 03 LDA &0328 ; player_feet_object_position_y &29c4 c5 69 CMP &69 ; door_height_west # Is the player at the height of the door? &29c6 d0 19 BNE &29e1 ; reduce_west_speed_and_retry # If not, reduce speed and retry &29c8 ad 00 03 LDA &0300 ; player_feet_object_position_x &29cb 20 d9 26 JSR &26d9 ; return_direction_towards_centre_of_door &29ce 30 11 BMI &29e1 ; reduce_west_speed_and_retry # Is the player near but not in the doorway? &29d0 d0 2f BNE &2a01 ; sidestep_north_or_south_towards_door # If so, sidestep towards the doorway ; player_beyond_west_wall &29d2 ad 50 03 LDA &0350 ; player_feet_object_position_z &29d5 38 SEC &29d6 e5 1e SBC &1e ; speed_z &29d8 c9 07 CMP #&07 # Has the player gone through the doorway? &29da b0 9e BCS &297a ; store_position_z &29dc a9 ff LDA #&ff ; west &29de 4c 79 18 JMP &1879 ; change_room # If so, change room ; reduce_west_speed_and_retry &29e1 c6 1e DEC &1e ; speed_z &29e3 f0 10 BEQ &29f5 ; to_stop_object_moving &29e5 4c 58 29 JMP &2958 ; try_moving_west ; check_if_object_can_carry_east &29e8 20 7e 2d JSR &2d7e ; check_if_object_can_carry &29eb d0 08 BNE &29f5 ; to_stop_object_moving &29ed c9 15 CMP #&15 ; SPRITE_GHOST_BACK # Unclear what this does. &29ef f0 04 BEQ &29f5 ; to_stop_object_moving &29f1 c9 17 CMP #&17 ; SPRITE_GHOST_FRONT # Commenting it out makes no difference to GHOSTs &29f3 d0 bb BNE &29b0 ; hit_object_can_carry_east_or_west ; to_stop_object_moving &29f5 4c 97 2b JMP &2b97 ; stop_object_moving ; sidestep_west_or_east_towards_door &29f8 c9 02 CMP #&02 ; north &29fa f0 03 BEQ &29ff ; sidestep_east &29fc a9 01 LDA #&01 ; west &29fe 2c a9 04 BIT &04a9 ; sidestep_east #29ff LDA #&04 ; east ; sidestep_north_or_south_towards_door &2a01 8d 00 6b STA &6b00 ; player_feet_object_movement_xz &2a04 a9 01 LDA #&01 &2a06 8d 1c 6b STA &6b1c ; player_feet_object_horizontal_speed # Sidestep with speed 1 &2a09 4c 23 29 JMP &2923 ; set_speeds # Handle the resulting movement ; is_it_moving_east &2a0c a5 0f LDA &0f ; previous_movement_xz &2a0e 29 04 AND #&04 ; east &2a10 85 8e STA &8e ; previous_movement_single &2a12 f0 7d BEQ &2a91 ; is_it_moving_south # Is the object moving east? ; try_moving_east &2a14 a5 6c LDA &6c ; room_maximum_z &2a16 18 CLC &2a17 69 0a ADC #&0a &2a19 38 SEC &2a1a f9 fc 06 SBC &06fc,Y ; objects_size_z &2a1d 85 14 STA &14 ; maximum_allowable_z_position ; try_moving_east_skipping_calculation &2a1f b9 50 03 LDA &0350,Y ; objects_position_z &2a22 85 13 STA &13 ; previous_position_z &2a24 18 CLC &2a25 65 1e ADC &1e ; speed_z &2a27 c5 14 CMP &14 ; maximum_allowable_z_position &2a29 b0 2c BCS &2a57 ; at_east_wall # Does the move take its end beyond the east wall? &2a2b be 00 03 LDX &0300,Y ; objects_position_x &2a2e e0 86 CPX #&86 ; north wall # Is the object in the north or south doorway? &2a30 b0 04 BCS &2a36 ; trying_to_move_east_in_doorway &2a32 e0 10 CPX #&10 ; south wall &2a34 b0 04 BCS &2a3a ; not_trying_to_move_east_in_doorway ; trying_to_move_east_in_doorway &2a36 c9 4d CMP #&4d ; centre of east/west # If so, don't allow it to move east of door's centre &2a38 b0 46 BCS &2a80 ; reduce_east_speed_and_retry ; not_trying_to_move_east_in_doorway ; store_z_position &2a3a 99 50 03 STA &0350,Y ; objects_position_z # Otherwise, update the object's position &2a3d 20 ab 25 JSR &25ab ; find_an_object_07_overlaps # X = object hit, if any &2a40 f0 48 BEQ &2a8a ; set_object_direction_east # Has the object hit something? &2a42 bd 00 05 LDA &0500,X ; objects_type &2a45 c9 47 CMP #&47 ; SPRITE_GUARD_FEET_FRONT &2a47 f0 0b BEQ &2a54 ; to_stop_moving_east_or_west # Stop this object if it's hit a GUARD_FEET &2a49 c6 1e DEC &1e ; speed_z &2a4b f0 07 BEQ &2a54 ; to_stop_moving_east_or_west &2a4d a5 13 LDA &13 ; previous_position_z # Otherwise, restore previous position &2a4f 99 50 03 STA &0350,Y ; objects_position_z # and see if it can approach a fraction shorter &2a52 d0 cb BNE &2a1f ; try_moving_east_skipping_calculation ; to_stop_moving_east_or_west &2a54 4c 99 29 JMP &2999 ; stop_moving_east_or_west ; at_east_wall # If the object is at the east wall, &2a57 c0 00 CPY #&00 # If not the player, reduce speed and retry &2a59 d0 25 BNE &2a80 ; reduce_east_speed_and_retry &2a5b aa TAX ; new_position_z &2a5c ad 50 03 LDA &0350 ; player_feet_object_position_z &2a5f c9 85 CMP #&85 ; east wall # Otherwise, consider the east door &2a61 f0 02 BEQ &2a65 ; player_at_east_wall &2a63 b0 11 BCS &2a76 ; player_beyond_east_wall ; player_at_east_wall &2a65 ad 28 03 LDA &0328 ; player_feet_object_position_y &2a68 c5 67 CMP &67 ; door_height_east # Is the player at the height of the door? &2a6a d0 14 BNE &2a80 ; reduce_east_speed_and_retry # If not, reduce speed and retry &2a6c ad 00 03 LDA &0300 ; player_feet_object_position_x &2a6f 20 d9 26 JSR &26d9 ; return_direction_towards_centre_of_door &2a72 30 0c BMI &2a80 ; reduce_east_speed_and_retry # Is the player near but not in the doorway? &2a74 d0 8b BNE &2a01 ; sidestep_north_or_south_towards_door # If so, sidestep towards the doorway ; player_beyond_east_wall &2a76 8a TXA &2a77 c9 8d CMP #&8d # Has the player gone through the door? &2a79 90 bf BCC &2a3a ; store_z_position &2a7b a9 01 LDA #&01 ; east &2a7d 4c 79 18 JMP &1879 ; change_room # If so, change room ; reduce_east_speed_and_retry &2a80 c6 1e DEC &1e ; speed_z &2a82 d0 9b BNE &2a1f ; try_moving_east_skipping_calculation &2a84 4c e8 29 JMP &29e8 ; check_if_object_can_carry_east # Consider north/south movements if being carried ; to_is_it_moving_north &2a87 4c 1d 2b JMP &2b1d ; is_it_moving_north ; set_object_direction_east &2a8a a9 04 LDA #&04 ; east ; set_object_direction &2a8c 99 c8 03 STA &03c8,Y ; objects_direction # Note any east / west movement &2a8f e6 22 INC &22 ; object_has_changed # and note the object has changed position ; is_it_moving_south &2a91 a5 0f LDA &0f &2a93 29 08 AND #&08 ; south &2a95 85 8e STA &8e ; previous_movement_single &2a97 f0 ee BEQ &2a87 ; to_is_it_moving_north # Is the object moving south? ; try_moving_south &2a99 b9 00 03 LDA &0300,Y ; objects_position_x &2a9c 85 13 STA &13 ; previous_position_x &2a9e c5 6b CMP &6b ; room_minimum_x # Is the object already at the south wall? &2aa0 90 42 BCC &2ae4 ; at_south_wall # If so, consider player and doorways &2aa2 e5 1f SBC &1f ; speed_x &2aa4 aa TAX ; new_position_x &2aa5 69 00 ADC #&00 &2aa7 c5 6b CMP &6b ; room_minimum_x # If not, would the move take it beyond the south wall? &2aa9 90 65 BCC &2b10 ; reduce_south_speed_and_retry # If so, see if it can move a little less &2aab b9 50 03 LDA &0350,Y ; objects_position_z &2aae c9 86 CMP #&86 ; east wall &2ab0 b0 04 BCS &2ab6 ; trying_to_move_south_in_doorway # If not, is the object in the east or west doorway? &2ab2 c9 10 CMP #&10 ; west wall &2ab4 b0 04 BCS &2aba ; not_trying_to_move_south_in_doorway ; trying_to_move_south_in_doorway &2ab6 e0 48 CPX #&48 ; centre of north/south # If so, don't allow it to move south of door's centre &2ab8 90 56 BCC &2b10 ; reduce_south_speed_and_retry ; not_trying_to_move_south_in_doorway &2aba 8a TXA ; new_position_x ; store_position_x &2abb 99 00 03 STA &0300,Y ; objects_position_x # Otherwise, update the object's position &2abe 20 ab 25 JSR &25ab ; find_an_object_07_overlaps # X = object hit, if any &2ac1 f0 1c BEQ &2adf ; not_hit_something_moving_south # Has the object hit something? &2ac3 bd 00 05 LDA &0500,X ; objects_type &2ac6 c9 47 CMP #&47 ; SPRITE_GUARD_FEET_FRONT &2ac8 f0 0c BEQ &2ad6 ; stop_moving_north_or_south # Stop this object if it's hit a GUARD_FEET &2aca c6 1f DEC &1f ; speed_x &2acc f0 08 BEQ &2ad6 ; stop_moving_north_or_south &2ace a5 13 LDA &13 ; previous_position_x # Otherwise, restore previous position &2ad0 99 00 03 STA &0300,Y ; objects_position_x # and see if it can move a little less &2ad3 4c 99 2a JMP &2a99 ; try_moving_south ; stop_moving_north_or_south # If not, and the object has hit another &2ad6 20 f8 25 JSR &25f8 ; find_objects_X_overlaps # Find what the hit object overlaps &2ad9 99 00 03 STA &0300,Y ; objects_position_x # Restore previous position (A = previous_position_z) &2adc 4c 0a 26 JMP &260a ; consider_hit_object # Consider the implications of what it has hit ; not_hit_something_moving_south &2adf a9 08 LDA #&08 ; south # Keep the object moving south if it didn't hit anything &2ae1 4c 9f 2b JMP &2b9f ; add_to_object_direction ; at_south_wall # If the object is at the south wall, &2ae4 c0 00 CPY #&00 # if not the player, reduce speed and retry &2ae6 d0 28 BNE &2b10 ; reduce_south_speed_and_retry &2ae8 c9 10 CMP #&10 # Otherwise, consider the south door &2aea 90 15 BCC &2b01 ; player_beyond_south_wall &2aec f0 02 BEQ &2af0 ; player_at_south_wall &2aee b0 20 BCS &2b10 ; reduce_south_speed_and_retry ; player_at_south_wall &2af0 ad 28 03 LDA &0328 ; player_feet_object_position_y &2af3 c5 68 CMP &68 ; door_height_south # Is the player at the height of the door? &2af5 d0 19 BNE &2b10 ; reduce_south_speed_and_retry # If not, reduce speed and retry &2af7 ad 50 03 LDA &0350 ; player_feet_object_position_z &2afa 20 d9 26 JSR &26d9 ; return_direction_towards_centre_of_door &2afd 30 11 BMI &2b10 ; reduce_south_speed_and_retry # Is the player near but not in the doorway? &2aff d0 16 BNE &2b17 ; to_sidestep_west_or_east_towards_door # If so, sidestep towards the doorway ; player_beyond_south_wall &2b01 ad 00 03 LDA &0300 ; player_feet_object_position_x &2b04 38 SEC &2b05 e5 1f SBC &1f ; speed_x &2b07 c9 08 CMP #&08 # Has the player gone through the doorway? &2b09 b0 b0 BCS &2abb ; store_position_x &2b0b a9 10 LDA #&10 ; south &2b0d 4c 79 18 JMP &1879 ; change_room # If so, change room ; reduce_south_speed_and_retry &2b10 c6 1f DEC &1f ; speed_x &2b12 d0 85 BNE &2a99 ; try_moving_south &2b14 4c 97 2b JMP &2b97 ; stop_object_moving ; to_sidestep_west_or_east_towards_door &2b17 4c f8 29 JMP &29f8 ; sidestep_west_or_east_towards_door ; unused_leave_with_zero &2b1a a9 00 LDA #&00 # Unused? &2b1c 60 RTS ; is_it_moving_north &2b1d a5 0f LDA &0f &2b1f 29 02 AND #&02 ; north &2b21 85 8e STA &8e ; previous_movement_single &2b23 f0 44 BEQ &2b69 ; to_consider_induced_movement # Is the object moving north? ; try_moving_north &2b25 a5 6d LDA &6d ; room_maximum_x &2b27 18 CLC &2b28 69 0c ADC #&0c &2b2a 38 SEC &2b2b f9 18 07 SBC &0718,Y ; objects_size_x &2b2e 85 14 STA &14 ; maximum_allowable_x_position ; try_moving_north_skipping_calculation &2b30 b9 00 03 LDA &0300,Y ; objects_position_x &2b33 85 13 STA &13 ; previous_position_x &2b35 18 CLC &2b36 65 1f ADC &1f ; speed_x &2b38 c5 14 CMP &14 ; maximum_allowable_x_position &2b3a b0 2f BCS &2b6b ; at_north_wall # Does the move take its end beyond the north wall? &2b3c be 50 03 LDX &0350,Y ; objects_position_z &2b3f e0 86 CPX #&86 ; east wall # Is the object in the east or west doorway? &2b41 b0 04 BCS &2b47 ; trying_to_north_east_in_doorway &2b43 e0 10 CPX #&10 ; west wall &2b45 b0 04 BCS &2b4b ; not_trying_to_north_east_in_doorway ; trying_to_north_east_in_doorway &2b47 c9 4d CMP #&4d ; centre of north/south # If so, don't allow it to move north of door's centre &2b49 b0 48 BCS &2b93 ; reduce_north_speed_and_retry ; not_trying_to_north_east_in_doorway ; store_x_position &2b4b 99 00 03 STA &0300,Y ; objects_position_x # Otherwise, update the object's position &2b4e 20 ab 25 JSR &25ab ; find_an_object_07_overlaps # X = object hit, if any &2b51 f0 4a BEQ &2b9d ; add_to_object_direction_north # Has the object hit something? &2b53 bd 00 05 LDA &0500,X ; objects_type &2b56 c9 47 CMP #&47 ; SPRITE_GUARD_FEET_FRONT &2b58 f0 0c BEQ &2b66 ; to_stop_moving_north_or_south # Stop this object if it's hit a GUARD_FEET &2b5a c6 1f DEC &1f ; speed_x &2b5c f0 08 BEQ &2b66 ; to_stop_moving_north_or_south &2b5e a5 13 LDA &13 ; previous_position_x # Otherwise, restore previous position &2b60 99 00 03 STA &0300,Y ; objects_position_x # and see if it can approach a fraction shorter &2b63 4c 30 2b JMP &2b30 ; try_moving_north_skipping_calculation ; to_stop_moving_north_or_south &2b66 4c d6 2a JMP &2ad6 ; stop_moving_north_or_south ; to_consider_induced_movement &2b69 f0 3c BEQ &2ba7 ; consider_induced_movement ; at_north_wall # If the object is at the north wall, &2b6b c0 00 CPY #&00 # if not the player, reduce speed and retry &2b6d d0 24 BNE &2b93 ; reduce_north_speed_and_retry &2b6f aa TAX ; new_position_x &2b70 a5 13 LDA &13 ; previous_position_x &2b72 c9 85 CMP #&85 # Otherwise, consider the north door &2b74 f0 02 BEQ &2b78 ; player_at_north_wall &2b76 b0 11 BCS &2b89 ; player_beyond_north_wall ; player_at_north_wall &2b78 ad 28 03 LDA &0328 ; player_feet_object_position_y &2b7b c5 66 CMP &66 ; door_height_north # Is the player at the height of the door? &2b7d d0 14 BNE &2b93 ; reduce_north_speed_and_retry # If not, reduce speed and retry &2b7f ad 50 03 LDA &0350 ; player_feet_object_position_z &2b82 20 d9 26 JSR &26d9 ; return_direction_towards_centre_of_door &2b85 30 0c BMI &2b93 ; reduce_north_speed_and_retry # Is the player near but not in the doorway? &2b87 d0 8e BNE &2b17 ; to_sidestep_west_or_east_towards_door # If so, sidestep towards the doorway ; player_beyond_north_wall &2b89 8a TXA ; new_position_x &2b8a c9 8e CMP #&8e # Has the player gone through the doorway? &2b8c 90 bd BCC &2b4b ; store_x_position &2b8e a9 f0 LDA #&f0 ; south &2b90 4c 79 18 JMP &1879 ; change_room # If so, change room ; reduce_north_speed_and_retry &2b93 c6 1e DEC &1e ; speed_z &2b95 d0 99 BNE &2b30 ; try_moving_north_skipping_calculation ; stop_object_moving &2b97 a9 00 LDA #&00 &2b99 99 00 6b STA &6b00,Y ; objects_movement_xz &2b9c 60 RTS ; add_to_object_direction_north &2b9d a9 02 LDA #&02 ; north # Keep the object moving north if it didn't hit anything ; add_to_object_direction &2b9f 59 c8 03 EOR &03c8,Y ; objects_direction # Add any north / south movement &2ba2 99 c8 03 STA &03c8,Y ; objects_direction # to any east / west movement &2ba5 e6 22 INC &22 ; object_has_changed # and note the object has changed position ; consider_induced_movement &2ba7 b9 97 04 LDA &0497,Y ; objects_induced_speed &2baa 85 1e STA &1e ; speed_z &2bac 85 1f STA &1f ; speed_x &2bae be 7c 04 LDX &047c,Y ; objects_induced_direction &2bb1 a9 00 LDA #&00 &2bb3 99 7c 04 STA &047c,Y ; objects_induced_direction &2bb6 8a TXA &2bb7 f0 03 BEQ &2bbc ; leave # Has the object been moved by a moving block? &2bb9 4c 35 29 JMP &2935 ; is_it_moving_west # If so, consider that movement too ; leave &2bbc 60 RTS ; consider_object_y_and_extra_movement &2bbd b9 00 6c LDA &6c00,Y ; objects_vertical_speed &2bc0 85 1e STA &1e ; vertical_speed &2bc2 b9 c8 6b LDA &6bc8,Y ; objects_movement_y &2bc5 f0 05 BEQ &2bcc ; isn't_rising_or_falling &2bc7 10 06 BPL &2bcf ; is_rising &2bc9 4c 6b 2c JMP &2c6b ; is_falling ; isnt_rising_or_falling &2bcc 4c 51 2c JMP &2c51 ; still_isn't_rising_or_falling ; is_rising # If the object is rising, &2bcf b9 28 03 LDA &0328,Y ; objects_position_y &2bd2 85 13 STA &13 ; previous_position_y &2bd4 18 CLC &2bd5 65 1e ADC &1e ; vertical_speed &2bd7 99 28 03 STA &0328,Y ; objects_position_y # Move it upwards &2bda 20 ab 25 JSR &25ab ; find_an_object_07_overlaps # X = object hit, if any &2bdd f0 34 BEQ &2c13 ; rising_object_hasn't_hit_anything # Has it hit something? &2bdf a5 13 LDA &13 ; previous_position_y &2be1 99 28 03 STA &0328,Y ; objects_position_y # If so, undo the movement &2be4 c6 1e DEC &1e ; vertical_speed &2be6 d0 e7 BNE &2bcf ; is_rising # and see if it can rise a little less &2be8 a9 ff LDA #&ff &2bea 99 c8 6b STA &6bc8,Y ; objects_movement_y # If it can't, set it falling &2bed a9 01 LDA #&01 &2bef 99 00 6c STA &6c00,Y ; objects_vertical_speed # with speed 1 &2bf2 c0 00 CPY #&00 &2bf4 d0 0f BNE &2c05 ; is_rising_but_not_feet # Is this the player's feet? &2bf6 e4 7a CPX &7a ; rising_or_falling_object &2bf8 f0 05 BEQ &2bff ; hit_moving_portcullis_or_spiked_ball # Has it hit a moving portcullis or spiked ball? &2bfa bd 1c 6c LDA &6c1c,X ; objects_support &2bfd 10 11 BPL &2c10 ; leave # Or something else deadly? ; hit_moving_portcullis &2bff 20 bb 26 JSR &26bb ; kill_player # If so, kill the player for jumping up into it &2c02 a9 00 LDA #&00 &2c04 60 RTS ; is_rising_but_not_feet &2c05 e0 00 CPX #&00 &2c07 d0 03 BNE &2c0c ; not_target_feet # Has the object come up into the player's feet? &2c09 20 bb 26 JSR &26bb ; kill_player # If so, kill the player ; not_target_feet &2c0c c4 7a CPY &7a ; rising_or_falling_object # Is this the moving portcullis? &2c0e f0 29 BEQ &2c39 ; stop_rising_or_falling_object # If so, stop it ; leave &2c10 a9 00 LDA #&00 &2c12 60 RTS ; rising_object_hasn't_hit_anything &2c13 e6 22 INC &22 ; object_has_changed # Note the object has changed position &2c15 c4 7a CPY &7a ; rising_or_falling_object # Is this the moving portcullis? &2c17 f0 13 BEQ &2c2c ; is_rising_portcullis &2c19 b9 28 03 LDA &0328,Y ; objects_position_y &2c1c d9 e4 6b CMP &6be4,Y ; objects_maximum_position # If not, has it reached its maximum height? &2c1f 90 ef BCC &2c10 ; leave &2c21 a9 ff LDA #&ff &2c23 99 c8 6b STA &6bc8,Y ; objects_movement_y # If so, move it down a fraction &2c26 a9 00 LDA #&00 &2c28 99 00 6c STA &6c00,Y ; objects_vertical_speed # and stop its motion &2c2b 60 RTS ; is_rising_portcullis # If this is the moving portcullis? &2c2c b9 28 03 LDA &0328,Y ; objects_position_y &2c2f c9 18 CMP #&18 # Has it reached its maximum height? &2c31 d0 dd BNE &2c10 ; leave &2c33 a9 06 LDA #&06 &2c35 85 92 STA &92 ; portcullis_grace # If so, prevent it from falling again immediately &2c37 d0 0c BNE &2c45 ; no_sound ; stop_rising_or_falling_object &2c39 b9 00 05 LDA &0500,Y ; objects_type &2c3c c9 0c CMP #&0c ; SPRITE_SPIKED_BALL &2c3e f0 05 BEQ &2c45 ; no_sound &2c40 a2 98 LDX #&98 ; sound_10 &2c42 20 e7 07 JSR &07e7 ; play_sound # Play a sound when the portcullis hits something ; no_sound &2c45 a9 ff LDA #&ff &2c47 85 7a STA &7a ; rising_or_falling_object # Forget that the portcullis or spiked ball was moving &2c49 a4 07 LDY &07 ; object_to_consider ; stop_movement &2c4b a9 00 LDA #&00 &2c4d 99 c8 6b STA &6bc8,Y ; objects_movement_y # Stop the object's vertical movement &2c50 60 RTS ; still_isn't_rising_or_falling # If the object is neither rising nor falling, &2c51 b9 00 05 LDA &0500,Y ; objects_type &2c54 c9 59 CMP #&59 ; SPRITE_CARRIED_BLOCK &2c56 f0 07 BEQ &2c5f ; is_carried_block # Is this a CARRIED_BLOCK? &2c58 b9 1c 6c LDA &6c1c,Y ; objects_support &2c5b c9 01 CMP #&01 &2c5d d0 b1 BNE &2c10 ; leave # or a TABLE or CHEST? ; is_carried_block &2c5f a9 01 LDA #&01 &2c61 99 00 6c STA &6c00,Y ; objects_vertical_speed # If so, set it to fall in the absence of support &2c64 85 1e STA &1e ; vertical_speed # with speed 1 &2c66 a9 ff LDA #&ff &2c68 99 c8 6b STA &6bc8,Y ; objects_movement_y ; is_falling # If the object is falling, &2c6b b9 28 03 LDA &0328,Y ; objects_position_y &2c6e 85 13 STA &13 ; previous_position_y &2c70 38 SEC &2c71 e5 1e SBC &1e ; vertical_speed &2c73 90 1d BCC &2c92 ; has_hit_floor # If it wouldn't hit the floor in doing so, then &2c75 99 28 03 STA &0328,Y ; objects_position_y # Move it downwards &2c78 20 ab 25 JSR &25ab ; find_an_object_07_overlaps # X = object hit, if any &2c7b f0 22 BEQ &2c9f ; falling_object_hasn't_hit_anything # Has it hit something? &2c7d c6 1e DEC &1e ; vertical_speed &2c7f f0 08 BEQ &2c89 ; no_longer_falling &2c81 a5 13 LDA &13 ; previous_position_y &2c83 99 28 03 STA &0328,Y ; objects_position_y # If so, undo the movement &2c86 4c 6b 2c JMP &2c6b ; is_falling # and see if it can move a little less ; no_longer_falling &2c89 20 f8 25 JSR &25f8 ; find_objects_X_overlaps &2c8c 99 28 03 STA &0328,Y ; objects_position_y # Restore previous position &2c8f 4c c0 2c JMP &2cc0 ; falling_object_has_hit_something ; has_hit_floor # Has it hit the floor? &2c92 c6 1e DEC &1e ; vertical_speed &2c94 d0 d5 BNE &2c6b # If so, see if it can move a little less ; stop_object &2c96 c4 7a CPY &7a ; rising_or_falling_object &2c98 f0 9f BEQ &2c39 ; stop_rising_or_falling_object &2c9a d0 af BNE &2c4b ; stop_movement # Otherwise, stop its vertical movement and leave ; leave &2c9c a9 00 LDA #&00 &2c9e 60 RTS ; falling_object_hasn't_hit_anything # If the falling object hasn't hit anything, &2c9f 98 TYA &2ca0 aa TAX # X = falling object &2ca1 fe 00 6c INC &6c00,X ; objects_vertical_speed # Make it fall faster &2ca4 fe 00 6c INC &6c00,X ; objects_vertical_speed &2ca7 e6 22 INC &22 ; object_has_changed # Note the object has changed position &2ca9 bd 00 05 LDA &0500,X ; objects_type &2cac c9 59 CMP #&59 ; SPRITE_CARRIED_BLOCK &2cae f0 0a BEQ &2cba ; falling_carried_block &2cb0 c9 54 CMP #&54 ; SPRITE_DESCENDING_BLOCK &2cb2 90 e8 BCC &2c9c ; leave &2cb4 a9 00 LDA #&00 &2cb6 99 c8 6b STA &6bc8,Y ; objects_movement_y # A descending block only falls when actively pushed &2cb9 60 RTS ; falling_carried_block &2cba a9 00 LDA #&00 &2cbc 99 00 6b STA &6b00,Y ; objects_movement_xz # A falling carried block ceases to be carried &2cbf 60 RTS ; falling_object_has_hit_something # If the falling object has hit something, &2cc0 a9 00 LDA #&00 &2cc2 85 7f STA &7f ; player_has_touched_deadly_thing &2cc4 85 4c STA &4c ; object_is_supported &2cc6 85 4b STA &4b ; block_has_disappeared &2cc8 85 73 STA &73 ; falling_charm_has_hit_player &2cca a6 44 LDX &44 ; number_of_objects # Looping over all objects, ; object_loop &2ccc bd 60 04 LDA &0460,X ; objects_overlap_results # For each object, &2ccf f0 61 BEQ &2d32 ; next_object # Does it overlap the falling one? &2cd1 e0 00 CPX #&00 &2cd3 d0 06 BNE &2cdb ; isn't_charm_falling_on_player &2cd5 c0 04 CPY #&04 # Y = falling object &2cd7 90 02 BCC &2cdb ; isn't_charm_falling_on_player # Has a room charm fallen on the player? &2cd9 e6 73 INC &73 ; falling_charm_has_hit_player # If so, note this fact for later ; isn't_charm_falling_on_player &2cdb bd 00 05 LDA &0500,X ; objects_type &2cde c0 00 CPY #&00 &2ce0 d0 08 BNE &2cea ; isn't_life_falling_on_player &2ce2 c9 26 CMP #&26 ; SPRITE_CHARM_LIFE &2ce4 d0 04 BNE &2cea ; isn't_life_falling_on_player # Has an extra life fallen on the player? &2ce6 85 7e STA &7e ; trigger_spiked_ball_falling # If so, trigger other falling objects &2ce8 f0 19 BEQ &2d03 ; gain_extra_life # and gain an extra life ; isn't_head_and_life &2cea c9 54 CMP #&54 ; SPRITE_DESCENDING_BLOCK &2cec d0 0c BNE &2cfa ; isn't_descending_block # Is something supported by a DESCENDING_BLOCK? &2cee a9 ff LDA #&ff &2cf0 9d c8 6b STA &6bc8,X ; objects_movement_y # If so, make the latter fall with speed 1 &2cf3 a9 01 LDA #&01 &2cf5 9d 00 6c STA &6c00,X ; objects_vertical_speed &2cf8 d0 14 BNE &2d0e ; isn't_disappearing_block ; isn't_descending_block &2cfa c9 55 CMP #&55 ; SPRITE_DISAPPEARING_BLOCK # Is something supported by a DISAPPEARING_BLOCK? &2cfc d0 10 BNE &2d0e ; isn't_disappearing_block &2cfe a5 4b LDA &4b ; block_has_disappeared &2d00 d0 30 BNE &2d32 ; next_object # and a block hasn't already disappeared this turn? &2d02 2c e6 8a BIT &8ae6 ; gain_extra_life #2d03 INC &8a ; life_counter &2d05 fe 28 04 INC &0428,X ; objects_about_to_disappear # If so, mark the block as about to disappear &2d08 e6 4b INC &4b ; block_has_disappeared &2d0a e6 4c INC &4c ; object_is_supported # and note the object is (temporarily) supported &2d0c 10 24 BPL &2d32 ; next_object ; isn't_disappearing_block &2d0e c9 57 CMP #&57 ; SPRITE_MOVING_BLOCK_X # Is something supported by a moving block? &2d10 b0 14 BCS &2d26 ; add_induced_movement # If so, add induced movement &2d12 48 PHA &2d13 bd 1c 6c LDA &6c1c,X ; objects_support &2d16 30 09 BMI &2d21 ; is_deadly # (checking first that it isn't deadly) &2d18 68 PLA &2d19 c9 53 CMP #&53 ; SPRITE_HOMING_MAGIC # Is something supported by HOMING_MAGIC? &2d1b f0 09 BEQ &2d26 ; add_induced_movement # If so, add induced movement &2d1d e6 4c INC &4c ; object_is_supported # Otherwise, note the object is supported &2d1f d0 11 BNE &2d32 ; next_object ; is_deadly # Note contact with anything deadly &2d21 a9 ff LDA #&ff &2d23 85 7f STA &7f ; player_has_touched_deadly_thing &2d25 68 PLA ; is_moving_block &2d26 bd c8 03 LDA &03c8,X ; objects_direction &2d29 99 7c 04 STA &047c,Y ; objects_induced_direction &2d2c bd 1c 6b LDA &6b1c,X ; objects_horizontal_speed &2d2f 99 97 04 STA &0497,Y ; objects_induced_speed ; next_object &2d32 ca DEX &2d33 10 97 BPL &2ccc ; object_loop &2d35 c4 7a CPY &7a ; rising_or_falling_object &2d37 f0 19 BEQ &2d52 ; is_falling_ball_or_portcullis &2d39 b9 00 05 LDA &0500,Y ; objects_type &2d3c c9 59 CMP #&59 ; SPRITE_CARRIED_BLOCK # Is this a CARRIED_BLOCK? &2d3e d0 0e BNE &2d4e ; not_carried_block &2d40 b9 7c 04 LDA &047c,Y ; objects_induced_direction &2d43 99 00 6b STA &6b00,Y ; objects_movement_xz # Give it movement from whatever is carrying it &2d46 b9 97 04 LDA &0497,Y ; objects_induced_speed &2d49 99 1c 6b STA &6b1c,Y ; objects_horizontal_speed &2d4c e6 4c INC &4c ; object_is_supported ; not_carried_block &2d4e a5 4c LDA &4c ; object_is_supported &2d50 f0 05 BEQ &2d57 ; object_isn't_moved_by_something # If the object is supported by something else, ; is_falling_ball_or_portcullis # or it is the moving portcullis or spiked ball, &2d52 a9 00 LDA #&00 &2d54 99 7c 04 STA &047c,Y ; objects_induced_direction # then remove any induced movement ; object_isn't_moved_by_something &2d57 a5 4b LDA &4b ; block_has_disappeared &2d59 f0 05 BEQ &2d60 ; no_sound # If a block has disappeared, &2d5b a2 a0 LDX #&a0 ; sound_11 &2d5d 20 e7 07 JSR &07e7 ; play_sound # play a sound ; no_sound &2d60 a4 07 LDY &07 ; object_to_consider &2d62 d0 10 BNE &2d74 ; no_deadly_contact &2d64 a5 7f LDA &7f ; player_has_touched_deadly_thing &2d66 f0 0c BEQ &2d74 ; no_deadly_contact &2d68 a5 4c LDA &4c ; object_is_supported &2d6a d0 08 BNE &2d74 ; no_deadly_contact &2d6c 20 bb 26 JSR &26bb ; kill_player # Kill the player &2d6f 68 PLA # Skip the rest of handle_object_movement &2d70 68 PLA &2d71 a9 00 LDA #&00 &2d73 60 RTS ; no_deadly_contact &2d74 a5 73 LDA &73 ; falling_charm_has_hit_player # Has a charm fallen on the player? &2d76 f0 03 BEQ &2d7b ; no_falling_charm &2d78 20 bb 26 JSR &26bb ; kill_player # If so, kill the player ; no_falling_charm &2d7b 4c 96 2c JMP &2c96 ; stop_object # Stop the object falling further ; check_if_object_can_carry &2d7e b9 00 05 LDA &0500,Y ; objects_type &2d81 c9 53 CMP #&53 ; SPRITE_HOMING_MAGIC &2d83 f0 10 BEQ &2d95 &2d85 c9 15 CMP #&15 ; SPRITE_GHOST_BACK &2d87 f0 0c BEQ &2d95 &2d89 c9 17 CMP #&17 ; SPRITE_GHOST_FRONT &2d8b f0 08 BEQ &2d95 &2d8d c9 13 CMP #&13 ; SPRITE_BALL &2d8f f0 04 BEQ &2d95 &2d91 c9 59 CMP #&59 ; SPRITE_CARRIED_BLOCK &2d93 f0 00 BEQ &2d95 &2d95 60 RTS ; background_objects_position_x &2d96 10 10 1f 28 68 80 90 90 90 90 90 90 ; +&00 square rooms &2da2 28 28 38 60 60 70 70 70 70 70 70 70 ; +&0c east west rooms &2dae 10 10 10 28 24 50 68 80 80 90 90 90 ; +&18 north south rooms &2dba 10 20 30 60 70 80 90 90 90 90 90 90 ; +&24 outside rooms &2dc6 40 50 ; outside rooms without west door &2dc8 90 90 ; outside rooms without north door ; background_objects_position_y &2dca 02 2e 1f 3c 1a 02 1c f9 29 12 25 f9 &2dd6 03 2f 3c 02 2b 31 0c f8 2b fa 26 52 &2de2 02 2e 5a 42 16 08 32 02 2b 25 fb 27 &2dee 05 04 03 05 04 04 fc fc fc fc fc fc &2dfa 04 04 &2dfc fc fc ; background_objects_position_z &2dfe 10 10 10 10 10 10 28 20 50 68 80 80 &2e0a 10 10 10 10 10 20 28 38 68 80 80 80 &2e16 30 30 30 30 30 30 30 30 30 40 68 68 &2e22 10 10 10 10 10 10 10 20 30 60 70 80 &2e2e 10 10 &2e30 40 50 ; background_objects_position_data &2e32 20 20 31 31 3b 42 33 39 39 39 28 28 &2e3e 20 20 31 42 42 39 39 39 33 28 28 28 &2e4a 20 20 20 31 31 31 3b 42 42 39 28 28 &2e56 24 25 24 25 24 25 2c 2d 2c 2c 2d 2c &2e62 25 24 &2e64 2d 2c ; sprite_y_subtraction &2e66 00 00 00 00 00 00 09 08 07 0d 00 07 07 07 06 09 &2e76 0a 06 09 03 03 03 03 03 03 04 04 08 08 03 03 03 &2e86 03 03 03 03 03 03 03 03 05 03 02 03 02 03 04 03 &2e96 02 02 02 03 04 03 04 06 04 03 04 03 02 02 02 02 &2ea6 02 01 03 01 01 ff 01 03 05 03 02 03 02 03 04 03 &2eb6 02 02 02 03 07 07 03 07 07 07 ; sprite_address_table &2ec0 c2 50 1e 51 60 51 18 52 48 52 a4 52 36 31 d2 31 &2ed0 1a 32 7a 32 c2 30 ee 32 5e 33 c2 33 32 34 b2 34 &2ee0 26 35 be 35 06 36 84 36 bd 36 f3 36 2c 37 65 37 &2ef0 9b 37 d4 37 19 38 5e 38 d3 38 36 39 56 39 76 39 &2f00 ac 39 e8 39 30 3a 6f 3a b1 3a f6 3a 38 3b 92 3b &2f10 ce 3b 92 3b 10 3c 49 3c 10 3c 75 3d 23 3e 75 3d &2f20 b1 3d ea 3d b1 3d 65 3e cb 3e 65 3e 10 3f 55 3f &2f30 10 3f a0 3f 75 40 a0 3f 03 40 3c 40 03 40 85 3c &2f40 ee 3c 06 36 b4 40 6b 3b 51 3d a7 3e dc 3f 92 3b &2f50 ce 3b 92 3b 10 3c 49 3c 10 3c 75 3d 23 3e 75 3d &2f60 b1 3d ea 3d b1 3d b4 40 ee 32 ee 32 b4 40 ee 32 &2f70 ee 32 ee 32 ; sprite_lines_table &2f74 2e 16 2e 10 2e 2e 34 24 30 3a 00 1c 19 1c 20 1d &2f94 26 18 2a 13 12 13 13 12 13 17 17 27 21 10 10 12 &2fa4 14 18 15 16 17 16 11 14 16 14 13 14 13 14 16 14 &2fb4 13 13 13 16 17 16 17 19 17 14 15 14 13 13 13 23 &2fc4 21 2a 18 0d 0c 0c 0d 0b 0d 0b 0b 0c 0b 0c 0d 0c &2fd4 0c 0c 0c 18 1c 1c 18 1c 1c 1c ; overlap_lookup_table &2fce 00 00 00 00 00 00 00 00 00 &2fd7 00 01 01 00 ff 01 00 00 00 &2fe0 00 01 01 00 01 01 00 00 00 ; o= b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 &2fe9 0b 0b 0b 0b 0b 17 0b 1e 0b 0b 0b 0b 0b 0b 01 01 01 01 0b 0b 1e 1e 1e 16 0b 0b 0b 0b 0b 0b ; object_type_size_y &3007 0f 0f 0f 13 0b 0e 0b 01 0f 0f 0b 0b 0b 0b 0a 0a 0a 0a 09 09 0f 0f 01 0a 0a 0f 0f 0f 0f 0f ; object_type_size_x &3025 0f 0f 0f 0b 11 0f 0b 0f 0f 0f 0b 0b 0b 0b 0a 0a 0a 0a 09 09 01 01 0f 0a 0a 0f 0f 0f 0f 0f ; object_type_size_z &3043 00 ff ff 01 01 00 ff 00 ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 ff 00 00 00 00 00 00 ; object_type_support ; initial_charms_position_room ; 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 &3061 44 03 00 22 77 0d 4a 7d 20 d7 4b f4 26 d2 84 8a &3071 58 18 09 fa 9d b0 f0 c8 06 ae 0f ff 2f b2 9f f8 ; initial_charms_position_packed &3081 73 7c 1d e3 6c 1e 70 9c 8f 6c 72 6f 97 9c 1c ff &3091 cb 73 fc 70 8e 6c 00 4f 6f 6c d8 8c 6f 8f fc 6f ; room_map ; one bit per room, set if room exists ; 128 actual rooms ; 0123456789abcdef &30a1 f3 c7 ; 11110011 11000111 00 ####..####...### &30a3 b3 c5 ; 10110011 11000101 10 #.##..####...#.# N &30a5 f3 c7 ; 11110011 11000111 20 ####..####...### | &30a7 11 01 ; 00010001 00000001 30 ...#...#.......# W-+-E &30a9 19 31 ; 00011001 00110001 40 ...##..#..##...# | &30aa 11 b1 ; 00010001 10110001 50 ...#...##.##...# S &30ac 11 91 ; 00010001 10010001 60 ...#...##..#...# &30ae 1f ff ; 00011111 11111111 70 ...############# &30b1 0f e0 ; 00001111 11100000 80 ....#######..... &30b3 09 bf ; 00001001 10111111 90 ....#..##.###### -10 &30b5 09 83 ; 00001001 10000011 a0 ....#..##.....## &30b7 ff 81 ; 11111111 10000001 b0 #########......# | &30b9 89 81 ; 10001001 10000001 c0 #...#..##......# -1 -+- +1 &30ba e9 87 ; 11101001 10000111 d0 ###.#..##....### | &30bc a8 85 ; 10101000 10000101 e0 #.#.#...#....#.# &30be f8 ff ; 11111000 11111111 f0 #####...######## +10 ; string_table &30c1 58 58 17 11 1d 15 f0 1f 26 15 22 ; "GAME OVER" &30cc 30 5d 13 18 11 22 1d 23 f0 13 1f 1c 1c 15 13 24 15 14 f0 00 00 ; "CHARMS COLLECTED 00" &30e1 50 66 23 20 11 13 15 1f 64 5f f0 60 5c 51 69 ; "SPACE to play" &30f0 58 56 1b 1e 19 17 18 24 f0 1c 1f 22 15 ; "KNIGHT LORE" &30fd 30 5b 24 18 15 f0 23 20 15 1c 1c f0 18 11 23 ff 12 22 1f 1b 15 1e "THE SPELL HAS BROKEN" &3113 50 5d 29 1f 25 f0 11 22 15 f0 16 22 15 15 "YOU ARE FREE" ; unused &3121 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &3130 00 00 00 00 00 00 Sprites ======= ; sprite &00: 2 bytes x 46 lines (offset 0), data @ &50c2 - &511d; SPRITE_BRICKWORK_SIDE ; sprite &01: 3 bytes x 22 lines (offset 0), data @ &511e - &515f; SPRITE_BRICKWORK_FIVE_BRICKS ; sprite &02: 4 bytes x 46 lines (offset 0), data @ &5160 - &5217; SPRITE_BRICKWORK_CORNER ; sprite &03: 3 bytes x 16 lines (offset 0), data @ &5218 - &5247; SPRITE_BRICKWORK_THREE_BRICKS ; sprite &04: 2 bytes x 46 lines (offset 0), data @ &5248 - &52a3; SPRITE_TREES_ONE ; sprite &05: 2 bytes x 46 lines (offset 0), data @ &52a4 - &52ff; SPRITE_TREES_TWO ; sprite &06: 3 bytes x 52 lines (offset 9), data @ &3136 - &31d1; SPRITE_ARCH_RIGHT ; sprite &07: 2 bytes x 36 lines (offset 8), data @ &31d2 - &3219; SPRITE_ARCH_LEFT ; sprite &08: 2 bytes x 48 lines (offset 7), data @ &321a - &3279; SPRITE_TREE_ARCH_LEFT ; sprite &09: 2 bytes x 58 lines (offset 13), data @ &327a - &32ed; SPRITE_TREE_ARCH_RIGHT ; sprite &0a: 0 bytes x 0 lines (offset 0); SPRITE_UNUSED ; sprite &0b: 4 bytes x 28 lines (offset 7), data @ &32ee - &335d, mask @ &42b4 - &4323; SPRITE_BLOCK ; sprite &0c: 4 bytes x 25 lines (offset 7), data @ &335e - &33c1, mask @ &4324 - &4387; SPRITE_SPIKED_BALL ; sprite &0d: 4 bytes x 28 lines (offset 7), data @ &33c2 - &3431, mask @ &4388 - &43f7; SPRITE_SPIKES ; sprite &0e: 4 bytes x 32 lines (offset 6), data @ &3432 - &34b1, mask @ &43f8 - &4477; SPRITE_TABLE ; sprite &0f: 4 bytes x 29 lines (offset 9), data @ &34b2 - &3525, mask @ &4478 - &44eb; SPRITE_CHEST ; sprite &10: 4 bytes x 38 lines (offset 10), data @ &3526 - &35bd, mask @ &44ec - &4583; SPRITE_CAULDRON ; sprite &11: 3 bytes x 24 lines (offset 6), data @ &35be - &3605, mask @ &4584 - &45cb; SPRITE_GARGOYLE ; sprite &12: 3 bytes x 42 lines (offset 9), data @ &3606 - &3683, mask @ &45cc - &4649; SPRITE_PORTCULLIS_X ; sprite &13: 3 bytes x 19 lines (offset 3), data @ &3684 - &36bc, mask @ &464a - &4682; SPRITE_BALL ; sprite &14: 3 bytes x 18 lines (offset 3), data @ &36bd - &36f2, mask @ &4683 - &46b8; SPRITE_BALL_FRAME_2 ; sprite &15: 3 bytes x 19 lines (offset 3), data @ &36f3 - &372b, mask @ &46b9 - &46f1; SPRITE_GHOST_BACK ; sprite &16: 3 bytes x 19 lines (offset 3), data @ &372c - &3764, mask @ &46f2 - &472a; SPRITE_GHOST_BACK_FRAME_2 ; sprite &17: 3 bytes x 18 lines (offset 3), data @ &3765 - &379a, mask @ &472b - &4760; SPRITE_GHOST_FRONT ; sprite &18: 3 bytes x 19 lines (offset 3), data @ &379b - &37d3, mask @ &4761 - &4799; SPRITE_GHOST_FRONT_FRAME_2 ; sprite &19: 3 bytes x 23 lines (offset 4), data @ &37d4 - &3818, mask @ &479a - &47de; SPRITE_GUARD_HEAD_FRONT ; sprite &1a: 3 bytes x 23 lines (offset 4), data @ &3819 - &385d, mask @ &47df - &4823; SPRITE_GUARD_HEAD_BACK ; sprite &1b: 3 bytes x 39 lines (offset 8), data @ &385e - &38d2, mask @ &4824 - &4898; SPRITE_WIZARD_HEAD_FRONT ; sprite &1c: 3 bytes x 33 lines (offset 8), data @ &38d3 - &3935, mask @ &4899 - &48fb; SPRITE_WIZARD_HEAD_BACK ; sprite &1d: 2 bytes x 16 lines (offset 3), data @ &3936 - &3955, mask @ &48fc - &491b; SPRITE_FIRE ; sprite &1e: 2 bytes x 16 lines (offset 3), data @ &3956 - &3975, mask @ &491c - &493b; SPRITE_FIRE_FRAME_2 ; sprite &1f: 3 bytes x 18 lines (offset 3), data @ &3976 - &39ab, mask @ &493c - &4971; SPRITE_CHARM_CUP ; sprite &20: 3 bytes x 20 lines (offset 3), data @ &39ac - &39e7, mask @ &4972 - &49ad; SPRITE_CHARM_GEM ; sprite &21: 3 bytes x 24 lines (offset 3), data @ &39e8 - &3a2f, mask @ &49ae - &49f5; SPRITE_CHARM_BOTTOM ; sprite &22: 3 bytes x 21 lines (offset 3), data @ &3a30 - &3a6e, mask @ &49f6 - &4a34; SPRITE_CHARM_BOOT ; sprite &23: 3 bytes x 22 lines (offset 3), data @ &3a6f - &3ab0, mask @ &4a35 - &4a76; SPRITE_CHARM_CRYSTAL_BALL ; sprite &24: 3 bytes x 23 lines (offset 3), data @ &3ab1 - &3af5, mask @ &4a77 - &4abb; SPRITE_CHARM_CHALICE ; sprite &25: 3 bytes x 22 lines (offset 3), data @ &3af6 - &3b37, mask @ &4abc - &4afd; SPRITE_CHARM_POISON ; sprite &26: 3 bytes x 17 lines (offset 3), data @ &3b38 - &3b6a, mask @ &4afe - &4b30; SPRITE_CHARM_LIFE ; sprite &27: 3 bytes x 20 lines (offset 3), data @ &3b92 - &3bcd, mask @ &4b58 - &4b92; SPRITE_MAN_FEET_FRONT ; sprite &28: 3 bytes x 22 lines (offset 5), data @ &3bce - &3c0f, mask @ &4b94 - &4bd5; SPRITE_MAN_FEET_FRONT_FRAME_2 ; sprite &29: 3 bytes x 20 lines (offset 3), data @ &3b92 - &3bcd, mask @ &4b58 - &4b93; SPRITE_MAN_FEET_FRONT_FRAME_3 ; sprite &2a: 3 bytes x 19 lines (offset 2), data @ &3c10 - &3c48, mask @ &4bd6 - &4c0e; SPRITE_MAN_FEET_FRONT_FRAME_4 ; sprite &2b: 3 bytes x 20 lines (offset 3), data @ &3c49 - &3c84, mask @ &4c0f - &4c4a; SPRITE_MAN_FEET_FRONT_FRAME_5 ; sprite &2c: 3 bytes x 19 lines (offset 2), data @ &3c10 - &3c48, mask @ &4bd6 - &4c0e; SPRITE_MAN_FEET_FRONT_FRAME_6 ; sprite &2d: 3 bytes x 20 lines (offset 3), data @ &3d75 - &3db0, mask @ &4d3b - &4d76; SPRITE_MAN_FEET_BACK ; sprite &2e: 3 bytes x 22 lines (offset 4), data @ &3e23 - &3e64, mask @ &4de9 - &4e2a; SPRITE_MAN_FEET_BACK_FRAME_2 ; sprite &2f: 3 bytes x 20 lines (offset 3), data @ &3d75 - &3db0, mask @ &4d3b - &4d76; SPRITE_MAN_FEET_BACK_FRAME_3 ; sprite &30: 3 bytes x 19 lines (offset 2), data @ &3db1 - &3dea, mask @ &4d77 - &4daf; SPRITE_MAN_FEET_BACK_FRAME_4 ; sprite &31: 3 bytes x 19 lines (offset 2), data @ &3dea - &3e22, mask @ &4db0 - &4de8; SPRITE_MAN_FEET_BACK_FRAME_5 ; sprite &32: 3 bytes x 19 lines (offset 2), data @ &3db1 - &3dea, mask @ &4d77 - &4daf; SPRITE_MAN_FEET_BACK_FRAME_6 ; sprite &33: 3 bytes x 22 lines (offset 3), data @ &3e65 - &3ea6, mask @ &4e2b - &4e6c; SPRITE_WOLF_FEET_FRONT ; sprite &34: 3 bytes x 23 lines (offset 4), data @ &3ecb - &3f0f, mask @ &4e91 - &4ed5; SPRITE_WOLF_FEET_FRONT_FRAME_2 ; sprite &35: 3 bytes x 22 lines (offset 3), data @ &3e65 - &3ea6, mask @ &4e2b - &4e6c; SPRITE_WOLF_FEET_FRONT_FRAME_3 ; sprite &36: 3 bytes x 23 lines (offset 4), data @ &3f10 - &3f54, mask @ &4ed6 - &4f1a; SPRITE_WOLF_FEET_FRONT_FRAME_4 ; sprite &37: 3 bytes x 25 lines (offset 6), data @ &3f55 - &3f9f, mask @ &4f1b - &4f65; SPRITE_WOLF_FEET_FRONT_FRAME_5 ; sprite &38: 3 bytes x 23 lines (offset 4), data @ &3f10 - &3f54, mask @ &4ed6 - &4f1a; SPRITE_WOLF_FEET_FRONT_FRAME_6 ; sprite &39: 3 bytes x 20 lines (offset 3), data @ &3fa0 - &3fdb, mask @ &4f66 - &4fa1; SPRITE_WOLF_FEET_BACK ; sprite &3a: 3 bytes x 21 lines (offset 4), data @ &4075 - &40b3, mask @ &503b - &5079; SPRITE_WOLF_FEET_BACK_FRAME_2 ; sprite &3b: 3 bytes x 20 lines (offset 3), data @ &3fa0 - &3fdb, mask @ &4f66 - &4fa1; SPRITE_WOLF_FEET_BACK_FRAME_3 ; sprite &3c: 3 bytes x 19 lines (offset 2), data @ &4003 - &403b, mask @ &4fc9 - &5001; SPRITE_WOLF_FEET_BACK_FRAME_4 ; sprite &3d: 3 bytes x 19 lines (offset 2), data @ &403c - &4074, mask @ &5002 - &503a; SPRITE_WOLF_FEET_BACK_FRAME_5 ; sprite &3e: 3 bytes x 19 lines (offset 2), data @ &4003 - &403b, mask @ &4fc9 - &5001; SPRITE_WOLF_FEET_BACK_FRAME_6 ; sprite &3f: 3 bytes x 35 lines (offset 2), data @ &3c85 - &3ced, mask @ &4c4b - &4cb3; SPRITE_SPASMING_WOLF ; sprite &40: 3 bytes x 33 lines (offset 2), data @ &3cee - &3d50, mask @ &4cb4 - &4d16; SPRITE_SPASMING_MAN ; sprite &41: 3 bytes x 42 lines (offset 1), data @ &3606 - &3683, mask @ &45cc - &4649; SPRITE_PORTCULLIS_Z ; sprite &42: 3 bytes x 24 lines (offset 3), data @ &40b4 - &40fb, mask @ &507a - &50c1; SPRITE_MAGIC ; sprite &43: 3 bytes x 13 lines (offset 1), data @ &3b6b - &3b91, mask @ &4b31 - &4b57; SPRITE_MAN_HEAD_FRONT ; sprite &44: 3 bytes x 12 lines (offset 1), data @ &3d51 - &3d74, mask @ &4d17 - &4d3a; SPRITE_MAN_HEAD_BACK ; sprite &45: 3 bytes x 12 lines (offset -1), data @ &3ea7 - &3eca, mask @ &4e6d - &4e90; SPRITE_WOLF_HEAD_FRONT ; sprite &46: 3 bytes x 13 lines (offset 1), data @ &3fdc - &4002, mask @ &4fa2 - &4fc8; SPRITE_WOLF_HEAD_BACK ; sprite &47: 3 bytes x 11 lines (offset 3), data @ &3b92 - &3bb2, mask @ &4b58 - &4b78; SPRITE_GUARD_FEET_FRONT ; sprite &48: 3 bytes x 13 lines (offset 5), data @ &3bce - &3bf4, mask @ &4b94 - &4bba; SPRITE_GUARD_FEET_FRONT_FRAME_2 ; sprite &49: 3 bytes x 11 lines (offset 3), data @ &3b92 - &3bb2, mask @ &4b58 - &4b78; SPRITE_GUARD_FEET_FRONT_FRAME_3 ; sprite &4a: 3 bytes x 11 lines (offset 2), data @ &3c10 - &3c30, mask @ &4bd6 - &4bf6; SPRITE_GUARD_FEET_FRONT_FRAME_4 ; sprite &4b: 3 bytes x 12 lines (offset 3), data @ &3c49 - &3c6c, mask @ &4c0f - &4c32; SPRITE_GUARD_FEET_FRONT_FRAME_5 ; sprite &4c: 3 bytes x 11 lines (offset 2), data @ &3c10 - &3c30, mask @ &4bd6 - &4bf6; SPRITE_GUARD_FEET_FRONT_FRAME_6 ; sprite &4d: 3 bytes x 12 lines (offset 3), data @ &3d75 - &3d98, mask @ &4d3b - &4d5e; SPRITE_GUARD_FEET_BACK ; sprite &4e: 3 bytes x 13 lines (offset 4), data @ &3e23 - &3e49, mask @ &4de9 - &4e0f; SPRITE_GUARD_FEET_BACK_FRAME_2 ; sprite &4f: 3 bytes x 12 lines (offset 3), data @ &3d75 - &3d98, mask @ &4d3b - &4d5e; SPRITE_GUARD_FEET_BACK_FRAME_3 ; sprite &50: 3 bytes x 12 lines (offset 2), data @ &3db1 - &3dd4, mask @ &4d77 - &4d9a; SPRITE_GUARD_FEET_BACK_FRAME_4 ; sprite &51: 3 bytes x 12 lines (offset 2), data @ &3dea - &3e0d, mask @ &4db0 - &4dd3; SPRITE_GUARD_FEET_BACK_FRAME_5 ; sprite &52: 3 bytes x 12 lines (offset 2), data @ &3db1 - &3dd4, mask @ &4d77 - &4d9a; SPRITE_GUARD_FEET_BACK_FRAME_6 ; sprite &53: 3 bytes x 24 lines (offset 3), data @ &40b4 - &40fb, mask @ &507a - &50c1; SPRITE_HOMING_MAGIC ; sprite &54: 4 bytes x 28 lines (offset 7), data @ &32ee - &335d, mask @ &42b4 - &4323; SPRITE_DESCENDING_BLOCK ; sprite &55: 4 bytes x 28 lines (offset 7), data @ &32ee - &335d, mask @ &42b4 - &4323; SPRITE_DISAPPEARING_BLOCK ; sprite &56: 3 bytes x 24 lines (offset 3), data @ &40b4 - &40fb, mask @ &507a - &50c1; SPRITE_DISAPPEARED ; sprite &57: 4 bytes x 28 lines (offset 7), data @ &32ee - &335d, mask @ &42b4 - &4323; SPRITE_MOVING_BLOCK_X ; sprite &58: 4 bytes x 28 lines (offset 7), data @ &32ee - &335d, mask @ &42b4 - &4323; SPRITE_MOVING_BLOCK_Z ; sprite &59: 4 bytes x 28 lines (offset 7), data @ &32ee - &335d, mask @ &42b4 - &4323; SPRITE_CARRIED_BLOCK ; sprite data &3136 00 03 00 00 0e 80 00 1e e0 00 1e f8 00 1e fe 00 &3146 1e fe 00 1e fe 00 1c 7e 00 12 9e 00 0e e6 00 1e &3156 f8 00 1e fe 00 1e fe 00 1e fe 00 18 7e 00 06 9e &3166 00 1e e6 00 1e f8 00 1e fe 00 1e fe 00 1e fe 00 &3176 18 fe 00 05 3e 00 3d ce 00 3d f0 00 3d fc 00 7d &3186 fc 00 7b fc 00 01 fc 00 fa 7c 00 f7 98 00 f7 e0 &3196 00 f7 f8 01 ef f0 00 ef f0 07 1f f0 07 cf e0 0f &31a6 b3 e0 1f 7c c0 2f 7f 00 36 ff 80 79 ff 00 fa 7f &31b6 00 f7 9e 00 ef e4 00 df f8 00 bf f0 00 1f e0 00 &31c6 c7 c0 00 31 80 00 0c 00 00 00 00 00 00 00 34 00 &31d6 77 00 77 c0 77 f0 77 f0 77 f0 77 f0 43 f0 34 f0 &31e6 77 30 77 c0 77 f0 43 f0 34 f0 77 30 77 c0 67 f0 &31f6 18 f0 7b 30 3b c0 3d f8 30 f8 0e 38 1e cc 0f 70 &3206 0f 3e 06 ce 01 f3 01 ec 00 ee 00 5e 00 1e 00 06 &3216 00 00 00 00 06 00 1b 00 7e c0 b3 30 b1 50 b3 50 &3226 d3 10 c7 90 65 b0 65 a0 35 20 65 10 47 30 57 a0 &3236 57 a0 d7 30 96 30 5a 70 6b 30 63 b0 6a b0 69 98 &3246 74 c8 62 64 61 32 61 91 70 c8 70 e6 70 63 30 73 &3256 32 73 32 71 72 71 72 71 66 71 66 71 4e 71 4c f1 &3266 58 e3 59 e3 19 c2 13 86 13 04 12 00 14 00 10 00 &3276 00 00 00 00 00 03 00 0f 00 07 00 02 00 06 00 06 &3286 00 06 00 0e 00 0c 00 0c 00 0e 00 06 00 06 00 03 &3296 00 03 00 03 00 07 00 0e 00 0e 00 1e 00 1c 00 1c &32a6 00 1c 00 18 00 18 00 18 00 10 00 30 00 38 00 38 &32b6 00 18 00 1c 00 7a 01 f2 01 e6 05 c6 04 ee 0c ec &32c6 18 f6 38 f6 72 7a 62 7a 66 3a c4 3a cc 32 88 34 &32d6 18 34 8c 34 8c 24 0c 20 0c 20 04 20 04 00 04 00 &32e6 08 00 08 00 08 00 00 00 00 00 00 00 00 01 80 00 &32f6 00 06 a0 00 00 1e 50 00 00 7e aa 00 01 fe 55 00 &3306 07 fe aa 80 1f fe 55 50 7f fe aa aa 7f fe 55 54 &3316 7f fe aa aa 7f fe 55 54 7f f9 8a aa 7f e7 e5 54 &3326 7f 9f f8 aa 7e 7f fe 54 79 ff ff 8a 67 ff ff e4 &3336 5f ff ff fa 7f ff ff fe 1f ff ff f8 07 ff ff e0 &3346 01 ff ff 80 00 7f fe 00 00 1f f8 00 00 07 e0 00 &3356 00 01 80 00 00 00 00 00 00 00 00 00 00 00 80 00 &3366 00 00 80 00 00 07 e2 00 00 2f f4 00 03 13 f4 00 &3376 01 6d ea 00 00 ed f7 00 00 f3 ff 00 00 7f fc 60 &3386 0f bf fb 80 00 7c f6 00 01 fb f9 80 01 fc ff f0 &3396 01 ff ff 80 06 ff f7 00 08 cf eb 00 00 37 f4 00 &33a6 00 6f fa 00 00 9e f9 00 00 05 60 00 00 09 10 00 &33b6 00 09 08 00 00 01 00 00 00 00 00 00 00 00 00 00 &33c6 00 01 80 00 00 07 e0 00 00 1e 78 00 00 79 9e 00 &33d6 01 e7 e7 80 07 9f b9 e0 1e 7d be 78 79 b5 b7 9e &33e6 67 b5 b6 e6 1f b5 b6 f8 7f d6 b5 fe 5d d6 b5 ba &33f6 1d d6 bb b8 1d ee bf b0 1d 7f 76 b0 0d 3f f6 b0 &3406 0c 6d b6 10 08 6d b6 10 08 65 a6 10 08 61 82 10 &3416 00 41 82 10 00 41 02 00 00 41 02 00 00 01 00 00 &3426 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 &3436 00 0c 00 00 00 14 00 00 00 14 00 00 00 14 00 00 &3446 00 14 00 00 18 14 00 00 28 14 00 00 28 14 00 0c &3456 28 14 00 14 28 14 00 14 28 04 00 14 28 18 00 14 &3466 28 66 18 14 29 99 88 14 26 7e 60 14 19 ff 98 14 &3476 67 ff e6 14 9f ff f9 94 ff ff fe 64 ff ff ff 98 &3486 7f ff ff e6 1f ff ff f9 07 ff ff ff 01 ff ff ff &3496 00 7f ff fc 00 1f ff f0 00 07 ff c0 00 01 ff 00 &34a6 00 00 7c 00 00 00 10 00 00 00 00 00 00 00 00 00 &34b6 00 00 38 00 00 00 da 00 00 03 57 80 00 0f 8f e0 &34c6 00 33 df f8 00 f3 df f6 03 f3 df fa 0d f3 df fc &34d6 39 f3 df fe 59 b3 df fe 59 93 df fe 39 93 07 fe &34e6 79 1c b9 fe 79 73 be 7e 79 cf df 9e 7b 33 9f e6 &34f6 7c f0 6f fa 73 f9 c7 fe 4d e0 39 fc 38 9c 7e 30 &3506 3c f2 3f c0 38 0f 0f 00 16 3f c4 00 1c 1f f0 00 &3516 0b 07 c0 00 07 e3 00 00 01 fc 00 00 00 00 00 00 &3526 01 c0 00 00 03 e1 c0 00 03 e3 c7 00 01 d3 cf 8c &3536 01 17 5f bc 38 98 a7 7c 7c 51 42 b8 7e 00 05 62 &3546 38 7f fe 0e 23 ff ff ce 0f ff ff f6 1f ff ff f8 &3556 3f ff ff fc 3f ff ff fc 7f ff ff fe 7f ff ff fe &3566 7f ff ff fe 7f ff ff fe 3f ff f0 3c 3f ff 8f cc &3576 1f fe 7f f0 1f fd ff fc 0f fb ff f4 07 f7 ff e2 &3586 03 cf ff c2 03 8f ff c2 03 8f ff c2 03 f0 0f c2 &3596 07 05 50 e4 0c 6c 21 38 0a 92 91 90 07 fd 51 60 &35a6 0d 35 e0 f0 06 fb f8 60 03 dd f8 c0 00 ff ff 00 &35b6 00 0f f0 00 00 00 00 00 00 00 00 00 10 00 00 7c &35c6 00 01 ff 00 07 e7 c0 1f 99 f0 7e 60 7c 39 9c 1e &35d6 07 7b a4 0e f7 b0 04 fc 60 03 3e 80 07 de 00 07 &35e6 f9 c0 03 f7 60 00 fc a0 00 38 90 00 37 f0 00 3f &35f6 e0 00 33 c0 00 73 80 00 7f c0 00 61 c0 00 00 00 &3606 00 00 00 00 00 0c 00 00 0e 00 00 18 00 03 04 00 &3616 03 8c 00 06 0e 00 c1 1e 00 e3 7c 01 83 ec 30 47 &3626 8c 38 df 0e 60 fb 1e 11 e3 7c 37 c3 ec 3e c7 8c &3636 78 df 0e 70 fb 1e 31 e3 7c 37 c3 ec 3e c7 8c 78 &3646 df 0e 70 fb 1e 31 e3 7c 37 c3 ec 3e c7 8c 78 df &3656 0e 70 fb 1e 31 e3 7c 37 c3 ec 3e c7 8c 78 df 0c &3666 70 fb 08 31 e3 00 37 c3 00 3e c2 00 78 c0 00 70 &3676 c0 00 30 80 00 30 00 00 20 00 00 00 00 00 00 00 &3686 00 00 7e 00 01 ff 80 03 ff c0 07 ff e0 0f ff f0 &3696 0f ff f0 1f ff f8 1f ff f8 19 ff f8 19 ff f8 18 &36a6 ff f8 0c 7f f0 0e 3f f0 07 07 e0 03 87 c0 01 ff &36b6 80 00 7e 00 00 00 00 00 00 00 00 7e 00 03 ff c0 &36c6 07 ff e0 0f ff f0 1f ff f8 1f ff f8 3f ff fc 33 &36d6 ff fc 33 ff fc 39 ff fc 18 ff f8 1c 7f f8 0e 07 &36e6 f0 07 87 e0 03 ff c0 00 7e 00 00 00 00 00 06 00 &36f6 03 1f 00 07 ff f0 0f ff f0 3f ff f0 7f ff fc 7f &3706 ff fe 3f ff fe 1f ff fc 0f ff f8 07 ff 98 07 ff &3716 50 03 ff 20 03 ff 20 01 ff c0 01 ff 80 00 ff 00 &3726 00 3c 00 00 00 00 00 0f 00 00 1f 80 1e 1f 90 0f &3736 1f f8 0f ff f8 3f ff fc 7f ff fe 3f ff fe 1f ff &3746 fc 0f ff f8 07 ff 98 07 ff 50 03 ff 20 03 ff 20 &3756 01 ff c0 01 ff 80 00 ff 00 00 3c 00 00 00 00 00 &3766 1c 00 00 1e 00 07 3f 38 0f ff f8 07 ff f8 07 ff &3776 fe 7f ff fe 7f ff fe 3f ff fc 1f c7 f8 0f 0b f8 &3786 06 9b f0 06 c7 f0 07 3f f0 03 ff e0 01 ff 80 00 &3796 3c 00 00 00 00 00 1e 00 00 3f 00 01 ff 00 01 fe &37a6 00 03 ff 66 7f ff fe 7f ff fe 3f ff fc 1f ff fc &37b6 0f c7 f8 07 0b f0 06 9b f0 02 c7 e0 03 3f e0 01 &37c6 ff c0 01 ff 80 00 ff 00 00 3c 00 00 00 00 00 00 &37d6 00 03 3f 00 07 7f e0 03 7f f0 0b 7f f0 0b 7f e0 &37e6 05 01 e0 06 60 20 05 f0 00 03 b0 c0 03 32 c0 06 &37f6 3b 20 04 1c 60 03 0f 80 03 33 f0 03 3c 60 01 bf &3806 80 01 9f c0 00 df c0 00 6f 80 00 37 00 00 1c 00 &3816 00 00 00 00 00 00 01 80 00 03 bf 00 03 7f e0 0b &3826 7f f0 0b bf f0 05 bf e0 05 81 e0 00 7e 40 01 ff &3836 80 0d c2 40 0d bc 60 0d bc 20 05 be 40 0b bc e0 &3846 07 7c c0 06 fc c0 01 fd 80 01 f9 80 00 fb 00 00 &3856 76 00 00 38 00 00 00 00 00 00 00 00 80 00 01 80 &3866 00 02 80 04 06 b7 04 06 b7 0a 0e 40 0a 0c 5f 1a &3876 0c 5f 92 0c 5f b2 1e 5f b2 1e bd b2 1f 7a b2 1e &3886 f2 b2 1e ea bc 1e ca f8 0f af 70 0f af 60 07 bf &3896 60 03 bf 00 01 7f 40 02 64 a0 02 40 20 02 1b 20 &38a6 03 20 a0 03 c0 40 03 ff 80 03 ff 00 03 8f 00 03 &38b6 16 00 03 3c 00 01 38 00 01 70 00 01 f0 00 01 e0 &38c6 00 01 c0 00 01 80 00 01 00 00 00 00 00 00 00 00 &38d6 20 00 00 30 00 00 38 00 00 3c 7f 10 3e ff b0 7f &38e6 7f b8 7f bf b8 7f df bc 7f df 7c 7f ef 7c 7f ff &38f6 fc 7f ff f8 07 ff f0 01 ff e0 00 7c 00 00 33 e0 &3906 00 cf f0 00 df f0 00 3e 70 00 3c f0 00 79 f8 00 &3916 79 f8 00 78 f8 00 78 f8 00 3c 7c 00 0f fc 00 03 &3926 fc 00 00 fc 00 00 3e 00 00 0e 00 00 02 00 00 00 &3936 00 00 0c 00 0b f0 07 f8 0f 7c 0e fc 2d 7c 2d 6c &3946 25 68 15 68 12 c4 02 a0 08 a0 08 40 01 40 00 00 &3956 00 00 03 c0 07 f8 05 fc 0c dc 0c 9c 48 c8 44 82 &3966 44 26 2f 6c 0e 6c 16 64 12 64 12 42 09 42 00 00 &3976 00 00 00 07 fc 00 0e 0e 00 09 f2 00 07 fc 00 0f &3986 fe f8 1f ff 7c 3f ff 8c 3e 0f 86 71 f1 c6 4e 0e &3996 46 30 01 86 40 00 5c 40 00 58 30 01 80 0e 0e 00 &39a6 01 f0 00 00 00 00 00 00 00 00 10 00 00 ba 00 01 &39b6 bb 00 03 7d 80 03 7d 80 06 fe c0 0e fe e0 0d ff &39c6 60 1d ff 70 3b ff b8 3a 00 b8 66 fe cc 5e fe f4 &39d6 3d 01 78 1b ff b0 07 ff c0 03 ff 80 01 ff 00 00 &39e6 00 00 00 00 00 00 7f 00 01 7f c0 02 01 e0 02 7d &39f6 e0 00 7d e0 02 7d e0 02 7d e0 02 7d e0 02 01 e0 &3a06 02 7f e0 01 7f e0 03 7f e0 01 bf c0 01 df c0 00 &3a16 df 80 00 6f 00 00 2e 00 00 2e 00 00 22 00 00 5d &3a26 00 00 3e 00 00 1c 00 00 00 00 00 00 00 07 c0 00 &3a36 0f e0 00 18 30 00 17 c8 00 0f f4 e0 1f fb f0 13 &3a46 fc 30 19 df d0 0d be e0 07 77 70 00 3f 60 00 17 &3a56 a0 00 1f c0 00 17 c0 00 18 20 00 30 10 00 20 10 &3a66 00 10 20 00 0f c0 00 00 00 00 00 00 00 7e 00 01 &3a76 ff 80 03 ff c0 07 81 e0 02 7e 40 01 ff 80 03 ff &3a86 c0 07 ff e0 07 ff e0 0f ff f0 0f ff f0 0f ff f0 &3a96 0c 7f f0 0c 7f f0 0c 3f f0 06 0f e0 07 0f e0 03 &3aa6 8f c0 01 ff 80 00 7e 00 00 00 00 00 00 00 00 7e &3ab6 00 01 ff c0 01 e7 e0 0c db f0 06 3d e0 03 81 c0 &3ac6 00 5e 00 03 bf c0 03 7f c0 06 00 e0 08 ff 10 05 &3ad6 ff e0 09 00 f0 18 ff 18 17 00 e8 08 00 10 10 00 &3ae6 08 10 00 08 08 00 10 07 00 e0 00 ff 00 00 00 00 &3af6 00 00 00 00 ff 00 07 ff e0 1e 7e 78 3e 99 7c 3f &3b06 e7 fc 7f 99 fe 7e 66 7e 7e 66 7e 7f c3 fe 3f c3 &3b16 fc 3e e7 7c 1f 7e f8 07 7e e0 00 7e 00 00 7e 00 &3b26 00 7e 00 00 42 00 00 bd 00 00 7e 00 00 3c 00 00 &3b36 00 00 00 00 00 00 e3 80 00 b7 80 00 57 00 00 36 &3b46 00 00 3e 00 00 df 80 00 df 80 00 df 80 00 df 80 &3b56 00 e3 80 00 5d 00 00 2e 00 00 2e 00 00 2e 00 00 &3b66 14 00 00 00 00 01 03 a0 02 62 10 04 60 10 08 a8 &3b76 20 10 d8 40 10 01 a0 0c 06 60 03 f9 40 00 07 40 &3b86 00 ee 80 00 75 00 00 1a 00 00 00 00 00 00 00 00 &3b96 0c 00 00 1f 00 01 d1 c0 01 e3 c0 01 bc 40 00 1d &3ba6 80 00 21 80 00 0c 00 00 6f 80 00 6f 60 00 ef 70 &3bb6 60 e3 b8 78 1c b8 3c ff 18 1a ff 6c 07 7e f0 0f &3bc6 7f f8 07 ff f0 03 8f e0 00 00 00 00 60 00 00 f8 &3bd6 00 00 fe 00 00 7f 00 00 07 00 00 0a 00 00 1d 00 &3be6 00 1b c0 00 30 c0 00 0f 40 00 3f 00 00 5f 80 00 &3bf6 5f b0 60 e3 b8 70 1c 98 3c ff 1c 1a ff ec 07 7f &3c06 f4 0f 7f f8 07 ff f8 03 8f e0 00 00 00 07 07 00 &3c16 07 c7 c0 07 f3 e0 00 f0 f0 00 00 30 00 61 c0 00 &3c26 8c 00 01 ee c0 01 ee e0 00 ee e0 00 e3 70 20 1c &3c36 70 70 ff 18 38 fe e8 17 7e f0 07 7f f0 03 ff e0 &3c46 03 8f c0 00 00 00 1c 00 00 1f 00 00 1f c0 e0 0b &3c56 e0 f8 00 c0 7c 01 80 0e 03 00 f6 04 e4 38 03 f3 &3c66 80 03 ed d0 01 ee e0 01 e2 e0 00 1c f0 10 fe 30 &3c76 38 fd c0 1d 7d f0 0b 7f f0 03 ff e0 03 8f c0 00 &3c86 00 00 03 00 c0 0f 80 f0 3f 00 7c 7c 00 1e 70 00 &3c96 0e 3c 00 3e 1f 00 f8 0f 33 20 02 f7 c0 01 f7 f0 &3ca6 03 ff f0 03 ff e0 01 ff c0 00 0f 80 00 f0 00 00 &3cb6 ff 00 01 ff 00 01 ff 00 01 ff 00 0f ff 80 1f 87 &3cc6 c0 2f 7b f0 26 7d e0 b1 fe d0 bf fe 58 9c fe 3c &3cd6 c1 fe 0c d7 fe 0c 1f bc 8c 3f 3e 8c 2f ee c0 18 &3ce6 06 e0 00 02 00 00 00 00 00 00 00 00 07 f0 18 03 &3cf6 f0 1c 00 38 0e 78 38 0e f1 0c 07 cf 70 03 3f 7e &3d06 30 1f fe 78 1f fc 5c 0f fa 0e 13 f4 0d 9c e8 0b &3d16 df 2c 07 ff cc 07 ff e6 03 ff c6 01 8f b6 00 01 &3d26 f6 03 00 7a 04 30 38 04 7c 40 04 2f 20 04 03 20 &3d36 04 08 10 02 33 10 03 37 10 02 87 10 03 60 10 01 &3d46 9e 60 00 e5 80 00 78 00 00 00 00 00 73 f8 00 cf &3d56 fc 00 df 8c 00 3e 78 00 79 70 00 f7 b8 01 e7 b0 &3d66 01 eb a0 00 ec 50 00 6f a0 00 07 00 00 00 00 00 &3d76 00 00 00 18 00 00 fc 00 01 fc 00 01 e2 00 00 da &3d86 00 00 36 00 01 60 00 01 4e 00 00 3f 00 00 7f 40 &3d96 00 ff 40 00 71 40 00 4e 20 0c 3f b8 3d df 88 7b &3da6 df d0 63 ff f8 01 ff 80 00 fc 70 00 00 00 00 c0 &3db6 00 07 e3 80 0f ef 80 0f 1f 80 06 d7 00 00 c9 00 &3dc6 00 dc 00 00 bd 80 00 7e c0 01 fe c0 00 f0 80 07 &3dd6 26 60 1e 5f a0 39 df d0 23 df e0 01 ff f0 00 ff &3de6 80 00 fc 70 00 00 00 00 00 e0 00 03 e0 06 0f e0 &3df6 3f 0e 00 7f 0d c0 78 01 80 36 30 00 06 7b 80 06 &3e06 fd f0 04 7e e0 03 b0 c0 0f 8e 40 1c 6f 80 11 ef &3e16 c0 01 ef e0 00 ff e0 00 ff 80 00 7c 70 00 00 00 &3e26 00 06 00 00 1f 00 00 7b 00 00 70 00 00 06 00 00 &3e36 0c 00 00 d8 00 07 d0 00 07 87 00 00 5f 00 00 bf &3e46 40 00 ff 40 01 71 1c 01 0e 7c 18 7f a8 1d bf 84 &3e56 3b df d8 37 ff f8 63 ff 80 61 fc 70 00 00 00 00 &3e66 00 00 04 04 00 07 87 00 07 e7 c0 01 fb f0 00 78 &3e76 f8 00 31 70 00 72 e0 00 f6 80 00 e7 00 01 eb 80 &3e86 09 ed e0 10 fe f0 31 ff 78 39 ff 7c 1d ff 78 0d &3e96 fe f8 01 fe f8 00 7f f0 03 8f f0 01 57 f0 04 58 &3ea6 60 07 df 80 05 6f 80 07 ff 80 03 fe 80 02 ef 00 &3eb6 06 4f 00 0b ff 80 0d ff 80 0e fb c0 0c 00 c0 10 &3ec6 00 20 00 00 00 00 00 00 10 00 00 1c 00 00 1f 00 &3ed6 80 07 c0 e0 01 e0 f8 00 c0 3c 01 84 0e 03 8c fe &3ee6 03 cc fc 03 ef 60 03 f7 80 09 f3 c0 19 fd e0 19 &3ef6 fe f0 1d fe f0 0d fe f0 05 fe e0 01 fe e0 00 7f &3f06 e0 03 8f e0 01 57 e0 04 58 40 00 00 00 00 10 00 &3f16 01 1c 00 01 df 00 01 ef c0 00 f3 e0 00 3c c0 00 &3f26 1d 00 00 1a c0 00 35 80 00 75 80 10 ed 80 20 ed &3f36 c0 20 fe e0 31 ff 70 3d ff 38 1d ff 3c 0d fe 7c &3f46 01 fe f8 00 7f f8 03 8f f0 01 57 e0 04 58 40 00 &3f56 00 00 00 80 00 00 e0 00 00 f8 00 00 3e 00 00 07 &3f66 00 00 2e 00 00 2e 00 00 1d 00 00 3d c0 00 3e 80 &3f76 30 3f 60 60 5e c0 60 5e c0 70 6e c0 38 ff 60 1d &3f86 ff 60 1d ff b0 0d ff b0 0d ff 78 0d fe f8 04 7f &3f96 f8 03 8f f0 01 57 e0 04 58 40 00 00 00 00 18 00 &3fa6 01 3c 00 01 fc 00 01 ec 00 00 da 00 03 36 00 06 &3fb6 b4 00 06 7a 00 06 7c 00 07 3e 00 03 df 00 01 ef &3fc6 40 00 f7 d0 00 f7 d8 00 ef d8 00 ef d8 00 ff e8 &3fd6 01 ff f8 01 ff f8 00 7f f8 00 8f e0 00 9f f0 01 &3fe6 f7 f0 01 d7 f0 00 bb f0 00 7b f0 00 77 f0 00 ef &40f6 e0 00 c0 e0 00 00 c0 00 00 80 00 00 00 00 00 00 &4006 00 c0 00 09 e3 80 0f cf 80 0f 37 80 06 69 00 00 &4016 63 00 00 eb 00 00 ed 80 00 f6 c0 00 76 c0 00 7a &4026 c0 00 7b c0 00 7b c0 00 77 d0 00 ef d0 00 ff d8 &4036 01 ff f8 01 ff f8 00 00 00 00 00 60 00 09 f0 03 &4046 07 f0 27 9b 60 3f b4 e0 3d a0 c0 1b 60 c0 03 75 &4056 c0 03 76 e0 03 bb 60 01 bd 60 00 1d c0 00 3d c0 &4066 00 7b c0 00 f7 c0 00 ef d0 01 ff f8 01 ff f8 00 &4076 00 00 00 06 00 00 5f 00 00 7b 00 00 37 00 00 06 &4086 00 02 6e 00 03 ec 00 03 dc 00 10 5e 00 20 5f 00 &4096 60 df 00 7c 3f 80 3f df 8c 0f ef de 01 ef d6 01 &40a6 df c6 01 df ee 01 ff ec 01 ff fc 00 ff fc 08 00 &40b6 00 1c 00 08 3e 20 1c 7f 08 08 3e 1c 00 1c 3e 20 &40c6 09 7f 70 03 be 20 07 dc 00 03 88 80 01 01 c0 10 &40d6 03 e0 02 01 c8 07 10 9c 02 38 3e 01 11 1c 03 83 &40e6 88 07 c1 00 0f e0 00 07 c8 00 03 9c 80 01 3f c0 &40f6 00 1c 80 00 08 00 ; mask data &40fc ff f0 7f ff e0 1f ff c0 07 ff c0 01 ff c0 00 ff &410c c0 00 ff c0 00 ff c0 00 ff c0 00 ff e0 00 ff c0 &411c 01 ff c0 00 ff c0 00 ff c0 00 ff c0 00 ff e0 00 &412c ff c0 00 ff c0 01 ff c0 00 ff c0 00 ff c0 00 ff &413c c0 00 ff c0 00 ff 80 00 ff 80 01 ff 80 01 ff 00 &414c 01 ff 00 01 ff 00 01 fe 00 01 fe 00 03 fe 00 07 &415c fe 00 03 fc 00 07 f8 00 07 f0 00 07 f0 00 0f e0 &416c 00 0f c0 00 1f 80 00 3f 80 00 3f 00 00 7f 00 00 &417c 7f 00 00 ff 00 01 ff 00 03 ff 00 07 ff 00 0f ff &418c 00 1f ff 00 3f ff c0 7f ff f3 ff ff c3 ff 80 ff &419c 00 3f 00 0f 00 07 00 07 00 07 00 07 00 07 80 07 &41ac 00 07 00 0f 00 07 00 07 80 07 00 07 00 0f 00 07 &41bc 80 07 00 07 80 07 80 03 80 03 c0 03 c0 01 e0 01 &41cc e0 00 f0 00 f8 00 fc 00 fe 00 ff 00 ff 80 ff e0 &41dc ff f8 ff fc e0 ff 80 3f 00 0f 00 07 00 07 00 07 &41ec 00 07 00 07 00 07 00 0f 80 0f 00 07 00 07 00 0f &41fc 00 0f 00 07 00 07 00 07 00 07 00 07 00 07 00 03 &420c 00 03 00 03 00 01 00 00 00 00 00 00 00 00 00 00 &421c 80 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 &422c 00 00 00 00 80 18 c0 30 c0 71 c0 fb c1 ff c3 ff &423c ef ff ff ff ff f0 ff e0 ff f0 ff f8 ff f0 ff f0 &424c ff f0 ff e0 ff e1 ff e1 ff e0 ff f0 ff f0 ff f8 &425c ff f8 ff f8 ff f0 ff e0 ff e0 ff c0 ff c1 ff c1 &426c ff c1 ff c3 ff c3 ff c3 ff c7 ff 87 ff 83 ff 83 &427c ff c3 ff 81 fe 00 fc 00 f8 00 f0 00 f0 00 e0 01 &428c c0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 &429c 00 01 00 01 00 81 01 8b 21 8f 71 8f 71 df f1 ff &42ac e3 ff e3 ff e3 ff f7 ff ff fe 7f ff ff f8 1f ff &42bc ff e0 07 ff ff 80 01 ff fe 00 00 7f f8 00 00 1f &42cc e0 00 00 07 80 00 00 01 00 00 00 00 00 00 00 00 &42dc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &42ec 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &42fc 00 00 00 00 00 00 00 00 80 00 00 01 e0 00 00 07 &430c f8 00 00 1f fe 00 00 7f ff 80 01 ff ff e0 07 ff &431c ff f8 1f ff ff fe 7f ff ff ff 7f ff ff fe 3f ff &432c ff f8 1d ff ff d0 08 ff fc 80 01 ff f8 00 01 ff &433c fc 00 00 ff fe 00 00 7f fe 00 00 1f f0 00 00 0f &434c e0 00 00 1f f0 00 00 7f fc 00 00 0f fc 00 00 07 &435c f8 00 00 0f f0 00 00 7f e0 00 00 7f f7 00 00 ff &436c ff 00 00 ff fe 00 00 7f ff 60 06 ff ff e0 07 ff &437c ff e0 63 ff ff f4 77 ff ff fe ff ff ff fe 7f ff &438c ff f8 1f ff ff e0 07 ff ff 80 01 ff fe 00 00 7f &439c f8 00 00 1f e0 00 00 07 80 00 00 01 00 00 00 00 &43ac 00 00 00 00 80 00 00 01 00 00 00 00 00 00 00 00 &43bc 80 00 00 01 c0 00 00 07 c0 00 00 07 e0 00 00 07 &43cc e0 00 00 47 e3 00 00 c7 e3 00 00 c7 e3 08 18 c7 &43dc f7 1c 38 c7 ff 1c 78 ef ff 1c 78 ff ff bc 7d ff &43ec ff fc 7f ff ff fc 7f ff ff fe ff ff ff f3 ff ff &43fc ff e1 ff ff ff c1 ff ff ff c1 ff ff ff c1 ff ff &440c e7 c1 ff ff c3 c1 ff ff 83 c1 ff f3 83 c1 ff e1 &441c 83 c1 ff c1 83 c1 ff c1 83 e1 ff c1 83 81 e7 c1 &442c 82 00 43 c1 80 00 03 c1 80 00 07 c1 80 00 01 c1 &443c 00 00 00 41 00 00 00 01 00 00 00 01 00 00 00 01 &444c 00 00 00 00 80 00 00 00 e0 00 00 00 f8 00 00 00 &445c fe 00 00 00 ff 80 00 03 ff e0 00 0f ff f8 00 3f &446c ff fe 00 ff ff ff 83 ff ff ff ef ff ff ff c7 ff &447c ff ff 01 ff ff fc 00 7f ff f0 00 1f ff c0 00 07 &448c ff 00 00 01 fc 00 00 00 f0 00 00 00 c0 00 00 01 &449c 80 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 &44ac 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &44bc 00 00 00 00 00 00 00 00 00 00 00 01 80 00 00 03 &44cc 80 00 00 0f 80 00 00 3f c0 00 00 ff c0 00 03 ff &44dc e0 00 0f ff f0 00 3f ff f8 00 ff ff fe 03 ff ff &44ec fc 1e 3f ff f8 08 18 ff f8 08 10 73 fc 00 00 01 &44fc c4 00 00 01 82 00 00 01 00 00 00 01 00 00 00 00 &450c 80 00 00 00 80 00 00 00 c0 00 00 00 c0 00 00 01 &451c 80 00 00 01 80 00 00 01 00 00 00 00 00 00 00 00 &452c 00 00 00 00 00 00 00 00 80 00 00 01 80 00 00 01 &453c c0 00 00 03 c0 00 00 01 e0 00 00 01 f0 00 00 08 &454c f8 00 00 18 f8 00 00 18 f8 00 00 18 f8 00 00 18 &455c f0 00 00 01 e0 00 00 03 e0 00 00 07 f0 00 00 0f &456c e0 00 00 07 f0 00 00 0f f8 00 00 1f fc 00 00 3f &457c ff 00 00 ff ff f0 0f ff ff ef ff ff 83 ff fe 00 &458c ff f8 00 3f e0 00 0f 80 00 03 00 00 01 80 00 00 &459c c0 00 01 e0 00 03 f0 00 0f f8 00 1f f0 00 3f f0 &45ac 00 1f f8 00 0f fc 00 0f ff 00 07 ff 80 07 ff 80 &45bc 0f ff 80 1f ff 00 3f ff 00 1f ff 00 1f ff 9e 3f &45cc ff ff f3 ff ff e1 ff ff e0 ff fc c1 ff f8 61 ff &45dc f8 21 ff 30 60 fe 18 00 fe 08 01 cc 18 01 86 00 &45ec 01 82 00 60 06 00 00 80 00 01 80 18 01 80 00 01 &45f6 00 00 60 06 00 00 80 00 01 80 18 01 80 00 01 00 &460c 00 60 06 00 00 80 00 01 80 18 01 80 00 01 00 00 &461c 60 06 00 00 80 00 01 80 18 01 80 00 01 00 00 61 &462c 06 00 63 80 00 77 80 18 7f 80 18 ff 00 1d ff 06 &463c 1f ff 86 3f ff 87 7f ff 8f ff ff df ff ff ff 81 &464c ff fe 00 7f fc 00 3f f8 00 1f f0 00 0f e0 00 07 &465c e0 00 07 c0 00 03 c0 00 03 c0 00 03 c0 00 03 c0 &466c 00 03 e0 00 07 e0 00 07 f0 00 0f f8 00 1f fc 00 &467c 3f fe 00 7f ff 81 ff ff 81 ff fc 00 3f f8 00 1f &468c f0 00 0f e0 00 07 c0 00 03 c0 00 03 80 00 01 80 &469c 00 01 80 00 01 80 00 01 c0 00 03 c0 00 03 e0 00 &46ac 07 f0 00 0f f8 00 1f fc 00 3f ff 81 ff fc e0 ff &46bc f8 00 0f f0 00 07 c0 00 07 80 00 03 00 00 01 00 &46cc 00 00 80 00 00 c0 00 01 e0 00 03 f0 00 03 f0 00 &46dc 07 f8 00 0f f8 00 0f fc 00 1f fc 00 3f fe 00 7f &46ec ff 00 ff ff c3 ff ff e0 7f e1 c0 2f c0 c0 07 e0 &46fc 00 03 c0 00 03 80 00 01 00 00 00 80 00 00 c0 00 &470c 01 e0 00 03 f0 00 03 f0 00 07 f8 00 0f f8 00 0f &471c fc 00 1f fc 00 3f fe 00 7f ff 00 ff ff c3 ff ff &472c c1 ff f8 c0 c7 f0 00 03 e0 00 03 f0 00 01 80 00 &473c 00 00 00 00 00 00 00 80 00 01 c0 00 03 e0 00 03 &474c f0 00 07 f0 00 07 f0 00 07 f8 00 0f fc 00 1f fe &475c 00 7f ff c3 ff ff c0 ff fe 00 7f fc 00 7f fc 00 &476c 99 80 00 00 00 00 00 00 00 00 80 00 01 c0 00 01 &477c e0 00 03 f0 00 07 f0 00 07 f8 00 0f f8 00 0f fc &478c 00 1f fc 00 3f fe 00 7f ff 00 ff ff c3 ff fc c0 &479c ff f8 00 1f f0 00 0f f0 00 07 e0 00 07 e0 00 0f &47ac f0 00 0f f0 00 0f f0 00 1f f8 00 1f f8 00 1f f0 &47bc 00 0f f0 00 0f f8 00 0f f8 00 07 f8 00 0f fc 00 &47cc 1f fc 00 1f fe 00 1f ff 00 3f ff 80 3f ff c0 ff &47dc ff e3 ff fe 7f ff fc 00 ff f8 00 1f f0 00 0f e0 &47ec 00 07 e0 00 07 f0 00 0f f0 00 0f f8 00 1f f0 00 &47fc 3f e0 00 1f e0 00 0f e0 00 0f f0 00 1f e0 00 0f &480c f0 00 1f f0 00 1f f8 00 3f fc 00 3f fe 00 7f ff &481c 00 ff ff 81 ff ff c7 ff ff ff ff fe ff ff fc 3f &482c fb f8 3f f1 f0 00 71 f0 00 60 e0 00 e0 e0 00 40 &483c e0 00 00 e0 00 00 c0 00 00 c0 00 00 c0 00 00 c0 &484c 00 00 c0 00 01 c0 00 03 e0 00 07 e0 00 0f f0 00 &485c 0f f8 00 1f fc 00 1f f8 00 0f f8 00 0f f8 00 0f &486c f8 00 0f f8 00 1f f8 00 3f f8 00 7f f8 00 7f f8 &487c 00 ff f8 01 ff fc 03 ff fc 07 ff fc 07 ff fc 0f &488c ff fc 1f ff fc 3f ff fc 7f ff fe ff ff df ff ff &489c 8f ff ff 87 ff ff 83 80 ef 81 00 47 80 00 07 00 &48ac 00 03 00 00 03 00 00 01 00 00 01 00 00 01 00 00 &48bc 01 00 00 03 80 00 07 f8 00 0f fe 00 1f ff 00 0f &48cc fe 00 07 fe 00 07 ff 00 07 ff 80 07 ff 00 03 ff &48dc 00 03 ff 00 03 ff 00 03 ff 80 01 ff c0 01 ff f0 &48ec 01 ff fc 01 ff ff 00 ff ff c0 ff ff f0 ff ff fd &48fc f3 ff e0 0f e0 07 f0 03 e0 01 c0 01 80 01 80 01 &490c 80 03 c0 03 c0 11 e0 0b e0 0f e2 1f f4 1f fe bf &491c fc 3f f8 07 f0 03 f0 01 e0 01 a0 01 02 21 10 10 &492c 10 00 80 01 c0 01 c0 01 c0 01 c0 18 e0 18 f6 bd &493c f8 03 ff f0 01 ff e0 00 ff e0 00 ff f0 00 07 e0 &494c 00 03 c0 00 01 80 00 01 80 00 20 00 00 10 00 00 &495c 10 80 00 20 00 00 01 00 00 03 80 00 27 c0 00 7f &496c f0 01 ff fe 0f ff ff ef ff ff 45 ff fe 00 ff fc &497c 00 7f f8 00 3f f8 00 3f f0 00 1f e0 00 0f e0 00 &498c 0f c0 00 07 80 00 03 80 00 03 00 00 01 00 00 01 &499c 80 00 03 c0 00 07 e0 00 0f f8 00 3f fc 00 7f fe &49ac 00 ff ff 80 ff fe 00 3f fc 00 1f f8 00 0f f8 00 &49bc 0f f8 00 0f f8 00 0f f8 00 0f f8 00 0f f8 00 0f &49cc f8 00 0f f8 00 0f f8 00 0f fc 00 1f fc 00 1f fe &49dc 00 3f ff 00 7f ff 80 ff ff 80 ff ff 80 ff ff 00 &49ec 7f ff 80 ff ff c1 ff ff e3 ff f8 3f ff f0 1f ff &49fc e0 0f ff c0 07 ff c0 03 1f e0 00 0f c0 00 07 c0 &4a0c 00 07 c0 00 07 e0 00 0f f0 00 07 f8 80 0f ff c0 &4a1c 0f ff c0 1f ff c0 1f ff c0 0f ff 80 07 ff 80 07 &4a2c ff c0 0f ff e0 1f ff f0 3f ff 81 ff fe 00 7f fc &4a3c 00 3f f8 00 1f f0 00 0f f8 00 1f fc 00 3f f8 00 &4a4c 1f f0 00 0f f0 00 0f e0 00 07 e0 00 07 e0 00 07 &4a5c e0 00 07 e0 00 07 e0 00 07 f0 00 0f f0 00 0f f8 &4a6c 00 1f fc 00 3f fe 00 7f ff 81 ff ff 81 ff fe 00 &4a7c 3f fc 00 1f f0 00 0f e0 00 07 f0 00 0f f8 00 1f &4a8c fc 00 3f f8 00 1f f8 00 1f f0 00 0f e0 00 07 f0 &4a9c 00 0f e0 00 07 c0 00 03 c0 00 03 e0 00 07 c0 00 &4aac 03 c0 00 03 e0 00 07 f0 00 0f f8 00 1f ff 00 ff &4abc ff 00 ff f8 00 1f e0 00 07 c0 00 03 80 00 01 80 &4acc 00 01 00 00 00 00 00 00 00 00 00 00 00 00 80 00 &4adc 01 80 00 01 c0 00 03 e0 00 07 f8 00 1f ff 00 ff &4aec ff 00 ff ff 00 ff fe 00 7f ff 00 ff ff 81 ff ff &4afc c3 ff ff 1c 7f fe 08 3f fe 00 3f ff 00 7f ff 80 &4b0c ff ff 00 7f fe 00 3f fe 00 3f fe 00 3f fe 00 3f &4b1c fe 00 3f ff 00 7f ff 80 ff ff 80 ff ff 80 ff ff &4b2c c1 ff ff e3 ff fc 00 0f f8 00 07 f0 00 07 e0 00 &4b3c 0f c0 00 0f c0 00 0f e0 00 0f f0 00 1f fc 00 1f &4b4c fe 00 3f ff 00 7f ff 80 ff ff e5 ff ff f3 ff ff &4b5c e0 ff fe 00 3f fc 00 1f fc 00 1f fc 00 1f fe 00 &4b6c 3f ff 80 3f ff 80 3f ff 00 1f ff 00 0f 9e 00 07 &4b7c 06 00 03 03 00 03 80 00 03 c0 00 01 e0 00 03 e0 &4b8c 00 03 f0 00 07 f8 00 0f ff 9f ff ff 07 ff fe 01 &4b9c ff fe 00 ff ff 00 7f ff 80 7f ff e0 7f ff c0 3f &4bac ff c0 1f ff 80 1f ff c0 1f ff 80 3f ff 00 0f 9f &4bbc 00 07 0e 00 03 03 00 03 80 00 01 c0 00 01 e0 00 &4bcc 01 e0 00 03 f0 00 03 f8 00 07 f8 f8 ff f0 30 3f &4bdc f0 00 1f f0 00 0f f8 04 07 ff 0e 07 ff 00 0f fe &4bec 00 3f fc 00 1f fc 00 0f fe 00 0f de 00 07 8f 00 &4bfc 07 06 00 03 80 00 03 c0 00 07 e0 00 07 f8 00 0f &4c0c f8 00 1f e3 ff ff c0 ff ff c0 3f 1f c0 1e 07 e0 &4c1c 0e 03 f4 1f 01 fc 3f 00 f8 0a 00 f0 00 01 f8 00 &4c2c 07 f8 00 07 fc 00 0f fc 00 0f ee 00 07 c6 00 07 &4c3c 82 00 0f c0 00 07 e0 00 07 f0 00 0f f8 00 1f fc &4c4c ff 3f f0 7e 0f c0 3e 03 80 7f 01 00 ff 80 03 ff &4c5c c0 80 ff 00 c0 4c 01 e0 00 07 f0 00 0f fc 00 07 &4c6c f8 00 07 f8 00 0f fc 00 1f fe 00 3f fe 00 7f fe &4c7c 00 7f fc 00 7f fc 00 7f f0 00 7f e0 00 3f c0 00 &4c8c 0f 80 00 07 00 00 0f 00 00 07 00 00 03 00 00 81 &4c9c 00 00 c1 00 00 61 00 00 21 80 00 21 80 00 13 c0 &4cac 10 0f e7 f8 1f ff fd ff ff f8 0f e7 f0 07 c3 f8 &4cbc 07 c1 04 03 e0 02 83 e0 00 01 f0 00 01 c8 00 00 &4ccc 84 c0 00 03 c0 01 01 e0 00 a0 40 01 e0 00 03 e0 &4cdc 00 01 f0 00 01 f0 00 00 f8 00 00 fc 00 00 fc 00 &4cec 00 f8 00 00 f0 00 01 f0 00 07 f0 00 0f f0 00 0f &4cfc f0 00 07 f8 00 07 f8 00 07 f8 00 07 f8 00 07 fc &4d0c 00 0f fe 00 1f ff 02 7f ff 87 ff ff 00 03 fe 00 &4d1c 01 fe 00 01 ff 00 03 ff 00 07 fe 00 03 fc 00 07 &4d2c fc 00 0f fe 00 07 ff 00 0f ff 90 5f ff f8 ff ff &4d3c e7 ff ff 03 ff fe 01 ff fc 01 ff fc 00 ff fe 00 &4d4c ff fe 00 ff fc 01 ff fc 00 ff fe 00 3f ff 00 1f &4d5c fe 00 1f ff 00 1f f3 00 07 c0 00 03 80 00 03 00 &4d6c 00 07 00 00 03 9c 00 07 fe 00 07 ff 3f ff f8 1c &4d7c 7f f0 00 3f e0 00 3f e0 00 3f f0 00 7f f8 00 7f &4d8c fe 00 7f fe 00 3f fe 00 1f fc 00 1f f8 00 1f e0 &4d9c 00 0f c0 00 0f 80 00 07 80 00 0f dc 00 07 fe 00 &4dac 0f fe 00 07 ff ff 1f ff fc 0f f9 f0 0f c0 e0 0f &4dbc 80 60 1f 00 60 1f 00 c0 3f 80 84 7f c0 00 0f f0 &4dcc 00 07 f0 00 0f f0 00 1f e0 00 1f c0 00 3f c0 00 &4ddc 1f ec 00 0f fe 00 0f fe 00 0f ff 00 07 ff f9 ff &4dec ff e0 ff ff 80 7f ff 00 7f ff 00 ff ff 80 ff ff &4dfc 21 ff f8 03 ff f0 00 ff f0 00 7f f8 00 3f fe 00 &4e0c 1f fe 00 03 fc 00 01 e4 00 01 c2 00 03 c0 00 01 &4e1c 80 00 03 80 00 03 08 00 07 0c 00 07 9e 00 03 fb &4e2c fb ff f0 70 ff f0 10 3f f0 00 0f f8 00 07 fe 00 &4e3c 03 ff 84 07 ff 00 0f fe 00 1f fe 00 7f f4 00 1f &4e4c e0 00 0f c6 00 07 84 00 03 80 00 01 c0 00 03 e0 &4e5c 00 03 f0 00 03 fc 00 07 f8 00 07 f8 00 07 f0 00 &4e6c 0f f0 00 1f f0 00 3f f0 00 3f f8 00 3f f8 00 7f &4e7c f0 00 7f e0 00 3f e0 00 3f e0 00 1f e1 04 1f c3 &4e8c ff 0f ef ff df ef ff ff c3 ff ff c0 ff 7f c0 3e &4e9c 1f e0 1e 07 f8 0e 03 fe 1b 01 fc 31 00 f8 20 00 &4eac f8 00 01 f8 00 03 f0 00 1f e0 00 1f c0 00 0f c0 &4ebc 00 07 c0 00 07 e0 00 07 f0 00 0f f8 00 0f fc 00 &4ecc 0f f8 00 0f f8 00 0f f0 00 1f ff ef ff fe c3 ff &4edc fc 00 ff fc 00 3f fc 00 1f fe 00 0f ff 00 1f ff &4eec c0 3f ff c0 1f ff 80 3f ef 00 3f c6 00 3f 8e 00 &4efc 1f 8e 00 0f 80 00 07 80 00 03 c0 00 01 e0 00 01 &4f0c f0 00 03 fc 00 03 f8 00 07 f8 00 0f f0 00 1f ff &4f1c 7f ff fe 1f ff fe 07 ff fe 01 ff ff 00 ff ff c0 &4f2c 7f ff 80 ff ff 80 ff ff c0 3f ff 80 1f cf 80 1f &4f3c 87 80 0f 0f 00 1f 0f 00 1f 07 00 1f 82 00 0f c0 &4f4c 00 0f c0 00 07 e0 00 07 e0 00 03 e0 00 03 f0 00 &4f5c 03 f8 00 07 f8 00 0f f0 00 1f ff e7 ff fe c3 ff &4f6c fc 01 ff fc 01 ff fc 01 ff fc 00 ff f8 00 ff f0 &4f7c 01 ff f0 00 ff f0 01 ff f0 00 ff f8 00 3f fc 00 &4f8c 0f fe 00 07 fe 00 03 fe 00 03 fe 00 03 fe 00 03 &4f9c fc 00 03 fc 00 03 fe 00 03 fe 00 07 fe 00 07 fc &4fac 00 07 fc 00 07 fe 00 07 ff 00 07 ff 00 07 fe 00 &4fbc 0f fe 10 0f ff 3e 1f ff fe 3f ff ff 7f ff 3f ff &4fcc f6 1c 7f e0 00 3f e0 00 3f e0 00 3f f0 00 7f f9 &4fdc 00 7f fe 00 7f fe 00 3f fe 00 1f ff 00 1f ff 00 &4fec 1f ff 00 1f ff 00 0f ff 00 07 fe 00 07 fe 00 03 &4ffc fc 00 03 fc 00 03 ff ff 9f ff f6 0f fc e0 07 d8 &500c 60 07 80 00 0f 80 00 0f 80 0a 1f c0 0a 1f e0 00 &501c 1f f8 00 0f f8 00 0f fc 00 0f fe 40 1f ff 80 1f &502c ff 00 1f fe 00 0f fe 00 07 fc 00 03 fc 00 03 ff &503c f9 ff ff a0 ff ff 00 7f ff 00 7f ff 80 7f fd 80 &504c ff f8 00 ff f8 01 ff e8 01 ff c4 00 ff 8f 00 7f &505c 02 00 7f 00 00 33 80 00 21 c0 00 00 f0 00 00 fc &506c 00 00 fc 00 00 fc 00 01 fc 00 01 fe 00 01 e3 ff &507c f7 c1 df e3 80 87 c1 00 43 e3 80 c1 d7 c0 80 8f &508c e0 00 07 f0 00 8f f0 01 5f f8 22 3f ec 74 1f c4 &509c f8 07 e8 ec 03 f0 46 01 f8 82 00 fc 44 41 f8 28 &50ac 23 f0 1c 77 e0 06 ff f0 03 7f f8 00 3f fc 00 1f &50bc fe c0 3f ff e3 7f ; background sprite data &50c2 c0 00 f0 00 fc 00 ff 00 ff c0 ff f0 ff fc 3f fe &50d2 cf fe e3 fe ec fe ef 3c ef cc 0f e0 67 e0 f9 e0 &50e2 fe 60 ff 80 ff e0 ff f0 ff f0 ff f0 7f f0 1f f0 &50f2 67 f0 79 f8 7e 7c 7f 1c 1f 04 e7 00 f9 00 fe 00 &5102 ff 00 ff a0 ff b8 3f dc cf dc f3 dc fc de ff 1e &5112 ff 0e ff 02 ff 00 3f 00 0f 00 03 00 01 80 00 01 &5122 e0 00 01 f8 00 00 fe 00 00 7f 80 00 7f 80 08 3f &5132 a0 1e 3f b8 0f bf b8 0f bf b8 0f 9f b8 0f a7 98 &5142 67 b9 80 79 be 00 7e 3f 80 3f 9f e0 0f e7 f8 03 &5152 f9 fe 00 fd fe 00 3d fe 00 0c 7e 00 00 1c 40 00 &5162 00 02 70 00 00 0e 7c 00 00 0e 7e 00 00 ee 7e c0 &5172 03 ee 7e f0 0f ee 7e fc 3f e8 36 fe ff e0 00 fe &5182 ff c0 06 3e ff 00 07 8e fc c0 07 e2 f3 c0 03 f8 &5192 cf 8c 03 fe 3f 3c 03 ff 7c fc 03 ff 73 fc 07 ff &51a2 4f f0 07 ff 3f c0 07 ff 7f 00 01 ff 7c 80 60 7f &51b2 73 80 78 1f 4f 80 7e 67 3f 00 7e f8 7c 00 1e fe &51c2 fb 02 06 fe e7 8e 00 fe 9f be 00 fe 7f bc 00 3e &51d2 ff b0 00 0e ff 80 06 30 ff 30 0e 3c fc 78 0f 9e &51e2 f1 f8 07 e6 49 f8 01 f8 3d f0 02 7f 7d e0 03 9f &51f2 7d 80 03 e7 7c 20 01 f9 78 f0 00 fe 73 f0 03 3f &5202 4f f0 03 cf 3f e0 03 f7 7f 80 00 f7 7e 00 00 33 &5212 78 00 00 00 60 00 00 00 02 00 00 0e 00 00 3e 00 &5222 00 fe 00 c3 fe 03 cf cc 0f df 28 3f dc e0 7f d3 &5232 e0 7f cf e0 7f 3f 80 7c fe 00 73 f8 00 47 e0 00 &5242 07 80 00 06 00 00 78 00 7e 00 7d 00 7c 80 6c fc &5252 6c 7c 6c 7d 5c 3e 5c 3e 5c 1f 2c 1f 1e 0f 17 0f &5262 57 0f 57 0f 4b 1e 4b 1e e7 9e e7 9c e7 9c e7 1c &5272 6f 1c 4f 1e 4b 3f 13 5e 26 5e 26 9c 4c 1c 5c 3c &5282 58 38 28 3e 28 3f 18 1e 18 1e 14 1c 14 1c 16 0c &5292 1e 0c 1c 0c 14 16 14 16 18 24 18 2c 18 48 10 10 &52a2 10 00 c0 00 78 00 3f f0 1f e8 1e e8 0e c4 0e c2 &52b2 4e c1 4e c0 4e 40 47 40 47 e0 43 e4 69 e4 68 e4 &52c2 65 ec 25 ec 25 ec 39 e4 39 f4 31 f2 31 f2 31 f0 &52d2 21 e0 21 e0 41 e1 41 f1 41 f2 01 f2 03 e2 07 c2 &52e2 07 83 0f 03 0e 03 1c 07 18 06 18 06 18 0c 18 1c &52f2 18 18 08 30 08 20 08 40 18 00 01 00 01 00 ; bit_reversed_bytes &5300 00 80 40 c0 20 a0 60 e0 10 90 50 d0 30 b0 70 f0 &5310 08 88 48 c8 28 a8 68 e8 18 98 58 d8 38 b8 78 f8 &5320 04 84 44 c4 24 a4 64 e4 14 94 54 d4 34 b4 74 f4 &5330 0c 8c 4c cc 2c ac 6c ec 1c 9c 5c dc 3c bc 7c fc &5340 02 82 42 c2 22 a2 62 e2 12 92 52 d2 32 b2 72 f2 &5350 0a 8a 4a ca 2a aa 6a ea 1a 9a 5a da 3a ba 7a fa &5360 06 86 46 c6 26 a6 66 e6 16 96 56 d6 36 b6 76 f6 &5370 0e 8e 4e ce 2e ae 6e ee 1e 9e 5e de 3e be 7e fe &5380 01 81 41 c1 21 a1 61 e1 11 91 51 d1 31 b1 71 f1 &5390 09 89 49 c9 29 a9 69 e9 19 99 59 d9 39 b9 79 f9 &53a0 05 85 45 c5 25 a5 65 e5 15 95 55 d5 35 b5 75 f5 &53b0 0d 8d 4d cd 2d ad 6d ed 1d 9d 5d dd 3d bd 7d fd &53c0 03 83 43 c3 23 a3 63 e3 13 93 53 d3 33 b3 73 f3 &53d0 0b 8b 4b cb 2b ab 6b eb 1b 9b 5b db 3b bb 7b fb &53e0 07 87 47 c7 27 a7 67 e7 17 97 57 d7 37 b7 77 f7 &53f0 0f 8f 4f cf 2f af 6f ef 1f 9f 5f df 3f bf 7f ff ; continue_initialisation &5400 a9 0b LDA #&0b &5402 8d 36 07 STA &0736 ; objects_size_y + 2 # Charm 1 &5405 8d 37 07 STA &0737 ; objects_size_y + 3 # Charm 2 &5408 a9 16 LDA #&16 &540a 8d 34 07 STA &0734 ; objects_size_y # Player's feet &540d a2 00 LDX #&00 &540f 8e 7a 03 STX &037a ; objects_flipped + 2 # Charm 1 &5412 8e 7b 03 STX &037b ; objects_flipped + 3 # Charm 2 &5415 e8 INX &5416 8e 35 07 STX &0735 ; objects_size_y + 1 # Player's head &5419 a2 03 LDX #&03 &541b 8e a0 03 STX &03a0 ; objects_bytes_per_line_of_sprite # Player's feet &541e 8e a1 03 STX &03a1 ; objects_bytes_per_line_of_sprite + 1 # Player's head &5421 8e a2 03 STX &03a2 ; objects_bytes_per_line_of_sprite + 2 # Charm 1 &5424 8e a3 03 STX &03a3 ; objects_bytes_per_line_of_sprite + 3 # Charm 2 &5427 e8 INX &5428 86 57 STX &57 ; room_colour_scheme &542a a9 42 LDA #&42 &542c 85 94 STA &94 ; cauldron_magic_type_table &542e 85 95 STA &95 ; cauldron_magic_type_table + 1 &5430 85 96 STA &96 ; cauldron_magic_type_table + 2 &5432 85 97 STA &97 ; cauldron_magic_type_table + 3 &5434 a9 00 LDA #&00 &5436 85 99 STA &99 ; cauldron_magic_flipped_table &5438 85 9b STA &9b ; cauldron_magic_flipped_table + 3 &543a a9 07 LDA #&07 &543c 85 98 STA &98 ; cauldron_magic_flipped_table + 1 &543e 85 9a STA &9a ; cauldron_magic_flipped_table + 2 &5440 a9 02 LDA #&02 &5442 85 a2 STA &a2 ; room_27_fire_movement_table &5444 a9 04 LDA #&04 &5446 85 a3 STA &a3 ; room_27_fire_movement_table + 1 &5448 a9 01 LDA #&01 &544a 85 a4 STA &a4 ; room_27_fire_movement_table + 2 &544c a9 08 LDA #&08 &544e 85 a5 STA &a5 ; room_27_fire_movement_table + 3 &5450 a2 69 LDX #&69 &5452 86 9e STX &9e ; sun_or_moon_address_high &5454 e8 INX &5455 86 a0 STX &a0 ; current_sun_or_moon_address_high &5457 a9 b3 LDA #&b3 &5459 8d 5d 03 STA &035d ; vdu_vector_low # Set OS general VDU vector to &ccb3 &545c a9 cc LDA #&cc &545e 8d 5e 03 STA &035e ; vdu_vector_high # (two bytes used by objects_position_z) &5461 a2 00 LDX #&00 &5463 8a TXA &5464 20 b3 cc JSR &ccb3 ; clear_screen_buffer # OS routine that zeros &6b00 - &7fff, using vector &5467 4c 65 13 JMP &1365 ; game_start ; (no filename) # Second chunk loaded by stream loader ; 006400 006bea 000a01 # &6400 - &6cff is unencrypted ; status_section # 256x56 pixels of raw MODE 4 screen data &6400 07 18 20 40 80 81 81 81 80 70 0c 03 00 e0 18 04 &6410 00 00 00 00 c0 30 0c 03 00 00 00 00 00 00 00 00 &6420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &64a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &64b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &64c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &64d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &64e0 00 00 00 00 00 00 00 00 00 00 00 00 03 0c 30 c0 &64f0 01 0e 30 c0 00 07 18 20 e0 18 04 02 01 81 81 81 &6500 c1 a1 91 4f 41 40 40 40 02 02 06 1a e2 02 04 04 &6510 00 00 00 00 00 00 00 00 c0 30 0c 03 00 00 00 00 &6520 00 00 00 00 c0 30 0c 03 00 00 00 00 00 00 00 00 &6530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6550 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6580 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6590 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &65a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &65b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &65c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &65d0 00 00 00 00 00 00 00 00 00 00 00 00 03 0c 30 c0 &65e0 03 0c 30 c0 00 00 00 00 00 00 00 00 00 00 00 00 &65f0 40 40 60 58 47 40 20 20 83 85 89 f2 82 02 02 02 &6600 40 40 40 40 40 40 40 40 04 04 04 04 04 04 04 04 &6610 02 05 05 05 0b 1c 1b 1b 80 c0 c0 c0 a0 70 f0 f0 &6620 00 00 00 00 00 00 00 00 c0 30 0c 03 00 00 00 00 &6630 00 00 00 00 c0 30 0c 03 00 00 00 00 00 00 00 00 &6640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6670 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6690 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &66a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &66b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &66c0 00 00 00 00 00 00 00 00 00 00 00 00 03 0c 30 c0 &66d0 03 0c 30 c0 00 00 00 00 00 00 00 00 00 00 00 00 &66e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &66f0 20 20 20 20 20 20 20 20 02 02 02 02 02 02 02 02 &6700 80 80 80 80 40 30 0f 00 02 02 02 02 04 1a e1 00 &6710 1b 1b 07 06 0a 16 1c 00 f0 f0 c0 c0 e0 f0 70 00 &6720 3c 66 6e 7e 76 66 3c 00 00 00 00 00 00 00 00 00 &6730 00 00 00 00 00 00 00 00 c0 30 0c 03 00 00 00 00 &6740 00 00 00 00 c0 30 0c 03 00 00 00 00 00 00 00 00 &6750 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6760 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6770 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6780 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6790 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &67a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &67b0 00 00 00 00 00 00 00 00 00 00 00 00 03 0c 30 c0 &67c0 03 0c 30 c0 01 07 1f 33 00 00 00 1f ff ff f0 80 &67d0 00 00 ff ff ff 00 00 00 00 00 00 f8 ff ff 0f 01 &67e0 00 00 00 00 80 e0 f8 cc 00 00 00 00 00 00 00 00 &67f0 40 40 40 40 20 58 87 00 01 01 01 01 02 0c f0 00 &6800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6840 00 00 00 00 00 00 00 00 c0 30 0c 03 00 00 00 00 &6850 00 00 00 00 c0 30 0c 03 00 00 00 00 00 00 00 00 &6860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6880 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6890 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &68a0 00 00 00 00 00 00 00 00 00 00 00 00 03 0c 30 c0 &68b0 03 0c 30 c0 00 00 00 00 00 00 00 00 00 00 00 00 &68c0 6e 5e 66 3e 0e 0e 1e 3a 00 00 00 00 00 00 00 00 &68d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &68e0 76 7a 66 7c 70 70 78 5c 00 00 00 00 00 00 00 00 &68f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6910 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6920 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6940 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6950 00 00 00 00 00 00 00 00 c0 30 0c 03 00 00 00 00 &6960 00 00 00 00 e0 18 04 72 00 00 00 00 00 00 00 00 &6970 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6980 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6990 00 00 00 00 00 00 00 00 00 00 00 00 07 18 20 4e &69a0 03 0c 30 c0 00 00 00 00 00 00 02 01 00 00 01 0d &69b0 08 08 00 3c 7e ff ff ff 00 00 40 80 00 00 80 80 &69c0 7e 4e 0e 4e 7e 3a 1e 0e 00 00 00 00 00 00 00 00 &69d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &69e0 7e 72 70 72 7e 5c 78 70 00 00 00 01 03 03 07 07 &69f0 00 3c f3 ef 2c 5e e7 fb 00 00 00 80 c0 c0 e0 e0 &6a00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6a20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6a30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6a40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &6a50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 0c &6a60 89 89 eb 9e 81 81 42 3c 78 6c 66 66 66 6c 78 00 &6a70 3c 66 66 7e 66 66 66 00 66 66 66 3c 18 18 18 00 &6a80 00 00 18 18 00 18 18 00 3c 66 6e 7e 76 66 3c 00 &6a90 3c 66 6e 7e 76 66 3c 00 91 91 d7 79 81 81 42 3c &6aa0 00 00 00 00 00 00 c0 30 01 01 00 00 01 02 00 00 &6ab0 ff ff ff 7e 3c 00 10 10 b0 80 00 00 80 40 00 00 &6ac0 0e 0e 0e 3e 6f 5f 63 3e 00 01 0f 7f ff f0 80 00 &6ad0 00 ff ff ff 00 00 00 00 00 80 f0 fe ff 0f 01 00 &6ae0 70 70 70 7c f6 fa c6 7c 07 07 03 03 01 00 00 00 &6af0 fb e3 df ef f3 fd 3c 00 e0 e0 c0 c0 80 00 00 00 # &6b00 - &6b43 is moved to &0000 - &0043 at &6d81 ; push_sprite_to_screen_buffer &0000 a5 ff LDA &ff # actually LDA (&01) ; sprite_slice_to_plot_zero_page_byte # &52 - &56, sprite_slices_should_plot &0002 d0 2e BNE &0032 ; plot_next_slice # Does this slice need plotting? &0004 a2 00 LDX #&00 # actually LDX &05 ; slice_number &0006 a0 00 LDY #&00 # actually LDY &07 ; location_in_eight_byte_screen_block &0008 a9 00 LDA #&00 # actually LDA &09 ; buffer_address_high &000a 85 14 STA &14 ; sprite_read_address_high &000c 85 1d STA &1d ; sprite_write_address_high &000e a9 00 LDA #&00 # actually LDA &0f ; lines_in_sprite &0010 85 45 STA &45 ; lines_to_plot ; push_sprite_to_screen_slice_loop &0012 b9 ff ff LDA &ffff,Y # actually LDA (&13),Y ; sprite_read_address # Read from buffer &0015 3d 00 05 AND &0500,X ; sprite_mask_staging_area ; mask_instruction # actually BIT &0500 for background objects &0018 1d 00 04 ORA &0400,X ; sprite_staging_area # Add sprite, subject to mask if necessary &001b 99 ff ff STA &ffff,Y # actually LDA (&1c), Y ; sprite_write_address # Write back to buffer &001e e8 INX ; inx_1 &001f e8 INX ; inx_2 &0020 e8 INX ; inx_3 # actually NOP for 2, 3 or 4 byte sprites &0021 e8 INX ; inx_4 # actually NOP for 3 or 4 byte sprites &0022 e8 INX ; inx_5 # actually NOP for 4 byte sprites &0023 c6 45 DEC &45 ; lines_to_plot &0025 f0 0b BEQ &0032 ; plot_next_slice &0027 88 DEY &0028 10 e8 BPL &0012 ; push_sprite_to_screen_slice_loop &002a a0 07 LDY #&07 &002c e6 14 INC &14 ; sprite_read_address_high &002e e6 1d INC &1d ; sprite_write_address_high &0030 10 e0 BPL &0012 ; push_sprite_to_screen_slice_loop ; plot_next_slice &0032 e6 01 INC &01 ; sprite_slice_to_plot_zero_page_byte &0034 a5 13 LDA &13 ; sprite_read_address_low &0036 18 CLC &0037 69 08 ADC #&08 ; adc_value # actually ADC #&f8 for flipped sprites &0039 85 13 STA &13 ; sprite_read_address_low &003b 85 1c STA &1c ; sprite_write_address_low &003d e6 05 INC &05 ; slice_number &003f c6 46 DEC &46 ; bytes_per_line_of_sprite &0041 d0 bd BNE &0000 ; push_sprite_to_screen_buffer &0043 60 RTS ; unused &64b4 78 48 6e 40 d4 73 69 6e 37 64 21 26 cd ab 16 8c &64c4 19 21 94 13 6e bc c7 08 11 7c 27 4c 70 cd 5b c7 &64d4 32 d3 5e e2 59 f5 e7 7a 00 8b a3 29 37 b1 8c 5a &64e4 fc d4 7a 53 21 bd e2 25 51 e4 9b 5d 4c fb 6e 72 &64f4 f0 83 5f 04 1e 8d 8f b4 5b bd 69 86 78 d3 2a d1 &6504 16 07 ba 08 a3 a2 e2 e6 3b dc 6b 2f 06 f1 92 e8 &6514 0a 23 a9 8e 12 19 37 87 17 f9 5f 8f bd a4 b8 05 &6524 d7 e7 95 52 02 80 0b 6c f4 22 eb ec 38 ff ae 1d &6534 55 ae 9b ac 59 f5 8c 65 85 97 f2 33 7b 9f 4f 54 &6544 3d 28 49 88 07 ac 1b a7 35 01 ae 8e 69 af 0d 9d &6554 66 ca e1 cf 91 71 ; entry_point ; via_decryption # VIA decryption method identical to previous binary &6bea 78 SEI &6beb a9 df LDA #&df # Set User VIA timer 2 to timed interrupt &6bed 2d 6b fe AND &fe6b ; User VIA auxiliary control register &6bf0 8d 6b fe STA &fe6b ; User VIA auxiliary control register &6bf3 a9 a0 LDA #&a0 # Enable interrupts for User VIA timer 2 &6bf5 8d 6e fe STA &fe6e ; User VIA interrupt enable register &6bf8 a9 ff LDA #&ff &6bfa 8d 68 fe STA &fe68 ; User VIA timer 2 counter LSB &6bfd 8d 69 fe STA &fe69 ; User VIA timer 2 counter MSB &6c00 a2 00 LDX #&00 ; via_decryption_loop &6c02 ad 00 6c LDA &6c00 # Runs from &6c00 to &6cff, # actually LDA &6c00 + via_decryption_offset # EORs all of &6d00 - &6dff on every loop &6c05 ee 1d 6c INC &6c1d ; via_decryption_eor &6c08 18 CLC &6c09 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6c0c a8 TAY &6c0d ad 1d 6c LDA &6c1d ; via_decryption_eor &6c10 4d fc ff EOR &fffc ; os_reset_address_low # Ensure 6502 reset vector hasn't been changed &6c13 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6c16 8d 1b 6c STA &6c1b ; via_decryption_add &6c19 98 TYA &6c1a 69 6d ADC #&6d # actually ADC via_decryption_add &6c1c 49 00 EOR #&00 # actually EOR via_decryption_eor &6c1e 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6c21 4d 40 d9 EOR &d940 ; os_default_vector_table # Ensure OS default vector table hasn't been changed # actually EOR &d900 + via_decryption_rom_offset_one &6c24 ee 1d 6c INC &6c1d ; via_decryption_eor &6c27 4d 69 fe EOR &fe69 ; User VIA timer 2 counter MSB &6c2a 4d cd d9 EOR &d9cd ; os_reset_handler # Ensure OS reset handler hasn't been changed # actually EOR &d900 + via_decryption_rom_offset_two &6c2d 5d 02 6c EOR &6c02,X ; via_decryption_loop &6c30 4d 1c dc EOR &dc1c ; os_irq_handler # Ensure OS main IRQ handler hasn't been changed # actually EOR &dc00 + via_decryption_rom_offset_three &6c33 5d 00 6d EOR &6d00,X ; payload &6c36 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6c39 4d d9 ea EOR &ead9 ; os_break_intercept_handler # Ensure OS break intercept handler hasn't been changed # actually EOR &ea00 + via_decryption_rom_offset_four # (OSBYTE 247 (&f7), calls &0287 after BREAK) &6c3c 38 SEC &6c3d 6d 03 6c ADC &6c03 ; via_decryption_offset &6c40 4d fd ff EOR &fffd ; os_reset_address_high &6c43 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6c46 18 CLC &6c47 7d 01 6d ADC &6d01,X ; payload + 1 # Runs from &6d01 to &6e00 &6c4a 4d 93 dc EOR &dc93 ; os_irq1v_handler # Ensure OS IRQ1 handler hasn't been changed # actually EOR &dc00 + via_decryption_rom_offset_five &6c4d ee 1b 6c INC &6c1b ; via_decryption_add &6c50 a8 TAY &6c51 ad 1b 6c LDA &6c1b ; via_decryption_add &6c54 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6c57 8d 1b 6c STA &6c1b ; via_decryption_add &6c5a 98 TYA &6c5b 4d b0 da EOR &dab0 ; ? # Runs over &da00 - &daff # actually EOR &da00 + via_decryption_rom_offset_six # (System VIA setup, OS sideways ROM checking) &6c5e 4d 69 fe EOR &fe69 ; User VIA timer 2 counter MSB &6c61 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6c64 9d 00 6d STA &6d00,X ; payload &6c67 e8 INX &6c68 d0 98 BNE &6c02 ; via_decryption_loop &6c6a a9 03 LDA #&03 &6c6c 8d 58 02 STA &0258 ; ESCAPE/BREAK effect &6c6f a9 4c LDA #&4c ; JMP # Set BREAK intercept code to JMP &0287, endless loop &6c71 8d 87 02 STA &0287 ; BREAK intercept code &6c74 a9 87 LDA #&87 &6c76 8d 88 02 STA &0288 ; BREAK intercept code + 1 &6c79 a9 02 LDA #&02 &6c7b 8d 89 02 STA &0289 ; BREAK intercept code + 2 &6c7e ee 31 6c INC &6c31 ; via_decryption_rom_offset_three &6c81 ee 2b 6c INC &6c2b ; via_decryption_rom_offset_two &6c84 ee 3a 6c INC &6c3a ; via_decryption_rom_offset_four &6c87 a0 35 LDY #&35 ; reset_vector_table_loop &6c89 b9 40 d9 LDA &d940,Y ; os_default_vector_table &6c8c 99 00 02 STA &0200,Y ; os_vector_table # Reset all vectors to OS default &6c8f 88 DEY &6c90 10 f7 BPL &6c89 ; reset_vector_table_loop &6c92 ee 22 6c INC &6c22 ; via_decryption_rom_offset_one &6c95 ee 4b 6c INC &6c4b ; via_decryption_rom_offset_five &6c98 ee 5c 6c INC &6c5c ; via_decryption_rom_offset_six &6c9b ad 1d 6c LDA &6c1d ; via_decryption_eor &6c9e 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6ca1 8d 1d 6c STA &6c1d ; via_decryption_eor &6ca4 ee 1d 6c INC &6c1d ; via_decryption_eor &6ca7 ee 03 6c INC &6c03 ; via_decryption_offset &6caa ad 03 6c LDA &6c03 ; via_decryption_offset &6cad c9 00 CMP #&00 &6caf f0 03 BEQ &6cb4 ; calculate_checksum &6cb1 4c 02 6c JMP &6c02 ; via_decryption_loop ; calculate_checksum &6cb4 a9 00 LDA #&00 # Checksum &6d00 - &6dfd &6cb6 85 70 STA &70 ; calculated_checksum_one &6cb8 85 71 STA &71 ; calculated_checksum_two &6cba a8 TAY ; calculate_checksum_loop &6cbb a5 71 LDA &71 ; calculated_checksum_two &6cbd 59 00 6d EOR &6d00,Y ; payload &6cc0 85 71 STA &71 ; calculated_checksum_two &6cc2 a2 08 LDX #&08 ; calculate_checksum_inner_loop &6cc4 a5 71 LDA &71 ; calculated_checksum_two &6cc6 2a ROL A &6cc7 90 0c BCC &6cd5 ; clear_set &6cc9 a5 71 LDA &71 ; calculated_checksum_two &6ccb 49 08 EOR #&08 &6ccd 85 71 STA &71 ; calculated_checksum_two &6ccf a5 70 LDA &70 ; calculated_checksum_one &6cd1 49 10 EOR #&10 &6cd3 85 70 STA &70 ; calculated_checksum_one ; clear_set &6cd5 26 70 ROL &70 ; calculated_checksum_one &6cd7 26 71 ROL &71 ; calculated_checksum_two &6cd9 ca DEX &6cda d0 e8 BNE &6cc4 ; calculate_checksum_inner_loop &6cdc c8 INY &6cdd c0 fe CPY #&fe &6cdf d0 da BNE &6cbb ; calculate_checksum_loop &6ce1 a5 70 LDA &70 ; calculated_checksum_one &6ce3 cd fe 6d CMP &6dfe ; valid_checksum_one &6ce6 d0 07 BNE &6cef ; invalid_checksum &6ce8 a5 71 LDA &71 ; calculated_checksum_two &6cea cd ff 6d CMP &6dff ; valid_checksum_two &6ced f0 11 BEQ &6d00 ; payload # If the checksum matches, run the decrypted code ; invalid_checksum &6cef a9 c8 LDA #&c8 ; Read/Write BREAK/ESCAPE effect # This is handled by the OS OSBYTE handler at &e99c, &6cf1 a2 03 LDX #&03 ; Clear memory on next RESET # which isn't checked in the decryption routine, &6cf3 a0 00 LDY #&00 # so could be intercepted with a custom ROM &6cf5 20 f4 ff JSR &fff4 ; OSBYTE ; endless_wiping_loop # Otherwise, if the checksum doesn't match, &6cf8 99 00 6d STA &6d00,Y ; payload # Wipe &4400 - &44ff (failed decryption) with &c8 &6cfb c8 INY &6cfc d0 fa BNE &6cf8 ; endless_wiping_loop &6cfe f0 f8 BEQ &6cf8 ; endless_wiping_loop # &6d00 - &6dff is decrypted by via_decryption ; payload &6d00 a9 03 LDA #&03 # Disable transmit and receiver interrupts &6d02 8d 08 fe STA &fe08 ; Cassette ACIA control register &6d05 a9 64 LDA #&64 &6d07 8d 10 fe STA &fe10 ; Serial ULA control register # Switch off cassette motor ; irq_trap &6d0a ad fe ff LDA &fffe ; os_irq_address_low # Infinite loop if OS IRQ address isn't as expected &6d0d c9 1c CMP #&1c &6d0f d0 f9 BNE &6d0a ; irq_trap &6d11 ad ff ff LDA &ffff ; os_irq_address_high &6d14 c9 dc CMP #&dc &6d16 d0 f2 BNE &6d0a ; irq_trap &6d18 a9 20 LDA #&20 # Disable User VIA timer 2 interrupts &6d1a 8d 6e fe STA &fe6e ; User VIA interrupt enable register &6d1d a9 03 LDA #&03 # Enable ESCAPE, clear memory on BREAK &6d1f 8d 58 02 STA &0258 ; ESCAPE/BREAK effect &6d22 a2 ff LDX #&ff &6d24 9a TXS ; decrypt_main_code &6d25 a9 00 LDA #&00 &6d27 85 70 STA &70 ; address_low &6d29 a9 04 LDA #&04 ; &0400 &6d2b 85 71 STA &71 ; address_high &6d2d a0 00 LDY #&00 ; decrypt_main_code_loop &6d2f b1 70 LDA (&70),Y ; address # Decrypt &0400 - &54ff &6d31 38 SEC # (suggests code reuse, as game data is &0750 - &5469) &6d32 e9 49 SBC #&49 &6d34 49 d4 EOR #&d4 &6d36 91 70 STA (&70),Y ; address &6d38 c8 INY &6d39 d0 f4 BNE &6d2f ; decrypt_main_code_loop &6d3b e6 71 INC &71 ; address_high &6d3d a5 71 LDA &71 ; address_high &6d3f c9 55 CMP #&55 &6d41 90 ec BCC &6d2f ; decrypt_main_code_loop &6d43 a2 43 LDX #&43 ; wipe_6d01_to_6d43_loop &6d45 9d 00 6d STA &6d00,X ; payload # Wipe &6d01 - &6d43 (decryption code) &6d48 ca DEX &6d49 d0 fa BNE &6d45 ; wipe_6d01_to_6d43_loop &6d4b a9 0c LDA #&0c # R12: Displayed screen start address register (high) &6d4d 8d 00 fe STA &fe00 ; video register number &6d50 a9 0a LDA #&0a &6d52 8d 01 fe STA &fe01 ; video register value &6d55 a9 0d LDA #&0d # R13: Displayed screen start address register (low) &6d57 8d 00 fe STA &fe00 ; video register number &6d5a a9 80 LDA #&80 # Set screen start address to &5400 &6d5c 8d 01 fe STA &fe01 ; video register value &6d5f a9 06 LDA #&06 # R6: Vertical displayed register &6d61 8d 00 fe STA &fe00 ; video register number &6d64 a9 17 LDA #&17 # Set screen to be 23 characters (184 pixels) high &6d66 8d 01 fe STA &fe01 ; video register value &6d69 58 CLI ; generate_random_seed &6d6a ad 40 02 LDA &0240 ; os_cfs_timeout_counter &6d6d f0 fb BEQ &6d6a ; generate_random_seed # Ensure non-zero seed &6d6f 85 76 STA &76 ; rnd_1 &6d71 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &6d74 f0 f4 BEQ &6d6a ; generate_random_seed # Ensure non-zero seed &6d76 85 77 STA &77 ; rnd_2 &6d78 4d 69 fe EOR &fe69 ; User VIA timer 2 counter MSB &6d7b f0 ed BEQ &6d6a ; generate_random_seed # Ensure non-zero seed &6d7d 85 78 STA &78 ; rnd_3 &6d7f a0 43 LDY #&43 ; relocate_zero_page_code_loop &6d81 b9 00 6b LDA &6b00,Y ; unrelocated_zero_page_code # Move &6b00 - &6b43 to &0000 - &0043 &6d84 99 00 00 STA &0000,Y ; zero_page_code &6d87 88 DEY &6d88 10 f7 BPL &6d81 ; relocate_zero_page_code_loop &6d8a a9 0a LDA #&0a &6d8c 8d 18 07 STA &0718 ; objects_size_x # Player's feet &6d8f 8d 19 07 STA &0719 ; objects_size_x + 1 # Player's head &6d92 8d 1a 07 STA &071a ; objects_size_x + 2 # Charm 1 &6d95 8d 1b 07 STA &071b ; objects_size_x + 3 # Charm 2 &6d98 8d fc 06 STA &06fc ; objects_size_z # Player's fee &6d9b 8d fd 06 STA &06fd ; objects_size_z + 2 # Player's head &6d9e 8d fe 06 STA &06fe ; objects_size_z + 3 # Charm 1 &6da1 8d ff 06 STA &06ff ; objects_size_z + 4 # Charm 2 &6da4 4c 00 54 JMP &5400 ; continue_initialisation ; unused &6da7 48 65 6c 6c 6f 2c 79 6f 75 20 74 6f 6f 6b 20 79 ; "Hello,you took y" &6db7 6f 75 72 20 74 69 6d 65 20 21 50 72 6f 74 65 63 ; "our time !Protec" &6dc7 74 69 6f 6e 20 64 65 73 69 67 6e 65 64 20 61 6e ; "ion designed and" &6dd7 64 20 69 6d 70 6c 65 6d 65 6e 74 65 64 20 62 79 ; " implemented by " &6de7 20 4b 65 76 69 6e 20 45 64 77 61 72 64 73 20 28 ; "Kevin Edwards (c" &6df7 63 29 20 31 39 38 35 ; ") 1985" ; valid_checksum_one &6dfe c2 ; valid_checksum_two &6dff b0 &6e00 00 # Used at &6c47 in final round of via_decryption