Zalaga disassembly ================== Zalaga was written by Nick "Orlando" Pelling, and was published by Aardvark Software for the BBC Micro in 1983. It is an unofficial conversion of Namco's similarly titled 1981 arcade game, Galaga. The following disassembly was created by reverse engineering binary images, without access to any source code. It is nevertheless reasonably complete, allowing the technical approaches used to be understood. The author of this disassembly imposes no additional copyright restrictions beyond those already present on the game itself. It is provided for educational purposes only, and it is hoped that the original authors will accept it in the good faith it was intended - as a tribute to their skills. Technical notes =============== The last block of the loader and game contains a false load address. The loader uses the following unofficial 6502 opcodes to disguise its code: af .. .. LAX &.... Equivalent to LDA &.... : LDX &.... 4b .. ALR #&.. Equivalent to AND #&.. : LSR A 4f .. .. SRE &.... Equivalent to LSR &.... : EOR &.... 04 .. NOP &.. 3c .. .. NOP &....,X 54 .. NOP &..,X 5c .. .. NOP &....,X 64 .. NOP &.. 74 .. NOP &..,X 7c .. .. NOP &....,X 99 .. NOP &.. c2 .. NOP #&.. Equivalent to NOP, but skip one or two bytes Part of the string "Orlando M. Pilchard" is processed as instructions. The disassembly analyses each stage after decryption has taken place. The game uses the following unofficial 6502 opcodes: dc .. .. NOP &.... Equivalent to NOP, but skip two bytes 87 .. SAX &.. Equivalent to STX &.. : PHA : AND &.. : STA &.. : PLA 4b .. ALR #&.. Equivalent to AND #&.. : LSR A 07 .. SLO &.. Equivalent to ASL &.. : ORA &.. The unofficial two byte NOP is used for efficient branching. A combination of SAX, ALR and SLO is used to reverse pixel pairs. Sprite are animated by changing the palette. Sprites are plotted using partially unrolled loops, and can be plotted horizontally or vertically flipped. Enemy slots are used as follows: &00 - &27 passive enemies &28 - &34 active enemies &35 - &3e enemy bombs &3f - &48 explosions Every active enemy has a corresponding passive enemy slot. After initialisation, &0400 - &0642 is used as follows: &0400 - &0448 ; enemies_x ; slots &00 - &48 (all) &0449 - &0491 ; enemies_y ; slots &00 - &48 (all) &0492 - &04da ; enemies_sprite ; slots &00 - &48 (all) &04db - &0523 ; enemies_screen_address_high ; slots &00 - &48 (all) &0524 - &056c ; enemies_screen_address_low ; slots &00 - &48 (all) &058e - &059a ; enemies_action ; slots &28 - &34 (active enemies) &059b - &05a4 ; enemies_bomb_direction ; slots &35 - &3e (enemy bombs) &05a5 - &05ae ; enemies_explosion_frame ; slots &3f - &48 (explosions) &05af - &05ed ; enemies_type_and_flags ; slots &00 - &3e (passive and active enemies, enemy bombs) &05ee - &05fa ; enemies_pattern_address_low ; slots &28 - &34 (active enemies) ; enemies_frames_to_return ; slots &28 - &34 (active enemies) &05fb - &0604 ; enemies_bomb_x_fraction ; slots &35 - &3e (enemy bombs) &0605 - &0611 ; enemies_pattern_address_high ; slots &28 - &34 (active enemies) &0612 - &061b ; enemies_bomb_x_speed ; slots &35 - &3e (enemy bombs) &061c - &0628 ; enemies_movement_duration ; slots &28 - &34 (active enemies) &0629 - &0635 ; enemies_passive_slot ; slots &28 - &34 (active enemies) &0636 - &0642 ; enemies_next_bombing_frame ; slots &28 - &34 (active enemies) &0643 - &066a ; enemies_home_column (constant) ; slots &00 - &27 (passive enemies) &066b - &0692 ; enemies_home_row (constant) ; slots &00 - &27 (passive enemies) Interesting pokes ================= &13a5 = &b5 infinite lives &159b = &18 invulnerability Loader disassembly ================== ; ZALAGA ; FFFF2400 FFFF2412 00000B00 # Actually loads at &23ee ; to_decrypt_decrypt_payload # &23ee - &23ff is "Orlando M.Pilchard" &23ee 4f 72 6c SRE &6c72 ; "Orl" # Obfuscation; equivalent to LSR &6c72 : EOR &6c72 &23f1 61 6e ADC (&6e,X) ; "an" # Obfuscation &23f3 64 6f NOP &6f ; "do" # Obfuscation &23f5 20 4d 2e JSR &2e4d ; decrypt_decrypt_payload ; " M." # Never returns ; unused_code &23f8 50 69 BVC &2463 ; "Pi &23fa 6c 63 68 JMP (&6863) ; "lch" ; unused &23fd 61 72 64 ; "ard" ; false_entry_point # This is at &2412 if loaded at &2400 &2400 a2 00 LDX #&00 ; write_software_protected_loop &2402 bd 44 24 LDA &2444,X ; software_protected_string + &12 # If so, software_protected_string is also offset &2405 20 ee ff JSR &ffee ; OSWRCH &2408 e8 INX &2409 e0 14 CPX #&14 &240b 90 f5 BCC &2402 ; write_software_protected_loop ; infinite_loop &240d 18 CLC &240e 90 fd BCC &240d ; infinite_loop ; unused &2410 48 61 ; entry_point &2412 af eb ff LAX &ffeb # Equivalent to LDA &ffeb : LDX &ffeb ; ?&ffeb = &ff &2415 4b c5 ALR #&c5 # Equivalent to AND #&c5 : LSR A ; sets carry &2417 74 a9 NOP &a9,X # Obfuscation &2419 b0 d3 BCS &23ee ; to_decrypt_decrypt_payload # Always branches ; unused &241b 7a 39 90 95 e3 38 2d ed c7 ed 23 2a 30 92 4e ; unused &242a 48 61 48 61 48 61 21 20 ; "HaHaHa! " ; software_protected_string &2432 20 53 6f 66 74 77 61 72 65 20 50 72 6f 74 65 63 ; " Software Protected " &2442 74 65 64 20 ; copy_title_screen &2446 08 PHA &2447 a9 16 LDA #&16 # Change to MODE 7 &2449 20 ef ff JSR &ffee ; OSWRCH &244d a9 07 LDA #&07 &244e 20 ee ff JSR &ffee ; OSWRCH &2451 a9 1c LDA #&1c # Define text window x:(6, 32), y:(22, 24) &2453 20 ee ff JSR &ffee ; OSWRCH &2456 a9 06 LDA #&06 &2458 20 ee ff JSR &ffee ; OSWRCH &245b a9 18 LDA #&18 &245d 20 ee ff JSR &ffee ; OSWRCH &2460 a9 20 LDA #&20 &2462 20 ee ff JSR &ffee ; OSWRCH &2465 a9 16 LDA #&16 &2467 20 ee ff JSR &ffee ; OSWRCH &246a a2 00 LDX #&00 ; copy_title_screen_loop &246c bd 82 25 LDA &2582,X ; title_screen_data &246f 9d 00 7c STA &7c00,X ; screen_memory &2472 bd 82 26 LDA &2682,X ; title_screen_data + &100 &2475 9d 00 7d STA &7d00,X ; screen_memory + &100 &2478 bd 82 27 LDA &2782,X ; title_screen_data + &200 &247b 9d 00 7e STA &7e00,X ; screen_memory + &200 &247e bd 82 28 LDA &2882,X ; title_screen_data + &300 &2481 9d 00 7f STA &7f00,X ; screen_memory + &300 &2484 e8 INX &2485 d0 e5 BNE &246c ; copy_title_screen_loop &2487 28 PLP # Not PLA; clears carry for decrypt_payload # &2488 - &2580 is decrypted at &2e74 ; decrypt_payload &2488 a0 00 LDY #&00 # &2488 is RTS prior to decrypt_decrypt_payload ; decrypt_payload_loop &248a b9 a7 24 LDA &24a7,Y ; key &248d 7d 82 29 ADC &2982,X ; encrypted_payload &2490 9d 00 04 STA &0400,X ; payload &2493 fd 82 2a SBC &2a82,X ; encrypted_payload + &100 &2496 9d 00 05 STA &0500,X ; payload + &100 &2499 c8 INY &249a 98 TYA &249b 49 da EOR #&da &249d d0 02 BNE &24a1 ; skip_wraparound &249f a0 00 LDY #&00 ; skip_wraparound &24a1 e8 INX &24a2 d0 e6 BNE &248a ; decrypt_payload_loop &24a4 4c 00 04 JMP &0400 ; payload ; key &24a7 4e 6f 73 65 79 20 62 61 73 74 61 72 64 21 20 54 ; "Nosey bastard! T" &24b7 68 69 73 20 69 73 20 73 75 70 70 6f 73 65 64 20 ; "his is supposed " &24c7 74 6f 20 62 65 20 70 72 6f 74 65 63 74 65 64 2c ; "to be protected," &24d7 20 73 6f 20 67 65 74 20 79 6f 75 72 20 66 61 74 ; " so get your fat" &24e7 20 66 69 6e 67 65 72 73 20 6f 75 74 20 6f 66 20 ; " fingers out of " &24f7 6d 79 20 63 6f 64 65 21 20 41 6e 79 77 61 79 2c ; "my code! Anyway," &2507 20 74 68 61 74 20 62 69 74 20 77 61 73 20 65 61 ; " that bit was ea" &2517 73 79 20 2d 20 74 68 65 20 6e 65 78 74 20 69 73 ; "sy - the next is" &2527 20 74 68 65 20 72 65 61 6c 20 74 65 73 74 2c 20 ; " the real test, " &2537 4d 72 20 53 6f 66 74 77 61 72 65 20 50 69 72 61 ; "Mr Software Pira" &2547 74 65 21 20 28 75 6e 6c 65 73 73 20 79 6f 75 27 ; "te! (unless you'" &2557 72 65 20 63 68 65 61 74 69 6e 67 29 20 2e 2e 2e ; "re cheating) ..." &2567 28 43 29 20 31 39 38 33 20 41 61 72 64 76 61 72 ; "(C) 1983 Aardvar" &2577 6b 20 53 6f 66 74 77 61 72 65 ; "k Software" ; unused &2581 b7 ; title_screen_data &2582 8d 83 41 61 72 64 76 61 72 6b 20 53 6f 66 74 77 ; "..Aardvark Software presents " &2592 61 72 65 20 70 72 65 73 65 6e 74 73 20 20 20 20 ; "..Aardvark Software presents.... " &25a2 20 20 20 20 20 20 20 20 8d 83 41 61 72 64 76 61 ; ".... " &25b2 72 6b 20 53 6f 66 74 77 61 72 65 20 70 72 65 73 ; "....x.........vo..vovo....vo.....vo...t " &25c2 65 6e 74 73 2e 2e 2e 2e 20 20 20 20 20 20 20 20 ; "...............j...j.j.....j......j.... " &25d2 9a 94 1d 93 20 20 20 20 20 20 20 20 20 20 20 20 ; "....+.........?z...j.j.....j.....g~.... " &25e2 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; ".... `~...?!j...j.j j...j! h||. j... " &25f2 20 20 20 20 20 20 20 20 1a 94 1d 93 78 7f 7f 7f ; ".... x....g~|~...j.j|~...j .b||vl~... " &2602 7f 7f 7f 7f 7f 7f 76 6f 7f 7f 76 6f 76 6f 7f 7f ; ".... `~...?)//.....j.://...j0 z...j.... " &2612 7f 7f 76 6f 7f 7f 7f 7f 7f 76 6f 7f 7f 7f 74 20 ; "....x.........vo...j....vo.j......"k... " &2622 9a 94 9d 93 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 6a ; "...............j...j.....j.j...... j... " &2632 7f 7f 7f 6a 7f 6a 7f 7f 7f 7f 7f 6a 7f 7f 7f 7f ; "....+.........'"o.g~....g~g~....?! "o.' " &2642 7f 7f 6a 7f 7f 7f 7f 20 9a 94 9d 93 2b 7f 7f 7f ; " .. " &2652 7f 7f 7f 7f 7f 7f 3f 7a 7f 7f 7f 6a 7f 6a 7f 7f ; " ...1 or 2 Player game....."1" or "2" " &2662 7f 7f 7f 6a 7f 7f 7f 7f 7f 67 7e 7f 7f 7f 7f 20 ; " ... " &2672 9a 94 9d 93 20 20 20 20 60 7e 7f 7f 7f 3f 21 6a ; " ...Keyboard..."K" Joysticks..."J" " &2682 7f 7f 7f 6a 7f 6a 20 6a 7f 7f 7f 6a 21 20 68 7c ; " ... " &2692 7c 7f 20 6a 7f 7f 7f 20 9a 94 9d 93 20 20 20 78 ; " ...Sound on..."S" Sound off..."Q" " &26a2 7f 7f 7f 7f 67 7e 7c 7e 7f 7f 7f 6a 7f 6a 7c 7e ; " ... " &26b2 7f 7f 7f 6a 20 1f 62 7c 7c 76 6c 7e 7f 7f 7f 20 ; " ... To move left........CAPS LOCK " &26c2 9a 94 9d 93 20 60 7e 7f 7f 7f 3f 29 2f 2f 7f 7f ; " ... To move right..........CTRL " &26d2 7f 7f 7f 6a 7f 3a 2f 2f 7f 7f 7f 6a 30 20 7a 7f ; " ... To fire...............RETURN " &26e2 7f 7f 6a 7f 7f 7f 7f 20 9a 94 9d 93 78 7f 7f 7f ; " " &26f2 7f 7f 7f 7f 7f 7f 76 6f 7f 7f 7f 6a 7f 7f 7f 7f ; " " &2702 76 6f 7f 6a 7f 7f 7f 7f 7f 7f 22 6b 7f 7f 7f 20 ; " " &2712 9a 94 9d 93 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 6a ; " " &2722 7f 7f 7f 6a 7f 7f 7f 7f 7f 6a 7f 6a 7f 7f 7f 7f &2732 7f 7f 20 6a 7f 7f 7f 20 9a 94 9d 93 2b 7f 7f 7f &2742 7f 7f 7f 7f 7f 7f 27 22 6f 7f 67 7e 7f 7f 7f 7f &2752 67 7e 67 7e 7f 7f 7f 7f 3f 21 20 22 6f 7f 27 20 &2762 20 94 9d 20 20 20 20 20 20 20 20 20 20 20 20 20 &2772 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2782 20 20 20 20 20 20 20 20 20 81 9d 82 31 20 6f 72 &2792 20 32 20 50 6c 61 79 65 72 20 67 61 6d 65 2e 2e &27a2 2e 2e 2e 22 31 22 20 6f 72 20 22 32 22 20 20 20 &27b2 20 81 9d 82 20 20 20 20 20 20 20 20 20 20 20 20 &27c2 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &27d2 20 20 20 20 20 20 20 20 20 81 9d 82 4b 65 79 62 &27e2 6f 61 72 64 2e 2e 2e 22 4b 22 20 20 20 20 4a 6f &27f2 79 73 74 69 63 6b 73 2e 2e 2e 22 4a 22 20 20 20 &2802 20 81 9d 82 20 20 20 20 20 20 20 20 20 20 20 20 &2812 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2822 20 20 20 20 20 20 20 20 20 81 9d 82 53 6f 75 6e &2832 64 20 6f 6e 2e 2e 2e 22 53 22 20 20 20 20 53 6f &2842 75 6e 64 20 6f 66 66 2e 2e 2e 22 51 22 20 20 20 &2852 20 81 9d 82 20 20 20 20 20 20 20 20 20 20 20 20 &2862 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2872 20 20 20 20 20 20 20 20 20 81 9d 82 20 20 54 6f &2882 20 6d 6f 76 65 20 6c 65 66 74 2e 2e 2e 2e 2e 2e &2892 2e 2e 43 41 50 53 20 20 4c 4f 43 4b 20 20 20 20 &28a2 20 81 9d 82 20 20 54 6f 20 6d 6f 76 65 20 72 69 &28b2 67 68 74 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 43 54 52 &28c2 4c 20 20 20 20 20 20 20 20 81 9d 82 20 20 54 6f &28d2 20 66 69 72 65 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e &28e2 2e 2e 2e 2e 52 45 54 55 52 4e 20 20 20 20 20 20 &28f2 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2902 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2912 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2922 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2932 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2942 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2952 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2962 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &2972 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 # &2982 - &2b81 is decrytped to &0400 - &05ff at &248a ; payload &0400 78 SEI &0401 ae b7 ff LDX &ffb7 ; os_rom_default_vector_table_address_low &0404 ac b8 ff LDY &ffb8 ; os_rom_default_vector_table_address_high &0407 30 04 BMI &040d ; not_mos_1.00 &0409 a2 41 LDX #&41 ; &d941 = os_1.00_rom_default_vector_table &040b a0 d9 LDY #&d9 ; not_mos_1.00 &040d 86 72 STX &72 ; default_vector_table_address_low &040f 84 73 STY &73 ; default_vector_table_address_high &0411 20 98 05 JSR &0598 ; initialise_protected &0414 ad b6 ff LDA &ffb6 ; os_rom_vector_table_length &0417 f0 06 BEQ &041f ; not_mos_0.10 # Zero in MOS 1.00 &0419 a0 01 LDY #&01 &041b b1 72 LDA (&72),Y ; default_vector_table_address # Get high byte of USERV &041d 10 7e BPL &049d ; is_mos_0.10 ; not_mos_0.10 &041f a0 11 LDY #&11 ; reset_vector_table_loop &0421 b1 72 LDA (&72),Y ; default_vector_table_address &0423 99 00 02 STA &0200,Y ; os_vector_table &0426 88 DEY &0427 10 f8 BPL &0421 ; reset_vector_table_loop &0429 58 CLI &042a c8 INY ; 0 &042b a2 ff LDX #&ff &042d 86 c9 STX &c9 ; osfileBlockAddressLow &042f e8 INX ; 0 &0430 86 c8 STX &c8 ; osfileBlockAddressHigh &0432 a9 8b LDA #&8b ; Set filing system attributes # Restore default *OPT values &0434 20 f4 ff JSR &fff4 ; OSBYTE &0437 a2 3e LDX #&3e ; &043e = run_string &0439 a0 04 LDY #&04 &043b 4c f7 ff JMP &fff7 ; OSCLI # *RUN ; run_string &043e 2f 0d ; "/" ; loadFile # &0440 - &0455 is a reduced version of &f283 - &f2a7 &0440 20 cb f9 JSR &f9cb ; os_claimSerialSystemForLoadSave # &f283 20 cb f9 JSR &f9cb &0442 ad f8 02 LDA &02f8 ; fsExecutionAddressLow # &f286 ad f8 02 LDA &02f8 ... &0446 20 ae 04 JSR &04ae ; searchForFile # &f28a 20 b6 f6 JSR &f6b6 &0449 ae f4 02 LDX &02f4 ; fsLoadAddressLow # &f290 ae f4 02 LDX &02f4 ... &044c ad f5 02 LDA &02f5 ; fsLoadAddressMid1 # &f293 ad f5 02 LDA &02f5 ... ; loadOrRunAX &044f 86 a0 STX &a0 ; loadAddressLow # &f2a1 86 a0 STX &a0 &0451 85 a1 STA &a1 ; loadAddressMid1 # &f2a3 85 a1 STA &a1 &0453 4c 59 04 JMP &0459 ; loadOrRun # &f2a5 4c ab f2 JMP &f2ab ; loadOrRun_block_loop # &0456 - &048c is a copy of &f2a8 - &f2de &0456 20 4a 05 JSR &054a ; readBlockHeader ; loadOrRun &0459 a9 30 LDA #&30 &045b 25 ad AND &ad ; tapeCurrentOptionsByte &045d f0 04 BEQ &0463 ; skip_checksum &045f a5 b3 LDA &b3 ; checksumIsValidFlag &0461 d0 03 BNE &0466 ; checksumFail ; skip_checksum &0463 20 de f7 JSR &f7de ; os_setStateForLoadingBlockDataOrReset ; checksumFail &0466 20 59 fa JSR &fa59 ; os_loadBlock &0469 d0 2d BNE &0498 ; retryAfterFailure &046b 20 b6 fa JSR &fab6 ; os_saveByteAndIncrementBlockNumbers &046e d0 28 BNE &0498 ; retryAfterFailure &0470 20 b4 fb JSR &fbb4 ; os_incrementBlockNumbers2 &0473 2c 00 03 BIT &0300 ; fsBlockFlagByte &0476 30 12 BMI &048a ; reached_final_block &0478 ad fe 02 LDA &02fe ; fsBlockLengthLow &047b 18 CLC &047c 65 a0 ADC &a0 ; loadAddressLow &047e 85 a0 STA &a0 ; loadAddressLow &0480 ad ff 02 LDA &02ff ; fsBlockLengthHigh &0483 65 a1 ADC &a1 ; loadAddressMid1 &0485 85 a1 STA &a1 ; loadAddressMid1 &0487 4c 56 04 JMP &0456 ; loadOrRun_block_loop ; reached_final_block &048a 20 6f f9 JSR &f96f ; os_beepCancelAndPrintReturn &048d 20 ad ff JSR &ffad ; os_CNTAPE # &f2df 4c ad ff JMP &ffad &0490 a9 81 LDA #&81 # Enable CA2 interrupts &0492 8d 4e fe STA &fe4e ; System VIA interrupt enable register &0495 6c f8 02 JMP (&02f8) ; fsExecutionAddressLow # &f2f2 6c f8 02 JMP (&02f8) ; retryAfterFailure &0498 20 b4 04 JSR &04b ; searchForSpecifiedBlock # &0498 - &049c is a copy of &f2e2 - &f2e6 &049b d0 bc BNE &0459 ; loadOrRun ; is_mos_0.10 &049d 58 CLI &049e a2 01 LDX #&01 # Disable CA2 interrupts &04a0 8e 4e fe STX &fe4e ; System VIA interrupt enable register &04a3 ca DEX ; 0 &04a4 8e 09 03 STX &0309 ; filenameToSearchFor &04a7 a9 a1 LDA #&a1 # Retry, short messages &04a9 85 b9 STA &b9 ; tapeOptionsByte &04ab 4c 40 04 JMP &0440 ; loadFile ; searchForFile # &04ae - &04e8 is a copy of &f6b6 - &f6f0 &04ae a9 00 LDA #&00 &04b0 85 a4 STA &a4 ; currentBlockNumberLow &04b2 85 a5 STA &a5 ; currentBlockNumberHigh ; searchForSpecifiedBlock &04b4 a5 a4 LDA &a4 ; currentBlockNumberLow &04b6 48 PHA &04b7 85 a6 STA &a6 ; nextBlockNumberLow &04b9 a5 a5 LDA &a5 ; currentBlockNumberHigh &04bb 48 PHA &04bc 85 a7 STA &a7 ; nextBlockNumberHigh &04be 20 43 fb JSR &fb43 ; os_safePrintFollowingMessage &04c1 53 65 61 72 63 68 69 6e 67 0d 00 ; "Searching\r" &04cc a9 ff LDA #&ff &04ce 20 e9 04 JSR &04e9 ; searchForBlockCheckFilingSystem &04d1 68 PLA &04d2 85 a5 STA &a5 ; currentBlockNumberHigh &04d4 68 PLA &04d5 85 a4 STA &a4 ; currentBlockNumberLow &04d7 a5 a6 LDA &a6 ; nextBlockNumberLow &04d9 05 a6 ORA &a6 ; nextBlockNumberLow &04db d0 09 BNE &04e6 ; leave_with_minus_one &04dd 85 a4 STA &a4 ; currentBlockNumberLow &04df 85 a5 STA &a5 ; currentBlockNumberHigh &04e1 a2 e7 LDX #&e7 &04e3 20 d6 fb JSR &fbd6 ; os_copyToSoughtFilename ; leave_with_minus_one &04e6 a0 ff LDY #&ff &04e8 60 RTS ; searchForBlockCheckFilingSystem # &04e9 - &0549 is a copy of &f34b - &f3ae &04e9 48 PHA &04ea 20 4a 05 JSR &054a ; readBlockHeader &04ed ad fc 02 LDA &02fc ; fsBlockNumberLow &04f0 85 a4 STA &a4 ; currentBlockNumberLow &04f2 ad fd 02 LDA &02fd ; fsBlockNumberHigh &04f5 85 a5 STA &a5 ; currentBlockNumberHigh &04f7 a2 ff LDX #&ff &04f9 86 ba STX &ba ; fsLastBlockReadFlagsCopy &04fb e8 INX &04fc 86 ab STX &ab ; currentBlockHasDataErrorFlag &04fe f0 10 BEQ &0510 ; skip_reset # Always branches ; resetBlockNumberAndContinue &0500 a9 ff LDA #&ff &0502 85 ba STA &ba ; fsLastBlockReadFlagsCopy &0504 8d fc 02 STA &02fc ; fsBlockNumberLow &0507 8d fd 02 STA &02fd ; fsBlockNumberHigh ; searchForBlockLoop &050a 20 b4 fb JSR &fbb4 ; os_incrementBlockNumbers2 &050d 20 4a 05 JSR &054a ; readBlockHeader ; skip_reset &0510 68 PLA &0511 48 PHA &0512 f0 1b BEQ &052f ; finishReadingBlockAndContinue &0514 20 04 fb JSR &fb04 ; os_compareFilenameToSearchFor &0517 d0 16 BNE &052f ; finishReadingBlockAndContinue &0519 a9 30 LDA #&30 &051b 25 ad AND &ad ; tapeCurrentOptionsByte &051d f0 0e BEQ &052d ; pullAAndReturn &051f ad fc 02 LDA &02fc ; fsBlockNumberLow &0522 c5 a6 CMP &a6 ; nextBlockNumberLow &0524 d0 09 BNE &052f ; finishReadingBlockAndContinue &0526 ad fd 02 LDA &02fd ; fsBlockNumberHigh &0529 c5 a7 CMP &a7 ; nextBlockNumberHigh &052b d0 02 BNE &052f ; finishReadingBlockAndContinue ; pullAAndReturn &052d 68 PLA &052e 60 RTS ; finishReadingBlockAndContinue &052f 50 03 BVC &0534 ; skip_set_progress_state &0531 20 da f7 JSR &f7da ; os_setProgressState4 ; skip_set_progress_state &0534 20 db f8 JSR &f8db ; os_generateScreenReports &0537 a2 00 LDX #&00 &0539 20 81 fa JSR &fa81 ; os_checkForChecksumError ; wait_for_state &053c a5 b4 LDA &b4 ; fsReadProgressState &053e d0 fc BNE &053c ; wait_for_state &0540 20 b9 fa JSR &fab9 ; os_incrementBlockNumbers &0543 2c 00 03 BIT &0300 ; fsBlockFlagByte &0546 30 b8 BMI &0500 ; resetBlockNumberAndContinue &0548 10 c0 BPL &050a ; searchForBlockLoop # Always branches ; readBlockHeader # &054a - &058c is a reduced copy of &f748 - &f790 &054a 20 c1 f7 JSR &f7c1 ; os_readTapeBlockHeader ; startOfBlock &054d a0 00 LDY #&00 &054f 84 b0 STY &b0 ; tapeChecksumLow &0551 84 b1 STY &b1 ; tapeChecksumHigh ; read_filename_loop &0553 20 91 f7 JSR &f791 ; os_readByteFromTape1 &0556 50 1c BVC &0574 ; reachedEndOfHeader # &f754 50 22 BVC &f778 ... &0558 99 e8 02 STA &02e8,Y ; fsFilename &055b c9 00 CMP #&00 &055d f0 06 BEQ &0565 ; end_of_filename &055f c8 INY &0560 c0 0b CPY #&0b &0562 d0 ef BNE &0553 ; read_filename_loop &0564 88 DEY ; end_of_filename &0565 a2 0c LDX #&0c ; readBlockHeaderLoop &0567 20 91 f7 JSR &f791 ; os_readByteFromTape1 &056a 50 08 BVC &0574 ; reachedEndOfHeader &056c 9d e8 02 STA &02e8,X ; fsFilename &056f e8 INX &0570 e0 1f CPX #&1f &0572 d0 f3 BNE &0567 ; readBlockHeaderLoop ; reachedEndOfHeader &0574 a9 00 LDA #&00 &0576 99 e8 02 STA &02e8,Y ; fsFilename &0579 a5 b0 LDA &b0 ; tapeChecksumLow &057b 05 b1 ORA &b1 ; tapeChecksumHigh &057d 85 b3 STA &b3 ; checksumIsValidFlag &057f a9 00 LDA #&00 &0581 85 b0 STA &b0 ; tapeChecksumLow &0583 85 b1 STA &b1 ; tapeChecksumHigh &0585 85 b4 STA &b4 ; fsReadProgressState &0587 98 TYA &0588 f0 c0 BEQ &054a ; readBlockHeader &058a a0 00 LDY #&00 &058c 60 RTS ; protected_string &058d 3f 64 65 74 63 65 74 6f 72 70 3f ; "?detcetorp?" ; initialise_protected &0598 a2 0a LDX #&0a ; initialise_protected_loop &059a bd 8d 05 LDA &058d,X ; protected_string &059d 95 01 STA &01,X ; protected &059f ca DEX &05a0 10 f8 BPL &059a ; initialise_protected_loop &05a2 60 RTS ; unused &05a3 57 65 6c 6c 20 64 6f 6e 65 21 20 59 6f 75 20 6d ; "Well done! You m" &05b3 69 67 68 74 20 73 61 79 20 74 68 61 74 20 49 27 ; "ight say that I'" &05c3 6d 20 61 6c 6d 6f 73 74 20 69 6d 70 72 65 73 73 ; "m almost impress" &05d3 65 64 2e 2e 2e 20 62 75 74 20 74 68 65 72 65 20 ; "ed... but there " &05e3 69 73 20 73 74 69 6c 6c 20 77 6f 72 6b 20 74 6f ; "is still work to" &05f3 20 62 65 20 64 6f 6e 65 2e 2e 2e 2e 2e ; " be done....." ; unused &2b82 a4 0f 22 19 47 3c 15 0e 18 0c e6 da f4 9c 0d bb &2b92 95 d4 45 80 51 25 48 d3 fa b1 90 48 d6 e6 6b f8 &2ba2 cd 38 02 99 8c 93 79 95 5f 3d 44 35 20 45 0c 45 &2bb2 6d 73 bf bd 4d 69 27 d1 5f 69 c8 05 17 eb a2 5e &2bc2 d8 88 34 47 f4 ff 2c c4 d8 36 1a 95 6a 49 8d 09 &2bd2 52 86 d1 e1 65 c5 5d 60 25 a0 45 0c dd 21 f1 37 &2be2 34 91 05 3d 15 72 2e cd a1 1d 6b 7a b0 ca 0c 81 &2bf2 d4 73 77 e6 d5 f4 c0 60 75 57 8e 88 ad c0 4a 8b &2c02 87 fe 9d 84 e9 66 05 c8 18 55 dd 0b 0f e7 44 84 &2c12 2c 14 39 fc 61 2b 69 44 89 13 52 46 90 f8 1d 41 &2c22 84 60 ba 19 a8 fd 5f f9 a9 33 3c 99 82 1c b5 02 &2c32 14 d4 09 78 78 01 91 70 ec 74 4c ab ef a3 c4 84 &2c42 c3 98 d5 b8 0d 7c f4 27 81 a8 a2 4c 75 f6 50 1e &2c52 ed b7 10 8d bb e0 d4 29 7d 90 80 6b 2a 47 01 88 &2c62 f1 35 c8 cb 55 ba 6c 79 9c 61 7c 8b 31 e5 76 3b &2c72 34 aa b6 98 7c 8e 28 1f 7c c7 fc f9 f7 4b 3b 8a &2c82 b9 14 43 f3 ff ff 0c f4 05 12 49 63 f7 f6 19 8f &2c92 cc 7f 91 3c 21 68 cd db e0 83 cb 08 fc e5 02 58 &2ca2 7d 4f 0d cc 3f 80 6e 30 d5 6d df 92 83 74 3d 11 &2cb2 73 29 7d c9 41 6e 65 01 e4 60 ed fb dd 91 3a 90 &2cc2 db 09 72 1c bf 16 fd a7 71 bb 08 de 76 e3 99 c6 &2cd2 cc e2 13 ed 12 48 1c 79 be f2 9d 4a 8a 66 99 e4 &2ce2 e6 38 90 b4 d0 5d 05 10 b5 39 a7 71 60 84 7e d3 &2cf2 4c aa 7b f7 0b 2a d8 a8 a9 e3 f7 8d ff b3 c1 e8 &2d02 84 62 46 43 f8 7a 26 f2 1b 9f e1 0f d8 83 73 f3 &2d12 2c ff 6b 93 73 69 6c 9b 50 d3 c5 05 96 60 52 ce &2d22 30 07 11 b5 6f 07 11 b5 81 72 f3 7a 5f 0b 46 76 &2d32 65 4c ad a5 a3 74 78 d9 f4 57 c2 70 84 e4 93 28 &2d42 91 3b 41 67 d0 23 aa b4 16 f5 0a 2a 8e 08 c9 36 &2d52 f2 81 df 85 34 98 35 1f 09 d7 fd 76 66 71 ee b9 &2d62 a6 99 f2 77 95 51 fc 2f 80 8e c0 15 23 59 f5 bf &2d72 50 83 6f 66 23 ad 6a 42 8a 58 2b d2 f6 e8 b1 fb &2d82 9a ff 6c 4d 27 16 3e 9a 0c 2d e4 82 9f 7b 72 27 &2d92 49 b8 32 94 fc dc c1 27 65 9c 66 b1 de db 0c 33 &2da2 64 e1 8d 4b 04 9f 24 aa 66 d0 ec c3 e7 03 1d c3 &2db2 f9 92 b4 01 f0 1d 51 8a 23 fa b8 cc d7 0e 37 cf &2dc2 d4 67 fc 4e b2 96 2b 25 5a 7b 81 66 e0 1d bb d1 &2dd2 14 f7 a5 7b d5 97 e1 1f 38 b5 d1 9d 96 ac 8f 51 &2de2 2f c9 dc 2d 5a 45 33 50 f0 cd 9a 9e 5e 55 cc 26 &2df2 47 b8 78 f4 54 1c 4b cc 45 7d 86 81 6d 5b 36 11 &2e02 0f 7a 05 fa 6a e2 3d c7 04 ec 86 56 db 23 d3 4d &2e12 4b 1c 8e 69 fb 2e 19 b1 a6 a7 40 41 85 81 dd 60 &2e22 ca 2c a9 48 b1 76 6c 54 3c 2a f5 37 f0 7c 63 92 &2e32 c8 ca c1 ee a3 d7 87 51 00 d0 cb 14 7d af 74 ea &2e42 90 b6 4f 3b 80 7b b7 82 f7 eb ad ; decrypt_decrypt_payload &2e4d c2 b9 NOP #&b9 &2e4f a9 bd LDA #&bd ; LDA &....,X &2e51 04 79 NOP &79 &2e53 8d 74 2e STA &2e74 ; decrypt_decrypt_payload_loop &2e56 99 99 NOP &99 &2e58 a9 7d LDA #&7d ; ADC &....,X &2e5a 04 a0 NOP &a0 &2e5c 8d 77 2e STA &2e77 ; decrypt_decrypt_payload_loop + 3 &2e5e 54 a9 NOP &a9,X &2e61 a9 9d LDA #&9d ; STA &....,X &2e63 5c ac f4 NOP &f4ac,X &2e66 8d 7a 2e STA &2e7a ; decrypt_decrypt_payload_loop + 6 &2e69 7c 9a 0d NOP &0d9a,X &2e6c a2 00 LDX #&00 &2e6e 3c 1c c6 NOP &c61c,X &2e71 a0 f9 LDY #&f9 &2e73 18 CLC ; decrypt_decrypt_payload_loop # Decrypt &2488 - &2580 &2e74 df 88 24 DCP &2488,X # actually LDA &2488,X ; decrypt_payload # &2e74 is set to &bd at &2e53 &2e77 40 89 24 RTI : NOP #&24 # actually ADC &2489,X ; decrypt_payload + 1 # &2e77 is set to &7d at &2e5c &2e7a fb 88 24 ISC &2488,X # actually STA &2488,X ; decrypt_payload # &2e7a is set to &9d at &2e66 &2e7d e8 INX &2e7e 88 DEY &2e7f d0 f3 BNE &2e74 ; decrypt_decrypt_payload_loop &2e81 4c 46 24 JMP &2446 ; copy_title_screen ; unused &2e84 f7 ff ac ad 82 ab 6a 32 f6 d3 79 43 f2 bc 4b 95 &2e94 9c 76 cb 67 39 eb 0c c5 b4 15 91 87 f7 36 6a e6 &2ea4 63 4b b4 39 31 f4 60 0d 0b 1d df bc f7 e7 2d cc &2eb4 62 aa 1c 2d 04 72 5f 35 f4 40 75 9c 8c ea e9 d6 &2ec4 11 84 66 78 5b 9b e8 4d 09 79 42 ea 48 b7 92 b1 &2ed4 40 88 43 ca 3c 80 14 27 6e 6f a8 38 95 f5 a8 03 &2ee4 9e a6 16 d7 38 d3 d8 22 71 89 Game disassembly ================ ; ? ; FFFF2E00 FFFF4522 00002D25 # Actually loads at &3000 # &3000 - &4410 is moved to &1341 - &2751 at &4785 ; title_screen_and_play_game_loop &1341 20 9c 21 JSR &219c ; title_screen &1344 20 4a 13 JSR &134a ; play_game &1347 4c 41 13 JMP &1341 ; title_screen_and_play_game_loop ; play_game &134a 20 10 22 JSR &2210 ; plot_scores # Unplot scores &134d a9 00 LDA #&00 &134f a2 15 LDX #&15 ; initialise_variables_loop # Wipe &001f - &0033 &1351 95 1e STA &1e,X ; players_score - 1 &1353 ca DEX &1354 d0 fb BNE &1351 ; initialise_variables_loop &1356 e8 INX ; 1 ; initialise_players_loop &1357 a9 01 LDA #&01 # Players start on stage 1 &1359 95 37 STA &37,X ; players_stage &135b a9 04 LDA #&04 # Players start with four lives &135d 95 35 STA &35,X ; players_lives &135f ca DEX &1360 10 f5 BPL &1357 ; initialise_players_loop &1362 a5 3c LDA &3c ; one_or_two_players # Negative if two player game &1364 30 02 BMI &1368 ; skip_disabling_player_two &1366 85 36 STA &36 ; players_lives + 1 # Set to zero to prevent player two from playing ; skip_disabling_player_two &1368 20 10 22 JSR &2210 ; plot_scores # Plot scores ; new_player_loop &136b a9 7e LDA #&7e ; Acknowledge ESCAPE condition &136d 20 f4 ff JSR &fff4 ; OSBYTE &1370 20 e7 18 JSR &18e7 ; set_movement_and_firing_check_routine_addresses &1373 20 7c 14 JSR &147c ; remove_all_enemies &1376 a0 00 LDY #&00 ; update_ready_text &1378 20 c6 1b JSR &1bc6 ; set_additional_update_routine_address ; initialise_player &137b a9 30 LDA #&30 ; &7730 &137d 85 17 STA &17 ; player_screen_address_low &137f a9 77 LDA #&77 &1381 85 18 STA &18 ; player_screen_address_high &1383 a9 26 LDA #&26 # Player starts in middle &1385 85 16 STA &16 ; player_x &1387 20 a6 24 JSR &24a6 ; plot_lives &138a 20 87 14 JSR &1487 ; use_game_envelopes &138d a9 00 LDA #&00 &138f 85 c3 STA &c3 ; doubling_wave_present # Set to positive to indicate no wave present &1391 85 33 STA &33 ; player_dead # Set to positive to indicate player is alive &1393 85 19 STA &19 ; player_doubled # Set to zero to indicate player not doubled &1395 85 bc STA &bc ; doubling_wave_state # Set to zero to indicate no parts of wave drawn &1397 a2 01 LDX #&01 ; initialise_player_missiles_loop &1399 95 b4 STA &b4,X ; player_missiles_state # Set to zero to indicate no missile in slot &139b ca DEX &139c 10 fb BPL &1399 ; initialise_player_missiles_loop &139e 86 c5 STX &c5 ; doubling_attack_queen # Set to negative to indicate no queen doubling attacking &13a0 20 f5 12 JSR &12f5 ; plot_player &13a3 a6 32 LDX &32 ; current_player &13a5 d6 35 DEC &35,X ; players_lives ; main_game_loop &13a7 20 01 22 JSR &2201 ; update_game &13aa 20 d9 1a JSR &1ad9 ; call_additional_update_routine &13ad 24 33 BIT &33 ; player_dead # Positive if player is alive &13af 10 f6 BPL &13a7 ; main_game_loop # When the player dies, &13b1 a5 54 LDA &54 ; active_enemies &13b3 d0 f2 BNE &13a7 ; main_game_loop # Wait for all active enemies to finish &13b5 c6 4d DEC &4d ; game_state_cooldown &13b7 f0 17 BEQ &13d0 ; end_of_life &13b9 a5 4d LDA &4d ; game_state_cooldown &13bb c9 82 CMP #&82 # Display "Game Over" for 130 frames &13bd d0 e8 BNE &13a7 ; main_game_loop &13bf a6 32 LDX &32 ; current_player &13c1 b5 35 LDA &35,X ; players_lives &13c3 d0 e2 BNE &13a7 ; main_game_loop &13c5 a0 28 LDY #&28 ; "Game Over" &13c7 20 93 20 JSR &2093 ; plot_unplottable_text &13ca 20 73 17 JSR &1773 ; plot_player_one_or_player_two &13cd 4c a7 13 JMP &13a7 ; main_game_loop ; end_of_life &13d0 a6 32 LDX &32 ; current_player &13d2 b5 35 LDA &35,X ; players_lives &13d4 d0 03 BNE &13d9 ; not_end_of_game_for_player &13d6 20 cc 24 JSR &24cc ; check_for_high_score ; not_end_of_game_for_player &13d9 a5 35 LDA &35 ; players_lives &13db 05 36 ORA &36 ; players_lives + 1 &13dd f0 23 BEQ &1402 ; end_of_game &13df a5 32 LDA &32 ; current_player &13e1 49 01 EOR #&01 # Swap to other player &13e3 aa TAX &13e4 b5 35 LDA &35,X ; players_lives &13e6 f0 93 BEQ &137b ; initialise_player # unless other player has no lives &13e8 86 32 STX &32 ; current_player &13ea 20 05 14 JSR &1405 ; remove_enemies_player_missiles_and_text &13ed 4c 6b 13 JMP &136b ; new_player_loop ; leave &13f0 60 RTS ; remove_enemy_bomb &13f1 20 3d 16 JSR &163d ; plot_enemy_bomb # Unplot enemy bomb ; remove_enemy &13f4 a9 00 LDA #&00 &13f6 9d db 04 STA &04db,X ; enemies_screen_address_high # Set to zero to remove enemy bomb &13f9 f0 1f BEQ &141a ; consider_next_enemy # Always branches ; check_for_player_quitting &13fb a9 8f LDA #&8f ; ESCAPE &13fd 20 2e 0e JSR &0e2e ; check_for_keypress &1400 f0 ee BEQ &13f0 ; leave ; end_of_game &1402 a2 fd LDX #&fd &1404 9a TXS ; remove_enemies_player_missiles_and_text &1405 a2 48 LDX #&48 ; ENEMY_LAST_LAST_EXPLOSION # Remove all enemies, enemy bombs and explosions ; remove_enemies_loop &1407 bd db 04 LDA &04db,X ; enemies_screen_address_high &140a f0 0e BEQ &141a ; consider_next_enemy &140c c9 ff CMP #&ff ; NOT_PLOTTED &140e f0 e4 BEQ &13f4 ; remove_enemy &1410 bd af 05 LDA &05af,X ; enemies_type_and_flags &1413 c9 08 CMP #&08 ; ENEMY_TYPE_BOMB &1415 f0 da BEQ &13f1 ; remove_enemy_bomb &1417 20 cc 0e JSR &0ecc ; unplot_enemy # Unplot enemy ; consider_next_enemy &141a ca DEX &141b 10 ea BPL &1407 ; remove_enemies_loop &141d 24 33 BIT &33 ; player_dead # Negative if player is dead &141f 30 03 BMI &1424 ; skip_unplotting_player &1421 20 f5 12 JSR &12f5 ; plot_player # Unplot player ; skip_unplotting_player &1424 20 fc 26 JSR &26fc ; remove_doubling_wave ; remove_player_missiles &1427 a2 01 LDX #&01 ; remove_player_missiles_loop &1429 b5 b4 LDA &b4,X ; player_missiles_state # Zero if no missile in slot &142b f0 07 BEQ &1434 ; consider_next_player_missile &142d 20 17 17 JSR &1717 ; plot_player_missile # Unplot player missile &1430 a9 00 LDA #&00 &1432 95 b4 STA &b4,X ; player_missiles_state # Set to zero to indicate no missile in slot ; consider_next_player_missile &1434 ca DEX &1435 10 f2 BPL &1429 ; remove_player_missiles_loop &1437 85 79 STA &79 ; suppress_sounds # Suppress sounds for one frame &1439 4c 7b 20 JMP &207b ; unplot_text # Unplot any text ; explosion_sprites ; 0 1 2 3 4 5 6 7 8 9 a b c d e &143c 28 27 26 27 28 27 26 27 26 27 28 26 27 28 ff # &ff indicates end of animation ; update_explosions &144b a2 3f LDX #&3f ; ENEMY_SLOT_FIRST_EXPLOSION ; update_explosions_loop &144d bd db 04 LDA &04db,X ; enemies_screen_address_high &1450 f0 24 BEQ &1476 ; consider_next_explosion # Zero if no explosion in slot &1452 a5 52 LDA &52 ; previous_frame_counter &1454 dd 45 05 CMP &0545,X ; enemies_frame_counter &1457 30 1d BMI &1476 ; consider_next_explosion # Is it time to update this explosion? &1459 20 cc 0e JSR &0ecc ; unplot_enemy # Unplot explosion; zeroes enemies_screen_address_high &145c bd 45 05 LDA &0545,X ; enemies_frame_counter &145f 18 CLC &1460 69 08 ADC #&08 # Update explosion in eight frames time &1462 9d 45 05 STA &0545,X ; enemies_frame_counter &1465 fe 66 05 INC &0566,X ; enemies_explosion_frame - &3f &1468 bc 66 05 LDY &0566,X ; enemies_explosion_frame - &3f &146b b9 3c 14 LDA &143c,Y ; explosion_sprites &146e 30 06 BMI &1476 ; consider_next_explosion # &ff indicates end of explosion animation &1470 9d 92 04 STA &0492,X ; enemies_sprite &1473 20 c9 0e JSR &0ec9 ; plot_enemy # Plot explosion; sets enemies_screen_address_high ; consider_next_explosion &1476 e8 INX &1477 e0 49 CPX #&49 ; ENEMY_SLOT_LAST_EXPLOSION + 1 &1479 90 d2 BCC &144d ; update_explosions_loop &147b 60 RTS ; remove_all_enemies &147c a2 48 LDX #&48 ; ENEMY_LAST_LAST_EXPLOSION # Remove all enemies, enemy bombs and explosions &147e a9 00 LDA #&00 ; remove_all_enemies_loop &1480 9d db 04 STA &04db,X ; enemies_screen_address_high # Set to zero to indicate slot is empty &1483 ca DEX &1484 10 fa BPL &1480 ; remove_all_enemies_loop &1486 60 RTS ; use_game_envelopes &1487 a0 00 LDY #&00 ; envelope_1 &1489 20 e9 23 JSR &23e9 ; define_envelope &148c a0 0e LDY #&0e ; envelope_2 &148e 20 e9 23 JSR &23e9 ; define_envelope &1491 a0 46 LDY #&46 ; envelope_6 &1493 20 e9 23 JSR &23e9 ; define_envelope &1496 a0 1c LDY #&1c ; envelope_3 &1498 4c e9 23 JMP &23e9 ; define_envelope ; flush_buffers &149b a9 0f LDA #&0f ; Flush all buffers &149d a2 00 LDX #&00 ; all buffers &149f 4c f4 ff JMP &fff4 ; OSBYTE ; leave &14a2 60 RTS ; update_player &14a3 24 33 BIT &33 ; player_dead # Negative if player is dead &14a5 30 fb BMI &14a2 ; leave &14a7 20 f5 12 JSR &12f5 ; plot_player &14aa a6 16 LDX &16 ; player_x &14ac 20 e1 18 JSR &18e1 ; check_for_movement # Returns X = &01 for right, X = &ff for left &14af 8a TXA &14b0 f0 2c BEQ &14de ; skip_movement &14b2 24 19 BIT &19 ; player_doubled # Negative if player doubled &14b4 10 08 BPL &14be ; not_doubled &14b6 e4 16 CPX &16 ; player_x &14b8 f0 24 BEQ &14de ; skip_movement # Player can't move beyond left edge of screen &14ba 90 02 BCC &14be ; not_doubled &14bc 69 05 ADC #&05 # Doubled player is wider ; not_doubled &14be c9 4a CMP #&4a &14c0 b0 1c BCS &14de ; skip_movement # Player can't move beyond right edge of screen &14c2 e4 16 CPX &16 ; player_x &14c4 f0 18 BEQ &14de ; skip_movement # Unnecessary code; already checked at &14b6 &14c6 86 16 STX &16 ; player_x &14c8 a5 17 LDA &17 ; player_screen_address_low &14ca b0 0a BCS &14d6 ; move_player_right ; move_player_left &14cc e9 07 SBC #&07 # Move left two pixels; carry is clear, so subtract 8 &14ce 85 17 STA &17 ; player_screen_address_low &14d0 b0 0c BCS &14de ; skip_movement &14d2 c6 18 DEC &18 ; player_screen_address_high &14d4 90 08 BCC &14de ; skip_movement # Always branches ; move_player_right &14d6 69 07 ADC #&07 # Move right two pixels; carry is set, so add 8 &14d8 85 17 STA &17 ; player_screen_address_low &14da 90 02 BCC &14de ; skip_movement &14dc e6 18 INC &18 ; player_screen_address_high ; skip_movement &14de 24 19 BIT &19 ; player_doubled # Negative if player doubled &14e0 30 34 BMI &1516 ; skip_starting_doubling &14e2 a6 32 LDX &32 ; current_player &14e4 b5 35 LDA &35,X ; players_lives &14e6 f0 2e BEQ &1516 ; skip_starting_doubling # Player can't double on last life &14e8 a5 bc LDA &bc ; doubling_wave_state &14ea c9 10 CMP #&10 ; FULL_DOUBLING_WAVE &14ec 90 28 BCC &1516 ; skip_starting_doubling # Doubling wave must be fully plotted to double &14ee a5 16 LDA &16 ; player_x &14f0 c5 c6 CMP &c6 ; minimum_x_for_doubling &14f2 90 22 BCC &1516 ; skip_starting_doubling # Player must be within doubling wave to double &14f4 c5 c7 CMP &c7 ; maximum_x_for_doubling &14f6 b0 1e BCS &1516 ; skip_starting_doubling &14f8 c6 19 DEC &19 ; player_doubled # Set to &ff to indicate player is doubled &14fa 20 a6 24 JSR &24a6 ; plot_lives &14fd a6 32 LDX &32 ; current_player &14ff d6 35 DEC &35,X ; players_lives # Remove life for doubling &1501 c6 54 DEC &54 ; active_enemies # Remove queen from count &1503 d6 39 DEC &39,X ; players_enemies_remaining # Remove queen from count &1505 20 fc 26 JSR &26fc ; remove_doubling_wave &1508 a6 c5 LDX &c5 ; doubling_attack_queen &150a 20 cc 0e JSR &0ecc ; unplot_enemy # Unplot queen &150d a9 ff LDA #&ff &150f 85 c5 STA &c5 ; doubling_attack_queen # Set to negative to indicate no queen doubling attacking &1511 a0 03 LDY #&03 ; TUNE_DOUBLING # Start doubling tune &1513 20 32 24 JSR &2432 ; play_tune ; skip_starting_doubling &1516 20 21 13 JSR &1321 ; use_player_screen_address &1519 a0 00 LDY #&00 # Check left ship &151b 20 7d 15 JSR &157d ; check_for_player_collision # Returns carry set if collision occurred &151e 24 19 BIT &19 ; player_doubled # Negative if player doubled &1520 90 26 BCC &1548 ; no_collision &1522 30 0a BMI &152e ; collision_while_doubled ; collision_while_not_doubled &1524 c6 33 DEC &33 ; player_dead # Set to negative to indicate player dead &1526 a9 e1 LDA #&e1 &1528 85 4d STA &4d ; game_state_cooldown # Wait 225 frames before starting next life &152a a5 16 LDA &16 ; player_x &152c 10 2f BPL &155d ; explode_player # Always branches ; collision_while_doubled &152e a5 16 LDA &16 ; player_x &1530 20 5d 15 JSR &155d ; explode_player # Explode left ship &1533 a5 16 LDA &16 ; player_x &1535 18 CLC &1536 69 06 ADC #&06 &1538 85 16 STA &16 ; player_x &153a a5 17 LDA &17 ; player_screen_address_low &153c 69 30 ADC #&30 &153e 85 17 STA &17 ; player_screen_address_low &1540 90 02 BCC &1544 ; skip_page &1542 e6 18 INC &18 ; player_screen_address_high ; skip_page &1544 e6 19 INC &19 ; player_doubled # Set to zero to indicate player is not doubled &1546 f0 96 BEQ &14de ; skip_movement # Always branches ; no_collision &1548 10 10 BPL &155a ; skip_double_explosion # Negative if player doubled &154a a0 30 LDY #&30 # Check right ship &154c 20 7d 15 JSR &157d ; check_for_player_collision # Returns carry set if collision occurred &154f 90 09 BCC &155a ; skip_double_explosion &1551 e6 19 INC &19 ; player_doubled # Set to zero to indicate player is not doubled &1553 a5 16 LDA &16 ; player_x &1555 69 05 ADC #&05 &1557 20 5d 15 JSR &155d ; explode_player # Explode right ship ; skip_double_explosion &155a 4c f5 12 JMP &12f5 ; plot_player ; explode_player &155d a0 08 LDY #&08 &155f 20 98 18 JSR &1898 ; add_explosion # Returns carry clear if explosion added &1562 a9 00 LDA #&00 &1564 b0 03 BCS &1569 ; skip_explosion &1566 99 66 05 STA &0566,Y ; enemies_explosion_frame - &3f # Player explosions last 14 frames ; skip_explosion &1569 85 79 STA &79 ; suppress_sounds # Set to zero to allow sound &156b 20 9b 14 JSR &149b ; flush_buffers &156e a0 38 LDY #&38 ; envelope_5 &1570 20 e9 23 JSR &23e9 ; define_envelope &1573 a0 74 LDY #&74 ; sound_5 &1575 20 e0 23 JSR &23e0 ; play_sound # Play sound for player exploding &1578 a9 d3 LDA #&d3 &157a 85 79 STA &79 ; suppress_sounds # Suppress sound for 45 frames ; leave &157c 60 RTS ; check_for_player_collision &157d 98 TYA &157e 48 PHA ; offset &157f 20 a2 15 JSR &15a2 ; large_collision_check # Returns carry clear if no collision occurred &1582 68 PLA ; offset &1583 90 f7 BCC &157c ; leave # Leave with carry clear if no collision occurred &1585 4a LSR A &1586 4a LSR A &1587 4a LSR A &1588 65 16 ADC &16 ; player_x &158a 85 61 STA &61 ; collision_x_min &158c 69 05 ADC #&05 &158e 85 62 STA &62 ; collision_x_max &1590 a9 08 LDA #&08 &1592 85 64 STA &64 ; collision_y_min &1594 a9 0e LDA #&0e &1596 85 63 STA &63 ; collision_y_max &1598 20 85 17 JSR &1785 ; check_for_player_collision # Returns A negative if collision occurred &159b 0a ASL A &159c 60 RTS # Leave with carry set if collision occurred ; small_collision_check &159d 8a TXA &159e a2 08 LDX #&08 # Check one columns of eight bytes / two pixels &15a0 d0 03 BNE &15a5 ; collision_check # Always branches ; large_collision_check &15a2 8a TXA &15a3 a2 30 LDX #&30 # Check six columns of eight bytes / twelve pixels ; collision_check &15a5 38 SEC &15a6 48 PHA ; tmp_x ; collision_check_loop &15a7 b1 02 LDA (&02),Y ; screen_address &15a9 29 55 AND #&55 ; 0F # Check right pixel of pair &15ab d0 05 BNE &15b2 ; leave_after_restoring_x # Leave with carry set if collision &15ad c8 INY &15ae ca DEX &15af d0 f6 BNE &15a7 ; collision_check_loop &15b1 18 CLC # Leave with carry clear if no collision ; leave_after_restoring_x &15b2 68 PLA ; tmp_x &15b3 aa TAX &15b4 60 RTS ; check_for_firing_release &15b5 20 e4 18 JSR &18e4 ; check_for_firing # Returns non-zero if fire pressed &15b8 d0 04 BNE &15be ; leave &15ba a9 00 LDA #&00 &15bc 85 31 STA &31 ; suppress_firing_autorepeat # Set to positive to permit firing ; leave &15be 60 RTS ; update_enemy_bombs &15bf a2 35 LDX #&35 ; ENEMY_SLOT_FIRST_BOMB ; update_enemies_loop &15c1 bd db 04 LDA &04db,X ; enemies_screen_address_high # Zero if no enemy bomb in slot &15c4 f0 62 BEQ &1628 ; consider_next_enemy_bomb &15c6 20 3d 16 JSR &163d ; plot_enemy_bomb ; apply_horizontal_movement_to_enemy_bomb &15c9 bd c6 05 LDA &05c6,X ; enemies_bomb_x_fraction - &35 &15cc 38 SEC &15cd fd dd 05 SBC &05dd,X ; enemies_bomb_x_speed - &35 # Apply fractional movement to bomb x position &15d0 9d c6 05 STA &05c6,X ; enemies_bomb_x_fraction - &35 &15d3 b0 21 BCS &15f6 ; move_enemy_bomb_down &15d5 69 41 ADC #&41 &15d7 9d c6 05 STA &05c6,X ; enemies_bomb_x_fraction - &35 &15da 08 PHP ; x fraction overflow &15db bd 66 05 LDA &0566,X ; enemies_bomb_direction - &35 &15de 30 09 BMI &15e9 ; move_enemy_bomb_left ; move_enemy_bomb_right &15e0 fe 00 04 INC &0400,X ; enemies_x &15e3 a9 08 LDA #&08 # Move right two pixels &15e5 a0 00 LDY #&00 &15e7 f0 07 BEQ &15f0 ; add_to_enemy_bomb_screen_address # Always branches ; move_enemy_bomb_left &15e9 de 00 04 DEC &0400,X ; enemies_x &15ec a9 f8 LDA #&f8 # Move left two pixels &15ee a0 ff LDY #&ff ; add_to_enemy_bomb_screen_address &15f0 20 2e 16 JSR &162e ; add_A_Y_to_enemies_screen_address &15f3 28 PLP ; x fraction overflow &15f4 90 d3 BCC &15c9 ; apply_horizontal_movement_to_enemy_bomb ; move_enemy_bomb_down &15f6 de 49 04 DEC &0449,X ; enemies_y # Move bomb down &15f9 de 49 04 DEC &0449,X ; enemies_y &15fc bd 24 05 LDA &0524,X ; enemies_screen_address_low &15ff 18 CLC &1600 69 04 ADC #&04 # Move down four pixels &1602 9d 24 05 STA &0524,X ; enemies_screen_address_low &1605 90 03 BCC &160a ; skip_page &1607 fe db 04 INC &04db,X ; enemies_screen_address_high ; skip_page &160a 29 04 AND #&04 &160c d0 07 BNE &1615 ; not_new_group &160e a9 78 LDA #&78 # Move down into next group &1610 a0 02 LDY #&02 &1612 20 2e 16 JSR &162e ; add_A_Y_to_enemies_screen_address ; not_new_group &1615 bd 49 04 LDA &0449,X ; enemies_y &1618 10 0b BPL &1625 ; replot_enemy_bomb &161a c9 f8 CMP #&f8 &161c b0 07 BCS &1625 ; replot_enemy_bomb # Remove bomb at bottom of screen ; remove_enemy_bomb &161e a9 00 LDA #&00 &1620 9d db 04 STA &04db,X ; enemies_screen_address_high # Set to zero to remove enemy bomb &1623 f0 03 BEQ &1628 ; consider_next_enemy_bomb # Always branches ; replot_enemy_bomb &1625 20 3d 16 JSR &163d ; plot_enemy_bomb ; consider_next_enemy_bomb &1628 e8 INX &1629 e0 3f CPX #&3f ; ENEMY_SLOT_LAST_BOMB + 1 &162b 90 94 BCC &15c1 ; update_enemies_loop &162d 60 RTS ; add_A_Y_to_enemies_screen_address &162e 18 CLC &162f 7d 24 05 ADC &0524,X ; enemies_screen_address_low &1632 9d 24 05 STA &0524,X ; enemies_screen_address_low &1635 98 TYA &1636 7d db 04 ADC &04db,X ; enemies_screen_address_high &1639 9d db 04 STA &04db,X ; enemies_screen_address_high &163c 60 RTS ; plot_enemy_bomb # Also unplots bomb &163d a0 09 LDY #&09 &163f bd db 04 LDA &04db,X ; enemies_screen_address_high &1642 85 03 STA &03 ; screen_address_high &1644 c9 30 CMP #&30 &1646 90 13 BCC &165b ; leave &1648 bd 24 05 LDA &0524,X ; enemies_screen_address_low &164b 85 02 STA &02 ; screen_address_low &164d 29 04 AND #&04 &164f d0 0b BNE &165c ; plot_unaligned_enemy_bomb_loop ; plot_aligned_plot_enemy_bomb_loop &1651 b1 02 LDA (&02),Y ; screen_address &1653 59 80 16 EOR &1680,Y ; sprite_enemy_bomb_aligned &1656 91 02 STA (&02),Y ; screen_address &1658 88 DEY &1659 10 f6 BPL &1651 ; plot_aligned_plot_enemy_bomb_loop ; leave &165b 60 RTS ; plot_unaligned_enemy_bomb_loop &165c b1 02 LDA (&02),Y ; screen_address &165e 59 8a 16 EOR &168a,Y ; sprite_enemy_bomb_unaligned &1661 91 02 STA (&02),Y ; screen_address &1663 88 DEY &1664 10 f6 BPL &165c ; plot_unaligned_enemy_bomb_loop &1666 a5 02 LDA &02 ; screen_address_low &1668 18 CLC &1669 69 7c ADC #&7c # Move down a group &166b 85 02 STA &02 ; screen_address_low &166d a5 03 LDA &03 ; screen_address_high &166f 69 02 ADC #&02 &1671 85 03 STA &03 ; screen_address_high &1673 a0 03 LDY #&03 ; plot_unaligned_enemy_bomb_bottom_loop &1675 b1 02 LDA (&02),Y ; screen_address &1677 59 84 16 EOR &1684,Y ; sprite_enemy_bomb_aligned + 4 &167a 91 02 STA (&02),Y ; screen_address &167c 88 DEY &167d 10 f6 BPL &1675 ; plot_unaligned_enemy_bomb_bottom_loop &167f 60 RTS ; sprite_enemy_bomb_aligned &1680 01 03 15 15 15 15 15 15 00 02 ; sprite_enemy_bomb_unaligned &168a 01 03 15 15 00 00 00 00 00 02 ; to_check_for_firing_release &1694 4c b5 15 JMP &15b5 ; check_for_firing_release ; update_player_missiles_and_consider_firing &1697 20 e1 16 JSR &16e1 ; update_player_missiles &169a a5 33 LDA &33 ; player_dead # Negative if player is dead &169c 05 30 ORA &30 ; suppress_firing_before_ready # Negative if waiting for "Ready" to disappear &169e 30 16 BMI &16b6 ; leave &16a0 a5 31 LDA &31 ; suppress_firing_autorepeat # Negative if firing suppressed &16a2 30 f0 BMI &1694 ; to_check_for_firing_release &16a4 20 e4 18 JSR &18e4 ; check_for_firing # Returns non-zero if fire pressed &16a7 f0 0d BEQ &16b6 ; leave &16a9 a9 ff LDA #&ff &16ab 85 31 STA &31 ; suppress_firing_autorepeat # Set to negative to suppress firing &16ad a2 01 LDX #&01 ; find_free_slot_loop &16af b5 b4 LDA &b4,X ; player_missiles_state # Zero if no missile in slot &16b1 f0 04 BEQ &16b7 ; add_player_missile &16b3 ca DEX &16b4 10 f9 BPL &16af ; find_free_slot_loop ; leave &16b6 60 RTS ; add_player_missile &16b7 a5 19 LDA &19 ; player_doubled # Negative if player is doubled &16b9 09 7f ORA #&7f &16bb 95 b4 STA &b4,X ; player_missiles_state # Set to &7f if single missile, &ff if double missile &16bd a5 17 LDA &17 ; player_screen_address_low &16bf 38 SEC &16c0 e9 70 SBC #&70 # Put missile in group above player, four pixels right &16c2 95 b0 STA &b0,X ; player_missiles_screen_address_low &16c4 a5 18 LDA &18 ; player_screen_address_high &16c6 e9 02 SBC #&02 &16c8 95 b2 STA &b2,X ; player_missiles_screen_address_high &16ca a9 0c LDA #&0c &16cc 95 b8 STA &b8,X ; player_missiles_y &16ce a5 16 LDA &16 ; player_x &16d0 69 02 ADC #&02 &16d2 95 b6 STA &b6,X ; player_missiles_x &16d4 20 17 17 JSR &1717 ; plot_player_missile &16d7 a0 64 LDY #&64 ; sound_3 &16d9 20 e0 23 JSR &23e0 ; play_sound # Play sounds for player firing &16dc a0 6c LDY #&6c ; sound_4 &16de 4c e0 23 JMP &23e0 ; play_sound ; update_player_missiles &16e1 a2 01 LDX #&01 ; update_player_missiles_loop &16e3 b5 b4 LDA &b4,X ; player_missiles_state # Zero if no missile in slot &16e5 f0 26 BEQ &170d ; consider_next_player_missile &16e7 20 17 17 JSR &1717 ; plot_player_missile &16ea b5 b8 LDA &b8,X ; player_missiles_y &16ec 18 CLC &16ed 69 04 ADC #&04 &16ef 95 b8 STA &b8,X ; player_missiles_y &16f1 b5 b0 LDA &b0,X ; player_missiles_screen_address_low &16f3 e9 7f SBC #&7f # Carry clear, so subtract &80 &16f5 95 b0 STA &b0,X ; player_missiles_screen_address_low &16f7 85 02 STA &02 ; screen_address_low &16f9 b5 b2 LDA &b2,X ; player_missiles_screen_address_high &16fb e9 02 SBC #&02 # Move missile up eight pixels &16fd 95 b2 STA &b2,X ; player_missiles_screen_address_high &16ff 85 03 STA &03 ; screen_address_high &1701 c9 30 CMP #&30 &1703 90 0c BCC &1711 ; remove_player_missile # Remove missile at top of screen &1705 20 36 17 JSR &1736 ; check_for_player_missile_collision # Returns carry set if collision occurred &1708 b0 07 BCS &1711 ; remove_player_missile &170a 20 17 17 JSR &1717 ; plot_player_missile ; consider_next_player_missile &170d ca DEX &170e 10 d3 BPL &16e3 ; update_player_missiles_loop &1710 60 RTS ; remove_player_missile &1711 a9 00 LDA #&00 &1713 95 b4 STA &b4,X ; player_missiles_state # Set to zero to indicate no missile in slot &1715 f0 f6 BEQ &170d ; consider_next_player_missile # Always branches ; plot_player_missile &1717 b5 b0 LDA &b0,X ; player_missiles_screen_address_low &1719 85 02 STA &02 ; screen_address_low &171b b5 b2 LDA &b2,X ; player_missiles_screen_address_high &171d 85 03 STA &03 ; screen_address_high &171f 20 29 17 JSR &1729 ; plot_single_player_missile &1722 b5 b4 LDA &b4,X ; player_missiles_state # Positive if single missile, negative if double &1724 10 0f BPL &1735 ; leave &1726 20 35 13 JSR &1335 ; move_to_right_of_sprite # Plot second missile to right of first ; plot_single_player_missile &1729 a0 0f LDY #&0f ; plot_single_player_missile_loop &172b b1 02 LDA (&02),Y ; screen_address &172d 59 61 07 EOR &0761,Y ; sprite_player_missile &1730 91 02 STA (&02),Y ; screen_address &1732 88 DEY &1733 10 f6 BPL &172b ; plot_single_player_missile_loop ; leave &1735 60 RTS ; check_for_player_missile_collision &1736 a0 00 LDY #&00 # Check left missile &1738 20 9d 15 JSR &159d ; small_collision_check # Returns carry set if collision occurred &173b b0 0b BCS &1748 ; player_missile_hit_something &173d 24 19 BIT &19 ; player_doubled # Negative if player doubled &173f 10 f4 BPL &1735 ; leave &1741 a0 30 LDY #&30 # Check right missile &1743 20 9d 15 JSR &159d ; small_collision_check # Returns carry set if collision occurred &1746 90 ed BCC &1735 ; leave ; player_missile_hit_something &1748 8a TXA &1749 48 PHA ; tmp_x &174a b5 b6 LDA &b6,X ; player_missiles_x # Check left missile &174c 85 61 STA &61 ; collision_x_min &174e 85 62 STA &62 ; collision_x_max &1750 b5 b8 LDA &b8,X ; player_missiles_y &1752 85 64 STA &64 ; collision_y_min &1754 69 02 ADC #&02 &1756 85 63 STA &63 ; collision_y_max &1758 20 8b 17 JSR &178b ; check_for_player_missile_collision &175b 24 19 BIT &19 ; player_doubled # Negative if player doubled &175d 10 10 BPL &176f ; skip_double_missile &175f 48 PHA ; first collision result &1760 a5 61 LDA &61 ; collision_x_min # Check right missile &1762 18 CLC &1763 69 06 ADC #&06 &1765 85 61 STA &61 ; collision_x_min &1767 85 62 STA &62 ; collision_x_max &1769 20 8b 17 JSR &178b ; check_for_player_missile_collision &176c 68 PLA ; first collision result &176d 05 60 ORA &60 ; collision_occurred ; skip_double_missile &176f 0a ASL A # Set carry if collision occurred &1770 68 PLA ; tmp_x &1771 aa TAX &1772 60 RTS ; plot_player_one_or_player_two &1773 a9 0e LDA #&0e ; "Player One" &1775 a0 10 LDY #&10 ; "Player Two" ; plot_text_depending_on_current_player &1777 a6 32 LDX &32 ; current_player &1779 d0 01 BNE &177c ; to_plot_unplottable_text &177b a8 TAY ; to_plot_unplottable_text &177c 4c 93 20 JMP &2093 ; plot_unplottable_text ; plot_one_up_or_two_up &177f a9 12 LDA #&12 ; "1UP" &1781 a0 14 LDY #&14 ; "2UP" &1783 d0 f2 BNE &1777 ; plot_text_depending_on_current_player # Always branches ; check_for_player_collision &1785 a2 28 LDX #&28 ; ENEMY_SLOT_FIRST_ACTIVE # Check active enemies and bombs &1787 a0 3f LDY #&3f ; ENEMY_SLOT_LAST_BOMB + 1 &1789 d0 04 BNE &178f ; check_for_collision_with_enemies # Always branches ; check_for_player_missile_collision &178b a2 00 LDX #&00 ; ENEMY_SLOT_FIRST_PASSIVE # Check passive and active enemies &178d a0 35 LDY #&35 ; ENEMY_SLOT_LAST_ACTIVE + 1 ; check_for_collision_with_enemies &178f 84 7c STY &7c ; last_slot_to_check &1791 a9 00 LDA #&00 &1793 85 72 STA &72 ; score_changed # Set to zero to indicate score hasn't changed &1795 85 60 STA &60 ; collision_occurred # Set to zero to indicate no collision occurred ; check_for_collision_with_enemies_loop &1797 bd db 04 LDA &04db,X ; enemies_screen_address_high &179a f0 3f BEQ &17db ; consider_next_enemy # Zero if no enemy in slot &179c c9 ff CMP #&ff ; NOT_PLOTTED &179e b0 3b BCS &17db ; consider_next_enemy # &ff is enemy hasn't been plotted &17a0 bc 92 04 LDY &0492,X ; enemies_sprite &17a3 b9 52 27 LDA &2752,Y ; sprite_sizes_offsets &17a6 29 fc AND #&fc # Top six bits set sprite &17a8 4a LSR A &17a9 a8 TAY &17aa bd 49 04 LDA &0449,X ; enemies_y &17ad 79 80 27 ADC &2780,Y ; sprite_sizes + 5 (y offset) &17b0 c5 63 CMP &63 ; collision_y_max &17b2 f0 02 BEQ &17b6 ; check_y_min &17b4 10 25 BPL &17db ; consider_next_enemy ; check_y_min &17b6 85 45 STA &45 ; y_min &17b8 b9 7f 27 LDA &277f,Y ; sprite_sizes + 4 (height) &17bb 4a LSR A &17bc 65 45 ADC &45 ; y_min &17be c5 64 CMP &64 ; collision_y_min &17c0 f0 19 BEQ &17db ; consider_next_enemy &17c2 30 17 BMI &17db ; consider_next_enemy &17c4 18 CLC &17c5 bd 00 04 LDA &0400,X ; enemies_x &17c8 79 7b 27 ADC &277b,Y ; sprite_sizes + 0 (x offset) &17cb c5 62 CMP &62 ; collision_x_max &17cd f0 02 BEQ &17d1 ; check_x_min &17cf 10 0a BPL &17db ; consider_next_enemy ; check_x_min &17d1 18 CLC &17d2 79 7e 27 ADC &277e,Y ; sprite_sizes + 3 (width) &17d5 c5 61 CMP &61 ; collision_x_min &17d7 f0 02 BEQ &17db ; consider_next_enemy &17d9 10 27 BPL &1802 ; player_or_player_missile_collided_with_enemy ; consider_next_enemy &17db e8 INX &17dc e4 7c CPX &7c ; last_slot_to_check &17de 90 b7 BCC &1797 ; check_for_collision_with_enemies_loop &17e0 a5 72 LDA &72 ; score_changed # Non-zero if score has changed &17e2 f0 03 BEQ &17e7 ; skip_plotting_score &17e4 20 1b 22 JSR &221b ; plot_score_for_current_player ; skip_plotting_score &17e7 24 60 BIT &60 ; collision_occurred # Negative if collision occurred &17e9 10 0a BPL &17f5 ; skip_sound &17eb a0 54 LDY #&54 ; sound_1 &17ed 20 e0 23 JSR &23e0 ; play_sound # Play sounds for enemy exploding &17f0 a0 5c LDY #&5c ; sound_2 &17f2 20 e0 23 JSR &23e0 ; play_sound ; skip_sound &17f5 a5 60 LDA &60 ; collision_occurred # Leave with A negative if collision occurred &17f7 60 RTS ; player_or_player_missile_collided_with_enemy_bomb &17f8 20 3d 16 JSR &163d ; plot_enemy_bomb # Unplot bomb &17fb a9 00 LDA #&00 &17fd 9d db 04 STA &04db,X ; enemies_screen_address_high # Set to zero to remove bomb &1800 f0 07 BEQ &1809 ; handle_collision # Always branches ; player_or_player_missile_collided_with_enemy &1802 e0 35 CPX #&35 ; ENEMY_SLOT_LAST_ACTIVE + 1 &1804 b0 f2 BCS &17f8 ; player_or_player_missile_collided_with_enemy_bomb &1806 20 cc 0e JSR &0ecc ; unplot_enemy # Unplot enemy ; handle_collision &1809 20 96 1d JSR &1d96 ; get_enemy_type_and_flags # Returns Y = enemy type, carry and V from flags &180c b9 93 21 LDA &2193,Y ; types_to_sprites_table + 1 &180f 10 28 BPL &1839 ; explode_enemy_and_increase_score # If top bit unset, explode enemy ; change_enemy_type # If top bit set, change type of enemy &1811 08 PHP ; enemy mirrored in C, transient in V &1812 29 7f AND #&7f # Lowest seven bits set new type of enemy &1814 48 PHA ; new type &1815 bd 92 04 LDA &0492,X ; enemies_sprite &1818 38 SEC &1819 f9 92 21 SBC &2192,Y ; types_to_sprites_table &181c 85 08 STA &08 ; sprite_angle &181e 68 PLA ; new type &181f a8 TAY &1820 0a ASL A &1821 28 PLP ; enemy mirrored in C, transient in V &1822 6a ROR A # Keep ENEMY_FLAG_MIRRORED if set &1823 50 02 BVC &1827 ; not_transient &1825 09 40 ORA #&40 ; ENEMY_FLAG_TRANSIENT # Keep ENEMY_FLAG_TRANSIENT if set ; not_transient &1827 9d af 05 STA &05af,X ; enemies_type_and_flags &182a b9 92 21 LDA &2192,Y ; types_to_sprites_table &182d 65 08 ADC &08 ; sprite_angle # Keep previous angle &182f 9d 92 04 STA &0492,X ; enemies_sprite &1832 20 c9 0e JSR &0ec9 ; plot_enemy # Plot enemy as new type &1835 c6 60 DEC &60 ; collision_occurred # Set to negative to indicate collision occurred &1837 30 a2 BMI &17db ; consider_next_enemy # Always branches ; explode_enemy_and_increase_score &1839 8a TXA &183a 48 PHA ; enemy slot &183b 24 72 BIT &72 ; score_changed &183d 30 05 BMI &1844 ; skip_unplotting_score # If the previous score hasn't already been unplotted, &183f 20 1b 22 JSR &221b ; plot_score_for_current_player # Unplot previous score &1842 c6 72 DEC &72 ; score_changed ; skip_unplotting_score &1844 a5 7a LDA &7a ; hits &1846 18 CLC &1847 f8 SED &1848 69 01 ADC #&01 &184a 85 7a STA &7a ; hits &184c d8 CLD &184d 68 PLA ; enemy slot &184e 48 PHA ; enemy slot &184f aa TAX &1850 20 96 1d JSR &1d96 ; get_enemy_type_and_flags # Returns Y = enemy type &1853 b9 93 21 LDA &2193,Y ; types_to_sprites_table + 1 # Second byte of table sets score for destroying enemy &1856 24 77 BIT &77 ; challenge_stage # Negative if challenge stage &1858 30 0a BMI &1864 ; skip_scoring &185a e0 28 CPX #&28 ; ENEMY_SLOT_LAST_PASSIVE + 1 &185c 90 03 BCC &1861 ; not_double_score &185e 20 ce 18 JSR &18ce ; add_to_score_and_consider_extra_life # Double points for destroying active enemy ; not_double_score &1861 20 ce 18 JSR &18ce ; add_to_score_and_consider_extra_life ; skip_scoring &1864 68 PLA ; enemy slot &1865 48 PHA ; enemy slot &1866 aa TAX &1867 bd 00 04 LDA &0400,X ; enemies_x &186a bc 49 04 LDY &0449,X ; enemies_y &186d 20 98 18 JSR &1898 ; add_explosion # Returns carry clear if explosion added ; consider_undoubling &1870 bd af 05 LDA &05af,X ; enemies_type_and_flags &1873 0a ASL A &1874 30 11 BMI &1887 ; not_remaining_enemy # Don't count if ENEMY_FLAG_TRANSIENT is set &1876 e0 35 CPX #&35 ; ENEMY_SLOT_LAST_ACTIVE + 1 &1878 b0 0d BCS &1887 ; not_remaining_enemy # Don't count if enemy bomb &187a e4 c5 CPX &c5 ; doubling_attack_queen &187c d0 03 BNE &1881 ; skip_removing_doubling_wave &187e 20 fc 26 JSR &26fc ; remove_doubling_wave ; skip_removing_doubling_wave &1881 a6 32 LDX &32 ; current_player &1883 d6 39 DEC &39,X ; players_enemies_remaining # Note that an enemy has been destroyed &1885 c6 ba DEC &ba ; frames_between_attacks # Make remaining enemies attack slightly more frequently ; not_remaining_enemy &1887 68 PLA ; enemy slot &1888 aa TAX &1889 c6 60 DEC &60 ; collision_occurred # Set to negative to indicate collision occurred &188b e0 28 CPX #&28 ; ENEMY_SLOT_FIRST_ACTIVE &188d 90 06 BCC &1895 ; to_consider_next_enemy &188f e0 35 CPX #&35 ; ENEMY_SLOT_LAST_ACTIVE + 1 &1891 b0 02 BCS &1895 ; to_consider_next_enemy # Was this an active enemy? &1893 c6 54 DEC &54 ; active_enemies # If so, reduce count of active enemies ; to_consider_next_enemy &1895 4c db 17 JMP &17db ; consider_next_enemy ; add_explosion # Called with explosion position in X and Y &1898 85 08 STA &08 ; explosion_x &189a 8a TXA &189b 48 PHA ; tmp_x &189c a2 3f LDX #&3f ; ENEMY_SLOT_FIRST_EXPLOSION ; find_explosion_slot_loop # Search for a free slot for explosion &189e bd db 04 LDA &04db,X ; enemies_screen_address_high &18a1 f0 07 BEQ &18aa ; found_free_slot # Zero if no explosion in slot &18a3 e8 INX &18a4 e0 49 CPX #&49 ; ENEMY_SLOT_LAST_EXPLOSION + 1 &18a6 90 f6 BCC &189e ; find_explosion_slot_loop &18a8 b0 21 BCS &18cb ; leave_after_restoring_x # Leave with carry set if no free slot for explosion ; found_free_slot &18aa a5 08 LDA &08 ; explosion_x &18ac 9d 00 04 STA &0400,X ; enemies_x &18af 98 TYA &18b0 9d 49 04 STA &0449,X ; enemies_y &18b3 a9 08 LDA #&08 &18b5 9d 66 05 STA &0566,X ; enemies_explosion_frame - &3f # Enemy explosions last six frames &18b8 a9 26 LDA #&26 ; SPRITE_EXPLOSION &18ba 9d 92 04 STA &0492,X ; enemies_sprite &18bd a5 52 LDA &52 ; previous_frame_counter &18bf 18 CLC &18c0 69 08 ADC #&08 # Update explosion in eight frames time &18c2 9d 45 05 STA &0545,X ; enemies_frame_counter &18c5 20 c9 0e JSR &0ec9 ; plot_enemy # Plot explosion &18c8 8a TXA &18c9 a8 TAY # Leave with Y = explosion slot &18ca 18 CLC # Leave with carry clear to indicate explosion added ; leave_after_restoring_x &18cb 68 PLA ; tmp_x &18cc aa TAX &18cd 60 RTS ; add_to_score_and_consider_extra_life &18ce 20 da 12 JSR &12da ; add_A_to_score # Returns carry set every 100,000 points ; consider_extra_life &18d1 90 0d BCC &18e0 ; leave &18d3 48 PHA ; tmp_a &18d4 f6 35 INC &35,X ; players_lives # Extra life every 100,000 points &18d6 f6 35 INC &35,X ; players_lives &18d8 20 a6 24 JSR &24a6 ; plot_lives &18db a6 32 LDX &32 ; current_player &18dd d6 35 DEC &35,X ; players_lives &18df 68 PLA ; tmp_a ; leave &18e0 60 RTS ; check_for_movement &18e1 6c 0e 00 JMP (&000e) ; check_routine_addresses ; check_for_firing &18e4 6c 10 00 JMP (&0010) ; check_routine_addresses + 2 ; set_movement_and_firing_check_routine_addresses &18e7 a0 00 LDY #&00 ; check_for_keyboard_movement &18e9 24 70 BIT &70 ; keyboard_or_joystick # Positive for keyboard, negative for joystick &18eb 10 08 BPL &18f5 ; set_addresses &18ed a0 04 LDY #&04 ; check_for_joystick_one_movement &18ef a5 32 LDA &32 ; current_player &18f1 f0 02 BEQ &18f5 ; set_addresses &18f3 a0 08 LDY #&08 ; check_for_joystick_two_movement ; set_addresses &18f5 a2 00 LDX #&00 ; set_addresses_loop &18f7 b9 03 19 LDA &1903,Y ; movement_and_firing_check_routines_addresses_table &18fa 95 0e STA &0e,X ; check_routine_addresses &18fc c8 INY &18fd e8 INX &18fe e0 04 CPX #&04 &1900 d0 f5 BNE &18f7 ; set_addresses_loop &1902 60 RTS ; movement_and_firing_check_routines_addresses_table &1903 47 19 ; &00 : &1947 = check_for_keyboard_movement &1905 58 19 ; &02 : &1958 = check_for_keyboard_firing &1907 0f 19 ; &04 : &190f = check_for_joystick_one_movement &1909 30 19 ; &06 : &1930 = check_for_joystick_one_firing &190b 12 19 ; &08 : &1912 = check_for_joystick_two_movement &190d 2d 19 ; &0a : &192d = check_for_joystick_two_firing ; check_for_joystick_one_movement &190f a9 01 LDA #&01 # First joystick left/right &1911 dc a9 03 NOP &03a9,X ; check_for_joystick_two_movement #1912 LDA #&03 # Second joystick left/right &1914 86 14 STX &14 ; tmp_x &1916 aa TAX &1917 98 TYA &1918 48 PHA ; tmp_y &1919 a9 80 LDA #&80 ; Read ADC channel &191b 20 f4 ff JSR &fff4 ; OSBYTE &191e a6 14 LDX &14 ; tmp_x &1920 c0 e0 CPY #&e0 &1922 90 01 BCC &1925 ; not_left &1924 ca DEX # Set X = &ff to indicate left ; not_left &1925 c0 20 CPY #&20 &1927 b0 01 BCS &192a ; not_right &1929 e8 INX # Set X = &01 to indicate right ; not_right &192a 68 PLA ; tmp_y &192b a8 TAY &192c 60 RTS ; check_for_joystick_two_firing &192d a9 02 LDA #&02 # Second fire button &192f dc a9 01 NOP &01a9,X ; check_for_joystick_one_firing #1930 LDA #&01 # First fire button &1932 85 14 STA &14 ; button_mask &1934 86 80 STX &80 ; tmp_x &1936 98 TYA &1937 48 PHA ; tmp_y &1938 a2 00 LDX #&00 &193a a9 80 LDA #&80 ; Read ADC channel &193c 20 f4 ff JSR &fff4 ; OSBYTE &193f 68 PLA ; tmp_y &1940 a8 TAY &1941 8a TXA &1942 a6 80 LDX &80 ; tmp_x &1944 25 14 AND &14 ; button_mask &1946 60 RTS ; check_for_keyboard_movement &1947 a9 bf LDA #&bf ; CAPSLOCK &1949 20 2e 0e JSR &0e2e ; check_for_keypress &194c f0 01 BEQ &194f ; capslock_not_pressed &194e ca DEX # Set X = &ff to indicate left ; capslock_not_pressed &194f a9 fe LDA #&fe ; CTRL &1951 20 2e 0e JSR &0e2e ; check_for_keypress &1954 f0 01 BEQ &1957 ; ctrl_not_pressed &1956 e8 INX # Set X = &01 to indicate right ; ctrl_not_pressed &1957 60 RTS ; check_for_keyboard_firing &1958 a9 b6 LDA #&b6 ; RETURN &195a 4c 2e 0e JMP &0e2e ; check_for_keypress ; consider_adding_queen_to_attack &195d a2 03 LDX #&03 &195f a9 00 LDA #&00 ; check_for_queens_loop &1961 1d e7 04 ORA &04e7,X ; enemies_screen_address_high + &c # ENEMY_SLOT_FIRST_QUEEN &1964 ca DEX &1965 10 fa BPL &1961 ; check_for_queens_loop &1967 aa TAX &1968 d0 06 BNE &1970 ; find_queen_to_add # Non-zero if any of the four queens are present &196a 20 97 0e JSR &0e97 ; rnd &196d 4c 0d 1a JMP &1a0d ; set_enemy_attacking ; find_queen_to_add &1970 20 97 0e JSR &0e97 ; rnd &1973 29 03 AND #&03 # Get random number of queen &1975 a8 TAY &1976 09 0c ORA #&0c ; ENEMY_SLOT_FIRST_QUEEN &1978 aa TAX &1979 bd db 04 LDA &04db,X ; enemies_screen_address_high &197c f0 f2 BEQ &1970 ; find_queen_to_add # Zero if slot is empty, i.e. queen not present &197e 98 TYA &197f 48 PHA ; queen number &1980 20 b9 1a JSR &1ab9 ; find_free_active_enemy_slot # Leaves with carry clear if slot found &1983 90 09 BCC &198e ; add_enemy_to_attack &1985 68 PLA ; queen number &1986 60 RTS ; add_enemy_to_attacking_queen &1987 20 c7 1a JSR &1ac7 ; set_enemy_accompanying_attack &198a 8a TXA &198b 29 03 AND #&03 # Get number of queen &198d 48 PHA ; queen number ; add_enemy_to_attack &198e bd af 05 LDA &05af,X ; enemies_type_and_flags &1991 99 af 05 STA &05af,Y ; enemies_type_and_flags &1994 20 4e 1a JSR &1a4e ; make_passive_enemy_active &1997 68 PLA ; queen number &1998 85 7e STA &7e ; queen_offset &199a 0a ASL A &199b 65 7e ADC &7e ; queen_offset # Multiply by three to get offset into table &199d 85 7e STA &7e ; queen_offset &199f a5 c5 LDA &c5 ; doubling_attack_queen # Positive if a queen is already attacking &19a1 10 0c BPL &19af ; skip_doubling_attack &19a3 20 97 0e JSR &0e97 ; rnd &19a6 29 03 AND #&03 # One in four chance of queen starting doubling attack &19a8 05 19 ORA &19 ; player_doubled # Non-zero if player doubled &19aa d0 03 BNE &19af ; skip_doubling_attack &19ac 4c 02 27 JMP &2702 ; set_queen_starting_doubling_attack ; skip_doubling_attack &19af a9 02 LDA #&02 # Attacking queen has up to two accompanying enemies &19b1 85 7d STA &7d ; limit &19b3 85 7f STA &7f ; count &19b5 bd af 05 LDA &05af,X ; enemies_type_and_flags &19b8 0a ASL A # Carry set if ENEMY_FLAG_MIRRORED set &19b9 08 PHP ; enemy mirrored ; add_accompanying_enemies_loop # Consider enemies that can accompany queen &19ba a6 7e LDX &7e ; queen_offset &19bc bd cd 1a LDA &1acd,X ; slots_of_enemies_accompanying_queens &19bf aa TAX &19c0 bd db 04 LDA &04db,X ; enemies_screen_address_high &19c3 f0 16 BEQ &19db ; skip_adding_enemy # Zero if slot is empty &19c5 20 b9 1a JSR &1ab9 ; find_free_active_enemy_slot # Leaves with carry clear if slot found &19c8 b0 17 BCS &19e1 ; leave_after_plp &19ca 20 4e 1a JSR &1a4e ; make_passive_enemy_active # Make accompanying enemy active &19cd bd af 05 LDA &05af,X ; enemies_type_and_flags &19d0 0a ASL A &19d1 28 PLP ; enemy mirrored &19d2 08 PHP ; enemy mirrored &19d3 6a ROR A # Keep ENEMY_FLAG_MIRRORED if set &19d4 9d af 05 STA &05af,X ; enemies_type_and_flags &19d7 c6 7d DEC &7d ; limit &19d9 f0 06 BEQ &19e1 ; leave_after_plp ; skip_adding_enemy &19db e6 7e INC &7e ; queen_offset &19dd c6 7f DEC &7f ; count &19df 10 d9 BPL &19ba ; add_accompanying_enemies_loop ; leave_after_plp &19e1 28 PLP ; enemy mirrored &19e2 60 RTS ; consider_setting_enemies_attacking &19e3 24 33 BIT &33 ; player_dead # Negative if player is dead &19e5 30 1b BMI &1a02 ; leave &19e7 a5 52 LDA &52 ; previous_frame_counter &19e9 38 SEC ; division_loop &19ea e5 ba SBC &ba ; frames_between_attacks &19ec b0 fc BCS &19ea ; division_loop &19ee 65 ba ADC &ba ; frames_between_attacks &19f0 d0 10 BNE &1a02 ; leave # Leave if not time for next attack ; set_enemies_attacking &19f2 a0 28 LDY #&28 ; ENEMY_SLOT_FIRST_ACTIVE ; find_free_slot_loop # Find a free active slot before choosing passive enemy &19f4 b9 db 04 LDA &04db,Y ; enemies_screen_address_high &19f7 f0 0a BEQ &1a03 ; found_free_slot &19f9 c8 INY &19fa c0 35 CPY #&35 ; ENEMY_SLOT_LAST_ACTIVE + 1 &19fc b0 04 BCS &1a02 ; leave # Leave if no free active slots &19fe c4 bb CPY &bb ; maximum_slot_for_active_enemies_plus_one &1a00 90 f2 BCC &19f4 ; find_free_slot_loop # Leave if level already has maximum active enemies ; leave &1a02 60 RTS ; found_free_slot &1a03 20 97 0e JSR &0e97 ; rnd &1a06 24 49 BIT &49 ; seven &1a08 d0 03 BNE &1a0d ; set_enemy_attacking &1a0a 4c 5d 19 JMP &195d ; consider_adding_queen_to_attack # One in eight times, consider adding a queen ; set_enemy_attacking &1a0d 85 08 STA &08 ; random_side # Random value, top bit determines side of attack &1a0f a9 0c LDA #&0c ; ACTION_ATTACK &1a11 99 66 05 STA &0566,Y ; enemies_action - &28 &1a14 a2 ff LDX #&ff ; ENEMY_SLOT_FIRST_PASSIVE - 1 &1a16 86 15 STX &15 ; passive_enemy_slot # Set negative to indicate no enemy yet considered &1a18 e8 INX ; find_outermost_passive_enemy_loop # Find the outermost passive enemy on chosen side &1a19 bd db 04 LDA &04db,X ; enemies_screen_address_high &1a1c f0 17 BEQ &1a35 ; consider_next_enemy # Skip if no enemy present in slot &1a1e 24 15 BIT &15 ; passive_enemy_slot &1a20 30 0c BMI &1a2e ; is_first_enemy_considered # If this isn't the first enemy considered, &1a22 bd 00 04 LDA &0400,X ; enemies_x &1a25 38 SEC &1a26 e5 14 SBC &14 ; outermost_x # Is it further out than the previously outermost enemy? &1a28 f0 7b BEQ &1aa5 ; use_this_enemy_or_consider_next_enemy_randomly &1a2a 45 08 EOR &08 ; random_side &1a2c 30 07 BMI &1a35 ; consider_next_enemy ; is_first_enemy_considered &1a2e bd 00 04 LDA &0400,X ; enemies_x &1a31 85 14 STA &14 ; outermost_x # If so, note its position ; use_this_enemy &1a33 86 15 STX &15 ; passive_enemy_slot # and note that it is the outermost enemy ; consider_next_enemy &1a35 e8 INX &1a36 e0 28 CPX #&28 ; ENEMY_SLOT_LAST_PASSIVE + 1 &1a38 90 df BCC &1a19 ; find_outermost_passive_enemy_loop &1a3a a6 15 LDX &15 ; passive_enemy_slot &1a3c 30 c4 BMI &1a02 ; leave # Leave if no passive enemy could be found &1a3e bd af 05 LDA &05af,X ; enemies_type_and_flags # X = passive slot, Y = active slot &1a41 99 af 05 STA &05af,Y ; enemies_type_and_flags # Use type of passive enemy for active enemy &1a44 bd 92 04 LDA &0492,X ; enemies_sprite &1a47 c9 18 CMP #&18 ; SPRITE_QUEEN &1a49 90 03 BCC &1a4e ; make_passive_enemy_active &1a4b 4c 87 19 JMP &1987 ; add_enemy_to_attacking_queen # If the enemy is a queen, add accompanying enemies ; make_passive_enemy_active # Called with X = passive slot, Y = active slot &1a4e 98 TYA &1a4f 48 PHA ; active slot &1a50 20 cc 0e JSR &0ecc ; unplot_enemy # Unplot passive enemy &1a53 68 PLA ; active slot &1a54 a8 TAY &1a55 bd 49 04 LDA &0449,X ; enemies_y &1a58 99 49 04 STA &0449,Y ; enemies_y # Use y position of passive enemy for active enemy &1a5b bd 92 04 LDA &0492,X ; enemies_sprite &1a5e 99 92 04 STA &0492,Y ; enemies_sprite # Use sprite of passive enemy for active enemy &1a61 a5 52 LDA &52 ; previous_frame_counter &1a63 99 45 05 STA &0545,Y ; enemies_frame_counter # Update on next check &1a66 18 CLC &1a67 69 19 ADC #&19 # Active enemy can bomb after 25 frames &1a69 99 0e 06 STA &060e,Y ; enemies_next_bombing_frame - &28 &1a6c bd 00 04 LDA &0400,X ; enemies_x &1a6f 99 00 04 STA &0400,Y ; enemies_x # Use x position of passive enemy for active enemy &1a72 bd 43 06 LDA &0643,X ; enemies_home_column &1a75 38 SEC &1a76 e9 05 SBC #&05 &1a78 29 80 AND #&80 &1a7a 49 80 EOR #&80 ; ENEMY_FLAG_MIRRORED # Set ENEMY_FLAG_MIRRORED if on right of formation &1a7c 1d af 05 ORA &05af,X ; enemies_type_and_flags &1a7f 99 af 05 STA &05af,Y ; enemies_type_and_flags &1a82 8a TXA &1a83 99 01 06 STA &0601,Y ; enemies_passive_slot - &28 # Note which passive enemy became active &1a86 98 TYA &1a87 aa TAX # X = active slot henceforth &1a88 e6 54 INC &54 ; active_enemies &1a8a a0 7c LDY #&7c ; sound_6 &1a8c 20 e0 23 JSR &23e0 ; play_sound # Play sound for enemy becoming active &1a8f a0 00 LDY #&00 ; ATTACK_PATTERN_0 ; set_enemies_pattern_address &1a91 b9 ad 1a LDA &1aad,Y ; attack_pattern_addresses_table &1a94 9d c6 05 STA &05c6,X ; enemies_pattern_address_low - &28 &1a97 b9 ae 1a LDA &1aae,Y ; attack_pattern_addresses_table + 1 &1a9a 9d dd 05 STA &05dd,X ; enemies_pattern_address_high - &28 &1a9d a9 ff LDA #&ff &1a9f 9d f4 05 STA &05f4,X ; enemies_movement_duration - &28 # Set to negative to get new movement on next update &1aa2 4c c9 0e JMP &0ec9 ; plot_enemy # Plot active enemy ; use_this_enemy_or_consider_next_enemy_randomly &1aa5 20 97 0e JSR &0e97 ; rnd &1aa8 4a LSR A &1aa9 90 8a BCC &1a35 ; consider_next_enemy &1aab b0 86 BCS &1a33 ; use_this_enemy # Always branches ; attack_pattern_addresses_table &1aad ec 07 ; &00 ATTACK_PATTERN_0 ; &07ec = attack_pattern_0_data + 1 &1aaf 62 03 ; &02 ATTACK_PATTERN_2 ; &0362 = attack_pattern_2_data + 1 &1ab1 65 01 ; &04 ATTACK_PATTERN_4 ; &0165 = attack_pattern_4_data + 1 &1ab3 4e 01 ; &06 ATTACK_PATTERN_6 ; &014e = attack_pattern_6_data + 1 &1ab5 a2 01 ; &08 ATTACK_PATTERN_8 ; &01a2 = attack_pattern_8_data + 1 &1ab7 aa 01 ; &0a ATTACK_PATTERN_a ; &01aa = attack_pattern_a_data + 1 ; find_free_active_enemy_slot &1ab9 18 CLC &1aba a0 28 LDY #&28 ; ENEMY_SLOT_FIRST_ACTIVE ; find_free_active_enemy_slot_loop &1abc b9 db 04 LDA &04db,Y ; enemies_screen_address_high &1abf f0 06 BEQ &1ac7 ; set_enemy_accompanying_attack &1ac1 c8 INY &1ac2 c0 35 CPY #&35 ; ENEMY_SLOT_LAST_ACTIVE + 1 &1ac4 90 f6 BCC &1abc ; find_free_active_enemy_slot_loop &1ac6 60 RTS # Leave with carry set if no free slot found ; set_enemy_accompanying_attack &1ac7 a9 13 LDA #&13 ; ACTION_ACCOMPANYING_ATTACK &1ac9 99 66 05 STA &0566,Y ; enemies_action - &28 &1acc 60 RTS # Leave with carry clear to indicate slot found ; slots_of_enemies_accompanying_queens &1acd 08 04 05 ; queen 0 &1ad0 09 05 04 ; queen 1 &1ad3 10 08 04 ; queen 2 &1ad6 14 09 05 ; queen 3 ; call_additional_update_routine &1ad9 6c 12 00 JMP (&0012) ; additional_update_routine_address ; additional_update_routine_addresses_table &1adc e7 1a ; &00 : &1ae7 = update_ready_text &1ade 06 1b ; &02 : &1b06 = update_stage_number_text &1ae0 85 1b ; &04 : &1b85 = initialise_enemies &1ae2 70 1c ; &06 : &1c70 = update_arriving_enemies &1ae4 d1 1b ; &08 : &1bd1 = update_attacking_enemies ; leave &1ae6 60 RTS ; update_ready_text &1ae7 a6 32 LDX &32 ; current_player &1ae9 a9 64 LDA #&64 # Leave "Ready" on screen for 100 frames &1aeb 85 4d STA &4d ; game_state_cooldown &1aed a9 ff LDA #&ff &1aef 85 30 STA &30 ; suppress_firing_before_ready # Set to negative to suppress firing &1af1 a0 02 LDY #&02 ; update_stage_number_text &1af3 20 c6 1b JSR &1bc6 ; set_additional_update_routine_address &1af6 a0 00 LDY #&00 ; "Ready" &1af8 20 93 20 JSR &2093 ; plot_unplottable_text # Plot "Ready" &1afb 20 7f 17 JSR &177f ; plot_one_up_or_two_up &1afe 20 73 17 JSR &1773 ; plot_player_one_or_player_two &1b01 a0 00 LDY #&00 ; TUNE_READY # Start ready tune &1b03 4c 32 24 JMP &2432 ; play_tune ; update_stage_number_text &1b06 c6 4d DEC &4d ; game_state_cooldown &1b08 d0 dc BNE &1ae6 ; leave &1b0a a2 00 LDX #&00 &1b0c 86 30 STX &30 ; suppress_firing_before_ready # Set to positive to permit firing &1b0e 86 77 STX &77 ; challenge_stage # Set to positive to indicate regular stage &1b10 86 8b STX &8b ; suppress_enemy_bombs &1b12 a9 64 LDA #&64 # Leave stage number on screen for 100 frames &1b14 85 4d STA &4d ; game_state_cooldown &1b16 20 7b 20 JSR &207b ; unplot_text # Remove "Ready" &1b19 a9 09 LDA #&09 &1b1b 20 2e 1c JSR &1c2e ; divide_stage_number_by_A # Returns A = stage MOD 9, XY = stage DIV 9 &1b1e c9 01 CMP #&01 &1b20 d0 02 BNE &1b24 ; not_first_stage # Stages 1, 10, 19 ... enemies don't bomb on arrival &1b22 c6 8b DEC &8b ; suppress_enemy_bombs # Set to negative to suppress enemy bombs ; not_first_stage &1b24 a9 32 LDA #&32 # Start with 50 frame delay between attack waves &1b26 85 ba STA &ba ; frames_between_attacks &1b28 a9 04 LDA #&04 &1b2a 20 2e 1c JSR &1c2e ; divide_stage_number_by_A # Returns A = stage MOD 4, XY = stage DIV 4 &1b2d c9 03 CMP #&03 &1b2f d0 28 BNE &1b59 ; not_challenge_stage # Stages 3, 7, 11, 15 are challenge stages ; is_challenge_stage &1b31 86 3d STX &3d ; number &1b33 84 3e STY &3e ; number + 1 &1b35 a0 00 LDY #&00 &1b37 a9 04 LDA #&04 &1b39 20 3c 1c JSR &1c3c ; divide_number_by_AY # Returns A = number MOD 4, XY = DIV 4, carry clear &1b3c 0a ASL A &1b3d 69 03 ADC #&03 # Use &03, &05, &07 and &09 for challenge stages 0 - 3 &1b3f 20 1c 21 JSR &211c ; set_players_arrival_patterns_offset &1b42 c6 77 DEC &77 ; challenge_stage # Set to negative to indicate challenge stage &1b44 b9 88 21 LDA &2188,Y ; waves_arrival_patterns_offset_table + 1 &1b47 85 78 STA &78 ; challenge_enemy_type &1b49 a9 00 LDA #&00 &1b4b 85 7a STA &7a ; hits &1b4d a9 08 LDA #&08 &1b4f 85 58 STA &58 ; number_of_enemies_that_arrive_at_once &1b51 a0 08 LDY #&08 ; "CHALLENGE STAGE" &1b53 20 93 20 JSR &2093 ; plot_unplottable_text &1b56 4c 7d 1b JMP &1b7d ; start_stage ; not_challenge_stage &1b59 48 PHA ; stage MOD 4 # A = stage MOD 4 &1b5a 8a TXA # X = stage DIV 4 &1b5b 69 39 ADC #&39 ; ENEMY_SLOT_FIRST_BOMB + 4 &1b5d 85 8a STA &8a ; maximum_slot_for_enemy_bombs_plus_one # Maximum of 5, 6 or 4 bombs for stages 1, 2, 4 &1b5f 8a TXA # X = stage DIV 4 &1b60 69 2a ADC #&2a ; ENEMY_SLOT_FIRST_ACTIVE + 2 # Maximum of 3, 4 or 2 active enemies for stages 1, 2, 4 &1b62 85 bb STA &bb ; maximum_slot_for_active_enemies_plus_one &1b64 a9 08 LDA #&08 # 8 enemies arrive at once on stages 1 - 4 &1b66 24 8b BIT &8b ; suppress_enemy_bombs &1b68 30 0a BMI &1b74 ; set_number_of_enemies_that_arrive_at_once &1b6a ca DEX &1b6b 30 07 BMI &1b74 ; set_number_of_enemies_that_arrive_at_once &1b6d a9 0a LDA #&0a # 10 enemies arrive at once on stages 5 - 8 &1b6f ca DEX &1b70 30 02 BMI &1b74 ; set_number_of_enemies_that_arrive_at_once &1b72 a9 0c LDA #&0c # 12 enemies arrive at once on stage 9 onwards ; set_number_of_enemies_that_arrive_at_once &1b74 85 58 STA &58 ; number_of_enemies_that_arrive_at_once &1b76 68 PLA ; stage MOD 4 &1b77 20 1c 21 JSR &211c ; set_players_arrival_patterns_offset # Use &00, &01, &02 for regular stages 0 - 2 &1b7a 20 83 23 JSR &2383 ; plot_stage_number ; start_stage &1b7d 20 7f 17 JSR &177f ; plot_one_up_or_two_up &1b80 a0 04 LDY #&04 ; initialise_enemies &1b82 4c c6 1b JMP &1bc6 ; set_additional_update_routine_address ; initialise_enemies &1b85 c6 4d DEC &4d ; game_state_cooldown &1b87 d0 47 BNE &1bd0 ; leave &1b89 20 7b 20 JSR &207b ; unplot_text &1b8c 20 7f 17 JSR &177f ; plot_one_up_or_two_up &1b8f a2 27 LDX #&27 ; ENEMY_SLOT_LAST_PASSIVE ; initialise_enemies_loop &1b91 a9 00 LDA #&00 &1b93 9d db 04 STA &04db,X ; enemies_screen_address_high # Set to zero to indicate enemy isn't present &1b96 bc 43 06 LDY &0643,X ; enemies_home_column &1b99 b9 9d 06 LDA &069d,Y ; column_x_positions &1b9c 9d 00 04 STA &0400,X ; enemies_x &1b9f bc 6b 06 LDY &066b,X ; enemies_home_row &1ba2 b9 a7 06 LDA &06a7,Y ; row_y_positions &1ba5 9d 49 04 STA &0449,X ; enemies_y &1ba8 ca DEX &1ba9 10 e6 BPL &1b91 ; initialise_enemies_loop &1bab e8 INX ; 0 &1bac 86 4e STX &4e ; enemy_to_move &1bae 86 50 STX &50 ; passive_movement_direction # Set to positive to expand passive enemies &1bb0 86 54 STX &54 ; active_enemies &1bb2 a9 80 LDA #&80 &1bb4 85 4f STA &4f ; passive_movement_bit &1bb6 a9 07 LDA #&07 &1bb8 85 51 STA &51 ; passive_movement_cooldown &1bba a6 32 LDX &32 ; current_player &1bbc a9 f8 LDA #&f8 ; -8 &1bbe 95 56 STA &56,X ; players_arrival_count # Will become zero at &1c83 &1bc0 a9 28 LDA #&28 ; ENEMY_TOTAL_NUMBER &1bc2 95 39 STA &39,X ; players_enemies_remaining &1bc4 a0 06 LDY #&06 ; update_arriving_enemies ; set_additional_update_routine_address &1bc6 b9 dc 1a LDA &1adc,Y ; additional_update_routine_addresses_table &1bc9 85 12 STA &12 ; additional_update_routine_address_low &1bcb b9 dd 1a LDA &1add,Y ; additional_update_routine_addresses_table + 1 &1bce 85 13 STA &13 ; additional_update_routine_address_high ; leave &1bd0 60 RTS ; update_attacking_enemies &1bd1 20 d2 11 JSR &11d2 ; update_two_passive_enemies &1bd4 20 e3 19 JSR &19e3 ; consider_setting_enemies_attacking &1bd7 20 a5 1d JSR &1da5 ; update_active_enemies &1bda a6 32 LDX &32 ; current_player &1bdc b5 39 LDA &39,X ; players_enemies_remaining &1bde d0 f0 BNE &1bd0 ; leave ; all_enemies_killed &1be0 24 77 BIT &77 ; challenge_stage # Negative if challenge stage &1be2 10 30 BPL &1c14 ; not_challenge_stage ; is_challenge_stage &1be4 20 48 23 JSR &2348 ; plot_hits &1be7 20 5c 23 JSR &235c ; plot_bonus_or_perfect &1bea a9 00 LDA #&00 &1bec 85 76 STA &76 ; bonus_high &1bee a5 7a LDA &7a ; hits &1bf0 f0 22 BEQ &1c14 ; skip_bonus # No bonus for no hits! &1bf2 20 1b 22 JSR &221b ; plot_score_for_current_player &1bf5 a5 7a LDA &7a ; hits &1bf7 a2 03 LDX #&03 &1bf9 c9 40 CMP #&40 # 40 hits needed for perfect clear &1bfb d0 06 BNE &1c03 ; not_perfect &1bfd a0 10 LDY #&10 ; 10,000 # Add 10,000 points for perfect clear &1bff a9 00 LDA #&00 ; 000 &1c01 f0 08 BEQ &1c0b ; add_bonus # Always branches ; not_perfect ; multiplication_loop &1c03 0a ASL A &1c04 26 76 ROL &76 ; bonus_high &1c06 ca DEX &1c07 10 fa BPL &1c03 ; multiplication_loop &1c09 a4 76 LDY &76 ; bonus_high # Add 80 points for each hit ; add_bonus &1c0b 20 dc 12 JSR &12dc ; add_AY_to_score &1c0e 20 d1 18 JSR &18d1 ; consider_extra_life &1c11 20 1b 22 JSR &221b ; plot_score_for_current_player ; skip_bonus ; not_challenge_stage &1c14 a6 32 LDX &32 ; current_player &1c16 a9 01 LDA #&01 # Next stage &1c18 18 CLC &1c19 f8 SED &1c1a 75 37 ADC &37,X ; players_stage &1c1c 95 37 STA &37,X ; players_stage &1c1e b5 25 LDA &25,X ; players_stage_high &1c20 69 00 ADC #&00 &1c22 95 25 STA &25,X ; players_stage_high &1c24 d8 CLD &1c25 a9 64 LDA #&64 # Display next stage number for 100 frames &1c27 85 4d STA &4d ; game_state_cooldown &1c29 a0 02 LDY #&02 ; update_stage_number_text &1c2b 4c c6 1b JMP &1bc6 ; set_additional_update_routine_address ; divide_stage_number_by_A # Called with A = divisor &1c2e a6 32 LDX &32 ; current_player &1c30 b4 37 LDY &37,X ; players_stage &1c32 84 3d STY &3d ; number &1c34 b4 25 LDY &25,X ; players_stage_high &1c36 84 3e STY &3e ; number + 1 &1c38 a0 00 LDY #&00 &1c3a 84 3f STY &3f ; number + 2 ; divide_number_by_AY &1c3c f8 SED &1c3d 85 76 STA &76 ; divisor_low &1c3f 84 80 STY &80 ; divisor_high &1c41 a0 00 LDY #&00 &1c43 a2 00 LDX #&00 ; division_loop &1c45 38 SEC &1c46 a5 3d LDA &3d ; number &1c48 e5 76 SBC &76 ; divisor_low &1c4a 48 PHA ; result low &1c4b a5 3e LDA &3e ; number + 1 &1c4d e5 80 SBC &80 ; divisor_high &1c4f 48 PHA ; result middle &1c50 a5 3f LDA &3f ; number + 2 &1c52 e9 00 SBC #&00 &1c54 90 13 BCC &1c69 ; leave_with_result &1c56 85 3f STA &3f ; number + 2 &1c58 68 PLA ; result middle &1c59 85 3e STA &3e ; number + 1 &1c5b 68 PLA ; result low &1c5c 85 3d STA &3d ; number &1c5e 8a TXA &1c5f 69 00 ADC #&00 &1c61 aa TAX &1c62 98 TYA &1c63 69 00 ADC #&00 &1c65 a8 TAY &1c66 4c 45 1c JMP &1c45 ; division_loop ; leave_with_result &1c69 68 PLA ; result middle &1c6a 68 PLA ; result low &1c6b a5 3d LDA &3d ; number &1c6d d8 CLD &1c6e 60 RTS # Leaves with A = modulus, XY = result, carry clear ; leave &1c6f 60 RTS ; update_arriving_enemies &1c70 20 d5 11 JSR &11d5 ; update_one_passive_enemy &1c73 a5 54 LDA &54 ; active_enemies &1c75 f0 03 BEQ &1c7a ; consider_making_more_enemies_arrive &1c77 4c a5 1d JMP &1da5 ; update_active_enemies ; consider_making_more_enemies_arrive &1c7a 24 33 BIT &33 ; player_dead # Negative if player is dead &1c7c 30 f1 BMI &1c6f ; leave &1c7e a6 32 LDX &32 ; current_player &1c80 b5 56 LDA &56,X ; players_arrival_count &1c82 18 CLC &1c83 69 08 ADC #&08 &1c85 95 56 STA &56,X ; players_arrival_count &1c87 c9 28 CMP #&28 ; ENEMY_TOTAL_NUMBER &1c89 90 09 BCC &1c94 ; add_new_arriving_enemies ; all_enemies_arrived &1c8b a9 00 LDA #&00 &1c8d 85 8b STA &8b ; suppress_enemy_bombs # Set to positive to allow enemy bombs &1c8f a0 08 LDY #&08 ; update_attacking_enemies &1c91 4c c6 1b JMP &1bc6 ; set_additional_update_routine_address ; add_new_arriving_enemies &1c94 85 45 STA &45 ; new_arrival_passive_slot &1c96 85 46 STA &46 ; new_arrival_first_passive_slot &1c98 a9 28 LDA #&28 ; ENEMY_SLOT_FIRST_ACTIVE &1c9a 85 47 STA &47 ; new_arrival_active_slot &1c9c 85 55 STA &55 ; enemy_to_consider &1c9e a9 14 LDA #&14 # First enemy arrives after 20 frames &1ca0 85 65 STA &65 ; frame_offset ; add_new_arriving_enemies_pattern_loop &1ca2 a6 32 LDX &32 ; current_player &1ca4 b4 74 LDY &74,X ; players_arrival_patterns_offset # Get next arrival pattern &1ca6 f6 74 INC &74,X ; players_arrival_patterns_offset &1ca8 a2 08 LDX #&08 # Subsequent enemies arrive every 8 frames &1caa b9 59 21 LDA &2159,Y ; wave_arrival_patterns_table # Top bit determines speed of arrival; faster if set &1cad 08 PHP ; wave arrival pattern sign &1cae 30 02 BMI &1cb2 ; top_bit_set &1cb0 a2 10 LDX #&10 # Subsequent enemies arrive every 16 frames ; top_bit_set &1cb2 86 68 STX &68 ; frame_offset_delta &1cb4 29 7f AND #&7f # Lowest seven bits set pattern &1cb6 a8 TAY &1cb7 20 fe 20 JSR &20fe ; get_arrival_pattern_address_and_delay &1cba a0 00 LDY #&00 &1cbc b1 66 LDA (&66),Y ; arrival_pattern_address # First byte of pattern data sets start x position &1cbe a6 73 LDX &73 ; mirror_arrival_pattern # Non-zero to mirror arrival pattern horizontally &1cc0 f0 05 BEQ &1cc7 ; skip_horizontal_mirroring &1cc2 a9 4c LDA #&4c &1cc4 38 SEC &1cc5 f1 66 SBC (&66),Y ; arrival_pattern_address ; skip_horizontal_mirroring &1cc7 85 61 STA &61 ; enemy_start_x &1cc9 c8 INY &1cca b1 66 LDA (&66),Y ; arrival_pattern_address # Second byte of pattern data sets start y position &1ccc 85 64 STA &64 ; enemy_start_y ; add_new_arriving_enemies_enemy_loop &1cce a6 47 LDX &47 ; new_arrival_active_slot &1cd0 a5 61 LDA &61 ; enemy_start_x &1cd2 9d 00 04 STA &0400,X ; enemies_x # Put new enemy at start position &1cd5 a5 64 LDA &64 ; enemy_start_y &1cd7 9d 49 04 STA &0449,X ; enemies_y &1cda 18 CLC &1cdb a5 52 LDA &52 ; previous_frame_counter &1cdd 65 65 ADC &65 ; frame_offset &1cdf 9d 45 05 STA &0545,X ; enemies_frame_counter # Update after frame_offset frames &1ce2 20 97 0e JSR &0e97 ; rnd &1ce5 29 03 AND #&03 # Add randomness to when enemies can start bombing &1ce7 65 63 ADC &63 ; arrival_pattern_delay &1ce9 65 52 ADC &52 ; previous_frame_counter &1ceb 65 65 ADC &65 ; frame_offset &1ced 9d 0e 06 STA &060e,X ; enemies_next_bombing_frame - &28 &1cf0 a9 ff LDA #&ff ; NOT_PLOTTED &1cf2 9d db 04 STA &04db,X ; enemies_screen_address_high # Set to &ff to indicate enemy exists, but not plotted &1cf5 9d f4 05 STA &05f4,X ; enemies_movement_duration - &28 # Set to negative to get new movement on next update &1cf8 a5 66 LDA &66 ; arrival_pattern_address_low &1cfa 18 CLC &1cfb 69 01 ADC #&01 # Add one to move past x position byte; y position byte &1cfd 9d c6 05 STA &05c6,X ; enemies_pattern_address_low - &28 # will be moved past on first movement at &1e4b &1d00 a9 00 LDA #&00 &1d02 65 67 ADC &67 ; arrival_pattern_address_high &1d04 9d dd 05 STA &05dd,X ; enemies_pattern_address_high - &28 &1d07 a5 45 LDA &45 ; new_arrival_passive_slot &1d09 38 SEC &1d0a e5 46 SBC &46 ; new_arrival_first_passive_slot &1d0c c9 04 CMP #&04 &1d0e 08 PHP ; late enemy comparison # Store if this is the fifth or later enemy &1d0f a5 46 LDA &46 ; new_arrival_first_passive_slot &1d11 4a LSR A # Enemies arrive in groups of four of the same type &1d12 4a LSR A &1d13 a8 TAY &1d14 b9 93 06 LDA &0693,Y ; arriving_enemy_types_table &1d17 c9 04 CMP #&04 ; ENEMY_TYPE_QUEEN &1d19 f0 06 BEQ &1d21 ; skip_using_challenge_enemy_type &1d1b 24 77 BIT &77 ; challenge_stage # Negative if challenge stage &1d1d 10 02 BPL &1d21 ; skip_using_challenge_enemy_type &1d1f a5 78 LDA &78 ; challenge_enemy_type # Override enemy type for challenge stages, if not queen ; skip_using_challenge_enemy_type &1d21 05 73 ORA &73 ; mirror_arrival_pattern &1d23 28 PLP ; late enemy comparison &1d24 08 PHP ; late enemy comparison # Is this the fifth or later enemy? &1d25 90 02 BCC &1d29 ; not_transient &1d27 09 40 ORA #&40 ; ENEMY_FLAG_TRANSIENT # If so, set ENEMY_FLAG_TRANSIENT; enemy won't remain ; not_transient &1d29 9d af 05 STA &05af,X ; enemies_type_and_flags &1d2c a0 02 LDY #&02 &1d2e b1 66 LDA (&66),Y ; arrival_pattern_address # Third byte of pattern data sets angle of sprite &1d30 29 1f AND #&1f ; ANGLE_MASK &1d32 a8 TAY &1d33 b9 48 07 LDA &0748,Y ; angles_to_sprite_rotations_table &1d36 20 96 1d JSR &1d96 ; get_enemy_type_and_flags # Returns Y = enemy type &1d39 18 CLC &1d3a 79 92 21 ADC &2192,Y ; types_to_sprites_table &1d3d 9d 92 04 STA &0492,X ; enemies_sprite &1d40 a9 09 LDA #&09 ; ACTION_CHALLENGE # Challenge stage enemies arrive and leave in patterns &1d42 28 PLP ; late enemy comparison &1d43 24 77 BIT &77 ; challenge_stage # Negative if challenge stage &1d45 30 06 BMI &1d4d ; set_enemies_action &1d47 a9 00 LDA #&00 ; ACTION_ARRIVAL # First to fourth enemies arrive and take passive slots &1d49 90 02 BCC &1d4d ; set_enemies_action &1d4b a9 04 LDA #&04 ; ACTION_TRANSIENT_ARRIVAL # Subsequent enemies arrive and leave ; set_enemies_action &1d4d 9d 66 05 STA &0566,X ; enemies_action - &28 &1d50 a5 45 LDA &45 ; new_arrival_passive_slot &1d52 9d 01 06 STA &0601,X ; enemies_passive_slot - &28 # Note corresponding passive slot for arriving enemy &1d55 e6 45 INC &45 ; new_arrival_passive_slot &1d57 e6 47 INC &47 ; new_arrival_active_slot &1d59 a5 65 LDA &65 ; frame_offset &1d5b 18 CLC &1d5c 65 68 ADC &68 ; frame_offset_delta &1d5e 85 65 STA &65 ; frame_offset &1d60 a5 47 LDA &47 ; new_arrival_active_slot &1d62 38 SEC &1d63 e9 28 SBC #&28 ; ENEMY_SLOT_FIRST_ACTIVE &1d65 c5 58 CMP &58 ; number_of_enemies_that_arrive_at_once &1d67 b0 27 BCS &1d90 ; leave_after_setting_active_enemies # Leave if enough active enemies have been added &1d69 a5 45 LDA &45 ; new_arrival_passive_slot &1d6b 38 SEC &1d6c e5 46 SBC &46 ; new_arrival_first_passive_slot &1d6e 0a ASL A &1d6f c5 58 CMP &58 ; number_of_enemies_that_arrive_at_once &1d71 90 1a BCC &1d8d ; to_add_new_arriving_enemies_enemy_loop ; is_second_half_of_arriving_wave # Stagger second half of arriving enemies &1d73 a6 32 LDX &32 ; current_player &1d75 b5 56 LDA &56,X ; players_arrival_count &1d77 69 03 ADC #&03 # Carry is set, so add 4 &1d79 85 45 STA &45 ; new_arrival_passive_slot &1d7b 85 46 STA &46 ; new_arrival_first_passive_slot &1d7d a9 1c LDA #&1c # Arrive after 28 frames &1d7f 85 65 STA &65 ; frame_offset &1d81 28 PLP ; wave arrival pattern sign &1d82 08 PHP ; wave arrival pattern sign # Negative if faster arrival &1d83 10 08 BPL &1d8d ; to_add_new_arriving_enemies_enemy_loop &1d85 a9 14 LDA #&14 # Arrive after 20 frames &1d87 85 65 STA &65 ; frame_offset &1d89 28 PLP ; wave arrival pattern sign &1d8a 4c a2 1c JMP &1ca2 ; add_new_arriving_enemies_pattern_loop ; to_add_new_arriving_enemies_enemy_loop &1d8d 4c ce 1c JMP &1cce ; add_new_arriving_enemies_enemy_loop ; leave_after_setting_active_enemies &1d90 a5 58 LDA &58 ; number_of_enemies_that_arrive_at_once &1d92 85 54 STA &54 ; active_enemies &1d94 28 PLP ; wave arrival pattern sign &1d95 60 RTS ; get_enemy_type_and_flags &1d96 48 PHA ; tmp_a &1d97 bd af 05 LDA &05af,X ; enemies_type_and_flags &1d9a 85 76 STA &76 ; enemy_type_and_flags &1d9c c9 80 CMP #&80 ; ENEMY_FLAG_MIRRORED &1d9e 29 1f AND #&1f ; ENEMY_TYPE_MASK &1da0 a8 TAY &1da1 24 76 BIT &76 ; enemy_type_and_flags # Leave with V set if ENEMY_FLAG_TRANSIENT set &1da3 68 PLA ; tmp_a # Leave with carry set if ENEMY_FLAG_MIRRORED set &1da4 60 RTS # Leave with Y = enemy type ; update_active_enemies &1da5 a4 55 LDY &55 ; enemy_to_consider &1da7 84 59 STY &59 ; last_enemy_to_consider ; update_active_enemies_loop &1da9 20 c7 1d JSR &1dc7 ; update_active_enemy &1dac e6 55 INC &55 ; enemy_to_consider &1dae a5 58 LDA &58 ; number_of_enemies_that_arrive_at_once &1db0 18 CLC &1db1 69 28 ADC #&28 ; ENEMY_SLOT_FIRST_ACTIVE &1db3 c5 55 CMP &55 ; enemy_to_consider &1db5 b0 04 BCS &1dbb ; skip_wraparound &1db7 a9 28 LDA #&28 ; ENEMY_SLOT_FIRST_ACTIVE &1db9 85 55 STA &55 ; enemy_to_consider ; skip_wraparound &1dbb a4 55 LDY &55 ; enemy_to_consider &1dbd c4 59 CPY &59 ; last_enemy_to_consider &1dbf f0 05 BEQ &1dc6 ; leave &1dc1 20 11 0e JSR &0e11 ; check_if_same_frame &1dc4 f0 e3 BEQ &1da9 ; update_active_enemies_loop ; leave &1dc6 60 RTS ; update_active_enemy &1dc7 a6 55 LDX &55 ; enemy_to_consider &1dc9 bd db 04 LDA &04db,X ; enemies_screen_address_high &1dcc f0 f8 BEQ &1dc6 ; leave # Zero if no enemy in slot ; update_active_enemy_assuming_present &1dce bc 66 05 LDY &0566,X ; enemies_action - &28 &1dd1 b9 e2 1d LDA &1de2,Y ; actions_to_action_routine_table &1dd4 a8 TAY &1dd5 b9 03 1e LDA &1e03,Y ; action_routine_addresses_table &1dd8 85 08 STA &08 ; action_routine_address_low &1dda b9 04 1e LDA &1e04,Y ; action_routine_addresses_table + 1 &1ddd 85 09 STA &09 ; action_routine_address_high &1ddf 6c 08 00 JMP (&0008) ; action_routine_address ; actions_to_action_routines_table &1de2 00 ; &00 = wait_for_frame_counter # ACTION_ARRIVAL &1de3 02 ; &01 = apply_movement_from_pattern &1de4 08 ; &02 = reset_sprite_and_next_bombing_frame &1de5 04 ; &03 = return_to_passive_position &1de6 00 ; &04 = wait_for_frame_counter # ACTION_TRANSIENT_ARRIVAL &1de7 02 ; &05 = apply_movement_from_pattern &1de8 16 ; &06 = change_to_pattern_2 &1de9 02 ; &07 = apply_movement_from_pattern &1dea 18 ; &08 = remove_transient_enemy &1deb 00 ; &09 = wait_for_frame_counter # ACTION_CHALLENGE &1dec 02 ; &0a = apply_movement_from_pattern &1ded 18 ; &0b = decrement_active_enemies &1dee 02 ; &0c = apply_movement_from_pattern # ACTION_ATTACK &1def 1a ; &0d = start_attack &1df0 1c ; &0e = continue_attack &1df1 06 ; &0f = change_to_pattern_4 &1df2 02 ; &10 = apply_movement_from_pattern &1df3 0a ; &11 = set_returning_from_top_of_screen &1df4 04 ; &12 = return_to_passive_position &1df5 02 ; &13 = apply_movement_from_pattern # ACTION_ACCOMPANYING_ATTACK &1df6 0c ; &14 = change_to_pattern_6 &1df7 02 ; &15 = apply_movement_from_pattern &1df8 0a ; &16 = set_returning_from_top_of_screen &1df9 04 ; &17 = return_to_passive_position &1dfa 02 ; &18 = apply_movement_from_pattern # ACTION_DOUBLING_ATTACK &1dfb 0e ; &19 = change_to_pattern_8 &1dfc 02 ; &1a = apply_movement_from_pattern &1dfd 10 ; &1b = start_emitting_doubling_wave &1dfe 12 ; &1c = continue_emitting_doubling_wave &1dff 14 ; &1d = change_to_pattern_a &1e00 02 ; &1e = apply_movement_from_pattern &1e01 0a ; &1f = set_returning_from_top_of_screen &1e02 04 ; &20 = return_to_passive_position ; action_routine_addresses_table &1e03 2a 1e ; &00 : &1e2a = wait_for_frame_counter &1e05 39 1e ; &02 : &1e39 = apply_movement_from_pattern &1e07 30 1f ; &04 : &1f30 = return_to_passive_position &1e09 e5 1e ; &06 : &1ee5 = change_to_pattern_4 &1e0b ca 1e ; &08 : &1eca = reset_sprite_and_next_bombing_frame &1e0d b2 1e ; &0a : &1eb2 = set_returning_from_top_of_screen &1e0f f1 1e ; &0c : &1ef1 = change_to_pattern_6 &1e11 eb 1e ; &0e : &1eeb = change_to_pattern_8 &1e13 0f 27 ; &10 : &270f = start_emitting_doubling_wave &1e15 c7 26 ; &12 : &26c7 = continue_emitting_doubling_wave &1e17 ee 1e ; &14 : &1eee = change_to_pattern_a &1e19 f4 1e ; &16 : &1ef4 = change_to_pattern_2 &1e1b a8 1f ; &18 : &1fa8 = remove_transient_enemy &1e1d fc 1e ; &1a : &1efc = start_attack &1e1f 02 1f ; &1c : &1f02 = continue_attack ; increment_enemy_action &1e21 fe 66 05 INC &0566,X ; enemies_action - &28 &1e24 a5 52 LDA &52 ; previous_frame_counter &1e26 9d 45 05 STA &0545,X ; enemies_frame_counter # Update on next check &1e29 60 RTS ; wait_for_frame_counter &1e2a a5 52 LDA &52 ; previous_frame_counter &1e2c dd 45 05 CMP &0545,X ; enemies_frame_counter &1e2f 30 95 BMI &1dc6 ; leave &1e31 f0 93 BEQ &1dc6 ; leave &1e33 20 21 1e JSR &1e21 ; increment_enemy_action &1e36 4c 3c 1e JMP &1e3c ; apply_movement_from_pattern_without_unplotting ; apply_movement_from_pattern &1e39 20 cc 0e JSR &0ecc ; unplot_enemy ; apply_movement_from_pattern_without_unplotting &1e3c a5 52 LDA &52 ; previous_frame_counter &1e3e 38 SEC &1e3f fd 45 05 SBC &0545,X ; enemies_frame_counter &1e42 85 80 STA &80 ; elapsed_frames &1e44 f0 5e BEQ &1ea4 ; set_enemies_frame_counter_and_plot_enemy # No movement if no time has elapsed ; apply_movement_from_pattern_loop &1e46 de f4 05 DEC &05f4,X ; enemies_movement_duration - &28 &1e49 10 12 BPL &1e5d ; not_new_movement &1e4b fe c6 05 INC &05c6,X ; enemies_pattern_address_low - &28 # Move to next byte of pattern data &1e4e d0 03 BNE &1e53 ; skip_page &1e50 fe dd 05 INC &05dd,X ; enemies_pattern_address_high - &28 ; skip_page &1e53 20 da 1f JSR &1fda ; get_byte_of_enemy_pattern_data # Get next byte of pattern data &1e56 20 d9 23 JSR &23d9 ; get_top_nibble &1e59 4a LSR A &1e5a 9d f4 05 STA &05f4,X ; enemies_movement_duration - &28 # Top three bits set duration of movement ; not_new_movement &1e5d 20 da 1f JSR &1fda ; get_byte_of_enemy_pattern_data # Get the same byte of pattern data again &1e60 c9 ff CMP #&ff # &ff marks end of pattern &1e62 f0 48 BEQ &1eac ; update_active_enemy_after_incrementing_enemy_action &1e64 29 1f AND #&1f ; ANGLE_MASK # Lowest five bits set angle of movement &1e66 a8 TAY &1e67 bd af 05 LDA &05af,X ; enemies_type_and_flags &1e6a 0a ASL A # Shift top bit (ENEMY_FLAG_MIRRORED) into carry &1e6b bd 00 04 LDA &0400,X ; enemies_x &1e6e 90 06 BCC &1e76 ; apply_regular_x_velocity # If ENEMY_FLAG_MIRRORED is set, ; apply_mirrored_x_velocity &1e70 f9 16 07 SBC &0716,Y ; angles_to_x_velocities_table # subtract x velocity &1e73 4c 79 1e JMP &1e79 ; set_enemies_x ; apply_regular_x_velocity &1e76 79 16 07 ADC &0716,Y ; angles_to_x_velocities_table # otherwise add x velocity ; set_enemies_x &1e79 9d 00 04 STA &0400,X ; enemies_x &1e7c 18 CLC &1e7d bd 49 04 LDA &0449,X ; enemies_y &1e80 79 2f 07 ADC &072f,Y ; angles_to_y_velocities_table # Add y velocity &1e83 9d 49 04 STA &0449,X ; enemies_y &1e86 b9 48 07 LDA &0748,Y ; angles_to_sprite_rotations_table &1e89 30 15 BMI &1ea0 ; skip_updating_sprite &1e8b 20 96 1d JSR &1d96 ; get_enemy_type_and_flags # Returns Y = enemy type &1e8e 90 0a BCC &1e9a ; set_enemies_sprite # carry set if ENEMY_FLAG_MIRRORED if set &1e90 49 ff EOR #&ff &1e92 69 0c ADC #&0c # Mirror sprite rotation &1e94 c9 0c CMP #&0c &1e96 90 02 BCC &1e9a ; set_enemies_sprite &1e98 a9 ff LDA #&ff # Carry is set, so add zero ; set_enemies_sprite &1e9a 79 92 21 ADC &2192,Y ; types_to_sprites_table &1e9d 9d 92 04 STA &0492,X ; enemies_sprite # Set sprite from type and angle ; skip_updating_sprite &1ea0 c6 80 DEC &80 ; elapsed_frames &1ea2 d0 a2 BNE &1e46 ; apply_movement_from_pattern_loop ; set_enemies_frame_counter_and_plot_enemy &1ea4 a5 52 LDA &52 ; previous_frame_counter &1ea6 9d 45 05 STA &0545,X ; enemies_frame_counter # Update on next check &1ea9 4c c9 0e JMP &0ec9 ; plot_enemy ; update_active_enemy_after_incrementing_enemy_action &1eac 20 21 1e JSR &1e21 ; increment_enemy_action &1eaf 4c ce 1d JMP &1dce ; update_active_enemy_assuming_present ; set_returning_from_top_of_screen &1eb2 bc 01 06 LDY &0601,X ; enemies_passive_slot - &28 # Y = passive slot, X = active slot &1eb5 b9 00 04 LDA &0400,Y ; enemies_x &1eb8 9d 00 04 STA &0400,X ; enemies_x # Set enemy x to passive x &1ebb a9 7e LDA #&7e &1ebd 9d 49 04 STA &0449,X ; enemies_y # Set enemy y to &7e (top of screen) &1ec0 38 SEC &1ec1 f9 49 04 SBC &0449,Y ; enemies_y &1ec4 4a LSR A &1ec5 9d c6 05 STA &05c6,X ; enemies_frames_to_return - &28 # Number of frames depends on distance to return &1ec8 10 05 BPL &1ecf ; set_enemies_sprite # Always branches ; reset_sprite_and_next_bombing_frame &1eca a9 0c LDA #&0c &1ecc 9d c6 05 STA &05c6,X ; enemies_frames_to_return - &28 # Arriving enemies take 12 frames to return ; set_enemies_sprite &1ecf 20 96 1d JSR &1d96 ; get_enemy_type_and_flags # Returns Y = enemy type &1ed2 b9 92 21 LDA &2192,Y ; types_to_sprites_table &1ed5 9d 92 04 STA &0492,X ; enemies_sprite &1ed8 a5 52 LDA &52 ; previous_frame_counter &1eda 69 7e ADC #&7e &1edc 9d 0e 06 STA &060e,X ; enemies_next_bombing_frame - &28 ; increment_enemy_action_and_plot_enemy &1edf 20 21 1e JSR &1e21 ; increment_enemy_action &1ee2 4c c9 0e JMP &0ec9 ; plot_enemy ; change_to_pattern_4 &1ee5 20 cc 0e JSR &0ecc ; unplot_enemy &1ee8 a0 04 LDY #&04 ; ATTACK_PATTERN_4 &1eea dc a0 08 NOP &08a0,X ; change_to_pattern_8 #1eeb LDY #&08 ; ATTACK_PATTERN_8 &1eed dc a0 0a NOP &0aa0,X ; change_to_pattern_a #1eee LDY #&0a ; ATTACK_PATTERN_a &1ef0 dc a0 06 NOP &06a0,X ; change_to_pattern_6 #1ef1 LDY #&06 ; ATTACK_PATTERN_6 &1ef3 dc a0 02 NOP &02a0,X ; change_to_pattern_2 #1ef4 LDY #&02 ; ATTACK_PATTERN_2 &1ef6 20 91 1a JSR &1a91 ; set_enemies_pattern_address &1ef9 4c 21 1e JMP &1e21 ; increment_enemy_action ; start_attack &1efc 20 21 1e JSR &1e21 ; increment_enemy_action &1eff 4c 05 1f JMP &1f05 ; continue_attack_without_unplotting_enemy ; continue_attack &1f02 20 cc 0e JSR &0ecc ; unplot_enemy ; continue_attack_without_unplotting_enemy &1f05 a5 52 LDA &52 ; previous_frame_counter &1f07 38 SEC &1f08 fd 45 05 SBC &0545,X ; enemies_frame_counter &1f0b a8 TAY &1f0c 88 DEY ; continue_attack_loop &1f0d de 49 04 DEC &0449,X ; enemies_y # Move enemy downwards &1f10 bd af 05 LDA &05af,X ; enemies_type_and_flags # Negative if ENEMY_FLAG_MIRRORED is set &1f13 10 06 BPL &1f1b ; move_enemy_right ; move_enemy_left &1f15 de 00 04 DEC &0400,X ; enemies_x &1f18 4c 1e 1f JMP &1f1e ; moved_left_or_right ; move_enemy_right &1f1b fe 00 04 INC &0400,X ; enemies_x ; moved_left_or_right &1f1e bd 49 04 LDA &0449,X ; enemies_y &1f21 c9 2d CMP #&2d &1f23 90 ba BCC &1edf ; increment_enemy_action_and_plot_enemy # Change to pattern once enemy gets low &1f25 88 DEY &1f26 10 e5 BPL &1f0d ; continue_attack_loop &1f28 a5 52 LDA &52 ; previous_frame_counter &1f2a 9d 45 05 STA &0545,X ; enemies_frame_counter # Update on next check &1f2d 4c c9 0e JMP &0ec9 ; plot_enemy ; return_to_passive_position &1f30 20 cc 0e JSR &0ecc ; unplot_enemy &1f33 bc 01 06 LDY &0601,X ; enemies_passive_slot - &28 # Y = passive slot, X = active slot &1f36 a5 52 LDA &52 ; previous_frame_counter &1f38 38 SEC &1f39 fd 45 05 SBC &0545,X ; enemies_frame_counter &1f3c 85 45 STA &45 ; elapsed_frames &1f3e dd c6 05 CMP &05c6,X ; enemies_frames_to_return - &28 &1f41 b0 3c BCS &1f7f ; at_passive_position # If enemy hasn't reached passive position, &1f43 a5 52 LDA &52 ; previous_frame_counter # calculate interpolated position &1f45 9d 45 05 STA &0545,X ; enemies_frame_counter # Update on next check &1f48 bd c6 05 LDA &05c6,X ; enemies_frames_to_return - &28 &1f4b 85 80 STA &80 ; frames_to_return &1f4d 38 SEC &1f4e e5 45 SBC &45 ; elapsed_frames &1f50 9d c6 05 STA &05c6,X ; enemies_frames_to_return - &28 &1f53 b9 00 04 LDA &0400,Y ; enemies_x &1f56 38 SEC &1f57 fd 00 04 SBC &0400,X ; enemies_x # X difference between passive and active position &1f5a 20 b5 1f JSR &1fb5 ; calculate_interpolated_distance &1f5d 7d 00 04 ADC &0400,X ; enemies_x &1f60 9d 00 04 STA &0400,X ; enemies_x &1f63 d9 00 04 CMP &0400,Y ; enemies_x &1f66 08 PHP ; at passive x &1f67 b9 49 04 LDA &0449,Y ; enemies_y &1f6a 38 SEC &1f6b fd 49 04 SBC &0449,X ; enemies_y # Y difference between passive and active position &1f6e 20 b5 1f JSR &1fb5 ; calculate_interpolated_distance &1f71 7d 49 04 ADC &0449,X ; enemies_y &1f74 9d 49 04 STA &0449,X ; enemies_y &1f77 28 PLP ; at passive x &1f78 d0 2b BNE &1fa5 ; to_plot_enemy # Has the enemy reached passive position? &1f7a d9 49 04 CMP &0449,Y ; enemies_y &1f7d d0 26 BNE &1fa5 ; to_plot_enemy # If not, plot active enemy ; at_passive_position &1f7f e4 c5 CPX &c5 ; doubling_attack_queen &1f81 d0 04 BNE &1f87 ; not_doubling_enemy &1f83 a9 ff LDA #&ff &1f85 85 c5 STA &c5 ; doubling_attack_queen # Set to negative to indicate no queen doubling attacking ; not_doubling_enemy &1f87 bd af 05 LDA &05af,X ; enemies_type_and_flags &1f8a 29 3f AND #&3f ; ENEMY_TYPE_MASK | &20 # Clear ENEMY_FLAG_MIRRORED and ENEMY_FLAG_TRANSIENT &1f8c 99 af 05 STA &05af,Y ; enemies_type_and_flags &1f8f a8 TAY &1f90 b9 92 21 LDA &2192,Y ; types_to_sprites_table &1f93 bc 01 06 LDY &0601,X ; enemies_passive_slot - &28 # Y = passive slot, X = active slot &1f96 99 92 04 STA &0492,Y ; enemies_sprite &1f99 8a TXA &1f9a 48 PHA ; tmp_x &1f9b 98 TYA &1f9c aa TAX &1f9d 20 c9 0e JSR &0ec9 ; plot_enemy # Plot enemy in passive position &1fa0 68 PLA ; tmp_x &1fa1 aa TAX &1fa2 c6 54 DEC &54 ; active_enemies &1fa4 60 RTS ; to_plot_enemy &1fa5 4c c9 0e JMP &0ec9 ; plot_enemy ; remove_transient_enemy &1fa8 c6 54 DEC &54 ; active_enemies &1faa bd af 05 LDA &05af,X ; enemies_type_and_flags &1fad 0a ASL A &1fae 30 04 BMI &1fb4 ; leave # Leave if ENEMY_FLAG_TRANSIENT is set &1fb0 a6 32 LDX &32 ; current_player &1fb2 d6 39 DEC &39,X ; players_enemies_remaining ; leave &1fb4 60 RTS ; calculate_interpolated_position # Called with A = difference between positions &1fb5 08 PHP ; sign of difference &1fb6 84 46 STY &46 ; tmp_y &1fb8 20 cf 1f JSR &1fcf ; invert_if_negative &1fbb a4 45 LDY &45 ; elapsed_frames &1fbd 85 47 STA &47 ; multiplier &1fbf a9 00 LDA #&00 ; multiplication_loop &1fc1 65 47 ADC &47 ; multiplier &1fc3 88 DEY &1fc4 d0 fb BNE &1fc1 ; multiplication_loop &1fc6 88 DEY ; division_loop &1fc7 c8 INY &1fc8 38 SEC &1fc9 e5 80 SBC &80 ; frames_to_return &1fcb b0 fa BCS &1fc7 ; division_loop &1fcd 98 TYA &1fce 28 PLP ; sign of difference ; invert_if_negative &1fcf 10 05 BPL &1fd6 ; skip_inversion &1fd1 49 ff EOR #&ff &1fd3 38 SEC &1fd4 69 00 ADC #&00 ; skip_inversion &1fd6 a4 46 LDY &46 ; tmp_y &1fd8 18 CLC &1fd9 60 RTS ; get_byte_of_enemy_pattern_data &1fda bd c6 05 LDA &05c6,X ; enemies_pattern_address_low - &28 &1fdd 85 08 STA &08 ; pattern_address_low &1fdf bd dd 05 LDA &05dd,X ; enemies_pattern_address_high - &28 &1fe2 85 09 STA &09 ; pattern_address_high &1fe4 a0 00 LDY #&00 &1fe6 b1 08 LDA (&08),Y ; pattern_address ; leave &1fe8 60 RTS ; consider_adding_enemy_bombs &1fe9 a5 77 LDA &77 ; challenge_stage # Negative if challenge stage &1feb 05 8b ORA &8b ; suppress_enemy_bombs # Negative if enemy bombs are suppressed &1fed 30 f9 BMI &1fe8 ; leave # No bombs in challenge stage or first stage arrival &1fef a0 28 LDY #&28 ; ENEMY_SLOT_FIRST_ACTIVE ; consider_adding_enemy_bombs_loop # For each active enemy, &1ff1 b9 db 04 LDA &04db,Y ; enemies_screen_address_high &1ff4 f0 7c BEQ &2072 ; consider_next_enemy # Can't bomb if no enemy in slot &1ff6 c9 ff CMP #&ff ; NOT_PLOTTED &1ff8 f0 78 BEQ &2072 ; consider_next_enemy # Can't bomb if enemy not yet plotted &1ffa c4 c5 CPY &c5 ; doubling_attack_queen &1ffc f0 74 BEQ &2072 ; consider_next_enemy # Can't bomb if doubling attacking queen &1ffe a5 52 LDA &52 ; previous_frame_counter &2000 d9 0e 06 CMP &060e,Y ; enemies_next_bombing_frame - &28 &2003 30 6d BMI &2072 ; consider_next_enemy # Can't bomb before time &2005 69 7e ADC #&7e &2007 99 0e 06 STA &060e,Y ; enemies_next_bombing_frame - &28 &200a a2 35 LDX #&35 ; ENEMY_SLOT_FIRST_BOMB ; find_slot_for_enemy_bomb # Find a slot for the new bomb &200c bd db 04 LDA &04db,X ; enemies_screen_address_high &200f f0 0b BEQ &201c ; found_slot_for_enemy_bomb # Zero if slot is empty &2011 e8 INX &2012 e0 3f CPX #&3f ; ENEMY_SLOT_LAST_BOMB + 1 &2014 b0 d2 BCS &1fe8 ; leave # Leave if no free slot found &2016 e4 8a CPX &8a ; maximum_slot_for_enemy_bombs_plus_one &2018 90 f2 BCC &200c ; find_slot_for_enemy_bomb &201a b0 cc BCS &1fe8 ; leave # Leave if too many bombs; always branches ; found_slot_for_enemy_bomb &201c a5 19 LDA &19 ; player_doubled # &ff if player is doubled &201e 29 03 AND #&03 &2020 38 SEC &2021 65 16 ADC &16 ; player_x # Bomb is aimed at centre of player &2023 f9 00 04 SBC &0400,Y ; enemies_x &2026 9d 66 05 STA &0566,X ; enemies_bomb_direction - &35 # Bomb moves towards player's position &2029 10 05 BPL &2030 ; skip_inversion &202b 49 ff EOR #&ff &202d 38 SEC &202e 69 00 ADC #&00 ; skip_inversion &2030 9d dd 05 STA &05dd,X ; enemies_bomb_x_speed - &35 &2033 a9 20 LDA #&20 &2035 9d c6 05 STA &05c6,X ; enemies_bomb_x_fraction - &35 &2038 b9 00 04 LDA &0400,Y ; enemies_x # Y = enemy, X =bomb &203b 18 CLC &203c 69 02 ADC #&02 # Bomb falls from centre of enemy &203e 9d 00 04 STA &0400,X ; enemies_x &2041 85 00 STA &00 ; sprite_x &2043 b9 49 04 LDA &0449,Y ; enemies_y &2046 29 fc AND #&fc &2048 9d 49 04 STA &0449,X ; enemies_y &204b 85 01 STA &01 ; sprite_y &204d a9 07 LDA #&07 &204f 85 07 STA &07 ; sprite_height &2051 98 TYA &2052 48 PHA ; enemy slot &2053 8a TXA &2054 48 PHA ; bomb slot &2055 20 01 0d JSR &0d01 ; calculate_screen_address # Returns X = address low, Y = address high &2058 68 PLA ; bomb slot &2059 aa TAX &205a a5 02 LDA &02 ; screen_address_low &205c 9d 24 05 STA &0524,X ; enemies_screen_address_low &205f 98 TYA &2060 9d db 04 STA &04db,X ; enemies_screen_address_high &2063 a9 08 LDA #&08 ; ENEMY_TYPE_BOMB &2065 9d af 05 STA &05af,X ; enemies_type_and_flags &2068 a9 25 LDA #&25 ; SPRITE_BOMB # Value is unused; enemy bombs plotted separately &206a 9d 92 04 STA &0492,X ; enemies_sprite &206d 20 3d 16 JSR &163d ; plot_enemy_bomb # Plot new enemy bomb &2070 68 PLA ; enemy slot &2071 a8 TAY ; consider_next_enemy &2072 c8 INY &2073 c0 35 CPY #&35 ; ENEMY_SLOT_LAST_ACTIVE + 1 &2075 90 01 BCC &2078 ; to_consider_adding_enemy_bombs_loop &2077 60 RTS ; to_consider_adding_enemy_bombs_loop &2078 4c f1 1f JMP &1ff1 ; consider_adding_enemy_bombs_loop ; unplot_text &207b a2 09 LDX #&09 ; unplot_text_loop &207d bd 04 0a LDA &0a04,X ; text_present_table &2080 30 0d BMI &208f ; consider_next_slot # Negative if no text in this slot &2082 a8 TAY &2083 8a TXA &2084 48 PHA ; tmp_x &2085 20 a2 20 JSR &20a2 ; plot_text # Unplot text &2088 68 PLA ; tmp_x &2089 aa TAX &208a a9 ff LDA #&ff &208c 9d 04 0a STA &0a04,X ; text_present_table # Set to negative to indicate no text in this slot ; consider_next_slot &208f ca DEX &2090 10 eb BPL &207d ; unplot_text_loop &2092 60 RTS ; plot_unplottable_text &2093 a2 09 LDX #&09 ; find_slot_loop &2095 bd 04 0a LDA &0a04,X ; text_present_table &2098 30 04 BMI &209e ; found_slot # Negative if no text in this slot &209a ca DEX &209b 10 f8 BPL &2095 ; find_slot_loop &209d 60 RTS ; found_slot &209e 98 TYA &209f 9d 04 0a STA &0a04,X ; text_present_table # Set to positive to indicate text present ; plot_text &20a2 b9 ce 20 LDA &20ce,Y ; text_addresses_table &20a5 85 5d STA &5d ; text_address_low &20a7 b9 cf 20 LDA &20cf,Y ; text_addresses_table + 1 &20aa 85 5e STA &5e ; text_address_high &20ac a0 00 LDY #&00 &20ae b1 5d LDA (&5d),Y ; text_address # First byte sets colour &20b0 85 83 STA &83 ; text_colour_mask &20b2 c8 INY &20b3 b1 5d LDA (&5d),Y ; text_address # Second byte sets x position &20b5 aa TAX &20b6 c8 INY &20b7 b1 5d LDA (&5d),Y ; text_address # Third byte sets y position &20b9 a8 TAY &20ba 20 62 0d JSR &0d62 ; calculate_text_screen_address &20bd a0 03 LDY #&03 ; plot_text_loop &20bf b1 5d LDA (&5d),Y ; text_address # Remaining bytes are characters &20c1 08 PHP ; top bit of text byte &20c2 29 7f AND #&7f &20c4 20 79 0d JSR &0d79 ; plot_character &20c7 28 PLP ; top bit of text byte &20c8 30 03 BMI &20cd ; leave # Top bit set ends text &20ca c8 INY &20cb d0 f2 BNE &20bf ; plot_text_loop ; leave &20cd 60 RTS ; text_addresses_table &20ce 45 2f ; &00 : &2f45 = ready_string &20d0 90 2f ; &02 : &2f90 = perfect_string &20d2 9c 2f ; &04 : &2f9c = hits_string &20d4 73 2f ; &06 : &2f73 = stage_string &20d6 7e 2f ; &08 : &2f7e = challenge_stage_string &20d8 a8 2f ; &0a : &2fa8 = bonus_string &20da c8 2f ; &0c : &2fc8 = q_string &20dc 4d 2f ; &0e : &2f4d = player_one_string &20de 5a 2f ; &10 : &2f5a = player_two_string &20e0 67 2f ; &12 : &2f67 = one_up_string &20e2 6d 2f ; &14 : &2f6d = two_up_string &20e4 08 2f ; &16 : &2f08 = press_return_or_fire_string &20e6 21 2f ; &18 : &2f21 = copyright_aardvark_string &20e8 34 2f ; &1a : &2f34 = zalagan_heroes_string &20ea cc 2f ; &1c : &2fcc = one_string &20ec d0 2f ; &1e : &2fd0 = two_string &20ee d4 2f ; &20 : &2fd4 = k_string &20f0 d8 2f ; &22 : &2fd8 = j_string &20f2 08 01 ; &24 : &0108 = temporary_string &20f4 20 01 ; &26 : &0120 = temporary_bonus_string &20f6 dc 2f ; &28 : &2fdc = game_over_string &20f8 b7 2f ; &2a : &2fb7 = special_bonus_string &20fa e2 2e ; &2c : &2ee2 = well_done_string &20fc f0 2e ; &2e : &2ef0 = please_type_your_name_string ; get_arrival_pattern_address_and_delay &20fe a9 00 LDA #&00 # Set to zero to not mirror arrival pattern by default ; set_mirror_arrival_pattern &2100 85 73 STA &73 ; mirror_arrival_pattern &2102 b9 26 21 LDA &2126,Y ; arrival_pattern_addresses_table + 1 &2105 d0 08 BNE &210f ; set_arrival_pattern_address_high &2107 b9 25 21 LDA &2125,Y ; arrival_pattern_addresses_table &210a a8 TAY &210b a9 80 LDA #&80 # Set to non-zero to mirror pattern horizontally &210d d0 f1 BNE &2100 ; set_mirror_arrival_pattern # Always branches ; set_arrival_pattern_address_high &210f 85 67 STA &67 ; arrival_pattern_address_high &2111 b9 27 21 LDA &2127,Y ; arrival_pattern_addresses_table + 2 &2114 85 63 STA &63 ; arrival_pattern_delay &2116 b9 25 21 LDA &2125,Y ; arrival_pattern_addresses_table &2119 85 66 STA &66 ; arrival_pattern_address_low &211b 60 RTS ; set_players_arrival_patterns_offset &211c a8 TAY &211d b9 87 21 LDA &2187,Y ; waves_arrival_patterns_offset_table &2120 a6 32 LDX &32 ; current_player &2122 95 74 STA &74,X ; players_arrival_patterns_offset &2124 60 RTS ; arrival_pattern_addresses_table &2125 02 00 ; &00 use mirrored pattern &02 &2127 39 01 05 ; &02 &0139 = arrival_pattern_02_data &212a 20 03 14 ; &05 &0320 = arrival_pattern_05_data &212d 05 00 ; &08 use mirrored pattern &05 &212f 34 03 14 ; &0a &0334 = arrival_pattern_0a_data &2132 48 03 14 ; &0d &0348 = arrival_pattern_0d_data &2135 0a 00 ; &10 use mirrored pattern &0a &2137 0d 00 ; &12 use mirrored pattern &0d &2139 71 07 ; &14 &0771 = arrival_pattern_14_data &213b 14 00 ; &16 use mirrored pattern &14 &213d 85 07 ; &18 &0785 = arrival_pattern_18_data &213f 18 00 ; &1a use mirrored pattern &18 &2141 94 07 ; &1c &0794 = arrival_pattern_1c_data &2143 1c 00 ; &1e use mirrored pattern &1c &2145 a7 07 ; &20 &07a7 = arrival_pattern_20_data &2147 20 00 ; &22 use mirrored pattern &20 &2149 b6 07 ; &24 &07b6 = arrival_pattern_24_data &214b 24 00 ; &26 use mirrored pattern &24 &214d c6 07 ; &28 &07c6 = arrival_pattern_28_data &214f 28 00 ; &2a use mirrored pattern &28 &2151 00 03 ; &2c &0300 = arrival_pattern_2c_data # &0380 if MOS 0.10 &2153 2c 00 ; &2e use mirrored pattern &2c &2155 da 07 ; &30 &07da = arrival_pattern_30_data &2157 30 00 ; &32 use mirrored pattern &30 ; wave_arrival_patterns_table # Top bit set for faster arrival &2159 80 82 90 8a 8a 90 02 00 ; &00 regular stage 0 &2161 80 82 05 08 02 00 ; &08 regular stage 1 &2167 80 82 8d 8a 92 90 02 00 ; &0e regular stage 2 &216f 94 96 18 1a 14 16 ; &16 challenge stage 0 &2175 9c 9e 20 22 1c 1e ; &1c challenge stage 1 &217b a4 a6 28 2a 24 26 ; &22 challenge stage 2 &2181 ac ae 30 32 2c 2e ; &28 challenge stage 3 ; waves_arrival_patterns_offset_table # First byte is offset into wave_arrival_patterns_table ; 0 1 # Second byte is enemy type for challenge stage &2187 00 ; regular stage 0 &2188 08 ; regular stage 1 &2189 0e ; regular stage 2 &218a 16 00 ; challenge stage 0, use ENEMY_TYPE_GUARD &218c 1c 02 ; challenge stage 1, use ENEMY_TYPE_DRONE &218e 22 00 ; challenge stage 2, use ENEMY_TYPE_GUARD &2190 28 02 ; challenge stage 3, use ENEMY_TYPE_DRONE ; types_to_sprites_table # First byte sets sprite ; 0 1 # Second byte sets score or new type if top bit set &2192 00 05 ; &00 ENEMY_TYPE_GUARD uses SPRITE_GUARD, scores 50 points &2194 0c 08 ; &02 ENEMY_TYPE_DRONE uses SPRITE_DRONE, scores 80 points &2196 18 86 ; &04 ENEMY_TYPE_QUEEN uses SPRITE_QUEEN, changes to ENEMY_TYPE_QUEEN_WEAK &2198 18 20 ; &06 ENEMY_TYPE_QUEEN_WEAK uses SPRITE_QUEEN, scores 200 points &219a 25 00 ; &08 ENEMY_TYPE_BOMB would use SPRITE_BOMB if not plotted separately ; title_screen &219c 20 7c 14 JSR &147c ; remove_all_enemies &219f 85 32 STA &32 ; current_player &21a1 20 e7 18 JSR &18e7 ; set_movement_and_firing_check_routine_addresses &21a4 20 72 22 JSR &2272 ; plot_or_unplot_title_screen_text ; wait_for_fire &21a7 20 b2 21 JSR &21b2 ; update_title_screen &21aa 20 e4 18 JSR &18e4 ; check_for_firing # Returns non-zero fire pressed &21ad f0 f8 BEQ &21a7 ; wait_for_fire &21af 4c 72 22 JMP &2272 ; plot_or_unplot_title_screen_text ; update_title_screen &21b2 20 4b 0e JSR &0e4b ; check_for_keyboard_or_joystick_keys # Returns not equal if K or J pressed &21b5 f0 13 BEQ &21ca ; skip_changing_keyboard_or_joystick &21b7 a0 20 LDY #&20 ; "K" &21b9 20 a2 20 JSR &20a2 ; plot_text # Plot or unplot text &21bc a0 22 LDY #&22 ; "J" &21be 20 a2 20 JSR &20a2 ; plot_text # Plot or unplot text &21c1 a5 70 LDA &70 ; keyboard_or_joystick &21c3 49 ff EOR #&ff # Positive for keyboard, negative for joystick &21c5 85 70 STA &70 ; keyboard_or_joystick &21c7 20 e7 18 JSR &18e7 ; set_movement_and_firing_check_routine_addresses ; skip_changing_keyboard_or_joystick &21ca 20 59 0e JSR &0e59 ; check_for_number_of_players_keys # Returns not equal if 1 or 2 pressed &21cd f0 10 BEQ &21df ; skip_changing_number_of_players &21cf a0 1c LDY #&1c ; "1" &21d1 20 a2 20 JSR &20a2 ; plot_text # Plot or unplot text &21d4 a0 1e LDY #&1e ; "2" &21d6 20 a2 20 JSR &20a2 ; plot_text # Plot or unplot text &21d9 a5 3c LDA &3c ; one_or_two_players &21db 49 ff EOR #&ff # Negative if two player game &21dd 85 3c STA &3c ; one_or_two_players ; skip_changing_keyboard_or_joystick ; update_background_and_tune_after_checking_for_sound_keypresses &21df 20 1e 0e JSR &0e1e ; check_for_sound_keypresses # Returns not equal if Q or S pressed &21e2 f0 0b BEQ &21ef ; skip_changing_sound_muted &21e4 a5 3b LDA &3b ; sound_muted &21e6 49 ff EOR #&ff # Negative if sound muted &21e8 85 3b STA &3b ; sound_muted &21ea a0 0c LDY #&0c ; "Q" &21ec 20 a2 20 JSR &20a2 ; plot_text # Plot or unplot text ; skip_changing_sound_muted ; update_background_and_tune &21ef 20 09 0e JSR &0e09 ; wait_for_v_sync &21f2 20 6a 0e JSR &0e6a ; consider_updating_palette &21f5 20 52 12 JSR &1252 ; update_stars &21f8 20 bf 15 JSR &15bf ; update_enemy_bombs &21fb 20 61 24 JSR &2461 ; update_tune &21fe 4c 4b 14 JMP &144b ; update_explosions ; update_game &2201 20 df 21 JSR &21df ; update_background_and_tune_after_checking_for_sound_keypresses &2204 20 a3 14 JSR &14a3 ; update_player &2207 20 97 16 JSR &1697 ; update_player_missiles_and_consider_firing &220a 20 e9 1f JSR &1fe9 ; consider_adding_enemy_bombs &220d 4c fb 13 JMP &13fb ; check_for_player_quitting ; plot_scores &2210 a9 00 LDA #&00 # Plot score for player one &2212 20 1d 22 JSR &221d ; plot_score_for_player_A &2215 20 46 22 JSR &2246 ; plot_high_score &2218 a9 01 LDA #&01 # Plot score for player two &221a dc a5 32 NOP &32a5,X ; plot_score_for_current_player #221b LDA &32 ; current_player ; plot_score_for_player_A &221d a2 0b LDX #&0b # x position for player one score &221f 48 PHA ; current player &2220 a8 TAY &2221 f0 02 BEQ &2225 ; is_player_one &2223 a2 3e LDX #&3e # x position for player two score ; is_player_one &2225 a0 7e LDY #&7e # y position for scores &2227 20 62 0d JSR &0d62 ; calculate_text_screen_address &222a a9 0f LDA #&0f ; colour 3 &222c 85 83 STA &83 ; text_colour_mask &222e 68 PLA ; current player &222f aa TAX &2230 b5 1f LDA &1f,X ; players_score &2232 48 PHA ; score low &2233 b4 21 LDY &21,X ; players_score + 2 &2235 b5 23 LDA &23,X ; players_score + 4 ; plot_score &2237 84 3e STY &3e ; number + 1 &2239 85 3f STA &3f ; number + 2 &223b 68 PLA ; score low &223c 85 3d STA &3d ; number &223e 20 02 23 JSR &2302 ; plot_five_digit_number &2241 a9 30 LDA #&30 ; "0" &2243 4c 79 0d JMP &0d79 ; plot_character ; plot_high_score &2246 a2 23 LDX #&23 &2248 a0 7e LDY #&7e &224a 20 62 0d JSR &0d62 ; calculate_text_screen_address &224d a9 3c LDA #&3c ; colour 6 &224f 85 83 STA &83 ; text_colour_mask &2251 ad fa 09 LDA &09fa ; high_scores_low &2254 48 PHA ; score low &2255 ac ec 0c LDY &0cec ; high_scores_middle &2258 ad f6 0c LDA &0cf6 ; high_scores_high &225b 4c 37 22 JMP &2237 ; plot_score ; plot_dashes # Called with Y = y position &225e a2 14 LDX #&14 &2260 20 62 0d JSR &0d62 ; calculate_text_screen_address &2263 a9 03 LDA #&03 ; colour 1 &2265 85 83 STA &83 ; text_colour_mask &2267 a2 0e LDX #&0e &2269 a9 2d LDA #&2d ; "-" ; plot_dashes_loop &226b 20 79 0d JSR &0d79 ; plot_character &226e ca DEX &226f d0 fa BNE &226b ; plot_dashes &2271 60 RTS ; plot_or_unplot_title_screen_text &2272 20 b2 21 JSR &21b2 ; update_title_screen &2275 a0 1a LDY #&1a ; "Zalagan Heroes" &2277 20 a2 20 JSR &20a2 ; plot_text &227a a0 76 LDY #&76 &227c 20 5e 22 JSR &225e ; plot_dashes # Plot top row of dashes &227f a0 6e LDY #&6e &2281 20 5e 22 JSR &225e ; plot_dashes # Plot bottom row of dashes &2284 20 92 22 JSR &2292 ; plot_high_scores &2287 a0 16 LDY #&16 ; "Press RETURN or (fire)" &2289 20 a2 20 JSR &20a2 ; plot_text &228c a0 18 LDY #&18 ; "(C) Aardvark '83" &228e 20 a2 20 JSR &20a2 ; plot_text &2291 60 RTS ; plot_high_scores &2292 a2 00 LDX #&00 ; plot_high_scores_loop &2294 86 7e STX &7e ; rank &2296 8a TXA &2297 20 f1 22 JSR &22f1 ; calculate_high_score_y_position &229a 20 62 0d JSR &0d62 ; calculate_text_screen_address &229d 20 ef 21 JSR &21ef ; update_background_and_tune &22a0 a9 03 LDA #&03 ; colour 1 &22a2 85 83 STA &83 ; text_colour_mask &22a4 a6 7e LDX &7e ; rank &22a6 bd fa 09 LDA &09fa,X ; high_scores_low &22a9 85 3d STA &3d ; number &22ab bd ec 0c LDA &0cec,X ; high_scores_middle &22ae 85 3e STA &3e ; number + 1 &22b0 bd f6 0c LDA &0cf6,X ; high_scores_high &22b3 85 3f STA &3f ; number + 2 &22b5 20 fe 22 JSR &22fe ; plot_six_digit_number &22b8 a9 30 LDA #&30 ; "0" &22ba 20 79 0d JSR &0d79 ; plot_character &22bd a9 3c LDA #&3c ; colour 6 &22bf 85 83 STA &83 ; text_colour_mask &22c1 a5 47 LDA &47 ; score_y &22c3 38 SEC &22c4 e9 04 SBC #&04 &22c6 a8 TAY &22c7 a2 03 LDX #&03 &22c9 20 62 0d JSR &0d62 ; calculate_text_screen_address &22cc a6 7e LDX &7e ; rank &22ce 8a TXA &22cf 0a ASL A &22d0 0a ASL A &22d1 0a ASL A &22d2 a8 TAY &22d3 65 7e ADC &7e ; rank &22d5 85 45 STA &45 ; tmp &22d7 98 TYA &22d8 0a ASL A &22d9 65 45 ADC &45 ; tmp &22db a8 TAY # Y = rank * &19 ; plot_high_scores_name_loop &22dc b9 00 09 LDA &0900,Y ; high_score_names &22df c9 0d CMP #&0d ; CR &22e1 f0 06 BEQ &22e9 ; consider_next_score &22e3 20 79 0d JSR &0d79 ; plot_character &22e6 c8 INY &22e7 d0 f3 BNE &22dc ; plot_high_scores_name_loop ; consider_next_score &22e9 e8 INX &22ea e0 0a CPX #&0a &22ec d0 a6 BNE &2294 ; plot_high_scores_loop &22ee 4c ef 21 JMP &21ef ; update_background_and_tune ; calculate_high_score_y_position # Called with A = rank &22f1 0a ASL A &22f2 0a ASL A &22f3 0a ASL A &22f4 49 ff EOR #&ff &22f6 69 68 ADC #&68 &22f8 85 47 STA &47 ; score_y &22fa a8 TAY &22fb a2 05 LDX #&05 &22fd 60 RTS ; plot_six_digit_number &22fe a9 f0 LDA #&f0 &2300 d0 02 BNE &2304 ; plot_five_or_six_digit_number # Always branches ; plot_five_digit_number &2302 a9 0f LDA #&0f &2304 85 44 STA &44 ; digit_nibble_mask ; plot_five_or_six_digit_number &2306 a5 3d LDA &3d ; number &2308 05 3e ORA &3e ; number + 1 &230a 05 3f ORA &3f ; number + 2 &230c f0 26 BEQ &2334 ; plot_zero &230e 8a TXA &230f 48 PHA ; tmp_x &2310 a2 02 LDX #&02 &2312 a0 00 LDY #&00 ; plot_five_or_six_digit_number_loop &2314 20 d1 23 JSR &23d1 ; get_next_digit &2317 c8 INY &2318 09 30 ORA #&30 ; "0" &231a c9 30 CMP #&30 ; "0" &231c d0 05 BNE &2323 ; not_leading_space &231e 88 DEY &231f d0 02 BNE &2323 ; not_leading_space &2321 a9 20 LDA #&20 ; " " ; not_leading_space &2323 20 79 0d JSR &0d79 ; plot_character &2326 a5 44 LDA &44 ; digit_nibble_mask &2328 49 ff EOR #&ff &232a 85 44 STA &44 ; digit_nibble_mask &232c 10 e6 BPL &2314 ; plot_five_or_six_digit_number_loop &232e ca DEX &232f 10 e3 BPL &2314 ; plot_five_or_six_digit_number_loop &2331 68 PLA ; tmp_x &2332 aa TAX &2333 60 RTS ; plot_zero &2334 a2 04 LDX #&04 &2336 a9 20 LDA #&20 ; " " &2338 24 44 BIT &44 ; digit_nibble_mask &233a 10 01 BPL &233d ; plot_leading_spaces_loop &233c e8 INX ; plot_leading_spaces_loop &233d 20 79 0d JSR &0d79 ; plot_character &2340 ca DEX &2341 d0 fa BNE &233d ; plot_leading_spaces_loop &2343 a9 30 LDA #&30 ; "0" &2345 4c 79 0d JMP &0d79 ; plot_character ; plot_hits &2348 a0 0b LDY #&0b ; copy_hits_string_loop &234a b9 9c 2f LDA &2f9c,Y ; hits_string &234d 99 08 01 STA &0108,Y ; temporary_string &2350 88 DEY &2351 10 f7 BPL &234a ; copy_hits_string_loop &2353 a5 7a LDA &7a ; hits &2355 a2 00 LDX #&00 # Poke up to two digits into string &2357 a0 12 LDY #&12 ; temporary_string + 10 &2359 4c 9a 23 JMP &239a ; poke_number_in_string_and_plot ; plot_bonus_or_perfect &235c a0 0e LDY #&0e ; copy_bonus_string_loop &235e b9 a8 2f LDA &2fa8,Y ; bonus_string &2361 99 20 01 STA &0120,Y ; temporary_bonus_string &2364 88 DEY &2365 10 f7 BPL &235e ; copy_bonus_string_loop &2367 a5 7a LDA &7a ; hits &2369 c9 40 CMP #&40 # Were all forty enemies destroyed? &236b f0 0c BEQ &2379 ; plot_perfect &236d a2 00 LDX #&00 # Poke up to two digits into string &236f a0 2b LDY #&2b ; temporary_bonus_string + 11 &2371 20 a2 23 JSR &23a2 ; poke_number_in_string &2374 a0 26 LDY #&26 ; temporary_bonus_string &2376 4c 93 20 JMP &2093 ; plot_unplottable_text ; plot_perfect &2379 a0 02 LDY #&02 ; "Perfect !" &237b 20 93 20 JSR &2093 ; plot_unplottable_text ; plot_special_bonus # Unused code &237e a0 2a LDY #&2a ; "Special Bonus!" &2380 4c 93 20 JMP &2093 ; plot_unplottable_text ; plot_stage_number &2383 a0 0a LDY #&0a &2385 b9 73 2f LDA &2f73,Y ; stage_string ; copy_stage_string_loop &2388 99 08 01 STA &0108,Y ; temporary_string &238b 88 DEY &238c 10 f7 BPL &2385 ; copy_stage_string_loop &238e a6 32 LDX &32 ; current_player &2390 b5 25 LDA &25,X ; players_stage_high &2392 85 3e STA &3e ; number + 1 &2394 b5 37 LDA &37,X ; players_stage &2396 a2 01 LDX #&01 # Poke up to four digits into string &2398 a0 0f LDY #&0f ; temporary_string + 7 ; poke_number_in_string_and_plot &239a 20 a2 23 JSR &23a2 ; poke_number_in_string &239d a0 24 LDY #&24 ; temporary_string &239f 4c 93 20 JMP &2093 ; plot_unplottable_text ; poke_number_in_string &23a2 85 3d STA &3d ; number &23a4 a9 ff LDA #&ff &23a6 85 60 STA &60 ; use_leading_spaces # Set to negative to use leading spaces &23a8 a9 f0 LDA #&f0 &23aa 85 44 STA &44 ; digit_nibble_mask ; poke_number_in_string_loop &23ac 20 d1 23 JSR &23d1 ; get_next_digit &23af f0 02 BEQ &23b3 ; is_zero &23b1 e6 60 INC &60 ; use_leading_spaces # Set to positive to stop leading spaces ; is_zero &23b3 24 60 BIT &60 ; use_leading_spaces &23b5 30 0d BMI &23c4 ; not_digit &23b7 49 30 EOR #&30 ; "0" &23b9 0a ASL A &23ba 48 PHA ; shifted byte &23bb b9 00 01 LDA &0100,Y ; temporary_string - 8 &23be 0a ASL A &23bf 68 PLA ; shifted byte &23c0 6a ROR A # Keep top bit (indicating end of string) if set &23c1 99 00 01 STA &0100,Y ; temporary_string - 8 ; not_digit &23c4 c8 INY &23c5 a5 44 LDA &44 ; digit_nibble_mask &23c7 49 ff EOR #&ff &23c9 85 44 STA &44 ; digit_nibble_mask &23cb 10 df BPL &23ac ; poke_number_in_string_loop &23cd ca DEX &23ce 10 dc BPL &23ac ; poke_number_in_string_loop &23d0 60 RTS ; get_next_digit &23d1 b5 3d LDA &3d,X ; number &23d3 25 44 AND &44 ; digit_nibble_mask &23d5 24 44 BIT &44 ; digit_nibble_mask &23d7 10 04 BPL &23dd ; not_top_nibble ; get_top_nibble &23d9 4a LSR A &23da 4a LSR A &23db 4a LSR A &23dc 4a LSR A ; not_top_nibble &23dd 09 00 ORA #&00 # Unnecessary code &23df 60 RTS ; play_sound &23e0 a5 3b LDA &3b ; sound_muted # Negative if sound muted &23e2 05 79 ORA &79 ; suppress_sounds # Negative if sounds temporarily suppressed &23e4 30 4b BMI &2431 ; leave &23e6 a9 07 LDA #&07 ; Generate a sound &23e8 dc a9 08 NOP &08a9,X ; define_envelope #23e9 a9 08 LDA #&08 ; Define a sound envelope &23eb 85 08 STA &08 ; osword_type &23ed 8a TXA &23ee 48 PHA ; tmp_x &23ef 98 TYA &23f0 48 PHA ; tmp_y &23f1 18 CLC &23f2 69 5e ADC #&5e ; &2e5e = sound_and_envelope_data &23f4 aa TAX &23f5 a9 00 LDA #&00 &23f7 69 2e ADC #&2e &23f9 a8 TAY &23fa a5 08 LDA &08 ; osword_type &23fc d0 29 BNE &2427 ; to_osword # Always branches ; play_tune_sound # Called with X = channel, A = byte of tune data &23fe c9 ff CMP #&ff # &ff indicates end of data for channel &2400 f0 2d BEQ &242f ; end_of_channel_data &2402 48 PHA ; tune data byte &2403 29 03 AND #&03 # Bottom two bits set duration &2405 69 01 ADC #&01 &2407 95 40 STA &40,X ; tune_channel_cooldowns - 1 &2409 68 PLA ; tune data byte &240a 29 fc AND #&fc # Top six bits set pitch &240c 8d 04 01 STA &0104 ; tune_sound (pitch) &240f 8a TXA &2410 48 PHA ; tmp_x &2411 09 10 ORA #&10 &2413 8d 00 01 STA &0100 ; tune_sound (channel) &2416 98 TYA &2417 48 PHA ; tmp_y &2418 a4 8d LDY &8d ; tune_tempo ; scale_tempo_loop &241a 16 40 ASL &40,X ; tune_channel_cooldowns - 1 &241c 88 DEY &241d d0 fb BNE &241a ; scale_tempo_loop &241f a9 07 LDA #&07 ; Generate a sound &2421 a6 3b LDX &3b ; sound_muted # Negative if sound muted &2423 d0 05 BNE &242a ; skip_sound &2425 a0 01 LDY #&01 ; &0100 = tune_sound ; to_osword &2427 20 f1 ff JSR &fff1 ; OSWORD ; skip_sound &242a 68 PLA ; tmp_y &242b a8 TAY &242c 68 PLA ; tmp_x &242d aa TAX &242e 60 RTS ; end_of_channel_data &242f 95 40 STA &40,X ; tune_channel_cooldowns - 1 # Set to negative to indicate channel has finished ; leave &2431 60 RTS ; play_tune &2432 24 3b BIT &3b ; sound_muted # Negative if sound muted &2434 30 5f BMI &2495 ; leave &2436 b9 a0 24 LDA &24a0,Y ; tune_variables_table &2439 85 6a STA &6a ; tune_address_low &243b b9 a1 24 LDA &24a1,Y ; tune_variables_table + 1 &243e 85 6b STA &6b ; tune_address_high &2440 b9 a2 24 LDA &24a2,Y ; tune_variables_table + 2 &2443 85 8d STA &8d ; tune_tempo &2445 a0 2a LDY #&2a ; envelope_4 &2447 20 e9 23 JSR &23e9 ; define_envelope &244a a0 02 LDY #&02 ; initialise_channels_loop &244c b1 6a LDA (&6a),Y ; tune_address # Get first three bytes of tune data &244e 99 6d 00 STA &006d,Y ; tune_channel_offsets # for offsets for channel data &2451 a9 00 LDA #&00 &2453 99 41 00 STA &0041,Y ; tune_channel_cooldowns # Set to zero to update channel immediately &2456 88 DEY &2457 10 f3 BPL &244c ; initialise_channels_loop &2459 a9 80 LDA #&80 ; TUNE_PLAYING &245b 85 79 STA &79 ; suppress_sounds # Set to negative to suppress sounds &245d a5 52 LDA &52 ; previous_frame_counter &245f 85 c8 STA &c8 ; tune_frame_counter ; update_tune &2461 a5 79 LDA &79 ; suppress_sounds # Negative if sounds temporarily suppressed &2463 10 30 BPL &2495 ; leave &2465 c9 80 CMP #&80 ; TUNE_PLAYING &2467 d0 2d BNE &2496 ; tune_not_playing ; play_tune_loop &2469 a2 03 LDX #&03 ; play_tune_channel_loop # For each of three channels, &246b b5 40 LDA &40,X ; tune_channel_cooldowns - 1 &246d d0 09 BNE &2478 ; skip_channel &246f b4 6c LDY &6c,X ; tune_channel_offsets - 1 &2471 b1 6a LDA (&6a),Y ; tune_address_low # Get a byte of tune data for pitch and duration &2473 20 fe 23 JSR &23fe ; play_tune_sound &2476 f6 6c INC &6c,X ; tune_channel_offsets - 1 ; skip_channel &2478 d6 40 DEC &40,X ; tune_channel_cooldowns - 1 &247a 10 02 BPL &247e ; skip_floor &247c f6 40 INC &40,X ; tune_channel_cooldowns - 1 # Keep positive to indicate channel is still playing ; skip_floor &247e ca DEX &247f d0 ea BNE &246b ; play_tune_channel_loop &2481 a5 c8 LDA &c8 ; tune_frame_counter &2483 e6 c8 INC &c8 ; tune_frame_counter &2485 c5 52 CMP &52 ; previous_frame_counter &2487 30 e0 BMI &2469 ; play_tune_loop &2489 a5 41 LDA &41 ; tune_channel_cooldowns &248b 25 42 AND &42 ; tune_channel_cooldowns + 1 &248d 25 43 AND &43 ; tune_channel_cooldowns + 2 &248f 10 04 BPL &2495 ; leave # Positive if any channel is still playing &2491 a9 e7 LDA #&e7 &2493 85 79 STA &79 ; suppress_sounds # Suppress sounds for 25 frames after end of tune ; leave &2495 60 RTS ; tune_not_playing &2496 e6 79 INC &79 ; suppress_sounds &2498 d0 fb BNE &2495 ; leave # Zero when sounds no longer suppressed &249a 20 9b 14 JSR &149b ; flush_buffers &249d 4c 87 14 JMP &1487 ; use_game_envelopes ; tune_variables_table ; addr t &24a0 80 08 02 ; &00 : &0880 = ready_tune_data, tempo 2 # &03a0 if MOS 0.10 &24a3 a4 0a 03 ; &03 ; &0aa4 = doubling_tune_data, tempo 3 ; plot_lives &24a6 a5 71 LDA &71 ; previous_lives &24a8 20 b1 24 JSR &24b1 ; plot_or_unplot_lives # Unplot lives &24ab a6 32 LDX &32 ; current_player &24ad b5 35 LDA &35,X ; players_lives &24af 85 71 STA &71 ; previous_lives ; plot_or_unplot_lives # Plot lives &24b1 85 45 STA &45 ; count &24b3 c9 02 CMP #&02 &24b5 90 14 BCC &24cb ; leave # Leave if last life &24b7 c6 45 DEC &45 ; count &24b9 a2 00 LDX #&00 &24bb a0 00 LDY #&00 ; plot_or_unplot_lives_loop &24bd a9 24 LDA #&24 ; SPRITE_LIFE &24bf 20 af 0e JSR &0eaf ; plot_sprite_at_X_Y &24c2 8a TXA &24c3 18 CLC &24c4 69 06 ADC #&06 &24c6 aa TAX &24c7 c6 45 DEC &45 ; count &24c9 d0 f2 BNE &24bd ; plot_or_unplot_lives_loop ; leave &24cb 60 RTS ; check_for_high_score &24cc 20 05 14 JSR &1405 ; remove_enemies_player_missiles_and_text &24cf 20 7b 20 JSR &207b ; unplot_text # Unnecessary; already called at &1439 &24d2 20 10 22 JSR &2210 ; plot_scores # Unplot scores &24d5 a0 09 LDY #&09 ; check_for_high_score_loop # For each rank, in ascending order &24d7 a6 32 LDX &32 ; current_player &24d9 b5 1f LDA &1f,X ; players_score &24db d9 fa 09 CMP &09fa,Y ; high_scores_low &24de b5 21 LDA &21,X ; players_score + 2 &24e0 f9 ec 0c SBC &0cec,Y ; high_scores_middle &24e3 b5 23 LDA &23,X ; players_score + 4 &24e5 f9 f6 0c SBC &0cf6,Y ; high_scores_high &24e8 90 4f BCC &2539 ; high_score_is_better # Is the player's score better than the ranked score? &24ea 84 08 STY &08 ; rank # If so, move ranked score down a rank &24ec 98 TYA &24ed 0a ASL A &24ee 65 08 ADC &08 ; rank &24f0 0a ASL A &24f1 0a ASL A &24f2 0a ASL A &24f3 65 08 ADC &08 ; rank &24f5 a8 TAY &24f6 84 7d STY &7d ; name_offset &24f8 c0 e1 CPY #&e1 ; 9 * &19 &24fa b0 22 BCS &251e ; skip_moving_score # Discard bottommost score &24fc a2 19 LDX #&19 ; move_name_loop # Move name down a rank &24fe b9 00 09 LDA &0900,Y ; high_score_names &2501 99 19 09 STA &0919,Y ; high_score_names + &19 &2504 c8 INY &2505 ca DEX &2506 d0 f6 BNE &24fe ; move_name_loop &2508 a4 08 LDY &08 ; rank &250a a6 32 LDX &32 ; current_player &250c b9 fa 09 LDA &09fa,Y ; high_scores_low # Move score down a rank &250f 99 fb 09 STA &09fb,Y ; high_scores_low + 1 &2512 b9 ec 0c LDA &0cec,Y ; high_scores_middle &2515 99 ed 0c STA &0ced,Y ; high_scores_middle + 1 &2518 b9 f6 0c LDA &0cf6,Y ; high_scores_high &251b 99 f7 0c STA &0cf7,Y ; high_scores_high + 1 ; skip_moving_score &251e a9 0d LDA #&0d ; CR &2520 a4 7d LDY &7d ; name_offset &2522 99 00 09 STA &0900,Y ; high_score_names &2525 a4 08 LDY &08 ; rank &2527 b5 1f LDA &1f,X ; players_score &2529 99 fa 09 STA &09fa,Y ; high_scores_low &252c b5 21 LDA &21,X ; players_score + 2 &252e 99 ec 0c STA &0cec,Y ; high_scores_middle &2531 b5 23 LDA &23,X ; players_score + 4 &2533 99 f6 0c STA &0cf6,Y ; high_scores_high &2536 88 DEY &2537 10 9e BPL &24d7 ; check_for_high_score_loop ; high_score_is_better &2539 c8 INY &253a c0 0a CPY #&0a &253c 08 PHP ; ranked tenth &253d 98 TYA &253e 48 PHA ; player rank &253f 20 10 22 JSR &2210 ; plot_scores # Plot scores &2542 68 PLA ; player rank &2543 28 PLP ; ranked tenth &2544 d0 01 BNE &2547 ; new_high_score &2546 60 RTS ; new_high_score &2547 48 PHA ; player rank &2548 20 92 22 JSR &2292 ; plot_high_scores &254b 68 PLA ; player rank &254c 20 f1 22 JSR &22f1 ; calculate_high_score_y_position &254f 98 TYA # Y = player rank &2550 38 SEC &2551 e9 04 SBC #&04 &2553 a8 TAY &2554 84 66 STY &66 ; new_name_y_position &2556 20 ef 25 JSR &25ef ; well_done_please_type_your_name # Plot text &2559 a9 3c LDA #&3c ; colour 6 &255b 85 83 STA &83 ; text_colour_mask &255d a9 7e LDA #&7e : Acknowledge ESCAPE condition &255f 20 f4 ff JSR &fff4 ; OSBYTE &2562 a2 00 LDX #&00 ; all buffers &2564 a9 0f LDA #&0f ; Flush all buffers &2566 20 f4 ff JSR &fff4 ; OSBYTE &2569 a4 7d LDY &7d ; name_offset &256b a2 00 LDX #&00 ; enter_name_loop &256d 86 7e STX &7e ; tmp_x &256f 84 7f STY &7f ; tmp_y &2571 20 ef 21 JSR &21ef ; update_background_and_tune &2574 a0 00 LDY #&00 &2576 a2 00 LDX #&00 &2578 a9 81 LDA #&81 ; Wait for input character &257a 20 f4 ff JSR &fff4 ; OSBYTE # Returns X = character, carry clear if key pressed &257d c0 1b CPY #&1b ; ESCAPE &257f 08 PHP ; escape pressed &2580 8a TXA &2581 a6 7e LDX &7e ; tmp_x &2583 a4 7f LDY &7f ; tmp_y &2585 28 PLP ; escape pressed &2586 f0 22 BEQ &25aa ; escape_pressed &2588 b0 e3 BCS &256d ; enter_name_loop &258a c9 7f CMP #&7f ; DELETE &258c f0 32 BEQ &25c0 ; delete_pressed &258e b0 dd BCS &256d ; enter_name_loop &2590 c9 15 CMP #&15 ; ctrl-U &2592 f0 23 BEQ &25b7 ; clear_line &2594 c9 0d CMP #&0d ; CR &2596 f0 48 BEQ &25e0 ; enter_pressed &2598 c9 20 CMP #&20 ; " " &259a 90 d1 BCC &256d ; enter_name_loop &259c e0 18 CPX #&18 # Don't accept input beyond end of line &259e b0 cd BCS &256d ; enter_name_loop &25a0 99 00 09 STA &0900,Y ; high_score_names &25a3 20 79 0d JSR &0d79 ; plot_character &25a6 c8 INY &25a7 e8 INX &25a8 d0 c3 BNE &256d ; enter_name_loop ; escape_pressed &25aa 8a TXA &25ab 48 PHA ; tmp_x &25ac 98 TYA &25ad 48 PHA ; tmp_y &25ae a9 7e LDA #&7e ; Acknowledge ESCAPE condition &25b0 20 f4 ff JSR &fff4 ; OSBYTE &25b3 68 PLA ; tmp_y &25b4 a8 TAY &25b5 68 PLA ; tmp_x &25b6 aa TAX ; clear_line ; clear_line_loop &25b7 8a TXA &25b8 f0 b3 BEQ &256d ; enter_name_loop &25ba 20 c9 25 JSR &25c9 ; remove_character_from_name &25bd 4c b7 25 JMP &25b7 ; clear_line_loop ; delete_pressed &25c0 8a TXA &25c1 f0 aa BEQ &256d ; enter_name_loop &25c3 20 c9 25 JSR &25c9 ; remove_character_from_name &25c6 4c 6d 25 JMP &256d ; enter_name_loop ; remove_character_from_name &25c9 ca DEX &25ca 88 DEY &25cb 20 d4 25 JSR &25d4 ; move_back_a_character &25ce b9 00 09 LDA &0900,Y ; high_score_names &25d1 20 79 0d JSR &0d79 ; plot_character # Unplot character ; move_back_a_character &25d4 a5 81 LDA &81 ; text_screen_address_low &25d6 38 SEC &25d7 e9 18 SBC #&18 # Move left six pixels &25d9 85 81 STA &81 ; text_screen_address_low &25db b0 02 BCS &25df ; skip_page &25dd c6 82 DEC &82 ; text_screen_address_high ; skip_page &25df 60 RTS ; enter_pressed &25e0 a9 0d LDA #&0d ; CR &25e2 99 00 09 STA &0900,Y ; high_score_names &25e5 20 92 22 JSR &2292 ; plot_high_scores &25e8 a2 00 LDX #&00 &25ea a9 0b LDA #&0b ; Set auto-repeat delay &25ec 20 f4 ff JSR &fff4 ; OSBYTE ; well_done_please_type_your_name # Unplot text if not called separately &25ef a0 2c LDY #&2c ; "Well Done!!" &25f1 20 a2 20 JSR &20a2 ; plot_text &25f4 20 b2 21 JSR &21b2 ; update_title_screen &25f7 a0 2e LDY #&2e ; "Please type your name" &25f9 20 a2 20 JSR &20a2 ; plot_text &25fc a2 03 LDX #&03 &25fe a4 66 LDY &66 ; new_name_y_position &2600 20 62 0d JSR &0d62 ; calculate_text_screen_address &2603 a0 3f LDY #&3f &2605 a6 82 LDX &82 ; text_screen_address_high &2607 e8 INX &2608 e8 INX &2609 20 11 26 JSR &2611 ; highlight_text # Highlight +&200 - +&23f &260c ca DEX &260d 20 11 26 JSR &2611 ; highlight_text # Highlight +&100 - +&1ff &2610 ca DEX ; highlight_text # Highlight +&000 - +&0ff &2611 a5 81 LDA &81 ; text_screen_address_low &2613 85 02 STA &02 ; screen_address_low &2615 86 03 STX &03 ; screen_address_high ; highlight_text_loop &2617 b1 02 LDA (&02),Y ; screen_address &2619 49 30 EOR #&30 ; colour 4 &261b 91 02 STA (&02),Y ; screen_address &261d 88 DEY &261e c0 ff CPY #&ff &2620 d0 f5 BNE &2617 ; highlight_text_loop &2622 60 RTS ; calculate_sprite_address_and_sizes # Called with Y = sprite &2623 98 TYA &2624 48 PHA ; tmp_y &2625 b9 52 27 LDA &2752,Y ; sprite_sizes_offsets &2628 48 PHA ; sprite sizes offset &2629 29 fc AND #&fc # Top six bits set sprite &262b 4a LSR A &262c a8 TAY &262d b9 7c 27 LDA &277c,Y ; sprite_sizes + 1 (address offset low) &2630 69 52 ADC #&52 ; &2752 = sprite_data &2632 85 04 STA &04 ; sprite_address_low &2634 b9 7d 27 LDA &277d,Y ; sprite_sizes + 2 (address offset high) &2637 69 27 ADC #&27 &2639 85 05 STA &05 ; sprite_address_high &263b b9 7e 27 LDA &277e,Y ; sprite_sizes + 3 (width) &263e 85 06 STA &06 ; sprite_width &2640 b9 7f 27 LDA &277f,Y ; sprite_sizes + 4 (height) &2643 85 07 STA &07 ; sprite_height &2645 b9 7b 27 LDA &277b,Y ; sprite_sizes + 0 (x offset) &2648 65 00 ADC &00 ; sprite_x &264a 85 00 STA &00 ; sprite_x &264c b9 80 27 LDA &2780,Y ; sprite_sizes + 5 (y offset) &264f 18 CLC &2650 65 01 ADC &01 ; sprite_y &2652 85 01 STA &01 ; sprite_y &2654 68 PLA ; sprite sizes offset &2655 29 03 AND #&03 # Lowest two bits set flipping &2657 0a ASL A &2658 0a ASL A &2659 85 1c STA &1c ; sprite_flip &265b 29 08 AND #&08 ; FLIP_HORIZONTALLY &265d f0 09 BEQ &2668 ; not_flipped_horizontally &265f a5 00 LDA &00 ; sprite_x &2661 65 06 ADC &06 ; sprite_width &2663 38 SEC &2664 e9 01 SBC #&01 &2666 85 00 STA &00 ; sprite_x ; not_flipped_norizontally &2668 68 PLA ; tmp_y &2669 a8 TAY &266a 60 RTS ; plot_part_of_doubling_wave &266b a6 bc LDX &bc ; doubling_wave_state &266d 86 be STX &be ; wave_size &266f 8a TXA &2670 29 03 AND #&03 &2672 a8 TAY &2673 b9 32 27 LDA &2732,Y ; wave_pixel_values &2676 85 44 STA &44 ; wave_pixel_value &2678 a5 c0 LDA &c0 ; doubling_enemy_y &267a 4a LSR A &267b 38 SEC &267c e5 bc SBC &bc ; doubling_wave_state &267e 0a ASL A &267f 0a ASL A &2680 85 63 STA &63 ; wave_y &2682 a9 00 LDA #&00 &2684 85 bd STA &bd ; width ; multiplication_loop &2686 65 bc ADC &bc ; doubling_wave_state &2688 ca DEX &2689 d0 fb BNE &2686 ; multiplication_loop &268b 85 bf STA &bf ; fraction &268d 85 c2 STA &c2 ; total &268f a5 c1 LDA &c1 ; doubling_enemy_x &2691 85 61 STA &61 ; wave_right_x &2693 85 62 STA &62 ; wave_left_x &2695 20 36 27 JSR &2736 ; plot_doubling_wave_pixel_pair ; plot_part_of_doubling_wave_loop &2698 a5 bf LDA &bf ; fraction &269a 38 SEC &269b 65 bd ADC &bd ; width &269d 65 bd ADC &bd ; width &269f e6 bd INC &bd ; width &26a1 e6 62 INC &62 ; wave_left_x &26a3 c6 61 DEC &61 ; wave_right_x &26a5 b0 04 BCS &26ab ; move_down &26a7 c5 c2 CMP &c2 ; total &26a9 90 09 BCC &26b4 ; skip_moving_down ; move_down &26ab 18 CLC &26ac e5 be SBC &be ; wave_size &26ae e5 be SBC &be ; wave_size &26b0 c6 be DEC &be ; wave_size &26b2 e6 63 INC &63 ; wave_y ; skip_moving_down &26b4 85 bf STA &bf &26b6 a5 61 LDA &61 ; wave_right_x &26b8 20 36 27 JSR &2736 ; plot_doubling_wave_pixel_pair &26bb a5 62 LDA &62 ; wave_left_x &26bd 20 36 27 JSR &2736 ; plot_doubling_wave_pixel_pair &26c0 a5 bd LDA &bd ; width &26c2 c5 be CMP &be ; wave_size &26c4 90 d2 BCC &2698 ; plot_part_of_doubling_wave_loop &26c6 60 RTS ; continue_emitting_doubling_wave &26c7 8a TXA &26c8 48 PHA ; tmp_x &26c9 20 d3 26 JSR &26d3 ; update_doubling_wave # Returns carry set if no doubling wave present &26cc 68 PLA ; tmp_x &26cd aa TAX &26ce 90 19 BCC &26e9 ; leave &26d0 4c df 1e JMP &1edf ; increment_enemy_action_and_plot_enemy ; update_doubling_wave &26d3 24 c3 BIT &c3 ; doubling_wave_present # Negative if doubling wave present &26d5 10 23 BPL &26fa ; leave_with_carry_set # Leave with carry set if no doubling wave present &26d7 a5 c4 LDA &c4 ; doubling_wave_reducing # Non-zero if doubling wave reducing &26d9 d0 15 BNE &26f0 ; reduce_doubling_wave &26db e6 bc INC &bc ; doubling_wave_state &26dd 30 0b BMI &26ea ; start_reducing_doubling_wave &26df a5 bc LDA &bc ; doubling_wave_state &26e1 c9 10 CMP #&10 ; FULL_DOUBLING_WAVE &26e3 b0 03 BCS &26e8 ; skip_increasing_doubling_wave ; to_plot_part_of_doubling_wave &26e5 20 6b 26 JSR &266b ; plot_part_of_doubling_wave # Plot part of doubling wave ; skip_increasing_doubling_wave &26e8 18 CLC # Leave with carry clear to indicate wave present ; leave &26e9 60 RTS ; start_reducing_doubling_wave &26ea c6 c4 DEC &c4 ; doubling_wave_reducing # Set to negative to indicate doubling wave reducing &26ec a9 10 LDA #&10 ; FULL_DOUBLING_WAVE &26ee 85 bc STA &bc ; doubling_wave_state ; reduce_doubling_wave &26f0 c6 bc DEC &bc ; doubling_wave_state &26f2 a5 bc LDA &bc ; doubling_wave_state &26f4 c9 03 CMP #&03 &26f6 b0 ed BCS &26e5 ; to_plot_part_of_doubling_wave # Unplot part of doubling wave &26f8 e6 c3 INC &c3 ; doubling_wave_present # Set to positive to indicate no doubling wave present ; leave_with_carry_set &26fa 38 SEC # Leave with carry set to indicate no wave present &26fb 60 RTS ; remove_doubling_wave &26fc 20 d3 26 JSR &26d3 ; update_doubling_wave # Returns carry set if no doubling wave present &26ff 90 fb BCC &26fc ; remove_doubling_wave &2701 60 RTS ; set_queen_starting_doubling_attack &2702 a9 18 LDA #&18 ; ACTION_DOUBLING_ATTACK &2704 9d 66 05 STA &0566,X ; enemies_action - &28 &2707 20 cc 0e JSR &0ecc ; unplot_enemy &270a 86 c5 STX &c5 ; doubling_attack_queen # Set to positive to indicate queen doubling attacking &270c 4c ac 1e JMP &1eac ; update_active_enemy_after_incrementing_enemy_action ; start_emitting_doubling_wave &270f a0 ff LDY #&ff &2711 84 c3 STY &c3 ; doubling_wave_present # Set to negative to indicate doubling wave present &2713 c8 INY ; 0 &2714 84 c4 STY &c4 ; doubling_wave_reducing # Set to zero to indicate doubling wave not reducing &2716 c8 INY &2717 c8 INY ; 2 &2718 84 bc STY &bc ; doubling_wave_state &271a bd 00 04 LDA &0400,X ; enemies_x &271d 38 SEC &271e e9 06 SBC #&06 &2720 85 c6 STA &c6 ; minimum_x_for_doubling &2722 69 07 ADC #&07 &2724 85 c1 STA &c1 ; doubling_enemy_x &2726 69 04 ADC #&04 &2728 85 c7 STA &c7 ; maximum_x_for_doubling &272a bc 49 04 LDY &0449,X ; enemies_y &272d 84 c0 STY &c0 ; doubling_enemy_y &272f 4c df 1e JMP &1edf ; increment_enemy_action_and_plot_enemy ; wave_pixel_values &2732 30 ; colour 4 &2733 fc ; colour 14 &2734 3c ; colour 6 &2735 ff ; colour 15 ; plot_doubling_wave_pixel_pair &2736 85 00 STA &00 ; sprite_x &2738 a5 63 LDA &63 ; wave_y &273a 4a LSR A &273b 08 PHP ; wave y oddness &273c 85 01 STA &01 ; sprite_y &273e a9 01 LDA #&01 &2740 85 07 STA &07 ; sprite_height &2742 20 01 0d JSR &0d01 ; calculate_screen_address &2745 28 PLP ; wave y oddness &2746 a0 00 LDY #&00 &2748 b0 01 BCS &274b ; not_odd_y &274a c8 INY ; not_odd_y &274b b1 02 LDA (&02),Y ; screen_address &274d 45 44 EOR &44 ; wave_pixel_value &274f 91 02 STA (&02),Y ; screen_address &2751 60 RTS # &4411 - &4510 is moved to &0400 - &04ff at &47c2 # &4511 - &4521 is moved to &0500 - &0510 at &47cd ; initialise_screen &0400 a9 16 LDA #&16 # Change to MODE 2 &0402 20 ee ff JSR &ffee ; OSWRCH &0405 a9 02 LDA #&02 &0407 20 ee ff JSR &ffee ; OSWRCH &040a a9 0a LDA #&0a # R10: Cursor start register &040c 8d 00 fe STA &fe00 ; video register number &040f a9 20 LDA #&20 # Disable cursor &0411 8d 01 fe STA &fe01 ; video register value &0414 a2 00 LDX #&00 ; randomise_rnd_loop &0416 20 97 0e JSR &0e97 ; rnd &0419 ca DEX &041a d0 fa BNE &0416 ; randomise_rnd_loop &041c 20 cd 04 JSR &04cd ; initialise_stars &041f a9 03 LDA #&03 ; colour 1 &0421 85 83 STA &83 ; text_colour_mask &0423 a2 00 LDX #&00 &0425 a0 7e LDY #&7e &0427 20 62 0d JSR &0d62 ; calculate_text_screen_address &042a a9 31 LDA #&31 ; "1" # Plot "1UP" &042c 20 79 0d JSR &0d79 ; plot_character &042f 20 c3 04 JSR &04c3 ; plot_up &0432 a2 1d LDX #&1d &0434 a0 7e LDY #&7e &0436 20 62 0d JSR &0d62 ; calculate_text_screen_address &0439 a9 48 LDA #&48 ; "H" # Plot "Hi" &043b 20 79 0d JSR &0d79 ; plot_character &043e a9 69 LDA #&69 ; "i" &0440 20 79 0d JSR &0d79 ; plot_character &0443 a2 36 LDX #&36 &0445 a0 7e LDY #&7e &0447 20 62 0d JSR &0d62 ; calculate_text_screen_address &044a a9 32 LDA #&32 ; "2" # Plot "2UP" &044c 20 79 0d JSR &0d79 ; plot_character &044f 20 c3 04 JSR &04c3 ; plot_up &0452 a0 1c LDY #&1c ; "1" &0454 20 a2 20 JSR &20a2 ; plot_text &0457 a0 20 LDY #&20 ; "2" &0459 20 a2 20 JSR &20a2 ; plot_text &045c a2 01 LDX #&01 ; initialise_player_missiles_state_loop &045e a9 00 LDA #&00 &0460 95 b4 STA &b4,X ; player_missiles_state # Set to zero to indicate no missile present &0462 ca DEX &0463 10 f9 BPL &045e ; initialise_player_missiles_state_loop &0465 a2 09 LDX #&09 ; initialise_text_present_table_loop &0467 a9 ff LDA #&ff &0469 9d 04 0a STA &0a04,X ; text_present_table # Set to negative to indicate no text present &046c ca DEX &046d 10 f8 BPL &0467 ; initialise_text_present_table_loop &046f a2 05 LDX #&05 ; initialise_players_score_loop &0471 a9 00 LDA #&00 # Zero both scores &0473 95 1f STA &1f,X ; players_score &0475 ca DEX &0476 10 f9 BPL &0471 ; initialise_players_score_loop &0478 20 10 22 JSR &2210 ; plot_scores # Plot scores &047b a0 60 LDY #&60 ; move_0511_to_0570_loop # Move &0511 - &0570 to &0320 - &037f &047d b9 10 05 LDA &0510,Y &0480 99 1f 03 STA &031f,Y &0483 88 DEY &0484 d0 f7 BNE &047d ; move_0511_to_0570_loop &0486 24 8c BIT &8c ; mos_version_flag # Positive if MOS 0.10 &0488 30 12 BMI &049c ; not_mos_0.10 &048a a0 20 LDY #&20 ; move_0591_to_05b0_to_0380_loop # Move &0591 - &05b0 to &0380 - &039f if MOS 0.10 (arrival_pattern_2c_data) &048c b9 90 05 LDA &0590,Y &048f 99 7f 03 STA &037f,Y &0492 88 DEY &0493 d0 f7 BNE &048c ; move_0591_to_05b0_to_0380_loop &0495 a9 80 LDA #&80 &0497 8d 51 21 STA &2151 ; arrival_pattern_addresses_table + &2c # Set address of arrival_pattern_2c_data to &0380 &049a 30 0b BMI &04a7 ; initialise_tune_sound # Always branches ; not_mos_0.10 &049c a0 20 LDY #&20 ; move_0591_to_05b0_to_0300_loop # Move &0591 - &05b0 to &0300 - &031f if not MOS 0.10 &049e b9 90 05 LDA &0590,Y &04a1 99 ff 02 STA &02ff,Y &04a4 88 DEY &04a5 d0 f7 BNE &049e ; move_0591_to_05b0_to_0300_loop ; initialise_tune_sound &04a7 a9 00 LDA #&00 &04a9 8d 01 01 STA &0101 ; tune_sound + 1 (channel high) &04ac 8d 03 01 STA &0103 ; tune_sound + 3 (volume high) &04af 8d 05 01 STA &0105 ; tune_sound + 5 (pitch high) &04b2 8d 07 01 STA &0107 ; tune_sound + 7 (duration_high &04b5 a9 01 LDA #&01 &04b7 8d 02 01 STA &0102 ; tune_sound + 2 (volume) &04ba a9 14 LDA #&14 &04bc 8d 06 01 STA &0106 ; tune_sound + 6 (duration) &04bf 58 CLI &04c0 4c 41 13 JMP &1341 ; title_screen_and_play_game_loop ; plot_up &04c3 a9 55 LDA #&55 ; "U" &04c5 20 79 0d JSR &0d79 ; plot_character &04c8 a9 50 LDA #&50 ; "P" &04ca 4c 79 0d JMP &0d79 ; plot_character ; initialise_stars &04cd a9 01 LDA #&01 &04cf 85 02 STA &02 ; screen_address_low &04d1 a9 30 LDA #&30 &04d3 85 03 STA &03 ; screen_address_high &04d5 a0 00 LDY #&00 &04d7 a2 31 LDX #&31 ; STARS_LAST ; initialise_stars_loop &04d9 a5 02 LDA &02 ; screen_address_low &04db 9d 0e 0a STA &0a0e,X ; stars_screen_address_low &04de 29 2a AND #&2a ; W0 # Limit star to left pixel of pair, non-flashing colours &04e0 9d 72 0a STA &0a72,X ; stars_pixel_value &04e3 51 02 EOR (&02),Y ; screen_address &04e5 91 02 STA (&02),Y ; screen_address &04e7 a5 03 LDA &03 ; screen_address_high &04e9 9d 40 0a STA &0a40,X ; stars_screen_address_high &04ec 18 CLC &04ed a5 02 LDA &02 ; screen_address_low &04ef 69 19 ADC #&19 &04f1 85 02 STA &02 ; screen_address_low &04f3 a5 03 LDA &03 ; screen_address_high &04f5 69 01 ADC #&01 &04f7 85 03 STA &03 ; screen_address_high &04f9 20 97 0e JSR &0e97 ; rnd &04fc 18 CLC &04fd 65 02 ADC &02 ; screen_address_low &04ff 85 02 STA &02 ; screen_address_low &0501 90 0a BCC &050d ; skip_page_or_wraparound &0503 e6 03 INC &03 ; screen_address_high &0505 10 06 BPL &050d ; skip_page_or_wraparound &0507 a5 03 LDA &03 ; screen_address_high &0509 e9 50 SBC #&50 &050b 85 03 STA &03 ; screen_address_high ; skip_page_or_wraparound &050d ca DEX &050e 10 c9 BPL &04d9 ; initialise_stars_loop &0510 60 RTS ; entry_point &4522 78 SEI &4523 a9 40 LDA #&40 ; RTI &4525 8d 00 0d STA &0d00 ; nmi_handler &4528 d8 CLD &4529 a2 ff LDX #&ff &452b 9a TXS &452c a2 0a LDX #&0a ; check_protected_loop &452e b5 01 LDA &01,X ; protected &4530 dd 10 48 CMP &4810,X ; protected_string &4533 f0 03 BEQ &4538 ; check_next_byte &4535 4c f5 46 JMP &46f5 ; software_protected_screen # Fail if &01 - &0b is not as initialised in loader ; check_next_byte &4538 ca DEX &4539 10 f3 BPL &452e ; check_protected_loop &453b a9 07 LDA #&07 &453d 85 1e STA &1e ; palette_state &453f 85 49 STA &49 ; seven &4541 a9 01 LDA #&01 &4543 85 1d STA &1d ; palette_change_cooldown # Set to one to update palette on next update &4545 a2 10 LDX #&10 &4547 8a TXA ; wipe_0b00_to_0b10_loop # Wipe &0b00 - &0b10 with &10 &4548 9d 00 0b STA &0b00,X ; os_function_key_offsets # i.e. reset function keys &454b ca DEX &454c 10 fa BPL &4548 ; wipe_0b00_to_0b10_loop &454e a9 00 LDA #&00 &4550 85 3b STA &3b ; sound_muted # Set to positive to permit sound by default &4552 85 79 STA &79 ; suppress_sounds # Set to positive to permit sound by default &4554 85 3c STA &3c ; one_or_two_players # Set to positive for one player game by default &4556 85 32 STA &32 ; current_player # Set to zero for player one &4558 85 70 STA &70 ; keyboard_or_joystick # Set to positive to use keyboard by default &455a 85 71 STA &71 ; previous_lives &455c a0 fa LDY #&fa ; move_5b6d_to_5c66_loop # Move &5b6d - &5c66 to &0900 - &09f9 &455e b9 6c 5b LDA &5b6c,Y &4561 99 ff 08 STA &08ff,Y &4564 88 DEY &4565 d0 f7 BNE &455e ; move_5b6d_to_5c66_loop &4567 a0 10 LDY #&10 ; move_5207_to_5216_loop # Move &5207 - &5216 to &0761 - &0770 &4569 b9 06 52 LDA &5206,Y &456c 99 60 07 STA &0760,Y &456f 88 DEY &4570 d0 f7 BNE &4569 ; move_5207_to_5216_loop &4572 a0 4b LDY #&4b ; move_54e2_to_552c_loop # Move &54e2 - &552c to &0716 - &0760 &4574 b9 e1 54 LDA &54e1,Y &4577 99 15 07 STA &0715,Y &457a 88 DEY &457b d0 f7 BNE &4574 ; move_54e2_to_552c_loop ; move_5307_to_5406_loop # Move &5307 - &5406 to &0b11 - &0c10 &457d a0 00 LDY #&00 &457f b9 07 53 LDA &5307,Y &4582 99 11 0b STA &0b11,Y &4585 c8 INY &4586 d0 f7 BNE &457f ; move_5307_to_5406_loop &4588 a0 db LDY #&db ; move_5407_to_54e1_loop # Move &5407 - &54e1 to &0c11 - &0ceb &458a b9 06 54 LDA &5406,Y &458d 99 10 0c STA &0c10,Y &4590 88 DEY &4591 d0 f7 BNE &458a ; move_5407_to_54e1_loop &4593 a0 30 LDY #&30 ; move_5217_to_5246_loop # Move &5217 - &5246 to &06b6 - &06e5 &4595 b9 16 52 LDA &5216,Y &4598 99 b5 06 STA &06b5,Y &459b 88 DEY &459c d0 f7 BNE &4595 ; move_5217_to_5246_loop &459e a0 30 LDY #&30 ; move_5247_to_5276_loop # Move &5247 - &5276 to &06e6 - &0715 &45a0 b9 46 52 LDA &5246,Y &45a3 99 e5 06 STA &06e5,Y &45a6 88 DEY &45a7 d0 f7 BNE &45a0 ; move_5247_to_5276_loop &45a9 a0 53 LDY #&53 ; move_52b4_to_5306_loop # Move &52b4 - &5306 to &0aa4 - &0af6 &45ab b9 b3 52 LDA &52b3,Y &45ae 99 a3 0a STA &0aa3,Y &45b1 88 DEY &45b2 d0 f7 BNE &45ab ; move_52b4_to_5306_loop &45b4 a0 80 LDY #&80 ; move_50b1_to_5130_loop # Move &50b1 - &5130 to &0511 - &0590 &45b6 b9 b0 50 LDA &50b0,Y &45b9 99 10 05 STA &0510,Y &45bc 88 DEY &45bd d0 f7 BNE &45b6 ; move_50b1_to_5130_loop &45bf a0 83 LDY #&83 ; move_510d_to_518f_loop # Move &510d - &518f to &0771 - &07f3 &45c1 b9 0c 51 LDA &510c,Y &45c4 99 70 07 STA &0770,Y &45c7 88 DEY &45c8 d0 f7 BNE &45c1 ; move_510d_to_518f_loop &45ca a0 77 LDY #&77 ; move_5190_to_5206_loop # Move &5190 - &5206 to &0139 - &01af &45cc b9 8f 51 LDA &518f,Y &45cf 99 38 01 STA &0138,Y &45d2 88 DEY &45d3 d0 f7 BNE &45cc ; move_5190_to_5206_loop &45d5 a0 00 LDY #&00 ; move_552d_to_5b2c_loop # Move &552d - &5b2c to &0d01 - &1300 &45d7 b9 2d 55 LDA &552d,Y &45da 99 01 0d STA &0d01,Y &45dd b9 2d 56 LDA &562d,Y &45e0 99 01 0e STA &0e01,Y &45e3 b9 2d 57 LDA &572d,Y &45e6 99 01 0f STA &0f01,Y &45e9 b9 2d 58 LDA &582d,Y &45ec 99 01 10 STA &1001,Y &45ef b9 2d 59 LDA &592d,Y &45f2 99 01 11 STA &1101,Y &45f5 b9 2d 5a LDA &5a2d,Y &45f8 99 01 12 STA &1201,Y &45fb c8 INY &45fc d0 d9 BNE &45d7 ; move_552d_to_5b2c_loop &45fe a0 40 LDY #&40 ; move_5b2d_to_5b6c_loop # Move &5b2d - &5b6c to &1301 - &1340 &4600 b9 2c 5b LDA &5b2c,Y &4603 99 00 13 STA &1300,Y &4606 88 DEY &4607 d0 f7 BNE &4600 ; move_5b2d_to_5b6c_loop &4609 a0 0a LDY #&0a ; move_5d0c_to_5d15_loop # Move &5d0c - &5d15 to &069d - &06a6 &460b b9 0b 5d LDA &5d0b,Y &460e 99 9c 06 STA &069c,Y &4611 88 DEY &4612 d0 f7 BNE &460b ; move_5d0c_to_5d15_loop &4614 a0 05 LDY #&05 ; move_5d16_to_5d1a_loop # Move &5d16 - &5d1a to &06a7 - &06ab &4616 b9 15 5d LDA &5d15,Y &4619 99 a6 06 STA &06a6,Y &461c 88 DEY &461d d0 f7 BNE &4616 ; move_5d16_to_5d1a_loop &461f a0 0a LDY #&0a ; move_5d02_to_5d0b_loop # Move &5d02 - &5d0b to &06ac - &06b5 &4621 b9 01 5d LDA &5d01,Y &4624 99 ab 06 STA &06ab,Y &4627 88 DEY &4628 d0 f7 BNE &4621 ; move_5d02_to_5d0b_loop &462a a0 20 LDY #&20 ; move_5ca5_to_5cc4_loop # Move &5ca5 - &5cc2 to &0591 - &05b0 &462c b9 a4 5c LDA &5ca4,Y &462f 99 90 05 STA &0590,Y &4632 88 DEY &4633 d0 f7 BNE &462c ; move_5ca5_to_5cc4_loop &4635 ac b6 ff LDY &ffb6 ; os_rom_vector_table_length # Zero in MOS 1.00 &4638 f0 2b BEQ &4665 ; is_mos_1.00 &463a ae b7 ff LDX &ffb7 ; os_rom_default_vector_table_address_low &463d ad b8 ff LDA &ffb8 ; os_rom_default_vector_table_address_high &4640 86 45 STX &45 ; default_vector_table_address_low &4642 85 46 STA &46 ; default_vector_table_address_high &4644 a0 01 LDY #&01 &4646 b1 45 LDA (&45),Y ; default_vector_table_address # Get high byte of USERV &4648 85 8c STA &8c ; mos_version_flag # Positive if MOS 0.10, negative if MOS 1.20 &464a 30 25 BMI &4671 ; not_mos_0.10 ; is_mos_0.10 &464c a0 20 LDY #&20 ; move_5c67_to_5c86_loop # Move &5c67 - &5c86 to &0200 - &021f if MOS 0.10 (vector table) &464e b9 66 5c LDA &5c66,Y ; initial_vector_table - 1 &4651 99 ff 01 STA &01ff,Y ; os_vector_table - 1 &4654 88 DEY &4655 d0 f7 BNE &464e ; move_5c67_to_5c87_loop &4657 a0 3d LDY #&3d ; move_5277_to_52b3_loop # Move &5277 - &52b3 to &03a0 - &03dc if MOS 0.10 (ready_tune_data) &4659 b9 76 52 LDA &5276,Y &465c 99 9f 03 STA &039f,Y &465f 88 DEY &4660 d0 f7 BNE &4659 ; move_5277_to_52b3_loop &4662 4c 34 47 JMP &4734 ; finished_mos_dependent_code ; is_mos_1.00 &4665 a2 41 LDX #&41 ; &d941 = os_1.00_rom_default_vector_table &4667 a9 d9 LDA #&d9 &4669 86 45 STX &45 ; default_vector_table_address_low &466b 85 46 STA &46 ; default_vector_table_address_high &466d a9 ff LDA #&ff &466f 85 8c STA &8c ; mos_version_flag # Set to negative to indicate not MOS 0.10 ; not_mos_0.10 &4671 a0 0b LDY #&1b ; check_vectors_loop &4673 b1 45 LDA (&45),Y ; default_vector_table_address &4675 d9 00 02 CMP &0200,Y ; os_vector_table &4678 d0 7b BNE &46f5 ; software_protected_screen # Fail if any vectors are not default &467a 88 DEY &467b 10 f6 BPL &4673 ; check_vectors_loop &467d a0 35 LDY #&35 ; reset_vector_table_loop &467f b1 45 LDA (&45),Y ; default_vector_table_address &4681 99 00 02 STA &0200,Y ; os_vector_table &4684 88 DEY &4685 10 f8 BPL &467f ; reset_vector_table_loop &4687 a0 3d LDY #&3d ; move_5277_to_52b3_loop # Move &5277 - &52b3 to &0880 - &08bc &4689 b9 76 52 LDA &5276,Y &468c 99 7f 08 STA &087f,Y &468f 88 DEY &4690 d0 f7 BNE &4689 ; move_5277_to_52b3_loop &4692 a9 67 LDA #&67 ; &0e67 = event_handler &4694 8d 20 02 STA &0220 ; event_vector_low &4697 a9 0e LDA #&0e &4699 8d 21 02 STA &0221 ; event_vector_high &469c a2 04 LDX #&04 ; v-sync event # Enable v-sync event &469e a9 0e LDA #&0e ; Enable event &46a0 20 f4 ff JSR &fff4 ; OSBYTE &46a3 a2 00 LDX #&00 ; output buffer empty event # Disable all other events &46a5 a9 0d LDA #&0d ; Disable event &46a7 20 f4 ff JSR &fff4 ; OSBYTE &46aa a2 01 LDX #&01 ; input buffer full &46ac a9 0d LDA #&0d ; Disable event &46ae 20 f4 ff JSR &fff4 ; OSBYTE &46b1 a2 02 LDX #&02 ; character entering buffer &46b3 a9 0d LDA #&0d ; Disable event &46b5 20 f4 ff JSR &fff4 ; OSBYTE &46b8 a2 03 LDX #&03 ; ADC conversion complete &46ba a9 0d LDA #&0d ; Disable event &46bc 20 f4 ff JSR &fff4 ; OSBYTE &46bf a2 05 LDX #&05 ; interval timer crossed zero &46c1 a9 0d LDA #&0d ; Disable event &46c3 20 f4 ff JSR &fff4 ; OSBYTE &46c6 a2 06 LDX #&06 ; ESCAPE pressed event &46c8 a9 0d LDA #&0d ; Disable event &46ca 20 f4 ff JSR &fff4 ; OSBYTE &46cd a2 07 LDX #&07 ; RS423 error &46cf a9 0d LDA #&0d ; Disable event &46d1 20 f4 ff JSR &fff4 ; OSBYTE &46d4 a2 08 LDX #&08 ; network error &46d6 a9 0d LDA #&0d ; Disable event &46d8 20 f4 ff JSR &fff4 ; OSBYTE &46db a0 ff LDY #&ff &46dd a2 00 LDX #&00 &46df a9 fe LDA #&fe ; Read/Write available RAM &46e1 20 f4 ff JSR &fff4 ; OSBYTE &46e4 8a TXA &46e5 10 0e BPL &46f5 ; software_protected_screen # Fail on 16K system &46e7 a0 ff LDY #&ff &46e9 a2 00 LDX #&00 &46eb a9 c8 LDA #&c8 ; Read/Write BREAK/ESCAPE effect # Read current effect &46ed 20 f4 ff JSR &fff4 ; OSBYTE &46f0 8a TXA &46f1 c9 03 CMP #&03 ; ESCAPE disabled, memory cleared on break &46f3 f0 2d BEQ &4722 ; protection_passed # Fail if *FX200,3 not previously called ; software_protected_screen &46f5 a0 00 LDY #&00 &46f7 a2 02 LDX #&02 ; Clear memory on next RESET &46f9 a9 c8 LDA #&c8 ; Read/Write BREAK/ESCAPE effect &46fb 20 f4 ff JSR &fff4 ; OSBYTE &46fe a2 00 LDX #&00 ; write_software_protected_loop &4700 bd 0e 47 LDA &470e,X ; software_protected_string &4703 20 ee ff JSR &ffee ; OSWRCH &4706 e8 INX &4707 e0 14 CPX #&14 &4709 d0 f5 BNE &4700 ; write_software_protected_loop ; infinite_loop &470b 4c 0b 47 JMP &470b ; infinite_loop ; software_protected_string &470e 16 07 ; MODE 7 &4710 53 6f 66 74 77 61 72 65 20 50 72 6f 74 65 63 74 ; "Software Protected" &4712 65 64 ; protection_passed &4722 a0 00 LDY #&00 &4724 a2 02 LDX #&02 ; Clear memory on next RESET &4726 a9 c8 LDA #&c8 ; Read/Write BREAK/ESCAPE effect &4728 20 f4 ff JSR &fff4 ; OSBYTE &472b a0 00 LDY #&00 &472d a2 00 LDX #&00 &472f a9 f7 LDA #&f7 ; Write BREAK intercept code &4731 20 f4 ff JSR &fff4 ; OSBYTE # Clear BREAK intercept ; finished_mos_dependent_code &4734 a2 00 LDX #&00 ; printer sink &4736 a9 05 LDA #&05 ; Select the printer type &4738 20 f4 ff JSR &fff4 ; OSBYTE &473b a2 01 LDX #&01 ; Cursor keys return ASCII values 135-139 &473d a9 04 LDA #&04 ; Define action of cursor editing keys &473f 20 f4 ff JSR &fff4 ; OSBYTE &4742 a2 00 LDX #&00 &4744 a9 0c LDA #&0c ; Set auto-repeat period &4746 20 f4 ff JSR &fff4 ; OSBYTE &4749 a0 0a LDY #&0a ; move_5c87_to_5c90_loop # Move &5c87 - &5c90 to &09fa - &0a03 &474b b9 86 5c LDA &5c86,Y &474e 99 f9 09 STA &09f9,Y &4751 88 DEY &4752 d0 f7 BNE &474b ; move_5c87_to_5c90_loop &4754 a0 14 LDY #&14 ; move_5c91_to_5ca4_loop # Move &5c91 - &5ca4 to &0cec - &0cff &4756 b9 90 5c LDA &5c90,Y &4759 99 eb 0c STA &0ceb,Y &475c 88 DEY &475d d0 f7 BNE &4756 ; move_5c91_to_5ca4_loop &475f a0 50 LDY #&50 ; move_5cb2_to_5d01_loop # Move &5cb2 - &5d01 to &0643 - &0692 &4761 b9 b1 5c LDA &5cb1,Y &4764 99 42 06 STA &0642,Y &4767 88 DEY &4768 d0 f7 BNE &4761 ; move_5cb2_to_5d01_loop &476a a0 0a LDY #&0a ; move_5d1b_to_5d24_loop # Move &5d1b - &5d24 to &0693 - &069c &476c b9 1a 5d LDA &5d1a,Y &476f 99 92 06 STA &0692,Y &4772 88 DEY &4773 d0 f7 BNE &476c ; move_5d1b_to_5d24_loop &4775 a9 00 LDA #&00 ; &3000 &4777 85 45 STA &45 ; source_address_low &4779 a9 30 LDA #&30 &477b 85 46 STA &46 ; source_address_high &477d a9 41 LDA #&41 ; &1341 &477f 85 47 STA &47 ; target_address_low &4781 a9 13 LDA #&13 &4783 85 48 STA &48 ; target_address_high ; move_3000_to_4410_loop # Move &3000 - &4410 to &1341 - &2751 &4785 b1 45 LDA (&45),Y ; source_address &4787 91 47 STA (&47),Y ; target_address &4789 98 TYA &478a 91 45 STA (&45),Y ; source_address &478c e6 45 INC &45 ; source_address_low &478e d0 02 BNE &4792 ; skip_source_page &4790 e6 46 INC &46 ; source_address_high ; skip_source_page &4792 e6 47 INC &47 ; target_address_low &4794 d0 02 BNE &4798 ; skip_target_page &4796 e6 48 INC &48 ; target_address_high ; skip_target_page &4798 a5 47 LDA &47 ; target_address_low &479a c9 52 CMP #&52 &479c a5 48 LDA &48 ; target_address_high &479e e9 27 SBC #&27 &47a0 90 e3 BCC &4785 ; move_3000_to_4410_loop &47a2 a9 1b LDA #&1b ; &481b &47a4 85 45 STA &45 ; source_address_low &47a6 a9 48 LDA #&48 &47a8 85 46 STA &46 ; source_address_high ; move_481b_to_50c8_loop # Move &481b - &50c8 to &2752 - &2fff &47aa b1 45 LDA (&45),Y ; source_address &47ac 91 47 STA (&47),Y ; target_address &47ae e6 45 INC &45 ; source_address_low &47b0 d0 02 BNE &47b4 ; skip_source_page &47b2 e6 46 INC &46 ; source_address_high ; skip_source_page &47b4 e6 47 INC &47 ; target_address_low &47b6 d0 02 BNE &47ba ; skip_target_page &47b8 e6 48 INC &48 ; target_address_high ; skip_target_page &47ba a5 48 LDA &48 ; target_address_high &47bc c9 30 CMP #&30 &47be 90 ea BCC &47aa ; move_481b_to_50c8_loop &47c0 a0 00 LDY #&00 ; move_4411_to_4510_loop # Move &4411 - &4510 to &0400 - &04ff &47c2 b9 11 44 LDA &4411,Y &47c5 99 00 04 STA &0400,Y &47c8 c8 INY &47c9 d0 f7 BNE &47c2 ; move_4411_to_4510_loop &47cb a0 11 LDY #&11 ; move_4511_to_4521_loop # Move &4511 - &4521 to &0500 - &0510 &47cd b9 10 45 LDA &4510,Y &47d0 99 ff 04 STA &04ff,Y &47d3 88 DEY &47d4 d0 f7 BNE &47cd ; move_4511_to_4521_loop &47d6 a0 00 LDY #&00 ; move_4f27_to_5026_loop # Move &4f27 - &5026 to &2e5e - &2f5d (unnecessary) &47d8 b9 27 4f LDA &4f27,Y &47db 99 5e 2e STA &2e5e,Y &47de c8 INY &47df d0 f7 BNE &47d8 ; move_4f27_to_5026_loop &47e1 a0 8a LDY #&8a ; move_5027_to_50b0_loop # Move &5027 - &50b0 to &2f5e - &2fe7 (unnecessary) &47e3 b9 26 50 LDA &5026,Y &47e6 99 5d 2f STA &2f5d,Y &47e9 88 DEY &47ea d0 f7 BNE &47e3 ; move_5027_to_50b0_loop &47ec 20 e7 18 JSR &18e7 ; set_movement_and_firing_check_routine_addresses &47ef a9 23 LDA #&23 ; &2623 = calculate_sprite_address_and_sizes &47f1 8d e0 0e STA &0ee0 ; plot_enemy_calculate_sprite_address_and_sizes + 1 &47f4 8d c1 0e STA &0ec1 ; plot_sprite_calculate_sprite_address_and_sizes + 1 &47f7 a9 26 LDA #&26 &47f9 8d e1 0e STA &0ee1 ; plot_enemy_calculate_sprite_address_and_sizes + 1 &47fc 8d c2 0e STA &0ec2 ; plot_sprite_calculate_sprite_address_and_sizes + 2 &47ff 24 8c BIT &8c ; mos_version_flag &4801 30 0a BMI &480d ; not_mos_0.10 # Positive if MOS 0.10 &4803 a9 a0 LDA #&a0 ; &03a0 # Set address of ready_tune_data to &03a0 &4805 8d a0 24 STA &24a0 ; tune_variables_table &4808 a9 03 LDA #&03 &480a 8d a1 24 STA &24a1 ; tune_variables_table + 1 ; not_mos_0.10 &480d 4c 00 04 JMP &0400 ; initialise_screen ; protected_string &4810 3f 64 65 74 63 65 74 6f 72 70 3f ; "?detcetorp?" # &481b - &50c8 is moved to &2752 - &2fff at &47aa ; sprite_data ; sprite_sizes_offsets # 842184.. sprite ; 0 1 2 3 4 5 6 7 8 9 a b # ......21 flip (2 horizontal, 1 vertical) &2752 25 19 0d 00 0c 18 24 1a 0e 02 0f 1b ; &00 SPRITE_GUARD &275e 55 49 3d 30 3c 48 54 4a 3e 32 3f 4b ; &0c SPRITE_DRONE &276a 85 79 6d 60 6c 78 84 7a 6e 62 6f 7b ; &14 SPRITE_QUEEN &2776 90 ; &24 SPRITE_LIFE &2777 9c ; &25 SPRITE_BOMB (unused) &2778 a8 a9 aa ; &26 SPRITE_EXPLOSION ; sprite_sizes ; xo addr w h yo &277b 00 83 00 04 16 00 ; &00 guard facing 3 o'clock &2781 00 da 00 07 11 00 ; &0c guard facing 4 o'clock &2787 00 4c 01 07 13 00 ; &18 guard facing 5 o'clock &278d 00 d1 01 06 0f 00 ; &24 guard facing 6 o'clock &2793 00 2b 02 06 10 00 ; &30 drone facing 3 o'clock &2799 00 8a 02 07 13 00 ; &3c drone facing 4 o'clock &279f 00 0a 03 06 17 00 ; &48 drone facing 5 o'clock &27a5 00 92 03 06 11 00 ; &54 drone facing 6 o'clock &27ab ff f8 03 07 15 00 ; &60 queen facing 3 o'clock &27b1 ff 85 04 08 15 00 ; &6c queen facing 4 o'clock &27b7 ff 2a 05 07 17 00 ; &78 queen facing 5 o'clock &27bd ff cb 05 07 17 00 ; &84 queen facing 6 o'clock &27c3 00 68 06 05 0a 00 ; &90 life &27c9 00 9a 06 02 08 00 ; &9c bomb # Unused; would plot part of explosion &27cf 00 9a 06 06 13 00 ; &a8 explosion ; sprites ; sprite_guard_3 &27d5 44 c3 c3 c3 41 41 00 00 05 05 0f 0f 05 05 00 00 &27e5 41 41 c3 c3 c3 44 cc 64 64 64 30 30 30 30 0b 0b &27f5 0b 0b 0b 0b 30 30 30 30 64 64 64 cc 00 88 88 c9 &2805 98 98 11 11 31 31 30 30 31 31 11 11 98 98 c9 88 &2815 88 00 00 82 82 88 88 00 00 22 22 22 20 20 22 22 &2825 22 00 00 88 88 82 82 ; sprite_guard_4 &282c 00 00 00 00 00 05 05 05 00 00 00 00 c3 41 41 00 &283c 00 41 c3 00 00 0f 0f 0f 0f 0f 01 00 10 10 92 30 &284c 98 44 30 92 92 41 41 0b 03 07 07 07 0f 30 64 64 &285c 64 cc 88 cc 64 64 30 64 64 0b 0b 03 12 12 12 00 &286c 00 00 00 00 00 88 88 88 88 00 11 31 31 30 33 33 &287c 33 20 20 10 00 00 00 00 10 20 20 22 33 33 30 32 &288c 22 00 00 00 88 82 00 00 82 88 00 00 00 00 00 00 &289c 00 00 ; sprite_guard_5 &289e 00 00 00 00 00 88 88 cc 64 30 92 92 c3 c3 41 00 &28ae 00 00 00 00 00 00 00 00 00 00 00 cc 98 30 61 c3 &28be c3 c3 82 00 00 00 00 00 00 0f 0f 0f 0b 03 07 0f &28ce 25 83 83 00 00 10 20 20 c9 44 00 00 44 4e 1a 12 &28de 03 0f 0f 0b 03 30 30 32 33 33 11 11 88 98 98 98 &28ee 30 30 30 61 41 00 12 30 33 33 31 30 22 22 00 00 &28fe 00 82 61 c3 c3 c3 82 00 00 30 10 00 22 22 22 00 &290e 00 00 00 00 00 00 00 00 00 00 00 00 00 88 82 00 &291e 00 00 00 00 00 ; sprite_guard_6 &2923 41 41 c9 c9 98 98 98 cc cc 44 00 00 00 10 c6 00 &2933 00 82 82 c3 30 30 30 30 88 00 11 31 11 00 00 05 &2943 0f 0f 03 0f 0f 03 03 30 30 32 32 32 32 00 00 0a &2953 0a 43 1a 1a 12 12 20 20 33 33 33 22 41 41 41 c3 &2963 92 30 30 64 64 cc 00 00 20 10 44 00 00 88 88 88 &2973 88 88 88 88 00 00 00 00 00 82 ; sprite_drone_3 &297d 40 c0 c0 03 03 00 05 0f 05 00 03 03 c0 c0 40 00 &298d 00 80 c0 03 03 1b 1b 1b 1b 1b 03 03 c0 80 00 00 &299d 00 00 00 02 02 03 33 33 33 03 02 02 00 00 00 00 &29ad 00 40 c0 81 03 17 3f 3f 3f 17 03 81 c0 40 00 00 &29bd c0 c0 c0 03 2a 30 30 3a 30 30 2a 03 c0 c0 c0 00 &29cd c0 80 80 03 00 00 20 30 20 00 00 03 80 80 c0 ; sprite_drone_4 &29dc 00 00 00 00 00 02 03 81 c0 c0 c0 40 00 00 00 00 &29ec 00 00 00 01 01 00 0f 0f 0f 05 07 03 81 c0 80 00 &29fc 00 00 00 00 00 00 c0 42 03 01 0f 1b 1b 33 03 01 &2a0c 01 01 40 40 00 00 00 00 00 80 c0 c0 42 02 02 03 &2a1c 23 37 37 3f 3f 17 81 c0 c0 c0 40 40 00 00 00 00 &2a2c 00 42 03 2b 3f 3a 3a 30 30 02 03 81 c0 80 80 00 &2a3c 00 00 00 40 c0 c0 42 03 01 20 20 30 30 00 02 02 &2a4c 00 00 00 00 00 00 80 c0 c0 80 80 02 02 00 00 00 ; sprite_drone_5 &2a5c 00 00 00 00 00 01 01 81 81 c0 c0 00 00 00 00 00 &2a6c 00 40 40 40 00 00 00 00 00 00 05 05 05 05 07 13 &2a7c 13 03 03 03 01 01 81 81 c0 c0 c0 c0 c0 40 01 01 &2a8c 01 0a 0f 0f 1b 33 33 33 33 17 3f 3f 3f 3a 12 12 &2a9c 02 03 81 01 00 c0 c0 42 42 42 42 03 03 03 23 2b &2aac 3f 3f 3a 3a 30 30 30 30 10 00 00 00 00 80 80 80 &2abc 00 00 00 00 c0 42 42 42 42 03 21 21 20 20 20 20 &2acc 00 00 00 00 00 00 00 00 00 00 00 80 80 c0 c0 c0 &2adc 80 80 02 02 02 00 00 00 ; sprite_drone_6 &2ae4 00 00 40 c0 40 00 00 00 00 00 00 40 40 c0 c0 c0 &2af4 80 01 81 81 81 81 81 81 01 00 01 03 17 17 12 02 &2b04 02 02 00 05 0f 0f 0f 33 33 13 17 3f 3f 3f 35 30 &2b14 30 30 10 01 01 0b 0b 0b 23 23 03 02 2b 2b 3f 35 &2b24 30 20 20 00 00 80 c0 c0 c0 80 80 00 00 00 02 42 &2b34 42 42 42 42 02 00 00 00 80 00 00 00 00 00 00 00 &2b44 00 80 80 80 80 80 ; sprite_queen_3 &2b4a 44 cc c9 64 c6 82 c3 41 00 00 00 00 00 41 c3 82 &2b5a c6 64 c9 cc 44 98 82 00 00 98 82 82 00 00 00 00 &2b6a 00 00 00 82 82 98 00 00 82 98 30 00 00 00 30 10 &2b7a 10 30 1a 30 10 30 1a 30 10 10 30 00 00 00 30 30 &2b8a 10 10 00 20 20 10 10 10 10 10 10 10 10 10 20 20 &2b9a 00 10 10 30 00 00 20 20 10 30 10 10 10 30 31 30 &2baa 10 10 10 30 10 20 20 00 00 00 00 00 00 00 33 33 &2bba 26 26 26 33 26 26 26 33 33 00 00 00 00 00 00 00 &2bca 00 00 00 00 22 22 33 22 22 22 33 22 22 ; sprite_queen_4 &2bd7 00 00 00 00 00 00 00 00 00 00 00 00 41 c3 c6 64 &2be7 c9 c9 cc 44 00 44 98 64 c6 c3 41 00 00 00 00 00 &2bf7 00 00 82 82 c9 98 00 82 98 10 30 00 00 98 82 00 &2c07 00 10 05 10 00 10 05 10 00 00 20 30 00 00 30 30 &2c17 00 00 20 30 00 30 20 20 20 20 20 20 20 20 30 10 &2c27 30 00 10 30 20 30 10 00 20 20 10 20 20 20 20 30 &2c37 20 20 20 10 20 10 30 20 00 00 00 20 20 30 30 30 &2c47 31 31 31 31 33 31 31 31 31 31 20 00 00 00 00 00 &2c57 00 00 00 00 22 33 19 19 19 33 19 19 19 33 22 00 &2c67 00 00 00 00 00 00 00 00 00 00 00 00 22 00 00 00 &2c77 22 00 00 00 00 ; sprite_queen_5 &2c7c 00 00 00 10 92 64 64 20 20 20 20 20 30 10 10 00 &2c8c 00 00 00 00 00 00 00 00 41 c3 c3 c9 61 20 20 30 &2c9c 30 10 00 00 00 20 30 10 00 00 00 00 00 00 00 82 &2cac 00 00 00 00 0a 0f 05 10 30 20 30 10 10 10 30 30 &2cbc 00 00 00 00 00 00 41 c3 41 00 0a 0f 05 30 30 00 &2ccc 10 30 10 30 31 33 26 26 33 11 00 00 cc 61 61 88 &2cdc 64 92 10 30 20 00 00 30 32 33 33 33 33 19 19 33 &2cec 33 22 22 88 cc c6 92 10 00 00 20 20 30 10 30 10 &2cfc 30 33 33 0c 0c 33 33 11 11 00 00 00 00 00 20 20 &2d0c 30 10 10 10 10 10 30 30 20 22 22 22 22 00 00 00 &2d1c 00 ; sprite_queen_6 &2d1d 44 cc 98 c9 61 20 20 20 20 20 20 20 20 30 10 00 &2d2d 00 00 00 00 00 00 00 88 30 92 cc c9 c9 61 20 20 &2d3d 30 20 20 20 10 30 30 31 11 11 11 00 00 00 00 00 &2d4d 82 c3 c3 82 00 05 25 30 00 00 30 20 10 30 33 0c &2d5d 0c 33 33 11 11 00 00 00 41 41 00 00 05 25 30 00 &2d6d 00 30 20 32 32 33 26 26 33 33 11 11 00 10 92 c6 &2d7d c3 c3 41 00 20 30 00 00 20 30 10 30 33 19 19 33 &2d8d 22 00 00 cc 64 92 c9 c9 88 20 20 20 20 20 20 20 &2d9d 10 30 20 20 00 00 00 00 00 00 00 88 88 88 20 20 &2dad 20 20 20 20 20 20 20 20 00 00 00 00 00 ; sprite_life &2dba 00 00 00 00 2a 02 35 3f 3f 3a 00 00 2a 17 35 3f &2dca 3f 3b 31 11 2a 2a 2a 3f 3f 37 37 1b 1b 33 00 00 &2dda 2a 02 20 2a 3f 3f 35 10 00 00 00 00 2a 02 20 2a &2dea 2a 2a ; sprite_explosion &2dec 00 01 00 00 0a 00 01 00 02 00 05 00 0a 00 02 05 &2dfc 00 00 00 0a 00 00 02 14 00 00 0a 00 14 00 14 02 &2e0c 00 00 00 00 02 01 0a 00 02 00 14 00 00 22 20 11 &2e1c 20 00 00 28 01 28 00 00 05 02 05 00 14 00 20 32 &2e2c 00 38 20 00 31 00 00 00 14 0a 00 02 02 00 00 05 &2e3c 28 00 00 01 14 00 14 00 00 28 00 05 02 05 00 00 &2e4c 00 02 00 05 00 0a 00 00 01 00 00 05 02 00 00 02 &2e5c 00 00 ; sound_and_envelope_data ; envelope_1 # Enemy exploding &2e5e 01 81 00 ff 02 0c 0c 1e 00 00 00 9c 00 00 ; &00 ; envelope_2 # Enemy exploding, player firing &2e6c 02 02 00 00 00 01 01 01 6e fd fe 9c 6e 5a ; &0e ; envelope_3 # Player firing &2e7a 03 81 01 00 fe 02 02 3c 00 00 00 00 00 00 ; &1c ; envelope_4 # Tune &2e88 01 01 00 00 00 01 01 01 5a fc ff ff 5a 46 ; &2a ; envelope_5 # Player exploding &2e96 01 82 00 01 00 06 01 32 73 01 fe 88 73 7e ; &38 ; envelope_6 # Enemy becoming active &2ea4 04 82 00 02 ff 03 0a 46 06 ff fe 82 6e 78 ; &46 ; sound_1 # Enemy exploding ; chan vol pitch dur &2eb2 10 00 02 00 03 00 08 00 ; &54 ; sound_2 # Enemy exploding ; chan vol pitch dur &2eba 11 00 01 00 ec 00 08 00 ; &5c ; sound_3 # Player firing ; chan vol pitch dur &2ec2 10 00 02 00 07 00 0c 00 ; &64 ; sound_4 # Player firing ; chan vol pitch dur &2eca 11 00 03 00 f0 00 0c 00 ; &6c ; sound_5 # Player exploding ; chan vol pitch dur &2ed2 10 00 01 00 05 00 19 00 ; &74 ; sound_6 # Enemy becoming active ; chan vol pitch dur &2eda 13 00 04 00 78 00 3c 00 ; &7c ; well_done_string &2ee2 0c &2ee3 16 72 &2ee5 57 65 6c 6c 20 44 6f 6e 65 21 a1 ; "Well Done!!" ; please_type_your_name_string &2ef0 fc &2ef1 08 0c &2ef3 50 6c 65 61 73 65 20 74 79 70 65 20 79 6f 75 72 ; "Please type your name" &2f03 20 6e 61 6d e5 ; press_return_or_fire_string &2f08 3f &2f09 06 0c &2f0b 50 72 65 73 73 20 52 45 54 55 52 4e 20 6f 72 20 ; "Press RETURN or (fire)" &2f1b 28 66 69 72 65 a9 ; copyright_aardvark_string &2f21 0c &2f22 0c 04 &2f24 28 43 29 20 41 61 72 64 76 61 72 6b 20 27 38 b3 ; "(C) Aardvark '83" ; zalagan_heroes_string &2f34 0c &2f35 14 72 &2f37 5a 61 6c 61 67 61 6e 20 48 65 72 6f 65 f3 ; "Zalagan Heroes" ; ready_string &2f45 3c &2f46 20 40 &2f48 52 65 61 64 f9 ; "Ready" ; player_one_string &2f4d 3c &2f4e 18 48 &2f50 50 6c 61 79 65 72 20 4f 6e e5 ; "Player One" ; player_two_string &2f5a 3c &2f5b 18 48 &2f5d 50 6c 61 79 65 72 20 54 77 ef ; "Player Two" ; one_up_string &2f67 c3 &2f68 00 7e &2f6a 31 55 d0 ; "1UP" ; two_up_string &2f6d c3 &2f6e 36 7e &2f70 32 55 d0 ; "2UP" ; stage_string &2f73 3c &2f74 19 44 &2f76 53 54 41 47 45 20 20 a0 ; "STAGE " ; challenge_stage_string &2f7e 3c &2f7f 14 40 &2f81 43 48 41 4c 4c 45 4e 47 45 20 53 54 41 47 c5 ; "CHALLENGE STAGE" ; perfect_string &2f90 0c &2f91 17 4a &2f93 50 65 72 66 65 63 74 20 a1 ; "Perfect !" ; hits_string &2f9c 33 &2f9d 17 40 &2f9f 48 69 74 73 20 3d 20 20 b0 ; "Hits = 0" ; bonus_string &2fa8 0f &2fa9 14 38 &2fab 42 6f 6e 75 73 20 3d 20 20 20 30 b0 ; "Bonus = 00" ; special_bonus_string # Unused &2fb7 0f &2fb8 11 38 &2fba 53 70 65 63 69 61 6c 20 42 6f 6e 75 73 a1 ; "Special Bonus!" ; q_string &2fc8 0c &2fc9 46 00 &2fcb d1 ; "Q" ; one_string &2fcc 0f &2fcd 4c 00 &2fcf b1 ; "1" ; two_string &2fd0 0f &2fd1 4c 00 &2fd3 b2 ; "2" ; k_string &2fd4 33 &2fd5 49 00 &2fd7 cb ; "K" ; j_string &2fd8 33 &2fd9 49 00 &2fdb ca ; "J" ; game_over_string &2fdc 3c &2fdd 1a &2fde 40 47 61 6d 65 20 4f 76 65 f2 ; "Game Over" # &50b1 - &5130 is moved to &0511 - &0590 at &45b6 # &0511 - &0570 is moved to &0320 - &037f at &047d ; arrival_pattern_05_data &0320 00 19 ; start position &0322 26 ; (+2, 0) x 2 &0323 e5 ; (+2, +1) x 8 &0324 24 ; (+2, +2) x 2 &0325 02 ; (+1, +2) x 1 &0326 20 ; ( 0, +3) x 2 &0327 36 ; (-1, +2) x 2 &0328 33 ; (-2, +1) x 2 &0329 12 ; (-2, 0) x 1 &032a 10 ; (-2, -2) x 1 &032b 0d ; (-1, -3) x 1 &032c 2c ; ( 0, -3) x 2 &032d 0b ; (+1, -3) x 1 &032e 09 ; (+2, -3) x 1 &032f 06 ; (+2, 0) x 1 &0330 05 ; (+2, +1) x 1 &0331 24 ; (+2, +2) x 2 &0332 63 ; (+2, +3) x 4 &0333 ff ; end of pattern ; arrival_pattern_0a_data &0334 00 19 ; start position &0336 26 ; (+2, 0) x 2 &0337 e5 ; (+2, +1) x 8 &0338 25 ; (+2, +1) x 2 &0339 03 ; (+2, +3) x 1 &033a 21 ; (+1, +3) x 2 &033b 40 ; ( 0, +3) x 3 &033c 37 ; (-1, +3) x 2 &033d 15 ; (-2, +3) x 1 &033e 32 ; (-2, 0) x 2 &033f 10 ; (-2, -2) x 1 &0340 2e ; (-1, -2) x 2 &0341 6c ; ( 0, -3) x 4 &0342 2b ; (+1, -3) x 2 &0343 08 ; (+2, -2) x 1 &0344 06 ; (+2, 0) x 1 &0345 45 ; (+2, +1) x 3 &0346 23 ; (+2, +3) x 2 &0347 ff ; end of pattern ; arrival_pattern_0d_data &0348 00 20 ; start position &034a 26 ; (+2, 0) x 2 &034b e5 ; (+2, +1) x 8 &034c 25 ; (+2, +1) x 2 &034d 01 ; (+1, +3) x 1 &034e 18 ; ( 0, 0) x 1 &034f 02 ; (+1, +2) x 1 &0350 00 ; ( 0, +3) x 1 &0351 18 ; ( 0, 0) x 1 &0352 36 ; (-1, +2) x 2 &0353 18 ; ( 0, 0) x 1 &0354 12 ; (-2, 0) x 1 &0355 18 ; ( 0, 0) x 1 &0356 12 ; (-2, 0) x 1 &0357 0d ; (-1, -3) x 1 &0358 18 ; ( 0, 0) x 1 &0359 0c ; ( 0, -3) x 1 &035a 0b ; (+1, -3) x 1 &035b 18 ; ( 0, 0) x 1 &035c 07 ; (+2, -1) x 1 &035d 18 ; ( 0, 0) x 1 &035e 26 ; (+2, 0) x 2 &035f 24 ; (+2, +2) x 2 &0360 ff ; end of pattern ; attack_pattern_2_data &0361 28 28 ; unused &0363 16 ; (-1, +2) x 1 &0364 19 ; (+3, 0) x 1 # Bug: sets sprite angle to &11 if enemy not mirrored &0365 02 ; (+1, +2) x 1 &0366 05 ; (+2, +1) x 1 &0367 06 ; (+2, 0) x 1 &0368 08 ; (+2, -2) x 1 &0369 2c ; ( 0, -3) x 2 &036a 10 ; (-2, -2) x 1 &036b 12 ; (-2, 0) x 1 &036c 36 ; (-1, +2) x 2 &036d 17 ; (-1, +3) x 1 &036e 13 ; (-2, +1) x 1 &036f 12 ; (-2, 0) x 1 &0370 11 ; (-2, -1) x 1 &0371 0d ; (-1, -3) x 1 &0372 0c ; ( 0, -3) x 1 &0373 2a ; (+1, -2) x 2 &0374 08 ; (+2, -2) x 1 &0375 07 ; (+2, -1) x 1 &0376 09 ; (+2, -3) x 1 &0377 0c ; ( 0, -3) x 1 &0378 2e ; (-1, -2) x 2 &0379 ec ; ( 0, -3) x 8 &037a 4c ; ( 0, -3) x 3 &037b ff ; end of pattern # &510d - &518f is moved to &0771 - &07f3 at &45c1 ; arrival_pattern_14_data &0771 23 7e ; start position &0773 ac ; ( 0, -3) x 6 &0774 eb ; (+1, -3) x 8 &0775 0b ; (+1, -3) x 1 &0776 ec ; ( 0, -3) x 8 &0777 ec ; ( 0, -3) x 8 &0778 2c ; ( 0, -3) x 2 &0779 2d ; (-1, -3) x 2 &077a 31 ; (-2, -1) x 2 &077b 33 ; (-2, +1) x 2 &077c 37 ; (-1, +3) x 2 &077d 20 ; ( 0, +3) x 2 &077e 21 ; (+1, +3) x 2 &077f 04 ; (+2, +2) x 1 &0780 05 ; (+2, +1) x 1 &0781 e6 ; (+2, 0) x 8 &0782 e6 ; (+2, 0) x 8 &0783 86 ; (+2, 0) x 5 &0784 ff ; end of pattern ; arrival_pattern_18_data &0785 00 46 ; start position &0787 e6 ; (+2, 0) x 8 &0788 47 ; (+2, -1) x 3 &0789 a8 ; (+2, -2) x 6 &078a 29 ; (+2, -3) x 2 &078b 2b ; (+1, -3) x 2 &078c cc ; ( 0, -3) x 7 &078d c0 ; ( 0, +3) x 7 &078e 21 ; (+1, +3) x 2 &078f 23 ; (+2, +3) x 2 &0790 84 ; (+2, +2) x 5 &0791 25 ; (+2, +1) x 2 &0792 e6 ; (+2, 0) x 8 &0793 ff ; end of pattern ; arrival_pattern_1c_data &0794 00 32 ; start position &0796 e1 ; (+1, +3) x 8 &0797 26 ; (+2, 0) x 2 &0798 eb ; (+1, -3) x 8 &0799 ea ; (+1, -2) x 8 &079a ca ; (+1, -2) x 7 &079b 46 ; (+2, 0) x 3 &079c 42 ; (+1, +2) x 3 &079d a0 ; ( 0, +3) x 6 &079e 56 ; (-1, +2) x 3 &079f 52 ; (-2, 0) x 3 &07a0 4e ; (-1, -2) x 3 &07a1 ac ; ( 0, -3) x 6 &07a2 4a ; (+1, -2) x 3 &07a3 e6 ; (+2, 0) x 8 &07a4 e6 ; (+2, 0) x 8 &07a5 c6 ; (+2, 0) x 7 &07a6 ff ; end of pattern ; arrival_pattern_20_data &07a7 1e 7e ; start position &07a9 ec ; ( 0, -3) x 8 &07aa ec ; ( 0, -3) x 8 &07ab ec ; ( 0, -3) x 8 &07ac ec ; ( 0, -3) x 8 &07ad 0c ; ( 0, -3) x 1 &07ae 2a ; (+1, -2) x 2 &07af 07 ; (+2, -1) x 1 &07b0 26 ; (+2, 0) x 2 &07b1 05 ; (+2, +1) x 1 &07b2 e3 ; (+2, +3) x 8 &07b3 e3 ; (+2, +3) x 8 &07b4 43 ; (+2, +3) x 3 &07b5 ff ; end of pattern ; arrival_pattern_24_data &07b6 00 46 ; start position &07b8 e6 ; (+2, 0) x 8 &07b9 e6 ; (+2, 0) x 8 &07ba e6 ; (+2, 0) x 8 &07bb 06 ; (+2, 0) x 1 &07bc 90 ; (-2, -2) x 5 &07bd b1 ; (-2, -1) x 6 &07be 47 ; (+2, -1) x 3 &07bf 49 ; (+2, -3) x 3 &07c0 ec ; ( 0, -3) x 8 &07c1 78 ; ( 0, 0) x 4 &07c2 e6 ; (+2, 0) x 8 &07c3 e6 ; (+2, 0) x 8 &07c4 66 ; (+2, 0) x 4 &07c5 ff ; end of pattern ; arrival_pattern_28_data &07c6 1e 7e ; start position &07c8 4c ; ( 0, -3) x 3 &07c9 98 ; ( 0, 0) x 5 &07ca a6 ; (+2, 0) x 6 &07cb 98 ; ( 0, 0) x 5 &07cc ac ; ( 0, -3) x 6 &07cd 98 ; ( 0, 0) x 5 &07ce a6 ; (+2, 0) x 6 &07cf 98 ; ( 0, 0) x 5 &07d0 ac ; ( 0, -3) x 6 &07d1 98 ; ( 0, 0) x 5 &07d2 e6 ; (+2, 0) x 8 &07d3 98 ; ( 0, 0) x 5 &07d4 ec ; ( 0, -3) x 8 &07d5 ec ; ( 0, -3) x 8 &07d6 0c ; ( 0, -3) x 1 &07d7 98 ; ( 0, 0) x 5 &07d8 66 ; (+2, 0) x 4 &07d9 ff ; end of pattern ; arrival_pattern_30_data &07da 00 6e ; start position &07dc e6 ; (+2, 0) x 8 &07dd e6 ; (+2, 0) x 8 &07de e6 ; (+2, 0) x 8 &07df e6 ; (+2, 0) x 8 &07e0 46 ; (+2, 0) x 3 &07e1 ef ; (-2, -3) x 8 &07e2 ef ; (-2, -3) x 8 &07e3 ef ; (-2, -3) x 8 &07e4 cf ; (-2, -3) x 7 &07e5 e6 ; (+2, 0) x 8 &07e6 e6 ; (+2, 0) x 8 &07e7 e6 ; (+2, 0) x 8 &07e8 e6 ; (+2, 0) x 8 &07e9 46 ; (+2, 0) x 3 &07ea ff ; end of pattern ; attack_pattern_0_data &07eb 1e 64 ; unused &07ed 00 ; ( 0, +3) x 1 &07ee 16 ; (-1, +2) x 1 &07ef 12 ; (-2, 0) x 1 &07f0 0e ; (-1, -2) x 1 &07f1 0d ; (-1, -3) x 1 &07f2 0c ; ( 0, -3) x 1 &07f3 ff ; end of pattern # &5190 - &5206 is moved to &0139 - &01af at &45cc ; arrival_pattern_02_data &0139 2d 7e ; unused &013b 4c ; ( 0, -3) x 3 &013c 0d ; (-1, -3) x 1 &013d ee ; (-1, -2) x 8 &013e ee ; (-1, -2) x 8 &013f ee ; (-1, -2) x 8 &0140 6e ; (-1, -2) x 4 &0141 2d ; (-1, -3) x 2 &0142 6c ; ( 0, -3) x 4 &0143 4b ; (+1, -3) x 3 &0144 0a ; (+1, -2) x 1 &0145 09 ; (+2, -3) x 1 &0146 07 ; (+2, -1) x 1 &0147 26 ; (+2, 0) x 2 &0148 25 ; (+2, +1) x 2 &0149 04 ; (+2, +2) x 1 &014a 02 ; (+1, +2) x 1 &014b 21 ; (+1, +3) x 2 &014c ff ; end of pattern ; attack_pattern_6_data &014d 23 64 ; unused &014f 4c ; ( 0, -3) x 3 &0150 4b ; (+1, -3) x 3 &0151 ea ; (+1, -2) x 8 &0152 8a ; (+1, -2) x 5 &0153 06 ; (+2, 0) x 1 &0154 22 ; (+1, +2) x 2 &0155 01 ; (+1, +3) x 1 &0156 00 ; ( 0, +3) x 1 &0157 17 ; (-1, +3) x 1 &0158 36 ; (-1, +2) x 2 &0159 12 ; (-2, 0) x 1 &015a 2e ; (-1, -2) x 2 &015b 0d ; (-1, -3) x 1 &015c 0c ; ( 0, -3) x 1 &015d 0b ; (+1, -3) x 1 &015e ea ; (+1, -2) x 8 &015f ea ; (+1, -2) x 8 &0160 ea ; (+1, -2) x 8 &0161 ea ; (+1, -2) x 8 &0162 4a ; (+1, -2) x 3 &0163 ff ; end of pattern ; attack_pattern_4_data &0164 2c 41 ; unused &0166 08 ; (+2, -2) x 1 &0167 0b ; (+1, -3) x 1 &0168 ec ; ( 0, -3) x 8 &0169 4c ; ( 0, -3) x 3 &016a 38 ; ( 0, 0) x 2 &016b 0d ; (-1, -3) x 1 &016c 38 ; ( 0, 0) x 2 &016d 0f ; (-2, -3) x 1 &016e 38 ; ( 0, 0) x 2 &016f 11 ; (-2, -1) x 1 &0170 38 ; ( 0, 0) x 2 &0171 12 ; (-2, 0) x 1 &0172 38 ; ( 0, 0) x 2 &0173 12 ; (-2, 0) x 1 &0174 38 ; ( 0, 0) x 2 &0175 12 ; (-2, 0) x 1 &0176 38 ; ( 0, 0) x 2 &0177 13 ; (-2, +1) x 1 &0178 38 ; ( 0, 0) x 2 &0179 15 ; (-2, +3) x 1 &017a 38 ; ( 0, 0) x 2 &017b 17 ; (-1, +3) x 1 &017c 38 ; ( 0, 0) x 2 &017d 00 ; ( 0, +3) x 1 &017e 38 ; ( 0, 0) x 2 &017f 00 ; ( 0, +3) x 1 &0180 38 ; ( 0, 0) x 2 &0181 00 ; ( 0, +3) x 1 &0182 38 ; ( 0, 0) x 2 &0183 01 ; (+1, +3) x 1 &0184 38 ; ( 0, 0) x 2 &0185 03 ; (+2, +3) x 1 &0186 38 ; ( 0, 0) x 2 &0187 05 ; (+2, +1) x 1 &0188 38 ; ( 0, 0) x 2 &0189 06 ; (+2, 0) x 1 &018a 38 ; ( 0, 0) x 2 &018b 06 ; (+2, 0) x 1 &018c 38 ; ( 0, 0) x 2 &018d 06 ; (+2, 0) x 1 &018e 38 ; ( 0, 0) x 2 &018f 06 ; (+2, 0) x 1 &0190 38 ; ( 0, 0) x 2 &0191 07 ; (+2, -1) x 1 &0192 38 ; ( 0, 0) x 2 &0193 0a ; (+1, -2) x 1 &0194 38 ; ( 0, 0) x 2 &0195 0c ; ( 0, -3) x 1 &0196 18 ; ( 0, 0) x 1 &0197 0c ; ( 0, -3) x 1 &0198 18 ; ( 0, 0) x 1 &0199 0c ; ( 0, -3) x 1 &019a 18 ; ( 0, 0) x 1 &019b 0c ; ( 0, -3) x 1 &019c 18 ; ( 0, 0) x 1 &019d 0c ; ( 0, -3) x 1 &019e 18 ; ( 0, 0) x 1 &019f 8c ; ( 0, -3) x 5 &01a0 ff ; end of pattern ; attack_pattern_8_data &01a1 23 6e ; unused &01a3 ea ; (+1, -2) x 8 &01a4 ea ; (+1, -2) x 8 &01a5 6a ; (+1, -2) x 4 &01a6 0b ; (+1, -3) x 1 &01a7 2c ; ( 0, -3) x 2 &01a8 ff ; end of pattern ; attack_pattern_a_data &01a9 32 3c ; unused &01ab ec ; ( 0, -3) x 8 &01ac ec ; ( 0, -3) x 8 &01ad ec ; ( 0, -3) x 8 &01ae 0c ; ( 0, -3) x 1 &01af ff ; end of pattern # &5207 - &5216 is moved to &0761 - &0770 at &4569 ; sprite_player_missile &0761 11 11 11 11 11 11 30 10 00 00 00 00 00 00 20 00 # &5217 - &5246 is moved to &06b6 - &06e5 at &4595 # &5247 - &5276 is moved to &06e6 - &0715 at &45a0 ; sprite_player &06b6 00 00 00 00 00 00 00 00 00 00 00 00 00 2a 2a 0a &06c6 15 15 15 05 3f 3f 3f 3f 00 00 00 00 2a 2a 2a 2a &06d6 00 00 00 00 00 2a 2a 0a 00 00 00 00 00 00 00 00 &06e6 2a 2a 0a 17 35 3f 3f 3a 17 35 3f 3f 3b 3b 31 11 &06f6 3f 3b 27 27 0f 0f 33 22 3f 3f 37 37 1b 1b 33 33 &0706 02 20 2a 3f 3f 3f 35 10 2a 2a 0a 02 20 2a 2a 2a # &5277 - &52b3 is moved to &0880 - &08bc at &4689 if not MOS 0.10 # &5277 - &52b3 is moved to &03a0 - &03dc at &4659 if MOS 0.10 ; ready_tune_data &0880 03 13 23 ; offsets ; ready_tune_channel_1_data &0883 4e 42 46 3a 3a 3e 42 3e 3a 3a 3a 4a 4d 4b 4e ff ; ready_tune_channel_2_data &0893 5e 52 56 4a 4e 4e 4e 4e 4e 5e 4a 62 5d 5b 5e ff ; ready_tune_channel_3_data &08a3 69 70 69 5c 61 68 61 54 5d 60 5d 54 4e 56 5c 60 &08b3 64 6a 69 6c 71 78 7d 67 6a ff # &52b4 - &5306 is moved to &0aa4 - &0af6 at &45ab ; doubling_tune_data &0aa4 03 1b 37 ; offsets ; doubling_tune_channel_1_data &0aa7 58 60 65 6c 64 61 58 60 65 6c 64 60 58 64 6c 75 &0ab7 6c 64 6c 64 50 65 5b ff ; doubling_tune_channel_2_data &0abf 34 3c 44 50 64 44 3c 50 64 3c 34 44 58 64 58 44 &0acf 34 3c 44 50 64 44 3c 50 30 29 36 ff ; doubling_tune_channel_3_data &0adb 28 30 34 44 50 34 30 44 50 34 28 34 44 58 44 34 &0aeb 28 30 34 44 50 34 20 30 50 19 2b ff # &5307 - &5406 is moved to &0b11 - &0c10 at &457d # &5407 - &54e1 is moved to &0c11 - &0ceb at &458a ; font_data &0b11 00 00 00 00 00 ; " " &0b16 00 00 00 fa 00 ; "!" &0b1b 00 e0 00 e0 00 ; """ &0b20 28 fe 28 fe 28 ; "#" &0b25 48 54 fe 54 24 ; "$" &0b2a 46 26 10 c8 c4 ; "%" &0b2f 0a 64 9a 92 6c ; "&" &0b34 00 80 40 20 00 ; "'" &0b39 00 82 44 38 00 ; "(" &0b3e 00 38 44 82 00 ; ")" &0b43 28 38 7c 38 28 ; "*" &0b48 10 10 7c 10 10 ; "+" &0b4d 00 06 07 01 00 ; "," &0b52 10 10 10 10 10 ; "-" &0b57 00 00 06 06 00 ; "." &0b5c 40 20 10 08 04 ; "/" &0b61 7c a2 92 8a 7c ; "0" &0b66 00 02 fe 42 00 ; "1" &0b6b 42 a2 92 8a 46 ; "2" &0b70 6c 92 92 82 44 ; "3" &0b75 10 fe 90 50 30 ; "4" &0b7a 9c a2 a2 a2 e4 ; "5" &0b7f 4c 92 92 92 7c ; "6" &0b84 c0 a0 90 8e 80 ; "7" &0b89 6c 92 92 92 6c ; "8" &0b8e 7c 92 92 92 64 ; "9" &0b93 00 66 66 00 00 ; ":" &0b98 00 66 67 01 00 ; ";" &0b9d 00 82 44 28 10 ; "<" &0ba2 28 28 28 28 28 ; "=" &0ba7 00 10 28 44 82 ; ">" &0bac 40 a0 9a 80 40 ; "?" &0bb1 78 aa ba 82 7c ; "@" &0bb6 7e 90 90 90 7e ; "A" &0bbb 6c 92 92 92 fe ; "B" &0bc0 44 82 82 82 7c ; "C" &0bc5 38 44 82 82 fe ; "D" &0bca 82 92 92 92 fe ; "E" &0bcf 80 90 90 90 fe ; "F" &0bd4 5c 92 82 82 7c ; "G" &0bd9 fe 10 10 10 fe ; "H" &0bde 82 82 fe 82 82 ; "I" &0be3 80 fc 82 82 04 ; "J" &0be8 82 44 28 10 fe ; "K" &0bed 02 02 02 02 fe ; "L" &0bf2 fe 40 30 40 fe ; "M" &0bf7 fe 0c 38 60 fe ; "N" &0bfc 7c 82 82 82 7c ; "O" &0c01 60 90 90 90 fe ; "P" &0c06 7a 84 8a 82 7c ; "Q" &0c0b 66 98 90 90 fe ; "R" &0c10 4c 92 92 92 64 ; "S" &0c15 80 80 fe 80 80 ; "T" &0c1a fc 02 02 02 fc ; "U" &0c1f f0 0c 02 0c f0 ; "V" &0c24 fe 04 18 04 fe ; "W" &0c29 c6 28 10 28 c6 ; "X" &0c2e e0 10 0e 10 e0 ; "Y" &0c33 c2 a2 92 8a 86 ; "Z" &0c38 00 82 82 82 fe ; "[" &0c3d 04 08 10 20 40 ; "\" &0c42 fe 82 82 82 00 ; "]" &0c47 20 40 fe 40 20 ; "^" &0c4c 01 01 01 01 01 ; "_" &0c51 42 92 92 7e 12 ; "`" &0c56 1e 2a 2a 2a 04 ; "a" &0c5b 1c 22 22 22 fe ; "b" &0c60 14 22 22 22 1c ; "c" &0c65 fe 22 22 22 1c ; "d" &0c6a 18 2a 2a 2a 1c ; "e" &0c6f 80 90 7e 10 00 ; "f" &0c74 1e 25 25 25 19 ; "g" &0c79 1e 20 20 20 fe ; "h" &0c7e 00 02 be 22 00 ; "i" &0c83 00 00 be 21 01 ; "j" &0c88 00 22 14 08 fe ; "k" &0c8d 00 02 fe 82 00 ; "l" &0c92 1e 30 18 30 1e ; "m" &0c97 1e 20 20 10 3e ; "n" &0c9c 1c 22 22 22 1c ; "o" &0ca1 18 24 24 24 3f ; "p" &0ca6 1f 24 24 24 18 ; "q" &0cab 20 20 10 3e 20 ; "r" &0cb0 24 2a 2a 2a 12 ; "s" &0cb5 00 22 22 fc 20 ; "t" &0cba 3e 02 02 02 3c ; "u" &0cbf 38 04 02 04 38 ; "v" &0cc4 3c 06 0c 06 3c ; "w" &0cc9 22 14 08 14 22 ; "x" &0cce 3e 05 05 05 39 ; "y" &0cd3 22 32 2a 26 22 ; "z" &0cd8 00 00 82 6c 10 ; "{" &0cdd 00 00 ee 00 00 ; "|" &0ce2 00 10 6c 82 00 ; "}" &0ce7 40 20 40 80 40 ; "~" # &54e2 - &552c is moved to &0716 - &0760 at &4574 ; angles_to_x_velocities_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 # 19 &0716 00 01 01 02 02 02 02 02 02 02 01 01 00 ff ff fe fe fe fe fe fe fe ff ff 00 # 03 ; angles_to_y_velocities_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 # 19 &072f 03 03 02 03 02 01 00 ff fe fd fe fd fd fd fe fd fe ff 00 01 02 03 02 03 00 # 00 ; angles_to_sprite_rotations_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 # 19 &0748 00 01 01 01 02 02 03 04 05 05 05 05 06 07 07 07 08 08 09 0a 0b 0b 0b 0b 03 # 11 from &0761 # &552d - &5b2c is moved to &0d01 - &1300 at &45d7 # &5b2d - &5b6c is moved to &1301 - &1340 at &4600 ; calculate_screen_address &0d01 a9 00 LDA #&00 &0d03 85 03 STA &03 ; screen_address_high &0d05 a9 7f LDA #&7f &0d07 38 SEC &0d08 e5 01 SBC &01 ; sprite_y &0d0a 0a ASL A &0d0b 09 01 ORA #&01 &0d0d aa TAX &0d0e 29 07 AND #&07 &0d10 85 15 STA &15 ; row_in_group &0d12 8a TXA &0d13 29 f8 AND #&f8 &0d15 85 02 STA &02 ; screen_address_low &0d17 0a ASL A &0d18 26 03 ROL &03 ; screen_address_high &0d1a 0a ASL A &0d1b 26 03 ROL &03 ; screen_address_high &0d1d 65 02 ADC &02 ; screen_address_low &0d1f 90 02 BCC &0d23 ; skip_page &0d21 e6 03 INC &03 ; screen_address_high ; skip_page &0d23 0a ASL A &0d24 26 03 ROL &03 ; screen_address_high &0d26 65 00 ADC &00 ; sprite_x &0d28 90 02 BCC &0d2c ; skip_page &0d2a e6 03 INC &03 ; screen_address_high ; skip_page &0d2c 0a ASL A &0d2d 26 03 ROL &03 ; screen_address_high &0d2f 0a ASL A &0d30 26 03 ROL &03 ; screen_address_high &0d32 0a ASL A &0d33 26 03 ROL &03 ; screen_address_high &0d35 05 15 ORA &15 ; row_in_group &0d37 69 00 ADC #&00 ; &3000 = screen_memory &0d39 aa TAX &0d3a a5 03 LDA &03 ; screen_address_high &0d3c 69 30 ADC #&30 &0d3e a8 TAY &0d3f 8a TXA &0d40 38 SEC &0d41 e5 07 SBC &07 ; sprite_height &0d43 b0 01 BCS &0d46 ; skip_page &0d45 88 DEY ; skip_page &0d46 aa TAX &0d47 24 00 BIT &00 ; sprite_x &0d49 10 05 BPL &0d50 ; x_not_negative &0d4b 98 TYA &0d4c 38 SEC &0d4d e9 08 SBC #&08 # Subtract &800, i.e. 256 * 8 &0d4f a8 TAY ; x_not_negative &0d50 24 01 BIT &01 ; sprite_y &0d52 10 05 BPL &0d59 ; y_not_negative &0d54 98 TYA &0d55 18 CLC &0d56 69 50 ADC #&50 # Add &5000 &0d58 a8 TAY ; y_not_negative &0d59 86 0c STX &0c ; sprite_screen_address_low &0d5b 84 0d STY &0d ; sprite_screen_address_high &0d5d 86 02 STX &02 ; screen_address_low &0d5f 84 03 STY &03 ; screen_address_high &0d61 60 RTS # Leave with X = address low, Y = address high ; calculate_text_screen_address &0d62 86 00 STX &00 ; sprite_x &0d64 98 TYA &0d65 29 fc AND #&fc &0d67 85 01 STA &01 ; sprite_y &0d69 a9 07 LDA #&07 &0d6b 85 07 STA &07 ; sprite_height &0d6d 20 01 0d JSR &0d01 ; calculate_screen_address # Returns X = address low, Y = address high &0d70 a5 02 LDA &02 ; screen_address_low &0d72 85 81 STA &81 ; text_screen_address_low &0d74 a5 03 LDA &03 ; screen_address_high &0d76 85 82 STA &82 ; text_screen_address_high &0d78 60 RTS ; plot_character &0d79 48 PHA ; tmp_a &0d7a 38 SEC &0d7b e9 20 SBC #&20 &0d7d 85 84 STA &84 ; font_address_low &0d7f 8a TXA &0d80 48 PHA ; tmp_x &0d81 98 TYA &0d82 48 PHA ; tmp_y &0d83 a2 00 LDX #&00 &0d85 8a TXA &0d86 a0 05 LDY #&05 ; calculate_font_address_loop # Character X data starts at &0b11 + ((X - &20) * 5) &0d88 18 CLC &0d89 65 84 ADC &84 ; font_address_low &0d8b 90 01 BCC &0d8e ; skip_overflow &0d8d e8 INX ; skip_overflow &0d8e 88 DEY &0d8f d0 f7 BNE &0d88 ; calculate_font_address_loop &0d91 18 CLC &0d92 69 11 ADC #&11 ; &0b11 = font_data &0d94 85 84 STA &84 ; font_address_low &0d96 8a TXA &0d97 69 0b ADC #&0b &0d99 85 85 STA &85 ; font_address_high &0d9b a9 04 LDA #&04 &0d9d 85 88 STA &88 ; columns_remaining ; plot_character_column_loop # For each pair of columns in the character, &0d9f a0 00 LDY #&00 ; plot_character_row_loop # For each row in the column, &0da1 84 89 STY &89 ; row &0da3 b9 e9 0d LDA &0de9,Y ; descending_bits &0da6 85 86 STA &86 ; bit &0da8 a2 00 LDX #&00 &0daa a9 aa LDA #&aa ; F0 # Set left pixel &0dac a4 88 LDY &88 ; columns_remaining ; plot_character_pixel_loop # For each pixel in the byte, &0dae 85 87 STA &87 ; pixel_value &0db0 b1 84 LDA (&84),Y ; font_address &0db2 25 86 AND &86 ; bit &0db4 f0 04 BEQ &0dba ; skip_setting_pixel &0db6 8a TXA &0db7 05 87 ORA &87 ; pixel_value &0db9 aa TAX ; skip_setting_pixel &0dba 88 DEY &0dbb 30 06 BMI &0dc3 ; is_second_pixel ; is_first_pixel &0dbd 98 TYA &0dbe 4a LSR A &0dbf a9 55 LDA #&55 ; 0F # Set right pixel &0dc1 b0 eb BCS &0dae ; plot_character_pixel_loop ; is_second_pixel &0dc3 a4 89 LDY &89 ; row &0dc5 8a TXA &0dc6 25 83 AND &83 ; text_colour_mask &0dc8 51 81 EOR (&81),Y ; text_screen_address &0dca 91 81 STA (&81),Y ; text_screen_address &0dcc e6 89 INC &89 ; row &0dce c8 INY &0dcf c0 08 CPY #&08 &0dd1 90 ce BCC &0da1 ; plot_character_row_loop &0dd3 a5 81 LDA &81 ; text_screen_address_low &0dd5 69 07 ADC #&07 # Move right two pixels; carry is set, so add 8 &0dd7 85 81 STA &81 ; text_screen_address_low &0dd9 90 02 BCC &0ddd ; skip_page &0ddb e6 82 INC &82 ; text_screen_address_high ; skip_page &0ddd c6 88 DEC &88 ; columns_remaining &0ddf c6 88 DEC &88 ; columns_remaining &0de1 10 bc BPL &0d9f ; plot_character_column_loop &0de3 68 PLA ; tmp_y &0de4 a8 TAY &0de5 68 PLA ; tmp_x &0de6 aa TAX &0de7 68 PLA ; tmp_a &0de8 60 RTS ; descending_bits &0de9 80 40 20 10 08 04 02 01 ; move_up_a_group &0df1 a5 0c LDA &0c ; sprite_screen_address_low &0df3 38 SEC &0df4 e9 78 SBC #&78 &0df6 85 0c STA &0c ; sprite_screen_address_low &0df8 a5 0d LDA &0d ; sprite_screen_address_high &0dfa e9 02 SBC #&02 &0dfc 85 0d STA &0d ; sprite_screen_address_high &0dfe 98 TYA &0dff 18 CLC &0e00 65 0c ADC &0c ; sprite_screen_address_low &0e02 a5 0d LDA &0d ; sprite_screen_address_high &0e04 69 00 ADC #&00 &0e06 c9 30 CMP #&30 # Leave with carry set if not above top of screen &0e08 60 RTS ; wait_for_v_sync &0e09 20 11 0e JSR &0e11 ; check_if_same_frame &0e0c f0 fb BEQ &0e09 ; wait_for_v_sync &0e0e 85 52 STA &52 ; previous_frame_counter &0e10 60 RTS ; check_if_same_frame &0e11 a5 53 LDA &53 ; frame_counter &0e13 24 8c BIT &8c ; mos_version_flag # Positive if MOS 0.10 &0e15 30 04 BMI &0e1b ; not_mos_0.10 &0e17 a5 f9 LDA &f9 ; os_vertical_sync_counter &0e19 49 ff EOR #&ff ; not_mos_0.10 &0e1b c5 52 CMP &52 ; previous_frame_counter &0e1d 60 RTS ; check_for_sound_keypresses &0e1e c6 69 DEC &69 ; key_check_cooldown &0e20 10 26 BPL &0e48 ; leave_with_zero &0e22 a9 0c LDA #&0c &0e24 85 69 STA &69 ; key_check_cooldown &0e26 a9 ef LDA #&ef ; Q &0e28 24 3b BIT &3b ; sound_muted # Negative if sound muted &0e2a 10 02 BPL &0e2e ; check_for_keypress &0e2c a9 ae LDA #&ae ; S ; check_for_keypress &0e2e 85 14 STA &14 ; keycode &0e30 8a TXA &0e31 48 PHA ; tmp_x &0e32 98 TYA &0e33 48 PHA ; tmp_y &0e34 a6 14 LDX &14 ; keycode &0e36 a0 ff LDY #&ff &0e38 a9 81 LDA #&81 ; Scan for a particular key &0e3a 20 f4 ff JSR &fff4 ; OSBYTE &0e3d 68 PLA ; tmp_y &0e3e a8 TAY &0e3f 68 PLA ; tmp_x &0e40 e0 00 CPX #&00 &0e42 08 PHP ; key pressed &0e43 aa TAX &0e44 a5 14 LDA &14 ; keycode &0e46 28 PLP ; key pressed &0e47 60 RTS ; leave_with_zero &0e48 a9 00 LDA #&00 &0e4a 60 RTS ; check_for_keyboard_or_joystick_keys &0e4b a5 69 LDA &69 ; key_check_cooldown &0e4d d0 f9 BNE &0e48 ; leave_with_zero &0e4f a9 b9 LDA #&b9 ; K &0e51 24 70 BIT &70 ; keyboard_or_joystick # Positive for keyboard, negative for joystick &0e53 30 d9 BMI &0e2e ; check_for_keypress &0e55 a9 ba LDA #&ba ; J &0e57 d0 d5 BNE &0e2e ; check_for_keypress # Always branches ; check_for_number_of_players_keys &0e59 a5 69 LDA &69 ; key_check_cooldown &0e5b d0 eb BNE &0e48 ; leave_with_zero &0e5d a9 cf LDA #&cf ; 1 &0e5f 24 3c BIT &3c ; one_or_two_players # Negative if two player game &0e61 30 cb BMI &0e2e ; check_for_keypress &0e63 a9 ce LDA #&ce ; 2 &0e65 d0 c7 BNE &0e2e ; check_for_keypress # Always branches ; event_handler &0e67 e6 53 INC &53 ; frame_counter &0e69 60 RTS ; consider_updating_palette &0e6a c6 1d DEC &1d ; palette_change_cooldown &0e6c f0 01 BEQ &0e6f ; update_palette &0e6e 60 RTS ; update_palette &0e6f a0 08 LDY #&08 &0e71 a6 1e LDX &1e ; palette_state &0e73 8a TXA &0e74 49 08 EOR #&08 &0e76 85 1e STA &1e ; palette_state ; update_palette_loop &0e78 bd 87 0e LDA &0e87,X ; palette_values &0e7b 8d 21 fe STA &fe21 ; video ULA palette register &0e7e ca DEX &0e7f 88 DEY &0e80 d0 f6 BNE &0e78 ; update_palette_loop &0e82 a9 14 LDA #&14 # Alternate colours every 20 frames &0e84 85 1d STA &1d ; palette_change_cooldown &0e86 60 RTS ; palette_values ; 8 9 10 11 12 13 14 15 &0e87 86 93 a7 b4 c7 d4 e1 f3 ; R B K Y K Y C B &0e8f 87 97 a3 b7 c4 d7 e3 f1 ; K K B K Y K B C ; rnd &0e97 ad 44 fe LDA &fe44 ; System VIA timer 1 counter LSB &0e99 45 52 EOR &52 ; previous_frame_counter &0e9c 45 16 EOR &16 ; player_x &0e9e 60 RTS ; unused_rnd # Unused code &0e9f 0a ASL A &0ea0 0a ASL A &0ea1 26 4c ROL &4c ; unused_rnd_state + 2 &0ea3 26 4b ROL &4b ; unused_rnd_state + 1 &0ea5 26 4a ROL &4a ; unused_rnd_state &0ea7 a5 4a LDA &4a ; unused_rnd_state &0ea9 45 52 EOR &52 ; previous_frame_counter &0eab 60 RTS ; unused # Unused code &0eac 68 PLA &0ead aa TAX &0eae 60 RTS ; plot_sprite_at_X_Y &0eaf 84 01 STY &01 ; sprite_y &0eb1 a8 TAY &0eb2 86 00 STX &00 ; sprite_x &0eb4 8a TXA &0eb5 48 PHA ; tmp_x &0eb6 20 be 0e JSR &0ebe ; plot_sprite &0eb9 68 PLA ; tmp_x &0eba aa TAX &0ebb a4 01 LDY &01 ; sprite_y &0ebd 60 RTS ; plot_sprite &0ebe 98 TYA &0ebf 48 PHA ; tmp_y # Bug: restored into X at &0f60 ; plot_sprite_calculate_sprite_address_and_sizes &0ec0 20 ff ff JSR &ffff # actually JSR &2623 ; calculate_sprite_address_and_sizes &0ec3 20 01 0d JSR &0d01 ; calculate_screen_address # Returns X = address low, Y = address high &0ec6 4c 11 0f JMP &0f11 ; plot_or_unplot_sprite ; plot_enemy &0ec9 a9 ff LDA #&ff # Set bottom bit to calculate new screen address &0ecb dc a9 00 NOP &00a9,X ; unplot_enemy #0ecc LDA #&00 # Clear bottom bit to use previous screen address &0ece 85 14 STA &14 ; use_or_set &0ed0 8a TXA &0ed1 48 PHA ; enemy slot &0ed2 bd 00 04 LDA &0400,X ; enemies_x &0ed5 85 00 STA &00 ; sprite_x &0ed7 bd 49 04 LDA &0449,X ; enemies_y &0eda 85 01 STA &01 ; sprite_y &0edc bc 92 04 LDY &0492,X ; enemies_sprite ; plot_enemy_calculate_sprite_address_and_sizes &0edf 20 ff ff JSR &ffff # actually JSR &2623 ; calculate_sprite_address_and_sizes &0ee2 46 14 LSR &14 ; use_or_set &0ee4 b0 1b BCS &0f01 ; calculate_and_set_enemy_screen_address &0ee6 bd db 04 LDA &04db,X ; enemies_screen_address_high &0ee9 f0 16 BEQ &0f01 ; calculate_and_set_enemy_screen_address &0eeb c9 ff CMP #&ff &0eed f0 12 BEQ &0f01 ; calculate_and_set_enemy_screen_address ; use_previous_enemy_screen_address &0eef 85 03 STA &03 ; screen_address_high &0ef1 85 0d STA &0d ; sprite_screen_address_high &0ef3 a9 00 LDA #&00 &0ef5 9d db 04 STA &04db,X ; enemies_screen_address_high # Set to zero to indicate enemy has been unplotted &0ef8 bd 24 05 LDA &0524,X ; enemies_screen_address_low &0efb 85 02 STA &02 ; screen_address_low &0efd 85 0c STA &0c ; sprite_screen_address_low &0eff 90 10 BCC &0f11 ; plot_or_unplot_sprite # Always branches ; calculate_and_set_enemy_screen_address &0f01 20 01 0d JSR &0d01 ; calculate_screen_address # Returns X = address low, Y = address high &0f04 68 PLA ; enemy slot &0f05 48 PHA ; enemy slot &0f06 aa TAX &0f07 a5 02 LDA &02 ; screen_address_low &0f09 9d 24 05 STA &0524,X ; enemies_screen_address_low &0f0c a5 03 LDA &03 ; screen_address_high &0f0e 9d db 04 STA &04db,X ; enemies_screen_address_high ; plot_or_unplot_sprite &0f11 a5 01 LDA &01 ; sprite_y &0f13 29 03 AND #&03 &0f15 05 1c ORA &1c ; sprite_flip &0f17 29 0f AND #&0f &0f19 aa TAX &0f1a bd b2 11 LDA &11b2,X ; plot_column_routine_addresses_low_table &0f1d 85 1a STA &1a ; plot_column_routine_address_low &0f1f bd c2 11 LDA &11c2,X ; plot_column_routine_addresses_high_table &0f22 85 1b STA &1b ; plot_column_routine_address_high &0f24 a5 04 LDA &04 ; sprite_address_low &0f26 d0 02 BNE &0f2a ; skip_page &0f28 c6 05 DEC &05 ; sprite_address_high ; skip_page &0f2a c6 04 DEC &04 ; sprite_address_low &0f2c a2 55 LDX #&55 ; 0F # Used in SAXes to extract right pixels from pairs &0f2e a5 1c LDA &1c ; sprite_flip &0f30 29 08 AND #&08 ; FLIP_HORIZONTALLY &0f32 d0 2f BNE &0f63 ; plot_horizontally_flipped_sprite_loop ; plot_horizonally_unflipped_sprite_loop &0f34 a4 07 LDY &07 ; sprite_height &0f36 a5 00 LDA &00 ; sprite_x &0f38 c9 50 CMP #&50 &0f3a b0 03 BCS &0f3f ; skip_plotting_column # Don't plot beyond left or right edges of screen &0f3c 20 91 0f JSR &0f91 ; plot_column_of_sprite ; skip_plotting_column &0f3f 18 CLC &0f40 98 TYA &0f41 65 04 ADC &04 ; sprite_address_low &0f43 85 04 STA &04 ; sprite_address_low &0f45 90 02 BCC &0f49 ; skip_page &0f47 e6 05 INC &05 ; sprite_address_high ; skip_page &0f49 a5 02 LDA &02 ; screen_address_low &0f4b 18 CLC &0f4c 69 08 ADC #&08 &0f4e 85 02 STA &02 ; screen_address_low &0f50 85 0c STA &0c ; sprite_screen_address_low &0f52 a5 03 LDA &03 ; screen_address_high &0f54 69 00 ADC #&00 &0f56 85 03 STA &03 ; screen_address_high &0f58 85 0d STA &0d ; sprite_screen_address_high &0f5a e6 00 INC &00 ; sprite_x &0f5c c6 06 DEC &06 ; sprite_width &0f5e d0 d4 BNE &0f34 ; plot_horizontally_unflipped_sprite_loop ; leave_after_restoring_x &0f60 68 PLA ; enemy slot # tmp_y if called via plot_sprite (see &0ebf) &0f61 aa TAX &0f62 60 RTS ; plot_horizontally_flipped_sprite_loop &0f63 a4 07 LDY &07 ; sprite_height &0f65 a5 00 LDA &00 ; sprite_x &0f67 c9 50 CMP #&50 &0f69 b0 03 BCS &0f6e ; skip_plotting_column # Don't plot beyond left or right edges of screen &0f6b 20 91 0f JSR &0f91 ; plot_column_of_sprite ; skip_plotting_column &0f6e 18 CLC &0f6f 98 TYA &0f70 65 04 ADC &04 ; sprite_address_low &0f72 85 04 STA &04 ; sprite_address_low &0f74 90 02 BCC &0f78 ; skip_page &0f76 e6 05 INC &05 ; sprite_address_high ; skip_page &0f78 a5 02 LDA &02 ; screen_address_low &0f7a 38 SEC &0f7b e9 08 SBC #&08 &0f7d 85 02 STA &02 ; screen_address_low &0f7f 85 0c STA &0c ; sprite_screen_address_low &0f81 a5 03 LDA &03 ; screen_address_high &0f83 e9 00 SBC #&00 &0f85 85 03 STA &03 ; screen_address_high &0f87 85 0d STA &0d ; sprite_screen_address_high &0f89 c6 00 DEC &00 ; sprite_x &0f8b c6 06 DEC &06 ; sprite_width &0f8d d0 d4 BNE &0f63 ; plot_horizontally_flipped_sprite_loop &0f8f f0 cf BEQ &0f60 ; leave_after_restoring_x # Always branches ; plot_column_of_sprite &0f91 6c 1a 00 JMP (&001a) ; plot_column_routine_address ; plot_horizontally_unflipped_vertically_unflipped_rows_7_and_6 # Plot regular column &0f94 b1 04 LDA (&04),Y ; sprite_address &0f96 51 0c EOR (&0c),Y ; sprite_screen_address &0f98 91 0c STA (&0c),Y ; sprite_screen_address # Plot eighth row of group &0f9a 88 DEY &0f9b f0 44 BEQ &0fe1 ; leave_with_sprite_height &0f9d b1 04 LDA (&04),Y ; sprite_address &0f9f 51 0c EOR (&0c),Y ; sprite_screen_address &0fa1 91 0c STA (&0c),Y ; sprite_screen_address # Plot seventh row of group &0fa3 88 DEY &0fa4 f0 3b BEQ &0fe1 ; leave_with_sprite_height ; plot_horizontally_unflipped_vertically_unflipped_rows_5_and_4 &0fa6 b1 04 LDA (&04),Y ; sprite_address &0fa8 51 0c EOR (&0c),Y ; sprite_screen_address &0faa 91 0c STA (&0c),Y ; sprite_screen_address # Plot sixth row of group &0fac 88 DEY &0fad f0 32 BEQ &0fe1 ; leave_with_sprite_height &0faf b1 04 LDA (&04),Y ; sprite_address &0fb1 51 0c EOR (&0c),Y ; sprite_screen_address &0fb3 91 0c STA (&0c),Y ; sprite_screen_address # Plot fifth row of group &0fb5 88 DEY &0fb6 f0 29 BEQ &0fe1 ; leave_with_sprite_height ; plot_horizontally_unflipped_vertically_unflipped_rows_3_and_2 &0fb8 b1 04 LDA (&04),Y ; sprite_address &0fba 51 0c EOR (&0c),Y ; sprite_screen_address &0fbc 91 0c STA (&0c),Y ; sprite_screen_address # Plot fourth row of group &0fbe 88 DEY &0fbf f0 20 BEQ &0fe1 ; leave_with_sprite_height &0fc1 b1 04 LDA (&04),Y ; sprite_address &0fc3 51 0c EOR (&0c),Y ; sprite_screen_address &0fc5 91 0c STA (&0c),Y ; sprite_screen_address # Plot third row of group &0fc7 88 DEY &0fc8 f0 17 BEQ &0fe1 ; leave_with_sprite_height ; plot_horizontally_unflipped_vertically_unflipped_rows_1_and_0 &0fca b1 04 LDA (&04),Y ; sprite_address &0fcc 51 0c EOR (&0c),Y ; sprite_screen_address &0fce 91 0c STA (&0c),Y ; sprite_screen_address # Plot second row of group &0fd0 88 DEY &0fd1 f0 0e BEQ &0fe1 ; leave_with_sprite_height &0fd3 b1 04 LDA (&04),Y ; sprite_address &0fd5 51 0c EOR (&0c),Y ; sprite_screen_address &0fd7 91 0c STA (&0c),Y ; sprite_screen_address # Plot first row of group &0fd9 88 DEY &0fda f0 05 BEQ &0fe1 ; leave_with_sprite_height &0fdc 20 f1 0d JSR &0df1 ; move_up_a_group # Returns carry set if not above top of screen &0fdf b0 b3 BCS &0f94 ; plot_horizontally_unflipped_vertically_unflipped_rows_7_and_6 ; leave_with_sprite_height &0fe1 a4 07 LDY &07 ; sprite_height ; leave &0fe3 60 RTS ; plot_horizontally_unflipped_vertically_flipped_rows_7_and_6 # Plot vertically flipped column &0fe4 e6 04 INC &04 ; sprite_address_low &0fe6 f0 6a BEQ &1052 ; next_page_unflipped_7 ; from_next_page_unflipped_7 &0fe8 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &0fea 51 0c EOR (&0c),Y ; sprite_screen_address &0fec 91 0c STA (&0c),Y ; sprite_screen_address # Plot eighth row of group &0fee 88 DEY &0fef f0 f2 BEQ &0fe3 ; leave &0ff1 e6 04 INC &04 ; sprite_address_low &0ff3 f0 61 BEQ &1056 ; next_page_unflipped_6 ; from_next_page_unflipped_6 &0ff5 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &0ff7 51 0c EOR (&0c),Y ; sprite_screen_address &0ff9 91 0c STA (&0c),Y ; sprite_screen_address # Plot seventh row of group &0ffb 88 DEY &0ffc f0 e5 BEQ &0fe3 ; leave ; plot_horizontally_unflipped_vertically_flipped_rows_5_and_4 &0ffe e6 04 INC &04 ; sprite_address_low &1000 f0 58 BEQ &105a ; next_page_unflipped_5 ; from_next_page_unflipped_5 &1002 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1004 51 0c EOR (&0c),Y ; sprite_screen_address &1006 91 0c STA (&0c),Y ; sprite_screen_address # Plot sixth row of group &1008 88 DEY &1009 f0 d8 BEQ &0fe3 ; leave &100b e6 04 INC &04 ; sprite_address_low &100d f0 4f BEQ &105e ; next_page_unflipped_4 ; from_next_page_unflipped_4 &100f a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1011 51 0c EOR (&0c),Y ; sprite_screen_address &1013 91 0c STA (&0c),Y ; sprite_screen_address # Plot fifth row of group &1015 88 DEY &1016 f0 cb BEQ &0fe3 ; leave ; plot_horizontally_unflipped_vertically_flipped_rows_3_and_2 &1018 e6 04 INC &04 ; sprite_address_low &101a f0 46 BEQ &1062 ; next_page_unflipped_3 ; from_next_page_unflipped_3 &101c a1 af LDA (&af,X) ; sprite_address - &55 + &100 &101e 51 0c EOR (&0c),Y ; sprite_screen_address &1020 91 0c STA (&0c),Y ; sprite_screen_address # Plot fourth row of group &1022 88 DEY &1023 f0 be BEQ &0fe3 ; leave &1025 e6 04 INC &04 ; sprite_address_low &1027 f0 3d BEQ &1066 ; next_page_unflipped_2 ; from_next_page_unflipped_2 &1029 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &102b 51 0c EOR (&0c),Y ; sprite_screen_address &102d 91 0c STA (&0c),Y ; sprite_screen_address # Plot third row of group &102f 88 DEY &1030 f0 b1 BEQ &0fe3 ; leave ; plot_horizontally_unflipped_vertically_flipped_rows_1_and_0 &1032 e6 04 INC &04 ; sprite_address_low &1034 f0 34 BEQ &106a ; next_page_unflipped_1 ; from_next_page_unflipped_1 &1036 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1038 51 0c EOR (&0c),Y ; sprite_screen_address &103a 91 0c STA (&0c),Y ; sprite_screen_address # Plot second row of group &103c 88 DEY &103d f0 a4 BEQ &0fe3 ; leave &103f e6 04 INC &04 ; sprite_address_low &1041 f0 2b BEQ &106e ; next_page_unflipped_0 ; from_next_page_unflipped_0 &1043 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1045 51 0c EOR (&0c),Y ; sprite_screen_address &1047 91 0c STA (&0c),Y ; sprite_screen_address # Plot first row of group &1049 88 DEY &104a f0 97 BEQ &0fe3 ; leave &104c 20 f1 0d JSR &0df1 ; move_up_a_group # Returns carry set if not above top of screen &104f b0 93 BCS &0fe4 ; plot_horizontally_unflipped_vertically_flipped_rows_7_and_6 &1051 60 RTS ; next_page_unflipped_7 &1052 e6 05 INC &05 ; sprite_address_high &1054 d0 92 BNE &0fe8 ; from_next_page_unflipped_7 # Always branches ; next_page_unflipped_6 &1056 e6 05 INC &05 ; sprite_address_high &1058 d0 9b BNE &0ff5 ; from_next_page_unflipped_6 # Always branches ; next_page_unflipped_5 &105a e6 05 INC &05 ; sprite_address_high &105c d0 a4 BNE &1002 ; from_next_page_unflipped_5 # Always branches ; next_page_unflipped_4 &105e e6 05 INC &05 ; sprite_address_high &1060 d0 ad BNE &100f ; from_next_page_unflipped_4 # Always branches ; next_page_unflipped_3 &1062 e6 05 INC &05 ; sprite_address_high &1064 d0 b6 BNE &101c ; from_next_page_unflipped_3 # Always branches ; next_page_unflipped_2 &1066 e6 05 INC &05 ; sprite_address_high &1068 d0 bf BNE &1029 ; from_next_page_unflipped_2 # Always branches ; next_page_unflipped_1 &106a e6 05 INC &05 ; sprite_address_high &106c d0 c8 BNE &1036 ; from_next_page_unflipped_1 # Always branches ; next_page_unflipped_0 &106e e6 05 INC &05 ; sprite_address_high &1070 d0 d1 BNE &1043 ; from_next_page_unflipped_0 # Always branches ; plot_horizontally_flipped_vertically_unflipped_rows_7_and_6 # Plot horizontally flipped column &1072 b1 04 LDA (&04),Y ; sprite_address &1074 87 80 SAX &80 ; tmp &1076 4b aa ALR #&aa ; F0 &1078 07 80 SLO &80 ; tmp &107a 51 0c EOR (&0c),Y ; sprite_screen_address &107c 91 0c STA (&0c),Y ; sprite_screen_address # Plot eighth row of group &107e 88 DEY &107f f0 6e BEQ &10ef ; leave_with_sprite_height &1081 b1 04 LDA (&04),Y ; sprite_address &1083 87 80 SAX &80 ; tmp &1085 4b aa ALR #&aa ; F0 &1087 07 80 SLO &80 ; tmp &1089 51 0c EOR (&0c),Y ; sprite_screen_address &108b 91 0c STA (&0c),Y ; sprite_screen_address # Plot seventh row of group &108d 88 DEY &108e f0 5f BEQ &10ef ; leave_with_sprite_height ; plot_horizontally_flipped_vertically_unflipped_rows_5_and_4 &1090 b1 04 LDA (&04),Y ; sprite_address &1092 87 80 SAX &80 ; tmp &1094 4b aa ALR #&aa ; F0 &1096 07 80 SLO &80 ; tmp &1098 51 0c EOR (&0c),Y ; sprite_screen_address &109a 91 0c STA (&0c),Y ; sprite_screen_address # Plot sixth row of group &109c 88 DEY &109d f0 50 BEQ &10ef ; leave_with_sprite_height &109f b1 04 LDA (&04),Y ; sprite_address &10a1 87 80 SAX &80 ; tmp &10a3 4b aa ALR #&aa ; F0 &10a5 07 80 SLO &80 ; tmp &10a7 51 0c EOR (&0c),Y ; sprite_screen_address &10a9 91 0c STA (&0c),Y ; sprite_screen_address # Plot fifth row of group &10ab 88 DEY &10ac f0 41 BEQ &10ef ; leave_with_sprite_height ; plot_horizontally_flipped_vertically_unflipped_rows_3_and_2 &10ae b1 04 LDA (&04),Y ; sprite_address &10b0 87 80 SAX &80 ; tmp &10b2 4b aa ALR #&aa ; F0 &10b4 07 80 SLO &80 ; tmp &10b6 51 0c EOR (&0c),Y ; sprite_screen_address &10b8 91 0c STA (&0c),Y ; sprite_screen_address # Plot fourth row of group &10ba 88 DEY &10bb f0 32 BEQ &10ef ; leave_with_sprite_height &10bd b1 04 LDA (&04),Y ; sprite_address &10bf 87 80 SAX &80 ; tmp &10c1 4b aa ALR #&aa ; F0 &10c3 07 80 SLO &80 ; tmp &10c5 51 0c EOR (&0c),Y ; sprite_screen_address &10c7 91 0c STA (&0c),Y ; sprite_screen_address # Plot third row of group &10c9 88 DEY &10ca f0 23 BEQ &10ef ; leave_with_sprite_height ; plot_horizontally_flipped_vertically_unflipped_rows_1_and_0 &10cc b1 04 LDA (&04),Y ; sprite_address &10ce 87 80 SAX &80 ; tmp &10d0 4b aa ALR #&aa ; F0 &10d2 07 80 SLO &80 ; tmp &10d4 51 0c EOR (&0c),Y ; sprite_screen_address &10d6 91 0c STA (&0c),Y ; sprite_screen_address # Plot second row of group &10d8 88 DEY &10d9 f0 14 BEQ &10ef ; leave_with_sprite_height &10db b1 04 LDA (&04),Y ; sprite_address &10dd 87 80 SAX &80 ; tmp &10df 4b aa ALR #&aa ; F0 &10e1 07 80 SLO &80 ; tmp &10e3 51 0c EOR (&0c),Y ; sprite_screen_address &10e5 91 0c STA (&0c),Y ; sprite_screen_address # Plot first row of group &10e7 88 DEY &10e8 f0 05 BEQ &10ef ; leave_with_sprite_height &10ea 20 f1 0d JSR &0df1 ; move_up_a_group # Returns carry set if not above top of screen &10ed b0 83 BCS &1072 ; plot_horizontally_flipped_vertically_unflipped_rows_7_and_6 ; leave_with_sprite_height &10ef a4 07 LDY &07 ; sprite_height &10f1 60 RTS ; next_page_flipped_7 &10f2 e6 05 INC &05 ; sprite_address_high &10f4 d0 1c BNE &1112 ; from_next_page_flipped_7 # Always branches ; next_page_flipped_6 &10f6 e6 05 INC &05 ; sprite_address_high &10f8 d0 2c BNE &1126 ; from_next_page_flipped_6 # Always branches ; next_page_flipped_5 &10fa e6 05 INC &05 ; sprite_address_high &10fc d0 3b BNE &1139 ; from_next_page_flipped_5 # Always branches ; next_page_flipped_4 &10fe e6 05 INC &05 ; sprite_address_high &1100 d0 4a BNE &114c ; from_next_page_flipped_4 # Always branches ; next_page_flipped_3 &1102 e6 05 INC &05 ; sprite_address_high &1104 d0 59 BNE &115f ; from_next_page_flipped_3 # Always branches ; next_page_flipped_2 &1106 e6 05 INC &05 ; sprite_address_high &1108 d0 68 BNE &1172 ; from_next_page_flipped_2 # Always branches ; next_page_flipped_1 &110a e6 05 INC &05 ; sprite_address_high &110c d0 77 BNE &1185 ; from_next_page_flipped_1 # Always branches ; plot_horizontally_flipped_vertically_flipped_rows_7_and_6 # Plot vertically and horizontally flipped column &110e e6 04 INC &04 ; sprite_address_low &1110 f0 e0 BEQ &10f2 ; next_page_flipped_7 ; from_next_page_flipped_7 &1112 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1114 87 80 SAX &80 ; tmp &1116 4b aa ALR #&aa ; F0 &1118 07 80 SLO &80 ; tmp &111a 51 0c EOR (&0c),Y ; sprite_screen_address &111c 91 0c STA (&0c),Y ; sprite_screen_address # Plot eighth row of group &111e 88 DEY &111f d0 01 BNE &1122 ; continue &1121 60 RTS ; continue &1122 e6 04 INC &04 ; sprite_address_low &1124 f0 d0 BEQ &10f6 ; next_page_flipped_7 ; from_next_page_flipped_7 &1126 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1128 87 80 SAX &80 ; tmp &112a 4b aa ALR #&aa ; F0 &112c 07 80 SLO &80 ; tmp &112e 51 0c EOR (&0c),Y ; sprite_screen_address &1130 91 0c STA (&0c),Y ; sprite_screen_address # Plot seventh row of group &1132 88 DEY &1133 f0 79 BEQ &11ae ; leave ; plot_horizontally_flipped_vertically_flipped_rows_5_and_4 &1135 e6 04 INC &04 ; sprite_address_low &1137 f0 c1 BEQ &10fa ; next_page_flipped_7 ; from_next_page_flipped_7 &1139 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &113b 87 80 SAX &80 ; tmp &113d 4b aa ALR #&aa ; F0 &113f 07 80 SLO &80 ; tmp &1141 51 0c EOR (&0c),Y ; sprite_screen_address &1143 91 0c STA (&0c),Y ; sprite_screen_address # Plot sixth row of group &1145 88 DEY &1146 f0 66 BEQ &11ae ; leave &1148 e6 04 INC &04 ; sprite_address_low &114a f0 b2 BEQ &10fe ; next_page_flipped_7 ; from_next_page_flipped_7 &114c a1 af LDA (&af,X) ; sprite_address - &55 + &100 &114e 87 80 SAX &80 ; tmp &1150 4b aa ALR #&aa ; F0 &1152 07 80 SLO &80 ; tmp &1154 51 0c EOR (&0c),Y ; sprite_screen_address &1156 91 0c STA (&0c),Y ; sprite_screen_address # Plot fifth row of group &1158 88 DEY &1159 f0 53 BEQ &11ae ; leave ; plot_horizontally_flipped_vertically_flipped_rows_3_and_2 &115b e6 04 INC &04 ; sprite_address_low &115d f0 a3 BEQ &1102 ; next_page_flipped_7 ; from_next_page_flipped_7 &115f a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1161 87 80 SAX &80 ; tmp &1163 4b aa ALR #&aa ; F0 &1165 07 80 SLO &80 ; tmp &1167 51 0c EOR (&0c),Y ; sprite_screen_address &1169 91 0c STA (&0c),Y ; sprite_screen_address # Plot fourth row of group &116b 88 DEY &116c f0 40 BEQ &11ae ; leave &116e e6 04 INC &04 ; sprite_address_low &1170 f0 94 BEQ &1106 ; next_page_flipped_7 ; from_next_page_flipped_7 &1172 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1174 87 80 SAX &80 ; tmp &1176 4b aa ALR #&aa ; F0 &1178 07 80 SLO &80 ; tmp &117a 51 0c EOR (&0c),Y ; sprite_screen_address &117c 91 0c STA (&0c),Y ; sprite_screen_address # Plot third row of group &117e 88 DEY &117f f0 2d BEQ &11ae ; leave ; plot_horizontally_flipped_vertically_flipped_rows_1_and_0 &1181 e6 04 INC &04 ; sprite_address_low &1183 f0 85 BEQ &110a ; next_page_flipped_7 ; from_next_page_flipped_7 &1185 a1 af LDA (&af,X) ; sprite_address - &55 + &100 &1187 87 80 SAX &80 ; tmp &1189 4b aa ALR #&aa ; F0 &118b 07 80 SLO &80 ; tmp &118d 51 0c EOR (&0c),Y ; sprite_screen_address &118f 91 0c STA (&0c),Y ; sprite_screen_address # Plot second row of group &1191 88 DEY &1192 f0 1a BEQ &11ae ; leave &1194 e6 04 INC &04 ; sprite_address_low &1196 d0 02 BNE &119a ; skip_page &1198 e6 05 INC &05 ; sprite_address_high ; skip_page &119a a1 af LDA (&af,X) ; sprite_address - &55 + &100 &119c 87 80 SAX &80 ; tmp &119e 4b aa ALR #&aa ; F0 &11a0 07 80 SLO &80 ; tmp &11a2 51 0c EOR (&0c),Y ; sprite_screen_address &11a4 91 0c STA (&0c),Y ; sprite_screen_address # Plot first row of group &11a6 88 DEY &11a7 f0 05 BEQ &11ae ; leave &11a9 20 f1 0d JSR &0df1 ; move_up_a_group # Returns carry set if not above top of screen &11ac b0 01 BCS &11af ; to_plot_horizontally_flipped_vertically_flipped_rows_7_and_6 ; leave &11ae 60 RTS ; to_plot_horizontally_flipped_vertically_flipped_rows_7_and_6 &11af 4c 0e 11 JMP &110e ; plot_horizontally_flipped_vertically_flipped_rows_7_and_6 ; plot_column_routine_addresses_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f ; unflipped v-flipped h-flipped v&h-flipped ; 76 54 32 01 76 54 32 01 76 54 32 01 76 54 32 01 &11b2 94 a6 b8 ca e4 fe 18 32 72 90 ae cc 0e 35 5b 81 ; plot_column_routine_addresses_high_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f ; unflipped v-flipped h-flipped v&h-flipped ; 76 54 32 01 76 54 32 01 76 54 32 01 76 54 32 01 &11c2 0f 0f 0f 0f 0f 0f 10 10 10 10 10 10 11 11 11 11 ; update_two_passive_enemies &11d2 20 d5 11 JSR &11d5 ; update_one_passive_enemy ; update_one_passive_enemy &11d5 c6 4e DEC &4e ; enemy_to_move &11d7 10 24 BPL &11fd ; skip_wraparound &11d9 a9 27 LDA #&27 ; ENEMY_SLOT_LAST_PASSIVE &11db 85 4e STA &4e ; enemy_to_move &11dd c6 51 DEC &51 ; passive_movement_cooldown &11df 10 0a BPL &11eb ; skip_toggling_passive_movement_direction &11e1 a9 07 LDA #&07 &11e3 85 51 STA &51 ; passive_movement_cooldown &11e5 a5 50 LDA &50 ; passive_movement_direction &11e7 49 ff EOR #&ff # Alternate between expanding and contracting enemies &11e9 85 50 STA &50 ; passive_movement_direction ; skip_toggling_passive_movement_direction &11eb a5 4f LDA &4f ; passive_movement_bit # One, and only one bit is set &11ed 24 50 BIT &50 ; passive_movement_direction # Positive if expanding, negative if contracting &11ef 30 06 BMI &11f7 ; rotate_right &11f1 c9 80 CMP #&80 # Replace in bottom bit if necessary &11f3 2a ROL A # Rotate set bit left &11f4 4c fb 11 JMP &11fb ; set_passive_movement_bit ; rotate_right &11f7 4a LSR A # Rotate set bit right &11f8 90 01 BCC &11fb ; set_passive_movement_bit &11fa 6a ROR A # Replace in top bit ; set_passive_movement_bit &11fb 85 4f STA &4f ; passive_movement_bit ; skip_wraparound &11fd a6 4e LDX &4e ; enemy_to_move &11ff bc 43 06 LDY &0643,X ; enemies_home_column &1202 b9 ac 06 LDA &06ac,Y ; passive_movement_frequencies # Enemies in outside columns more likely to move &1205 bc 6b 06 LDY &066b,X ; enemies_home_row &1208 19 ac 06 ORA &06ac,Y ; passive_movement_frequencies # Enemies in top rows more likely to move &120b 24 4f BIT &4f ; passive_movement_bit &120d f0 42 BEQ &1251 ; leave # Should this enemy move? If not, leave &120f bd db 04 LDA &04db,X ; enemies_screen_address_high &1212 08 PHP ; enemies_screen_address_high &1213 f0 03 BEQ &1218 ; skip_unplotting &1215 20 cc 0e JSR &0ecc ; unplot_enemy ; skip_unplotting &1218 bc 43 06 LDY &0643,X ; enemies_home_column &121b b9 ac 06 LDA &06ac,Y ; passive_movement_frequencies &121e 24 4f BIT &4f ; passive_movement_bit &1220 f0 11 BEQ &1233 ; skip_horizontal_movement # Should this enemy move horizontally? &1222 c0 05 CPY #&05 # Set carry if enemy is on right of formation &1224 bc 00 04 LDY &0400,X ; enemies_x &1227 6a ROR A # A is negative if enemy is on right of formation &1228 45 50 EOR &50 ; passive_movement_direction # Positive if expanding, negative if contracting &122a 30 02 BMI &122e ; move_enemy_right ; move_enemy_left &122c 88 DEY # Left enemies move left when formation expanding, &122d 88 DEY # right enemies move left when formation contracting ; move_enemy_right # Right enemies move right when formation expanding, &122e c8 INY # left enemies move right when formation contracting &122f 98 TYA &1230 9d 00 04 STA &0400,X ; enemies_x ; skip_horizontal_movement &1233 bc 6b 06 LDY &066b,X ; enemies_home_row &1236 b9 ac 06 LDA &06ac,Y ; passive_movement_frequencies &1239 24 4f BIT &4f ; passive_movement_bit &123b f0 0e BEQ &124b ; skip_vertical_movement # Should this enemy move vertically? &123d bc 49 04 LDY &0449,X ; enemies_y &1240 24 50 BIT &50 ; passive_movement_direction # Positive if expanding, negative if contracting &1242 10 02 BPL &1246 ; move_enemy_down ; move_enemy_up &1244 c8 INY # Enemies move up when formation contracting &1245 c8 INY ; move_enemy_down &1246 88 DEY # Enemies move down when formation expanding &1247 98 TYA &1248 9d 49 04 STA &0449,X ; enemies_y ; skip_vertical_movement &124b 28 PLP ; enemies_screen_address_high &124c f0 03 BEQ &1251 ; leave # Leave if enemies_screen_address_high is zero &124e 4c c9 0e JMP &0ec9 ; plot_enemy ; leave &1251 60 RTS ; update_stars &1252 a0 00 LDY #&00 &1254 a2 31 LDX #&31 ; STARS_LAST ; update_stars_loop &1256 bd 0e 0a LDA &0a0e,X ; stars_screen_address_low &1259 85 02 STA &02 ; screen_address_low &125b bd 40 0a LDA &0a40,X ; stars_screen_address_high &125e 85 03 STA &03 ; screen_address_high &1260 bd 72 0a LDA &0a72,X ; stars_pixel_value &1263 51 02 EOR (&02),Y ; screen_address &1265 91 02 STA (&02),Y ; screen_address &1267 fe 0e 0a INC &0a0e,X ; stars_screen_address_low &126a d0 03 BNE &126f ; skip_page &126c fe 40 0a INC &0a40,X ; stars_screen_address_high ; skip_page &126f bd 0e 0a LDA &0a0e,X ; stars_screen_address_low &1272 24 49 BIT &49 ; seven &1274 f0 1a BEQ &1290 ; move_star_down_a_group ; set_screen_address_low &1276 85 02 STA &02 ; screen_address_low &1278 bd 40 0a LDA &0a40,X ; stars_screen_address_high &127b 85 03 STA &03 ; screen_address_high &127d 18 CLC &127e bd 72 0a LDA &0a72,X ; stars_pixel_value &1281 69 16 ADC #&16 &1283 29 2a AND #&2a ; W0 # Limit star to left pixel of pair, non-flashing colours &1285 9d 72 0a STA &0a72,X ; stars_pixel_value &1288 51 02 EOR (&02),Y ; screen_address &128a 91 02 STA (&02),Y ; screen_address &128c ca DEX &128d 10 c7 BPL &1256 ; update_stars_loop &128f 60 RTS ; move_star_down_a_group &1290 18 CLC &1291 69 78 ADC #&78 &1293 48 PHA &1294 9d 0e 0a STA &0a0e,X ; stars_screen_address_low &1297 bd 40 0a LDA &0a40,X ; stars_screen_address_high &129a 69 02 ADC #&02 &129c 9d 40 0a STA &0a40,X ; stars_screen_address_high &129f 30 04 BMI &12a5 ; wrap_star_around_bottom_of_screen &12a1 68 PLA &12a2 4c 76 12 JMP &1276 ; set_screen_address_low ; wrap_star_around_bottom_of_screen &12a5 20 b9 12 JSR &12b9 ; get_random_screen_address &12a8 18 CLC &12a9 a5 03 LDA &03 ; screen_address_high &12ab 69 30 ADC #&30 &12ad 9d 40 0a STA &0a40,X ; stars_screen_address_high &12b0 68 PLA &12b1 a5 02 LDA &02 ; screen_address_low &12b3 9d 0e 0a STA &0a0e,X ; stars_screen_address_low &12b6 4c 76 12 JMP &1276 ; set_screen_address_low ; get_random_screen_address &12b9 a9 00 LDA #&00 &12bb 85 03 STA &03 ; screen_address_high &12bd 20 97 0e JSR &0e97 ; rnd ; fit_to_range_loop &12c0 e9 4f SBC #&4f &12c2 b0 fc BCS &12c0 ; fit_to_range_loop &12c4 69 50 ADC #&50 &12c6 a0 03 LDY #&03 ; multiply_loop &12c8 0a ASL A &12c9 26 03 ROL &03 ; screen_address_high &12cb 88 DEY &12cc d0 fa BNE &12c8 ; multiply_loop &12ce 85 02 STA &02 ; screen_address_low &12d0 20 97 0e JSR &0e97 ; rnd &12d3 29 07 AND #&07 &12d5 05 02 ORA &02 ; screen_address_low &12d7 85 02 STA &02 ; screen_address_low &12d9 60 RTS ; add_A_to_score &12da a0 00 LDY #&00 ; add_AY_to_score &12dc a6 32 LDX &32 ; current_player &12de 48 PHA ; tmp_a &12df 18 CLC &12e0 f8 SED &12e1 75 1f ADC &1f,X ; players_score # 100s and 10s &12e3 95 1f STA &1f,X ; players_score &12e5 98 TYA &12e6 75 21 ADC &21,X ; players_score + 2 # 10,000s and 1,000s &12e8 95 21 STA &21,X ; players_score + 2 &12ea 08 PHP ; score 100,000 rollover &12eb a9 00 LDA #&00 &12ed 75 23 ADC &23,X ; players_score + 4 # 1,000,000s and 100,000s &12ef 95 23 STA &23,X ; players_score + 4 &12f1 28 PLP ; score 100,000 rollover &12f2 d8 CLD &12f3 68 PLA ; tmp_a &12f4 60 RTS # Leaves with carry set if score rolled over 100,000 ; plot_player &12f5 20 21 13 JSR &1321 ; use_player_screen_address &12f8 18 CLC &12f9 69 80 ADC #&80 &12fb 85 0c STA &0c ; bottom_screen_address_low &12fd a5 18 LDA &18 ; player_screen_address_high &12ff 69 02 ADC #&02 &1301 85 0d STA &0d ; bottom_screen_address_high &1303 20 0d 13 JSR &130d ; plot_player_sprite &1306 24 19 BIT &19 ; player_doubled # Negative if player doubled &1308 10 16 BPL &1320 ; leave &130a 20 2a 13 JSR &132a ; move_to_right_of_player ; plot_player_sprite &130d a0 2f LDY #&2f ; plot_player_sprite_loop &130f b1 02 LDA (&02),Y ; screen_address &1311 59 b6 06 EOR &06b6,Y ; sprite_player &1314 91 02 STA (&02),Y ; screen_address &1316 b1 0c LDA (&0c),Y ; bottom_screen_address &1318 59 e6 06 EOR &06e6,Y ; sprite_player + &30 &131b 91 0c STA (&0c),Y ; bottom_screen_address &131d 88 DEY &131e 10 ef BPL &130f ; plot_player_sprite_loop ; leave &1320 60 RTS ; use_player_screen_address &1321 a5 18 LDA &18 ; player_screen_address_high &1323 85 03 STA &03 ; screen_address_high &1325 a5 17 LDA &17 ; player_screen_address_low &1327 85 02 STA &02 ; screen_address_low &1329 60 RTS ; move_to_right_of_player &132a a5 0c LDA &0c ; bottom_screen_address_low &132c 18 CLC &132d 69 30 ADC #&30 &132f 85 0c STA &0c ; bottom_screen_address_low &1331 90 02 BCC &1335 ; skip_bottom_screen_page &1333 e6 0d INC &0d ; bottom_screen_address_high ; skip_bottom_screen_page ; move_to_right_of_sprite &1335 a5 02 LDA &02 ; screen_address_low &1337 18 CLC &1338 69 30 ADC #&30 &133a 85 02 STA &02 ; screen_address_low &133c 90 02 BCC &1340 ; skip_screen_page &133e e6 03 INC &03 ; screen_address_high ; skip_screen_page &1340 60 RTS # &5b6d - &5c66 is moved to &0900 - &09f9 at &455e ; high_score_names &0900 20 20 20 20 2a 2a 2a 20 4f 72 6c 61 6e 64 6f 20 2a 2a 2a 0d 2a 0d 6d 6f 0d ; " *** Orlando ***.*.mo." &0919 0d 44 52 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d ; ".DR......................" (hidden text) &0932 0d 65 61 6e 2d 50 61 75 6c 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d ; ".ean-Paul................" (hidden text) &094b 20 20 20 4d 61 6e 79 20 74 68 61 6e 6b 73 20 74 6f 20 2e 2e 2e 0d 2e 0d 0d ; " Many thanks to ......." &0964 0d 68 65 61 70 20 50 61 63 28 6b 69 6e 29 20 52 69 70 2d 6f 66 66 0d 0d 0d ; ".heap Pac(kin) Rip-off..." (hidden text) &097d 20 20 4e 4a 4d 50 2c 20 43 41 50 2c 20 44 43 45 2c 20 4c 50 4d 2c 0d 2c 0d ; " NJMP, CAP, DCE, LPM,.,." &0996 4a 44 2c 20 4b 48 2c 20 50 43 2c 20 53 4b 2c 20 53 4a 2c 20 41 44 2c 0d 0d ; "JD, KH, PC, SK, SJ, AD,.." &09af 49 41 54 2c 20 52 41 4c 2c 20 30 2e 56 30 4c 4c 28 4e 30 52 53 4b 45 29 0d ; "IAT, RAL, 0.V0LL(N0RSKE)." &09c8 0d 50 42 2c 20 50 48 2c 20 44 4a 44 2c 20 52 4a 4d 2c 20 52 41 46 2c 0d 0d ; ".PB, PH, DJD, RJM, RAF,.." (hidden text) &09e1 2e 2e 2e 2b 20 61 6c 6c 20 61 74 20 41 63 72 6f 6e 73 66 6f 74 0d 45 29 0d ;"...+ all at Acronsfot.E)." # &5c67 - &5c86 is moved to &0200 - &021f at &464e if MOS 0.10 ; initial_vector_table # Used if MOS version is 0.10 &5c67 b2 db ; &dbb2 USERV &5c69 33 b4 ; &b433 BRKV &5c6b e4 dd ; &dde4 IRQ1V &5c6d b2 db ; &dbb2 IRQ2V &5c6f 62 e0 ; &e062 CLIV &5c71 b8 e8 ; &e8b8 BYTEV &5c73 eb e8 ; &e8eb WORDV &5c75 bb e1 ; &e1bb WRCHV &5c77 a5 df ; &dfa5 RDCHV &5c79 47 f2 ; &f247 FILEV &5c7b 93 f5 ; &f593 ARGSV &5c7d a5 f4 ; &f4a5 BGETV &5c7f 21 f5 ; &f521 BPUTV &5c81 69 f6 ; &f669 BGPBV &5c83 af f3 ; &f3af FINDV &5c85 e7 f2 ; &e7f2 FSCV # &5c87 - &5c90 is moved to &09fa - &0a03 at &474b ; high_scores_low &09fa 00 00 00 00 00 00 00 00 00 00 # &5c91 - &5ca4 is moved to &0cec - &0cff at &4756 ; high_scores_middle &0cec 01 01 01 01 01 01 01 01 01 01 # All high scores are 1,000 ; high_scores_high &0cf6 00 00 00 00 00 00 00 00 00 00 # &5ca5 - &5cb1 is moved to &0591 - &059d at &462c # &0591 - &059d is moved to &0300 - &030c at &049e if not MOS 0.10 # &0591 - &05b0 is moved to &0380 - &030c at &048c if MOS 0.10 ; arrival_pattern_2c_data &0300 00 14 ; start position &0302 e3 ; (+2, +3) x 8 &0303 e3 ; (+2, +3) x 8 &0304 e3 ; (+2, +3) x 8 &0305 ec ; ( 0, -3) x 8 &0306 ed ; (-1, -3) x 8 &0307 6d ; (-1, -3) x 4 &0308 38 ; ( 0, 0) x 2 &0309 e3 ; (+2, +3) x 8 &030a e3 ; (+2, +3) x 8 &030b a3 ; (+2, +3) x 6 &030c ff ; end of pattern # &5cb2 - &5d01 is moved to &0643 - &0692 at &4761 ; enemies_home_column ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0643 04 05 04 05 04 05 04 05 03 06 03 06 04 05 03 06 ; &00 &0653 02 01 02 01 07 08 07 08 03 02 03 02 06 07 06 07 ; &10 &0663 01 00 01 00 08 09 08 09 ; &20 ; enemies_home_row ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &066b 01 01 00 00 03 03 02 02 03 03 02 02 04 04 04 04 ; &00 &067b 03 03 02 02 03 03 02 02 01 01 00 00 01 01 00 00 ; &10 &068b 01 01 00 00 01 01 00 00 ; &20 # &5d02 - &5d0b is moved to &06ac - &06b5 at &4621 ; passive_movement_frequencies ; 0 1 2 3 4 5 6 7 8 9 &06ac ff ; 0 : 11111111, 8 bits set &06ad 77 ; 1 : 01110111, 6 bits set &06ae 55 ; 2 : 01010101, 4 bits set &06af 22 ; 3 : 00100010, 2 bits set &06b0 00 ; 4 : 00000000, 0 bits set &06b1 00 ; 5 : 00000000, 0 bits set &06b2 22 ; 6 : 00100010, 2 bits set &06b3 55 ; 7 : 01010101, 4 bits set &06b4 77 ; 8 : 01110111, 6 bits set &06b5 ff ; 9 : 11111111, 8 bits set # &5d0c - &5d15 is moved to &069d - &06a6 at &460b ; column_x_positions ; 0 1 2 3 4 5 6 7 8 9 &069d 06 0d 14 1b 22 29 30 37 3e 45 # &5d16 - &5d1a is moved to &06a7 - &06ab at &4616 ; row_y_positions ; 0 1 2 3 4 &06a7 4a 53 5c 65 6e # &5d1b - &5d24 is moved to &0693 - &069c at &476c ; arriving_enemy_types_table &0693 00 ; ENEMY_TYPE_DRONE &0694 02 ; ENEMY_TYPE_GUARD &0695 02 ; ENEMY_TYPE_GUARD &0696 04 ; ENEMY_TYPE_QUEEN &0697 02 ; ENEMY_TYPE_GUARD &0698 02 ; ENEMY_TYPE_GUARD &0699 00 ; ENEMY_TYPE_DRONE &069a 00 ; ENEMY_TYPE_DRONE &069b 00 ; ENEMY_TYPE_DRONE &069c 00 ; ENEMY_TYPE_DRONE