Styker's Run (Standard version) disassembly =========================================== Stryker's Run was written by Chris Roberts and Philip Meller, with graphics by Nick Elms and music by Martin Galway. It was published by Superior Software for the BBC Micro in 1986. It is a side-scrolling shooter, in which the player must transport plans across a battlefield. The game is notable for its graphics. The following disassembly was created by reverse engineering binary images, without access to any source code. It is nevertheless reasonably complete, allowing the technical approaches used to be understood. The author of this disassembly imposes no additional copyright restrictions beyond those already present on the game itself. It is provided for educational purposes only, and it is hoped that the original authors will accept it in the good faith it was intended - as a tribute to their skills. Technical notes =============== The main binary is protected by a VIA-based decryption routine written by Kevin Edwards. The disassembly analyses each stage after decryption has taken place. Interesting pokes ================= &2c32 = &a9 infinite lives &2976 = &a9 infinite fuel &28e1 = &00 player moves twice as quickly Notes ===== Mover types: &00 : MOVER_TYPE_PLAYER &01 : MOVER_TYPE_SOLDIER_WITH_RIFLE &02 : MOVER_TYPE_OFFICER_WITH_PISTOL &03 : MOVER_TYPE_TROOPER_WITH_RIFLE &04 : MOVER_TYPE_TROOPER_WITH_BAZOOKA &05 : MOVER_TYPE_HELICOPTER_WITH_MISSILE &06 : MOVER_TYPE_HELICOPTER &07 : MOVER_TYPE_HELICOPTER_WITH_SOLDIER &08 : MOVER_TYPE_RED_HELICOPTER &09 : MOVER_TYPE_MORTAR &0a : MOVER_TYPE_MACHINE_GUN &0b : MOVER_TYPE_BLUE_CRAFT &0c : MOVER_TYPE_SAM &0d : MOVER_TYPE_SKELETON &0e : MOVER_TYPE_EXPLOSION &0f : MOVER_TYPE_BULLET &10 : MOVER_TYPE_GRENADE &11 : MOVER_TYPE_BOMB &12 : MOVER_TYPE_ROCKET &13 : MOVER_TYPE_MINE Mover slots: &00 : player &01 - &09 : enemies &0a - &0b : enemy helicopters &0c : player grenade &0d - &10 : enemy grenades &11 : player bullet &12 - &14 : enemy bullets &15 - &17 : ally bullets &18 - &20 : ally helicopters Loader disassembly ================== ; Stryker ; FFFF0E00 FFFF8023 0015 &0e00 0d # Start of BASIC program &0e01 00 0a 0d 2a 46 58 20 32 30 30 20 33 0d ; 10*FX 200 3 &0e0e 00 14 06 2a 2f 0d ; 20*/ &0e14 ff # End of BASIC program ; StrykerSCR ; FFFF1100 FFFF1E71 0DCD ; unused &1100 00 ; packed_data_zero # Image &1101 04 16 bc 04 16 fc b9 b6 b9 b6 b9 bc b6 b9 b6 b9 &1111 b6 bc b9 b6 b9 b6 b9 bc 3d 03 96 bc 0a 00 bc bf &1121 bc 80 94 7d 54 fd 94 00 29 d6 83 a9 43 56 bc b9 &1131 bc b9 b6 b9 b6 b9 bc b6 b9 b6 b9 b6 bc b9 b6 b9 &1141 b6 b9 bc 30 03 96 0b 03 96 a8 0b 00 a8 be a8 80 &1151 bc 7f bc 05 3f bc 00 2f 7c a9 83 96 bc b9 b6 b9 &1161 b6 b3 bc b9 bc b9 bc b9 bc b6 b9 b6 b9 b6 bc 06 &1171 29 30 03 a9 96 09 03 bc 11 00 bc ff bc 7f be bd &1181 bf bd 94 00 2d 56 bc 79 7c 04 36 bc b9 b3 b9 b3 &1191 b9 bc b6 bc b6 bc b6 bc d6 35 03 a9 96 05 03 bc &11a1 a8 0e 00 94 bd bc 80 a8 be ff bc 05 3f bc 00 2b &11b1 b6 b9 b6 b9 b3 bc b6 b9 b6 b9 b6 bc 05 33 bc 05 &11c1 33 05 3c 96 15 03 06 16 14 03 bc 04 03 bc 05 03 &11d1 a9 bc 0e 00 bc 7f bc 80 bc ff bc 7f bd be a8 00 &11e1 31 05 36 bc 05 33 bc 05 36 bc 05 33 07 3c 05 16 &11f1 c3 0a 16 ac bc 06 30 78 96 10 03 bc a9 05 03 a9 &1201 96 83 56 bc a8 0e 00 bc 7f bc 80 bc 7e bd 7f be &1211 bf be 7d 94 00 35 05 33 bc 05 33 bc 05 33 bc 05 &1221 33 0a 3c 4c ac bc ad cf bc 8c 8d 4f 4c 9c 8c ac &1231 b4 07 30 bc 0f 03 a9 96 07 03 bc a8 07 00 94 04 &1241 38 54 04 00 bc bf bc 80 bc ff be bd bf bc ff bc &1251 00 3c 05 33 bc 05 36 bc 05 33 bc 05 36 06 3c 6d &1261 8d 9c cc ac 4c 9c 8f ac 06 0c 9c ac 9c 8c bc b4 &1271 04 30 b4 bc 0e 03 56 a9 05 03 96 bc a8 04 00 54 &1281 ed b4 f0 b4 ed bc 94 bc a8 40 a8 be bf be bd be &1291 bf bc 7f be a8 00 45 05 33 bc 05 33 bc b6 b9 b6 &12a1 b9 b6 bc b6 04 33 bc 96 bc 9e bc 9e ad 9e ad 9e &12b1 ad 9c ad 9c ac 9c bc ac 9c ac 9c ad 9e ad 9e 9c &12c1 bc ac 4c 8f 04 2d 8f bc 0c 03 96 a9 07 03 96 bc &12d1 c0 94 ad ac 4c 8e 8f 9e 8e 7c ac 9e 4f 04 0c ac &12e1 bc 54 80 bc bf be bd bf bc be a8 00 56 b9 b6 b9 &12f1 b6 b9 bc b9 b6 b9 76 bc b6 b9 b6 bc b6 bc b6 b9 &1301 b6 b3 b6 bc 83 08 29 bc 9e bc 9e bc e9 9c bc 9e &1311 bc 9e ad 9e bc 9c ac 8c 4e 4f 9e 04 38 96 11 03 &1321 56 bc 80 54 ad 4f 8d 9c ac 9c ac 9c ac 9c bc ac &1331 9c ac 9e ac 9c 8c 9e 8f 9c 04 38 7c be bf bc 00 &1341 54 05 29 bc b9 b6 b9 b3 bc 83 e9 43 bc b6 b9 b6 &1351 b9 b6 bc 16 03 a9 9e bc 9c bc 04 1c b8 bc 04 30 &1361 bc 10 03 96 bc 94 6d 4f 9e 8f 9e ad 9e ad 9c ac &1371 9c a8 80 68 7c 9c ad 9c ad 9e b8 f0 b4 bc 73 04 &1381 39 94 00 43 05 03 a9 bc 76 bc a9 06 03 bc b6 bc &1391 b6 bc b6 bc 16 03 96 ac bc ad bc ad 6c bc b4 bc &13a1 04 30 bc 0a 03 04 16 6c 8c 5c 0d 38 94 06 00 04 &13b1 28 bc f4 bc b6 f3 b6 b3 b6 b9 94 00 39 2e 03 bc &13c1 8c 05 0f 8c 9c 6c 05 2d bc 05 16 04 2c 6d 05 0c &13d1 bc 70 a0 04 10 04 30 f4 bc 05 00 06 14 05 3c 94 &13e1 bc 76 bc b3 bc b3 bc 00 2c 2e 03 bc 8c 4f 9e 8c &13f1 9c ac 4c 8d 04 0f bc f0 bc 06 0c 8e 4c 9c 04 3c &1401 b0 80 08 30 bc cc ac 94 80 94 6c 9c 05 3c a9 bd &1411 7c 78 b0 60 78 b6 a8 00 30 09 16 c3 05 16 43 08 &1421 16 c3 06 16 83 56 c3 d6 bc ac 8c 7c 9c 05 0c 9e &1431 4e 8c bc f0 bc 0b 0c 04 2d b4 08 30 bc ac cc 9c &1441 79 bc 8c 08 3c 96 bc 70 04 10 80 a0 b0 bc 00 37 &1451 ec ad 05 0f ec 04 0c ac bc ac 8c 5c 7c 9c 4c ac &1461 bc ac 4e cf fc 8e 6c ad 4f 4e 8c 6c 8c 9c 4c ac &1471 9c 4c ac 9c e8 b4 bc 8c 9c bc 0e 1c bc 05 34 70 &1481 bc 04 1c b9 b3 7c 8c 0a 3c 07 30 90 b0 7c 00 40 &1491 05 3c 5e 4c 9c cc 9c 4c 9c 8d 9e b8 04 30 b4 b8 &14a1 9c 8c bc 8c 9c 8c 9c 8c 9e f8 9c 8c 9c 8e 9e 8c &14b1 9c 8c 9c 8c 9c 8c 9c 8c bc 4c 9c 8c ac 94 c0 bc &14c1 ac bc 8c 6c 8c 9c 8c 9c ac 4c ac 8c 9c 8d 8f 9e &14d1 b8 07 30 bc 4f 4e bc 73 bc 4c 06 3c 96 ab bc b4 &14e1 07 30 fc 00 55 08 3c ad 9c ac 9c ac ad 9e ad 9e &14f1 ad bc b0 b8 b4 b0 74 b8 bc ac 9c bc 0d 38 bc 9c &1501 ac 9c ac 9c ac 9c ad 9c ac 9c ac 9c bc b0 78 bc &1511 8c ac 8c 9c 8c ac 9c 8c 9c 4c ac 8c 9c 04 3c b0 &1521 a0 07 30 b8 9e 04 0c bc 68 9c cc 04 2c 05 3c 74 &1531 70 b4 7c a8 00 51 07 3c 9e bc 9e bc 9c e9 bc 9e &1541 bc 9e bc b8 b4 b8 74 bc 69 bc b4 b8 b4 b8 b4 b8 &1551 b4 b8 b4 b8 b4 b8 b4 b8 b4 bc ac 9c ac 9c ad 9e &1561 ad 9e ad 9c ac bc f0 bc 9c ac 9c ac 9c bc ac 9c &1571 ac 9c ac ad 9e ad 9e ad bc ad bc b0 90 a0 08 30 &1581 78 9c bc a8 c0 07 28 9e bc 9e bc 9e fc 68 00 5a &1591 7c a9 11 03 04 29 05 03 0f 29 83 12 3c 9c 0b 3c &15a1 9e ad 9e ad bc b4 70 04 10 06 30 b4 bc 13 00 94 &15b1 bd 94 bd 94 00 26 2d 03 7c 0e 3d 06 3c fd bc 04 &15c1 00 e8 bc 9e bc ad bc ad 04 2c 6d bc 6d bc 12 00 &15d1 94 bc 7f bd be bd 94 00 23 2e 03 10 29 83 bc 40 &15e1 04 28 08 00 94 ad 9e ad 9e 8f 8d 04 0c 8e 8f ad &15f1 9e a8 12 00 bc bf bc 7f bc bf bc 00 24 3d 03 96 &1601 a8 0d 00 94 bc 8f ac 9e 8e 8c 4f 8c 9c cc 9c a8 &1611 14 00 a8 be 7f be bf be a8 00 1e 3a 03 96 68 0e &1621 00 bc 70 b8 9c cc 9c ac 5c ac 9c a8 18 00 a8 be &1631 68 00 18 a9 96 37 03 96 a8 11 00 a8 74 bc ac 9c &1641 06 0c 6c 54 00 13 43 a9 96 33 03 96 a8 15 00 a8 &1651 9c bc 9c ac 9c 8c 9c 06 0c 7c 94 05 00 d4 00 1a &1661 c3 a9 bc 96 30 03 bc 1a 00 68 9c ac 9c ac 9c ac &1671 5c b8 f0 bc d4 bc a8 54 7c 54 00 1c 06 03 a9 56 &1681 2c 03 96 a8 19 00 94 c0 e8 7c f0 74 79 b3 7c a8 &1691 07 3c 68 54 00 1a 09 03 a9 96 29 03 bc 11 00 bc &16a1 80 94 bc b8 94 04 00 bc 08 00 04 28 f6 a8 94 04 &16b1 3c b9 06 3c 54 68 54 00 23 0b 03 69 56 14 03 69 &16c1 96 0f 03 bc 10 00 bc 94 7c b0 ba bd 94 40 bc 0c &16d1 00 94 05 3c b9 b6 b9 bc b6 b3 bc a8 06 3c 54 68 &16e1 54 00 2a 0e 03 69 96 14 03 a9 96 0b 03 56 a8 11 &16f1 00 bc 80 fc b4 b0 ba bc 80 bc 0b 00 06 3c b6 bc &1701 b6 bc 05 28 5e 6d 06 3c 94 bc 00 29 0f 03 96 a9 &1711 15 03 a9 96 09 03 bc 14 00 bc a8 04 3c 74 04 3c &1721 0c 00 e8 0c 00 68 5e 04 28 7c a8 00 21 0e 03 bc &1731 19 03 bc 06 03 96 a8 15 00 bc 80 a8 06 3c 80 bc &1741 07 00 0d 05 00 19 0b 03 56 a9 1a 03 69 96 c3 bc &1751 1b 00 a8 04 3c 85 bc 45 17 0f c5 00 17 09 03 96 &1761 bc 43 a9 96 1c 03 a9 96 a8 1b 00 85 4f fc 8f ad &1771 4f 9e 06 0f bc 14 0f 45 00 1d 07 03 96 a9 06 03 &1781 a9 96 1c 03 69 94 16 00 85 04 0f 04 3c 8f bc 8f &1791 fc 9e 04 0f bc 18 0f 85 00 20 0f 03 a9 96 1f 03 &17a1 bc 13 00 06 0f 04 2d 4f bc ad 05 3c 9e 4f bc 18 &17b1 0f 9e 4f 00 1b 11 03 bc 1f 03 a9 94 10 00 0d 0f &17c1 bc 9e 07 3c 9e ad 12 0f 5e 04 0f bc cf 00 1a 10 &17d1 03 96 a9 20 03 bc 94 0e 00 0e 0f bc 8f ad 06 3c &17e1 8f bc 09 0f 5e cf bc 4f 9e fc 9e 4f bc 04 0f 00 &17f1 22 0e 03 96 a9 24 03 a9 54 0b 00 0f 0f ad 4f ad &1801 fc 4f bc 08 0f 04 3c 9e 8f bc 4f 06 3c 9e ad 04 &1811 0f 00 22 0c 03 56 a9 26 03 56 a8 0a 00 14 0f 7c &1821 4f bc 08 0f ad 04 3c ad 9e 4f ad 05 3c 8f bc cf &1831 00 1f 09 03 96 69 25 03 d6 a8 0e 00 13 0f 7c 9e &1841 8f ad 0b 0f 7c 8f bc 05 0f fc 8f bc 4f 00 1d 06 &1851 03 56 a9 21 03 d6 bc e8 13 00 8a 10 0f 05 2d 0b &1861 0f 9e 7c 8f bc 06 0f 7c 8f bc 8f 00 1e c3 96 69 &1871 1f 03 d6 68 1c 00 8a 28 0f ed 8f 8a 00 11 43 96 &1881 a9 1c 03 d6 68 24 00 4a 25 0f 4a 00 0f 83 96 a9 &1891 19 03 56 68 2d 00 4a 1c 0f ca 00 0f a9 19 03 96 &18a1 a8 36 00 05 0a 0d 0f ca 00 0e 18 03 96 a8 00 06 &18b1 16 03 96 a8 00 06 14 03 96 a8 00 06 11 03 56 a8 &18c1 00 06 0e 03 96 68 00 06 0a 03 56 68 00 06 08 03 &18d1 96 a8 00 06 06 03 96 a8 00 06 04 03 96 a8 00 06 &18e1 c3 bc 00 04 43 96 a8 00 05 83 96 a8 00 05 96 a8 &18f1 00 84 ; unused &18f2 00 ; packed_data_one # Logos &18f4 94 7d 54 0e 00 54 7d 54 17 00 bc 04 2d bc c0 bc &1904 0d 2d bc 00 15 bc bf bc 7e 7d 54 06 00 54 7d 7e &1914 69 7e 7d 54 13 00 bc 04 0f bc c0 bc cf de bc e8 &1924 bc 4f bc 00 20 bc bf bc 43 69 7e 7d 54 7d 7e 69 &1934 06 03 69 7e 7d 54 0f 00 bc 04 0f 05 2d cf bc 06 &1944 00 bc 4f bc 00 21 bc bf bc 56 04 03 69 7e 69 04 &1954 03 56 7d 56 04 03 a9 bc bf bc 0f 00 bc 0c 1e bc &1964 06 00 bc 5e bc 00 21 bc 04 3f 7d 56 06 03 56 7d &1974 06 3f 7d 56 83 bc bf bc 23 00 04 14 00 17 a8 7e &1984 06 3f 7d 56 7d 06 3f 7e 06 3f 7d bf bc 23 00 bc &1994 4f bc 00 16 c0 68 7e 0a 3f 7e 68 40 e8 7e 04 3f &19a4 bc 0f 00 bc 14 2d 4f bc 00 16 bc 54 04 00 68 7e &19b4 7f 7e 68 0b 00 68 7e bc 0f 00 bc 09 0f 0b 1e 4f &19c4 bc 00 19 bc 43 69 54 04 00 68 13 00 a8 0f 00 0b &19d4 28 09 00 bc 4f bc 00 15 bc 06 03 69 54 80 fc 80 &19e4 94 04 3c 94 80 fc 80 94 04 3c 94 23 00 04 28 00 &19f4 19 bc 83 07 17 83 bc 80 a8 04 3c a8 80 fc 80 a8 &1a04 04 3c a8 80 a8 7c 0f 00 bc 16 2d bc 00 1d bc 83 &1a14 ab 07 03 bc c0 06 14 04 00 09 14 0f 00 bc 09 0f &1a24 de cf 05 1e 4f bc 00 1a bc 83 04 2b 83 ab 43 bc &1a34 80 fc 04 28 fc 80 fc 07 28 0f 00 0a 28 40 bc cf &1a44 bc c0 bc 4f bc 00 1f bc 83 eb bf 97 c3 bc 80 68 &1a54 06 3c 68 80 a8 09 3c 16 00 05 14 bc cf bc c0 bc &1a64 4f bc 00 1d bc c3 ab 57 c3 bc 80 08 14 c0 09 14 &1a74 10 00 bc 06 2d 06 1e cf 05 2d 4f bc 00 1a bc 83 &1a84 04 2b 04 03 bc 80 e8 7c e8 7c 80 e8 fc 68 7c c0 &1a94 94 0b 00 07 28 05 00 0c 28 00 1d bc 83 04 2b 97 &1aa4 ab 43 bc 80 08 14 7c 04 00 68 04 3c a8 c0 bc 04 &1ab4 00 94 11 00 bc 0b 2d bc 00 1f bc 83 04 2b bf 6b &1ac4 83 bc 80 08 28 7c c0 06 14 05 00 bc 04 00 bc 04 &1ad4 00 94 80 0b 14 bc 4f 05 1e bc 04 28 00 24 bc 83 &1ae4 97 ab bf ab 97 c3 bc 80 94 09 3c 80 fc a8 7c a8 &1af4 fc c0 bc 04 00 bc 04 00 bc 80 bc 0d 0f bc 00 22 &1b04 bc 83 ab 83 6b 04 03 bc 80 a8 7c 07 14 80 68 40 &1b14 68 40 68 40 94 bc 04 00 bc 04 00 bc 80 bc 05 1e &1b24 bc 04 28 bc 4f bc 09 14 00 2a bc 83 97 eb 97 c3 &1b34 bc 80 94 7c 07 28 80 09 3c 94 40 7c c0 94 bc 04 &1b44 00 bc 0c 00 bc 0b 1e bc 00 20 bc 83 07 2b 83 bc &1b54 80 a8 09 3c 80 d4 fc 94 fc 40 7c c0 7c c0 94 bc &1b64 80 18 14 00 1b bc 09 03 bc 80 09 14 40 04 28 80 &1b74 04 28 c0 7c c0 7c c0 7c 80 bc 16 0f bc 00 1a bc &1b84 09 03 bc 80 e8 7c 68 fc 80 0a 3c 40 7c c0 7c c0 &1b94 7c 80 bc 0b 1e 4f bc 09 28 00 1c bc 09 03 bc 80 &1ba4 09 3c a8 c0 06 14 04 00 7c 80 94 80 7c c0 7c 06 &1bb4 00 d4 ed cf ad 54 00 1d bc 09 03 bc 80 09 14 40 &1bc4 fc 04 28 fc 40 7c 80 bc 80 7c 80 bc 80 7c 80 54 &1bd4 ed 04 0f de e8 5e 6d 54 00 22 bc 09 03 bc 80 e8 &1be4 fc a8 fc 80 68 06 3c 68 40 7c 80 bc 80 7c 80 bc &1bf4 80 7c 80 bc cf 5e e8 08 00 68 5e 6d 94 00 25 bc &1c04 09 03 bc 80 04 3c a8 04 3c a8 80 09 14 40 07 14 &1c14 a8 80 a8 80 68 80 04 28 11 00 68 00 1e bc 09 03 &1c24 bc c0 06 14 c0 e8 fc a8 fc 80 04 3c 68 07 3c 80 &1c34 bc 16 2d bc 00 19 bc 09 03 bc 80 fc a8 7c a8 fc &1c44 80 04 3c a8 04 3c a8 05 00 54 fc 40 7c 80 bc 0e &1c54 0f 06 1e 4f bc 00 21 bc 09 03 bc 80 68 40 68 40 &1c64 68 0c 00 04 3c e8 06 3c 80 bc cf bc 07 28 bc 4f &1c74 bc 04 00 bc 4f bc 00 21 bc 09 03 bc 25 00 bc cf &1c84 bc 07 00 bc 4f bc 04 00 bc 5e bc 00 15 bc 09 03 &1c94 bc 17 00 07 3c 06 14 80 bc de bc 07 00 04 28 00 &1ca4 14 bc 09 03 bc 17 00 fc 68 40 06 28 80 18 14 00 &1cb4 10 bc 09 03 bc 17 00 fc 04 14 07 00 bc 16 0f bc &1cc4 00 11 bc 09 03 bc 17 00 07 28 06 3c 80 bc 08 1e &1cd4 68 bc cf bc 04 28 bc 4f bc 00 19 bc 09 03 bc 30 &1ce4 00 bc cf bc 04 00 bc 4f bc 00 10 bc 09 03 bc 17 &1cf4 00 08 3c 05 14 80 07 14 05 2d cf bc 04 14 bc 4f &1d04 bc 00 18 bc 09 03 bc 17 00 05 28 40 04 28 7c 80 &1d14 bc 06 1e 04 28 bc 0b 1e bc 00 18 bc 09 03 bc 17 &1d24 00 08 14 c0 7c 80 06 14 c0 0f 14 00 12 bc 09 03 &1d34 bc 17 00 07 28 06 3c 80 bc 04 0f bc c0 bc 06 0f &1d44 05 1e 4f bc 00 19 bc 09 03 bc 25 00 bc 04 0f bc &1d54 d4 bc cf bc e8 c0 bc 4f bc 00 15 bc 09 03 bc 25 &1d64 00 bc 0c 0f bc 06 00 bc 4f bc 00 11 a8 09 02 a8 &1d74 25 00 0e 28 06 00 04 28 00 8e ; run_string &1d7e 2f 0d ; "/" ; unused &1d80 4e 20 74 67 61 6d 65 0d ; "N tgame" ; packed_data_addresses_low_table &1d88 11 18 ; unused &1d8a 00 ; packed_data_addresses_high_table &1d8b 01 f4 ; unused &1d8d 00 ; mask_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1d8e ff aa 55 00 aa aa 00 00 55 00 55 00 00 00 00 00 ; &00 &1d9e aa aa 00 00 aa aa 00 00 00 00 00 00 00 00 00 00 ; &10 &1dae 55 00 55 00 00 00 00 00 55 00 55 00 00 00 00 00 ; &20 &1dbe 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &30 ; unpack_screen_data &1dce 86 75 STX &75 ; screen_address_high &1dd0 85 74 STA &74 ; screen_address_low &1dd2 86 71 STX &71 ; column_address_high &1dd4 85 70 STA &70 ; column_address_low &1dd6 b9 88 1d LDA &1d88,Y ; packed_data_addresses_low_table &1dd9 85 73 STA &73 ; data_address_high &1ddb b9 8b 1d LDA &1d8b,Y ; packed_data_addresses_high_table &1dde 85 72 STA &72 ; data_address_low &1de0 a0 00 LDY #&00 ; unpack_screen_data_loop &1de2 b1 72 LDA (&72),Y ; data_address # Get byte of packed data &1de4 f0 66 BEQ &1e4c ; end_of_column # Zero indicates end of column ; not_end_of_column &1de6 aa TAX &1de7 10 12 BPL &1dfb ; is_positive ; is_negative &1de9 29 40 AND #&40 &1deb d0 07 BNE &1df4 ; is_run_length_3 ; is_run_length_1 &1ded 8a TXA # 10 ...... run length 1 &1dee 29 3f AND #&3f &1df0 a2 01 LDX #&01 &1df2 d0 19 BNE &1e0d ; unpack_run # Always branches ; is_run_length_3 &1df4 8a TXA # 11 ...... run length 3 &1df5 29 3f AND #&3f &1df7 a2 03 LDX #&03 &1df9 d0 12 BNE &1e0d ; unpack_run # Always branches ; is_positive &1dfb 29 40 AND #&40 &1dfd f0 07 BEQ &1e06 ; is_variable_run_length ; is_run_length_2 &1dff 8a TXA # 01 ...... run length 2 &1e00 29 3f AND #&3f &1e02 a2 02 LDX #&02 &1e04 d0 07 BNE &1e0d ; unpack_run # Always branches ; is_variable_run_length &1e06 c8 INY # 00 ...... use next byte for run length &1e07 d0 02 BNE &1e0b ; skip_page &1e09 e6 73 INC &73 ; data_address_high ; skip_page &1e0b b1 72 LDA (&72),Y ; data_address # Get byte of packed data for run length ; unpack_run &1e0d 8d 29 1e STA &1e29 ; pixel_value &1e10 84 76 STY &76 ; offset &1e12 a8 TAY &1e13 b9 8e 1d LDA &1d8e,Y; mask_table &1e16 8d 27 1e STA &1e27 ; pixel_mask &1e19 a4 76 LDY &76 ; offset &1e1b c8 INY &1e1c d0 02 BNE &1e20 ; unpack_run_loop &1e1e e6 73 INC &73 ; data_address_high ; unpack_run_loop &1e20 84 76 STY &76 ; offset &1e22 a0 00 LDY #&00 &1e24 b1 74 LDA (&74),Y ; screen_address &1e26 29 ff AND #&ff # actually AND pixel_mask &1e28 49 ff EOR #&ff # actually EOR pixel_value &1e2a 91 74 STA (&74),Y ; screen_address &1e2c a4 76 LDY &76 ; offset &1e2e a5 74 LDA &74 ; screen_address_low &1e30 29 07 AND #&07 &1e32 f0 07 BEQ &1e3b ; move_up_a_group ; move_up_a_row &1e34 c6 74 DEC &74 ; screen_address_low ; next_byte_of_run &1e36 ca DEX &1e37 d0 e7 BNE &1e20 ; unpack_run_loop &1e39 f0 a7 BEQ &1de2 ; unpack_screen_data_loop # Always branches ; move_up_a_group &1e3b c6 75 DEC &75 ; screen_address_high &1e3d c6 75 DEC &75 ; screen_address_high &1e3f a5 74 LDA &74 ; screen_address_low &1e41 38 SEC &1e42 e9 79 SBC #&79 &1e44 85 74 STA &74 ; screen_address_low &1e46 b0 ee BCS &1e36 ; next_byte_of_run &1e48 c6 75 DEC &75 ; screen_address_high &1e4a d0 ea BNE &1e36 ; next_byte_of_run # Always branches ; end_of_column &1e4c c8 INY &1e4d d0 02 BNE &1e51 ; skip_page &1e4f e6 73 INC &73 ; data_address_high ; skip_page &1e51 b1 72 LDA (&72),Y ; data_address # Get byte of packed data &1e53 10 01 BPL &1e56 ; next_column # Negative indicates end of data &1e55 60 RTS ; next_column &1e56 c8 INY &1e57 d0 02 BNE &1e5b ; skip_page &1e59 e6 73 INC &73 ; data_address_high ; skip_page &1e5b a5 70 LDA &70 ; column_address_low &1e5d 18 CLC &1e5e 69 08 ADC #&08 # Move right a column &1e60 85 70 STA &70 ; column_address_low &1e62 90 02 BCC &1e66 ; skip_page_column &1e64 e6 71 INC &71 ; column_address_high ; skip_page_column &1e66 a5 71 LDA &71 ; column_address_high &1e68 85 75 STA &75 ; screen_address_high &1e6a a5 70 LDA &70 ; column_address_low &1e6c 85 74 STA &74 ; screen_address_low &1e6e 4c e2 1d JMP &1de2 ; unpack_screen_data_loop ; entry_point &1e71 a9 16 LDA #&16 # Change to MODE 2 &1e73 20 ee ff JSR &ffee ; OSWRCH &1e76 a9 02 LDA #&02 &1e78 20 ee ff JSR &ffee ; OSWRCH &1e7b a9 06 LDA #&06 ; R6: Vertical displayed register &1e7d 8d 00 fe STA &fe00 ; video register number &1e80 a9 0f LDA #&0f &1e82 8d 01 fe STA &fe01 ; video register value &1e85 a9 07 LDA #&07 ; R7: Vertical sync position &1e87 8d 00 fe STA &fe00 ; video register number &1e8a a9 1c LDA #&1c &1e8c 8d 01 fe STA &fe01 ; video register value &1e8f a9 0c LDA #&0c ; R12: Displayed screen start address register (high) &1e91 8d 00 fe STA &fe00 ; video register number &1e94 a9 0b LDA #&0b # Set screen memory to start at &5a80 &1e96 8d 01 fe STA &fe01 ; video register value &1e99 a9 0d LDA #&0d ; R13: Displayed screen start address register (low) &1e9b 8d 00 fe STA &fe00 ; video register number &1e9e a9 50 LDA #&50 &1ea0 8d 01 fe STA &fe01 ; video register value &1ea3 a9 9a LDA #&9a ; Write to Video ULA control register and RAM copy &1ea5 a2 14 LDX #&14 # Use settings for MODE 2, disabling cursor &1ea7 20 f4 ff JSR &fff4 ; OSBYTE &1eaa a9 01 LDA #&01 # Set colour 0 to cyan &1eac 8d 21 fe STA &fe21 ; video ULA palette register &1eaf a9 67 LDA #&67 # Set colour 6 to black &1eb1 8d 21 fe STA &fe21 ; video ULA palette register &1eb4 a9 87 LDA #&87 &1eb6 a2 7d LDX #&7d ; &7d87 &1eb8 a0 00 LDY #&00 # Plot image &1eba 20 ce 1d JSR &1dce ; unpack_screen_data &1ebd a9 24 LDA #&24 &1ebf a2 7c LDX #&7c ; &7c24 &1ec1 a0 01 LDY #&01 # Plot Stryker's Run and Superior Software logo &1ec3 20 ce 1d JSR &1dce ; unpack_screen_data &1ec6 a2 7e LDX #&7e ; &1d7e = run_string &1ec8 a0 1d LDY #&1d &1eca 4c f7 ff JMP &fff7 ; OSCLI # Run Stryker2 ; Stryker2 ; FFFF0E00 FFFF0E00 0500 ; entry_point &0e00 a2 0f LDX #&0f &0e02 a9 00 LDA #&00 ; remove_roms_loop &0e04 9d a1 02 STA &02a1,X ; os_paged_rom_type_table # Remove paged ROMs from ROM information table &0e07 ca DEX &0e08 10 fa BPL &0e04 ; remove_roms_loop &0e0a a2 00 LDX #&00 ; move_1200_to_12ff_loop # Move &1200 - &12ff to &0700 - &07ff &0e0c bd 00 12 LDA &1200,X ; unrelocated_load_game &0e0f 9d 00 07 STA &0700,X ; load_game &0e12 e8 INX &0e13 d0 f7 BNE &0e0c ; move_1200_to_12ff_loop &0e15 a9 0f LDA #&0f ; Flush all buffers &0e17 20 f4 ff JSR &fff4 ; OSBYTE &0e1a 4c d3 0e JMP &0ed3 ; via_decryption ; unused &0e1d 50 72 6f 74 65 63 74 69 6f 6e 20 28 63 29 20 4b ; "Protection (c) K" &0e2d 65 76 69 6e 20 45 64 77 61 72 64 73 20 31 39 38 ; "evin Edwards 198" &0e3d 36 ; "6" ; unused &0e3e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0e4e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0e5e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0e6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0e7e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0e8e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0e9e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0eae 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0ebe 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &0ece 00 00 00 00 00 ; via_decryption &0ed3 78 SEI &0ed4 a2 ff LDX #&ff &0ed6 9a TXS &0ed7 e8 INX ; 0 &0ed8 a9 40 LDA #&40 # Set User VIA timer 1 to continuous interrupts &0eda 8d 6b fe STA &fe6b ; User VIA auxiliary control register &0edd a9 7f LDA #&7f # Disable all User VIA interrupts &0edf 8d 6e fe STA &fe6e ; User VIA interrupt enable register &0ee2 a9 e0 LDA #&e0 # Enable interrupts for User VIA timers 1 and 2 &0ee4 8d 6e fe STA &fe6e ; User VIA interrupt enable register &0ee7 a9 21 LDA #&21 &0ee9 8d 68 fe STA &fe68 ; User VIA timer 2 counter LSB &0eec a9 56 LDA #&56 &0eee 8d 69 fe STA &fe69 ; User VIA timer 2 counter MSB &0ef1 a9 45 LDA #&45 &0ef3 8d 64 fe STA &fe64 ; User VIA timer 1 counter LSB &0ef6 a9 4b LDA #&4b &0ef8 8d 65 fe STA &fe65 ; User VIA timer 1 counter MSB &0efb a9 03 LDA #&03 # Enable ESCAPE, clear memory on BREAK &0efd 8d 58 02 STA &0258 ; ESCAPE/BREAK effect ; via_decryption_code ; via_decryption_loop &0f00 ad 00 0f LDA &0f00 # Runs from &0f00 to &0fff # actually LDA &0f00 + via_decryption_offset &0f03 4d 69 fe EOR &fe69 ; User VIA timer 2 counter MSB &0f06 ce 65 fe DEC &fe65 ; User VIA timer 1 counter MSB &0f09 5d 00 10 EOR &1000,X ; payload &0f0c 9d 00 01 STA &0100,X ; stack # Populate &0100 - &01ff with random numbers &0f0f ac 64 fe LDY &fe64 ; User VIA timer 1 counter LSB &0f12 8c 17 0f STY &0f17 ; via_decryption_add &0f15 18 CLC &0f16 69 ed ADC #&ed # actually ADC via_decryption_add &0f18 4d 64 fe EOR &fe64 ; User VIA timer 1 counter LSB &0f1b ac 65 fe LDY &fe65 ; User VIA timer 1 counter MSB &0f1e cc 69 fe CPY &fe69 ; User VIA timer 2 counter MSB &0f21 6d 68 fe ADC &fe68 ; User VIA timer 2 counter LSB &0f24 ac 69 fe LDY &fe69 ; User VIA timer 2 counter MSB &0f27 8c 2b 0f STY &0f2b ; via_decryption_eor_one &0f2a 49 ee EOR #&ee # actually EOR via_decryption_eor_one &0f2c 4d 17 0f EOR &0f17 ; via_decryption_add &0f2f 4d 64 fe EOR &fe64 ; User VIA timer 1 counter LSB &0f32 0e 69 fe ASL &fe69 ; User VIA timer 2 counter MSB &0f35 ce 65 fe DEC &fe65 ; User VIA timer 1 counter MSB &0f38 5d 00 07 EOR &0700,X ; load_game # Runs over &0700 to &07ff &0f3b ac 65 fe LDY &fe65 ; User VIA timer 1 counter MSB &0f3e 59 00 0f EOR &0f00,Y ; via_decryption_code &0f41 ee 45 0f INC &0f45 ; via_decryption_eor_two &0f44 49 78 EOR #&78 # actually EOR via_decryption_eor_two &0f46 4d 66 fe EOR &fe66 ; User VIA timer 1 latch LSB &0f49 ce 67 fe DEC &fe67 ; User VIA timer 1 latch MSB &0f4c 5d 01 10 EOR &1001,X ; payload + 1 # Runs over &1001 to &1100 &0f4f ce 69 fe DEC &fe69 ; User VIA timer 2 counter MSB &0f52 38 SEC &0f53 6e 68 fe ROR &fe68 ; User VIA timer 2 counter LSB &0f56 ac 69 fe LDY &fe69 ; User VIA timer 2 counter MSB &0f59 8c 64 fe STY &fe64 ; User VIA timer 1 counter LSB &0f5c 9d 00 10 STA &1000,X ; payload &0f5f e8 INX &0f60 d0 9e BNE &0f00 ; via_decryption_loop &0f62 a0 03 LDY #&03 # Clear memory on break &0f64 8c 58 02 STY &0258 ; ESCAPE/BREAK effect &0f67 a9 4c LDA #&4c ; JMP # Set BREAK intercept code to JMP &0287, endless loop &0f69 8d 87 02 STA &0287 ; BREAK intercept code &0f6c a9 87 LDA #&87 &0f6e 8d 88 02 STA &0288 ; BREAK intercept code + 1 &0f71 88 DEY ; 2 &0f72 8c 89 02 STY &0289 ; BREAK intercept code + 2 &0f75 a9 40 LDA #&40 ; RTI # Reset NMI handler &0f77 8d 00 0d STA &0d00 ; nmi_handler &0f7a ad fa ff LDA &fffa ; os_nmi_handler_address_low # Ensure NMI handler address hasn't been changed &0f7d d0 5e BNE &0fdd ; endless_wiping_loop &0f7f ad fb ff LDA &fffb ; os_nmi_handler_address_high &0f82 c9 0d CMP #&0d ; &0d00 = nmi_handler &0f84 d0 57 BNE &0fdd ; endless_wiping_loop &0f86 ee 01 0f INC &0f01 ; via_decryption_offset &0f89 f0 03 BEQ &0f8e ; calculate_checksum &0f8b 4c 00 0f JMP &0f00 ; via_decryption_loop ; calculate_checksum # Checksum &1000 - &1013 &0f8e a9 00 LDA #&00 &0f90 85 70 STA &70 ; calculated_checksum_one &0f92 85 71 STA &71 ; calculated_checksum_two &0f94 a8 TAY ; calculate_checksum_loop &0f95 a5 71 LDA &71 ; calculated_checksum_two &0f97 59 00 10 EOR &1000,Y ; payload &0f9a 85 71 STA &71 ; calculated_checksum_two &0f9c a2 08 LDX #&08 ; calculate_checksum_inner_loop &0f9e a5 71 LDA &71 ; calculated_checksum_two &0fa0 2a ROL A &0fa1 90 0c BCC &0faf ; clear_set &0fa3 a5 71 LDA &71 ; calculated_checksum_two &0fa5 49 08 EOR #&08 &0fa7 85 71 STA &71 ; calculated_checksum_two &0fa9 a5 70 LDA &70 ; calculated_checksum_one &0fab 49 10 EOR #&10 &0fad 85 70 STA &70 ; calculated_checksum_one ; clear_set &0faf 26 70 ROL &70 ; calculated_checksum_one &0fb1 26 71 ROL &71 ; calculated_checksum_two &0fb3 ca DEX &0fb4 d0 e8 BNE &0f9e ; calculate_checksum_inner_loop &0fb6 c8 INY &0fb7 c0 14 CPY #&14 &0fb9 d0 da BNE &0f95 ; calculate_checksum_loop &0fbb a5 70 LDA &70 ; calculated_checksum_one &0fbd cd fe 10 CMP &10fe ; valid_checksum_one &0fc0 d0 14 BNE &0fd6 ; invalid_checksum &0fc2 a5 71 LDA &71 ; calculated_checksum_two &0fc4 cd ff 10 CMP &10ff ; valid_checksum_two &0fc7 f0 37 BEQ &1000 ; payload # If the checksum matches, run the decrypted code &0fc9 d0 0b BNE &0fd6 ; invalid_checksum # Always branches ; unused &0fcb 48 69 20 42 54 57 20 2e 2e 2e 2e ; "Hi BTW ...." ; invalid_checksum &0fd6 a9 c8 LDA #&c8 ; Read/Write BREAK/ESCAPE effect # This is handled by the OS OSBYTE handler at &e99c, &0fd8 a2 03 LDX #&03 ; Clear memory on next RESET # which isn't checked in the decryption routine &0fda 20 f4 ff JSR &fff4 ; OSBYTE # so could be intercepted with a custom ROM ; endless_wiping_loop # Otherwise, if the checksum doesn't match, &0fdd 99 00 10 STA &1000,Y ; payload # Wipe &1000 - &10ff (failed decryption) with &c8 &0fe0 c8 INY &0fe1 4c dd 0f JMP &0fdd ; endless_wiping_loop ; unused &0fe4 20 28 63 29 20 4b 65 76 69 6e 20 45 64 77 61 72 ; " (c) Kevin Edwar" &0ff4 64 73 20 31 39 38 36 20 20 20 20 20 ; "ds 1986 " # &1000 - &10ff is decrypted by via_decryption_code ; payload &1000 a2 c8 LDX #&c8 &1002 9a TXS &1003 a9 03 LDA #&03 # Enable ESCAPE, clear memory on BREAK &1005 8d 58 02 STA &0258 ; ESCAPE/BREAK effect &1008 ea NOP &1009 ea NOP &100a ea NOP &100b ea NOP &100c ea NOP &100d ea NOP &100e ea NOP &100f ea NOP &1010 ea NOP &1011 ea NOP &1012 a0 00 LDY #&00 &1014 98 TYA ; wipe_1000_to_1014_loop # Wipe &1000 - &1014 &1015 99 00 10 STA &1000,Y ; payload &1018 c8 INY &1019 c0 15 CPY #&15 &101b d0 f8 BNE &1015 ; wipe_1000_to_1014_loop &101d a2 35 LDX #&35 ; check_vector_table_loop &101f bd 00 02 LDA &0200,X ; os_vector_table # Check all vectors are in ROM &1022 10 b9 BPL &0fdd ; endless_wiping_loop # Wipe payload if any are in RAM &1024 ca DEX &1025 ca DEX &1026 10 f7 BPL &101f ; check_vector_table_loop &1028 a0 00 LDY #&00 ; decrypt_0700_to_07ff_loop # Decrypt &0700 - &07ff &102a b9 00 07 LDA &0700,Y ; load_game &102d 49 7c EOR #&7c # actually EOR decryption_eor &102f ee 2e 10 INC &102e ; decryption_eor &1032 99 00 07 STA &0700,Y ; load_game &1035 c8 INY &1036 d0 f2 BNE &102a ; decrypt_0700_to_07ff_loop &1038 98 TYA ; 0 ; wipe_1000_to_1038_loop # Wipe &1000 - &1038 &1039 99 00 10 STA &1000,Y ; payload &103c c8 INY &103d c0 39 CPY #&39 &103f d0 f8 BNE &1039 ; wipe_1000_to_1038_loop ; call_load_game &1041 20 00 07 JSR &0700 ; load_game # Doesn't return; execution continues at decrypt_game ; unused &1044 a9 00 LDA #&00 # Unused code; obfuscation &1046 8d 41 10 STA &1041 ; call_load_game &1049 8d 42 10 STA &1042 ; call_load_game + 1 &104c 8d 43 10 STA &1043 ; call_load_game + 2 &104f a9 7f LDA #&7f # Disable all User VIA interrupts &1051 8d 6e fe STA &fe6e ; User VIA interrupt enable register &1054 58 CLI &1055 a9 8c LDA #&8c ; Select Tape FS &1057 a2 0c LDX #&0c ; 1200 baud &1059 20 f4 ff JSR &fff4 ; OSBYTE &105c a2 a9 LDX #&a9 ; &10a9 = load_game_command &105e a0 10 LDY #&10 &1060 20 f7 ff JSR &fff7 ; OSCLI &1063 ad 89 1a LDA &1a89 # Obfuscation &1066 48 PHA ; decryption_key_high &1067 ad f5 23 LDA &23f5 &106a 48 PHA ; decryption_key_low ; decrypt_game &106b 78 SEI &106c a9 03 LDA #&03 # Enable ESCAPE, clear memory on BREAK &106e 8d 58 02 STA &0258 ; ESCAPE/BREAK effect &1071 ad 87 02 LDA &0287 ; BREAK intercept code &1074 c9 4c CMP #&4c ; JMP &1076 f0 03 BEQ &107b ; no_tampering_detected &1078 4c dd 0f JMP &0fdd ; endless_wiping_loop ; no_tampering_detected &107b a9 40 LDA #&40 # Set timer 1 to continuous countdown &107d 8d 6b fe STA &fe6b ; User VIA auxiliary control register &1080 68 PLA ; decryption_key_low # Use values set at &074a for decryption &1081 8d 68 fe STA &fe68 ; User VIA timer 2 counter LSB &1084 68 PLA ; decryption_key_high &1085 8d 69 fe STA &fe69 ; User VIA timer 2 counter MSB &1088 a0 00 LDY #&00 &108a a2 46 LDX #&46 ; decrypt_1400_to_59ff_loop # Decrypt &1400 - &59ff &108c b9 00 14 LDA &1400,Y # actually LDA decryption_read_address,Y &108f 4d 68 fe EOR &fe68 ; User VIA timer 2 counter LSB &1092 ee 68 fe INC &fe68 ; User VIA timer 2 counter LSB &1095 4d 69 fe EOR &fe69 ; User VIA timer 2 counter MSB &1098 99 00 14 STA &1400,Y # actually LDA decryption_write_address,Y &109b c8 INY &109c d0 ee BNE &108c ; decrypt_1400_to_59ff_loop &109e ee 8e 10 INC &108e ; decryption_read_address_high &10a1 ee 9a 10 INC &109a ; decryption_write_address_high &10a4 ca DEX &10a5 d0 e5 BNE &108c ; decrypt_1400_to_59ff_loop &10a7 58 CLI &10a8 60 RTS # Leaves to main_binary_entry_point, pushed at &0741 ; load_game_command # Unused; obfuscation &10a9 4c 2e 47 41 4d 45 83 7f 20 31 34 30 30 0d ; "L.GAME.. 1400" ; game_string # Filename contains TELETEXT_YELLOW and DELETE &10b7 47 41 4d 45 83 7f 0d ; "GAME.." &10be 50 72 6f 74 65 63 74 69 6f 6e 20 28 63 29 20 4b ; "Protection (c) K" &10ce 65 76 69 6e 20 45 64 77 61 72 64 73 20 31 39 38 ; "evin Edwards 198" &10de 36 20 59 6f 75 20 74 6f 6f 6b 20 79 6f 75 72 20 ; "6 You took your " &10ee 74 69 6d 65 20 21 20 48 69 20 74 6f 20 42 54 57 ; "time ! Hi to BTW" ; valid_checksum_one &10fe 54 ; valid_checksum_two &10ff 67 &1100 00 # Used at &0f4c in final round of via_decryption ; unused &1101 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1111 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1121 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1131 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1141 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1151 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1161 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1171 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1181 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &1191 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &11a1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &11b1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &11c1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &11d1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &11e1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &11f1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # &1200 - &12ff moved to &0700 - &07ff at &0e0c and decrypted at &102a ; load_game &0700 78 SEI &0701 a2 e3 LDX #&e3 # Obfuscation # actually LDX stack_obfuscation &0703 9a TXS &0704 8d 02 07 STA &0702 ; stack_obfuscation &0707 a9 01 LDA #&01 # Reset controller by writing 1 and 0 to reset register &0709 8d 82 fe STA &fe82 ; 8271 disk controller reset register &070c 20 3b 07 JSR &073b ; short_delay &070f a9 00 LDA #&00 # Then configure controller to use unhelpful settings &0711 8d 82 fe STA &fe82 ; 8271 disk controller reset register &0714 20 3b 07 JSR &073b ; short_delay &0717 a9 35 LDA #&35 # Command &35: specify &0719 8d 80 fe STA &fe80 ; 8271 disk controller command register &071c 20 3b 07 JSR &073b ; short_delay &071f a9 0d LDA #&0d # Parameter &0d: specify initialization &0721 8d 81 fe STA &fe81 ; 8271 disk controller parameter register &0724 20 3b 07 JSR &073b ; short_delay &0727 a9 01 LDA #&01 &0729 8d 81 fe STA &fe81 ; 8271 disk controller parameter register # Set step rate to 2ms &072c 20 3b 07 JSR &073b ; short_delay &072f 8d 81 fe STA &fe81 ; 8271 disk controller parameter register # Set head settling time to 2ms &0732 20 3b 07 JSR &073b ; short_delay &0735 8d 81 fe STA &fe81 ; 8271 disk controller parameter register # Set head load time to 4ms, index count to 0 &0738 4c 41 07 JMP &0741 ; prepare_stack_and_load_game ; short_delay &073b a2 14 LDX #&14 ; short_delay_loop &073d ca DEX &073e d0 fd BNE &073d ; delay &0740 60 RTS ; prepare_stack_and_load_game &0741 a2 d4 LDX #&d4 &0743 9a TXS &0744 a9 57 LDA #&57 ; &576e = main_binary_entry_point - 1 # Used at &10a8 &0746 48 PHA &0747 a9 6e LDA #&6e &0749 48 PHA &074a a9 c3 LDA #&c3 # Used to decrypt main binary &074c 48 PHA ; decryption_key_low &074d a9 66 LDA #&66 # Used to decrypt main binary &074f 48 PHA ; decryption_key_high &0750 a9 10 LDA #&10 ; &106a = decrypt_game - 1 # Used at &07b4 &0752 48 PHA &0753 a9 6a LDA #&6a &0755 48 PHA &0756 a9 ff LDA #&ff ; &ffdc = OSFILE - 1 &0758 48 PHA &0759 a9 dc LDA #&dc &075b 48 PHA &075c a9 00 LDA #&00 &075e 8d 41 10 STA &1041 ; call_load_game &0761 8d 42 10 STA &1042 ; call_load_game + 1 &0764 8d 43 10 STA &1043 ; call_load_game + 2 &0767 a2 69 LDX #&69 &0769 8a TXA ; wipe_0701_to_0769_loop # Wipe &0701 - &0769 &076a 9d 00 07 STA &0700,X ; load_game &076d ca DEX &076e d0 fa BNE &076a ; wipe_0701_to_0769_loop &0770 a9 b7 LDA #&b7 ; &10b7 = game_string # Set up OSFILE block at &0171 to load GAME at 1400 &0772 8d 71 01 STA &0171 ; osfile_block &0775 a9 10 LDA #&10 &0777 8d 72 01 STA &0172 ; osfile_block + 1 &077a a9 00 LDA #&00 &077c 8d 73 01 STA &0173 ; osfile_block + 2 &077f 8d 77 01 STA &0177 ; osfile_block + 6 &0782 a9 14 LDA #&14 ; &1400 = main_binary_start_address &0784 8d 74 01 STA &0174 ; osfile_block + 3 &0787 a9 7f LDA #&7f # Disable all User VIA interrupts &0789 8d 6e fe STA &fe6e ; User VIA interrupt enable register &078c a2 8f LDX #&8f &078e a9 ff LDA #&ff ; wipe_0701_to_078f_loop # Wipe &0701 - &078f &0790 9d 00 07 STA &0700,X ; load_game &0793 ca DEX &0794 d0 fa BNE &0790 ; wipe_0701_to_078f_loop &0796 58 CLI &0797 a9 8c LDA #&8c ; Select Tape FS &0799 a2 0c LDX #&0c ; 1200 baud &079b 20 f4 ff JSR &fff4 ; OSBYTE &079e a9 8b LDA #&8b ; Set filing system attributes # *OPT 1,0 (turn off filing system messages) &07a0 a2 01 LDX #&01 &07a2 a0 00 LDY #&00 &07a4 20 f4 ff JSR &fff4 ; OSBYTE &07a7 a2 71 LDX #&71 ; &0171 = osfile_block &07a9 a9 ff LDA #&ff &07ab a0 ac LDY #&ac ; wipe_0701_to_07ac_loop # Wipe &0701 - &07ac &07ad 99 00 07 STA &0700,Y ; load_game &07b0 88 DEY &07b1 d0 fa BNE &07ad ; wipe_0700_to_07ac_loop &07b3 c8 INY ; &01 &07b4 60 RTS # Leaves to OSFILE, then decrypt_game ; unused &07b5 50 72 6f 74 65 63 74 69 6f 6e 20 28 63 29 20 4b ; "Protection (c) K" &07c5 65 76 69 6e 20 45 64 77 61 72 64 73 20 31 39 38 ; "evin Edwards 198" &07d5 36 50 72 6f 74 65 63 74 69 6f 6e 20 28 63 29 20 ; "6Protection (c) " &07e5 4b 65 76 69 6e 20 45 64 77 61 72 64 73 20 31 39 ; "Kevin Edwards 19" &07f5 38 36 50 72 6f 74 65 63 74 69 6f ; "86Protectio" Game disassembly ================ ; GAME?? ; BBC1BBC2 BBC1BBC2 4600 # Loaded at &1400 &1400 00 02 17 00 00 84 # Continuation of mover_sprite_34 ; mover_sprite_35 (SPRITE_MACHINE_GUN) &1406 00 00 02 00 02 00 02 94 0d 00 85 00 06 a8 94 0c &1416 00 8a 94 00 08 40 a8 94 04 00 fc d4 85 bc 80 94 &1426 00 0d bc d4 7c 06 14 bc 5e bc 94 bc 00 0c a8 40 &1436 94 68 06 00 a8 bc 8f bc a8 bc 00 0e 80 94 a8 0a &1446 00 bc 8f bc 80 a8 00 0c bc 0c 00 bc 9e bc 94 00 &1456 89 ; mover_sprite_37 (SPRITE_SAM) &1457 00 94 00 03 bc 94 00 04 bc 9c ac 94 c0 54 00 08 &1467 a8 80 a8 9c ac 94 bc 8c bc c0 54 bc 05 2c bc 54 &1477 00 12 94 c0 bc 8c bc 8c ac bc 80 bc ac 8c bc 05 &1487 0c bc 56 a8 00 14 bc d4 bc 9c bc 4c fc 4c bc 05 &1497 0c bc 54 00 0f 7c 04 1c bc 4c fc 4c bc 05 0c bc &14a7 56 a8 00 0f bc c0 bc 8c bc 4c bc a8 bc 4c bc 05 &14b7 0c bc 54 00 11 c0 94 ac 9c bc 8c bc a8 80 a8 bc &14c7 9c bc 05 0c bc 56 a8 00 14 bc 94 ac 9c a8 80 a8 &14d7 9c bc 05 00 07 28 00 0f bc 9c a8 00 05 bc 00 83 ; mover_sprite_38 (SPRITE_ROCKET) &14e7 00 40 54 00 04 94 bc 96 0a 29 94 00 08 80 a8 96 &14f7 bc 09 28 00 88 ; enemy_helicopters_initial_x &14fc 29 57 ; scenery_data_one ; s d &14fe 01 06 ; SCENERY_GREEN_YELLOW_PILLBOX &1500 81 0c ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &1502 0e 14 ; SCENERY_HEADQUARTERS_SIGN &1504 0a 3c ; SCENERY_LOW_RED_BUILDING &1506 16 42 ; SCENERY_RED_BUILDING_WITH_DOOR &1508 96 4b ; SCENERY_RED_BUILDING_WITH_DOOR | SCENERY_FLIPPED &150a 8d 58 ; SCENERY_HIGH_RED_BUILDING | SCENERY_FLIPPED &150c 0d 60 ; SCENERY_HIGH_RED_BUILDING &150e 0a 6a ; SCENERY_LOW_RED_BUILDING &1510 8a 70 ; SCENERY_LOW_RED_BUILDING | SCENERY_FLIPPED &1512 16 78 ; SCENERY_RED_BUILDING_WITH_DOOR &1514 96 81 ; SCENERY_RED_BUILDING_WITH_DOOR | SCENERY_FLIPPED &1516 02 8c ; SCENERY_LOW_GREEN_YELLOW_PILLBOX &1518 82 92 ; SCENERY_LOW_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &151a 8c 9a ; SCENERY_SANDBAGS | SCENERY_FLIPPED &151c 07 f0 ; SCENERY_SIGNPOST &151e 06 1a ; SCENERY_TREES_ONE &1520 15 24 ; SCENERY_TREES_TWO &1522 14 c8 ; SCENERY_HIGH_RUINS &1524 12 d4 ; SCENERY_LOW_RUINS &1526 94 e0 ; SCENERY_HIGH_RUINS | SCENERY_FLIPPED &1528 0b f8 ; SCENERY_GRAVES_WITH_HELMETS &152a 11 fb ; SCENERY_OIL_DRUM &152c 11 01 ; SCENERY_OIL_DRUM &152e 01 10 ; SCENERY_GREEN_YELLOW_PILLBOX &1530 81 16 ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &1532 15 a0 ; SCENERY_TREES_TWO &1534 06 a8 ; SCENERY_TREES_ONE &1536 95 b2 ; SCENERY_TREES_TWO | SCENERY_FLIPPED &1538 06 ba ; SCENERY_TREES_ONE &153a 86 c4 ; SCENERY_TREES_ONE | SCENERY_FLIPPED &153c 09 f0 ; SCENERY_GRAVES &153e 07 50 ; SCENERY_SIGNPOST &1540 13 64 ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL &1542 93 6a ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL | SCENERY_FLIPPED &1544 14 8a ; SCENERY_HIGH_RUINS &1546 11 7c ; SCENERY_OIL_DRUM &1548 0f 8a ; SCENERY_CONNING_TOWER &154a 8f 92 ; SCENERY_CONNING_TOWER | SCENERY_FLIPPED &154c 8c 9c ; SCENERY_SANDBAGS | SCENERY_FLIPPED &154e 12 96 ; SCENERY_LOW_RUINS &1550 94 a2 ; SCENERY_HIGH_RUINS | SCENERY_FLIPPED &1552 92 ae ; SCENERY_LOW_RUINS | SCENERY_FLIPPED &1554 8d c8 ; SCENERY_HIGH_RED_BUILDING | SCENERY_FLIPPED &1556 0d d0 ; SCENERY_HIGH_RED_BUILDING &1558 0a dc ; SCENERY_LOW_RED_BUILDING &155a 16 e2 ; SCENERY_RED_BUILDING_WITH_DOOR &155c 96 eb ; SCENERY_RED_BUILDING_WITH_DOOR | SCENERY_FLIPPED &155e 8a f4 ; SCENERY_LOW_RED_BUILDING | SCENERY_FLIPPED &1560 16 01 ; SCENERY_RED_BUILDING_WITH_DOOR &1562 0d 0a ; SCENERY_HIGH_RED_BUILDING &1564 16 18 ; SCENERY_RED_BUILDING_WITH_DOOR &1566 96 21 ; SCENERY_RED_BUILDING_WITH_DOOR | SCENERY_FLIPPED &1568 8d 2c ; SCENERY_HIGH_RED_BUILDING | SCENERY_FLIPPED &156a 16 34 ; SCENERY_RED_BUILDING_WITH_DOOR &156c 96 3d ; SCENERY_RED_BUILDING_WITH_DOOR | SCENERY_FLIPPED &156e 0d 46 ; SCENERY_HIGH_RED_BUILDING &1570 0a 50 ; SCENERY_LOW_RED_BUILDING &1572 8a 56 ; SCENERY_LOW_RED_BUILDING | SCENERY_FLIPPED &1574 12 64 ; SCENERY_LOW_RUINS &1576 14 b1 ; SCENERY_HIGH_RUINS &1578 0c c2 ; SCENERY_SANDBAGS &157a 01 ce ; SCENERY_GREEN_YELLOW_PILLBOX &157c 81 d4 ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &157e 11 dc ; SCENERY_OIL_DRUM &1580 11 e2 ; SCENERY_OIL_DRUM &1582 02 0a ; SCENERY_LOW_GREEN_YELLOW_PILLBOX &1584 82 10 ; SCENERY_LOW_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &1586 8c 18 ; SCENERY_SANDBAGS | SCENERY_FLIPPED &1588 06 c8 ; SCENERY_TREES_ONE &158a 86 d2 ; SCENERY_TREES_ONE | SCENERY_FLIPPED &158c 15 dc ; SCENERY_TREES_TWO &158e 06 e4 ; SCENERY_TREES_ONE &1590 95 ee ; SCENERY_TREES_TWO | SCENERY_FLIPPED &1592 12 8c ; SCENERY_LOW_RUINS &1594 00 b4 ; SCENERY_WHITE_GREEN_PILLBOX &1596 80 ba ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &1598 13 c0 ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL &159a 93 c6 ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL | SCENERY_FLIPPED &159c 11 f6 ; SCENERY_OIL_DRUM &159e 11 fc ; SCENERY_OIL_DRUM &15a0 00 1e ; SCENERY_WHITE_GREEN_PILLBOX &15a2 80 24 ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &15a4 8c 2c ; SCENERY_SANDBAGS | SCENERY_FLIPPED &15a6 06 c8 ; SCENERY_TREES_ONE &15a8 14 e6 ; SCENERY_HIGH_RUINS &15aa 12 06 ; SCENERY_LOW_RUINS &15ac 0b a0 ; SCENERY_GRAVES_WITH_HELMETS &15ae 15 f0 ; SCENERY_TREES_TWO &15b0 12 f8 ; SCENERY_LOW_RUINS &15b2 13 b4 ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL &15b4 93 ba ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL | SCENERY_FLIPPED &15b6 8c c2 ; SCENERY_SANDBAGS | SCENERY_FLIPPED &15b8 06 b4 ; SCENERY_TREES_ONE &15ba 15 be ; SCENERY_TREES_TWO &15bc 12 0a ; SCENERY_LOW_RUINS &15be 02 1e ; SCENERY_LOW_GREEN_YELLOW_PILLBOX &15c0 82 24 ; SCENERY_LOW_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &15c2 01 2a ; SCENERY_GREEN_YELLOW_PILLBOX &15c4 81 30 ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &15c6 11 68 ; SCENERY_OIL_DRUM &15c8 11 6e ; SCENERY_OIL_DRUM &15ca 0f 78 ; SCENERY_CONNING_TOWER &15cc 8f 80 ; SCENERY_CONNING_TOWER | SCENERY_FLIPPED &15ce 01 90 ; SCENERY_GREEN_YELLOW_PILLBOX &15d0 81 96 ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &15d2 8c 9d ; SCENERY_SANDBAGS | SCENERY_FLIPPED &15d4 06 f0 ; SCENERY_TREES_ONE &15d6 15 6e ; SCENERY_TREES_TWO &15d8 0c c8 ; SCENERY_SANDBAGS &15da 00 d2 ; SCENERY_WHITE_GREEN_PILLBOX &15dc 80 d8 ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &15de 13 de ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL &15e0 93 e4 ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL | SCENERY_FLIPPED &15e2 12 f0 ; SCENERY_LOW_RUINS &15e4 8d a0 ; SCENERY_HIGH_RED_BUILDING | SCENERY_FLIPPED &15e6 0d a8 ; SCENERY_HIGH_RED_BUILDING &15e8 0c 78 ; SCENERY_SANDBAGS &15ea 00 82 ; SCENERY_WHITE_GREEN_PILLBOX &15ec 80 88 ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &15ee 13 8e ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL &15f0 93 94 ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL | SCENERY_FLIPPED &15f2 00 9a ; SCENERY_WHITE_GREEN_PILLBOX &15f4 80 a0 ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &15f6 13 a6 ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL &15f8 93 ac ; SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL | SCENERY_FLIPPED &15fa 00 b2 ; SCENERY_WHITE_GREEN_PILLBOX &15fc 80 b8 ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &15fe 11 d2 ; SCENERY_OIL_DRUM &1600 11 d8 ; SCENERY_OIL_DRUM &1602 11 fc ; SCENERY_OIL_DRUM &1604 0f 04 ; SCENERY_CONNING_TOWER &1606 8f 0c ; SCENERY_CONNING_TOWER | SCENERY_FLIPPED &1608 00 21 ; SCENERY_WHITE_GREEN_PILLBOX &160a 80 27 ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &160c 8c 2e ; SCENERY_SANDBAGS | SCENERY_FLIPPED &160e 06 0a ; SCENERY_TREES_ONE &1610 15 14 ; SCENERY_TREES_TWO &1612 86 1c ; SCENERY_TREES_ONE | SCENERY_FLIPPED &1614 06 26 ; SCENERY_TREES_ONE &1616 95 30 ; SCENERY_TREES_TWO | SCENERY_FLIPPED &1618 0b 38 ; SCENERY_GRAVES_WITH_HELMETS &161a 06 40 ; SCENERY_TREES_ONE &161c 14 4a ; SCENERY_HIGH_RUINS &161e 15 56 ; SCENERY_TREES_TWO &1620 07 f2 ; SCENERY_SIGNPOST &1622 06 b4 ; SCENERY_TREES_ONE &1624 15 be ; SCENERY_TREES_TWO &1626 11 c6 ; SCENERY_OIL_DRUM &1628 06 cc ; SCENERY_TREES_ONE &162a 86 d6 ; SCENERY_TREES_ONE | SCENERY_FLIPPED &162c 15 e0 ; SCENERY_TREES_TWO &162e 12 c8 ; SCENERY_LOW_RUINS &1630 14 d4 ; SCENERY_HIGH_RUINS &1632 94 e0 ; SCENERY_HIGH_RUINS | SCENERY_FLIPPED &1634 09 ec ; SCENERY_GRAVES &1636 12 f4 ; SCENERY_LOW_RUINS &1638 12 be ; SCENERY_LOW_RUINS &163a 00 ce ; SCENERY_WHITE_GREEN_PILLBOX &163c 80 d4 ; SCENERY_WHITE_GREEN_PILLBOX | SCENERY_FLIPPED &163e 06 a0 ; SCENERY_TREES_ONE &1640 15 aa ; SCENERY_TREES_TWO &1642 14 64 ; SCENERY_HIGH_RUINS &1644 01 71 ; SCENERY_GREEN_YELLOW_PILLBOX &1646 81 77 ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &1648 12 50 ; SCENERY_LOW_RUINS &164a 01 98 ; SCENERY_GREEN_YELLOW_PILLBOX &164c 81 9e ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &164e 12 a0 ; SCENERY_LOW_RUINS &1650 01 b4 ; SCENERY_GREEN_YELLOW_PILLBOX &1652 81 ba ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &1654 0a c8 ; SCENERY_LOW_RED_BUILDING &1656 8a ce ; SCENERY_LOW_RED_BUILDING | SCENERY_FLIPPED &1658 16 d6 ; SCENERY_RED_BUILDING_WITH_DOOR &165a 96 df ; SCENERY_RED_BUILDING_WITH_DOOR | SCENERY_FLIPPED &165c 8a e8 ; SCENERY_LOW_RED_BUILDING | SCENERY_FLIPPED &165e 8d ef ; SCENERY_HIGH_RED_BUILDING | SCENERY_FLIPPED &1660 0d f7 ; SCENERY_HIGH_RED_BUILDING &1662 0e 02 ; SCENERY_HEADQUARTERS_SIGN &1664 02 0a ; SCENERY_LOW_GREEN_YELLOW_PILLBOX &1666 82 10 ; SCENERY_LOW_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED &1668 81 f9 ; SCENERY_GREEN_YELLOW_PILLBOX | SCENERY_FLIPPED # Not displayed ; unused &166a 17 ; scenery_data_two ; s d y &166b 10 fe 00 ; SCENERY_BRIDGE &166e 90 08 00 ; SCENERY_BRIDGE | SCENERY_FLIPPED &1671 09 f0 17 ; SCENERY_GRAVES &1674 08 e5 14 ; SCENERY_RUNWAY &1677 08 f1 14 ; SCENERY_RUNWAY &167a 08 fd 14 ; SCENERY_RUNWAY &167d 0b f8 17 ; SCENERY_GRAVES_WITH_HELMETS &1680 10 74 00 ; SCENERY_BRIDGE &1683 90 7e 00 ; SCENERY_BRIDGE | SCENERY_FLIPPED &1686 08 64 14 ; SCENERY_RUNWAY &1689 08 70 14 ; SCENERY_RUNWAY &168c 06 78 17 ; SCENERY_TREES_ONE &168f 06 80 17 ; SCENERY_TREES_ONE &1692 07 89 17 ; SCENERY_SIGNPOST &1695 0b 82 17 ; SCENERY_GRAVES_WITH_HELMETS &1698 08 d2 14 ; SCENERY_RUNWAY &169b 08 de 14 ; SCENERY_RUNWAY &169e 08 ea 14 ; SCENERY_RUNWAY &16a1 10 f4 00 ; SCENERY_BRIDGE &16a4 90 fe 00 ; SCENERY_BRIDGE | SCENERY_FLIPPED &16a7 07 06 17 ; SCENERY_SIGNPOST &16aa 0b 0a 17 ; SCENERY_GRAVES_WITH_HELMETS &16ad 07 cc 17 ; SCENERY_SIGNPOST &16b0 08 36 14 ; SCENERY_RUNWAY &16b3 08 42 14 ; SCENERY_RUNWAY &16b6 08 4e 14 ; SCENERY_RUNWAY &16b9 08 5a 14 ; SCENERY_RUNWAY &16bc 0b 64 17 ; SCENERY_GRAVES_WITH_HELMETS &16bf 07 6a 17 ; SCENERY_SIGNPOST &16c2 0b 6e 17 ; SCENERY_GRAVES_WITH_HELMETS &16c5 08 c0 14 ; SCENERY_RUNWAY &16c8 08 cc 14 ; SCENERY_RUNWAY &16cb 08 d8 14 ; SCENERY_RUNWAY &16ce 08 e4 14 ; SCENERY_RUNWAY &16d1 08 f0 14 ; SCENERY_RUNWAY &16d4 07 fa 17 ; SCENERY_SIGNPOST &16d7 10 fa 00 ; SCENERY_BRIDGE &16da 90 04 00 ; SCENERY_BRIDGE | SCENERY_FLIPPED &16dd 08 c6 14 ; SCENERY_RUNWAY &16e0 08 d2 14 ; SCENERY_RUNWAY &16e3 06 aa 17 ; SCENERY_TREES_ONE &16e6 07 ae 17 ; SCENERY_SIGNPOST &16e9 07 b4 17 ; SCENERY_SIGNPOST &16ec 15 bb 17 ; SCENERY_TREES_TWO &16ef 10 c0 00 ; SCENERY_BRIDGE &16f2 90 ca 00 ; SCENERY_BRIDGE | SCENERY_FLIPPED &16f5 10 d4 00 ; SCENERY_BRIDGE &16f8 90 de 00 ; SCENERY_BRIDGE | SCENERY_FLIPPED &16fb 10 e8 00 ; SCENERY_BRIDGE &16fe 90 f2 00 ; SCENERY_BRIDGE | SCENERY_FLIPPED &1701 07 aa 17 ; SCENERY_SIGNPOST &1704 07 96 17 ; SCENERY_SIGNPOST &1707 07 96 ; SCENERY_SIGNPOST # Not displayed ; flipped_mover_sprite_addresses_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1709 fd da a7 72 3e 0c e1 b2 81 58 32 03 d6 b1 89 5c ; &00 &1719 29 b1 f2 2c 79 7f d1 8c 57 36 0b e0 b5 93 6b 3e ; &10 &1729 0c e2 74 0a aa 6b 36 f4 94 3c 15 06 f4 d8 9d 00 ; &20 &1739 00 00 00 a7 01 4d 00 e3 f3 ; &30 ; trigger_points_x_low_table &1742 ff 44 08 90 1c ae 30 c2 80 28 d7 58 b5 dd 48 c7 &1752 cb 52 d0 8e 80 fa b1 64 f0 0c 82 78 16 20 fa ac &1762 66 3e cd 7a 02 ; trigger_points_x_high_table &1767 fe 01 02 02 03 03 04 04 05 07 07 08 08 09 0a 0a &1777 0b 0c 0c 0d 0e 0e 0f 10 10 12 12 13 14 15 15 16 &1787 17 18 18 19 1a 63 ; new_movers_type &178d 01 13 01 83 83 13 01 83 83 83 01 83 83 83 83 13 &179d 01 83 89 83 83 83 82 8c 83 82 83 82 84 83 8c 82 &17ad 8c 8c 8c 82 0a 83 84 89 84 82 8a 8c 83 8c 8c 84 &17bd 83 82 8a 89 83 02 01 84 82 8a 83 8c 83 84 8c 83 &17cd 01 09 01 13 83 89 83 84 13 84 83 8c 8c 83 84 83 &17dd 8a 82 13 83 89 83 83 82 8a 84 83 83 89 8c 83 8a &17ed 83 82 83 8c 83 83 8a 82 83 13 83 84 83 84 89 83 &17fd 01 02 83 82 01 ; new_movers_initial_x_low &1802 1e b6 d2 fa 0a 1e 38 6e 82 8c c1 26 50 74 b6 dc &1812 3a 5a 64 82 b4 f6 32 3c 78 b4 da 0a 36 be e6 14 &1822 46 70 82 a0 20 3c 6a a0 b5 dc 04 1e 50 3a 46 70 &1832 96 bc c8 16 aa d2 1a 42 6e a6 d2 02 1e 8c aa dc &1842 00 a9 ce fa 02 46 6e a0 00 28 76 b4 c8 01 3c 64 &1852 6c 5a 82 aa d0 0a 82 c6 f0 0a 64 02 46 6e 9e 1e &1862 48 6e aa fa 28 6e b4 01 32 8c b4 dc 1f 6e 8c c8 &1872 08 2e 50 78 96 ; new_movers_initial_x_high_and_flags # ..218421 x high &1877 80 00 40 80 81 01 41 41 81 41 81 42 42 82 82 02 # 84...... flags: &1887 43 83 03 83 43 43 84 04 84 44 44 45 45 85 05 46 # &00 stationary &1897 06 07 07 87 08 88 48 08 88 48 09 09 49 0a 0a 4a # &40 moves between limits &18a7 4a 8a 0a 0b 4b 8b 4c 8c 4c 0c 4c 0d 8d 4d 0d 4d # &80 stationary, but gun animation &18b7 8e 0e 4e 0e 4f 0f 4f 4f 10 50 50 10 10 51 51 91 &18c7 11 52 12 52 12 93 53 53 13 54 54 55 15 15 55 16 &18d7 56 56 96 16 57 57 17 98 58 18 58 58 59 99 19 59 &18e7 9a 5a 9a 5a 9a ; new_helicopter_types &18ec 85 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER_WITH_MISSILE &18ed 86 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER &18ee 85 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER_WITH_MISSILE &18ef 87 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER_WITH_SOLDIER &18f0 85 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER_WITH_MISSILE &18f1 06 ; MOVER_TYPE_HELICOPTER &18f2 87 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER_WITH_SOLDIER &18f3 86 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER ; movers_firing_cooldown &18f4 00 00 00 00 00 00 00 00 00 00 00 00 ; flipped_scenery_sprite_addresses_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1900 78 26 ea ba a8 a5 90 ea 27 6f ea 54 9b 29 80 f4 ; &00 &1910 7b ce 65 3d 0c e4 a2 ; &10 ; flipped_scenery_sprite_addresses_high_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1917 09 0a 0a 0b 0c 0d 0e 0e 0f 0f 0f 10 10 11 11 11 ; &00 &1927 12 12 13 06 07 07 01 ; &10 ; unflipped_scenery_sprite_addresses_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &192e 00 93 4a 10 c9 b8 b8 a2 f0 2d 77 09 60 a1 38 89 ; &00 &193e 06 87 db 80 66 16 00 ; &10 ; unflipped_scenery_sprite_addresses_high_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1945 09 09 0a 0b 0b 0c 0d 0e 0e 0f 0f 10 10 10 11 11 ; &00 &1955 12 12 12 05 06 07 01 ; &10 ; scenery_sprite_width_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &195c 05 05 05 0b 0b 0b 09 06 0b 07 05 07 07 07 07 07 ; &00 &196c 09 05 0b 05 0b 07 08 ; &10 ; unflipped_mover_sprite_addresses_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1973 dd aa 75 41 0f e4 b5 84 5b 35 0c d9 b4 8c 5f 2f ; &00 &1983 fe 10 36 83 d8 b5 8f 5a 39 0e e3 b8 96 6e 41 0f ; &10 &1993 e9 7c 12 b0 6e 3c fe 9e 3f 19 0b f9 e0 a3 8b 00 ; &20 &19a3 00 00 00 6e aa 06 00 57 e7 ; &30 ; unflipped_mover_sprite_addresses_high_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &19ac 3f 3f 3f 3f 3f 3e 3e 3e 3e 3e 3e 3d 3d 3d 3d 3d ; &00 &19bc 3c 0b 3c 3b 3a 34 3a 3a 3a 3a 39 39 39 39 39 39 ; &10 &19cc 38 38 38 37 37 37 36 36 36 36 36 35 35 35 35 35 ; &20 &19dc 34 34 33 13 13 14 00 14 14 ; &30 ; flipped_mover_sprite_addresses_high_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &19e5 3f 3f 3f 3f 3f 3f 3e 3e 3e 3e 3e 3e 3d 3d 3d 3d ; &00 &19f5 3d 0b 3c 3c 3b 35 3a 3a 3a 3a 3a 39 39 39 39 39 ; &10 &1a05 39 38 38 38 37 37 37 36 36 36 36 36 35 35 35 35 ; &20 &1a15 35 34 34 13 14 14 00 14 14 ; &30 ; movers_type_and_colour ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1a1e 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1a2e 00 00 00 00 00 00 00 00 08 0d 06 05 06 08 05 05 ; &10 &1a3e 0d ; &20 ; movers_frame_and_flip ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1a3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1a4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &10 &1a5f 00 ; &20 ; movers_x_low ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1a60 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1a70 00 00 00 00 00 00 00 00 ec 66 fa da 37 50 c1 ea ; &10 &1a80 cf ; &20 ; movers_x_high ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1a81 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1a91 00 00 00 00 00 00 00 00 02 05 07 09 0e 0e 11 11 ; &10 &1aa1 14 ; &20 ; movers_y ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1aa2 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1ab2 00 00 00 00 00 00 00 00 18 18 18 18 18 18 18 18 ; &10 &1ac2 18 ; &20 ; movers_screen_address_low ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1ac3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1ad3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &10 &1ae3 00 ; &20 ; movers_screen_address_high ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1ae4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1af4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &10 &1b04 00 ; &20 ; movers_raster_y ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1b05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &00 &1b15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &10 &1b25 00 ; &20 ; projectiles_x_velocity &1b26 00 00 00 00 00 00 00 00 00 00 00 00 ; projectiles_y_velocity &1b32 00 00 00 00 00 00 00 00 00 00 00 00 ; projectiles_is_rocket &1b3e 00 00 00 00 00 00 00 00 00 00 00 00 ; projectiles_ttl &1b4a 00 00 00 00 00 00 00 00 00 00 00 00 ; mover_types_first_sprite_animation_offsets ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1b56 00 00 00 00 00 2b 31 37 49 59 59 4f 5c 3d 41 46 ; &00 &1b66 47 48 5d 5e 0e 1c 0e 1c 50 25 25 25 25 5a 5b ; &10 ; mover_types_width_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1b75 06 06 06 06 06 0b 0b 0b 0b 09 09 0b 0b 06 06 02 ; &00 &1b85 02 03 02 03 ; &10 ; mover_types_height_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1b89 1d 1b 1d 1b 1b 1c 1b 1c 1c 16 16 17 17 1d 0f 03 ; &00 &1b99 04 04 0d 04 ; &10 ; mover_types_third_sprite &1b9d 09 ; &00 (MOVER_TYPE_PLAYER) : SPRITE_PLAYER_HEAD &1b9e 0c ; &01 (MOVER_TYPE_SOLDIER_WITH_RIFLE) : SPRITE_SOLDIER_HEAD &1b9f 0e ; &02 (MOVER_TYPE_OFFICER_WITH_PISTOL) : SPRITE_OFFICER_HEAD &1ba0 20 ; &03 (MOVER_TYPE_TROOPER_WITH_RIFLE) : SPRITE_TROOPER_HEAD &1ba1 20 ; &04 (MOVER_TYPE_TROOPER_WITH_BAZOOKA) : SPRITE_TROOPER_HEAD ; mover_types_second_sprite_offset ; 0 1 2 3 4 5 6 7 8 9 a &1ba2 00 00 00 00 00 0e 0e 14 14 1a 1b ; mover_types_animation_frames ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1bad 06 06 06 06 06 06 06 06 06 01 01 01 01 04 05 01 ; &00 &1bbd 01 01 01 01 ; &10 ; mover_types_new_grenade_bomb_or_rocket_y_offset ; 0 1 2 3 4 5 6 7 8 9 a b c &1bc1 22 22 22 22 22 01 01 01 01 22 00 01 22 ; mover_types_new_bullet_y_offset ; 0 1 2 3 4 5 6 7 8 9 a b &1bce 10 10 10 10 10 10 0f 14 10 00 18 10 ; mover_types_new_grenade_bomb_or_rocket_type ; 0 1 2 3 4 5 6 7 8 9 a b c &1bda 10 00 10 00 00 11 10 11 11 10 00 00 12 ; mover_types_new_grenade_bomb_or_rocket_y_velocity ; 0 1 2 3 4 5 6 7 8 9 a b c &1be7 06 00 06 00 00 80 80 80 80 08 00 80 01 ; mover_types_new_bullet_type ; 0 1 2 3 4 5 6 7 8 9 a b c &1bf4 0f 0f 0f 0f 11 0f 0f 0f 00 00 0f 0f 00 ; mover_types_maximum_firing_cooldown ; 0 1 2 3 4 5 6 7 8 9 a &1c01 0a 0a 0a 0a 0a 05 06 02 05 00 02 ; player_helicopter_types_vertical_speed ; 5 6 7 8 9 a b &1c0c 04 03 02 02 00 00 04 ; animation_table &1c13 00 ; &00 &00 : SPRITE_LEGS_ONE &1c14 01 ; &01 : SPRITE_LEGS_TWO &1c15 02 ; &02 : SPRITE_LEGS_THREE &1c16 00 ; &03 : SPRITE_LEGS_ONE &1c17 03 ; &04 : SPRITE_LEGS_FOUR &1c18 04 ; &05 : SPRITE_LEGS_FIVE &1c19 0a ; &06 : SPRITE_LEGS_SIX &1c1a 0d ; &07 : SPRITE_LEGS_SEVEN &1c1b 0a ; &08 : SPRITE_LEGS_SIX &1c1c 1b ; &09 : SPRITE_LEGS_NINE &1c1d 1c ; &0a : SPRITE_LEGS_TEN &1c1e 1a ; &0b : SPRITE_LEGS_EIGHT &1c1f 0a ; &0c : SPRITE_LEGS_SIX &1c20 0d ; &0d : SPRITE_LEGS_SEVEN &1c21 05 ; &0e &00 : SPRITE_TORSO_WITH_PISTOL_ONE &1c22 06 ; &01 : SPRITE_TORSO_WITH_PISTOL_TWO &1c23 05 ; &02 : SPRITE_TORSO_WITH_PISTOL_ONE &1c24 08 ; &03 : SPRITE_TORSO_WITH_PISTOL_FOUR &1c25 07 ; &04 : SPRITE_TORSO_WITH_PISTOL_THREE &1c26 08 ; &05 : SPRITE_TORSO_WITH_PISTOL_FOUR &1c27 0f ; &06 : SPRITE_TORSO_WITH_PISTOL_FIVE &1c28 0f ; &07 : SPRITE_TORSO_WITH_PISTOL_FIVE &1c29 05 ; &08 : SPRITE_TORSO_WITH_PISTOL_ONE &1c2a 1d ; &09 : SPRITE_TORSO_WITH_PISTOL_SIX &1c2b 05 ; &0a : SPRITE_TORSO_WITH_PISTOL_ONE &1c2c 1e ; &0b : SPRITE_TORSO_WITH_PISTOL_SEVEN &1c2d 1f ; &0c : SPRITE_TORSO_WITH_PISTOL_EIGHT &1c2e 05 ; &0d : SPRITE_TORSO_WITH_PISTOL_ONE &1c2f 10 ; &1c &00 : SPRITE_TORSO_WITH_RIFLE_ONE &1c30 10 ; &01 : SPRITE_TORSO_WITH_RIFLE_ONE &1c31 10 ; &02 : SPRITE_TORSO_WITH_RIFLE_ONE &1c32 10 ; &03 : SPRITE_TORSO_WITH_RIFLE_ONE &1c33 10 ; &04 : SPRITE_TORSO_WITH_RIFLE_ONE &1c34 10 ; &05 : SPRITE_TORSO_WITH_RIFLE_ONE &1c35 0b ; &06 : SPRITE_TORSO_WITH_RIFLE_ZERO &1c36 0b ; &07 : SPRITE_TORSO_WITH_RIFLE_ZERO &1c37 10 ; &08 : SPRITE_TORSO_WITH_RIFLE_ONE &1c38 16 ; &25 &00 : SPRITE_ROTORS_ONE &1c39 17 ; &01 : SPRITE_ROTORS_TWO &1c3a 19 ; &02 : SPRITE_ROTORS_FOUR &1c3b 18 ; &03 : SPRITE_ROTORS_THREE &1c3c 19 ; &04 : SPRITE_ROTORS_FOUR &1c3d 17 ; &05 : SPRITE_ROTORS_TWO &1c3e 12 ; &2b &00 : SPRITE_HELICOPTER_WITH_MISSILE_BODY &1c3f 12 ; &01 : SPRITE_HELICOPTER_WITH_MISSILE_BODY &1c40 12 ; &02 : SPRITE_HELICOPTER_WITH_MISSILE_BODY &1c41 12 ; &03 : SPRITE_HELICOPTER_WITH_MISSILE_BODY &1c42 12 ; &04 : SPRITE_HELICOPTER_WITH_MISSILE_BODY &1c43 12 ; &05 : SPRITE_HELICOPTER_WITH_MISSILE_BODY &1c44 11 ; &31 &00 : SPRITE_HELICOPTER_BODY &1c45 11 ; &01 : SPRITE_HELICOPTER_BODY &1c46 11 ; &02 : SPRITE_HELICOPTER_BODY &1c47 11 ; &03 : SPRITE_HELICOPTER_BODY &1c48 11 ; &04 : SPRITE_HELICOPTER_BODY &1c49 11 ; &05 : SPRITE_HELICOPTER_BODY &1c4a 15 ; &37 &00 : SPRITE_HELICOPTER_WITH_SOLDIER_BODY &1c4b 15 ; &01 : SPRITE_HELICOPTER_WITH_SOLDIER_BODY &1c4c 15 ; &02 : SPRITE_HELICOPTER_WITH_SOLDIER_BODY &1c4d 15 ; &03 : SPRITE_HELICOPTER_WITH_SOLDIER_BODY &1c4e 15 ; &04 : SPRITE_HELICOPTER_WITH_SOLDIER_BODY &1c4f 15 ; &05 : SPRITE_HELICOPTER_WITH_SOLDIER_BODY &1c50 24 ; &3d &00 : SPRITE_SKELETON_FOUR &1c51 23 ; &01 : SPRITE_SKELETON_THREE &1c52 22 ; &02 : SPRITE_SKELETON_TWO &1c53 21 ; &03 : SPRITE_SKELETON_ONE &1c54 29 ; &41 &00 : SPRITE_EXPLOSION_FIVE &1c55 28 ; &01 : SPRITE_EXPLOSION_FOUR &1c56 27 ; &02 : SPRITE_EXPLOSION_THREE &1c57 26 ; &03 : SPRITE_EXPLOSION_TWO &1c58 25 ; &04 : SPRITE_EXPLOSION_ONE &1c59 2a ; &46 &00 : SPRITE_BULLET &1c5a 2b ; &47 &00 : SPRITE_GRENADE &1c5b 2c ; &48 &00 : SPRITE_BOMB &1c5c 14 ; &49 &00 : SPRITE_RED_HELICOPTER_BODY &1c5d 14 ; &01 : SPRITE_RED_HELICOPTER_BODY &1c5e 14 ; &02 : SPRITE_RED_HELICOPTER_BODY &1c5f 14 ; &03 : SPRITE_RED_HELICOPTER_BODY &1c60 14 ; &04 : SPRITE_RED_HELICOPTER_BODY &1c61 14 ; &05 : SPRITE_RED_HELICOPTER_BODY &1c62 13 ; &4f &00 : SPRITE_BLUE_CRAFT &1c63 2d ; &50 &00 : SPRITE_TORSO_WITH_BAZOOKA &1c64 2d ; &01 : SPRITE_TORSO_WITH_BAZOOKA &1c65 2d ; &02 : SPRITE_TORSO_WITH_BAZOOKA &1c66 2d ; &03 : SPRITE_TORSO_WITH_BAZOOKA &1c67 2d ; &04 : SPRITE_TORSO_WITH_BAZOOKA &1c68 2d ; &05 : SPRITE_TORSO_WITH_BAZOOKA &1c69 2d ; &06 : SPRITE_TORSO_WITH_BAZOOKA &1c6a 2d ; &07 : SPRITE_TORSO_WITH_BAZOOKA &1c6b 2d ; &08 : SPRITE_TORSO_WITH_BAZOOKA &1c6c 34 ; &59 &00 : SPRITE_MORTAR_OR_MACHINE_GUN_SOLDIER &1c6d 33 ; &5a &00 : SPRITE_MORTAR &1c6e 35 ; &5b &00 : SPRITE_MACHINE_GUN &1c6f 37 ; &5c &00 : SPRITE_SAM &1c70 38 ; &5d &00 : SPRITE_ROCKET &1c71 2e ; &5e &00 : SPRITE_MINE ; sprites_y_offset ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1c72 0c 0b 0a 0c 0b 0a 0c 06 0c 0a 0a 09 0c 04 15 15 ; &00 &1c82 15 15 15 15 17 17 17 17 17 17 00 00 ; &10 ; player_helicopters_type &1c8e 08 0b 06 05 06 08 05 05 0b ; player_helicopters_initial_x_low &1c97 ec 66 fa da 37 50 c1 ea cf ; player_helicopters_initial_x_high &1ca0 02 05 07 09 0e 0e 11 11 14 ; scroll_screen_left &1ca9 20 7d 20 JSR &207d ; initialise_column_buffer &1cac a6 b2 LDX &b2 ; viewport_left_low &1cae d0 02 BNE &1cb2 ; skip_overflow_left &1cb0 c6 ba DEC &ba ; viewport_left_high ; skip_underflow_left &1cb2 c6 b2 DEC &b2 ; viewport_left_low &1cb4 a4 b3 LDY &b3 ; viewport_right_low &1cb6 d0 07 BNE &1cbf ; skip_underflow_right &1cb8 c6 bb DEC &bb ; viewport_right_high &1cba a5 bb LDA &bb ; viewport_right_high &1cbc 20 19 26 JSR &2619 ; add_enemy_helicopters ; skip_underflow_right &1cbf c6 b3 DEC &b3 ; viewport_right_low &1cc1 ce cb 1f DEC &1fcb ; ground_left_x_low &1cc4 ce cc 1f DEC &1fcc ; ground_right_x_low &1cc7 a6 01 LDX &01 ; screen_start_address_high &1cc9 a5 00 LDA &00 ; screen_start_address_low &1ccb a0 00 LDY #&00 ; &0008 # Move left a column &1ccd 20 d2 20 JSR &20d2 ; subtract_delta_from_screen_address_in_AX &1cd0 86 01 STX &01 ; screen_start_address_high &1cd2 85 00 STA &00 ; screen_start_address_low &1cd4 a6 b0 LDX &b0 ; crtc_start_address_high &1cd6 a4 b1 LDY &b1 ; crtc_start_address_low &1cd8 88 DEY &1cd9 c0 ff CPY #&ff &1cdb d0 01 BNE &1cde ; skip_underflow_crtc &1cdd ca DEX ; skip_underflow_crtc &1cde e0 07 CPX #&07 &1ce0 d0 02 BNE &1ce4 ; skip_wraparound &1ce2 a2 0f LDX #&0f ; skip_wraparound &1ce4 86 b0 STX &b0 ; crtc_start_address_high &1ce6 84 b1 STY &b1 ; crtc_start_address_low &1ce8 a0 05 LDY #&05 &1cea 84 b7 STY &b7 ; edge_and_layer &1cec a9 01 LDA #&01 &1cee 85 cc STA &cc ; edge # Set to non-zero to indicate right edge &1cf0 a9 d0 LDA #&d0 ; BNE &1cf2 8d db 1d STA &1ddb ; use_flipped_or_unflipped_scenery_sprite_opcode_one &1cf5 8d 49 1f STA &1f49 ; use_flipped_or_unflipped_scenery_sprite_opcode_two &1cf8 a9 55 LDA #&55 ; Kf &1cfa 20 d3 23 JSR &23d3 ; change_pixel_tables # Use background palette (use colour 15 for cyan) ; scroll_layers_left_loop # For each of three layers on two edges, &1cfd 20 57 1d JSR &1d57 ; check_for_scenery_when_scrolling_left # Returns non-zero if scenery present &1d00 f0 09 BEQ &1d0b ; no_scenery_in_layer &1d02 a5 cc LDA &cc ; edge &1d04 d0 0b BNE &1d11 ; consider_next_layer # If this is a left layer, &1d06 20 b3 1d JSR &1db3 ; add_column_of_scenery_to_column_buffer # plot a column of scenery &1d09 10 06 BPL &1d11 ; consider_next_layer # Always branches ; no_scenery_in_layer &1d0b b9 3b 1e LDA &1e3b,Y ; scenery_layers_table &1d0e 20 80 1d JSR &1d80 ; consider_adding_scenery_when_scrolling_left ; consider_next_layer &1d11 c6 b7 DEC &b7 ; edge_and_layer &1d13 a4 b7 LDY &b7 ; edge_and_layer &1d15 c0 02 CPY #&02 &1d17 d0 02 BNE &1d1b ; not_left_edge &1d19 c6 cc DEC &cc ; edge # Set to zero to indicate left edge ; not_left_edge &1d1b 98 TYA &1d1c 10 df BPL &1cfd ; scroll_layers_left_loop &1d1e a9 14 LDA #&14 ; KC &1d20 20 d3 23 JSR &23d3 ; change_pixel_tables # Use foreground palette (use colour 6 for cyan) &1d23 a0 00 LDY #&00 &1d25 20 8d 1f JSR &1f8d ; add_ground_to_column_buffer # Plot a column of ground &1d28 20 f7 1f JSR &1ff7 ; use_viewport_left_as_edge &1d2b 20 17 21 JSR &2117 ; calculate_screen_addresses_for_movers_on_edge &1d2e 20 cc 22 JSR &22cc ; add_movers_to_column_buffer # Plot a column of movers &1d31 a6 7e LDX &7e ; trigger_offset &1d33 bc 42 17 LDY &1742,X ; trigger_points_x_low_table &1d36 88 DEY &1d37 cc 60 1a CPY &1a60 ; movers_x_low &1d3a d0 14 BNE &1d50 ; skip_trigger_left &1d3c bd 67 17 LDA &1767,X ; trigger_points_x_high_table &1d3f cd 81 1a CMP &1a81 ; movers_x_high &1d42 d0 0c BNE &1d50 ; skip_trigger_left &1d44 20 39 32 JSR &3239 ; decrement_new_movers_offset &1d47 ca DEX &1d48 86 7e STX &7e ; trigger_offset &1d4a 20 43 32 JSR &3243 ; add_new_movers &1d4d 20 39 32 JSR &3239 ; decrement_new_movers_offset ; skip_trigger_left &1d50 a5 00 LDA &00 ; screen_start_address_low &1d52 a6 01 LDX &01 ; screen_start_address_high &1d54 4c f0 1e JMP &1ef0 ; set_edge_screen_address_from_AX ; check_for_scenery_when_scrolling_left &1d57 20 88 20 JSR &2088 ; get_scenery_address_for_layer_Y &1d5a f0 06 BEQ &1d62 ; leave # Leave with zero if no scenery in layer &1d5c 20 37 1f JSR &1f37 ; calculate_sprite_address_for_column_of_scenery &1d5f b9 c8 03 LDA &03c8,Y ; scenery_layer_sprite_addresses_high ; leave &1d62 60 RTS ; get_scenery_type &1d63 a0 00 LDY #&00 &1d65 b1 b4 LDA (&b4),Y ; scenery_data_address ; get_sprite_and_flip &1d67 48 PHA ; byte &1d68 29 7f AND #&7f # Low seven bits specify scenery or sprite type &1d6a aa TAX &1d6b 68 PLA ; byte &1d6c 29 80 AND #&80 # Top bit set if horizontally flipped &1d6e 4a LSR A &1d6f 49 40 EOR #&40 &1d71 85 cb STA &cb ; scenery_layer_flip &1d73 60 RTS # Leave with X = sprite, A = flip ; get_mountain_type &1d74 a0 00 LDY #&00 &1d76 b1 b4 LDA (&b4),Y ; scenery_data_address &1d78 29 03 AND #&03 &1d7a aa TAX &1d7b bd 47 1e LDA &1e47,X ; mountains_table &1d7e d0 e7 BNE &1d67 ; get_sprite_and_flip # Always branches ; consider_adding_scenery_when_scrolling_left &1d80 85 cd STA &cd ; scenery_layer &1d82 a5 b4 LDA &b4 ; scenery_data_address_low &1d84 38 SEC &1d85 e5 cd SBC &cd ; scenery_layer &1d87 85 b4 STA &b4 ; scenery_data_address_low &1d89 b0 02 BCS &1d8d ; skip_page &1d8b c6 b5 DEC &b5 ; scenery_data_address_high ; skip_page &1d8d a5 cd LDA &cd ; scenery_layer &1d8f c9 01 CMP #&01 &1d91 d0 05 BNE &1d98 ; not_mountain &1d93 20 74 1d JSR &1d74 ; get_mountain_type &1d96 10 11 BPL &1da9 ; add_scenery_when_scrolling_left # Always branches ; not_mountain &1d98 20 63 1d JSR &1d63 ; get_scenery_type &1d9b bd 5c 19 LDA &195c,X ; scenery_sprite_width_table &1d9e c8 INY &1d9f 18 CLC &1da0 71 b4 ADC (&b4),Y ; scenery_data_address &1da2 a4 cc LDY &cc ; edge # Zero if left edge, non-zero if right edge &1da4 d9 b2 00 CMP &00b2,Y ; viewport_left_low &1da7 d0 4b BNE &1df4 ; leave ; add_scenery_when_scrolling_left &1da9 20 c1 1d JSR &1dc1 ; get_scenery_y_sprite_and_flip_for_layer_Y &1dac 20 96 20 JSR &2096 ; set_scenery_address_for_layer_Y &1daf a5 cc LDA &cc ; edge # Zero if left edge, non-zero if right edge &1db1 d0 41 BNE &1df4 ; leave ; add_column_of_scenery_to_column_buffer &1db3 b9 d8 03 LDA &03d8,Y ; scenery_layers_y &1db6 48 PHA ; scenery_layer_y &1db7 be c8 03 LDX &03c8,Y ; scenery_layer_sprite_addresses_high &1dba b9 d0 03 LDA &03d0,Y ; scenery_layer_sprite_addresses_low &1dbd a8 TAY &1dbe 4c 25 20 JMP &2025 ; add_column_of_scenery_sprite_to_column_buffer ; get_scenery_y_sprite_and_flip_for_layer_Y &1dc1 a4 b7 LDY &b7 ; edge_and_layer &1dc3 b9 41 1e LDA &1e41,Y ; scenery_layers_y_positions &1dc6 a0 03 LDY #&03 &1dc8 c4 cd CPY &cd ; scenery_layer &1dca d0 03 BNE &1dcf ; not_variable_y_position &1dcc 88 DEY &1dcd b1 b4 LDA (&b4),Y ; scenery_data_address ; not_variable_y_position &1dcf a4 b7 LDY &b7 ; edge_and_layer &1dd1 99 d8 03 STA &03d8,Y ; scenery_layers_y &1dd4 a5 cb LDA &cb ; scenery_layer_flip &1dd6 99 ea 02 STA &02ea,Y ; scenery_layers_flip &1dd9 85 b8 STA &b8 ; pixel_table_address_low ; use_flipped_or_unflipped_scenery_sprite_opcode_one &1ddb f0 08 BEQ &1de5 ; use_flipped_sprite # if scrolling right # also BNE &1de5 ; use_flipped_sprite # if scrolling left ; use_unflipped_sprite &1ddd bd 2e 19 LDA &192e,X ; unflipped_scenery_sprite_addresses_low_table &1de0 bc 45 19 LDY &1945,X ; unflipped_scenery_sprite_addresses_high_table &1de3 d0 06 BNE &1deb ; set_scenery_sprite_address # Always branches ; use_flipped_sprite &1de5 bd 00 19 LDA &1900,X ; flipped_scenery_sprite_addresses_low_table &1de8 bc 17 19 LDY &1917,X ; flipped_scenery_sprite_addresses_high_table ; set_scenery_sprite_address &1deb a6 b7 LDX &b7 ; edge_and_layer &1ded 9d d0 03 STA &03d0,X ; scenery_layer_sprite_addresses_low &1df0 98 TYA &1df1 9d c8 03 STA &03c8,X ; scenery_layer_sprite_addresses_high ; leave &1df4 a4 b7 LDY &b7 ; edge_and_layer &1df6 60 RTS ; consider_adding_scenery_when_scrolling_right &1df7 a5 cd LDA &cd ; scenery_layer &1df9 c9 01 CMP #&01 &1dfb d0 05 BNE &1e02 ; not_mountains &1dfd 20 74 1d JSR &1d74 ; get_mountain_type &1e00 10 0e BPL &1e10 ; add_scenery_when_scrolling_right # Always branches ; not_mountains &1e02 20 63 1d JSR &1d63 ; get_scenery_type &1e05 a4 cc LDY &cc ; edge # Zero if left edge, non-zero if right edge &1e07 b9 b2 00 LDA &00b2,Y ; viewport_left_low &1e0a a0 01 LDY #&01 &1e0c d1 b4 CMP (&b4),Y ; scenery_data_address &1e0e d0 0a BNE &1e1a ; leave ; add_scenery_when_scrolling_right &1e10 20 c1 1d JSR &1dc1 ; get_scenery_y_sprite_and_flip_for_layer_Y &1e13 a5 cc LDA &cc ; edge # Zero if left edge, non-zero if right edge &1e15 f0 03 BEQ &1e1a ; leave &1e17 4c b3 1d JMP &1db3 ; add_column_of_scenery_to_column_buffer ; leave &1e1a 60 RTS ; check_for_scenery_when_scrolling_right &1e1b 85 cd STA &cd ; scenery_layer &1e1d 20 88 20 JSR &2088 ; get_scenery_address_for_layer_Y &1e20 f0 18 BEQ &1e3a ; leave # Leave with zero if no scenery in layer &1e22 20 37 1f JSR &1f37 ; calculate_sprite_address_for_column_of_scenery &1e25 b9 c8 03 LDA &03c8,Y ; scenery_layer_sprite_addresses_high &1e28 d0 10 BNE &1e3a ; leave &1e2a a5 b4 LDA &b4 ; scenery_data_address_low &1e2c 18 CLC &1e2d 65 cd ADC &cd ; scenery_layer &1e2f 85 b4 STA &b4 ; scenery_data_address_low &1e31 90 02 BCC &1e35 ; skip_page &1e33 e6 b5 INC &b5 ; scenery_data_address_high ; skip_page &1e35 20 96 20 JSR &2096 ; set_scenery_address_for_layer_Y &1e38 a9 00 LDA #&00 ; leave &1e3a 60 RTS ; scenery_layers_table ; left right ; 0 1 2 3 4 5 &1e3b 02 03 01 02 03 01 # &01 = mountains, &02 = scenery one, &03 = scenery two ; scenery_layers_y_positions ; left right ; 0 1 2 3 4 5 &1e41 17 03 17 17 03 17 ; mountains_table &1e47 05 ; SCENERY_MOUNTAINS_TWO &1e48 85 ; SCENERY_MOUNTAINS_TWO | SCENERY_FLIPPED &1e49 84 ; SCENERY_MOUNTAINS_ONE | SCENERY_FLIPPED &1e4a 04 ; SCENERY_MOUNTAINS_ONE ; scroll_screen_right &1e4b 20 7d 20 JSR &207d ; initialise_column_buffer &1e4e e6 b2 INC &b2 ; viewport_left_low &1e50 d0 02 BNE &1e54 ; skip_overflow_left &1e52 e6 ba INC &ba ; viewport_left_high ; skip_overflow_left &1e54 e6 b3 INC &b3 ; viewport_right_low &1e56 d0 07 BNE &1e5f ; skip_overflow_right &1e58 e6 bb INC &bb ; viewport_right_high ; skip_overflow_right &1e5a a5 bb LDA &bb ; viewport_right_high &1e5c 20 19 26 JSR &2619 ; add_enemy_helicopters &1e5f ee cb 1f INC &1fcb ; ground_left_x_low &1e62 ee cc 1f INC &1fcc ; ground_right_x_low &1e65 a6 01 LDX &01 ; screen_start_address_high &1e67 a5 00 LDA &00 ; screen_start_address_low &1e69 a0 00 LDY #&00 ; &0008 # Move right a column &1e6b 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &1e6e 86 01 STX &01 ; screen_start_address_high &1e70 85 00 STA &00 ; screen_start_address_low &1e72 a6 b0 LDX &b0 ; crtc_start_address_high &1e74 a4 b1 LDY &b1 ; crtc_start_address_low &1e76 c8 INY &1e77 d0 01 BNE &1e7a ; skip_page &1e79 e8 INX ; skip_page &1e7a e0 10 CPX #&10 &1e7c d0 02 BNE &1e80 ; skip_wraparound &1e7e a2 08 LDX #&08 ; skip_wraparound &1e80 86 b0 STX &b0 ; crtc_start_address_high &1e82 84 b1 STY &b1 ; crtc_start_address_low &1e84 a0 05 LDY #&05 &1e86 84 b7 STY &b7 ; edge_and_layer &1e88 a9 01 LDA #&01 &1e8a 85 cc STA &cc ; edge # Set to non-zero to indicate right edge &1e8c a9 f0 LDA #&f0 ; BEQ &1e8e 8d db 1d STA &1ddb ; use_flipped_or_unflipped_scenery_sprite_opcode_one &1e91 8d 49 1f STA &1f49 ; use_flipped_or_unflipped_scenery_sprite_opcode_two &1e94 a9 55 LDA #&55 ; Kf &1e96 20 d3 23 JSR &23d3 ; change_pixel_tables # Use background palette (use colour 15 for cyan) ; scroll_layers_right_loop # For each of three layers on two edges, &1e99 b9 3b 1e LDA &1e3b,Y ; scenery_layers_table &1e9c 20 1b 1e JSR &1e1b ; check_for_scenery_when_scrolling_right # Returns non-zero if scenery present &1e9f f0 09 BEQ &1eaa ; no_scenery_in_layer &1ea1 a5 cc LDA &cc ; edge &1ea3 f0 08 BEQ &1ead ; consider_next_layer # If this is a right layer, &1ea5 20 b3 1d JSR &1db3 ; add_column_of_scenery_to_column_buffer # plot a column of scenery &1ea8 10 03 BPL &1ead ; consider_next_layer # Always branches ; no_scenery_in_layer &1eaa 20 f7 1d JSR &1df7 ; consider_adding_scenery_when_scrolling_left ; consider_next_layer &1ead c6 b7 DEC &b7 ; edge_and_layer &1eaf a4 b7 LDY &b7 ; edge_and_layer &1eb1 c0 02 CPY #&02 &1eb3 d0 02 BNE &1eb7 ; not_left_edge &1eb5 c6 cc DEC &cc ; edge # Set to zero to indicate left edge ; not_left_edge &1eb7 98 TYA &1eb8 10 df BPL &1e99 ; scroll_layers_right_loop &1eba a9 14 LDA #&14 ; KC &1ebc 20 d3 23 JSR &23d3 ; change_pixel_tables # Use foreground palette (use colour 6 for cyan) &1ebf a0 01 LDY #&01 &1ec1 20 8d 1f JSR &1f8d ; add_ground_to_column_buffer # Plot a column of ground &1ec4 20 ef 1f JSR &1fef ; use_viewport_right_as_edge &1ec7 20 17 21 JSR &2117 ; calculate_screen_addresses_for_movers_on_edge &1eca 20 cc 22 JSR &22cc ; add_movers_to_column_buffer # Plot a column of movers &1ecd a6 7e LDX &7e ; trigger_offset &1ecf e8 INX &1ed0 bc 42 17 LDY &1742,X ; trigger_points_x_low_table &1ed3 cc 60 1a CPY &1a60 ; movers_x_low &1ed6 d0 0f BNE &1ee7 ; skip_trigger_right &1ed8 bd 67 17 LDA &1767,X ; trigger_points_x_high_table &1edb cd 81 1a CMP &1a81 ; movers_x_high &1ede d0 07 BNE &1ee7 ; skip_trigger_right &1ee0 86 7e STX &7e ; trigger_offset &1ee2 e8 INX &1ee3 e8 INX &1ee4 20 43 32 JSR &3243 ; add_new_movers ; skip_trigger_right &1ee7 a6 01 LDX &01 ; screen_start_address_high &1ee9 a5 00 LDA &00 ; screen_start_address_low &1eeb a0 07 LDY #&07 ; &0278 &1eed 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX ; set_edge_screen_address_from_AX &1ef0 86 86 STX &86 ; edge_screen_address_high &1ef2 85 85 STA &85 ; edge_screen_address_low &1ef4 18 CLC # Unnecessary code &1ef5 60 RTS ; update_screen ; wait_for_timer &1ef6 ad 69 fe LDA &fe69 ; User VIA timer 2 counter MSB &1ef9 c9 c8 CMP #&c8 &1efb b0 f9 BCS &1ef6 ; wait_for_timer # Wait for raster to be at approximately ground level ; update_screen_without_delay &1efd a2 0c LDX #&0c ; R12: Displayed screen start address register (high) &1eff 8e 00 fe STX &fe00 ; video register number &1f02 a5 b0 LDA &b0 ; crtc_start_address_high &1f04 8d 01 fe STA &fe01 ; video register value &1f07 e8 INX ; &0d ; R13: Displayed screen start address register (low) &1f08 8e 00 fe STX &fe00 ; video register number &1f0b a5 b1 LDA &b1 ; crtc_start_address_low &1f0d 8d 01 fe STA &fe01 ; video register value &1f10 a0 00 LDY #&00 &1f12 a2 c8 LDX #&c8 ; plot_column_from_buffer_loop &1f14 bd ff 02 LDA &02ff,X ; column_buffer - 1 &1f17 91 85 STA (&85),Y ; edge_screen_address &1f19 c8 INY &1f1a c0 08 CPY #&08 &1f1c f0 04 BEQ &1f22 ; next_group ; next_row &1f1e ca DEX &1f1f d0 f3 BNE &1f14 ; plot_column_from_buffer_loop &1f21 60 RTS ; next_group &1f22 86 9a STX &9a ; buffer_offset &1f24 a5 85 LDA &85 ; edge_screen_address_low &1f26 a6 86 LDX &86 ; edge_screen_address_high &1f28 a0 02 LDY #&02 ; &0280 # Move down a group &1f2a 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &1f2d 86 86 STX &86 ; edge_screen_address_high &1f2f 85 85 STA &85 ; edge_screen_address_low &1f31 a6 9a LDX &9a ; buffer_offset &1f33 a0 00 LDY #&00 &1f35 f0 e7 BEQ &1f1e ; next_row # Always branches ; calculate_sprite_address_for_column_of_scenery &1f37 b9 ea 02 LDA &02ea,Y ; scenery_layers_flip &1f3a 85 b8 STA &b8 ; pixel_table_address_low &1f3c 18 CLC &1f3d 69 80 ADC #&80 # &0480 = flipped_mask_table, &04c0 = unflipped_mask_table &1f3f 85 c8 STA &c8 ; mask_table_address_low &1f41 a9 04 LDA #&04 &1f43 85 c9 STA &c9 ; mask_table_address_high &1f45 85 b9 STA &b9 ; pixel_table_address_high &1f47 a5 b8 LDA &b8 ; pixel_table_address_low # Zero if sprite is flipped ; use_flipped_or_unflipped_scenery_sprite_opcode_two &1f49 f0 03 BEQ &1f4e ; to_move_backwards_through_sprite # if scrolling right # also BNE &1f4e ; to_move_backwards_through_sprite # if scrolling left &1f4b 4c 72 1f JMP &1f72 ; move_forward_through_sprite ; to_move_backwards_through_sprite &1f4e 4c 51 1f JMP &1f51 ; move_backwards_through_sprite # Unnecessary code ; move_backwards_through_sprite &1f51 20 e1 1f JSR &1fe1 ; use_scenery_sprite_address_for_layer_Y &1f54 b1 ce LDA (&ce),Y ; scenery_sprite_address &1f56 f0 14 BEQ &1f6c ; set_scenery_layer_sprite_address_high &1f58 85 f9 STA &f9 ; column_length_in_bytes &1f5a a6 cf LDX &cf ; scenery_sprite_address_high &1f5c a5 ce LDA &ce ; scenery_sprite_address_low &1f5e 38 SEC &1f5f e5 f9 SBC &f9 ; column_length_in_bytes &1f61 b0 01 BCS &1f64 ; skip_page &1f63 ca DEX ; skip_page &1f64 a4 b7 LDY &b7 ; edge_and_layer &1f66 99 d0 03 STA &03d0,Y ; scenery_layer_sprite_addresses_low &1f69 8a TXA &1f6a d0 02 BNE &1f6e ; set_scenery_layer_sprite_address_high # Always branches ; set_scenery_layer_Y_sprite_address_high &1f6c a4 b7 LDY &b7 ; edge_and_layer ; set_scenery_layer_sprite_address_high &1f6e 99 c8 03 STA &03c8,Y ; scenery_layer_sprite_addresses_high &1f71 60 RTS ; move_forward_through_sprite &1f72 b9 d0 03 LDA &03d0,Y ; scenery_layer_sprite_addresses_low &1f75 a8 TAY &1f76 20 04 20 JSR &2004 ; move_to_next_column_in_XY &1f79 99 d0 03 STA &03d0,Y ; scenery_layer_sprite_addresses_low &1f7c 8a TXA &1f7d 99 c8 03 STA &03c8,Y ; scenery_layer_sprite_addresses_high &1f80 20 e1 1f JSR &1fe1 ; use_scenery_sprite_address_for_layer_Y &1f83 b1 ce LDA (&ce),Y ; scenery_sprite_address &1f85 10 03 BPL &1f8a ; leave &1f87 98 TYA &1f88 f0 e2 BEQ &1f6c ; set_scenery_layer_sprite_address_high ; leave &1f8a a4 b7 LDY &b7 ; edge_and_layer &1f8c 60 RTS ; add_ground_to_column_buffer &1f8d be cb 1f LDX &1fcb,Y ; ground_left_x_low &1f90 bd 00 80 LDA &8000,X ; rom # Use ROM as pseudo-random stream for ground &1f93 29 03 AND #&03 &1f95 aa TAX &1f96 48 PHA ; ground_type &1f97 20 af 2f JSR &2faf ; multiply_A_by_X &1f9a 68 PLA ; ground_type &1f9b aa TAX &1f9c ad 09 03 LDA &0309 ; column_buffer + 9 &1f9f d0 29 BNE &1fca ; leave # Don't add ground if a bridge is present &1fa1 a0 13 LDY #&13 &1fa3 ad 15 03 LDA &0315 ; column_buffer + &15 &1fa6 d0 14 BNE &1fbc ; add_ground_to_column_buffer_loop # Don't add ground edge if runway present &1fa8 bd cd 1f LDA &1fcd,X ; ground_edge_bottom_pixel_values &1fab 8d 16 03 STA &0316 ; column_buffer + &16 &1fae ad 17 03 LDA &0317 ; column_buffer + &17 &1fb1 3d d5 1f AND &1fd5,X ; ground_edge_masks &1fb4 5d d1 1f EOR &1fd1,X ; ground_edge_top_pixel_values &1fb7 8d 17 03 STA &0317 ; column_buffer + &17 &1fba a0 15 LDY #&15 ; add_ground_to_column_buffer_loop &1fbc b1 c5 LDA (&c5),Y ; result # &0000,Y, &0001,Y, &0004,Y or &0009,Y &1fbe 29 07 AND #&07 &1fc0 aa TAX &1fc1 bd d9 1f LDA &1fd9,X ; ground_pixel_values &1fc4 99 00 03 STA &0300,Y ; column_buffer # Add ground to column buffer &1fc7 88 DEY &1fc8 10 f2 BPL &1fbc ; add_ground_to_column_buffer_loop ; leave &1fca 60 RTS ; ground_left_x_low &1fcb 00 ; ground_right_x_low &1fcc 00 ; ground_edge_bottom_pixel_values &1fcd 3c ; CC &1fce 29 ; CR &1fcf 16 ; RC &1fd0 03 ; RR ; ground_edge_top_pixel_values &1fd1 00 ; KK &1fd2 14 ; KC &1fd3 28 ; CK &1fd4 3c ; CC ; ground_edge_masks &1fd5 ff ; ## &1fd6 aa ; #. &1fd7 55 ; .# &1fd8 00 ; .. ; ground_pixel_values &1fd9 03 ; RR &1fda 29 ; CR &1fdb 03 ; RR &1fdc 16 ; RC &1fdd 03 ; RR &1fde 03 ; RR &1fdf 03 ; RR &1fe0 03 ; RR ; use_scenery_sprite_address_for_layer_Y &1fe1 b9 d0 03 LDA &03d0,Y ; scenery_layer_sprite_addresses_low &1fe4 be c8 03 LDX &03c8,Y ; scenery_layer_sprite_addresses_high &1fe7 a8 TAY ; set_scenery_sprite_address_from_XY &1fe8 86 cf STX &cf ; scenery_sprite_address_high &1fea 84 ce STY &ce ; scenery_sprite_address_low &1fec a0 00 LDY #&00 &1fee 60 RTS ; use_viewport_right_as_edge &1fef a6 b3 LDX &b3 ; viewport_right_low &1ff1 a4 bb LDY &bb ; viewport_right_high &1ff3 a9 01 LDA #&01 # Non-zero to indicate right edge &1ff5 d0 06 BNE &1ffd ; set_edge_x # Always branches ; use_viewport_left_as_edge &1ff7 a6 b2 LDX &b2 ; viewport_left_low &1ff9 a4 ba LDY &ba ; viewport_left_high &1ffb a9 00 LDA #&00 # Zero to indicate left edge ; set_edge_x &1ffd 86 b5 STX &b5 ; edge_x_low &1fff 84 b4 STY &b4 ; edge_x_high &2001 85 cf STA &cf ; edge &2003 60 RTS ; move_to_next_column_in_XY &2004 20 e8 1f JSR &1fe8 ; set_scenery_sprite_address_from_XY # Returns Y = 0 ; find_end_of_column_loop &2007 c8 INY &2008 b1 ce LDA (&ce),Y ; scenery_sprite_address # Zero indicates end of column &200a f0 09 BEQ &2015 ; move_to_next_column &200c b1 ce LDA (&ce),Y ; scenery_sprite_address &200e 29 c0 AND #&c0 &2010 d0 f5 BNE &2007 ; find_end_of_column_loop &2012 c8 INY # Get extra byte for variable length run &2013 d0 f2 BNE &2007 ; find_end_of_column_loop # Always branches ; move_to_next_column &2015 a6 cf LDX &cf ; scenery_sprite_address_high &2017 c8 INY # One byte for the zero that indicates end of column &2018 d0 01 BNE &201b ; skip_page_byte &201a e8 INX ; skip_page_byte &201b 98 TYA # Bytes for the content of the plotted column &201c 18 CLC &201d 65 ce ADC &ce ; scenery_sprite_address_low &201f 90 01 BCC &2022 ; skip_page_column_length &2021 e8 INX ; skip_page_column_length &2022 a4 b7 LDY &b7 ; edge_and_layer &2024 60 RTS # Leave with AX = scenery_sprite_address ; add_column_of_scenery_sprite_to_column_buffer &2025 a9 b1 LDA #&b1 ; LDA (&c8),Y ; scenery_sprite_address # Plot with mask &2027 8d 5e 20 STA &205e ; plot_scenery_mask_opcode &202a a9 c8 LDA #&c8 &202c 8d 5f 20 STA &205f ; plot_scenery_mask_opcode + 1 &202f 68 PLA ; scenery_layer_y ; add_column_of_sprite_to_column_buffer # Called with A = y position &2030 20 e8 1f JSR &1fe8 ; set_scenery_sprite_address_from_XY &2033 85 f8 STA &f8 ; end_of_run_offset ; unpack_scenery_loop &2035 c8 INY &2036 b1 ce LDA (&ce),Y ; scenery_sprite_address # Get byte of scenery data &2038 f0 db BEQ &2015 ; move_to_next_column # Zero indicates end of column &203a aa TAX &203b 10 0d BPL &204a ; is_positive ; is_negative &203d 0a ASL A &203e 30 05 BMI &2045 ; is_run_length_3 ; is_run_length_1 &2040 8a TXA # 10 ...... run length 1 &2041 a2 01 LDX #&01 &2043 d0 10 BNE &2055 ; unpack_scenery_run # Always branches ; is_run_length_3 &2045 8a TXA # 11 ...... run length 1 &2046 a2 03 LDX #&03 &2048 d0 0b BNE &2055 ; unpack_scenery_run # Always branches ; is_positive &204a 0a ASL A &204b 10 05 BPL &2052 ; is_variable_run_length ; is_run_length_2 &204d 8a TXA # 01 ...... run length 2 &204e a2 02 LDX #&02 &2050 d0 03 BNE &2055 ; unpack_scenery_run # Always branches ; is_variable_run_length &2052 c8 INY # 00 ...... use next byte for run length &2053 b1 ce LDA (&ce),Y ; scenery_sprite_address ; unpack_scenery_run &2055 84 d0 STY &d0 ; scenery_data_offset &2057 29 3f AND #&3f &2059 a8 TAY &205a b1 b8 LDA (&b8),Y ; pixel_table_address &205c 85 f9 STA &f9 ; scenery_pixel_value ; plot_scenery_mask_opcode &205e b1 c8 LDA (&c8),Y ; mask_table_address # if adding scenery # also LDA #&ff # if adding movers &2060 85 a7 STA &a7 ; scenery_mask &2062 8a TXA &2063 18 CLC &2064 65 f8 ADC &f8 ; end_of_run_offset &2066 a6 f8 LDX &f8 ; end_of_run_offset &2068 85 f8 STA &f8 ; end_of_run_offset ; unpack_scenery_run_loop &206a bd 00 03 LDA &0300,X ; column_buffer &206d 25 a7 AND &a7 ; mask &206f 45 f9 EOR &f9 ; pixel &2071 9d 00 03 STA &0300,X ; column_buffer # Add scenery sprite to background buffer &2074 e8 INX &2075 e4 f8 CPX &f8 ; end_of_run_offset &2077 d0 f1 BNE &206a ; unpack_scenery_run_loop &2079 a4 d0 LDY &d0 ; scenery_data_offset &207b d0 b8 BNE &2035 ; unpack_scenery_loop # Always branches ; initialise_column_buffer &207d a9 00 LDA #&00 &207f a2 c8 LDX #&c8 ; initialise_column_buffer_loop &2081 9d ff 02 STA &02ff,X ; column_buffer - 1 &2084 ca DEX &2085 d0 fa BNE &2081 ; initialise_column_buffer_loop &2087 60 RTS ; get_scenery_address_for_layer_Y &2088 b9 f2 02 LDA &02f2,Y ; scenery_layer_addresses_high &208b 85 b5 STA &b5 ; scenery_data_address_high &208d b9 aa 01 LDA &01aa,Y ; scenery_layer_addresses_low &2090 85 b4 STA &b4 ; scenery_data_address_low &2092 be c8 03 LDX &03c8,Y ; scenery_layer_sprite_addresses_high &2095 60 RTS ; set_scenery_address_for_layer_Y &2096 a5 b4 LDA &b4 ; scenery_data_address_low &2098 99 aa 01 STA &01aa,Y ; scenery_layer_addresses_low &209b a5 b5 LDA &b5 ; scenery_data_address_high &209d 99 f2 02 STA &02f2,Y ; scenery_layer_addresses_high &20a0 60 RTS ; deltas_low_table ; 0 1 2 3 4 5 6 7 8 &20a1 08 10 80 79 20 28 30 78 88 ; deltas_high_table ; 0 1 2 3 4 5 6 7 8 &20aa 00 00 02 02 00 00 00 02 3e ; add_delta_to_screen_address_in_AX # Called with A = address_low, X = address_high &20b3 20 c5 20 JSR &20c5 ; get_screen_address_delta &20b6 18 CLC &20b7 65 b6 ADC &b6 ; delta_low &20b9 a8 TAY &20ba 8a TXA &20bb 65 b7 ADC &b7 ; delta_high &20bd 10 03 BPL &20c2 ; skip_wraparound &20bf 38 SEC &20c0 e9 40 SBC #&40 ; skip_wraparound &20c2 aa TAX &20c3 98 TYA &20c4 60 RTS # Leave with A = address_low, X = address_high ; get_screen_address_delta &20c5 48 PHA ; tmp_a &20c6 b9 a1 20 LDA &20a1,Y ; deltas_low_table &20c9 85 b6 STA &b6 ; delta_low &20cb b9 aa 20 LDA &20aa,Y ; deltas_high_table &20ce 85 b7 STA &b7 ; delta_high &20d0 68 PLA ; tmp_a &20d1 60 RTS ; subtract_delta_from_screen_address_in_AX # Called with A = address_low, X = address_high &20d2 20 c5 20 JSR &20c5 ; get_screen_address_delta &20d5 38 SEC &20d6 e5 b6 SBC &b6 ; delta_low &20d8 a8 TAY &20d9 8a TXA &20da e5 b7 SBC &b7 ; delta_high &20dc c9 40 CMP #&40 &20de b0 02 BCS &20e2 ; skip_wraparound &20e0 69 40 ADC #&40 ; skip_wraparound &20e2 aa TAX &20e3 98 TYA &20e4 60 RTS # Leave with A = address_low, X = address_high ; subtract_Y_rows_from_screen_address_in_AX &20e5 84 cd STY &cd ; rows &20e7 f0 fb BEQ &20e4 ; leave ; consider_next_row &20e9 a8 TAY &20ea 29 07 AND #&07 &20ec f0 07 BEQ &20f5 ; next_group &20ee 88 DEY &20ef 98 TYA ; next_row &20f0 c6 cd DEC &cd ; rows &20f2 d0 f5 BNE &20e9 ; consider_next_row &20f4 60 RTS ; next_group &20f5 98 TYA &20f6 a0 03 LDY #&03 ; &0279 &20f8 20 d2 20 JSR &20d2 ; subtract_delta_from_screen_address_in_AX &20fb 4c f0 20 JMP &20f0 ; next_row ; add_Y_rows_from_screen_address_in_AX &20fe 84 cd STY &cd ; rows ; next_row &2100 a8 TAY &2101 29 07 AND #&07 &2103 c9 07 CMP #&07 &2105 f0 07 BEQ &210e ; next_group &2107 c8 INY &2108 98 TYA &2109 c6 cd DEC &cd ; rows ; to_next_row &210b d0 f3 BNE &2100 ; next_row &210d 60 RTS ; next_group &210e 98 TYA &210f a0 03 LDY #&03 ; &0279 &2111 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &2114 4c 09 21 JMP &2109 ; to_next_row ; calculate_screen_addresses_for_movers_on_edge &2117 a0 00 LDY #&00 ; MOVER_FIRST # Bug: player is never on edge, so should be &01 ; calculate_screen_addresses_for_movers_on_edge_loop &2119 20 22 21 JSR &2122 ; calculate_screen_addresses_for_mover_on_edge &211c c8 INY &211d c0 21 CPY #&21 ; MOVER_LAST + 1 &211f 90 f8 BCC &2119 ; calculate_screen_addresses_for_movers_on_edge_loop &2121 60 RTS ; calculate_screen_addresses_for_mover_on_edge &2122 b9 81 1a LDA &1a81,Y ; movers_x_high &2125 85 d0 STA &d0 ; mover_x_high &2127 20 33 31 JSR &3133 ; get_mover_Y_type # Returns A = mover type &212a aa TAX &212b bd 75 1b LDA &1b75,X ; mover_types_width_table &212e 85 cd STA &cd ; mover_width &2130 b9 60 1a LDA &1a60,Y ; movers_x_low &2133 a6 cf LDX &cf ; edge # Zero for left edge, non-zero for right edge &2135 d0 07 BNE &213e ; skip_adding_width &2137 18 CLC # Consider right edge of mover for left edge of screen &2138 65 cd ADC &cd ; mover_width &213a 90 02 BCC &213e ; skip_overflow &213c e6 d0 INC &d0 ; mover_x_high ; skip_overflow ; skip_adding_width &213e c5 b5 CMP &b5 ; edge_x_low # Is the edge of the mover on the edge of the screen? &2140 d0 47 BNE &2189 ; leave &2142 a5 d0 LDA &d0 ; mover_x_high &2144 c5 b4 CMP &b4 ; edge_x_high &2146 d0 41 BNE &2189 ; leave &2148 a9 c7 LDA #&c7 # If so, calculate the screen address &214a 38 SEC &214b f9 a2 1a SBC &1aa2,Y ; movers_y &214e 84 79 STY &79 ; mover &2150 aa TAX &2151 29 07 AND #&07 &2153 85 d0 STA &d0 ; row_in_group &2155 8a TXA &2156 4a LSR A &2157 4a LSR A &2158 4a LSR A &2159 85 d1 STA &d1 ; groups &215b a6 01 LDX &01 ; screen_start_address_high &215d a5 00 LDA &00 ; screen_start_address_low ; add_groups_loop &215f a0 02 LDY #&02 ; &0280 # Move down a group &2161 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &2164 c6 d1 DEC &d1 ; groups &2166 d0 f7 BNE &215f ; add_groups_loop &2168 18 CLC &2169 65 d0 ADC &d0 ; row_in_group &216b a4 cf LDY &cf ; edge &216d f0 08 BEQ &2177 ; is_left_edge ; is_right_edge &216f a0 07 LDY #&07 ; &0278 # Move to right of group &2171 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &2174 4c 80 21 JMP &2180 ; set_mover_screen_address ; is_left_edge ; find_right_edge_loop &2177 a0 00 LDY #&00 ; &0008 # Move left a column &2179 20 d2 20 JSR &20d2 ; subtract_delta_from_screen_address_in_AX &217c c6 cd DEC &cd ; mover_width &217e d0 f7 BNE &2177 ; find_right_edge_loop ; set_mover_screen_address &2180 a4 79 LDY &79 ; mover &2182 99 c3 1a STA &1ac3,Y ; movers_screen_address_low &2185 8a TXA &2186 99 e4 1a STA &1ae4,Y ; movers_screen_address_high ; leave &2189 60 RTS ; consider_plotting_next_column_of_mover &218a 84 cd STY &cd ; sprite_data_offset &218c a5 ce LDA &ce ; screen_address_low &218e a6 cf LDX &cf ; screen_address_high &2190 a0 00 LDY #&00 ; &0008 # Move right a column &2192 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &2195 85 ce STA &ce ; screen_address_low &2197 86 cf STX &cf ; screen_address_high &2199 86 40 STX &40 ; column_screen_address_high &219b 85 3f STA &3f ; column_screen_address_low &219d a4 b8 LDY &b8 ; pixel_table_address_low # Zero if sprite is flipped &219f d0 11 BNE &21b2 ; not_flipped ; is_flipped &21a1 84 cd STY &cd ; sprite_data_offset &21a3 b1 05 LDA (&05),Y ; mover_sprite_address &21a5 f0 11 BEQ &21b8 ; leave &21a7 a5 05 LDA &05 ; sprite_address_low &21a9 38 SEC &21aa f1 05 SBC (&05),Y ; mover_sprite_address # Move back a column of sprite data &21ac 85 05 STA &05 ; sprite_address_low &21ae b0 02 BCS &21b2 ; skip_page &21b0 c6 06 DEC &06 ; sprite_address_high ; skip_page ; not_flipped &21b2 a6 f8 LDX &f8 ; mover_x_low &21b4 e4 b3 CPX &b3 ; viewport_right_low &21b6 d0 01 BNE &21b9 ; next_column ; leave &21b8 60 RTS ; next_column &21b9 e8 INX &21ba 86 f8 STX &f8 ; mover_x_low &21bc a4 cd LDY &cd ; sprite_data_offset &21be c8 INY &21bf 4c 04 00 JMP &0004 ; unpack_column_of_sprite ; get_mover_type_and_colour &21c2 a9 04 LDA #&04 ; &0440 = unflipped_green_pixel_table &21c4 85 b9 STA &b9 ; pixel_table_address_high &21c6 a9 40 LDA #&40 &21c8 85 b8 STA &b8 ; pixel_table_address_low # Non-zero to indicate not flipped by default &21ca b9 1e 1a LDA &1a1e,Y ; movers_type_and_colour # Positive if ally, negative if enemy &21cd 10 0a BPL &21d9 ; not_white &21cf c9 85 CMP #&85 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER_WITH_MISSILE &21d1 f0 06 BEQ &21d9 ; not_white &21d3 c9 87 CMP #&87 ; MOVER_TYPE_ENEMY | MOVER_TYPE_HELICOPTER_WITH_SOLDIER &21d5 f0 02 BEQ &21d9 ; not_white &21d7 e6 b9 INC &b9 ; pixel_table_address_high # Use white pixel table for most enemies ; not_white &21d9 29 7f AND #&7f &21db 85 7a STA &7a ; mover_type ; leave &21dd 60 RTS ; plot_player &21de a0 00 LDY #&00 ; MOVER_PLAYER ; plot_mover &21e0 a5 b2 LDA &b2 ; viewport_left_low &21e2 85 b5 STA &b5 ; edge_x_low &21e4 84 79 STY &79 ; mover &21e6 98 TYA &21e7 f0 06 BEQ &21ef ; use_mask_table &21e9 a9 a9 LDA #&a9 ; LDA #&ff # Plot without mask &21eb a2 ff LDX #&ff &21ed d0 04 BNE &21f3 ; set_mask_table_lookup_opcode # Always branches ; use_mask_table &21ef a9 b1 LDA #&b1 ; LDA (&c8),Y ; mask_table_address # Plot with mask &21f1 a2 c8 LDX #&c8 ; set_mask_table_lookup_opcode &21f3 85 32 STA &32 ; mask_table_lookup_opcode &21f5 86 33 STX &33 ; mask_table_lookup_opcode + 1 &21f7 20 41 23 JSR &2341 ; get_mover_Y_x &21fa 20 c2 21 JSR &21c2 ; get_mover_type_and_colour # Returns A = mover type &21fd aa TAX &21fe 20 ef 23 JSR &23ef ; check_if_mover_is_on_screen # Returns carry set if mover not on screen &2201 b0 da BCS &21dd ; leave &2203 20 74 22 JSR &2274 ; get_mover_sprite_and_screen_addresses &2206 20 58 22 JSR &2258 ; plot_mover_sprite # Plot first part of mover (e.g. player's legs) &2209 a4 79 LDY &79 ; mover &220b 20 41 23 JSR &2341 ; get_mover_Y_x &220e a6 7a LDX &7a ; mover_type &2210 e0 0b CPX #&0b ; MOVER_TYPE_BLUE_CRAFT &2212 b0 5f BCS &2273 ; leave # Leave if the mover only uses one sprite &2214 b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &2217 29 3f AND #&3f &2219 7d a2 1b ADC &1ba2,X ; mover_types_second_sprite_offset &221c aa TAX &221d bd 72 1c LDA &1c72,X ; sprites_y_offset &2220 85 78 STA &78 ; y_offset &2222 a5 7a LDA &7a ; mover_type &2224 18 CLC &2225 69 14 ADC #&14 # Use mover types &14 - &1e for second part of mover &2227 aa TAX &2228 20 74 22 JSR &2274 ; get_mover_sprite_and_screen_addresses &222b a4 78 LDY &78 ; y_offset &222d 20 e5 20 JSR &20e5 ; subtract_Y_rows_from_screen_address_in_AX &2230 20 58 22 JSR &2258 ; plot_mover_sprite # Plot second part of mover (e.g. player's torso) &2233 a4 79 LDY &79 ; mover &2235 20 41 23 JSR &2341 ; get_mover_Y_x &2238 a6 7a LDX &7a ; mover_type &223a e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &223c b0 35 BCS &2273 ; leave # Leave if the mover only uses two sprites &223e a5 78 LDA &78 ; y_offset &2240 18 CLC &2241 69 08 ADC #&08 &2243 85 78 STA &78 ; y_offset &2245 a9 00 LDA #&00 &2247 85 cd STA &cd ; sprite_data_offset &2249 bd 9d 1b LDA &1b9d,X ; mover_types_third_sprite &224c aa TAX &224d b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &2250 20 7d 22 JSR &227d ; get_sprite_and_screen_addresses_for_frame_A &2253 a4 78 LDY &78 ; y_offset &2255 20 e5 20 JSR &20e5 ; subtract_Y_rows_from_screen_address_in_AX ; plot_mover_sprite # Plot third part of mover (e.g. player's head) &2258 85 3f STA &3f ; column_screen_address_low &225a 86 40 STX &40 ; column_screen_address_high &225c 85 ce STA &ce ; screen_address_low &225e 86 cf STX &cf ; screen_address_high &2260 a9 04 LDA #&04 &2262 85 c9 STA &c9 ; mask_table_address_high &2264 a5 b8 LDA &b8 ; pixel_table_address_low &2266 09 80 ORA #&80 &2268 85 c8 STA &c8 ; mask_table_address_low &226a a0 01 LDY #&01 &226c 20 04 00 JSR &0004 ; unpack_column_of_sprite &226f a9 40 LDA #&40 &2271 85 b8 STA &b8 ; pixel_table_address_low ; leave &2273 60 RTS ; get_mover_sprite_and_screen_addresses # Called with X = mover type &2274 a9 00 LDA #&00 &2276 85 cd STA &cd ; columns_to_clip_from_left &2278 a4 79 LDY &79 ; mover &227a 20 c3 23 JSR &23c3 ; get_mover_Y_sprite # Returns X = sprite, A = frame and flip ; get_sprite_and_screen_addresses_for_frame_A &227d 30 11 BMI &2290 ; is_flipped ; is_unflipped &227f bc 73 19 LDY &1973,X ; unflipped_mover_sprite_addresses_low_table &2282 bd ac 19 LDA &19ac,X ; unflipped_mover_sprite_addresses_high_table &2285 aa TAX &2286 20 c1 22 JSR &22c1 ; check_mover_x_against_viewport_left &2289 b0 1c BCS &22a7 ; set_sprite_address &228b 20 80 23 JSR &2380 ; clip_unflipped_mover_loop # Returns carry set &228e b0 17 BCS &22a7 ; set_sprite_address # Always branches ; is_flipped &2290 a9 00 LDA #&00 &2292 85 b8 STA &b8 ; pixel_table_address_low &2294 bc 09 17 LDY &1709,X ; flipped_mover_sprite_addresses_low_table &2297 84 ce STY &ce ; sprite_address_low &2299 bd e5 19 LDA &19e5,X ; flipped_mover_sprite_addresses_high_table &229c aa TAX &229d 86 cf STX &cf ; sprite_address_high &229f 20 c1 22 JSR &22c1 ; check_mover_x_against_viewport_left &22a2 b0 03 BCS &22a7 ; set_sprite_address &22a4 20 a1 23 JSR &23a1 ; clip_flipped_mover_loop ; set_sprite_address &22a7 84 05 STY &05 ; mover_sprite_address_low &22a9 86 06 STX &06 ; mover_sprite_address_high &22ab a4 79 LDY &79 ; mover &22ad be e4 1a LDX &1ae4,Y ; movers_screen_address_high &22b0 b9 c3 1a LDA &1ac3,Y ; movers_screen_address_low &22b3 a4 cd LDY &cd ; columns_to_clip_from_left &22b5 f0 09 BEQ &22c0 ; leave ; adjust_screen_address_loop &22b7 a0 00 LDY #&00 ; &0008 # Move right a column &22b9 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &22bc c6 cd DEC &cd ; columns_to_clip_from_left &22be d0 f7 BNE &22b7 ; adjust_screen_address_loop ; leave &22c0 60 RTS # Leave with AX = mover_screen_address ; check_mover_x_against_viewport_left &22c1 a5 c5 LDA &c5 ; mover_x_high &22c3 c5 ba CMP &ba ; viewport_left_high &22c5 d0 04 BNE &22cb ; leave &22c7 a5 f8 LDA &f8 ; mover_x_low &22c9 c5 b2 CMP &b2 ; viewport_left_low ; leave &22cb 60 RTS # Leave with carry set if mover_x >= viewport_left ; add_movers_to_column_buffer &22cc a9 a9 LDA #&a9 ; LDA #&ff # Plot without mask &22ce 8d 5e 20 STA &205e ; plot_scenery_mask_opcode &22d1 a9 ff LDA #&ff &22d3 8d 5f 20 STA &205f ; plot_scenery_mask_opcode + 1 &22d6 a0 01 LDY #&01 ; MOVER_FIRST + 1 &22d8 84 03 STY &03 ; mover_to_update ; add_movers_to_column_buffer_loop &22da a4 03 LDY &03 ; mover_to_update &22dc 20 c2 21 JSR &21c2 ; get_mover_type_and_colour # Returns A = mover type &22df 20 4c 23 JSR &234c ; check_if_mover_is_on_edge # Returns carry set if mover is on edge &22e2 90 49 BCC &232d ; consider_next_mover &22e4 a5 f9 LDA &f9 ; mover_y &22e6 20 30 20 JSR &2030 ; add_column_of_sprite_to_column_buffer # Add first part of mover (e.g. player's legs) &22e9 20 3a 23 JSR &233a ; get_mover_x_and_y &22ec a6 7a LDX &7a ; mover_type &22ee e0 0b CPX #&0b ; MOVER_TYPE_BLUE_CRAFT &22f0 b0 3b BCS &232d ; consider_next_mover # Finish if the mover only uses one sprite &22f2 a5 f9 LDA &f9 ; mover_y &22f4 b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &22f7 29 3f AND #&3f &22f9 7d a2 1b ADC &1ba2,X ; mover_types_second_sprite_offset &22fc aa TAX &22fd a5 f9 LDA &f9 ; mover_y &22ff 7d 72 1c ADC &1c72,X ; sprites_y_offset &2302 85 78 STA &78 ; y_offset &2304 a5 7a LDA &7a ; mover_type &2306 18 CLC &2307 69 14 ADC #&14 # Use mover types &14 - &1e for second part of mover &2309 aa TAX &230a 20 74 23 JSR &2374 ; calculate_sprite_address_for_mover_on_edge &230d a5 78 LDA &78 ; y_offset &230f 20 30 20 JSR &2030 ; add_column_of_sprite_to_column_buffer # Add second part of mover (e.g. player's torso) &2312 20 3a 23 JSR &233a ; get_mover_x_and_y &2315 a6 7a LDX &7a ; mover_type &2317 e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &2319 b0 12 BCS &232d ; consider_next_mover # Finish if the mover only uses two sprites &231b bd 9d 1b LDA &1b9d,X ; mover_types_third_sprite &231e aa TAX &231f b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &2322 20 77 23 JSR &2377 ; calculate_sprite_address_for_mover_on_edge_from_sprite &2325 a5 78 LDA &78 ; y_offset &2327 18 CLC &2328 69 08 ADC #&08 &232a 20 30 20 JSR &2030 ; add_column_of_sprite_to_column_buffer # Add third part of mover (e.g. player's head) ; consider_next_mover &232d a9 40 LDA #&40 &232f 85 b8 STA &b8 ; pixel_table_address_low # Set to &40 to use unflipped pixel table by default &2331 e6 03 INC &03 ; mover_to_update &2333 a4 03 LDY &03 ; mover_to_update &2335 c0 21 CPY #&21 ; MOVER_LAST + 1 &2337 90 a1 BCC &22da ; add_movers_to_column_buffer_loop &2339 60 RTS ; get_mover_x_and_y &233a a4 03 LDY &03 ; mover_to_update ; get_mover_Y_x_and_y &233c b9 a2 1a LDA &1aa2,Y ; movers_y &233f 85 f9 STA &f9 ; mover_y ; get_mover_Y_x &2341 b9 60 1a LDA &1a60,Y ; movers_x_low &2344 85 f8 STA &f8 ; mover_x_low &2346 b9 81 1a LDA &1a81,Y ; movers_x_high &2349 85 c5 STA &c5 ; mover_x_high &234b 60 RTS ; check_if_mover_is_on_edge &234c 20 3a 23 JSR &233a ; get_mover_x_and_y &234f a6 7a LDX &7a ; mover_type &2351 a4 c5 LDY &c5 ; mover_x_high &2353 c4 b4 CPY &b4 ; edge_x_high &2355 90 0a BCC &2361 ; check_x_max &2357 f0 02 BEQ &235b ; check_x_low ; leave_with_carry_clear &2359 18 CLC # Leave with carry clear to indicate mover not on edge &235a 60 RTS ; check_x_low &235b a5 b5 LDA &b5 ; edge_x_low &235d c5 f8 CMP &f8 ; mover_x_low &235f 90 f8 BCC &2359 ; leave_with_carry_clear ; check_x_max &2361 a5 f8 LDA &f8 ; mover_x_low &2363 18 CLC &2364 7d 75 1b ADC &1b75,X ; mover_types_width_table &2367 90 01 BCC &236a ; skip_overflow &2369 c8 INY ; skip_overflow &236a c4 b4 CPY &b4 ; edge_x_high &236c 90 eb BCC &2359 ; leave_with_carry_clear &236e d0 04 BNE &2374 ; is_on_edge &2370 c5 b5 CMP &b5 ; edge_x_low &2372 90 e5 BCC &2359 ; leave_with_carry_clear ; calculate_sprite_address_for_mover_on_edge &2374 20 c1 23 JSR &23c1 ; get_mover_sprite # Returns X = sprite, A = frame and flip ; calculate_sprite_address_for_mover_on_edge_from_sprite &2377 30 1a BMI &2393 ; is_flipped ; is_unflipped &2379 bc 73 19 LDY &1973,X ; unflipped_mover_sprite_addresses_low_table &237c bd ac 19 LDA &19ac,X ; unflipped_mover_sprite_addresses_high_table &237f aa TAX ; clip_unflipped_mover_loop &2380 a5 f8 LDA &f8 ; mover_x_low &2382 c5 b5 CMP &b5 ; edge_x_low &2384 f0 0b BEQ &2391 ; leave_with_carry_set &2386 20 04 20 JSR &2004 ; move_to_next_column_in_XY &2389 a8 TAY &238a e6 f8 INC &f8 ; mover_x_low &238c e6 cd INC &cd ; columns_to_clip_from_left &238e 4c 80 23 JMP &2380 ; clip_unflipped_mover_loop ; leave_with_carry_set &2391 38 SEC # Leave with carry set to indicate mover is on edge &2392 60 RTS ; is_flipped &2393 bd 09 17 LDA &1709,X ; flipped_mover_sprite_addresses_low_table &2396 85 ce STA &ce ; sprite_address_low &2398 bd e5 19 LDA &19e5,X ; flipped_mover_sprite_addresses_high_table &239b 85 cf STA &cf ; sprite_address_high &239d a9 00 LDA #&00 &239f 85 b8 STA &b8 ; pixel_table_address_low # Set to zero to use flipped pixel table ; clip_flipped_mover_loop &23a1 a0 00 LDY #&00 &23a3 a5 f8 LDA &f8 ; mover_x_low &23a5 c5 b5 CMP &b5 ; edge_x_low &23a7 f0 12 BEQ &23bb ; leave_with_sprite_address_and_carry_set &23a9 a5 ce LDA &ce ; sprite_address_low &23ab 38 SEC &23ac f1 ce SBC (&ce),Y ; sprite_address # Move back a column of sprite data &23ae 85 ce STA &ce ; sprite_address_low &23b0 b0 02 BCS &23b4 ; skip_page &23b2 c6 cf DEC &cf ; sprite_address_high ; skip_page &23b4 e6 f8 INC &f8 ; mover_x_low &23b6 e6 cd INC &cd ; columns_to_clip_from_left &23b8 4c a1 23 JMP &23a1 ; clip_flipped_mover_loop ; leave_with_sprite_address_and_carry_set &23bb a4 ce LDY &ce ; sprite_address_low &23bd a6 cf LDX &cf ; sprite_address_high &23bf 38 SEC # Leave with carry set to indicate mover is on edge &23c0 60 RTS ; get_mover_sprite &23c1 a4 03 LDY &03 ; mover_to_update ; get_mover_Y_sprite &23c3 b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &23c6 48 PHA ; mover_frame_and_flip &23c7 29 3f AND #&3f &23c9 18 CLC &23ca 7d 56 1b ADC &1b56,X ; mover_types_first_sprite_animation_offsets &23cd a8 TAY &23ce be 13 1c LDX &1c13,Y ; animation_table &23d1 68 PLA ; mover_frame_and_flip &23d2 60 RTS # Leave with X = sprite, A = mover frame and flip ; change_pixel_tables # Called with A = &14 (KC) or A = &55 (Kf) &23d3 85 ce STA &ce ; value &23d5 8d 54 04 STA &0454 ; unflipped_green_pixel_table + &14 # KC &23d8 8d 28 04 STA &0428 ; flipped_green_pixel_table + &28 &23db 0a ASL A &23dc 8d 14 04 STA &0414 ; flipped_green_pixel_table + &14 &23df 8d 68 04 STA &0468 ; unflipped_green_pixel_table + &28 # CK &23e2 45 ce EOR &ce ; value &23e4 8d 3c 04 STA &043c ; flipped_green_pixel_table + &3c &23e7 8d 7c 04 STA &047c ; unflipped_green_pixel_table + &3c # CC &23ea 60 RTS ; check_if_mover_Y_is_on_screen &23eb 20 33 31 JSR &3133 ; get_mover_Y_type # Returns A = mover type &23ee aa TAX ; check_if_mover_is_on_screen &23ef a4 c5 LDY &c5 ; mover_x_high &23f1 c4 bb CPY &bb ; viewport_right_high &23f3 90 0a BCC &23ff ; is_left_of_viewport_right &23f5 f0 02 BEQ &23f9 ; check_x_low ; leave_with_carry_set &23f7 38 SEC # Leave with carry set to indicate mover not on screen &23f8 60 RTS ; check_x_low &23f9 a5 b3 LDA &b3 ; viewport_right_low &23fb c5 f8 CMP &f8 ; mover_x_low &23fd 90 f8 BCC &23f7 ; leave_with_carry_set ; is_left_of_viewport_right &23ff bd 75 1b LDA &1b75,X ; mover_types_width_table &2402 18 CLC &2403 65 f8 ADC &f8 ; mover_x_low &2405 90 01 BCC &2408 ; skip_overflow &2407 c8 INY ; skip_overflow &2408 c4 ba CPY &ba ; viewport_left_high &240a 90 eb BCC &23f7 ; leave_with_carry_set &240c d0 04 BNE &2412 ; leave_with_carry_clear &240e c5 b2 CMP &b2 ; viewport_left_low &2410 90 e5 BCC &23f7 ; leave_with_carry_set ; leave_with_carry_clear &2412 18 CLC # Leave with carry clear to indicate mover is on screen &2413 60 RTS ; completion_screen &2414 a0 8d LDY #&8d ; &258d = completion_screen_text &2416 a2 25 LDX #&25 &2418 20 61 33 JSR &3361 ; text_screen ; game_over_screen &241b a0 e6 LDY #&e6 ; &33e6 = game_over_text &241d a2 33 LDX #&33 &241f 20 61 33 JSR &3361 ; text_screen ; press_space_to_play_screen &2422 a0 c1 LDY #&c1 ; &33c1 = press_space_to_play_text &2424 a2 33 LDX #&33 &2426 20 61 33 JSR &3361 ; text_screen ; start_game &2429 a2 17 LDX #&17 ; MOVER_FIRST_ALLY_HELICOPTER - 1 # Remove all movers except for ally helicopters &242b a9 ff LDA #&ff ; initialise_movers_loop &242d 9d 81 1a STA &1a81,X ; movers_x_high # Set to negative to indicate no mover in slot &2430 ca DEX &2431 10 fa BPL &242d ; initialise_movers_loop &2433 a2 20 LDX #&20 ; MOVER_LAST_ALLY_HELICOPTER ; initialise_player_helicopters_loop &2435 bd 76 1c LDA &1c76,X ; player_helicopters_type - &18 &2438 9d 1e 1a STA &1a1e,X ; movers_type_and_colour &243b bd 7f 1c LDA &1c7f,X ; player_helicopters_initial_x_low - &18 &243e 9d 60 1a STA &1a60,X ; movers_x_low &2441 bd 88 1c LDA &1c88,X ; player_helicopters_initial_x_high - &18 &2444 9d 81 1a STA &1a81,X ; movers_x_high &2447 a9 02 LDA #&02 &2449 9d a4 0b STA &0ba4,X ; movers_helicopter_fuel_high &244c a9 18 LDA #&18 &244e 9d a2 1a STA &1aa2,X ; movers_y &2451 ca DEX &2452 e0 17 CPX #&17 ; MOVER_FIRST_ALLY_HELICOPTER - 1 &2454 d0 df BNE &2435 ; initialise_player_helicopters_loop &2456 a9 26 LDA #&26 # Set player starting position &2458 8d 60 1a STA &1a60 ; movers_x_low &245b a9 18 LDA #&18 &245d 8d a2 1a STA &1aa2 ; movers_y &2460 a9 0a LDA #&0a ; MOVER_FIRST_HELICOPTER &2462 85 80 STA &80 ; helicopter_to_update &2464 a9 09 LDA #&09 # Player starts with nine lives &2466 85 95 STA &95 ; lives &2468 a9 04 LDA #&04 &246a 85 b9 STA &b9 ; pixel_table_address_high &246c a9 40 LDA #&40 &246e 85 b8 STA &b8 ; pixel_table_address_low &2470 a2 01 LDX #&01 &2472 86 7f STX &7f ; new_movers_offset &2474 86 c0 STX &c0 ; movers_to_update_base &2476 ca DEX ; 0 &2477 86 7e STX &7e ; trigger_offset &2479 86 82 STX &82 ; player_y_velocity &247b 86 84 STX &84 ; player_helicopter # Set to zero to indicate not in helicopter &247d 86 8e STX &8e ; player_firing_cooldown &247f 86 8f STX &8f ; player_helicopter_explosion # Set to zero to indicate not exploding &2481 8e 81 1a STX &1a81 ; movers_x_high &2484 8e 1e 1a STX &1a1e ; movers_type_and_colour ; initialise_enemies_loop &2487 86 78 STX &78 ; initial_new_movers_offset &2489 20 43 32 JSR &3243 ; add_new_movers &248c a6 78 LDX &78 ; initial_new_movers_offset &248e e8 INX &248f e0 03 CPX #&03 &2491 90 f4 BCC &2487 ; initialise_enemies_loop &2493 a9 02 LDA #&02 # Set colour 0 to magenta &2495 85 94 STA &94 ; bottom_palette_value &2497 a0 05 LDY #&05 &2499 a9 6c LDA #&6c ; "0" ; initialise_score_loop &249b 99 fa 33 STA &33fa,Y ; game_over_text + &14 &249e 88 DEY &249f 10 fa BPL &249b ; initialise_score_loop &24a1 20 f1 24 JSR &24f1 ; scroll_into_world &24a4 20 60 2a JSR &2a60 ; buffer_player &24a7 a0 00 LDY #&00 ; MOVER_PLAYER &24a9 20 e0 21 JSR &21e0 ; plot_mover &24ac 20 f8 32 JSR &32f8 ; plot_lives ; main_game_loop &24af a5 95 LDA &95 ; lives &24b1 10 07 BPL &24ba ; not_game_over &24b3 a5 96 LDA &96 ; game_over_cooldown &24b5 10 27 BPL &24de ; not_at_headquarters &24b7 4c 1b 24 JMP &241b ; game_over_screen ; not_game_over &24ba 20 f6 2f JSR &2ff6 ; check_for_player_input &24bd a5 c2 LDA &c2 ; keys_pressed_bitmap # Negative if &80 (KEY_PAUSE) set &24bf 10 09 BPL &24ca ; not_paused ; wait_for_unpause &24c1 20 f6 2f JSR &2ff6 ; check_for_player_input &24c4 a5 c2 LDA &c2 ; keys_pressed_bitmap &24c6 29 7f AND #&7f ; !KEY_PAUSE &24c8 f0 f7 BEQ &24c1 ; wait_for_unpause ; not_paused &24ca 20 63 28 JSR &2863 ; update_player &24cd ad 60 1a LDA &1a60 ; movers_x_low &24d0 c9 02 CMP #&02 &24d2 d0 0a BNE &24de ; not_at_headquarters &24d4 ad 81 1a LDA &1a81 ; movers_x_high &24d7 c9 1b CMP #&1b &24d9 d0 03 BNE &24de ; not_at_headquarters &24db 4c 14 24 JMP &2414 ; completion_screen ; not_at_headquarters &24de 20 a0 2c JSR &2ca0 ; update_projectiles &24e1 20 cc 2a JSR &2acc ; update_movers &24e4 4c af 24 JMP &24af ; main_game_loop ; check_for_keypress &24e7 a0 ff LDY #&ff &24e9 a9 81 LDA #&81 ; Scan for a particular key &24eb 20 f4 ff JSR &fff4 ; OSBYTE &24ee e0 ff CPX #&ff &24f0 60 RTS ; scroll_into_world &24f1 20 55 25 JSR &2555 ; reset_screen_scroll &24f4 a2 05 LDX #&05 &24f6 8e fa 02 STX &02fa ; unused_variable # Unused variable &24f9 20 3d 25 JSR &253d ; initialise_scenery_layer_addresses &24fc 20 3d 25 JSR &253d ; initialise_scenery_layer_addresses &24ff a2 01 LDX #&01 ; R1: Number of characters per line &2501 8e 00 fe STX &fe00 ; video register number &2504 ca DEX ; 0 # Hide screen &2505 8e 01 fe STX &fe01 ; video register value &2508 a9 4f LDA #&4f &250a 85 02 STA &02 ; count ; scroll_into_world_loop &250c 20 4b 1e JSR &1e4b ; scroll_screen_right &250f 20 fd 1e JSR &1efd ; update_screen_without_delay &2512 c6 02 DEC &02 ; count &2514 d0 f6 BNE &250c ; scroll_into_world_loop &2516 a2 02 LDX #&02 &2518 20 3d 25 JSR &253d ; initialise_scenery_layer_addresses &251b a2 00 LDX #&00 &251d 8d cb 1f STA &1fcb ; ground_left_x_low &2520 20 4b 1e JSR &1e4b ; scroll_screen_right &2523 20 fd 1e JSR &1efd ; update_screen_without_delay &2526 20 38 25 JSR &2538 ; wait_for_vsync &2529 a2 01 LDX #&01 ; R1: Number of characters per line &252b 8e 00 fe STX &fe00 ; video register number &252e a9 50 LDA #&50 # Display screen &2530 8d 01 fe STA &fe01 ; video register value &2533 ca DEX ; 0 &2534 8e fa 02 STX &02fa ; unused_variable # Unused variable &2537 60 RTS ; wait_for_vsync &2538 a9 13 LDA #&13 ; Wait for vertical retrace &253a 4c f4 ff JMP &fff4 ; OSBYTE ; initialise_scenery_layer_addresses &253d a0 02 LDY #&02 ; initialise_scenery_layer_addresses_loop &253f b9 87 25 LDA &2587,Y ; initial_scenery_layer_addresses_high &2542 9d f2 02 STA &02f2,X ; scenery_layer_addresses_high &2545 b9 8a 25 LDA &258a,Y ; initial_scenery_layer_addresses_low &2548 9d aa 01 STA &01aa,X ; scenery_layer_addresses_low &254b a9 00 LDA #&00 &254d 9d c8 03 STA &03c8,X ; scenery_layer_sprite_addresses_high &2550 ca DEX &2551 88 DEY &2552 10 eb BPL &253f ; initialise_scenery_layer_addresses_loop &2554 60 RTS ; reset_screen_scroll &2555 a2 0d LDX #&0d ; R13: Displayed screen start address register (low) &2557 8e 00 fe STX &fe00 ; video register number &255a a0 00 LDY #&00 &255c 84 b1 STY &b1 ; crtc_start_address_low &255e 8c 01 fe STY &fe01 ; video register value &2561 ca DEX ; &0c ; R12: Displayed screen start address register (high) &2562 8e 00 fe STX &fe00 ; video register number &2565 a9 08 LDA #&08 &2567 85 b0 STA &b0 ; crtc_start_address_high &2569 8d 01 fe STA &fe01 ; video register value &256c 88 DEY ; &ff &256d 84 b3 STY &b3 ; viewport_right_low &256f 84 ba STY &ba ; viewport_left_high &2571 84 bb STY &bb ; viewport_right_high &2573 8c cc 1f STY &1fcc ; ground_right_x_low &2576 a9 b0 LDA #&b0 &2578 85 b2 STA &b2 ; viewport_left_low &257a a2 01 LDX #&01 ; reset_screen_start_address_loop &257c bd 85 25 LDA &2585,X ; initial_screen_start_address &257f 95 00 STA &00,X ; screen_start_address &2581 ca DEX &2582 10 f8 BPL &257c ; reset_screen_start_address_loop &2584 60 RTS ; initial_screen_start_address &2585 00 40 ; initial_scenery_layer_addresses_high # &00 : &14fe = scenery_data_one ; 0 1 2 # &01 : &166b = scenery_data_two &2587 14 16 83 # &02 : &8300 = rom + &300 (used for mountains) ; initial_scenery_layer_addresses_low &258a fe 6b 00 ; completion_screen_text &258d 78 45 ; at &4578 &258f 2a 18 48 48 18 36 30 60 06 36 2a 3c 24 12 4e 12 ; "MISSION COMPLETED" &259f 0c &25a0 fe ; end of string &25a1 38 57 ; at &5738 &25a3 06 36 0c 12 60 54 18 06 4e 36 42 5a ; "CODE VICTORY" &25af ff ; end of text ; consider_adding_player_bullet_or_grenade &25b0 29 10 AND #&10 ; KEY_FIRE &25b2 f0 30 BEQ &25e4 ; consider_adding_player_grenade &25b4 ad 92 1a LDA &1a92 ; movers_x_high + &11 (MOVER_PLAYER_BULLET) &25b7 10 2b BPL &25e4 ; consider_adding_player_grenade # Positive if a bullet already in slot &25b9 a9 06 LDA #&06 ; FRAME_SHOOTING &25bb 85 81 STA &81 ; frame &25bd 85 a0 STA &a0 ; firing_frame &25bf a5 84 LDA &84 ; player_helicopter # Non-zero if in helicopter &25c1 d0 05 BNE &25c8 ; add_player_bullet &25c3 a9 04 LDA #&04 &25c5 85 8e STA &8e ; player_firing_cooldown &25c7 60 RTS ; add_player_bullet &25c8 a2 05 LDX #&05 ; MOVER_PLAYER_BULLET - &c &25ca 86 86 STX &86 ; projectile_slot &25cc e8 INX ; 6 ; FRAME_SHOOTING &25cd 86 a0 STX &a0 ; firing_frame &25cf ae 1e 1a LDX &1a1e ; movers_type_and_colour &25d2 20 38 2e JSR &2e38 ; add_bullet # Returns carry set if bullet couldn't be added &25d5 b0 41 BCS &2618 ; leave &25d7 a9 0c LDA #&0c &25d9 8d 4f 1b STA &1b4f ; projectiles_ttl - &c + &11 (MOVER_PLAYER_BULLET) ; plot_bullet_and_play_sound &25dc 20 b6 30 JSR &30b6 ; plot_projectile &25df a9 20 LDA #&20 # Play sound for firing bullet &25e1 4c 1b 30 JMP &301b ; play_sound ; consider_adding_player_grenade &25e4 a5 c2 LDA &c2 ; keys_pressed_bitmap &25e6 29 20 AND #&20 ; KEY_GRENADE &25e8 f0 2e BEQ &2618 ; leave &25ea a5 84 LDA &84 ; player_helicopter # Zero if player not in helicopter &25ec f0 07 BEQ &25f5 ; add_player_grenade &25ee ad a2 1a LDA &1aa2 ; movers_y &25f1 c9 30 CMP #&30 # Helicopter can't drop bombs if too low &25f3 90 23 BCC &2618 ; leave ; add_player_grenade &25f5 a2 00 LDX #&00 ; MOVER_PLAYER_GRENADE - &c &25f7 bd 8d 1a LDA &1a8d,X ; movers_x_high + &c (MOVER_PLAYER_GRENADE) &25fa 10 1c BPL &2618 ; leave &25fc 86 86 STX &86 ; projectile_slot &25fe ae 1e 1a LDX &1a1e ; movers_type_and_colour &2601 20 5d 2e JSR &2e5d ; add_new_grenade_to_slot &2604 b0 12 BCS &2618 ; leave &2606 a6 84 LDX &84 ; player_helicopter # Zero if player not in helicopter &2608 f0 07 BEQ &2611 ; skip_setting_velocity &260a a5 82 LDA &82 ; player_y_velocity &260c 10 03 BPL &2611 ; skip_setting_velocity &260e 99 32 1b STA &1b32,Y ; projectiles_y_velocity ; skip_setting_velocity &2611 a9 0c LDA #&0c ; FRAME_THROWING &2613 85 81 STA &81 ; frame &2615 20 dd 32 JSR &32dd ; plot_grenade_and_play_sound ; leave &2618 60 RTS ; add_enemy_helicopters # Called with A = viewport_right_high &2619 85 78 STA &78 ; right_high &261b 0a ASL A &261c a8 TAY &261d a2 0a LDX #&0a ; MOVER_FIRST_HELICOPTER ; add_enemy_helicopters_loop &261f bd f2 14 LDA &14f2,X ; enemy_helicopters_initial_x - &a &2622 9d 60 1a STA &1a60,X ; movers_x_low &2625 38 SEC &2626 e9 28 SBC #&28 &2628 9d 1d 30 STA &301d,X ; enemy_helicopters_minimum_x_low - &a &262b 18 CLC &262c 69 64 ADC #&64 &262e 9d 1b 30 STA &301b,X ; enemy_helicopters_maximum_x_low - &a &2631 a5 78 LDA &78 ; right_high &2633 9d 81 1a STA &1a81,X ; movers_x_high &2636 8a TXA &2637 18 CLC &2638 65 78 ADC &78 ; right_high &263a a8 TAY &263b b9 00 83 LDA &8300,Y ; rom + &300 # Use ROM as pseudo-random stream for enemy helicopters &263e 29 07 AND #&07 &2640 a8 TAY &2641 b9 ec 18 LDA &18ec,Y ; new_helicopter_types &2644 9d 1e 1a STA &1a1e,X ; movers_type_and_colour &2647 ad 68 fe LDA &fe68 ; User VIA timer 2 counter LSB &264a 29 1f AND #&1f # Use random height for helicopter &264c 18 CLC &264d 69 73 ADC #&73 &264f 9d a2 1a STA &1aa2,X ; movers_y &2652 a9 00 LDA #&00 &2654 9d 3f 1a STA &1a3f,X ; movers_frame_and_flip &2657 c8 INY &2658 e8 INX &2659 e0 0c CPX #&0c ; MOVER_LAST_HELICOPTER + 1 &265b 90 c2 BCC &261f ; add_enemy_helicopters_loop &265d 60 RTS ; animate_mover &265e a9 80 LDA #&80 &2660 85 8d STA &8d ; hostile_mover # Set to negative to indicate no hostile mover &2662 85 81 STA &81 ; mover_had_hostile_collision # Set to negative to indicate no hostile collision &2664 20 31 31 JSR &3131 ; get_mover_type # Returns A = mover type &2667 c9 0d CMP #&0d ; MOVER_TYPE_SKELETON &2669 f0 19 BEQ &2684 ; skip_animation &266b aa TAX &266c bd ad 1b LDA &1bad,X ; mover_types_animation_frames &266f 85 c6 STA &c6 ; frames &2671 b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &2674 29 7f AND #&7f &2676 aa TAX &2677 e8 INX &2678 e4 c6 CPX &c6 ; frames &267a 90 02 BCC &267e ; skip_wraparound &267c a2 00 LDX #&00 ; skip_wraparound &267e 8a TXA &267f 05 7b ORA &7b ; flip &2681 99 3f 1a STA &1a3f,Y ; movers_frame_and_flip ; skip_animation &2684 b9 a2 1a LDA &1aa2,Y ; movers_y &2687 60 RTS ; move_mover_right &2688 a5 f8 LDA &f8 ; mover_x_low &268a 18 CLC &268b 65 7c ADC &7c ; x_delta &268d aa TAX &268e a5 c5 LDA &c5 ; mover_x_high &2690 69 00 ADC #&00 &2692 a8 TAY &2693 20 a8 26 JSR &26a8 ; check_for_collision_after_horizontal_move # Returns carry set if hostile collision occurred &2696 b0 08 BCS &26a0 ; skip_changing_screen_address &2698 a4 7c LDY &7c ; x_delta &269a 88 DEY &269b 30 03 BMI &26a0 ; skip_changing_screen_address &269d 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX ; skip_changing_screen_address &26a0 85 c2 STA &c2 ; mover_screen_address_low &26a2 86 c3 STX &c3 ; mover_screen_address_high &26a4 20 f7 1f JSR &1ff7 ; use_viewport_left_as_edge &26a7 60 RTS ; check_for_collision_after_horizontal_move &26a8 8a TXA &26a9 20 59 2b JSR &2b59 ; check_for_mover_collision_with_movers # Returns carry set if collision, X = mover collided with &26ac 20 c2 26 JSR &26c2 ; check_for_hostile_collision # Returns carry set if collision was hostile &26af 90 0c BCC &26bd ; not_hostile &26b1 c6 81 DEC &81 ; mover_had_hostile_collision # Set to positive to indicate hostile collision &26b3 b9 60 1a LDA &1a60,Y ; movers_x_low &26b6 85 f8 STA &f8 ; mover_x_low &26b8 b9 81 1a LDA &1a81,Y ; movers_x_high &26bb 85 c5 STA &c5 ; mover_x_high ; not_hostile &26bd a6 c3 LDX &c3 ; mover_screen_address_high &26bf a5 c2 LDA &c2 ; mover_screen_address_low &26c1 60 RTS ; check_for_hostile_collision &26c2 bd 1e 1a LDA &1a1e,X ; movers_type_and_colour &26c5 a4 03 LDY &03 ; mover_to_update &26c7 90 1e BCC &26e7 ; leave_with_carry_clear # Carry is clear if no collision occurred &26c9 d0 0a BNE &26d5 ; not_player ; is_player &26cb c9 0d CMP #&0d ; MOVER_TYPE_SKELETON &26cd 90 18 BCC &26e7 ; leave_with_carry_clear # Player can walk through all friendly movers &26cf c9 8c CMP #&8c ; MOVER_TYPE_ENEMY | MOVER_TYPE_SAM &26d1 f0 14 BEQ &26e7 ; leave_with_carry_clear # Player can walk through enemy SAM &26d3 d0 0e BNE &26e3 ; leave_with_carry_set # Everything else is hostile to player; always branches ; not_player &26d5 c0 0c CPY #&0c ; MOVER_FIRST_PROJECTILE &26d7 90 0a BCC &26e3 ; leave_with_carry_set # All collisions involving enemies are hostile &26d9 29 7f AND #&7f &26db c9 13 CMP #&13 ; MOVER_TYPE_MINE &26dd f0 04 BEQ &26e3 ; leave_with_carry_set # All collisions involving mines are hostile &26df c9 0c CMP #&0c ; MOVER_TYPE_SAM &26e1 b0 04 BCS &26e7 ; leave_with_carry_clear # Ignore collisions with skeletons, explosions and projectiles ; leave_with_carry_set &26e3 86 8d STX &8d ; hostile_mover &26e5 38 SEC # Leave with carry set to indicate hostile collision &26e6 60 RTS ; leave_with_carry_clear &26e7 18 CLC # Leave with carry clear to indicate not hostile &26e8 60 RTS ; move_mover_left &26e9 a5 f8 LDA &f8 ; mover_x_low &26eb 38 SEC &26ec e5 7c SBC &7c ; x_delta &26ee aa TAX &26ef a5 c5 LDA &c5 ; mover_x_high &26f1 e9 00 SBC #&00 &26f3 a8 TAY &26f4 20 a8 26 JSR &26a8 ; check_for_collision_after_horizontal_move # Returns carry set if hostile collision occurred &26f7 b0 08 BCS &2701 ; skip_changing_screen_address &26f9 a4 7c LDY &7c ; x_delta &26fb 88 DEY &26fc 30 03 BMI &2701 ; skip_changing_screen_address &26fe 20 d2 20 JSR &20d2 ; subtract_delta_from_screen_address_in_AX ; skip_changing_screen_address &2701 85 c2 STA &c2 ; mover_screen_address_low &2703 86 c3 STX &c3 ; mover_screen_address_high &2705 20 ef 1f JSR &1fef ; use_viewport_right_as_edge &2708 60 RTS ; move_mover_up # Called with A = mover_y &2709 18 CLC &270a 65 7d ADC &7d ; y_delta &270c 85 f9 STA &f9 ; mover_y &270e 20 1f 27 JSR &271f ; check_for_collision_after_vertical_move &2711 b0 07 BCS &271a ; skip_changing_screen_address &2713 a4 7d LDY &7d ; y_delta &2715 f0 03 BEQ &271a ; skip_changing_screen_address &2717 20 e5 20 JSR &20e5 ; subtract_Y_rows_from_screen_address_in_AX ; skip_changing_screen_address ; set_mover_screen_address &271a 86 c3 STX &c3 ; mover_screen_address_high &271c 85 c2 STA &c2 ; mover_screen_address_low &271e 60 RTS ; check_for_collision_after_vertical_move &271f a6 03 LDX &03 ; mover_to_update &2721 bc 81 1a LDY &1a81,X ; movers_x_high &2724 bd 60 1a LDA &1a60,X ; movers_x_low &2727 20 59 2b JSR &2b59 ; check_for_mover_collision_with_movers # Returns carry set if collision, X = mover collided with &272a 20 c2 26 JSR &26c2 ; check_for_hostile_collision # Returns carry set if collision was hostile &272d 90 05 BCC &2734 ; no_collision &272f b9 a2 1a LDA &1aa2,Y ; movers_y &2732 85 f9 STA &f9 ; mover_y ; no_collision &2734 be e4 1a LDX &1ae4,Y ; movers_screen_address_high &2737 b9 c3 1a LDA &1ac3,Y ; movers_screen_address_low &273a 60 RTS ; move_mover_down # Called with A = mover_y &273b 38 SEC &273c e5 7d SBC &7d ; y_delta &273e 85 f9 STA &f9 ; mover_y &2740 20 1f 27 JSR &271f ; check_for_collision_after_vertical_move &2743 b0 d5 BCS &271a ; skip_changing_screen_address &2745 a4 7d LDY &7d ; y_delta &2747 f0 d1 BEQ &271a ; skip_changing_screen_address &2749 20 fe 20 JSR &20fe ; add_Y_rows_from_screen_address_in_AX &274c 4c 1a 27 JMP &271a ; set_mover_screen_address ; move_mover_up_and_right &274f 20 09 27 JSR &2709 ; move_mover_up &2752 4c 88 26 JMP &2688 ; move_mover_right ; move_mover_down_and_right &2755 20 3b 27 JSR &273b ; move_mover_down &2758 4c 88 26 JMP &2688 ; move_mover_right ; move_mover_up_and_left &275b 20 09 27 JSR &2709 ; move_mover_up &275e 4c e9 26 JMP &26e9 ; move_mover_left ; move_mover_down_and_left &2761 20 3b 27 JSR &273b ; move_mover_down &2764 4c e9 26 JMP &26e9 ; move_mover_left ; unplot_and_move_mover &2767 a4 03 LDY &03 ; mover_to_update &2769 20 e0 21 JSR &21e0 ; plot_mover # Unplot mover ; move_mover &276c a5 7c LDA &7c ; x_delta &276e 29 80 AND #&80 &2770 85 7b STA &7b ; flip &2772 0a ASL A &2773 2a ROL A &2774 48 PHA ; x direction &2775 a5 7d LDA &7d ; y_delta &2777 0a ASL A &2778 68 PLA ; x direction &2779 2a ROL A &277a aa TAX &277b bd dd 2b LDA &2bdd,X ; move_mover_routine_addresses_high_table &277e 8d 98 27 STA &2798 ; move_mover_routine_address_high &2781 bd e1 2b LDA &2be1,X ; move_mover_routine_addresses_low_table &2784 8d 97 27 STA &2797 ; move_mover_routine_address_low &2787 a5 7c LDA &7c ; x_delta &2789 29 7f AND #&7f &278b 85 7c STA &7c ; x_delta &278d a5 7d LDA &7d ; y_delta &278f 29 7f AND #&7f &2791 85 7d STA &7d ; y_delta &2793 20 5e 26 JSR &265e ; animate_mover # Returns A = mover_y &2796 20 ff ff JSR &ffff # Move mover up or down, then right or left # actually JSR move_mover_routine_address &2799 a4 03 LDY &03 ; mover_to_update &279b a5 f8 LDA &f8 ; mover_x_low &279d 99 60 1a STA &1a60,Y ; movers_x_low &27a0 a5 c5 LDA &c5 ; mover_x_high &27a2 99 81 1a STA &1a81,Y ; movers_x_high &27a5 a5 c2 LDA &c2 ; mover_screen_address_low &27a7 99 c3 1a STA &1ac3,Y ; movers_screen_address_low &27aa a5 c3 LDA &c3 ; mover_screen_address_high &27ac 99 e4 1a STA &1ae4,Y ; movers_screen_address_high &27af a5 f9 LDA &f9 ; mover_y &27b1 99 a2 1a STA &1aa2,Y ; movers_y &27b4 85 c6 STA &c6 ; y &27b6 a9 c7 LDA #&c7 &27b8 38 SEC &27b9 e5 c6 SBC &c6 ; y &27bb 18 CLC &27bc 69 18 ADC #&18 &27be a2 4e LDX #&4e &27c0 20 af 2f JSR &2faf ; multiply_A_by_X &27c3 a4 03 LDY &03 ; mover_to_update &27c5 a5 c6 LDA &c6 ; result_high &27c7 99 05 1b STA &1b05,Y ; movers_raster_y &27ca 20 22 21 JSR &2122 ; calculate_screen_addresses_for_mover_on_edge &27cd c0 00 CPY #&00 ; MOVER_PLAYER &27cf d0 12 BNE &27e3 ; leave &27d1 a5 81 LDA &81 ; mover_had_hostile_collision # Positive if mover had hostile collision &27d3 10 0e BPL &27e3 ; leave # Don't scroll if player had hostile collision &27d5 a5 7c LDA &7c ; x_delta &27d7 f0 0a BEQ &27e3 ; leave &27d9 a5 7b LDA &7b ; flip &27db 10 03 BPL &27e0 ; to_scroll_screen_right &27dd 4c a9 1c JMP &1ca9 ; scroll_screen_left ; to_scroll_screen_right &27e0 20 4b 1e JSR &1e4b ; scroll_screen_right ; leave &27e3 60 RTS ; use_player_position_for_mover_Y &27e4 ae e4 1a LDX &1ae4 ; movers_screen_address_high &27e7 ad c3 1a LDA &1ac3 ; movers_screen_address_low ; use_player_position_for_mover_Y_with_screen_address_from_AX &27ea 99 c3 1a STA &1ac3,Y ; movers_screen_address_low &27ed 8a TXA &27ee 99 e4 1a STA &1ae4,Y ; movers_screen_address_high &27f1 ad 81 1a LDA &1a81 ; movers_x_high &27f4 99 81 1a STA &1a81,Y ; movers_x_high &27f7 ad 60 1a LDA &1a60 ; movers_x_low &27fa 99 60 1a STA &1a60,Y ; movers_x_low &27fd ad 3f 1a LDA &1a3f ; movers_frame_and_flip &2800 99 3f 1a STA &1a3f,Y ; movers_frame_and_flip &2803 60 RTS ; leave_helicopter &2804 20 67 2a JSR &2a67 ; unbuffer_player_getting_addresses &2807 a4 84 LDY &84 ; player_helicopter &2809 20 e4 27 JSR &27e4 ; use_player_position_for_mover_Y &280c a5 98 LDA &98 ; helicopter_fuel_high &280e 99 a4 0b STA &0ba4,Y ; movers_helicopter_fuel_high ; set_player_as_soldier &2811 a9 00 LDA #&00 ; MOVER_TYPE_PLAYER &2813 85 84 STA &84 ; player_helicopter # Set to zero to indicate player not in helicopter &2815 8d 1e 1a STA &1a1e ; movers_type_and_colour &2818 20 e0 21 JSR &21e0 ; plot_mover &281b 4c 5d 28 JMP &285d ; buffer_and_plot_player ; enter_or_leave_helicopter &281e a4 84 LDY &84 ; player_helicopter # Zero if player not in helicopter &2820 d0 e2 BNE &2804 ; leave_helicopter &2822 a9 01 LDA #&01 &2824 85 81 STA &81 ; mover_x_offset &2826 20 3a 23 JSR &233a ; get_mover_x_and_y &2829 20 7b 2d JSR &2d7b ; calculate_mover_x_max_from_offset_getting_frame_and_flip &282c a9 33 LDA #&33 &282e 85 c9 STA &c9 ; mover_y_max &2830 a2 17 LDX #&17 ; MOVER_FIRST_ALLY_HELICOPTER - 1 &2832 86 b7 STX &b7 ; last_mover &2834 a2 21 LDX #&21 ; MOVER_LAST_ALLY_HELICOPTER + 1 # Bug: should be &20 &2836 20 6c 2b JSR &2b6c ; check_for_mover_collision_with_range_of_movers &2839 90 6c BCC &28a7 ; leave # Carry clear if no collision, otherwise X = mover &283b 86 8d STX &8d ; helicopter &283d 20 67 2a JSR &2a67 ; unbuffer_player_getting_addresses &2840 a4 8d LDY &8d ; helicopter &2842 84 84 STY &84 ; player_helicopter &2844 b9 1e 1a LDA &1a1e,Y ; movers_type_and_colour &2847 8d 1e 1a STA &1a1e ; movers_type_and_colour # Turn player into helicopter &284a b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &284d 8d 3f 1a STA &1a3f ; movers_frame_and_flip &2850 20 e0 21 JSR &21e0 ; plot_mover &2853 a4 84 LDY &84 ; player_helicopter &2855 20 9a 2c JSR &2c9a ; remove_mover &2858 b9 a4 0b LDA &0ba4,Y ; movers_helicopter_fuel_high &285b 85 98 STA &98 ; helicopter_fuel_high ; buffer_and_plot_player &285d 20 60 2a JSR &2a60 ; buffer_player &2860 4c de 21 JMP &21de ; plot_player ; update_player &2863 a0 00 LDY #&00 ; MOVER_PLAYER &2865 84 03 STY &03 ; mover_to_update &2867 a5 8f LDA &8f ; player_helicopter_explosion # Zero if player helicopter is not exploding &2869 f0 0e BEQ &2879 ; not_in_exploding_helicopter ; update_player_in_exploding_helicopter &286b ad 92 1a LDA &1a92 ; movers_x_high + &11 (MOVER_PLAYER_BULLET) &286e 10 37 BPL &28a7 ; leave # Positive if explosion animation hasn't finished &2870 84 8f STY &8f ; player_helicopter_explosion # Set to zero to indicate explosion has finished &2872 84 83 STY &83 ; player_jump_direction &2874 a4 84 LDY &84 ; player_helicopter &2876 4c 11 28 JMP &2811 ; set_player_as_soldier ; not_in_exploding_helicopter &2879 ad 1e 1a LDA &1a1e ; movers_type_and_colour &287c c9 0d CMP #&0d ; MOVER_TYPE_SKELETON &287e d0 1c BNE &289c ; not_skeleton ; is_skeleton &2880 20 be 2a JSR &2abe ; check_if_player_is_on_ground &2883 d0 57 BNE &28dc ; to_to_consider_falling ; is_skeleton_on_ground &2885 20 67 2a JSR &2a67 ; unbuffer_player_getting_addresses &2888 ad 3f 1a LDA &1a3f ; movers_frame_and_flip &288b 29 7f AND #&7f &288d d0 07 BNE &2896 ; animate_player_skeleton # Zero at end of animation &288f a9 50 LDA #&50 &2891 85 96 STA &96 ; game_over_cooldown &2893 c6 95 DEC &95 ; lives # Set to negative to indicate game over &2895 60 RTS ; animate_player_skeleton &2896 ce 3f 1a DEC &1a3f ; movers_frame_and_flip &2899 4c de 21 JMP &21de ; plot_player ; not_skeleton &289c a5 8e LDA &8e ; player_firing_cooldown &289e f0 08 BEQ &28a8 ; not_firing &28a0 c6 8e DEC &8e ; player_firing_cooldown &28a2 d0 03 BNE &28a7 ; leave &28a4 20 c8 25 JSR &25c8 ; add_player_bullet ; leave &28a7 60 RTS ; not_firing &28a8 20 be 2a JSR &2abe ; check_if_player_is_on_ground &28ab d0 09 BNE &28b6 ; not_entering_or_leaving_helicopter &28ad a5 c2 LDA &c2 ; keys_pressed_bitmap &28af 29 40 AND #&40 ; KEY_ENTER &28b1 f0 03 BEQ &28b6 ; not_entering_or_leaving_helicopter &28b3 4c 1e 28 JMP &281e ; enter_or_leave_helicopter ; not_entering_or_leaving_helicopter &28b6 ad 3f 1a LDA &1a3f ; movers_frame_and_flip &28b9 29 80 AND #&80 &28bb 85 7b STA &7b ; flip &28bd aa TAX &28be a5 c2 LDA &c2 ; keys_pressed_bitmap &28c0 29 0c AND #&0c ; KEY_RIGHT | KEY_LEFT &28c2 f0 0d BEQ &28d1 ; set_x_delta &28c4 c9 0c CMP #&0c ; KEY_RIGHT | KEY_LEFT &28c6 f0 09 BEQ &28d1 ; set_x_delta &28c8 88 DEY ; &ff # Set to negative to indicate moving horizontally &28c9 a2 01 LDX #&01 # Set player moving right &28cb c9 04 CMP #&04 ; KEY_RIGHT &28cd f0 02 BEQ &28d1 ; set_x_delta &28cf a2 81 LDX #&81 # Set player moving left ; set_x_delta &28d1 86 7c STX &7c ; x_delta &28d3 84 81 STY &81 ; frame # Set to zero if player is not moving, &ff if moving &28d5 a5 84 LDA &84 ; player_helicopter # Zero if player not in helicopter &28d7 d0 0c BNE &28e5 ; check_for_player_firing &28d9 20 be 2a JSR &2abe ; check_if_player_is_on_ground ; to_to_consider_falling &28dc d0 3c BNE &291a ; to_consider_falling ; is_soldier_on_ground &28de a5 80 LDA &80 ; helicopter_to_update &28e0 29 01 AND #&01 &28e2 f0 01 BEQ &28e5 ; check_for_player_firing # Branch one in two frames ; leave &28e4 60 RTS ; check_for_player_firing &28e5 a5 c2 LDA &c2 ; keys_pressed_bitmap &28e7 29 30 AND #&30 ; KEY_FIRE | KEY_GRENADE &28e9 f0 07 BEQ &28f2 ; not_firing &28eb 20 b0 25 JSR &25b0 ; consider_adding_player_bullet_or_grenade &28ee a5 84 LDA &84 ; player_helicopter # Zero if player not in helicopter &28f0 f0 4c BEQ &293e ; skip_vertical_movement ; not_firing &28f2 ad 3f 1a LDA &1a3f ; movers_frame_and_flip &28f5 29 7f AND #&7f &28f7 aa TAX &28f8 a5 c2 LDA &c2 ; keys_pressed_bitmap &28fa 29 01 AND #&01 ; KEY_UP &28fc d0 1f BNE &291d ; is_jumping_or_moving_up ; not_jumping &28fe 20 be 2a JSR &2abe ; check_if_player_is_on_ground &2901 d0 5d BNE &2960 ; consider_falling ; consider_crouching_or_moving_down &2903 a5 c2 LDA &c2 ; keys_pressed_bitmap &2905 29 02 AND #&02 ; KEY_DOWN &2907 d0 29 BNE &2932 ; is_crouching_or_moving_down &2909 e0 09 CPX #&09 ; FRAME_PREJUMP &290b d0 31 BNE &293e ; skip_vertical_movement ; start_jump &290d a5 7c LDA &7c ; x_delta &290f 85 83 STA &83 ; player_jump_direction &2911 a9 30 LDA #&30 # Play sound for jumping &2913 20 1b 30 JSR &301b ; play_sound &2916 a9 06 LDA #&06 ; set_player_y_velocity &2918 85 82 STA &82 ; player_y_velocity ; to_consider_falling &291a 4c 60 29 JMP &2960 ; consider_falling ; is_jumping_or_moving_up &291d ac 1e 1a LDY &1a1e ; movers_type_and_colour &2920 f0 14 BEQ &2936 ; prepare_for_jump &2922 ad a2 1a LDA &1aa2 ; movers_y &2925 c9 a4 CMP #&a4 # Player can't move above top of screen &2927 b0 37 BCS &2960 ; consider_falling &2929 b9 07 1c LDA &1c07,Y ; player_helicopter_types_vertical_speed - 5 &292c a6 98 LDX &98 ; helicopter_fuel_high &292e 10 e8 BPL &2918 ; set_player_y_velocity &2930 30 2e BMI &2960 ; consider_falling # Always branches ; is_crouching_or_moving_down &2932 a9 0d LDA #&0d ; FRAME_CROUCHING &2934 d0 02 BNE &2938 ; set_player_frame # Always branches ; prepare_for_jump &2936 a9 09 LDA #&09 ; FRAME_PREJUMP ; set_player_frame &2938 85 81 STA &81 ; frame &293a e4 81 CPX &81 ; frame &293c f0 a6 BEQ &28e4 ; leave ; skip_vertical_movement &293e a5 81 LDA &81 ; frame &2940 30 1e BMI &2960 ; consider_falling # Negative if player moving left or right &2942 ad 1e 1a LDA &1a1e ; movers_type_and_colour &2945 f0 05 BEQ &294c ; not_helicopter ; is_helicopter &2947 20 5e 26 JSR &265e ; animate_mover &294a d0 07 BNE &2953 ; replot_player # Always branches ; not_helicopter &294c a5 7b LDA &7b ; flip &294e 05 81 ORA &81 ; frame &2950 8d 3f 1a STA &1a3f ; movers_frame_and_flip ; replot_player &2953 a0 00 LDY #&00 ; MOVER_PLAYER ; wait_to_replot_player &2955 20 d6 2f JSR &2fd6 ; check_if_raster_is_in_mover # Returns carry set if raster is in mover &2958 b0 fb BCS &2955 ; wait_to_replot_player &295a 20 67 2a JSR &2a67 ; unbuffer_player_getting_addresses &295d 4c de 21 JMP &21de ; plot_player ; consider_falling &2960 a5 82 LDA &82 ; player_y_velocity &2962 85 7d STA &7d ; y_delta &2964 a5 84 LDA &84 ; player_helicopter # Zero if player not in helicopter &2966 d0 0a BNE &2972 ; is_descending_helicopter &2968 20 be 2a JSR &2abe ; check_if_player_is_on_ground &296b f0 18 BEQ &2985 ; skip_setting_x_delta &296d a5 83 LDA &83 ; player_jump_direction &296f 4c 83 29 JMP &2983 ; set_x_delta ; is_descending_helicopter &2972 a5 98 LDA &98 ; helicopter_fuel_high &2974 30 0b BMI &2981 ; suppress_horizontal_movement &2976 c6 99 DEC &99 ; helicopter_fuel_low &2978 d0 02 BNE &297c ; skip_underflow &297a c6 98 DEC &98 ; helicopter_fuel_high ; skip_underflow &297c 20 be 2a JSR &2abe ; check_if_player_is_on_ground &297f d0 04 BNE &2985 ; skip_setting_x_delta ; suppress_horizontal_movement &2981 a5 7b LDA &7b ; flip ; set_x_delta &2983 85 7c STA &7c ; x_delta ; skip_setting_x_delta &2985 a6 7c LDX &7c ; x_delta &2987 e0 81 CPX #&81 &2989 d0 0b BNE &2996 ; not_at_left_edge_of_world &298b a5 b2 LDA &b2 ; viewport_left_low &298d d0 07 BNE &2996 ; not_at_left_edge_of_world &298f a5 ba LDA &ba ; viewport_left_high &2991 d0 03 BNE &2996 ; not_at_left_edge_of_world &2993 ca DEX ; &80 &2994 86 7c STX &7c ; x_delta # Set to &80 to stop player moving left of edge ; not_at_left_edge_of_world &2996 20 3b 2a JSR &2a3b ; get_player_screen_and_buffer_addresses &2999 20 6c 27 JSR &276c ; move_mover &299c ad 1e 1a LDA &1a1e ; movers_type_and_colour &299f d0 18 BNE &29b9 ; skip_animating_player &29a1 20 be 2a JSR &2abe ; check_if_player_is_on_ground &29a4 d0 08 BNE &29ae ; use_jumping_frame &29a6 a5 82 LDA &82 ; player_y_velocity &29a8 f0 0f BEQ &29b9 ; skip_animating_player &29aa a9 0b LDA #&0b ; FRAME_LANDING &29ac d0 02 BNE &29b0 ; set_frame # Always branches ; use_jumping_frame &29ae a9 0a LDA #&0a ; FRAME_JUMPING ; set_frame &29b0 85 79 STA &79 ; new_frame &29b2 a5 7b LDA &7b ; flip &29b4 05 79 ORA &79 ; new_frame &29b6 8d 3f 1a STA &1a3f ; movers_frame_and_flip ; skip_animating_player &29b9 a5 81 LDA &81 ; frame # Negative if moving left or right &29bb 10 15 BPL &29d2 ; not_scrolling &29bd a5 7c LDA &7c ; x_delta &29bf f0 11 BEQ &29d2 ; not_scrolling &29c1 20 38 25 JSR &2538 ; wait_for_vsync &29c4 20 6a 2a JSR &2a6a ; unbuffer_player &29c7 20 60 2a JSR &2a60 ; buffer_player &29ca 20 f6 1e JSR &1ef6 ; update_screen &29cd 20 f8 32 JSR &32f8 ; plot_lives # Leaves with negative &29d0 30 0d BMI &29df ; skip_rebuffering_player # Always branches ; not_scrolling &29d2 a0 00 LDY #&00 ; MOVER_PLAYER ; wait_to_unplot_player &29d4 20 d6 2f JSR &2fd6 ; check_if_raster_is_in_mover # Returns carry set if raster is in mover &29d7 b0 f9 BCS &29d2 ; wait_to_unplot_player &29d9 20 6a 2a JSR &2a6a ; unbuffer_player &29dc 20 60 2a JSR &2a60 ; buffer_player ; skip_rebuffering_player &29df a4 8d LDY &8d ; hostile_mover # Positive if player touching hostile mover &29e1 30 18 BMI &29fb ; skip_killing_player &29e3 20 eb 2b JSR &2beb ; kill_mover &29e6 a5 91 LDA &91 ; dying_mover_type &29e8 c9 0d CMP #&0d ; MOVER_TYPE_SKELETON &29ea f0 0f BEQ &29fb ; skip_killing_player &29ec ad 1e 1a LDA &1a1e ; movers_type_and_colour &29ef c9 0d CMP #&0d ; MOVER_TYPE_SKELETON &29f1 f0 08 BEQ &29fb ; skip_killing_player &29f3 a0 00 LDY #&00 ; MOVER_PLAYER &29f5 20 13 2c JSR &2c13 ; kill_mover_Y &29f8 4c fe 29 JMP &29fe ; skip_plotting_player ; skip_killing_player &29fb 20 de 21 JSR &21de ; plot_player ; skip_plotting_player &29fe 20 be 2a JSR &2abe ; check_if_player_is_on_ground &2a01 d0 06 BNE &2a09 ; not_on_ground &2a03 a6 82 LDX &82 ; player_y_velocity &2a05 d0 2a BNE &2a31 ; end_jump &2a07 f0 31 BEQ &2a3a ; leave # Always branches ; not_on_ground &2a09 a6 82 LDX &82 ; player_y_velocity &2a0b d0 02 BNE &2a0f ; not_starting_to_fall &2a0d a2 80 LDX #&80 # Set player moving down ; not_starting_to_fall &2a0f 30 05 BMI &2a16 ; is_falling &2a11 ca DEX &2a12 d0 1a BNE &2a2e ; set_player_y_velocity &2a14 a2 7f LDX #&7f ; is_falling &2a16 ad a2 1a LDA &1aa2 ; movers_y &2a19 38 SEC &2a1a e9 18 SBC #&18 &2a1c c5 7d CMP &7d ; y_delta &2a1e 90 0b BCC &2a2b ; set_player_falling_velocity &2a20 f0 09 BEQ &2a2b ; set_player_falling_velocity &2a22 e8 INX &2a23 e0 86 CPX #&86 &2a25 90 07 BCC &2a2e ; set_player_y_velocity &2a27 a2 86 LDX #&86 # Maximum falling speed &2a29 30 03 BMI &2a2e ; set_player_y_velocity # Always branches ; set_player_falling_velocity &2a2b 09 80 ORA #&80 &2a2d aa TAX ; set_player_y_velocity &2a2e 86 82 STX &82 ; player_y_velocity &2a30 60 RTS ; end_jump &2a31 a9 00 LDA #&00 &2a33 85 82 STA &82 ; player_y_velocity &2a35 a9 28 LDA #&28 # Play sound for landing &2a37 20 1b 30 JSR &301b ; play_sound ; leave &2a3a 60 RTS ; get_player_screen_and_buffer_addresses &2a3b ad c3 1a LDA &1ac3 ; movers_screen_address_low &2a3e ae e4 1a LDX &1ae4 ; movers_screen_address_high &2a41 85 8b STA &8b ; player_screen_address_low &2a43 86 8c STX &8c ; player_screen_address_high &2a45 a6 01 LDX &01 ; screen_start_address_high &2a47 a5 00 LDA &00 ; screen_start_address_low &2a49 a0 08 LDY #&08 ; &3e88 # Use invisible area of screen as buffer for player &2a4b 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &2a4e 86 8a STX &8a ; buffer_address_high &2a50 85 89 STA &89 ; buffer_address_low &2a52 60 RTS ; set_buffering_or_unbuffering &2a53 a0 03 LDY #&03 ; set_buffering_or_unbuffering_loop &2a55 bd c4 2a LDA &2ac4,X ; buffer_or_unbuffer_code &2a58 99 89 2a STA &2a89,Y ; buffer_or_unbuffer_player_column_loop &2a5b ca DEX &2a5c 88 DEY &2a5d 10 f6 BPL &2a55 ; set_buffering_or_unbuffering_loop &2a5f 60 RTS ; buffer_player &2a60 20 3b 2a JSR &2a3b ; get_player_screen_and_buffer_addresses &2a63 a2 07 LDX #&07 # Use buffering code &2a65 d0 05 BNE &2a6c ; buffer_or_unbuffer_player # Always branches ; unbuffer_player_getting_addresses &2a67 20 3b 2a JSR &2a3b ; get_player_screen_and_buffer_addresses ; unbuffer_player &2a6a a2 03 LDX #&03 # Use unbuffering code ; buffer_or_unbuffer_player &2a6c 20 53 2a JSR &2a53 ; set_buffering_or_unbuffering &2a6f ae 1e 1a LDX &1a1e ; movers_type_and_colour &2a72 bd 89 1b LDA &1b89,X ; mover_types_height_table &2a75 85 79 STA &79 ; rows_remaining ; buffer_or_unbuffer_player_row_loop &2a77 a4 8b LDY &8b ; player_screen_address_low &2a79 a5 8c LDA &8c ; player_screen_address_high &2a7b 85 cf STA &cf ; screen_address_high &2a7d ae 1e 1a LDX &1a1e ; movers_type_and_colour &2a80 bd 75 1b LDA &1b75,X ; mover_types_width_table &2a83 85 cc STA &cc ; columns_remaining &2a85 a2 00 LDX #&00 &2a87 86 ce STX &ce ; screen_address_low ; buffer_or_unbuffer_player_column_loop &2a89 a1 89 LDA (&89,X) ; buffer_address # if unbuffering # also LDA (&ce),Y ; screen_address # if buffering &2a8b 91 ce STA (&ce),Y ; screen_address # if unbuffering # also STA (&89,X) ; buffer_address # if buffering &2a8d 98 TYA &2a8e 18 CLC &2a8f 69 08 ADC #&08 &2a91 a8 TAY &2a92 90 08 BCC &2a9c ; skip_page_screen &2a94 e6 cf INC &cf ; screen_address_high &2a96 10 04 BPL &2a9c ; skip_wraparound_screen &2a98 a9 40 LDA #&40 &2a9a 85 cf STA &cf ; screen_address_high ; skip_wraparound_screen ; skip_page_screen &2a9c e6 89 INC &89 ; buffer_address_low &2a9e d0 08 BNE &2aa8 ; skip_page_buffer &2aa0 e6 8a INC &8a ; buffer_address_high &2aa2 10 04 BPL &2aa8 ; skip_wraparound_buffer &2aa4 a9 40 LDA #&40 &2aa6 85 8a STA &8a ; buffer_address_high ; skip_wraparound_buffer ; skip_page_buffer &2aa8 c6 cc DEC &cc ; columns_remaining &2aaa 10 dd BPL &2a89 ; buffer_or_unbuffer_player_column_loop &2aac a5 8b LDA &8b ; player_screen_address_low &2aae a6 8c LDX &8c ; player_screen_address_high &2ab0 a0 01 LDY #&01 &2ab2 20 e5 20 JSR &20e5 ; subtract_Y_rows_from_screen_address_in_AX &2ab5 85 8b STA &8b ; player_screen_address_low &2ab7 86 8c STX &8c ; player_screen_address_high &2ab9 c6 79 DEC &79 ; rows_remaining &2abb 10 ba BPL &2a77 ; buffer_or_unbuffer_player_row_loop &2abd 60 RTS ; check_if_player_is_on_ground &2abe ad a2 1a LDA &1aa2 ; movers_y &2ac1 c9 18 CMP #&18 &2ac3 60 RTS ; buffer_or_unbuffer_code # Copied, not executed &2ac4 a1 89 LDA (&89,X) ; buffer_address # &03 : unbuffer (copy from buffer to screen) &2ac6 91 ce STA (&ce),Y ; screen_address &2ac8 b1 ce LDA (&ce),Y ; screen_address # &07 : buffer (copy from screen to buffer) &2aca 81 89 STA (&89,X) ; buffer_address ; update_movers &2acc ad 4b fe LDA &fe4b ; System VIA auxiliary control register &2acf 29 df AND #&df # Set System VIA timer 2 to one-shot mode &2ad1 8d 4b fe STA &fe4b ; System VIA auxiliary control register &2ad4 a9 20 LDA #&20 # Enable System VIA timer 2 interrupts &2ad6 8d 4e fe STA &fe4e ; System VIA interrupt enable register &2ad9 a9 ff LDA #&ff &2adb 8d 48 fe STA &fe48 ; System VIA timer 2 counter LSB &2ade 8d 49 fe STA &fe49 ; System VIA timer 2 counter MSB &2ae1 a4 c0 LDY &c0 ; movers_to_update_base &2ae3 a2 02 LDX #&02 &2ae5 86 c1 STX &c1 ; movers_to_update_count ; populate_movers_to_update_loop &2ae7 b9 05 1b LDA &1b05,Y ; movers_raster_y &2aea 9d 37 2b STA &2b37,X ; movers_to_update_raster_y &2aed 98 TYA &2aee 9d 34 2b STA &2b34,X ; movers_to_update &2af1 c8 INY &2af2 c0 0a CPY #&0a ; MOVER_LAST_ENEMY_SOLDIER + 1 &2af4 90 02 BCC &2af8 ; skip_wraparound &2af6 a0 01 LDY #&01 ; MOVER_FIRST_ENEMY ; skip_wraparound &2af8 ca DEX &2af9 10 ec BPL &2ae7 ; populate_movers_to_update_loop &2afb 84 c0 STY &c0 ; movers_to_update_base ; update_movers_loop &2afd a2 02 LDX #&02 ; find_topmost_remaining_mover_loop &2aff a0 02 LDY #&02 ; find_topmost_remaining_mover_inner_loop &2b01 b9 37 2b LDA &2b37,Y ; movers_to_update_raster_y &2b04 dd 37 2b CMP &2b37,X ; movers_to_update_raster_y &2b07 b0 03 BCS &2b0c ; not_topmost_mover &2b09 ca DEX &2b0a 10 f3 BPL &2aff ; find_topmost_remaining_mover_loop # Always branches ; not_topmost_mover &2b0c 88 DEY &2b0d 10 f2 BPL &2b01 ; find_topmost_remaining_mover_inner_loop &2b0f a9 ff LDA #&ff &2b11 9d 37 2b STA &2b37,X ; movers_to_update_raster_y # Set to maximum value to prevent being found again &2b14 bc 34 2b LDY &2b34,X ; movers_to_update &2b17 84 03 STY &03 ; mover_to_update &2b19 20 ee 31 JSR &31ee ; update_mover # Update mover &2b1c c6 c1 DEC &c1 ; movers_to_update_count &2b1e 10 dd BPL &2afd ; update_movers_loop &2b20 a5 80 LDA &80 ; helicopter_to_update &2b22 a8 TAY &2b23 49 01 EOR #&01 # Update enemy helicopters alternately &2b25 85 80 STA &80 ; helicopter_to_update &2b27 84 03 STY &03 ; mover_to_update &2b29 20 29 30 JSR &3029 ; update_enemy_helicopter ; wait_for_timer &2b2c ad 49 fe LDA &fe49 ; System VIA timer 2 counter MSB &2b2f c9 70 CMP #&70 &2b31 b0 f9 BCS &2b2c ; wait_for_timer # Wait for raster to be in sky &2b33 60 RTS ; movers_to_update &2b34 00 00 00 ; movers_to_update_raster_y &2b37 00 00 00 ; get_mover_X_type_and_height &2b3a bd 1e 1a LDA &1a1e,X ; movers_type_and_colour &2b3d 29 7f AND #&7f &2b3f a8 TAY &2b40 bd 3f 1a LDA &1a3f,X ; movers_frame_and_flip &2b43 29 7f AND #&7f &2b45 c9 0d CMP #&0d ; MOVER_TYPE_SKELETON &2b47 d0 04 BNE &2b4d ; use_height_table &2b49 a9 11 LDA #&11 &2b4b d0 03 BNE &2b50 ; leave # Always branches ; use_height_table &2b4d b9 89 1b LDA &1b89,Y ; mover_types_height_table ; leave &2b50 60 RTS ; check_for_mover_Y_collision_with_player # Called with X = 0 (MOVER_PLAYER) &2b51 20 3c 23 JSR &233c ; get_mover_Y_x_and_y &2b54 a8 TAY &2b55 a5 f8 LDA &f8 ; mover_x_low &2b57 d0 02 BNE &2b5b ; set_first_mover # Always branches ; check_for_mover_collision_with_movers &2b59 a2 17 LDX #&17 ; MOVER_LAST_PROJECTILE ; set_first_mover &2b5b 86 b6 STX &b6 ; first_mover &2b5d a2 ff LDX #&ff ; MOVER_PLAYER - 1 &2b5f 86 b7 STX &b7 ; last_mover &2b61 a6 03 LDX &03 ; mover_to_update &2b63 85 f8 STA &f8 ; mover_x_low &2b65 84 c5 STY &c5 ; mover_x_high &2b67 20 78 2b JSR &2b78 ; calculate_mover_x_max_and_y_max &2b6a a6 b6 LDX &b6 ; first_mover ; check_for_mover_collision_with_range_of_movers ; check_for_mover_collision_with_range_of_movers_loop &2b6c 20 9b 2b JSR &2b9b ; check_for_mover_collision_with_mover_X &2b6f b0 06 BCS &2b77 ; leave # Leave with carry set to indicate collision, X = mover &2b71 ca DEX &2b72 e4 b7 CPX &b7 ; last_mover &2b74 d0 f6 BNE &2b6c ; check_for_mover_collision_with_range_of_movers_loop &2b76 18 CLC # Leave with carry clear to indicate no collision ; leave &2b77 60 RTS ; calculate_mover_x_max_and_y_max &2b78 a5 c5 LDA &c5 ; mover_x_high &2b7a 85 c6 STA &c6 ; mover_x_max_high &2b7c 20 3a 2b JSR &2b3a ; get_mover_X_type_and_height &2b7f 18 CLC &2b80 65 f9 ADC &f9 ; mover_y &2b82 85 c9 STA &c9 ; mover_y_max &2b84 b9 75 1b LDA &1b75,Y ; mover_types_width_table &2b87 18 CLC &2b88 65 f8 ADC &f8 ; mover_x_low &2b8a 90 02 BCC &2b8e ; skip_overflow &2b8c e6 c6 INC &c6 ; mover_x_max_high ; skip_overflow &2b8e 85 c7 STA &c7 ; mover_x_max_low &2b90 60 RTS ; check_for_player_collision_with_mover_Y &2b91 20 3c 23 JSR &233c ; get_mover_Y_x_and_y &2b94 20 78 2b JSR &2b78 ; calculate_mover_x_max_and_y_max &2b97 a2 00 LDX #&00 ; MOVER_PLAYER &2b99 f0 04 BEQ &2b9f ; check_for_collision_with_mover ; check_for_mover_collision_with_mover_X &2b9b e4 03 CPX &03 ; mover_to_update &2b9d f0 3c BEQ &2bdb ; leave_with_carry_clear ; check_for_collision_with_mover &2b9f 20 3a 2b JSR &2b3a ; get_mover_X_type_and_height &2ba2 85 78 STA &78 ; height &2ba4 b9 75 1b LDA &1b75,Y ; mover_types_width_table &2ba7 85 7a STA &7a ; width &2ba9 bd 81 1a LDA &1a81,X ; movers_x_high &2bac a8 TAY &2bad c5 c6 CMP &c6 ; mover_x_max_high &2baf 90 09 BCC &2bba ; check_x_high &2bb1 d0 28 BNE &2bdb ; leave_with_carry_clear &2bb3 a5 c7 LDA &c7 ; mover_x_max_low &2bb5 dd 60 1a CMP &1a60,X ; movers_x_low &2bb8 90 21 BCC &2bdb ; leave_with_carry_clear ; check_x_high &2bba bd 60 1a LDA &1a60,X ; movers_x_low &2bbd 18 CLC &2bbe 65 7a ADC &7a ; width &2bc0 90 01 BCC &2bc3 ; skip_overflow &2bc2 c8 INY ; skip_overflow &2bc3 c4 c5 CPY &c5 ; mover_x_high &2bc5 90 14 BCC &2bdb ; leave_with_carry_clear &2bc7 d0 04 BNE &2bcd ; skip_low_check &2bc9 c5 f8 CMP &f8 ; mover_x_low &2bcb 90 0e BCC &2bdb ; leave_with_carry_clear ; skip_low_check &2bcd bd a2 1a LDA &1aa2,X ; movers_y &2bd0 c5 c9 CMP &c9 ; mover_y_max &2bd2 b0 07 BCS &2bdb ; leave_with_carry_clear &2bd4 65 78 ADC &78 ; height &2bd6 c5 f9 CMP &f9 ; mover_y &2bd8 90 01 BCC &2bdb ; leave_with_carry_clear &2bda 60 RTS # Leave with carry set to indicate collision ; leave_with_carry_clear &2bdb 18 CLC # Leave with carry clear to indicate no collision &2bdc 60 RTS ; move_mover_routine_addresses_high_table # &00 : &274f = move_mover_up_and_right &2bdd 27 27 27 27 # &01 : &2755 = move_mover_down_and_right ; move_mover_routine_addresses_low_table # &02 : &275b = move_mover_up_and_left &2be1 4f 55 5b 61 # &03 : &2761 = move_mover_down_and_left ; set_dying_mover_type &2be5 20 33 31 JSR &3133 ; get_mover_Y_type # Returns A = mover type &2be8 85 91 STA &91 ; dying_mover_type &2bea 60 RTS ; kill_mover # Called with Y = hostile mover &2beb 20 e5 2b JSR &2be5 ; set_dying_mover_type # Returns A = mover type &2bee 84 87 STY &87 ; dying_mover &2bf0 c9 13 CMP #&13 ; MOVER_TYPE_MINE &2bf2 f0 11 BEQ &2c05 ; not_player &2bf4 c9 0c CMP #&0c ; MOVER_TYPE_SAM &2bf6 b0 e3 BCS &2bdb ; leave_with_carry_clear &2bf8 c0 00 CPY #&00 ; MOVER_PLAYER &2bfa d0 09 BNE &2c05 ; not_player &2bfc a5 8f LDA &8f ; player_helicopter_explosion # Non-zero if player in exploding helicopter &2bfe d0 db BNE &2bdb ; leave_with_carry_clear &2c00 20 67 2a JSR &2a67 ; unbuffer_player_getting_addresses # Returns negative &2c03 30 0c BMI &2c11 ; skip_unplotting_mover # Always branches ; not_player &2c05 a6 87 LDX &87 ; dying_mover &2c07 20 91 2b JSR &2b91 ; check_for_player_collision_with_mover_Y # Returns carry set if collision &2c0a a4 87 LDY &87 ; dying_mover &2c0c b0 cd BCS &2bdb ; leave_with_carry_clear # Skip unplotting if player was cause of collision &2c0e 20 e0 21 JSR &21e0 ; plot_mover ; skip_unplotting_mover &2c11 a4 87 LDY &87 ; dying_mover ; kill_mover_Y &2c13 84 87 STY &87 ; dying_mover &2c15 20 e5 2b JSR &2be5 ; set_dying_mover_type &2c18 a9 00 LDA #&00 # Play sound for explosion &2c1a 20 1b 30 JSR &301b ; play_sound &2c1d a6 91 LDX &91 ; dying_mover_type &2c1f a9 10 LDA #&10 # Play sound for exploding soldier &2c21 e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &2c23 90 02 BCC &2c27 ; play_sound_for_dying_mover &2c25 a9 08 LDA #&08 # Play sound for exploding helicopter ; play_sound_for_dying_mover &2c27 20 1b 30 JSR &301b ; play_sound &2c2a a4 87 LDY &87 ; dying_mover &2c2c d0 0f BNE &2c3d ; not_player ; is_player &2c2e a5 84 LDA &84 ; player_helicopter # Zero if player not in helicopter &2c30 d0 3a BNE &2c6c ; kill_player_helicopter ; kill_player &2c32 c6 95 DEC &95 ; lives &2c34 08 PHP ; out of lives &2c35 20 f8 32 JSR &32f8 ; plot_lives &2c38 a4 87 LDY &87 ; dying_mover &2c3a 28 PLP ; out of lives &2c3b d0 2c BNE &2c69 ; to_plot_mover # Don't turn player into skeleton until last life ; not_player &2c3d a6 91 LDX &91 ; dying_mover_type &2c3f a9 0d LDA #&0d ; MOVER_TYPE_SKELETON &2c41 e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &2c43 a2 03 LDX #&03 &2c45 90 03 BCC &2c4a ; set_dying_mover_type_and_frame &2c47 a9 0e LDA #&0e ; MOVER_TYPE_EXPLOSION &2c49 e8 INX ; set_dying_mover_type_and_frame &2c4a 99 1e 1a STA &1a1e,Y ; movers_type_and_colour &2c4d 8a TXA &2c4e 85 81 STA &81 ; frame &2c50 b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &2c53 29 80 AND #&80 &2c55 49 80 EOR #&80 &2c57 05 81 ORA &81 ; frame &2c59 99 3f 1a STA &1a3f,Y ; movers_frame_and_flip &2c5c 84 92 STY &92 ; dying_mover &2c5e a6 92 LDX &92 ; dying_mover &2c60 20 91 2b JSR &2b91 ; check_for_player_collision_with_mover_Y # Returns carry set if collision &2c63 a4 92 LDY &92 ; dying_mover &2c65 f0 02 BEQ &2c69 ; to_plot_mover &2c67 b0 31 BCS &2c9a ; remove_mover # Skip unplotting if player was cause of collision ; to_plot_mover &2c69 4c e0 21 JMP &21e0 ; plot_mover ; kill_player_helicopter &2c6c a9 04 LDA #&04 &2c6e 8d 3f 1a STA &1a3f ; movers_frame_and_flip &2c71 20 90 2c JSR &2c90 ; plot_player_bullet_and_grenade # Unplot player bullet and grenade &2c74 a0 11 LDY #&11 ; MOVER_PLAYER_BULLET &2c76 20 e4 27 JSR &27e4 ; use_player_position_for_mover_Y &2c79 ad c3 1a LDA &1ac3 ; movers_screen_address_low &2c7c a0 06 LDY #&06 ; &0030 &2c7e 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &2c81 a0 0c LDY #&0c ; MOVER_PLAYER_GRENADE # Use slots for player helicopter explosions &2c83 20 ea 27 JSR &27ea ; use_player_position_for_mover_Y_with_screen_address_from_AX &2c86 a0 0e LDY #&0e ; MOVER_TYPE_EXPLOSION &2c88 8c 2a 1a STY &1a2a ; movers_type_and_colour + &c (MOVER_PLAYER_GRENADE) &2c8b 8c 2f 1a STY &1a2f ; movers_type_and_colour + &11 (MOVER_PLAYER_BULLET) &2c8e 84 8f STY &8f ; player_helicopter_explosion # Set to non-zero to indicate player helicopter exploding ; plot_player_bullet_and_grenade &2c90 a0 11 LDY #&11 ; MOVER_PLAYER_BULLET &2c92 20 e0 21 JSR &21e0 ; plot_mover &2c95 a0 0c LDY #&0c ; MOVER_PLAYER_GRENADE &2c97 4c e0 21 JMP &21e0 ; plot_mover ; remove_mover &2c9a a9 ff LDA #&ff &2c9c 99 81 1a STA &1a81,Y ; movers_x_high # Set to negative to indicate no mover in slot &2c9f 60 RTS ; update_projectiles &2ca0 a0 17 LDY #&17 ; MOVER_LAST_PROJECTILE ; update_projectiles_loop &2ca2 84 03 STY &03 ; mover_to_update &2ca4 b9 81 1a LDA &1a81,Y ; movers_x_high # Negative if no projectile in slot &2ca7 30 17 BMI &2cc0 ; to_consider_next_projectile &2ca9 b9 1e 1a LDA &1a1e,Y ; movers_type_and_colour &2cac c9 0e CMP #&0e ; MOVER_TYPE_EXPLOSION &2cae d0 13 BNE &2cc3 ; update_projectile ; update_explosion &2cb0 20 e0 21 JSR &21e0 ; plot_mover # Unplot explosion &2cb3 a6 03 LDX &03 ; mover_to_update &2cb5 a4 03 LDY &03 ; mover_to_update &2cb7 de 3f 1a DEC &1a3f,X ; movers_frame_and_flip &2cba 18 CLC &2cbb 10 59 BPL &2d16 ; to_replot_projectile ; remove_projectile &2cbd 20 9a 2c JSR &2c9a ; remove_mover ; to_consider_next_projectile &2cc0 4c 70 2d JMP &2d70 ; consider_next_projectile ; update_projectile &2cc3 b9 26 1b LDA &1b26,Y ; projectiles_y_velocity - &c &2cc6 be 32 1b LDX &1b32,Y ; projectiles_is_rocket - &c # Non-zero if projectile is rocket &2cc9 d0 19 BNE &2ce4 ; is_rocket ; not_rocket &2ccb c0 11 CPY #&11 ; MOVER_PLAYER_BULLET # Bullets aren't affected by gravity &2ccd b0 1e BCS &2ced ; set_y_delta &2ccf aa TAX &2cd0 30 08 BMI &2cda ; increase_downwards_velocity &2cd2 ca DEX # Grenades and bombs fall &2cd3 8a TXA &2cd4 d0 17 BNE &2ced ; set_y_delta &2cd6 a9 80 LDA #&80 &2cd8 30 13 BMI &2ced ; set_y_delta ; increase_downwards_velocity &2cda e8 INX &2cdb 8a TXA &2cdc c9 86 CMP #&86 &2cde 90 0d BCC &2ced ; set_y_delta &2ce0 a9 86 LDA #&86 &2ce2 30 09 BMI &2ced ; set_y_delta # Always branches ; is_rocket &2ce4 aa TAX &2ce5 e8 INX # Rockets accelerate upwards &2ce6 e0 0a CPX #&0a &2ce8 90 02 BCC &2cec ; skip_ceiling &2cea a2 0a LDX #&0a ; skip_ceiling &2cec 8a TXA ; set_y_delta &2ced 85 7d STA &7d ; y_delta &2cef 99 26 1b STA &1b26,Y ; projectiles_y_velocity - &c &2cf2 b9 1a 1b LDA &1b1a,Y ; projectiles_x_velocity - &c &2cf5 85 7c STA &7c ; x_delta &2cf7 20 67 27 JSR &2767 ; unplot_and_move_mover # Move projectile &2cfa a6 03 LDX &03 ; mover_to_update &2cfc a4 8d LDY &8d ; hostile_mover # Positive if projectile hit hostile mover &2cfe 10 1f BPL &2d1f ; projectile_hit_mover &2d00 bd a2 1a LDA &1aa2,X ; movers_y &2d03 c9 19 CMP #&19 &2d05 90 36 BCC &2d3d ; explode_projectile # Explode grenades and bombs on ground &2d07 bc 1e 1a LDY &1a1e,X ; movers_type_and_colour &2d0a c0 12 CPY #&12 ; MOVERS_TYPE_ROCKET &2d0c d0 04 BNE &2d12 ; not_rocket &2d0e c9 ae CMP #&ae &2d10 b0 2b BCS &2d3d ; explode_projectile # Explode rocket at top of screen ; not_rocket &2d12 a4 03 LDY &03 ; mover_to_update &2d14 c0 11 CPY #&11 ; MOVER_FIRST_BULLET ; to_replot_projectile &2d16 90 55 BCC &2d6d ; replot_projectile # Grenades have no ttl, but bullets do &2d18 de 3e 1b DEC &1b3e,X ; projectiles_ttl - &c &2d1b f0 20 BEQ &2d3d ; explode_projectile # Explode projectile at end of life &2d1d d0 4e BNE &2d6d ; replot_projectile # Always branches ; projectile_hit_mover &2d1f e0 11 CPX #&11 ; MOVER_PLAYER_BULLET &2d21 f0 04 BEQ &2d27 ; is_player_projectile &2d23 e0 0c CPX #&0c ; MOVER_PLAYER_GRENADE &2d25 d0 03 BNE &2d2a ; not_player_projectile ; is_player_projectile &2d27 20 95 33 JSR &3395 ; increase_score_for_killing_enemy ; not_player_projectile &2d2a a4 8d LDY &8d ; projectile_hit_mover &2d2c f0 09 BEQ &2d37 ; projectile_hit_player &2d2e 20 91 2b JSR &2b91 ; check_for_player_collision_with_mover_Y # Returns carry set if collision &2d31 a4 8d LDY &8d ; hostile_mover &2d33 90 02 BCC &2d37 ; explode_mover_Y &2d35 a0 00 LDY #&00 ; MOVER_PLAYER ; projectile_hit_player &2d37 20 eb 2b JSR &2beb ; kill_mover &2d3a 4c 4f 2d JMP &2d4f ; replace_projectile_with_explosion ; explode_projectile &2d3d a4 03 LDY &03 ; mover_to_update ; explode_mover_Y &2d3f a9 38 LDA #&38 # Play sound for exploding bullet &2d41 c0 11 CPY #&11 ; MOVER_FIRST_BULLET &2d43 b0 07 BCS &2d4c ; play_sound_for_exploding_projectile &2d45 a9 00 LDA #&00 # Play sound for exploding grenade &2d47 20 1b 30 JSR &301b ; play_sound &2d4a a9 08 LDA #&08 # Play sound for exploding grenade ; play_sound_for_exploding_projectile &2d4c 20 1b 30 JSR &301b ; play_sound ; replace_projectile_with_explosion &2d4f a4 03 LDY &03 ; mover_to_update &2d51 a9 04 LDA #&04 # Big explosion &2d53 c0 11 CPY #&11 ; MOVER_FIRST_BULLET &2d55 90 02 BCC &2d59 ; set_frame_and_flip &2d57 a9 00 LDA #&00 # Small explosion ; set_frame_and_flip &2d59 99 3f 1a STA &1a3f,Y ; movers_frame_and_flip &2d5c a9 0e LDA #&0e ; MOVER_TYPE_EXPLOSION &2d5e 99 1e 1a STA &1a1e,Y ; movers_type_and_colour &2d61 a2 00 LDX #&00 ; MOVER_PLAYER &2d63 20 51 2b JSR &2b51 ; check_for_mover_Y_collision_with_player # Returns carry set if collision &2d66 a4 03 LDY &03 ; mover_to_update &2d68 90 03 BCC &2d6d ; replot_projectile &2d6a 4c bd 2c JMP &2cbd ; remove_projectile ; replot_projectile &2d6d 20 e0 21 JSR &21e0 ; plot_mover # Plot projectile or explosion ; consider_next_projectile &2d70 a4 03 LDY &03 ; mover_to_update &2d72 88 DEY &2d73 c0 0c CPY #&0c ; MOVER_FIRST_PROJECTILE &2d75 90 03 BCC &2d7a ; leave &2d77 4c a2 2c JMP &2ca2 ; update_projectiles_loop ; leave &2d7a 60 RTS ; calculate_mover_x_max_from_offset_getting_frame_and_flip &2d7b 20 db 31 JSR &31db ; get_mover_frame_and_flip ; calculate_mover_x_max_from_offset &2d7e a6 c5 LDX &c5 ; mover_x_high &2d80 86 c6 STX &c6 ; mover_x_max_high &2d82 a5 f8 LDA &f8 ; mover_x_low &2d84 a4 b7 LDY &b7 ; frame_and_flip &2d86 30 0b BMI &2d93 ; is_flipped ; not_flipped &2d88 18 CLC &2d89 65 81 ADC &81 ; mover_x_offset &2d8b 90 01 BCC &2d8e ; skip_overflow &2d8d e8 INX ; skip_overflow &2d8e 85 c7 STA &c7 ; mover_x_max_low # Leave with mover_x_max = mover_x + x_offset, &2d90 86 c6 STX &c6 ; mover_x_max_high # mover_x = mover_x if unflipped &2d92 60 RTS ; is_flipped &2d93 85 c7 STA &c7 ; mover_x_max_low # Leave with mover_x_max = mover_x, &2d95 38 SEC # mover_x = mover_x - x_offset if flipped &2d96 e5 81 SBC &81 ; mover_x_offset &2d98 b0 01 BCS &2d9b ; set_mover_x &2d9a ca DEX ; set_mover_x &2d9b 86 c5 STX &c5 ; mover_x_high &2d9d 85 f8 STA &f8 ; mover_x_low &2d9f 60 RTS ; check_for_collision_with_friends &2da0 a2 0b LDX #&0b ; MOVER_LAST_ENEMY_HELICOPTER ; check_for_collision_with_non_bullet_movers_loop &2da2 20 9b 2b JSR &2b9b ; check_for_mover_collision_with_mover_X &2da5 90 05 BCC &2dac ; consider_next_mover &2da7 20 b1 2d JSR &2db1 ; check_if_friendly # Returns carry set if friendly &2daa 90 04 BCC &2db0 ; leave # Leave with carry clear to indicate hostile collision ; consider_next_mover &2dac ca DEX &2dad 10 f3 BPL &2da2 ; check_for_collision_with_non_bullet_movers_loop &2daf 38 SEC # Leave with carry set to indicate no hostile collision ; leave &2db0 60 RTS ; check_if_friendly &2db1 a4 03 LDY &03 ; mover_to_update &2db3 bd 1e 1a LDA &1a1e,X ; movers_type_and_colour &2db6 c9 0d CMP #&0d ; MOVER_TYPE_SKELETON # Skeletons are friendly &2db8 f0 06 BEQ &2dc0 ; leave_with_carry_set &2dba 59 1e 1a EOR &1a1e,Y ; movers_type_and_colour # Otherwise check if movers are same colour &2dbd 18 CLC # Leave with carry clear to indicate unfriendly &2dbe 30 f0 BMI &2db0 ; leave ; leave_with_carry_set &2dc0 38 SEC # Leave with carry set to indicate friendly &2dc1 60 RTS ; search_for_target_with_offset &2dc2 85 81 STA &81 ; mover_x_offset &2dc4 20 3a 23 JSR &233a ; get_mover_x_and_y &2dc7 20 eb 23 JSR &23eb ; check_if_mover_Y_is_on_screen # Returns carry set if mover is not on screen &2dca b0 f4 BCS &2dc0 ; leave_with_carry_set # If so, leave with carry set to indicate no target found &2dcc a5 f9 LDA &f9 ; mover_y &2dce 18 CLC &2dcf 69 40 ADC #&40 &2dd1 85 c9 STA &c9 ; mover_y_max ; search_for_target &2dd3 20 7e 2d JSR &2d7e ; calculate_mover_x_max_from_offset &2dd6 a2 ff LDX #&ff &2dd8 86 b6 STX &b6 ; target # Set to negative to indicate no target found by default &2dda e8 INX ; 0 &2ddb 86 89 STX &89 ; friendly_targets_found # Variable is unused in standard version &2ddd 86 8a STX &8a ; unfriendly_targets_found # Variable is unused in standard version &2ddf a2 0b LDX #&0b ; MOVER_LAST_ENEMY_HELICOPTER ; search_for_target_loop &2de1 20 9b 2b JSR &2b9b ; check_for_mover_collision_with_mover_X # Returns carry set if collision, i.e. mover in range &2de4 90 1e BCC &2e04 ; consider_next_enemy &2de6 a4 b6 LDY &b6 ; target &2de8 30 18 BMI &2e02 ; found_target ; check_if_target_is_better &2dea b9 81 1a LDA &1a81,Y ; movers_x_high # Prefer nearer targets &2ded dd 81 1a CMP &1a81,X ; movers_x_high &2df0 d0 06 BNE &2df8 ; skip_low_check &2df2 b9 60 1a LDA &1a60,Y ; movers_x_low &2df5 dd 60 1a CMP &1a60,X ; movers_x_low ; skip_low_check &2df8 a5 b7 LDA &b7 ; frame_and_flip &2dfa 30 04 BMI &2e00 ; is_facing_left ; is_facing_right &2dfc 90 06 BCC &2e04 ; consider_next_enemy &2dfe b0 02 BCS &2e02 ; found_target # Always branches ; is_facing_left &2e00 b0 02 BCS &2e04 ; consider_next_enemy ; found_target &2e02 86 b6 STX &b6 ; target ; consider_next_enemy &2e04 ca DEX &2e05 10 da BPL &2de1 ; search_for_target_loop &2e07 a6 b6 LDX &b6 ; target &2e09 10 a6 BPL &2db1 ; check_if_friendly # Leave with carry clear if unfriendly target found &2e0b 38 SEC # Leave with carry set to indicate no target found &2e0c 60 RTS ; find_free_projectile_slot # Called with A = first slot, X = last slot + 1 &2e0d 85 85 STA &85 ; last_slot ; find_free_projectile_slot_loop &2e0f bd 8d 1a LDA &1a8d,X ; movers_x_high + &c (MOVERS_FIRST_PROJECTILE) &2e12 30 07 BMI &2e1b ; found_free_slot &2e14 e8 INX &2e15 e4 85 CPX &85 ; last_slot &2e17 90 f6 BCC &2e0f ; find_free_projectile_slot_loop &2e19 a2 ff LDX #&ff # Negative to indicate no free slot ; found_free_slot &2e1b 86 86 STX &86 ; projectile_slot &2e1d 20 33 31 JSR &3133 ; get_mover_Y_type # Returns A = mover type &2e20 aa TAX # Leave with A = X = mover type &2e21 60 RTS ; add_mover_bullet &2e22 a4 03 LDY &03 ; mover_to_update &2e24 a9 06 LDA #&06 ; MOVER_FIRST_ENEMY_BULLET - &c &2e26 be 1e 1a LDX &1a1e,Y ; movers_type_and_colour # Negative if enemy &2e29 30 02 BMI &2e2d ; calculate_last_slot &2e2b a9 09 LDA #&09 ; MOVER_FIRST_ALLY_BULLET - &c ; calculate_last_slot &2e2d aa TAX &2e2e 18 CLC &2e2f 69 03 ADC #&03 &2e31 20 0d 2e JSR &2e0d ; find_free_projectile_slot # Returns X = mover type &2e34 a5 86 LDA &86 ; projectile_slot &2e36 30 16 BMI &2e4e ; leave_with_carry_set # Negative if no free slot ; add_bullet &2e38 bc ce 1b LDY &1bce,X ; mover_types_new_bullet_y_offset &2e3b a9 00 LDA #&00 &2e3d 85 78 STA &78 ; y_velocity &2e3f bd f4 1b LDA &1bf4,X ; mover_types_new_bullet_type &2e42 f0 0a BEQ &2e4e ; leave_with_carry_set # Leave if mover can't fire bullets &2e44 20 6a 2e JSR &2e6a ; add_new_projectile &2e47 a6 86 LDX &86 ; projectile_slot &2e49 fe 26 1b INC &1b26,X ; projectiles_x_velocity &2e4c 18 CLC # Leave with carry clear to indicate bullet added &2e4d 60 RTS ; leave_with_carry_set &2e4e 38 SEC # Leave with carry set to indicate couldn't add bullet &2e4f 60 RTS ; add_new_grenade # Also bombs and rockets &2e50 a4 03 LDY &03 ; mover_to_update &2e52 a2 01 LDX #&01 ; MOVER_FIRST_ENEMY_GRENADE - &c &2e54 a9 05 LDA #&05 ; MOVER_LAST_ENEMY_GRENADE - &c + 1 &2e56 20 0d 2e JSR &2e0d ; find_free_projectile_slot # Returns X = mover type &2e59 a4 86 LDY &86 ; projectile_slot &2e5b 30 f1 BMI &2e4e ; leave_with_carry_set # Negative if no free slot ; add_new_grenade_to_slot &2e5d bd e7 1b LDA &1be7,X ; mover_types_new_grenade_bomb_or_rocket_y_velocity &2e60 85 78 STA &78 ; y_velocity &2e62 bc c1 1b LDY &1bc1,X ; mover_types_new_grenade_bomb_or_rocket_y_offset &2e65 bd da 1b LDA &1bda,X ; mover_types_new_grenade_bomb_or_rocket_type &2e68 f0 e4 BEQ &2e4e ; leave_with_carry_set # Leave if mover can't fire grenade ; add_new_projectile &2e6a 84 87 STY &87 ; projectile_y_offset &2e6c a4 86 LDY &86 ; projectile_slot &2e6e 99 2a 1a STA &1a2a,Y ; movers_type_and_colour + &c (MOVERS_FIRST_PROJECTILE) &2e71 86 a1 STX &a1 ; firing_mover_type &2e73 a9 00 LDA #&00 &2e75 e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &2e77 b0 05 BCS &2e7e ; not_soldier &2e79 a4 a0 LDY &a0 ; firing_frame &2e7b b9 72 1c LDA &1c72,Y ; sprites_y_offset ; not_soldier &2e7e a6 86 LDX &86 ; projectile_slot &2e80 a4 03 LDY &03 ; mover_to_update &2e82 18 CLC &2e83 65 87 ADC &87 ; projectile_y_offset &2e85 85 87 STA &87 ; projectile_y_offset &2e87 79 a2 1a ADC &1aa2,Y ; movers_y &2e8a 38 SEC &2e8b e9 0a SBC #&0a &2e8d 9d ae 1a STA &1aae,X ; movers_y + &c (MOVERS_FIRST_PROJECTILE) &2e90 b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &2e93 29 80 AND #&80 &2e95 9d 4b 1a STA &1a4b,X ; movers_frame_and_flip + &c (MOVERS_FIRST_PROJECTILE) &2e98 85 89 STA &89 ; firing_direction &2e9a a2 05 LDX #&05 &2e9c a9 01 LDA #&01 # Set projectiles_is_rocket to non-zero if rocket &2e9e a4 a1 LDY &a1 ; firing_mover_type &2ea0 c0 0c CPY #&0c ; MOVER_TYPE_SAM &2ea2 f0 07 BEQ &2eab ; skip_offset &2ea4 be 75 1b LDX &1b75,Y ; mover_types_width_table &2ea7 e8 INX &2ea8 e8 INX &2ea9 a9 00 LDA #&00 # Set projectiles_is_rocket to zero if not rocket ; skip_offset &2eab a4 86 LDY &86 ; projectile_slot &2ead 99 3e 1b STA &1b3e,Y ; projectiles_is_rocket &2eb0 49 01 EOR #&01 &2eb2 45 89 EOR &89 ; firing_direction &2eb4 99 26 1b STA &1b26,Y ; projectiles_x_velocity &2eb7 86 88 STX &88 ; projectile_x_offset &2eb9 a4 03 LDY &03 ; mover_to_update &2ebb b9 60 1a LDA &1a60,Y ; movers_x_low &2ebe be 81 1a LDX &1a81,Y ; movers_x_high &2ec1 a4 a1 LDY &a1 ; firing_mover_type &2ec3 c0 0c CPY #&0c ; MOVER_TYPE_SAM &2ec5 f0 04 BEQ &2ecb ; add_x_offset &2ec7 a4 89 LDY &89 ; firing_direction &2ec9 30 08 BMI &2ed3 ; subtract_x_offset ; add_x_offset &2ecb 18 CLC &2ecc 65 88 ADC &88 ; projectile_x_offset &2ece 90 09 BCC &2ed9 ; calculate_bullet_screen_address &2ed0 e8 INX &2ed1 10 06 BPL &2ed9 ; calculate_bullet_screen_address # Always branches ; subtract_x_offset &2ed3 38 SEC &2ed4 e9 04 SBC #&04 &2ed6 b0 01 BCS &2ed9 ; calculate_bullet_screen_address &2ed8 ca DEX ; calculate_bullet_screen_address &2ed9 a4 86 LDY &86 ; projectile_slot &2edb 99 6c 1a STA &1a6c,Y ; movers_x_low + &c (MOVERS_FIRST_PROJECTILE) &2ede 8a TXA &2edf 99 8d 1a STA &1a8d,Y ; movers_x_high + &c (MOVERS_FIRST_PROJECTILE) &2ee2 a4 03 LDY &03 ; mover_to_update &2ee4 be e4 1a LDX &1ae4,Y ; movers_screen_address_high &2ee7 b9 c3 1a LDA &1ac3,Y ; movers_screen_address_low &2eea a4 a1 LDY &a1 ; firing_mover_type &2eec c0 0c CPY #&0c ; MOVER_TYPE_SAM &2eee f0 04 BEQ &2ef4 ; mover_is_firing_right &2ef0 a4 89 LDY &89 ; firing_direction &2ef2 30 0b BMI &2eff ; mover_is_firing_left ; mover_is_firing_right &2ef4 a0 00 LDY #&00 ; &0008 # Move right a column &2ef6 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &2ef9 c6 88 DEC &88 ; projectile_x_offset &2efb d0 f7 BNE &2ef4 ; mover_is_firing_right &2efd f0 05 BEQ &2f04 ; subtract_y_offset # Always branches ; mover_is_firing_left &2eff a0 04 LDY #&04 ; &0020 # Move left four columns &2f01 20 d2 20 JSR &20d2 ; subtract_delta_from_screen_address_in_AX ; subtract_y_offset &2f04 a4 87 LDY &87 ; projectile_y_offset &2f06 20 e5 20 JSR &20e5 ; subtract_Y_rows_from_screen_address_in_AX &2f09 a0 0a LDY #&0a &2f0b 20 fe 20 JSR &20fe ; add_Y_rows_from_screen_address_in_AX &2f0e a4 86 LDY &86 ; projectile_slot &2f10 99 cf 1a STA &1acf,Y ; movers_screen_address_low + &c (MOVERS_FIRST_PROJECTILE) &2f13 8a TXA &2f14 99 f0 1a STA &1af0,Y ; movers_screen_address_high + &c (MOVERS_FIRST_PROJECTILE) &2f17 a5 78 LDA &78 ; y_velocity &2f19 99 32 1b STA &1b32,Y ; projectiles_y_velocity &2f1c a9 0e LDA #&0e &2f1e a6 a1 LDX &a1 ; firing_mover_type &2f20 e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &2f22 b0 10 BCS &2f34 ; set_ttl ; is_soldier &2f24 a5 ba LDA &ba ; viewport_left_high &2f26 4a LSR A &2f27 c9 04 CMP #&04 &2f29 b0 07 BCS &2f32 ; use_ceiling &2f2b 29 03 AND #&03 &2f2d 18 CLC &2f2e 69 0a ADC #&0a &2f30 90 02 BCC &2f34 ; set_ttl ; use_ceiling &2f32 a9 0e LDA #&0e ; set_ttl &2f34 99 4a 1b STA &1b4a,Y ; projectiles_ttl - &c + &c (MOVERS_FIRST_PROJECTILE) &2f37 18 CLC &2f38 60 RTS ; clear_screen &2f39 a9 01 LDA #&01 # Set colour 0 to cyan &2f3b 85 94 STA &94 ; bottom_palette_value &2f3d 20 38 25 JSR &2538 ; wait_for_vsync &2f40 a9 40 LDA #&40 &2f42 8d 4b 2f STA &2f4b ; wipe_address_high &2f45 a0 00 LDY #&00 &2f47 a9 00 LDA #&00 ; clear_screen_loop # Wipe &4000 - &7fff &2f49 99 00 40 STA &4000,Y # actually STA wipe_address,Y &2f4c c8 INY &2f4d d0 fa BNE &2f49 ; clear_screen_loop &2f4f ee 4b 2f INC &2f4b ; wipe_address_high &2f52 10 f5 BPL &2f49 ; clear_screen_loop &2f54 60 RTS ; irq1_handler &2f55 8a TXA &2f56 48 PHA ; tmp_x &2f57 98 TYA &2f58 48 PHA ; tmp_y &2f59 ad 4d fe LDA &fe4d ; System VIA interrupt flag register &2f5c 29 82 AND #&82 &2f5e c9 82 CMP #&82 # &80 set if an interrupt occurred, &02 if v-sync &2f60 f0 13 BEQ &2f75 ; is_vsync ; not_vsync &2f62 ad 6d fe LDA &fe6d ; User VIA interrupt flag register &2f65 29 c0 AND #&c0 # &40 set if timer 1 interrupt &2f67 c9 c0 CMP #&c0 &2f69 d0 3d BNE &2fa8 ; leave_irq1_handler &2f6b ad 64 fe LDA &fe64 ; User VIA timer 1 counter LSB &2f6e a5 94 LDA &94 ; bottom_palette_value &2f70 8d 21 fe STA &fe21 ; video ULA palette register &2f73 d0 33 BNE &2fa8 ; leave_irq1_handler # Always branches ; is_vsync &2f75 ad 6b fe LDA &fe6b ; User VIA auxiliary control register &2f78 29 df AND #&df # Set User VIA timer 2 to one-shot mode &2f7a 8d 6b fe STA &fe6b ; User VIA auxiliary control register &2f7d a9 20 LDA #&20 # Enable User VIA timer 2 interrupts &2f7f 8d 6e fe STA &fe6e ; User VIA interrupt enable register &2f82 a9 ff LDA #&ff &2f84 8d 68 fe STA &fe68 ; User VIA timer 2 counter LSB &2f87 8d 69 fe STA &fe69 ; User VIA timer 2 counter MSB &2f8a ad 6b fe LDA &fe6b ; User VIA auxiliary control register &2f8d 29 3f AND #&3f # Set User VIA timer 1 to one-shot mode &2f8f 8d 6b fe STA &fe6b ; User VIA auxiliary control register &2f92 a9 c0 LDA #&c0 # Enable User VIA timer 1 interrupts &2f94 8d 6e fe STA &fe6e ; User VIA interrupt enable register &2f97 a9 00 LDA #&00 &2f99 8d 64 fe STA &fe64 ; User VIA timer 1 counter LSB &2f9c a9 29 LDA #&29 &2f9e 8d 65 fe STA &fe65 ; User VIA timer 1 counter MSB &2fa1 a9 01 LDA #&01 # Set colour 0 to cyan for sky &2fa3 8d 21 fe STA &fe21 ; video ULA palette register &2fa6 c6 96 DEC &96 ; game_over_cooldown ; leave_irq1_handler &2fa8 68 PLA ; tmp_y &2fa9 a8 TAY &2faa 68 PLA ; tmp_x &2fab aa TAX &2fac 4c ff ff JMP &ffff # actually JMP previous_irq1_vector ; multiply_A_by_X &2faf 85 c7 STA &c7 ; multiplicand &2fb1 86 c8 STX &c8 ; multiplier_low &2fb3 a9 00 LDA #&00 &2fb5 85 c5 STA &c5 ; result_low &2fb7 85 c6 STA &c6 ; result_high &2fb9 85 c9 STA &c9 ; multiplier_high &2fbb a0 08 LDY #&08 ; multiply_A_by_X_loop &2fbd 46 c7 LSR &c7 ; multiplicand &2fbf 90 0d BCC &2fce ; consider_next_bit &2fc1 18 CLC &2fc2 a5 c8 LDA &c8 ; multiplier_low &2fc4 65 c5 ADC &c5 ; result_low &2fc6 85 c5 STA &c5 ; result_low &2fc8 a5 c9 LDA &c9 ; multiplier_high &2fca 65 c6 ADC &c6 ; result_high &2fcc 85 c6 STA &c6 ; result_high ; consider_next_bit &2fce 06 c8 ASL &c8 ; multiplier_low &2fd0 26 c9 ROL &c9 ; multiplier_high &2fd2 88 DEY &2fd3 d0 e8 BNE &2fbd ; multiply_A_by_X_loop &2fd5 60 RTS ; check_if_raster_is_in_mover &2fd6 ad 69 fe LDA &fe69 ; User VIA timer 2 counter MSB &2fd9 49 ff EOR #&ff &2fdb 85 cf STA &cf ; threshold &2fdd b9 05 1b LDA &1b05,Y ; movers_raster_y &2fe0 c5 cf CMP &cf ; threshold &2fe2 b0 08 BCS &2fec ; leave_with_carry_set &2fe4 69 08 ADC #&08 &2fe6 c5 cf CMP &cf ; threshold &2fe8 90 02 BCC &2fec ; leave_with_carry_set &2fea 18 CLC # Leave with carry clear to indicate raster not in mover &2feb 60 RTS ; leave_with_carry_set &2fec 38 SEC # Leave with carry set to indicate raster in mover &2fed 60 RTS ; keys &2fee be ; &01 (KEY_UP) : A &2fef 9e ; &02 (KEY_DOWN) : Z &2ff0 86 ; &04 (KEY_RIGHT) : RIGHT &2ff1 e6 ; &08 (KEY_LEFT) : LEFT &2ff2 ff ; &10 (KEY_FIRE) : SHIFT &2ff3 a6 ; &20 (KEY_GRENADE) : DELETE &2ff4 fe ; &40 (KEY_ENTER) : CTRL &2ff5 c8 ; &80 (KEY_PAUSE) : P ; check_for_player_input &2ff6 a0 00 LDY #&00 &2ff8 84 c2 STY &c2 ; keys_pressed_bitmap &2ffa 84 c3 STY &c3 ; key_to_check ; check_for_player_input_loop &2ffc be ee 2f LDX &2fee,Y ; keys &2fff 20 e7 24 JSR &24e7 ; check_for_keypress &3002 d0 0e BNE &3012 ; key_not_pressed &3004 a9 01 LDA #&01 &3006 a4 c3 LDY &c3 ; key_to_check &3008 f0 04 BEQ &300e ; skip_shift ; shift_loop &300a 0a ASL A &300b 88 DEY &300c d0 fc BNE &300a ; shift_loop ; skip_shift &300e 45 c2 EOR &c2 ; keys_pressed_bitmap &3010 85 c2 STA &c2 ; keys_pressed_bitmap ; key_not_pressed &3012 e6 c3 INC &c3 ; key_to_check &3014 a4 c3 LDY &c3 ; key_to_check &3016 c0 08 CPY #&08 &3018 d0 e2 BNE &2ffc ; check_for_player_input_loop ; leave &301a 60 RTS ; play_sound &301b 09 80 ORA #&80 ; &0880 = sound_data &301d aa TAX &301e a0 08 LDY #&08 &3020 a9 07 LDA #&07 ; Generate a sound &3022 4c f1 ff JMP &fff1 ; OSWORD ; enemy_helicopters_maximum_x_low &3025 00 00 ; enemy_helicopters_minimum_x_low &3027 00 00 ; update_enemy_helicopter &3029 20 ec 30 JSR &30ec ; check_if_mover_can_be_updated # Returns carry clear if mover can be updated &302c b0 ec BCS &301a ; leave &302e 20 db 31 JSR &31db ; get_mover_frame_and_flip &3031 20 3a 23 JSR &233a ; get_mover_x_and_y &3034 a9 55 LDA #&55 # Consider targets in air, in front of helicopter &3036 85 f9 STA &f9 ; mover_y &3038 a9 b0 LDA #&b0 &303a 85 c9 STA &c9 ; mover_y_max &303c a9 3c LDA #&3c &303e 85 81 STA &81 ; mover_x_offset &3040 20 d3 2d JSR &2dd3 ; search_for_target # Returns carry clear if target found &3043 a4 03 LDY &03 ; mover_to_update &3045 90 15 BCC &305c ; move_helicopter_towards_target_vertically &3047 a5 b7 LDA &b7 ; frame_and_flip &3049 49 80 EOR #&80 # Consider targets in air, behind helicopter &304b 85 b7 STA &b7 ; frame_and_flip &304d 20 3a 23 JSR &233a ; get_mover_x_and_y &3050 20 d3 2d JSR &2dd3 ; search_for_target # Returns carry clear if target found &3053 a4 03 LDY &03 ; mover_to_update &3055 90 23 BCC &307a ; keep_vertical_position &3057 20 db 31 JSR &31db ; get_mover_frame_and_flip &305a b0 1e BCS &307a ; keep_vertical_position # Always branches ; move_helicopter_towards_target_vertically &305c bd a2 1a LDA &1aa2,X ; movers_y &305f 38 SEC &3060 f9 a2 1a SBC &1aa2,Y ; movers_y &3063 b0 02 BCS &3067 ; skip_inversion &3065 49 7f EOR #&7f ; skip_inversion &3067 be a2 1a LDX &1aa2,Y ; movers_y &306a 29 83 AND #&83 &306c 85 7d STA &7d ; y_delta &306e 90 06 BCC &3076 ; is_moving_down ; is_moving_up &3070 e0 a0 CPX #&a0 # Enemy helicopters can't rise above top of screen &3072 90 0a BCC &307e ; consider_horizontal_direction &3074 b0 04 BCS &307a ; keep_vertical_position # Always branches ; is_moving_down &3076 e0 69 CPX #&69 # Enemy helicopters can't fall below top of mountains &3078 b0 04 BCS &307e ; consider_horizontal_direction ; keep_vertical_position &307a a9 00 LDA #&00 &307c 85 7d STA &7d ; y_delta ; consider_horizontal_direction &307e 98 TYA &307f 29 01 AND #&01 &3081 85 cf STA &cf ; which_helicopter &3083 a5 b7 LDA &b7 ; frame_and_flip &3085 29 80 AND #&80 &3087 48 PHA ; helicopter direction &3088 0a ASL A # Set carry if helicopter is flipped &3089 2a ROL A # Set &01 if helicopter is flipped &308a 0a ASL A # Set &02 if helicopter is flipped &308b 45 cf EOR &cf ; which_helicopter &308d aa TAX &308e 20 3a 23 JSR &233a ; get_mover_x_and_y &3091 a5 f8 LDA &f8 ; mover_x_low &3093 dd 25 30 CMP &3025,X ; helicopters_maximum_x_low # Use helicopters_minimum_x_low if helicopter is flipped &3096 d0 0c BNE &30a4 ; skip_flipping_direction &3098 20 d3 2d JSR &2dd3 ; search_for_target # Returns carry clear if target found &309b a4 03 LDY &03 ; mover_to_update &309d 68 PLA ; helicopter direction &309e aa TAX &309f 90 06 BCC &30a7 ; set_x_delta # If no target found, &30a1 49 80 EOR #&80 # Flip direction of helicopter &30a3 48 PHA ; helicopter direction ; skip_flipping_direction &30a4 68 PLA ; helicopter direction &30a5 aa TAX &30a6 e8 INX ; set_x_delta &30a7 86 7c STX &7c ; x_delta &30a9 20 c4 30 JSR &30c4 ; move_and_replot_mover # Move helicopter &30ac a9 14 LDA #&14 &30ae a2 05 LDX #&05 ; MOVER_TYPE_HELICOPTER_WITH_MISSILE &30b0 20 9a 32 JSR &329a ; consider_mover_firing_grenade # Consider dropping bomb &30b3 4c 54 31 JMP &3154 ; consider_mover_firing_bullet ; plot_projectile &30b6 98 TYA &30b7 18 CLC &30b8 69 0c ADC #&0c ; MOVER_FIRST_PROJECTILE &30ba a8 TAY &30bb 4c e0 21 JMP &21e0 ; plot_mover ; move_horizontally_and_replot_mover &30be a4 03 LDY &03 ; mover_to_update &30c0 a9 00 LDA #&00 &30c2 85 7d STA &7d ; y_delta ; move_and_replot_mover ; wait_to_move_mover &30c4 20 d6 2f JSR &2fd6 ; check_if_raster_is_in_mover # Returns carry set if raster is in mover &30c7 b0 fb BCS &30c4 ; wait_to_move_mover &30c9 20 67 27 JSR &2767 ; unplot_and_move_mover &30cc 20 db 31 JSR &31db ; get_mover_frame_and_flip &30cf a6 8d LDX &8d ; hostile_mover &30d1 30 0c BMI &30df ; to_plot_mover &30d3 20 b1 2d JSR &2db1 ; check_if_friendly # Returns carry set if friendly &30d6 90 0a BCC &30e2 ; kill_hostile_mover_and_mover ; is_friendly &30d8 a5 b7 LDA &b7 ; frame_and_flip &30da 49 80 EOR #&80 # Flip friendly mover when touching player &30dc 99 3f 1a STA &1a3f,Y ; movers_frame_and_flip ; to_plot_mover &30df 4c e0 21 JMP &21e0 ; plot_mover # Plot mover ; kill_hostile_mover_and_mover &30e2 a4 8d LDY &8d ; hostile_mover &30e4 20 eb 2b JSR &2beb ; kill_mover &30e7 a4 03 LDY &03 ; mover_to_update &30e9 4c 13 2c JMP &2c13 ; kill_mover_Y ; check_if_mover_can_be_updated &30ec a6 03 LDX &03 ; mover_to_update &30ee 20 91 2b JSR &2b91 ; check_for_player_collision_with_mover_Y # Returns carry set if collision &30f1 b0 3b BCS &312e ; leave_with_mover_to_update # Leave with carry set if mover overlaps player &30f3 a6 bb LDX &bb ; viewport_right_high &30f5 a5 b3 LDA &b3 ; viewport_right_low &30f7 18 CLC &30f8 69 0a ADC #&0a &30fa 90 01 BCC &30fd ; skip_overflow &30fc e8 INX ; skip_overflow &30fd e4 c5 CPX &c5 ; mover_x_high &30ff 90 2c BCC &312d ; leave_with_carry_set &3101 d0 04 BNE &3107 ; skip_low_check &3103 c5 f8 CMP &f8 ; mover_x_low # If the mover is beyond the right edge of the screen, &3105 90 26 BCC &312d ; leave_with_carry_set # Leave with carry set to indicate no update required ; is_on_screen &3107 20 31 31 JSR &3131 ; get_mover_type # Returns A = mover type &310a c9 13 CMP #&13 ; MOVER_TYPE_MINE # If the mover is a mine, &310c f0 20 BEQ &312e ; leave_with_mover_to_update # Leave with carry set to indicate no update required &310e c9 0d CMP #&0d ; MOVER_TYPE_SKELETON # If the mover is not an explosion or a skeleton, &3110 90 1c BCC &312e ; leave_with_mover_to_update # Leave with carry clear to indicate it can be updated ; animate_explosion_or_skeleton &3112 20 e0 21 JSR &21e0 ; plot_mover # Unplot explosion or skeleton &3115 a6 03 LDX &03 ; mover_to_update &3117 bd 3f 1a LDA &1a3f,X ; movers_frame_and_flip &311a 29 7f AND #&7f &311c d0 07 BNE &3125 ; not_end_of_animation ; remove_explosion_or_skeleton &311e a9 ff LDA #&ff &3120 9d 81 1a STA &1a81,X ; movers_x_high # Set to negative to remove mover &3123 38 SEC # Leave with carry set to indicate no update required &3124 60 RTS ; not_end_of_animation &3125 de 3f 1a DEC &1a3f,X ; movers_frame_and_flip &3128 a4 03 LDY &03 ; mover_to_update &312a 20 e0 21 JSR &21e0 ; plot_mover # Plot explosion or skeleton ; leave_with_carry_set &312d 38 SEC # Leave with carry set to indicate no update required ; leave_with_mover_to_update &312e a4 03 LDY &03 ; mover_to_update &3130 60 RTS ; get_mover_type &3131 a4 03 LDY &03 ; mover_to_update ; get_mover_Y_type &3133 b9 1e 1a LDA &1a1e,Y ; movers_type_and_colour &3136 29 7f AND #&7f &3138 60 RTS ; movers_minimum_x_low &3139 00 00 00 00 00 00 00 00 00 ; movers_maximum_x_low &3142 00 00 00 00 00 00 00 00 00 ; movers_flags &314b 00 00 00 00 00 00 00 00 00 ; consider_mover_firing_bullet &3154 a6 03 LDX &03 ; mover_to_update &3156 bd f3 18 LDA &18f3,X ; movers_firing_cooldown - 1 &3159 f0 06 BEQ &3161 ; can_fire &315b de f3 18 DEC &18f3,X ; movers_firing_cooldown - 1 &315e 38 SEC &315f d0 79 BNE &31da ; leave ; can_fire &3161 20 db 31 JSR &31db ; get_mover_frame_and_flip &3164 a9 22 LDA #&22 # Consider targets in front of mover &3166 20 c2 2d JSR &2dc2 ; search_for_target_with_offset # Returns carry clear if target found &3169 20 31 31 JSR &3131 ; get_mover_type # Returns A = mover type &316c aa TAX &316d 86 7c STX &7c ; mover_type &316f 90 19 BCC &318a ; found_target ; check_for_target_behind_mover &3171 a5 b7 LDA &b7 ; frame_and_flip &3173 49 80 EOR #&80 # Consider targets behind mover &3175 85 b7 STA &b7 ; frame_and_flip &3177 a9 28 LDA #&28 &3179 20 c2 2d JSR &2dc2 ; search_for_target_with_offset # Returns carry clear if target found &317c b0 5d BCS &31db ; get_mover_frame_and_flip # Leave with carry set to indicate mover couldn't fire &317e a9 08 LDA #&08 ; FRAME_SHOOTING &3180 a6 7c LDX &7c ; mover_type &3182 e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &3184 90 35 BCC &31bb ; replot_mover &3186 a5 b7 LDA &b7 ; frame_and_flip &3188 b0 39 BCS &31c3 ; set_frame_and_flip # Always branches ; found_target &318a a9 07 LDA #&07 # 4 in 8 chance initially of soldier crouching &318c 20 e7 32 JSR &32e7 ; rnd_skewed_towards_right_of_world &318f b0 49 BCS &31da ; leave &3191 a2 06 LDX #&06 ; FRAME_GUN_DOWN &3193 ad 69 fe LDA &fe69 ; User VIA timer 2 counter MSB &3196 29 0f AND #&0f # Soldiers more likely to crouch to shoot further right &3198 c5 ba CMP &ba ; viewport_left_high &319a b0 01 BCS &319d ; set_firing_frame &319c e8 INX ; 7 ; FRAME_SHOOTING_CROUCHED ; set_firing_frame &319d 86 a0 STX &a0 ; firing_frame &319f 20 22 2e JSR &2e22 ; add_mover_bullet # Returns carry clear if bullet added &31a2 b0 36 BCS &31da ; leave # If not, leave with carry set to indicate mover couldn't fire &31a4 20 dc 25 JSR &25dc ; plot_bullet_and_play_sound &31a7 20 db 31 JSR &31db ; get_mover_frame_and_flip &31aa a6 7c LDX &7c ; mover_type &31ac bd 01 1c LDA &1c01,X ; mover_types_maximum_firing_cooldown &31af 99 f3 18 STA &18f3,Y ; movers_firing_cooldown - 1 &31b2 20 db 31 JSR &31db ; get_mover_frame_and_flip &31b5 e0 05 CPX #&05 ; MOVER_TYPE_FIRST_HELICOPTER &31b7 b0 20 BCS &31d9 ; leave_with_carry_clear &31b9 a5 a0 LDA &a0 ; firing_frame ; replot_mover &31bb 85 7c STA &7c ; new_frame &31bd a5 b7 LDA &b7 ; frame_and_flip &31bf 29 80 AND #&80 &31c1 05 7c ORA &7c ; new_frame ; set_frame_and_flip &31c3 85 7c STA &7c ; new_frame_and_flip &31c5 a4 03 LDY &03 ; mover_to_update ; wait_to_replot_mover &31c7 20 d6 2f JSR &2fd6 ; check_if_raster_is_in_mover # Returns carry set if raster is in mover &31ca b0 fb BCS &31c7 ; wait_to_replot_mover &31cc 20 e0 21 JSR &21e0 ; plot_mover # Unplot mover &31cf a4 03 LDY &03 ; mover_to_update &31d1 a5 7c LDA &7c ; new_frame_and_flip &31d3 99 3f 1a STA &1a3f,Y ; movers_frame_and_flip &31d6 20 e0 21 JSR &21e0 ; plot_mover # Replot mover ; leave_with_carry_clear &31d9 18 CLC ; leave &31da 60 RTS ; get_mover_frame_and_flip &31db a4 03 LDY &03 ; mover_to_update &31dd b9 3f 1a LDA &1a3f,Y ; movers_frame_and_flip &31e0 85 b7 STA &b7 ; frame_and_flip ; leave &31e2 60 RTS ; animate_stationery_mover &31e3 ad 69 fe LDA &fe69 ; User VIA timer 2 counter MSB &31e6 29 20 AND #&20 &31e8 d0 f8 BNE &31e2 ; leave &31ea a9 08 LDA #&08 ; FRAME_GUN_DOWN &31ec d0 cd BNE &31bb ; replot_mover # Always branches ; update_mover &31ee 20 ec 30 JSR &30ec ; check_if_mover_can_be_updated # Returns carry clear if mover can be updated &31f1 b0 e6 BCS &31d9 ; leave_with_carry_clear &31f3 20 54 31 JSR &3154 ; consider_mover_firing_bullet # Returns carry clear if mover fired bullet &31f6 90 e1 BCC &31d9 ; leave_with_carry_clear &31f8 20 9a 32 JSR &329a ; consider_mover_firing_grenade # Returns carry clear if mover fired grenade &31fb a4 03 LDY &03 ; mover_to_update &31fd b0 0f BCS &320e ; not_throwing_grenade &31ff 20 db 31 JSR &31db ; get_mover_frame_and_flip &3202 20 33 31 JSR &3133 ; get_mover_Y_type &3205 c9 05 CMP #&05 ; MOVER_TYPE_FIRST_HELICOPTER &3207 b0 05 BCS &320e ; not_throwing_grenade &3209 a9 0c LDA #&0c ; FRAME_THROWING &320b 4c bb 31 JMP &31bb ; replot_mover ; not_throwing_grenade &320e b9 4a 31 LDA &314a,Y ; movers_flags - 1 &3211 f0 cf BEQ &31e2 ; leave # If mover_flags is &00, mover is stationary &3213 c9 80 CMP #&80 &3215 f0 cc BEQ &31e3 ; animate_stationery_mover # If mover flags is &80, mover is stationary but lifts gun &3217 a5 b7 LDA &b7 ; frame_and_flip # Otherwise, mover moves between two limits &3219 29 80 AND #&80 &321b aa TAX &321c e8 INX &321d 86 7c STX &7c ; x_delta &321f a6 7c LDX &7c ; x_delta &3221 98 TYA &3222 ca DEX &3223 30 03 BMI &3228 ; is_moving_left ; is_moving_right &3225 18 CLC &3226 69 09 ADC #&09 ; movers_maximum_x_low - movers_minimum_x_low ; is_moving_left &3228 aa TAX &3229 a5 f8 LDA &f8 ; mover_x_low &322b dd 38 31 CMP &3138,X ; movers_minimum_x_low - 1 &322e d0 06 BNE &3236 ; skip_changing_direction &3230 a5 7c LDA &7c ; x_delta &3232 49 80 EOR #&80 &3234 85 7c STA &7c ; x_delta ; skip_changing_direction &3236 4c be 30 JMP &30be ; move_horizontally_and_replot_mover ; decrement_new_movers_offset &3239 a4 7f LDY &7f ; new_movers_offset &323b 88 DEY &323c d0 02 BNE &3240 ; skip_wraparound &323e a0 03 LDY #&03 ; skip_wraparound &3240 84 7f STY &7f ; new_movers_offset &3242 60 RTS ; add_new_movers # Called with X = new movers offset &3243 a9 03 LDA #&03 &3245 20 af 2f JSR &2faf ; multiply_A_by_X # Add three movers in slots 1, 4 and 7 &3248 a4 7f LDY &7f ; new_movers_offset # or 2, 5 and 8 &324a a6 7f LDX &7f ; new_movers_offset # or 3, 6 and 9 &324c c8 INY &324d c0 04 CPY #&04 &324f 90 02 BCC &3253 ; skip_wraparound &3251 a0 01 LDY #&01 &3253 84 7f STY &7f ; new_movers_offset ; skip_wraparound &3255 a4 c5 LDY &c5 ; result_low ; add_movers_loop &3257 b9 77 18 LDA &1877,Y ; new_movers_initial_x_high_and_flags &325a 29 c0 AND #&c0 &325c 9d 4a 31 STA &314a,X ; movers_flags - 1 &325f b9 02 18 LDA &1802,Y ; new_movers_initial_x_low &3262 9d 60 1a STA &1a60,X ; movers_x_low &3265 38 SEC &3266 e9 1e SBC #&1e &3268 b0 02 BCS &326c ; skip_floor &326a a9 00 LDA #&00 ; skip_floor &326c 9d 38 31 STA &3138,X ; movers_minimum_x_low - 1 &326f 18 CLC &3270 69 3c ADC #&3c &3272 90 02 BCC &3276 ; skip_ceiling &3274 a9 ff LDA #&ff ; skip_ceiling &3276 9d 41 31 STA &3141,X ; movers_maximum_x_low - 1 &3279 b9 8d 17 LDA &178d,Y ; new_movers_type &327c 9d 1e 1a STA &1a1e,X ; movers_type_and_colour &327f b9 77 18 LDA &1877,Y ; new_movers_initial_x_high_and_flags &3282 29 3f AND #&3f &3284 9d 81 1a STA &1a81,X ; movers_x_high &3287 a9 00 LDA #&00 &3289 9d 3f 1a STA &1a3f,X ; movers_frame_and_flip &328c a9 18 LDA #&18 &328e 9d a2 1a STA &1aa2,X ; movers_y &3291 e8 INX &3292 e8 INX &3293 e8 INX &3294 c8 INY &3295 e0 0a CPX #&0a &3297 90 be BCC &3257 ; add_movers_loop &3299 60 RTS ; consider_mover_firing_grenade # Also bombs and rockets &329a 20 3a 23 JSR &233a ; get_mover_x_and_y &329d 20 eb 23 JSR &23eb ; check_if_mover_Y_is_on_screen # Returns carry set if mover is not on screen &32a0 b0 44 BCS &32e6 ; leave &32a2 86 a1 STX &a1 ; firing_mover_type &32a4 a0 0f LDY #&0f &32a6 84 81 STY &81 ; mover_x_offset &32a8 20 7b 2d JSR &2d7b ; calculate_mover_x_max_from_offset_getting_frame_and_flip &32ab a6 a1 LDX &a1 ; firing_mover_type &32ad a9 0a LDA #&0a &32af e0 0c CPX #&0c ; MOVER_TYPE_SAM &32b1 d0 08 BNE &32bb ; not_sam ; is_sam &32b3 a5 b7 LDA &b7 ; frame_and_flip &32b5 49 80 EOR #&80 &32b7 85 b7 STA &b7 ; frame_and_flip &32b9 a9 3c LDA #&3c ; not_sam &32bb 85 f9 STA &f9 ; mover_y &32bd 18 CLC &32be 69 78 ADC #&78 &32c0 85 c9 STA &c9 ; mover_y_max &32c2 a9 0a LDA #&0a &32c4 85 81 STA &81 ; mover_x_offset &32c6 20 7e 2d JSR &2d7e ; calculate_mover_x_max_from_offset &32c9 20 db 31 JSR &31db ; get_mover_frame_and_flip &32cc 20 a0 2d JSR &2da0 ; check_for_collision_with_friends # Returns carry set if collision with friendly mover &32cf b0 15 BCS &32e6 ; leave &32d1 a9 3f LDA #&3f # 4 in 64 chance initially of firing grenade &32d3 20 e7 32 JSR &32e7 ; rnd_skewed_towards_right_of_world &32d6 b0 0e BCS &32e6 ; leave &32d8 20 50 2e JSR &2e50 ; add_new_grenade # Returns carry clear if grenade was added &32db b0 09 BCS &32e6 ; leave # Otherwise, leave with carry set to indicate no grenade fired ; plot_grenade_and_play_sound &32dd 20 b6 30 JSR &30b6 ; plot_projectile &32e0 a9 18 LDA #&18 # Play sound for firing grenade &32e2 20 1b 30 JSR &301b ; play_sound &32e5 18 CLC # Leave with carry clear to indicate grenade fired ; leave &32e6 60 RTS ; rnd_skewed_towards_right_of_world &32e7 85 ce STA &ce ; mask &32e9 a5 ba LDA &ba ; viewport_left_high &32eb 18 CLC &32ec 69 04 ADC #&04 &32ee 85 cf STA &cf ; threshold &32f0 ad 68 fe LDA &fe68 ; User VIA timer 2 counter LSB &32f3 25 ce AND &ce ; mask &32f5 c5 cf CMP &cf ; threshold &32f7 60 RTS ; plot_lives &32f8 a5 00 LDA &00 ; screen_start_address_low &32fa 85 ce STA &ce ; text_screen_address_low &32fc a5 01 LDA &01 ; screen_start_address_high &32fe 85 cf STA &cf ; text_screen_address_high &3300 a5 95 LDA &95 ; lives &3302 a2 06 LDX #&06 &3304 20 af 2f JSR &2faf ; multiply_A_by_X &3307 a5 c5 LDA &c5 ; result_low &3309 18 CLC &330a 69 6c ADC #&6c ; "0" &330c 20 19 33 JSR &3319 ; plot_character &330f a0 07 LDY #&07 &3311 a9 00 LDA #&00 ; plot_lives_blank_loop &3313 91 ce STA (&ce),Y ; text_screen_address &3315 88 DEY &3316 10 fb BPL &3313 ; plot_lives_blank_loop &3318 60 RTS ; plot_character # Called with A = font offset for character &3319 aa TAX &331a 18 CLC &331b 69 06 ADC #&06 &331d 85 c8 STA &c8 ; font_end_offset &331f a9 aa LDA #&aa # Start with left pixel &3321 85 c5 STA &c5 ; text_pixel ; plot_character_column_loop &3323 bd 0d 34 LDA &340d,X ; font_data &3326 85 c9 STA &c9 ; font_byte &3328 a0 07 LDY #&07 ; plot_character_row_loop &332a a9 00 LDA #&00 &332c 26 c9 ROL &c9 ; font_byte &332e 90 04 BCC &3334 ; set_pixel_value &3330 a9 3c LDA #&3c ; set_pixel_value &3332 25 c5 AND &c5 ; text_pixel &3334 85 c6 STA &c6 ; pixel_value &3336 a5 c5 LDA &c5 ; text_pixel &3338 49 ff EOR #&ff &333a 31 ce AND (&ce),Y ; text_screen_address &333c 45 c6 EOR &c6 ; pixel_value &333e 91 ce STA (&ce),Y ; text_screen_address &3340 88 DEY &3341 10 e7 BPL &332a ; plot_character_row_loop &3343 a5 c5 LDA &c5 ; text_pixel &3345 49 ff EOR #&ff # Use other pixel &3347 85 c5 STA &c5 ; text_pixel &3349 10 10 BPL &335b ; not_next_byte &334b 86 cd STX &cd ; tmp_x &334d a6 cf LDX &cf ; text_screen_address_high &334f a5 ce LDA &ce ; text_screen_address_low &3351 c8 INY &3352 20 b3 20 JSR &20b3 ; add_delta_to_screen_address_in_AX &3355 86 cf STX &cf ; text_screen_address_high &3357 85 ce STA &ce ; text_screen_address_low &3359 a6 cd LDX &cd ; tmp_x ; not_next_byte &335b e8 INX &335c e4 c8 CPX &c8 ; font_end_offset &335e d0 c3 BNE &3323 ; plot_character_column_loop &3360 60 RTS ; text_screen &3361 86 c3 STX &c3 ; text_address_high &3363 84 c2 STY &c2 ; text_address_low &3365 20 55 25 JSR &2555 ; reset_screen_scroll &3368 20 39 2f JSR &2f39 ; clear_screen ; plot_text_loop &336b b1 c2 LDA (&c2),Y ; text_address # Get two bytes for screen address &336d 85 ce STA &ce ; text_screen_address_low &336f c8 INY &3370 b1 c2 LDA (&c2),Y ; text_address &3372 85 cf STA &cf ; text_screen_address_high &3374 20 84 33 JSR &3384 ; plot_text_string &3377 c8 INY &3378 c9 ff CMP #&ff # &ff indicates end of text &337a d0 ef BNE &336b ; plot_text_loop ; wait_for_space &337c a2 9d LDX #&9d ; SPACE &337e 20 e7 24 JSR &24e7 ; check_for_keypress &3381 d0 f9 BNE &337c ; wait_for_space &3383 60 RTS ; plot_text_string_loop &3384 c8 INY &3385 b1 c2 LDA (&c2),Y ; text_screen_address_high # Get byte for character &3387 c9 fe CMP #&fe &3389 90 01 BCC &338c ; not_end_of_string # &fe indicates end of string, &ff end of text &338b 60 RTS ; not_end_of_string &338c 84 c1 STY &c1 ; text_offset &338e 20 19 33 JSR &3319 ; plot_character &3391 a4 c1 LDY &c1 ; text_offset &3393 d0 ef BNE &3384 ; plot_text_string_loop # Always branches ; increase_score_for_killing_enemy &3395 20 33 31 JSR &3133 ; get_mover_Y_type &3398 a8 TAY &3399 c0 0b CPY #&0b ; MOVER_TYPE_LAST_ENEMY + 1 &339b b0 23 BCS &33c0 ; leave &339d ad fd 33 LDA &33fd ; game_over_text + &17 # Bytes in Game Over text are used for score &33a0 18 CLC &33a1 79 01 34 ADC &3401,Y ; mover_type_scoring_table &33a4 8d fd 33 STA &33fd ; game_over_text + &17 &33a7 a2 05 LDX #&05 &33a9 a0 00 LDY #&00 ; update_score_loop &33ab 98 TYA &33ac a0 00 LDY #&00 &33ae 18 CLC &33af 7d fa 33 ADC &33fa,X ; game_over_text + &14 &33b2 c9 a8 CMP #&a8 ; "9" + 6 &33b4 90 04 BCC &33ba ; skip_overflow &33b6 e9 3c SBC #&3c ; "9" - "0" + 6 &33b8 a0 06 LDY #&06 ; skip_overflow &33ba 9d fa 33 STA &33fa,X ; game_over_text + &14 &33bd ca DEX &33be 10 eb BPL &33ab ; update_score_loop ; leave &33c0 60 RTS ; press_space_to_play_text &33c1 a8 45 ; at &45a8 &33c3 48 4e 42 5a 1e 12 42 48 60 42 54 30 ; "STRYKERS RUN" &33cf fe ; end of string &33d0 58 77 ; at &7758 &33d2 3c 42 12 48 48 60 48 3c 00 06 12 60 4e 36 60 3c ; "PRESS SPACE TO PLAY" &33e2 24 00 5a &33e5 ff ; end of text ; game_over_text &33e6 d8 4a ; at &4ad8 &33e8 66 00 2a 12 60 36 54 12 42 ; "GAME OVER" &33f1 fe ; end of string &33f2 b8 63 ; at &63b8 &33f4 48 06 36 42 12 60 66 66 66 66 66 66 ; "SCORE GGGGGG" &3400 ff ; end of text ; mover_type_scoring_table &3401 00 ; &00 : MOVER_TYPE_PLAYER # 0 points (unused) &3402 00 ; &01 : MOVER_TYPE_SOLDIER_WITH_RIFLE # 0 points &3403 18 ; &02 : MOVER_TYPE_OFFICER_WITH_PISTOL # 400 points &3404 0c ; &03 : MOVER_TYPE_TROOPER_WITH_RIFLE # 200 points &3405 12 ; &04 : MOVER_TYPE_TROOPER_WITH_BAZOOKA # 300 points &3406 2a ; &05 : MOVER_TYPE_HELICOPTER_WITH_MISSILE # 700 points &3407 30 ; &06 : MOVER_TYPE_HELICOPTER # 800 points &3408 1e ; &07 : MOVER_TYPE_HELICOPTER_WITH_SOLDIER # 500 points &3409 00 ; &08 : MOVER_TYPE_RED_HELICOPTER # 0 points &340a 18 ; &09 : MOVER_TYPE_MORTAR # 400 points &340b 24 ; &0a : MOVER_TYPE_MACHINE_GUN # 600 points ; unused &340c 35 ; font_data # start with A, 60 = " ", six bytes per character &340d ff f9 19 19 ff 00 ; &00 : "A" &3413 ff f9 c1 c1 c0 00 ; &06 : "C" &3419 ff f9 c1 c3 fe 00 ; &0c : "D" &341f ff f9 c9 c9 c0 00 ; &12 : "E" &3425 00 c1 ff f9 c1 00 ; &18 : "I" &342b ff f8 0c 36 c3 00 ; &1e : "K" &3431 ff f8 c0 c0 c0 00 ; &24 : "L" &3437 ff f3 06 03 ff 00 ; &2a : "M" &343d ff f9 01 01 ff 00 ; &30 : "N" &3443 ff f9 c1 c1 ff 00 ; &36 : "O" &3449 ff f9 19 19 1f 00 ; &3c : "P" &344f ff f9 19 19 ef 00 ; &42 : "R" &3455 cf cd c9 f9 f8 00 ; &48 : "S" &345b 01 01 ff f9 01 00 ; &4e : "T" &3461 3f 78 c0 60 3f 00 ; &54 : "U" or "V" &3467 3f 38 e0 20 3f 00 ; &5a : "Y" &346d 00 00 00 00 00 00 ; &60 : " " &3473 ff f9 c1 db f8 00 ; &66 : "G" &3479 00 fe f2 c2 c2 fe ; &6c : "0" &347f 00 00 fe f0 00 00 ; &72 : "1" &3485 00 f2 f2 d2 d2 de ; &78 : "2" &348b 00 c0 d2 d2 d2 fe ; &7e : "3" &3491 00 1e 10 fc f0 10 ; &84 : "4" &3497 00 de d2 d2 d2 f2 ; &8a : "5" &349d 00 fe e8 c8 c8 f8 ; &80 : "6" &34a3 00 02 c2 f2 3e 0e ; &96 : "7" &34a9 00 fe f2 d2 d2 fe ; &9c : "8" &34af 00 1e 12 12 f2 fe ; &a2 : "9" ; mover_sprite_15 (SPRITE_HELICOPTER_WITH_SOLIDER) &34b5 00 12 00 bc ec bd bc 00 08 bc 06 00 07 14 05 00 &34c5 a8 9c bf ae bc 00 0e bc 94 c0 94 bc ac 6e bf 7e &34d5 fd 04 2c bc bf 8c bc 00 12 bc 80 a8 94 bc bd 9d &34e5 9c bd bc 7d bf bd 04 3e 5c bc 8c ae bc 00 16 bc &34f5 94 a9 83 96 7d be bf bd be bf bd be bd 7f 7e bf &3505 bd bc 9d bc 00 17 bc a8 96 bc 05 3e bc ad bc b9 &3515 b3 bc bf bc 4f ad be bc bf bc 00 16 a8 40 bc bf &3525 bc de bc 8f bc 8f bc e8 bc 9e a8 80 bc bf bc 00 &3535 15 c0 bc ae bc 8c bc 94 fc 8f bc 7d 6c fd ac 8c &3545 bc 00 12 94 40 bc 9d bc 4c 6e bf bc 8f 7c 07 38 &3555 9c a8 00 11 bc 40 bc be bf 6e 8c 5c bc ad bc b8 &3565 f0 a0 80 90 b4 a8 00 14 bc 94 a8 80 bc 04 0c bc &3575 b0 78 a8 60 80 90 94 b4 a8 00 13 a8 94 c0 68 5c &3585 bc 06 34 68 00 8b ; mover_sprite_2e (SPRITE_MINE) &358b 00 bc bd 94 00 05 bc 8c ae bd 94 00 07 bc 4c be &359b a8 00 06 bc 9c a8 00 85 ; mover_sprite_2d (SPRITE_TORSO_WITH_BAZOOKA) &35a3 00 06 00 05 14 00 06 bc 05 2c bc 8f 9b b3 00 09 &35b3 bc 9c 6c 8c 5c ad 73 00 09 bc 9c bc 5c 73 bc b3 &35c3 a2 00 0a c0 94 ad 79 9e 8f 85 94 00 0a 04 00 68 &35d3 bc 4f ad 94 00 09 06 00 bc de bc 00 87 ; mover_sprite_2c (SPRITE_BOMB) &35e0 00 94 ac 94 bd 94 00 07 94 6c bd 94 00 06 a8 9c &35f0 9d be a8 00 07 40 a8 00 84 ; mover_sprite_2b (SPRITE_GRENADE) &35f9 00 80 94 7d 94 00 06 a8 9c 4c be a8 00 07 40 68 &3609 00 84 ; mover_sprite_2a (SPRITE_BULLET) &360b 00 bc a9 bc 00 05 bc 83 bc 00 05 e8 00 83 ; mover_sprite_29 (SPRITE_EXPLOSION_FIVE) &3619 00 00 02 08 00 94 00 05 05 00 54 a9 83 bc 94 00 &3629 09 04 00 a8 56 4b 83 96 a8 00 0a 06 00 68 96 a8 &3639 00 07 00 02 00 82 ; mover_sprite_28 (SPRITE_EXPLOSION_FOUR) &363f 00 05 00 94 80 94 80 94 bd 54 00 0b 40 94 bc bd &364f 7c be a8 80 bc 7e bc 00 0d 94 bd bc be bc 96 83 &365f a9 94 a9 83 96 a8 be a8 00 11 bc bd bc d6 8b 8f &366f 8b 83 bc 54 bc bd 94 00 0f 80 bc be a8 40 a8 bc &367f 83 bc 56 bc 7d 94 00 0f c0 bc bd 94 bc bf bc bd &368f bc a8 be 68 00 0e 04 00 a8 40 a8 80 a8 00 89 ; mover_sprite_27 (SPRITE_EXPLOSION_THREE) &369e 00 05 00 94 80 94 80 94 bd 54 00 0b 40 94 7d bf &36ae bd bf bc 7e 7f bc 00 0c 94 bd 7f be bc 69 94 a9 &36be 94 bc bf be bd 94 00 10 bc bd bf bd bc 80 bc 96 &36ce 8f 87 a9 bc 7e bd bc 00 11 80 bc bf 7d bc 95 bc &36de 96 7c bd be bf bd 94 00 10 40 a8 be 7f be bf be &36ee bf be a8 be 68 00 0e 04 00 68 80 a8 80 a8 00 89 ; mover_sprite_26 (SPRITE_EXPLOSION_TWO) &36fe 00 00 02 04 00 d4 fd 54 00 07 40 94 bc 7f be a8 &370e 7e bf be bd bc 00 0d 80 a8 be bf 7d 94 80 94 bd &371e 7f bc 00 0d 40 a8 bc ff bd ff bd be a8 00 0b c0 &372e 68 be bc bf bc be 68 00 0a 07 00 a8 00 85 ; mover_sprite_25 (SPRITE_EXPLOSION_ONE) &373c 00 00 02 08 00 54 00 05 04 00 94 fd 7f bc 94 00 &374c 09 c0 bc be bf be 68 be bf bd bc 00 0c c0 bc 7e &375c bf 7d bf be bd bc 00 0b 06 00 68 bc be 68 00 08 &376c 00 82 ; mover_sprite_24 (SPRITE_SKELETON_FOUR) &376e 00 94 7d 94 80 54 00 07 94 bd be bf bd 7e bc 54 &377e 00 0a a8 be bd bc bd bc bf bd 7f bd 94 00 0d bc &378e bf bd bc be bc bf bd 7f be a8 00 0d a8 be bd 7e &379e bc 04 28 00 09 a8 be bd bf be a8 00 08 a8 7e a8 &37ae 00 85 ; mover_sprite_23 (SPRITE_SKELETON_THREE) &37b0 00 0c 00 54 7d 94 00 07 94 bd 94 bd 54 04 00 94 &37c0 bd bf be bc a8 54 00 10 bc be bd bc 7e bd bc 94 &37d0 bd 94 bc bd bc bf bd 7f bd 94 00 14 94 bd bc 94 &37e0 7d bc bf bc be a8 be bc 7f bd 7f be a8 00 13 bc &37f0 be bd bf be 68 be bc bf 7c be bf bd bc 68 00 11 &3800 40 68 05 00 bc bd bf bc 68 00 0b 08 00 a8 7e a8 &3810 00 87 ; mover_sprite_22 (SPRITE_SKELETON_TWO) &3812 00 0c 00 94 fd 94 00 07 94 bd 54 7d 54 05 00 bc &3822 bd bf be a8 05 14 00 10 bc be bd 94 68 7e 7d 80 &3832 54 bd bc 7d bc bf bd 7f bd bc 00 14 94 bd bc 40 &3842 d4 bc 7d bf bd bf bd bf bc be bf bd 7f be bc 00 &3852 15 bc be bc 7d fe bd bc a8 be bc bf bc bf bc bf &3862 bc e8 40 00 14 40 04 28 40 a8 80 a8 7e 7d bc 94 &3872 a8 00 0e 0d 00 68 7e a8 00 87 ; mover_sprite_21 (SPRITE_SKELETON_ONE) &387c 00 0e 00 54 00 05 94 bd 94 c0 54 05 00 a8 7e 04 &388c 3d 94 00 0e bc be 04 3d 7e fd 54 80 54 bd bc bd &389c bc bf bc 54 bd bc 7d 94 00 16 94 bd bc e8 54 e8 &38ac be bf bd bf bd bf bd bf bd bf bc bf bc bf be ff &38bc bc 00 19 bc be 04 3d 7e fd bf aa bc be bc bf bc &38cc bf bc bf be 68 04 3e a8 00 17 40 04 28 40 05 28 &38dc 7e 05 3d be a8 00 0d 0f 00 05 28 00 86 ; mover_sprite_20 (SPRITE_TROOPER_HEAD) &38e9 00 00 02 94 bc a9 6c a9 bc 94 00 09 bc 4c 5c 4c &38f9 bc 00 07 bc 8c 9c 8c bc 8c 9c bc 00 0a 80 06 28 &3909 00 05 00 02 00 82 ; mover_sprite_1f (SPRITE_TORSO_WITH_PISTOL_EIGHT) &390f 00 00 02 bc 6c bc ec bc 00 07 bc 9c b9 b3 b6 9c &391f 4c 00 09 bc 73 6d 5c b9 00 07 a8 bc 8f 9e bc 68 &392f b6 b9 bc b9 94 00 0d 80 e8 04 00 a8 f6 a8 00 09 &393f 00 82 ; mover_sprite_1e (SPRITE_TORSO_WITH_PISTOL_SEVEN) &3941 00 00 02 94 6c 7c 6c 94 00 07 8c 9c ac 4c 9c 4c &3951 00 08 5c bc 9c b3 b9 bc 9c 00 09 c0 a8 bc 73 8f &3961 ad 94 00 09 05 00 e8 5e a8 00 07 00 82 ; mover_sprite_1d (SPRITE_TORSO_WITH_PISTOL_SIX) &396e 00 c0 d4 00 04 6c bc cc ac 94 00 07 8c bc 73 bc &397e 9c 4c 00 08 bc 73 6d 5c a8 00 07 bc ad 8f 9e a8 &398e 00 07 80 68 00 04 00 82 ; mover_sprite_1c (SPRITE_LEGS_TEN) &3996 00 00 02 94 bc 69 bc 94 40 54 00 09 bc 83 96 bc &39a6 4c 6c 4c 00 09 05 28 bc dc a8 00 07 00 02 00 02 &39b6 00 82 ; mover_sprite_1b (SPRITE_LEGS_NINE) &39b8 00 00 02 94 bc 69 94 c0 54 00 08 bc 83 96 ac 8c &39c8 ac 94 bc 4c 00 0b bc a9 bc ac 5c cc 9c 00 09 68 &39d8 80 a8 5c bc 68 00 08 00 02 00 82 ; mover_sprite_1a (SPRITE_LEGS_EIGHT) &39e3 00 00 02 40 54 04 00 94 00 07 80 bc 56 ac 54 bc &39f3 8c 00 09 94 a9 83 96 6c bc 4c 00 09 bc 96 a8 5c &3a03 cc bc 00 08 05 00 e8 00 05 00 82 ; mover_sprite_19 (SPRITE_ROTORS_FOUR) &3a0e 00 00 02 00 02 00 02 40 54 00 04 40 bc ab bc 00 &3a1e 06 ed 83 bc 00 05 fe 83 bc 00 05 40 bc 97 bc 00 &3a2e 06 c0 68 00 04 00 02 00 02 00 82 ; mover_sprite_18 (SPRITE_ROTORS_THREE) &3a39 00 00 02 00 02 00 02 00 02 00 02 6d bc bd 94 00 &3a49 06 5e bc be bc 00 06 00 02 00 02 00 02 00 02 00 &3a59 82 ; mover_sprite_17 (SPRITE_ROTORS_TWO) &3a5a 00 00 02 00 02 40 54 00 04 40 bc bf bc 00 06 40 &3a6a bc 83 bc 00 06 6d 9f 83 bc 00 06 7e ad 83 bc 00 &3a7a 06 40 bc 83 bc 00 06 40 bc bf bc 00 06 c0 68 00 &3a8a 04 00 02 00 82 ; mover_sprite_16 (SPRITE_ROTORS_ONE) &3a8f 00 40 bc bd 94 00 06 40 bc bf bc 00 06 40 bc ab &3a9f bc 00 06 40 bc 83 bc 00 06 40 bc 83 bc 00 06 7d &3aaf be 83 bc 00 06 5e ad 83 bc 00 06 40 bc 83 bc 00 &3abf 06 40 bc 83 bc 00 06 40 bc 97 bc 00 06 40 bc bf &3acf bc 00 06 40 a8 be bc 00 86 ; mover_sprite_14 (SPRITE_RED_HELICOPTER_BODY) &3ad8 00 0d 00 a8 bc e9 d4 69 bc 00 0a 0f 00 a8 96 83 &3ae8 9e 8b 83 96 a8 00 0c 0a 00 bc a9 6d bc 69 83 bc &3af8 83 bc 00 0d 94 06 00 d4 bc 83 4f bc c3 bc 83 bc &3b08 00 0e bc 04 00 94 7c 43 bc 96 5e bc e8 bc 83 bc &3b18 ad 94 00 12 bc 94 80 94 a9 43 bc 43 bc 54 05 00 &3b28 bc 83 bc 8f a8 00 13 bc 80 a8 bc c3 bc ad bc b8 &3b38 b0 07 38 b0 bc 9e 00 11 bc 40 bc c3 bc 8f bc 05 &3b48 30 a0 80 90 b0 b4 a8 00 11 bc 40 bc c3 bc 9e bc &3b58 b0 60 80 50 b0 b4 a8 00 10 bc 94 a8 bc c3 bc b0 &3b68 a0 50 b0 74 68 00 0e bc 40 a8 bc 43 bc b0 74 68 &3b78 00 0b a8 94 40 a8 56 bc a8 00 89 ; mover_sprite_13 (SPRITE_BLUE_SPACESHIP) &3b83 00 94 04 00 d4 fc 78 bc 78 bc 80 bc 69 bc 00 0f &3b93 bc 40 54 bc 56 7c a9 70 bc a9 7c 94 bc 56 bc 00 &3ba3 11 bc a8 94 bc 83 7c b0 7c 83 70 bc 83 7c b4 bc &3bb3 70 bc 00 13 bc 80 94 bc 96 7c b0 7c 83 70 fc 40 &3bc3 bc 74 bc 00 11 bc a8 80 bc 83 7c b0 7c 83 70 bc &3bd3 a8 40 bf bc 00 11 bc 40 bc 83 7c b0 7c 83 70 bc &3be3 40 bf 94 a8 00 10 c0 bc 96 7c b0 7c 83 70 bc 80 &3bf3 bf 94 a8 00 0f 05 00 a8 bc b0 7c 83 b0 bc 80 bf &3c03 94 a8 00 0f 94 c0 94 a8 bc b4 7c 83 b0 bc bf 94 &3c13 a8 00 0f bc 80 94 a8 c0 fc 83 b0 bc 94 a8 00 0d &3c23 bc a8 06 00 7c 83 b4 bc 00 0a a8 94 07 00 a8 96 &3c33 bc 00 89 ; mover_sprite_12 (SPRITE_HELICOPTER_WITH_MISSILE) &3c36 00 0f 00 a8 bc bd 6c bc 00 09 bc 05 00 94 6d bc &3c46 6d 94 04 00 bc ae 9d bc 00 10 bc a8 94 04 00 a8 &3c56 9e b9 9e a8 80 54 6c bc 9d bf bc 00 13 bc 40 a8 &3c66 94 c0 bc b3 fc 7e bf 8c bc 7f bc 00 10 bc a8 94 &3c76 80 94 bc 94 ac bc b3 bc 9c 4c bc 7f bd ae 8c bc &3c86 00 15 a8 94 80 bc bf ae 8c 9d bc b3 bc bf bd 9c &3c96 bc 7e dc bc 00 14 c0 bc cc be ad a7 ad 7e b8 04 &3ca6 30 a0 b0 bc 00 10 bc 80 94 a8 bc be 7f bd 9e bd &3cb6 bc 04 30 a0 80 90 bc 00 13 bc a8 80 bc 4c ac be &3cc6 ae bd bf bc 70 a0 80 90 b4 a8 00 13 a8 94 80 a8 &3cd6 9c 8c ae bf bd 9c 8c bc b0 80 90 b4 a8 00 13 05 &3ce6 00 bc ad bc a8 bc 9d bc b0 b4 a8 00 0e 05 00 bc &3cf6 9e bc 80 a8 7e a8 00 8b ; mover_sprite_10 (SPRITE_TORSO_WITH_RIFLE_ONE) &3cfe 00 00 02 bc ac bc 04 2c 94 00 08 bc ac 4c ad 9c &3d0e 4c 00 08 bc 9c 99 b9 8f 5c a8 00 09 bc 9e 76 8f &3d1e 9e a8 00 08 a8 9e 76 8f ad 94 00 08 04 00 68 00 &3d2e 85 ; mover_sprite_0f (SPRITE_TORSO_WITH_PISTOL_FIVE) &3d2f 00 00 02 bc 06 2c bc 00 06 bc 8c 9c ac 4c 9c 8c &3d3f 00 09 68 bc 9c b3 b9 9c bc 00 09 40 a8 b6 bc b6 &3d4f b9 b3 8f bc 00 0b 05 00 68 bc 9e bc 00 08 00 82 ; mover_sprite_0e (SPRITE_OFFICER_HEAD) &3d5f 00 00 02 54 bc a9 bc ac 54 00 08 bc b9 b3 b9 96 &3d6f a9 9c 8c 6c 94 00 0c bc 76 b3 be bc 96 a9 9c 5e &3d7f bc 00 0c c0 68 40 68 00 06 00 02 00 82 ; mover_sprite_0d (SPRITE_LEGS_SEVEN) &3d8c 00 00 02 bc e9 bc ac 40 00 07 bc 96 6c 4c 40 00 &3d9c 07 bc 69 5c ac 40 00 07 bc 83 96 bc 9c 8c bc 00 &3dac 09 e8 80 68 00 05 00 82 ; mover_sprite_0c (SPRITE_SOLDIER_HEAD) &3db4 00 00 02 94 bc 04 2c bc 94 00 08 bc 5c b9 9c 4c &3dc4 bc 00 08 bc 76 b3 be ac 9c bc 00 09 40 05 28 00 &3dd4 05 00 02 00 82 ; mover_sprite_0b (SPRITE_TORSO_WITH_RIFLE_ZERO) &3dd9 00 00 02 bc 06 2c bc 00 06 bc 8c 9c ac 4c 9c 8c &3de9 00 09 7c 9c 4c bc 9e 8f 00 08 40 a8 bc 8d 73 4f &3df9 94 00 09 c0 94 ad 79 8f bc 00 08 04 00 68 bc 5e &3e09 a8 00 88 ; mover_sprite_0a (SPRITE_LEGS_SIX) &3e0c 00 00 02 bc 69 bc 6c 94 7c ec 00 09 bc 96 7c 5c &3e1c cc 5c 8c 00 09 bc 43 bc 4c ec 5c a8 00 09 bc 96 &3e2c bc 07 28 00 07 00 02 00 82 ; mover_sprite_09 (SPRITE_PLAYER_HEAD) &3e35 00 00 02 94 bc 04 2c bc 94 00 08 bc 8c 9c 6d 9c &3e45 8c bc 00 09 bc 9c bc 9e 8f 9e bc a8 00 0a c0 e8 &3e55 00 04 00 02 00 82 ; mover_sprite_08 (SPRITE_TORSO_WITH_PISTOL_FOUR) &3e5b 00 00 02 bc 6c bc ec bc 00 07 bc 9c b9 b3 b6 9c &3e6b 4c 00 09 bc 73 6d 5c bc 00 07 a8 bc 8f 9e bc 76 &3e7b bc 00 09 80 e8 00 04 00 82 ; mover_sprite_07 (SPRITE_TORSO_WITH_PISTOL_THREE) &3e84 00 c0 04 14 00 05 fc b9 b3 a6 ac bc 00 08 bc 73 &3e94 a7 ad 9c 4c 00 08 bc ad 8f 9e bc 99 b9 bc 00 0a &3ea4 e8 80 a8 bc b6 73 bc 00 09 06 00 04 28 00 06 00 &3eb4 82 ; mover_sprite_06 (SPRITE_TORSO_WITH_PISTOL_TWO) &3eb5 00 c0 04 14 00 05 bc ec 4c ac bc 00 07 bc cc 9c &3ec5 ac 4c 00 07 bc 5c bc 59 9c bc 00 08 c0 68 76 b3 &3ed5 9b 8f ad 94 00 0a 07 00 e8 5e a8 00 07 00 82 ; mover_sprite_05 (SPRITE_TORSO_WITH_PISTOL_ONE) &3ee4 00 00 02 bc 06 2c bc 00 06 bc 8c 9c b9 4c 9c 8c &3ef4 00 09 7c 73 9c bc 9c a8 00 08 80 a8 bc 73 8f bc &3f04 00 08 40 68 bc 9e bc 00 07 00 82 ; mover_sprite_04 (SPRITE_LEGS_FIVE) &3f0f 00 40 94 bc e9 bc 00 07 40 bc 83 96 ac 8c ac 7c &3f1f 00 0a 40 68 7c 5c ac 8c 00 08 54 bc 6c cc 5c 00 &3f2f 07 bc 83 a9 bc 9c bc e8 00 09 a8 bc 56 bc 00 06 &3f3f 00 82 ; mover_sprite_03 (SPRITE_LEGS_FOUR) &3f41 00 94 bc e9 bc 94 00 07 bc 83 96 bc ac 8c 6c 7c &3f51 ac 00 0b 68 04 3c 5c bc 4c 00 08 40 bc 43 bc 8c &3f61 ac 4c 9c 00 0a 40 bc 96 bc a8 bc 5c bc a8 00 0b &3f71 00 02 00 82 ; mover_sprite_02 (SPRITE_LEGS_THREE) &3f75 00 40 94 e9 bc 94 00 07 80 bc 83 96 6c 8c 7c ac &3f85 00 0a 80 e8 bc 9c 8c ac 4c 00 09 54 bc 6c 8c ac &3f95 5c bc 00 09 bc 83 a9 bc 9c bc 68 00 09 a8 bc 56 &3fa5 bc 00 06 00 82 ; mover_sprite_01 (SPRITE_LEGS_TWO) &3faa 00 94 bc e9 bc 94 00 07 bc 83 96 bc ac 8c 6c 7c &3fba ac 00 0b 68 04 3c 9c 04 0c 00 08 40 bc 43 bc 8c &3fca ec 9c 00 09 40 bc 96 bc a8 bc 5c bc a8 00 0b 00 &3fda 02 00 82 ; mover_sprite_00 (SPRITE_LEGS_ONE) &3fdd 00 00 02 07 14 80 94 bc 6c 00 08 bc 43 bc cc 6c &3fed cc 00 08 bc 96 bc e8 bc dc bc a8 00 0a 00 02 00 &3ffd 02 00 82 # &4000 - &4aff is moved to &0900 - &13ff at &5298 ; scenery_sprite_00 (SCENERY_WHITE_GREEN_PILLBOX) &0900 00 fd ec 0c 3d 05 2c bc 40 94 bc 05 2c 07 3d 04 &0910 2c bc 94 00 14 ae 4c 5d 04 3f 04 2e 07 3f ae 4c &0920 bc 94 ac 8c bc 8c dd 05 3f ae dd cc bc bf bd 94 &0930 00 1d 8c 9d 08 3f 5d 04 0c ae ff 9d 4c 7c 5d bc &0940 0f 3e 9c bc 7f bc 00 16 0f 3e dc 04 3e 9c 7c be &0950 bd bc ff ee 8c 5d 07 3f bc ac be bc 00 16 cc 09 &0960 3f ae 08 3f 9d 8c 7c 7f bc bf ae cc 9d 4c ae 04 &0970 3f bc 7f bc 8c 9d bc 00 1b 9d 06 3f ee 04 0c ae &0980 08 3f 7c 7f bc bf 5d 05 3f 9d 04 3f bc 7f bc 7f &0990 bc 00 9a ; scenery_sprite_01 (SCENERY_GREEN_YELLOW_PILLBOX) &0993 00 05 2c 04 2d 10 2c ed 04 2c bc 0f 2c bc c0 bc &09a3 6d 94 00 13 04 1c 04 1e 06 1c 7c 08 1c de 04 1c &09b3 5e 0f 1c bc c0 bc 9e 9c bc 00 17 8c 05 0e 8c ac &09c3 06 0c 5c 4c 4f 8e 8c 8e 06 0c 04 1c 9e 9c bc ac &09d3 8c 9c 4c dc 04 0c bc c0 bc 4c bc 00 22 09 2c bc &09e3 ec bc 0c 2c bc 4c 7c 40 7c 8c 4d 9c 8c bc 8c 9c &09f3 8c ac 9c 4c bc 40 94 bc 4c bc 00 1f 8d 04 0c 5c &0a03 8c ac 9c ac bc 9c ac 4c 7c 6c 7c 04 0c bc 8c 8d &0a13 7c 40 7c 8c 9c 8e 8f 8c ac 04 1c ac 8d 8f ed 04 &0a23 0c bc 00 28 4f 4d 04 0c ac 8c ac 8c 4d 4f bc 8f &0a33 7c 8d bc 04 0c bc 4c 7c 40 7c cc 8e 9e cc 8d 04 &0a43 0f 4e 05 0c bc 00 a3 ; scenery_sprite_02 (SCENERY_LOW_GREEN_YELLOW_PILLBOX) &0a4a 00 ec bc 05 2c 06 2d 05 2c 6d ac 7c ac bc 40 94 &0a5a bc ad bc 6c bc ec bc 80 bc 6c bc ad 94 00 1e dc &0a6a bc 06 1c de 5c fc 9c 5e 5c 7c 8f bc 80 bc 8c bc &0a7a ad 9e 9c ac 04 0c bc 94 bc 4c bc 8f 8e bc 00 21 &0a8a cc bc 4c cd 8f cc ad 9c ac ad 8d bc 8f 8e cc bc &0a9a 8c bc 80 bc 8c bc de dc 5e 05 1c bc 4c bc 00 20 &0aaa cc bc 8d 4f 4e 8f 4c 4f 9c ec 8e 4c 6c 8c bc 8d &0aba fc ac bc 8c ac 9c ac 4f 8e 8c 5c 4c 8d bc ac 9c &0aca bc 00 23 8f 8d 8c bc 9e 07 1c 9e 0b 1c bc 8c fc &0ada 8c bc 6c 8c 8e 9e 9c 4c 7c 4f 8c bc 8c 8e bc 00 &0aea 1e cf bc 8f 8d bc 8d 8c bc 4c bc 4c bc 8e 8f bc &0afa 8e 8c bc 4c bc 8c fc 8c bc 4c ac cc 8d 8f 7c 8e &0b0a 4c bc 4c bc 00 a5 ; scenery_sprite_03 (SCENERY_HELICOPTER) # Not used as scenery ; mover_sprite_11 (SPRITE_HELICOPTER_BODY) &0b10 00 0e 00 a8 bc 6c bc ec bc a8 00 0b bc 0f 00 bc &0b20 8c bc 8c 9c a8 00 0b bc a8 94 04 00 04 14 bc 04 &0b30 2c 4c bc 8c bc 00 10 bc 40 a8 54 bc 8f bc 4f bc &0b40 78 9c cc bc 8c bc 00 11 bc c0 bc 8c bc 8f bc ad &0b50 9e b8 f0 f8 bc 9c bc 00 11 bc e8 bc 4c ac bc 8f &0b60 bc 07 30 bc 9e bc 00 0f a8 94 c0 bc 4c bc 8f bc &0b70 06 30 bf bc 8f bc 00 10 94 04 00 7c ac bc 9e bc &0b80 b4 f0 b5 ba b4 68 00 10 bc 40 94 a8 80 bc 8c bc &0b90 9e 7c b0 b5 ba b4 a8 00 11 bc 94 a8 c0 bc 8c bc &0ba0 4c bc b0 b4 a8 00 0e bc 05 00 bc 8c bc 8c 9c 68 &0bb0 00 0b a8 94 05 00 a8 bc 9c a8 00 8a be 68 be bc &0bc0 be a8 04 00 a8 be a8 00 8e ; scenery_sprite_04 (SCENERY_MOUNTAINS_ONE) &0bc9 00 0f 00 68 54 19 00 54 68 80 94 bd 0f 3f 7d 54 &0bd9 00 11 13 00 a8 94 13 00 54 68 06 00 7c 7d 0f 3f &0be9 be a8 00 12 15 00 a8 54 0e 00 94 a8 08 00 94 bd &0bf9 0b 3f be 05 3f be bc 00 15 18 00 68 54 08 00 94 &0c09 a8 0a 00 a8 7e 0a 3f bd be 7f be bd 7f bd 94 00 &0c19 18 1c 00 a8 54 40 94 68 0e 00 a8 fe 08 3f bd be &0c29 bd 06 3f bc 00 15 1f 00 a8 94 a8 11 00 54 95 bd &0c39 08 3f bd be 05 3f be a8 00 14 e8 d4 0e 00 94 a8 &0c49 0a 00 a8 94 0f 00 94 bd 0e 3f bd 7e bf be a8 00 &0c59 17 06 00 68 94 08 00 54 a8 0d 00 a8 0e 00 a8 7e &0c69 11 3f 7d 94 00 15 08 00 a8 94 04 00 94 68 20 00 &0c79 a8 be 14 3f bc 00 11 0a 00 68 94 a8 1d 00 a8 94 &0c89 05 00 94 7d 05 3f 7e fd 07 3f be a8 00 17 0d 00 &0c99 a8 94 1e 00 bc c0 bc 07 3f bd 09 3f 7e a8 00 12 &0ca9 0f 00 bc 1e 00 a8 94 40 bc 0e 3f be a8 00 8f ; scenery_sprite_05 (SCENERY_MOUNTAINS_TWO) &0cb8 00 0e 00 94 a8 13 00 94 0b 00 bc 80 54 bd 0d 3f &0cc8 bc 00 12 0c 00 94 a8 15 00 a8 94 09 00 94 68 be &0cd8 0b 3f be 04 3f bd 54 00 16 0b 00 bc 19 00 a8 54 &0ce8 05 00 94 a8 c0 a8 be 0a 3f bd 7e 04 3f 7d 94 00 &0cf8 18 0a 00 bc 80 a8 54 19 00 68 54 80 a8 94 05 00 &0d08 68 be 0a 3f bd be ff be a8 00 1a 09 00 bc 05 00 &0d18 68 94 1a 00 a8 94 a8 07 00 94 bd 09 3f be bd 7e &0d28 a8 00 18 12 00 a8 94 18 00 bc 07 00 94 bd 08 3f &0d38 be 7d 04 3f bd 94 00 15 14 00 bc 14 00 54 a8 06 &0d48 00 94 bd 0d 3f 7e 04 3f bc 00 13 15 00 a8 94 10 &0d58 00 94 a8 07 00 94 bd 0c 3f be 7d 04 3f be a8 00 &0d68 16 16 00 94 a8 0d 00 94 a8 d4 06 00 a8 be 11 3f &0d78 be a8 00 13 14 00 94 a8 0e 00 94 a8 04 00 e8 94 &0d88 04 00 a8 be 0d 3f be a8 00 16 12 00 94 a8 17 00 &0d98 94 a8 06 00 bc 0a 3f 7e bd bf bd 94 00 14 0f 00 &0da8 94 68 1a 00 68 54 40 bc 0a 3f bd ff be a8 00 92 ; scenery_sprite_06 (SCENERY_TREES_ONE) &0db8 00 1b 00 d4 bc 68 40 54 06 00 94 06 00 94 a8 94 &0dc8 00 11 fc 08 14 07 3c d4 40 d4 bc a8 c0 bc a8 94 &0dd8 bc 40 94 06 00 bc 80 94 e8 80 94 00 1b bc 68 06 &0de8 3c 04 28 c0 04 28 06 3c 68 d4 04 00 a8 40 bc c0 &0df8 94 bc e8 54 68 80 bc 00 1c 94 13 00 a8 94 c0 bc &0e08 80 a8 94 80 94 68 40 94 68 80 bc 94 bc 68 40 54 &0e18 07 00 94 00 1c fc 0d 14 06 00 a8 c0 bc 94 68 07 &0e28 00 54 bc c0 54 bc a8 d4 a8 94 80 94 a8 94 00 1b &0e38 14 3c 05 14 7c 04 00 d4 04 3c a8 04 3c a8 c0 d4 &0e48 80 94 a8 00 15 05 3c e8 bc 54 05 00 04 28 0d 3c &0e58 a8 bc 68 04 00 7c a8 bc 94 a8 c0 a8 00 19 a8 0a &0e68 00 a8 0f 00 a8 7c 0a 00 94 a8 80 a8 94 68 7c 94 &0e78 80 94 a8 94 00 18 1e 00 a8 94 07 00 94 a8 94 80 &0e88 a8 80 a8 04 00 a8 94 00 13 1e 00 a8 80 a8 94 a8 &0e98 94 0c 00 a8 94 a8 80 a8 00 91 ; scenery_sprite_07 (SCENERY_SIGNPOST) &0ea2 00 0c 00 94 bd 94 40 bc fd bc 00 0b 0c 00 bc bf &0eb2 bc 40 bc bf bc bf bc 00 0d bc 10 3d bc bf be bf &0ec2 bc bd bc 00 0c 0c 28 bc bd bc 68 bc bf be bf bc &0ed2 68 00 0e 0c 00 bc be bc 40 bc bf bc bf bc 00 0d &0ee2 11 00 a8 be bf be a8 00 09 13 00 a8 00 85 ; scenery_sprite_08 (SCENERY_RUNWAY) &0ef0 00 bc 4f bc 00 05 bc 4f bc 00 05 bc 4f bc 00 05 &0f00 bc 4f bc 00 05 bc 4f bc 00 05 bc 4f bc 00 05 bc &0f10 4f bc 00 05 bc 4f bc 00 05 bc 4f bc 00 05 bc 4f &0f20 bc 00 05 bc 4f bc 00 05 bc 4f bc 00 85 ; scenery_sprite_09 (SCENERY_GRAVES) &0f2d 00 bc 09 3d d4 00 06 bc 7f be bf bc 04 3f 7e bf &0f3d bd bc 94 00 0e bc 7f bc bf be bf fd 7c bd bf 7c &0f4d 00 0d bc 7f bd bf bd 04 3f fe 68 00 0b 0a 28 bc &0f5d 4f bc 00 07 0b 2d 5e 6d bc 00 07 0a 28 bc 4f bc &0f6d 68 00 08 0a 00 a8 5e a8 00 87 ; scenery_sprite_0a (SCENERY_LOW_RED_BUILDING) &0f77 00 23 00 04 14 bc 69 bc 05 38 bd bc a9 bc 04 14 &0f87 00 11 1e 14 7c e9 04 03 bc 43 08 29 83 bc 04 03 &0f97 e9 7c 00 12 1e 03 7c 07 29 bc 0b 29 bc 07 29 7c &0fa7 94 00 0f 05 29 bc 04 39 bc e9 bc 04 38 7d bc 08 &0fb7 29 7c 07 03 bc 43 08 16 83 bc 43 bc 04 39 fc 00 &0fc7 1e 05 03 bc 04 39 bc c3 bc 05 30 ba bc 08 03 7c &0fd7 07 16 bc 43 bc 04 30 ba bf bc 83 bc 43 bc 04 39 &0fe7 04 3c 00 23 05 03 bc 04 39 bc c3 bc 06 34 bc 08 &0ff7 03 7c 07 03 bc 43 bc 06 30 bc 83 bc 43 05 29 7c &1007 00 9e ; scenery_sprite_0b (SCENERY_GRAVES_WITH_HELMETS) &1009 00 0c 00 94 6d 94 00 07 0c 00 bc 4f bc 80 05 14 &1019 00 0a 0d 2d 5e 6d bc cc 6c 94 00 0a 0c 28 bc 4f &1029 bc 68 bc 8c 5c bc a8 00 0d 0c 00 bc 4f bc 40 e8 &1039 00 09 09 00 d4 80 68 80 54 04 2c 54 00 0c 05 28 &1049 7c d4 fc 94 04 3c 9c 04 0c bc 00 0e 06 00 a8 0b &1059 00 bc 5c bc 68 00 8b ; scenery_sprite_0c (SCENERY_SANDBAGS) &1060 00 6d 7c ed bc 94 00 07 cf ad bc cf bc 6d bc 94 &1070 00 0a de bc ad cf bc cf bc 00 09 cf ad bc 5e bc &1080 ad 4f 9e bc 00 0b 04 0f bc 4f ad bc e8 00 09 de &1090 6d 4f 9e bc 00 07 cf ad bc e8 00 06 de bc a8 00 &10a0 85 ; scenery_sprite_0d (SCENERY_HIGH_RED_BUILDING) &10a1 00 32 03 0b 16 43 06 16 83 fc 00 0b 06 03 bc 0c &10b1 39 bc 05 03 bc 09 2d bc 0e 03 bc 07 30 ba bf bc &10c1 43 bc 04 36 bc 83 7c 00 1d 06 03 bc 0c 36 bc 05 &10d1 03 bc 09 1e bc c3 bc 0a 03 bc 09 30 bc 43 bc 04 &10e1 36 bc 83 04 3c 00 1e 27 16 bc 0a 03 bc 09 34 bc &10f1 43 bc 96 f6 bc 83 04 3c 00 13 0f 03 09 16 0f 03 &1101 bc 1e 16 04 3c 00 0d 0f 03 bc 05 30 7a bc 0f 03 &1111 bc 0c 03 06 16 0c 03 fc 00 13 27 28 bc 0c 03 bc &1121 04 36 bc 0c 03 7c a8 00 0f 27 00 bc 0c 16 bc 04 &1131 36 bc 0c 16 7c 00 8e ; scenery_sprite_0e (SCENERY_HEADQUARTERS_SIGN) &1138 00 07 00 94 07 2d 94 00 08 07 2d bc 8f 6d bc 6d &1148 8f bc 00 0b 07 28 bc 8f 5e bc 5e 8f bc 00 0b 07 &1158 00 bc 8f 9e 05 0f bc 00 0a 07 00 bc 8f 9e ed bc &1168 8f bc 00 0b 07 14 bc 8f 7c 5e bc 8f bc 00 0b 07 &1178 1e bc 8f 9e 05 0f bc 00 0a 07 00 a8 07 1e a8 00 &1188 88 ; scenery_sprite_0f (SCENERY_CONNING_TOWER) &1189 00 25 00 54 ac bc 0b 00 bc 6c 54 00 0c 21 00 54 &1199 6c cc bc 09 38 7d bc 04 0c fc 0c 14 00 11 20 2c &11a9 bc 07 0c bc 0a 30 ba bc 04 0c 7c a8 00 10 20 0c &11b9 bc 07 0c bc 0b 30 bc 04 0c 7c 94 00 0f 20 1c bc &11c9 07 1c 0d 2c 04 1c 04 3c 00 0d 20 0c bc 07 0c bc &11d9 09 38 7d bc 04 0c fc a8 00 10 1a 2d 7c 04 0c bc &11e9 07 0c bc 0b 30 bc 04 0c 7c a8 00 12 1a 0f 7c 04 &11f9 0c bc 07 0c bc 0b 30 bc 04 0c 7c 00 91 ; scenery_sprite_10 (SCENERY_BRIDGE) &1206 00 43 56 43 96 43 a9 43 d6 bc a8 7c 6d fc 00 0f &1216 a9 05 03 56 bc 04 28 54 6d 5e 68 fc 00 0e 96 bc &1226 05 28 40 54 6d 5e 68 04 00 fc 00 0e 09 00 bc 8f &1236 6d 54 06 00 fc 00 0b 09 00 bc 8f bc a8 5e 6d 54 &1246 40 fc 00 0d 09 00 bc 8f bc c0 68 5e 6d fc 00 0c &1256 09 00 bc 8f bc 05 00 54 ad 8f fc 00 0d 09 00 bc &1266 8f bc 80 54 6d 5e 68 fc 00 0d 09 00 bc 8f 6d 5e &1276 68 04 00 fc 00 0c 09 00 bc 8f bc a8 08 00 fc 00 &1286 8b ; scenery_sprite_11 (SCENERY_OIL_DRUM) &1287 00 94 05 00 94 05 00 94 05 00 94 00 0c bc 05 3d &1297 bc 05 3d bc 05 3d bc 00 0c bc bf 4c ae bf bc bf &12a7 4c ae bf bc bf 4c ae bf bc 00 12 bc 04 0c bf bc &12b7 04 0c bf bc 04 0c bf bc 94 00 10 bc 05 0c bc 05 &12c7 0c bc 05 0c bc a8 00 0d bc 05 28 bc 05 28 bc 05 &12d7 28 bc 00 8c ; scenery_sprite_12 (SCENERY_LOW_RUINS) &12db 00 bc a9 bc 80 d4 00 07 bc 96 bc 94 bc 83 bc 00 &12eb 09 43 bc 83 bc a9 bc 00 08 43 e9 83 69 bc c0 bc &12fb a9 bc 00 0b 06 03 bc a9 bc e9 bc 83 bc 06 29 bc &130b a9 bc 00 10 06 03 bc 96 bc 0b 28 7c 96 bc 00 0c &131b bc a9 bc d6 43 bc 0b 00 7c 83 bc 00 0d bc 96 7c &132b 83 bc 43 bc 0b 00 7c 96 bc 00 0e bc 83 bc e9 43 &133b 69 bc 94 bc 08 29 bc 83 bc 00 10 e9 08 03 d6 bc &134b a8 bc 56 bc a9 bc 96 bc 00 0f bc a9 bc 83 bc a8 &135b bc 83 d6 bc 07 00 bc 96 bc 00 11 bc 96 bc 68 80 &136b e8 00 88 ; mover_sprite_33 (SPRITE_MORTAR) &136e 00 00 02 00 02 00 02 94 95 94 00 05 bc 8f be bc &137e 6f 55 54 00 09 bc 9e e8 de be af 7d 54 00 0a c0 &138e 54 6d 7e bc 9e 8f 6f 7d 94 00 0c 94 6d 5e 68 04 &139e 00 68 5e a8 00 0b 80 68 00 04 00 82 ; mover_sprite_34 (SPRITE_MORTAR_OR_MACHINE_GUN_SOLDIER) &13aa 00 07 00 05 14 00 06 54 69 54 bc ac 8c 9c ac 8c &13ba 6c 94 00 0d bc 83 96 ac 8c ac 9c 4c bc 8c 9c ac &13ca 4c ac 94 04 2c 94 00 14 04 28 5c 8c 9c 68 bc 4c &13da 9c 7c 4c 5c 4c bc 00 10 06 00 68 40 a8 9c 99 b9 &13ea 94 a8 9c 7c 8c 9c a8 00 11 0b 00 a8 62 a8 c0 68 &13fa 00 09 00 02 00 02 # Continued at start of binary ; unused # Source code fragment corresponding to &3338 - &336b &4b00 35 20 20 0d ; ... 5 &4b04 0a a0 1e 80 28 26 43 45 29 2c 59 3a 82 26 43 36 ; 2720AND(&CE),Y:EOR&C6:STA(&CE),Y &4b14 3a 53 54 41 28 26 43 45 29 2c 59 20 20 0d &4b22 0a aa 11 44 45 59 3a 42 50 4c 70 6c 6f 6f 70 31 ; 2730DEY:BPLploop1 &4b32 0d &4b33 0a b4 21 4c 44 41 26 43 35 3a 82 23 32 35 35 3a ; 2740LDA&C5:EOR#255:STA&C5:BPLpok2 &4b43 53 54 41 26 43 35 3a 42 50 4c 70 6f 6b 32 20 20 &4b53 0d &4b54 0a be 1c 53 54 58 26 43 44 3a 4c 44 58 26 43 46 ; 2750STX&CD:LDX&CF:LDA&CE:INY &4b64 3a 4c 44 41 26 43 45 3a 49 4e 59 0d &4b70 0a c8 24 4a 53 52 61 64 64 69 74 69 6f 6e 3a 53 ; 2760JSRaddition:STX&CF:STA&CE:LDX&CD &4b80 54 58 26 43 46 3a 53 54 41 26 43 45 3a 4c 44 58 &4b90 26 43 44 0d &4b94 0a d2 21 2e 70 6f 6b 32 20 49 4e 58 3a 43 50 58 ; 2770.pok2 INX:CPX&C8:BNEploop &4ba4 26 43 38 3a 42 4e 45 70 6c 6f 6f 70 20 20 20 20 &4bb4 0d &4bb5 0a dc 07 52 54 53 0d ; 2780RTS &4bbc 0a e6 05 20 0d ; 2790 &4bc1 0a f0 05 20 0d ; 2800 &4bc6 0a fa 24 2e 70 72 73 74 72 69 6e 67 20 53 54 58 ; 2810.prstring STX&C3:STY&C2:JSRsetsc &4bd6 26 43 33 3a 53 54 59 26 43 32 3a 4a 53 52 73 65 &4be6 74 73 63 0d &4bea 0b 04 1e 4a 53 52 63 6c 65 61 72 3a 2e 70 72 73 ; 2820JSRclear:.prst2 LDA ... &4bfa 74 32 20 4c 44 41 # &4c00 - &4fff is moved to &0400 - &07ff at &5267 ; flipped_green_pixel_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f &0400 00 02 01 03 08 0a 09 0b 04 06 05 07 0c 0e 0d 0f ; &00 : KK RK KR RR GK YK GR YR KG RG KY RY GG YG GY YY &0410 20 22 21 23 28 2a 29 2b 24 26 25 27 2c 2e 2d 2f ; &10 : BK MK BR MR CK WK CR WR BG MG BY MY CG WG CY WY &0420 10 12 11 13 18 1a 19 1b 14 16 15 17 1c 1e 1d 1f ; &20 : KB RB KM RM GB YB GM YM KC RC KW RW GC YC GW YW &0430 30 32 31 33 38 3a 39 3b 34 36 35 37 3c 3e 3d 3f ; &30 : BB MB BM MM CB WB CM WM BC MC BW MW CC WC CW WW ; unflipped_green_pixel_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f &0440 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ; &00 : KK KR RK RR KG KY RG RY GK GR YK YR GG GY YG YY &0450 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ; &10 : KB KM RB RM KC KW RC RW GB GM YB YM GC GW YC YW &0460 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f ; &20 : BK BR MK MR BG BY MG MY CK CR WK WR CG CY WG WY &0470 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f ; &30 : BB BM MB MM BC BW MC MW CB CM WB WM CC CW WC WW ; flipped_mask_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &0480 ff 55 aa 00 55 55 00 00 aa 00 aa 00 00 00 00 00 ; &00 &0490 55 55 00 00 55 55 00 00 00 00 00 00 00 00 00 00 ; &10 &04a0 aa 00 aa 00 00 00 00 00 aa 00 aa 00 00 00 00 00 ; &20 &04b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &30 ; unflipped_mask_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &04c0 ff aa 55 00 aa aa 00 00 55 00 55 00 00 00 00 00 ; &00 &04d0 aa aa 00 00 aa aa 00 00 00 00 00 00 00 00 00 00 ; &10 &04e0 55 00 55 00 00 00 00 00 55 00 55 00 00 00 00 00 ; &20 &04f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &30 ; flipped_white_pixel_table # Uses white in place of green ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f &0500 00 02 01 03 2a 0a 2b 0b 15 17 05 07 3f 1f 2f 0f ; &00 : KK RK KR RR WK YK WR YR KW RW KY RY WW YW WY YY &0510 20 22 21 23 28 2a 29 2b 35 37 25 27 3d 3f 2d 2f ; &10 : BK MK BR MR CK WK CR WR BW MW BY MY CW WW CY WY &0520 10 12 11 13 3a 1a 3b 1b 14 16 15 17 3e 1e 3f 1f ; &20 : KB RB KM RM WB YB WM YM KC RC KW RW WC YC WW YW &0530 30 32 31 33 38 3a 39 3b 34 36 35 37 3c 3e 3d 3f ; &30 : BB MB BM MM CB WB CM WM BC MC BW MW CC WC CW WW ; unflipped_white_pixel_table # Uses white in place of green ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f &0540 00 01 02 03 15 05 17 07 2a 2b 0a 0b 3f 2f 1f 0f ; &00 : KK KR RK RR KW KY RW RY WK WR YK YR WW WY YW YY &0550 10 11 12 13 14 15 16 17 3a 3b 1a 1b 3e 3f 1e 1f ; &10 : KB KM RB RM KC KW RC RW WB WM YB YM WC WW YC YW &0560 20 21 22 23 35 25 37 27 28 29 2a 2b 3d 2d 3f 2f ; &20 : BK BR MK MR BW BY MW MY CK CR WK WR CW CY WW WY &0570 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f ; &30 : BB BM MB MM BC BW MC MW CB CM WB WM CC CW WC WW ; scenery_sprite_13 (SCENERY_WHITE_GREEN_PILLBOX_WITH_SKULL) &0580 00 06 2c 06 3d 6c 0c 3d 07 2c 0b 3d ec 7d 04 2c &0590 fd 06 2c bc c0 bc bd bc 94 00 1a 07 2c 04 3d 07 &05a0 2c 0a 3d 04 2c 08 3d bc 05 3d ac fd ec 05 3d 04 &05b0 2c bc c0 bc ac bc 9c ac 94 00 20 cc 9d ff 04 2e &05c0 bf 9d 8c 7c ac fd 7c 7f ae 8c ae 7f 5d 8c 9d ff &05d0 7e fc 04 2e 4c ae bf 5d cc ae 05 3f 9d 8c bc c0 &05e0 bc 8c bc 8c bd bc 00 2d 8c 9d ff ae 4c 9d 05 3f &05f0 bc bf bd 7e bd ae bc 6e bf 4c 9d 04 3f 7e 04 3c &0600 06 3d bc 9c 4c 04 3f 5d 07 3f 8c bc c0 bc 8c bc &0610 7f bc 00 2c 8c 09 3f ae 4c 9d bc 7f 7c 4c bc 8c &0620 9d bf 9d 7f 7e 06 3c bd 7f be 7c be ff bd be 08 &0630 3f ae 8c ae ff bc d4 bc bf bc 7f bc 00 2a 04 3f &0640 ae bf ae 04 0c 9d 7f bc 7f 7c bf 9d bc 04 3f 07 &0650 3c ff 7e bf bd 07 3f bc 07 3f 05 0c ae 06 3f ae &0660 bc ae bf bc 00 a8 ; scenery_sprite_14 (SCENERY_HIGH_RUINS) &0666 00 69 bc c0 d4 00 06 43 69 bc a9 bc 83 bc 07 29 &0676 bc 08 14 bc a9 bc 04 14 00 13 04 03 bc 96 bc 69 &0686 83 12 16 c3 bc 54 04 00 d4 00 11 0a 03 bc 10 00 &0696 bc 05 03 bc 04 14 bc 83 bc d4 00 11 0a 03 bc 10 &06a6 00 bc a9 bc 08 03 e9 43 bc 04 14 00 11 c3 bc a9 &06b6 bc 04 03 bc 10 00 bc 96 7c a9 bc 0e 03 bc 00 13 &06c6 c3 bc 96 bc 04 03 bc 10 00 bc 43 bc 96 bc 43 bc &06d6 0c 28 00 14 0a 03 bc 10 14 bc 07 03 bc 00 0b 06 &06e6 03 bc a9 bc 83 12 16 06 03 7c 08 14 00 0f 06 03 &06f6 bc 96 bc 68 10 00 bc c3 bc e8 00 0e 08 03 bc 54 &0706 10 00 bc d6 bc 00 0b 04 16 bc a8 bc d6 bc 00 89 ; scenery_sprite_15 (SCENERY_TREES_TWO) &0716 00 fc 05 14 08 3c d4 04 3c 54 06 00 94 c0 94 09 &0726 00 54 0d 00 d4 bc 68 00 18 1b 3c 94 bc 54 bc 54 &0736 bc 94 fc 54 bc e8 94 0b 00 54 bc a8 c0 a8 94 00 &0746 18 05 3c 05 28 bc 94 80 94 40 68 bc 04 00 68 0a &0756 3c 08 28 c0 a8 07 00 54 bc a8 00 1b bc 68 07 00 &0766 94 80 a8 c0 94 a8 94 08 00 a8 80 a8 80 06 14 08 &0776 3c 54 80 54 fc 68 7c 94 00 1e bc 94 fc d4 7c 54 &0786 05 3c 04 14 80 94 bc 04 14 09 3c 05 28 bc a8 07 &0796 3c 94 04 00 68 bc 68 94 c0 94 00 22 0d 3c 04 28 &07a6 0e 3c 68 04 00 a8 04 00 bc 94 40 e8 bc 68 bc 94 &07b6 05 00 a8 94 80 a8 94 a8 80 a8 00 20 7c a8 04 00 &07c6 04 28 09 00 68 05 00 68 bc 94 04 00 94 a8 06 00 &07d6 bc 94 08 00 a8 bc 94 05 00 a8 40 a8 94 00 23 a8 &07e6 1d 00 68 54 a8 80 a8 05 00 a8 80 a8 bc 09 00 68 &07f6 94 a8 07 00 a8 94 a8 00 9a ; unused &07ff 45 # &5000 - &507f is moved to &0880 - &08ff at &52a1 ; sound_data ; chan vol pitch dur &0880 10 00 f1 ff 07 00 07 00 ; &00 # Explosion solider or helicopter, exploding grenade &0888 11 00 01 00 c8 00 07 00 ; &08 # Exploding soldier, exploding grenade &0890 11 00 04 00 c8 00 07 00 ; &10 # Exploding helicopter &0898 13 00 02 00 a0 00 1e 00 ; &18 # Firing grenade &08a0 12 00 02 00 78 00 0a 00 ; &20 # Firing bullet &08a8 12 00 03 00 05 00 05 00 ; &28 # Player landing &08b0 13 00 02 00 37 00 05 00 ; &30 # Player jumping &08b8 10 00 f1 ff 06 00 03 00 ; &38 # Exploding grenade ; OS envelope storage &08c0 01 fe 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 ; 1 &08d0 01 ff 00 00 ff 00 00 3c ff ff fd 7e 64 00 00 00 ; 2 &08e0 01 02 00 00 ff 00 00 7f fe 00 f6 7e 64 00 00 00 ; 3 &08f0 02 02 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 ; 4 # &5080 - &50f3 is moved to &0004 - &0077 at &527f ; unpack_column_of_sprite &0004 b9 ff ff LDA &ffff,Y # actually LDA mover_sprite_address,Y &0007 aa TAX &0008 f0 61 BEQ &006b ; end_of_column # &00 indicates end of column &000a 10 11 BPL &001d ; is_positive ; is_negative &000c 0a ASL A &000d 10 07 BPL &0016 ; is_run_length_1 ; is_run_length_3 &000f 8a TXA # 11 ...... run length 3 &0010 29 3f AND #&3f &0012 a2 03 LDX #&03 &0014 d0 14 BNE &002a ; unpack_run # Always branches ; is_run_length_1 &0016 8a TXA # 10 ...... run length 1 &0017 29 3f AND #&3f &0019 a2 01 LDX #&01 &001b d0 0d BNE &002a ; unpack_run # Always branches ; is_positive &001d 0a ASL A &001e 10 07 BPL &0027 ; get_next_byte_of_sprite_data ; is_run_length_2 &0020 8a TXA # 01 ...... run length 2 &0021 29 3f AND #&3f &0023 a2 02 LDX #&02 &0025 d0 03 BNE &002a ; unpack_run # Always branches ; is_variable_run_length &0027 c8 INY # 00 ...... use next byte for run length &0028 b1 05 LDA (&05),Y ; sprite_address ; unpack_run &002a c8 INY &002b 84 cd STY &cd ; sprite_data_offset &002d a8 TAY &002e b1 b8 LDA (&b8),Y ; pixel_table_address &0030 85 3d STA &3d ; sprite_byte ; mask_table_lookup_opcode &0032 b1 c8 LDA (&c8),Y ; mask_table_address # also LDA #&ff &0034 85 3b STA &3b ; sprite_mask &0036 a0 00 LDY #&00 ; unpack_run_loop &0038 b1 3f LDA (&3f),Y ; column_screen_address &003a 29 ff AND #&ff # actually AND sprite_mask &003c 49 ff EOR #&ff # actually EOR sprite_byte &003e 8d ee ee STA &eeee # actually STA column_screen_address &0041 a5 3f LDA &3f ; column_screen_address_low &0043 29 07 AND #&07 &0045 f0 09 BEQ &0050 ; move_up_a_group &0047 c6 3f DEC &3f ; column_screen_address_low # Move up a row ; next_byte_of_run &0049 ca DEX &004a d0 ec BNE &0038 ; unpack_run_loop &004c a4 cd LDY &cd ; sprite_data_offset &004e d0 b4 BNE &0004 ; unpack_column_of_sprite ; move_up_a_group &0050 c6 40 DEC &40 ; column_screen_address_high # Move up a group &0052 c6 40 DEC &40 ; column_screen_address_high &0054 a5 3f LDA &3f ; column_screen_address_low &0056 38 SEC &0057 e9 79 SBC #&79 &0059 85 3f STA &3f ; column_screen_address_low &005b b0 02 BCS &005f ; skip_page &005d c6 40 DEC &40 ; column_screen_address_high ; skip_page &005f a5 40 LDA &40 ; column_screen_address_high &0061 c9 40 CMP #&40 &0063 b0 e4 BCS &0049 ; next_byte_of_run &0065 69 40 ADC #&40 &0067 85 40 STA &40 ; column_screen_address_high &0069 d0 de BNE &0049 ; next_byte_of_run # Always branches ; end_of_column &006b c8 INY &006c b1 05 LDA (&05),Y ; sprite_address &006e 30 03 BMI &0073 ; consider_next_column ; to_consider_plotting_next_column_of_mover &0070 4c 8a 21 JMP &218a ; consider_plotting_next_column_of_mover ; consider_next_column &0073 a5 b8 LDA &b8 ; pixel_table_address_low # Zero if sprite is flipped &0075 f0 f9 BEQ &0070 ; to_consider_plotting_next_column_of_mover &0077 60 RTS ; unused &50f4 00 00 00 00 00 00 00 00 00 00 00 00 # &5100 - &51a9 is moved to &0100 - &01a9 at &52ac ; scenery_sprite_16 (SCENERY_RED_BUILDING_WITH_DOOR) &0100 00 04 29 bc 06 39 bc 14 29 bc 0b 39 bc 05 29 bc &0110 06 38 7d bc 0a 29 7c 00 18 04 03 bc 06 36 bc 14 &0120 03 0d 29 05 03 bc 08 34 bc 0a 03 7c 00 15 3f 16 &0130 07 16 7c 00 07 1c 16 04 03 0f 16 c3 0a 16 0a 03 &0140 7c 00 0e 1a 0f 7c 04 03 bc 0d 33 bc c3 bc 06 30 &0150 ba bf bc 04 03 bc 04 39 fc 00 18 1a 0f 7c 04 03 &0160 bc 09 39 bc 04 29 c3 bc 08 30 bc 04 03 bc 04 39 &0170 fc 00 18 0f 0f 5e 09 0f 7c 04 03 bc 09 33 bc 07 &0180 03 bc 08 30 bc 04 03 bc 04 39 fc 00 1a 1a 1e 7c &0190 04 03 bc 09 36 bc 07 03 bc 08 34 bc 04 03 06 29 &01a0 7c 00 16 3f 03 07 03 7c 00 87 ; unused &51aa 00 00 00 00 00 00 ; initialise_game_screen &51b0 a9 06 LDA #&06 ; R6: Vertical displayed register &51b2 8d 00 fe STA &fe00 ; video register number &51b5 a9 19 LDA #&19 &51b7 8d 01 fe STA &fe01 ; video register value &51ba a9 07 LDA #&07 ; R7: Vertical sync position &51bc 8d 00 fe STA &fe00 ; video register number &51bf a9 20 LDA #&20 &51c1 8d 01 fe STA &fe01 ; video register value &51c4 a9 0f LDA #&0f &51c6 8d 42 fe STA &fe42 ; System VIA data direction register B &51c9 a9 04 LDA #&04 # Set B4 = 0 &51cb 8d 40 fe STA &fe40 ; System VIA port B input/output register &51ce a9 05 LDA #&05 # Set B5 = 0, i.e. scroll from &4000 &51d0 8d 40 fe STA &fe40 ; System VIA port B input/output register &51d3 a9 0a LDA #&0a ; Set second colour duration &51d5 a2 00 LDX #&00 # Disable flashing colours &51d7 20 f4 ff JSR &fff4 ; OSBYTE &51da a9 9a LDA #&9a ; Write to Video ULA control register and RAM copy &51dc a2 14 LDX #&14 # Use settings for MODE 2, disabling cursor &51de 20 f4 ff JSR &fff4 ; OSBYTE &51e1 a9 0c LDA #&0c ; R12: Displayed screen start address register (high) &51e3 8d 00 fe STA &fe00 ; video register number &51e6 a9 08 LDA #&08 # Set screen start address to &4000 &51e8 8d 01 fe STA &fe01 ; video register value &51eb a9 f7 LDA #&f7 # Set colour 15 to black &51ed 8d 21 fe STA &fe21 ; video ULA palette register &51f0 a9 80 LDA #&80 # Set colour 8 to white &51f2 8d 21 fe STA &fe21 ; video ULA palette register &51f5 a9 97 LDA #&97 # Set colour 9 to black &51f7 8d 21 fe STA &fe21 ; video ULA palette register &51fa a9 67 LDA #&67 # Set colour 6 to black &51fc 8d 21 fe STA &fe21 ; video ULA palette register &51ff a9 47 LDA #&47 &5201 85 9c STA &9c ; unused # Unused variable &5203 ad 04 02 LDA &0204 ; irq1_vector_low &5206 8d ad 2f STA &2fad ; previous_irq1_vector_low &5209 ad 05 02 LDA &0205 ; irq1_vector_high &520c 8d ae 2f STA &2fae ; previous_irq1_vector_high &520f 78 SEI &5210 a9 55 LDA #&55 ; &2f55 = irq1_handler &5212 8d 04 02 STA &0204 ; irq1_vector_low &5215 a9 2f LDA #&2f &5217 8d 05 02 STA &0205 ; irq1_vector_high &521a 58 CLI &521b a9 02 LDA #&02 # Disable v-sync interrupt &521d 8d 4e fe STA &fe4e ; System VIA interrupt enable register ; wait_for_vsync &5220 2c 4d fe BIT &fe4d ; System VIA interrupt flag register &5223 f0 fb BEQ &5220 ; wait_for_vsync &5225 ad 6b fe LDA &fe6b ; User VIA auxiliary control register &5228 29 df AND #&df # Set User VIA timer 2 to one-shot mode &522a 8d 6b fe STA &fe6b ; User VIA auxiliary control register &522d a9 20 LDA #&20 # Enable User VIA timer 2 interrupts &522f 8d 6e fe STA &fe6e ; User VIA interrupt enable register &5232 a9 ff LDA #&ff &5234 8d 68 fe STA &fe68 ; User VIA timer 2 counter LSB &5237 8d 69 fe STA &fe69 ; User VIA timer 2 counter MSB &523a a9 82 LDA #&82 # Enable v-sync interrupts &523c 8d 4e fe STA &fe4e ; System VIA interrupt enable register &523f ad 6b fe LDA &fe6b ; User VIA auxiliary control register &5242 29 3f AND #&3f # Set User VIA timer 1 to one-shot mode &5244 8d 6b fe STA &fe6b ; User VIA auxiliary control register &5247 a9 c0 LDA #&c0 # Enable User VIA timer 1 interrupts &5249 8d 6e fe STA &fe6e ; User VIA interrupt enable register &524c a9 90 LDA #&90 &524e 8d 64 fe STA &fe64 ; User VIA timer 1 counter LSB &5251 a9 29 LDA #&29 &5253 8d 65 fe STA &fe65 ; User VIA timer 1 counter MSB &5256 a9 01 LDA #&01 # Set colour 0 to cyan &5258 8d 21 fe STA &fe21 ; video ULA palette register &525b a9 06 LDA #&06 ; FRAME_SHOOTING &525d 85 a0 STA &a0 ; firing_frame &525f 4c 29 24 JMP &2429 ; start_game ; move_memory_and_start_game &5262 a2 ff LDX #&ff &5264 9a TXS &5265 a2 00 LDX #&00 ; move_4c00_to_4fff_loop # Move &4c00 - &4fff to &0400 - &07ff &5267 bd 00 4c LDA &4c00,X # actually LDA source_one_address,X &526a 9d 00 04 STA &0400,X # actually STA target_one_address,X &526d e8 INX &526e d0 f7 BNE &5267 ; move_4c00_to_4fff_loop &5270 ee 69 52 INC &5269 ; source_one_address_high &5273 ee 6c 52 INC &526c ; target_one_address_high &5276 ad 69 52 LDA &5269 ; source_one_address_high &5279 c9 50 CMP #&50 &527b d0 ea BNE &5267 ; move_4c00_to_4fff_loop &527d a2 73 LDX #&73 ; move_5080_to_50f3_loop # Move &5080 - &50f3 to &0004 - &0077 &527f bd 80 50 LDA &5080,X ; unrelocated_unpack_column_of_sprite &5282 95 04 STA &04,X ; unpack_column_of_sprite &5284 ca DEX &5285 10 f8 BPL &527f ; move_5080_to_50f3_loop &5287 a2 00 LDX #&00 ; move_4000_to_4aff_loop # Move &4000 - &4aff to &0900 - &13ff &5289 bd 00 40 LDA &4000,X # actually LDA source_two_address,X &528c 9d 00 09 STA &0900,X # actually STA target_two_address,X &528f e8 INX &5290 d0 f7 BNE &5289 ; move_4000_to_4aff_loop &5292 ee 8b 52 INC &528b ; source_two_address_high &5295 ee 8e 52 INC &528e ; target_two_address_high &5298 ad 8b 52 LDA &528b ; source_two_address_high &529b c9 4b CMP #&4b &529d d0 ea BNE &5289 ; move_4000_to_4aff_loop &529f a2 7f LDX #&7f ; move_5000_to_507f_loop # Move &5000 - &507f to &0880 - &08ff &52a1 bd 00 50 LDA &5000,X &52a4 9d 80 08 STA &0880,X &52a7 ca DEX &52a8 10 f7 BPL &52a1 ; move_5000_to_507f_loop &52aa a2 00 LDX #&00 ; move_5100_to_51a9_loop # Move &5100 - &51a9 to &0100 - &01a9 &52ac bd 00 51 LDA &5100,X &52af 9d 00 01 STA &0100,X &52b2 e8 INX &52b3 e0 aa CPX #&aa &52b5 90 f5 BCC &52ac ; move_5100_to_51a9_loop &52b7 a2 ff LDX #&ff &52b9 9a TXS &52ba 4c b0 51 JMP &51b0 ; initialise_game_screen ; title_screen_font_data &52bd 00 fe f2 c2 c2 fe ; &00 : "0" &52c3 00 00 fe f0 00 00 ; &01 : "1" &52c9 00 f2 f2 d2 d2 de ; &02 : "2" &52cf 00 c0 d2 d2 d2 fe ; &03 : "3" &52d5 00 1e 10 fc f0 10 ; &04 : "4" &52db 00 de d2 d2 d2 f2 ; &05 : "5" &52e1 00 fe e8 c8 c8 f8 ; &06 : "6" &52e7 00 02 c2 f2 3e 0e ; &07 : "7" &52ed 00 fe f2 d2 d2 fe ; &08 : "8" &52f3 00 1e 12 12 f2 fe ; &09 : "9" &52f9 00 ff f9 19 19 ff ; &0a : "A" &52ff 00 ff f9 c9 cf f8 ; &0b : "B" &5305 00 ff f1 c1 c1 c0 ; &0c : "C" &530b 00 ff f1 c1 c3 fe ; &0d : "D" &5311 00 ff f9 c9 c9 c0 ; &0e : "E" &5317 00 ff f9 09 09 01 ; &0f : "F" &531d 00 ff f1 c1 cb fa ; &10 : "G" &5323 00 ff f8 08 08 ff ; &11 : "H" &5329 00 c1 ff f9 c1 00 ; &12 : "I" &532f 00 e0 c0 c0 f8 ff ; &13 : "J" &5335 00 ff f8 34 62 c1 ; &14 : "K" &533b 00 ff f8 c0 c0 c0 ; &15 : "L" &5341 00 ff f3 06 03 ff ; &16 : "M" &5347 00 ff f9 01 01 ff ; &17 : "N" &534d 00 ff f9 c1 c1 ff ; &18 : "O" &5353 00 ff f9 09 09 0f ; &19 : "P" &5359 00 ff f9 c1 61 bf ; &1a : "Q" &535f 00 ff f9 09 39 cf ; &1b : "R" &5365 00 cf c9 c9 c9 f9 ; &1c : "S" &536b 00 03 f3 ff 03 03 ; &1d : "T" &5371 00 ff f8 c0 c0 ff ; &1e : "U" &5377 00 3f 78 e0 60 3f ; &1f : "V" &537d 00 7f f8 20 e0 7f ; &20 : "W" &5383 00 e7 3c 18 3c e7 ; &21 : "X" &5389 00 3f 3c f0 30 3f ; &22 : "Y" &538f 00 f1 d9 cd c7 c3 ; &23 : "Z" &5395 34 34 34 34 34 34 ; &24 : "=" &539b 00 00 00 00 00 00 ; &25 : " " &53a1 7e c3 bd a5 c3 7e ; &26 : "(c)" &53a7 00 00 c0 c0 00 00 ; &27 : "." &53ad 00 18 18 18 18 18 ; &28 : "-" &53b3 00 30 18 0c 18 30 ; &29 : "^" &53b9 00 06 0c 18 30 60 ; &2a : "\" &53bf 00 6e f3 d9 cd 7e ; &2b : "@" &53c5 00 ff c1 c1 c1 c1 ; &2c : "[" &53cb c0 c0 c0 c0 c0 c0 ; &2d : "_" &53d1 00 00 36 76 00 00 ; &2e : ";" &53d7 00 00 34 34 00 00 ; &2f : ":" &53dd 00 c1 c1 c1 c1 ff ; &30 : "]" &53e3 00 00 30 70 00 00 ; &31 : "," &53e9 00 60 30 18 0c 06 ; &32 : "/" ; plot_title_screen_character # Called with X = character &53ef 85 cd STA &cd ; text_pixel &53f1 a9 06 LDA #&06 &53f3 20 96 54 JSR &5496 ; multiply_A_by_X &53f6 a5 c5 LDA &c5 ; result_low &53f8 a4 c6 LDY &c6 ; result_high &53fa 18 CLC &53fb 69 bd ADC #&bd ; &52bd = title_screen_font_data &53fd 90 01 BCC &5400 ; skip_page &53ff c8 INY ; skip_page &5400 8d 0d 54 STA &540d ; font_address_low &5403 98 TYA &5404 18 CLC &5405 69 52 ADC #&52 &5407 8d 0e 54 STA &540e ; font_address_high &540a a2 00 LDX #&00 ; plot_title_screen_character_column_loop &540c bd b9 16 LDA &16b9,X # actually LDA font_address,X &540f 85 cb STA &cb ; font_byte &5411 a0 07 LDY #&07 ; plot_title_screen_character_row_loop &5413 a9 00 LDA #&00 &5415 26 cb ROL &cb ; font_byte &5417 90 04 BCC &541d ; set_pixel_value &5419 a9 03 LDA #&03 # actually LDA text_colour &541b 25 cd AND &cd ; text_pixel ; set_pixel_value &541d 85 ca STA &ca ; pixel_value &541f a5 cd LDA &cd ; text_pixel &5421 49 ff EOR #&ff &5423 31 ce AND (&ce),Y ; text_screen_address &5425 45 ca EOR &ca ; pixel_value &5427 91 ce STA (&ce),Y ; text_screen_address &5429 88 DEY &542a 10 e7 BPL &5413 ; plot_title_screen_character_row_loop &542c a5 cd LDA &cd ; text_pixel &542e 49 ff EOR #&ff &5430 85 cd STA &cd ; text_pixel &5432 10 0b BPL &543f ; not_next_byte &5434 a5 ce LDA &ce ; text_screen_address_low &5436 18 CLC &5437 69 08 ADC #&08 &5439 85 ce STA &ce ; text_screen_address_low &543b 90 02 BCC &543f ; skip_page &543d e6 cf INC &cf ; text_screen_address_high ; skip_page ; not_next_byte &543f e8 INX &5440 e0 06 CPX #&06 &5442 d0 c8 BNE &540c ; plot_title_screen_character_column_loop &5444 60 RTS ; clear_title_screen &5445 a9 13 LDA #&13 ; Wait for vertical retrace &5447 20 f4 ff JSR &fff4 ; OSBYTE &544a a9 5a LDA #&5a &544c 8d 55 54 STA &5455 ; wipe_address_high &544f a2 00 LDX #&00 &5451 a9 00 LDA #&00 ; clear_title_screen_loop &5453 9d 80 5a STA &5a80,X # Wipe &5a80 - &807f # actually STA wipe_address,X &5456 e8 INX &5457 d0 fa BNE &5453 ; clear_title_screen_loop &5459 ee 55 54 INC &5455 ; wipe_address_high &545c 10 f5 BPL &5453 ; clear_title_screen_loop &545e 60 RTS ; plot_title_screen_text &545f 86 c3 STX &c3 ; text_address_high &5461 84 c2 STY &c2 ; text_address_low &5463 20 45 54 JSR &5445 ; clear_title_screen &5466 a0 00 LDY #&00 ; plot_title_screen_text_loop &5468 b1 c2 LDA (&c2),Y ; text_address # Get two bytes for screen address &546a 85 ce STA &ce ; text_screen_address_low &546c c8 INY &546d b1 c2 LDA (&c2),Y ; text_address &546f 85 cf STA &cf ; text_screen_address_high &5471 c8 INY &5472 b1 c2 LDA (&c2),Y ; text_address # Get byte for colour &5474 8d 1a 54 STA &541a ; text_colour &5477 a9 aa LDA #&aa &5479 85 cd STA &cd ; text_pixel &547b 20 84 54 JSR &5484 ; plot_title_screen_text_string_loop &547e c8 INY &547f c9 ff CMP #&ff # &ff indicates end of text &5481 d0 e5 BNE &5468 ; plot_title_screen_text_loop &5483 60 RTS ; plot_title_screen_text_string_loop &5484 c8 INY &5485 b1 c2 LDA (&c2),Y ; text_screen_address_high # Get byte for character &5487 10 01 BPL &548a ; not_end_of_string # &fe indicates end of string, &ff end of text &5489 60 RTS ; not_end_of_string &548a 84 c1 STY &c1 ; text_offset &548c aa TAX &548d a5 cd LDA &cd ; text_pixel &548f 20 ef 53 JSR &53ef ; plot_title_screen_character &5492 a4 c1 LDY &c1 ; text_offset &5494 d0 ee BNE &5484 ; plot_title_screen_text_string_loop # Always branches ; multiply_A_by_X &5496 85 c7 STA &c7 ; multiplicand &5498 86 c8 STX &c8 ; multiplier_low &549a a9 00 LDA #&00 &549c 85 c5 STA &c5 ; result_low &549e 85 c6 STA &c6 ; result_high &54a0 85 c9 STA &c9 ; multiplier_high &54a2 a0 08 LDY #&08 ; multiply_A_by_X_loop &54a4 46 c7 LSR &c7 ; multiplicand &54a6 90 0d BCC &54b5 ; consider_next_bit &54a8 18 CLC &54a9 a5 c8 LDA &c8 ; multiplier &54ab 65 c5 ADC &c5 ; result_low &54ad 85 c5 STA &c5 ; result_low &54af a5 c9 LDA &c9 ; multiplier_high &54b1 65 c6 ADC &c6 ; result_high &54b3 85 c6 STA &c6 ; result_high ; consider_next_bit &54b5 06 c8 ASL &c8 ; multiplier_low &54b7 26 c9 ROL &c9 ; multiplier_high &54b9 88 DEY &54ba d0 e8 BNE &54a4 ; multiply_A_by_X_loop &54bc 60 RTS ; define_controls &54bd a2 00 LDX #&00 &54bf 86 c0 STX &c0 ; key_offset &54c1 e8 INX &54c2 86 03 STX &03 ; unused # Unused variable &54c4 a2 56 LDX #&56 ; &56ed = define_controls_text &54c6 a0 ed LDY #&ed &54c8 20 5f 54 JSR &545f ; plot_title_screen_text # Clear screen &54cb 84 c1 STY &c1 ; text_offset ; define_controls_loop &54cd a4 c1 LDY &c1 ; text_offset &54cf 20 68 54 JSR &5468 ; plot_title_screen_text_loop # Write next control &54d2 84 c1 STY &c1 ; text_offset &54d4 20 3b 55 JSR &553b ; get_keypress &54d7 a4 c0 LDY &c0 ; key_offset &54d9 c9 70 CMP #&70 ; ESCAPE &54db d0 03 BNE &54e0 ; not_escape &54dd 4c 73 57 JMP &5773 ; title_screen ; not_escape &54e0 85 cc STA &cc ; keycode &54e2 aa TAX &54e3 49 ff EOR #&ff &54e5 99 ee 2f STA &2fee,Y ; keys &54e8 8a TXA ; keycode &54e9 4a LSR A &54ea 4a LSR A &54eb 4a LSR A &54ec 4a LSR A &54ed a2 06 LDX #&06 &54ef 20 96 54 JSR &5496 ; multiply_A_by_X &54f2 a5 cc LDA &cc ; keycode &54f4 38 SEC &54f5 e5 c5 SBC &c5 ; result_low &54f7 aa TAX # X = keycode - ((keycode DIV 16) * 6) &54f8 bd 9d 56 LDA &569d,X ; key_translation_table &54fb 30 20 BMI &551d ; is_long_name &54fd aa TAX &54fe 0a ASL A &54ff 30 07 BMI &5508 ; is_function_key ; is_character # &00 - &32 writes character &5501 a5 cd LDA &cd ; text_pixel &5503 20 ef 53 JSR &53ef ; plot_title_screen_character &5506 f0 29 BEQ &5531 ; finished_writing_key # Always branches ; is_function_key # &40 - &49 writes F followed by number &5508 86 cc STX &cc ; keycode &550a a2 0f LDX #&0f ; "F" &550c a5 cd LDA &cd ; text_pixel &550e 20 ef 53 JSR &53ef ; plot_title_screen_character &5511 a5 cc LDA &cc ; keycode &5513 29 3f AND #&3f &5515 aa TAX &5516 a5 cd LDA &cd ; text_pixel &5518 20 ef 53 JSR &53ef ; plot_title_screen_character &551b f0 14 BEQ &5531 ; finished_writing_key # Always branches ; is_long_name # &80 - &ff writes long character name &551d 29 7f AND #&7f &551f 85 cc STA &cc ; keycode ; write_key_loop &5521 a4 cc LDY &cc ; keycode &5523 be 2a 56 LDX &562a,Y ; key_names &5526 30 09 BMI &5531 ; finished_writing_key &5528 a5 cd LDA &cd ; text_pixel &552a 20 ef 53 JSR &53ef ; plot_title_screen_character &552d e6 cc INC &cc ; keycode &552f d0 f0 BNE &5521 ; write_key_loop ; finished_writing_key &5531 a4 c1 LDY &c1 ; text_offset &5533 e6 c0 INC &c0 ; key_offset &5535 a5 c0 LDA &c0 ; key_offset &5537 c9 08 CMP #&08 &5539 90 92 BCC &54cd ; define_controls_loop ; get_keypress &553b a2 ff LDX #&ff ; SHIFT # Wait for SHIFT, CTRL and other keys to be released &553d 20 68 55 JSR &5568 ; check_for_title_screen_keypress &5540 f0 f9 BEQ &553b ; get_keypress &5542 a2 fe LDX #&fe ; CTRL &5544 20 68 55 JSR &5568 ; check_for_title_screen_keypress &5547 f0 f2 BEQ &553b ; get_keypress &5549 a5 ec LDA &ec ; os_most_recently_pressed_key &554b d0 ee BNE &553b ; get_keypress ; get_keypress_loop &554d a2 ff LDX #&ff ; SHIFT &554f 20 68 55 JSR &5568 ; check_for_title_screen_keypress &5552 d0 03 BNE &5557 ; not_shift &5554 a9 00 LDA #&00 # Return zero to indicate SHIFT pressed &5556 60 RTS ; not_shift &5557 a2 fe LDX #&fe ; CTRL &5559 20 68 55 JSR &5568 ; check_for_title_screen_keypress &555c d0 03 BNE &5561 ; not_ctrl &555e a9 01 LDA #&01 # Return one to indicate CTRL pressed &5560 60 RTS ; not_ctrl &5561 a5 ec LDA &ec ; os_most_recently_pressed_key &5563 f0 e8 BEQ &554d ; get_keypress_loop &5565 29 7f AND #&7f # Return key pressed &5567 60 RTS ; check_for_title_screen_keypress &5568 a0 ff LDY #&ff &556a a9 81 LDA #&81 ; Scan for a particular key &556c 20 f4 ff JSR &fff4 ; OSBYTE &556f e0 ff CPX #&ff &5571 60 RTS ; title_screen_text &5572 28 5b 3e ; at &5b28, colour &3e (WC) &5575 1c 1d 1b 22 14 0e 1b 1c 25 1b 1e 17 ; "STRYKERS RUN" &5581 fe ; end of string &5582 a8 5d 0c ; at &5da8, colour &0c (GG) &5585 24 24 24 24 24 24 24 24 24 24 24 24 ; "============" &5591 fe ; end of string &5592 60 60 0f ; at &6060, colour &0f (YY) &5595 18 19 1d 12 18 17 1c ; "OPTIONS" &559c fe ; end of string &559d 10 65 03 ; at &6510, colour &03 (RR) &55a0 01 25 1c 1d 0a 1b 1d 25 10 0a 16 0e ; "1 START GAME" &55ac fe ; end of string &55ad f0 69 33 ; at &69f0, colour &33 (MM) &55b0 02 25 0d 0e 0f 12 17 0e 25 0c 18 17 1d 1b 18 15 ; "2 DEFINE CONTROLS" &55c0 1c &55c1 fe ; end of string &55c2 d0 6e 30 ; at &6ed0, colour &30 (BB) &55c5 03 25 1b 0e 0a 0d 25 12 17 1c 1d 1b 1e 0c 1d 12 ; "3 READ INSTRUCTIONS" &55d5 18 17 1c &55d8 fe ; end of string &55d9 c0 73 0c ; at &73c0, colour &0c (GG) &55dc 20 1b 12 1d 1d 0e 17 25 0b 22 25 0c 27 1b 18 0b ; "WRITTEN BY C.ROBERTS" &55ec 0e 1b 1d 1c &55f0 fe ; end of string &55f1 98 78 03 ; at &7898, colour &03 (RR) &55f4 10 1b 0a 19 11 12 0c 1c 2f 19 27 16 0e 15 15 0e ; "GRAPHICS:P.MELLER AND C.R" &5604 1b 25 0a 17 0d 25 0c 27 1b &560d fe ; end of string &560e a0 7d 3e ; at &7da0, colour &3e (WC) &5611 26 25 1c 1e 19 0e 1b 12 18 1b 25 1c 18 0f 1d 20 ; "(c) SUPERIOR SOFTWARE 1986" &5621 0a 1b 0e 25 01 09 08 06 &5629 ff ; end of text ; key_names &562a 1c 11 12 0f 1d fe ; &80 : "SHIFT" &5630 0c 1d 1b 15 fe ; &86 : "CTRL" &5635 15 0e 0f 1d 25 0c 1e 1b 1c 18 1b fe ; &8b : "LEFT CURSOR" &5641 0c 0a 19 1c 25 15 18 0c 14 fe ; &97 : "CAPS LOCK" &564b 1b 0e 1d 1e 1b 17 fe ; &a1 : "RETURN" &5652 1c 11 12 0f 1d 25 15 18 0c 14 fe ; &a8 : "SHIFT LOCK" &565d 0d 0e 15 0e 1d 0e fe ; &b3 : "DELETE" &5664 0d 18 20 17 25 0c 1e 1b 1c 18 1b fe ; &ba : "DOWN CURSOR" &5670 1e 19 25 0c 1e 1b 1c 18 1b fe ; &c6 : "UP CURSOR" &567a 1d 0a 0b fe ; &d0 : "TAB" &567e 1c 19 0a 0c 0e fe ; &d4 : "SPACE" &5684 0c 18 19 22 fe ; &da : "COPY" &5689 0e 1c 0c 0a 19 0e fe ; &df : "ESCAPE" &5690 1b 12 10 11 1d 25 0c 1e 1b 1c 18 1b fe ; &e6 : "RIGHT CURSOR" ; key_translation_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &569d 80 86 00 00 00 00 00 00 00 00 1a 03 04 05 44 08 ; &00 &56ad 47 28 29 8b 40 20 0e 1d 07 09 12 00 2d ba 01 02 ; &10 &56bd 0d 1b 06 1e 18 19 2c c6 97 0a 21 0f 22 13 14 2b ; &20 &56cd 2f a1 a8 1c 0c 10 11 17 15 2e 30 b3 d0 23 d4 1f ; &30 &56dd 0b 16 31 27 32 da df 41 42 43 45 46 48 49 2a e6 ; &40 ; define_controls_text &56ed 08 5b 03 ; at &5b08, colour &03 (RR) &56f0 ff ; end of text &56f1 80 5a 0f ; at &5a80, colour &0f (YY) &56f4 13 1e 16 19 32 16 18 1f 0e 25 1e 19 2f 25 ; "JUMP/MOVE UP: " &5702 ff ; end of text &5703 80 5f 0c ; at &5f80, colour &0c (GG) &5706 0d 1e 0c 14 2f 25 ; "DUCK: " &570c ff ; end of text &570d 80 64 33 ; at &6480, colour &33 (MM) &5710 16 18 1f 0e 25 1b 12 10 11 1d 2f 25 ; "MOVE RIGHT: " &571c ff ; end of text &571d 80 69 03 ; at &6980, colour &03 (RR) &5720 16 18 1f 0e 25 15 0e 0f 1d 2f 25 ; "MOVE LEFT: " &572b ff ; end of text &572c 80 6e 3f ; at &6e80, colour &3f (WW) &572f 0f 12 1b 0e 25 15 0a 1c 0e 1b 2f 25 ; "FIRE LASER: " &573b ff ; end of text &573c 80 73 03 ; at &7380, colour &03 (RR) &573f 10 1b 0e 17 0a 0d 0e 32 0b 18 16 0b 2f 25 ; "GRENADE/BOMB: " &574d ff ; end of text &574e 80 78 0c ; at &7880, colour &0c (GG) &5751 0e 17 1d 0e 1b 32 15 0e 0a 1f 0e 2f 25 ; "ENTER/LEAVE: " &575e ff ; end of text &575f 80 7d 3e ; at &7d80, colour &3e (WC) &5762 19 0a 1e 1c 0e 25 10 0a 16 0e 2f 25 ; "PAUSE GAME: " &576e ff ; end of text ; entry_point &576f a9 06 LDA #&06 ; MOVER_TYPE_HELICOPTER &5771 85 a1 STA &a1 ; firing_mover_type ; title_screen &5773 a9 07 LDA #&07 # Set colour 0 to black &5775 8d 21 fe STA &fe21 ; video ULA palette register &5778 a9 61 LDA #&61 # Set colour 6 to cyan &577a 8d 21 fe STA &fe21 ; video ULA palette register &577d a2 55 LDX #&55 ; &5572 = title_screen_text &577f a0 72 LDY #&72 &5781 20 5f 54 JSR &545f ; plot_title_screen_text ; title_screen_loop &5784 20 3b 55 JSR &553b ; get_keypress &5787 c9 30 CMP #&30 &5789 90 0f BCC &579a ; not_one_or_two &578b 38 SEC &578c e9 30 SBC #&30 ; "1" &578e f0 2e BEQ &57be ; to_move_memory_and_start_game &5790 c9 02 CMP #&02 ; "2" &5792 b0 f0 BCS &5784 ; title_screen_loop &5794 20 bd 54 JSR &54bd ; define_controls &5797 4c 73 57 JMP &5773 ; tile_screen ; not_one_or_two &579a c9 11 CMP #&11 ; "3" &579c d0 e6 BNE &5784 ; title_screen_loop ; read_instructions &579e a2 57 LDX #&57 ; &57c1 = instructions_text_one &57a0 a0 c1 LDY #&c1 &57a2 20 5f 54 JSR &545f ; plot_title_screen_text &57a5 20 3b 55 JSR &553b ; get_keypress &57a8 a2 58 LDX #&58 ; &586e = instructions_text_two &57aa a0 6e LDY #&6e &57ac 20 5f 54 JSR &545f ; plot_title_screen_text &57af 20 3b 55 JSR &553b ; get_keypress &57b2 a2 59 LDX #&59 ; &5937 = instructions_text_three &57b4 a0 37 LDY #&37 &57b6 20 5f 54 JSR &545f ; plot_title_screen_text &57b9 20 3b 55 JSR &553b ; get_keypress &57bc d0 b5 BNE &5773 ; title_screen ; to_move_memory_and_start_game &57be 4c 62 52 JMP &5262 ; move_memory_and_start_game ; instructions_text_one &57c1 80 5d 03 ; at &5d80, colour &03 (RR) &57c4 1d 11 0e 25 16 12 1c 1c 12 18 17 2f ; "THE MISSION:" &57d0 fe ; end of string &57d1 00 62 3c ; at &6200, colour &3c (CC) &57d4 0a 25 20 0e 0a 14 17 0e 1c 1c 25 11 0a 1c 25 0b ; "A WEAKNESS HAS BEEN FOUND" &57e4 0e 0e 17 25 0f 18 1e 17 0d &57ed fe ; end of string &57ee 00 67 3c ; at &6700, colour &3c (CC) &57f1 12 17 25 1d 11 0e 25 0e 17 0e 16 22 25 0d 0e 0f ; "IN THE ENEMY DEFENCES." &5801 0e 17 0c 0e 1c 27 &5807 fe ; end of string &5808 00 6c 3c ; at &6c00, colour &3c (CC) &580b 1d 11 12 1c 25 12 17 1d 0e 15 15 12 10 0e 17 0c ; "THIS INTELLIGENCE MUST BE" &581b 0e 25 16 1e 1c 1d 25 0b 0e &5824 fe ; end of string &5825 00 71 3c ; at &7100, colour &3c (CC) &5828 0c 18 17 1f 0e 22 0e 0d 25 1d 18 25 16 0a 12 17 ; "CONVEYED TO THE MAIN H.Q." &5838 25 11 27 1a 27 &583d fe ; end of string &583e 00 76 3c ; at &7600, colour &3c (CC) &5841 12 16 16 0e 0d 12 0a 1d 0e 15 22 27 25 0b 0e 0c ; "IMMEDIATELY. BECAUSE OF" &5851 0a 1e 1c 0e 25 18 0f &5858 fe ; end of string &5859 00 7b 3c ; at &7b00, colour &3c (CC) &585c 1d 11 0e 25 17 0a 1d 1e 1b 0e 25 18 0f 25 1d 11 ; "THE NATURE OF THE" &586c 0e &586d ff ; end of text ; instructions_text_two &586e 80 5a 3c ; at &5a80, colour &3c (CC) &5871 12 17 0f 18 1b 16 0a 1d 12 18 17 31 25 12 1d 25 ; "INFORMATION, IT CAN NOT" &5881 0c 0a 17 17 18 1d 25 &5888 fe ; end of string &5889 80 5f 3c ; at &5f80, colour &3c (CC) &588c 0b 0e 25 1d 1b 0a 17 1c 16 12 1d 1d 0e 0d 25 18 ; "BE TRANSMITTED OVER THE" &589c 1f 0e 1b 25 1d 11 0e &58a3 fe ; end of string &58a4 80 64 3c ; at &6480, colour &3c (CC) &58a7 0a 12 1b 20 0a 1f 0e 1c 27 ; "AIRWAVES." &58b0 fe ; end of string &58b1 80 69 3c ; at &6980, colour &3c (CC) &58b4 22 18 1e 31 25 0c 18 16 16 0a 17 0d 0e 1b 25 13 ; "YOU, COMMANDER JOHN" &58c4 18 11 17 &58c7 fe ; end of string &58c8 80 6e 3c ; at &6e80, colour &3c (CC) &58cb 1c 1d 1b 22 14 0e 1b 31 25 11 0a 1f 0e 25 0b 0e ; "STRYKER, HAVE BEEN CHOSEN" &58db 0e 17 25 0c 11 18 1c 0e 17 &58e4 fe ; end of string &58e5 80 73 3c ; at &7380, colour &3c (CC) &58e8 0f 18 1b 25 1d 11 12 1c 25 16 12 1c 1c 12 18 17 ; "FOR THIS MISSION. THE MAIN" &58f8 27 25 1d 11 0e 25 16 0a 12 17 &5902 fe ; end of string &5903 80 78 3c ; at &7880, colour &3c (CC) &5906 11 27 1a 27 25 11 18 20 0e 1f 0e 1b 25 12 1c 25 ; "H.Q. HOWEVER IS SEVERAL" &5916 1c 0e 1f 0e 1b 0a 15 &591d fe ; end of string &591e 80 7d 3c ; at &7d80, colour &3c (CC) &5921 16 12 15 0e 1c 25 0a 20 0a 22 25 18 1f 0e 1b 25 ; "MILES AWAY OVER ENEMY" &5931 0e 17 0e 16 22 &5936 ff ; end of text ; instructions_text_three &5937 80 5a 3c ; at &5a80, colour &3c (CC) &593a 1d 0e 1b 1b 12 1d 18 1b 22 27 ; "TERRITORY." &5944 fe ; end of string &5945 80 5f 3c ; at &5f80, colour &3c (CC) &5948 18 17 25 22 18 1e 1b 25 13 18 1e 1b 17 0e 22 25 ; "ON YOUR JOURNEY YOU CAN" &5958 22 18 1e 25 0c 0a 17 &595f fe ; end of string &5960 80 64 3c ; at &6480, colour &3c (CC) &5963 0c 18 16 16 0a 17 0d 0e 0e 1b 25 0a 17 22 25 0a ; "COMMANDEER ANY AIRCRAFT" &5973 12 1b 0c 1b 0a 0f 1d &597a fe ; end of string &597b 80 69 3c ; at &6980, colour &3c (CC) &597e 22 18 1e 25 16 0a 22 25 0f 12 17 0d 25 0a 17 0d ; "YOU MAY FIND AND USE THEIR" &598e 25 1e 1c 0e 25 1d 11 0e 12 1b &5998 fe ; end of string &5999 80 6e 3c ; at &6e80, colour &3c (CC) &599c 16 18 1b 0e 25 19 18 20 0e 1b 0f 1e 15 25 20 0e ; "MORE POWERFUL WEAPONRY TO" &59ac 0a 19 18 17 1b 22 25 1d 18 &59b5 fe ; end of string &59b6 80 73 3c ; at &7380, colour &3c (CC) &59b9 0a 12 0d 25 22 18 1e 25 12 17 25 22 18 1e 1b 25 ; "AID YOU IN YOUR QUEST." &59c9 1a 1e 0e 1c 1d 27 &59cf fe ; end of string &59d0 40 79 0c ; at &7940, colour &0c (GG) &59d3 10 18 18 0d 25 15 1e 0c 14 ; "GOOD LUCK" &59dc fe ; end of string &59dd e0 7d 03 ; at &7de0, colour &03 (RR) &59e0 0c 18 16 16 0a 17 0d 0e 1b 25 1c 1d 1b 22 14 0e ; "COMMANDER STRYKER" &59f0 1b &59f1 ff ; end of text ; unused &59f2 ff 00 00 00 00 00 00 00 00 00 00 00 00 00