Frak! disassembly ================= Frak! was written by Nick "Orlando" Pelling, and was published by Aardvark Software for the BBC Micro in 1984. It is a platform game in which the player controls a yoyo-wielding caveman. 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 first stage of the loader can be CHAINed or *RUN. The remaining binaries have false load addresses. Sprites are plotted using a recursive routine that can also check for overlaps. Interesting pokes ================= &0be5 = &a9 infinite lives &1262 = &00 player is invulnerable to monsters, balloons and daggers Loader disassembly ================== ; Frak ; 00003000 000036af 07a0 ; BASIC &3000 0d # Start of BASIC program &3001 00 0a 1e f4 20 20 20 20 20 46 72 61 6b 21 20 4c ; 10REM Frak! Loader program &3011 6f 61 64 65 72 20 70 72 6f 67 72 61 6d 0d &301f 00 14 21 f4 20 20 28 43 29 20 41 61 72 64 76 61 ; 20REM (C) Aardvark Software 1984 &302f 72 6b 20 53 6f 66 74 77 61 72 65 20 31 39 38 34 &303f 0d &3040 00 1e 05 20 0d ; 30 &3045 00 28 4a f4 20 20 20 20 55 6e 61 75 74 68 6f 72 ; 40REM Unauthorised copiers (NOTE: Pirates included) will be rounded up, &3055 69 73 65 64 20 63 6f 70 69 65 72 73 20 28 4e 4f &3065 54 45 3a 20 50 69 72 61 74 65 73 20 69 6e 63 6c &3075 75 64 65 64 29 20 77 69 6c 6c 20 62 65 20 72 6f &3085 75 6e 64 65 64 20 75 70 2c 0d &308f 00 32 3f f4 20 20 68 6f 72 73 65 77 68 69 70 70 ; 50REM horsewhipped, tied down with cheese-wires, and then have &309f 65 64 2c 20 74 69 65 64 20 64 6f 77 6e 20 77 69 &30af 74 68 20 63 68 65 65 73 65 2d 77 69 72 65 73 2c &30bf 20 61 6e 64 20 74 68 65 6e 20 68 61 76 65 0d &30ce 00 3c 46 f4 20 20 6e 20 64 65 67 72 65 65 73 20 ; 60REM n degrees of unholy whatever kicked out of them by Very Big Men &30de 6f 66 20 75 6e 68 6f 6c 79 20 77 68 61 74 65 76 &30ee 65 72 20 6b 69 63 6b 65 64 20 6f 75 74 20 6f 66 &30fe 20 74 68 65 6d 20 62 79 20 56 65 72 79 20 42 69 &310e 67 20 4d 65 6e 0d &3114 00 46 40 f4 20 20 77 65 61 72 69 6e 67 20 56 65 ; 70REM wearing Very Big Boots for a Very, Very Long Time indeed. &3124 72 79 20 42 69 67 20 42 6f 6f 74 73 20 66 6f 72 &3134 20 61 20 56 65 72 79 2c 20 56 65 72 79 20 4c 6f &3144 6e 67 20 54 69 6d 65 20 69 6e 64 65 65 64 2e 0d &3154 00 50 48 f4 20 20 20 20 50 6c 65 61 73 65 20 63 ; 80REM Please consult your local Telephone Directory for the number of &3164 6f 6e 73 75 6c 74 20 79 6f 75 72 20 6c 6f 63 61 &3174 6c 20 54 65 6c 65 70 68 6f 6e 65 20 44 69 72 65 &3184 63 74 6f 72 79 20 66 6f 72 20 74 68 65 20 6e 75 &3194 6d 62 65 72 20 6f 66 0d &319c 00 5a 4a f4 20 20 74 68 65 20 6e 65 61 72 65 73 ; 90REM the nearest casualty ward to you before attempting to rip this off. &31ac 74 20 63 61 73 75 61 6c 74 79 20 77 61 72 64 20 &31bc 74 6f 20 79 6f 75 20 62 65 66 6f 72 65 20 61 74 &31cc 74 65 6d 70 74 69 6e 67 20 74 6f 20 72 69 70 20 &31dc 74 68 69 73 20 6f 66 66 2e 0d &31e6 00 64 05 20 0d ; 100 &31eb 00 6e 41 f4 20 20 47 6f 6f 64 20 4c 75 63 6b 21 ; 110REM Good Luck! and may your god go with you! (only kidding!) &31fb 20 61 6e 64 20 6d 61 79 20 79 6f 75 72 20 67 6f &320b 64 20 67 6f 20 77 69 74 68 20 79 6f 75 21 20 20 &321b 20 28 6f 6e 6c 79 20 6b 69 64 64 69 6e 67 21 29 &322b 0d &322c 00 78 05 20 0d ; 120 &3231 00 82 07 d6 b8 50 0d ; 130CALLTOP &3238 00 8c 12 f5 f7 3a f2 70 75 67 77 61 73 68 3a fd ; 140REPEAT &3248 a3 0d RESTORE: ; PROCpugwash: ; UNTILFALSE &324a 00 96 07 28 e0 29 0d ; 150(END) &3251 00 a0 05 20 0d ; 160 &3256 00 aa 0e dd 20 f2 70 75 67 77 61 73 68 0d ; 170DEF PROCpugwash &3264 00 b4 d5 e2 31 2c 31 2c 30 2c 30 2c 30 2c 31 2c ; 180ENVELOPE1,1,0,0,0,1,1,1,60,-4,-1,-1,120,90: &3274 31 2c 31 2c 36 30 2c 2d 34 2c 2d 31 2c 2d 31 2c ; B$="C D EF G A Bc d ef": &3284 31 32 30 2c 39 30 3a 42 24 3d 22 43 20 44 20 45 ; C$="55551111555511555566661154321155": &3294 46 20 47 20 41 20 42 63 20 64 20 65 66 22 3a 43 ; E$="88887777888877888899997A88357A88": &32a4 24 3d 22 35 35 35 35 31 31 31 31 35 35 35 35 31 ; D$="123475.A.86...9": &32b4 31 35 35 35 35 36 36 36 36 31 31 35 34 33 32 31 ; T%=9: &32c4 31 35 35 22 3a 45 24 3d 22 38 38 38 38 37 37 37 ; B%=6: &32d4 37 38 38 38 38 37 37 38 38 38 38 39 39 39 39 37 ; READA$,N%: &32e4 41 38 38 33 35 37 41 38 38 22 3a 44 24 3d 22 31 ; NOW=TIME: &32f4 32 33 34 37 35 2e 41 2e 38 36 2e 2e 2e 39 22 3a ; M%=0: &3304 54 25 3d 39 3a 42 25 3d 36 3a f3 41 24 2c 4e 25 ; U%=FALSE: &3314 3a 4e 4f 57 3d 91 3a 4d 25 3d 30 3a 55 25 3d a3 ; R%=B%+4*INSTR(D$,LEFT$(C$,1)) &3324 3a 52 25 3d 42 25 2b 34 2a a7 44 24 2c c0 43 24 &3334 2c 31 29 29 0d &3339 00 be 8e f5 e7 4d 25 3c 3d 30 4d 25 3d 4d 25 2b ; 190REPEAT &3349 33 3a e7 a9 43 24 d4 26 31 31 2c 31 2c 52 25 2d ; IFM%<=0M%=M%+3: &3359 28 53 25 2d 52 25 29 2a 55 25 2c 2d 31 3a d4 26 ; IFLENC$SOUND&11,1,R%-(S%-R%)*U%,-1: &3369 31 32 2c 31 80 55 25 2c 53 25 2b 31 32 2c 2d 31 ; SOUND&12,1ANDU%,S%+12,-1: &3379 3a 55 25 3d ac 55 25 3a 52 25 3d 42 25 2b 34 2a ; U%=NOTU%: &3389 a7 44 24 2c c0 43 24 2c 31 29 29 3a 53 25 3d 42 ; R%=B%+4*INSTR(D$,LEFT$(C$,1)): &3399 25 2b 34 2a a7 44 24 2c c0 45 24 2c 31 29 29 3a ; S%=B%+4*INSTR(D$,LEFT$(E$,1)): &33a9 43 24 3d c2 43 24 2c a9 43 24 2b 55 25 29 3a 45 ; C$=RIGHT$(C$,LENC$+U%): &33b9 24 3d c2 45 24 2c a9 45 24 2b 55 25 29 0d ; E$=RIGHT$(E$,LENE$+U%) &33c7 00 c8 6c 4d 25 3d 4d 25 2d 4e 25 3a 43 25 3d 43 ; 200M%=M%-N%: &33d7 25 2d 4e 25 3a d4 26 31 33 2c 31 2c 42 25 2b 34 ; C%=C%-N%: &33e7 2a 28 a7 42 24 2c c0 41 24 2c 31 29 29 2d 28 a7 ; SOUND&13,1,B%+4*(INSTR(B$,LEFT$(A$,1))-(INSTR(A$,"#")>0)+12),-1: &33f7 41 24 2c 22 23 22 29 3e 30 29 2b 31 32 29 2c 2d ; NOW=NOW+N%*T%: &3407 31 3a 4e 4f 57 3d 4e 4f 57 2b 4e 25 2a 54 25 3a ; REPEATUNTILTIME>NOW: &3417 f5 fd 91 3e 4e 4f 57 3a f3 20 41 24 2c 4e 25 3a ; READ A$,N%: &3427 fd 41 24 3d 22 64 6e 65 22 3a e1 0d ; UNTILA$="dne": ; ENDPROC &3433 00 d2 af dc 20 46 2c 31 2c 20 46 2c 31 2c 20 46 ; 210DATA F,1, F,1, F,1, F,3, F,1, F,1, F,1, F,2, c,1, A,2, F,1, A,2, &3443 2c 31 2c 20 46 2c 33 2c 20 46 2c 31 2c 20 46 2c ; c,1, f,2, c,1, A,2, F,1, C,1, C,1, C,1, C,3, C,1, C,1, C,1, &3453 31 2c 20 46 2c 31 2c 20 46 2c 32 2c 20 63 2c 31 ; C,2, G,1, E,2, C,1, E,2, G,1, A#,2, G,1, E,2, C,1 &3463 2c 20 41 2c 32 2c 20 46 2c 31 2c 20 41 2c 32 2c &3473 20 63 2c 31 2c 20 66 2c 32 2c 20 63 2c 31 2c 20 &3483 41 2c 32 2c 20 46 2c 31 2c 20 43 2c 31 2c 20 43 &3493 2c 31 2c 20 43 2c 31 2c 20 43 2c 33 2c 20 43 2c &34a3 31 2c 20 43 2c 31 2c 20 43 2c 31 2c 20 43 2c 32 &34b3 2c 20 47 2c 31 2c 20 45 2c 32 2c 20 43 2c 31 2c &34c3 20 45 2c 32 2c 20 47 2c 31 2c 20 41 23 2c 32 2c &34d3 20 47 2c 31 2c 20 45 2c 32 2c 20 43 2c 31 0d &34e2 00 dc 92 dc 20 46 2c 31 2c 20 46 2c 31 2c 20 46 ; 220DATA F,1, F,1, F,1, F,3, F,1, F,1, F,1, F,2, c,1, A,2, F,1, A,2, &34f2 2c 31 2c 20 46 2c 33 2c 20 46 2c 31 2c 20 46 2c ; c,1, f,3, F,3, C,2, f,1, e,2, d,1, c,2, A#,1, A,2, G,1, &3502 31 2c 20 46 2c 31 2c 20 46 2c 32 2c 20 63 2c 31 ; F,3, A,3, F,3, A,2, A#,1 &3512 2c 20 41 2c 32 2c 20 46 2c 31 2c 20 41 2c 32 2c &3522 20 63 2c 31 2c 20 66 2c 33 2c 20 46 2c 33 2c 20 &3532 43 2c 32 2c 20 66 2c 31 2c 20 65 2c 32 2c 20 64 &3542 2c 31 2c 20 63 2c 32 2c 20 41 23 2c 31 2c 20 41 &3552 2c 32 2c 20 47 2c 31 2c 20 46 2c 33 2c 20 41 2c &3562 33 2c 20 46 2c 33 2c 20 41 2c 32 2c 20 41 23 2c &3572 31 0d &3574 00 e6 a7 dc 20 63 2c 31 2c 20 63 2c 31 2c 20 63 ; 230DATA c,1, c,1, c,1, c,3, c,1, c,1, c,1, c,3, d,2, e,1, f,2, e,1, &3584 2c 31 2c 20 63 2c 33 2c 20 63 2c 31 2c 20 63 2c ; d,2, c,1, A#,2, A,1, A#,2, c,1, d,2, c,1, A#,2, A,1, G,2, &3594 31 2c 20 63 2c 31 2c 20 63 2c 33 2c 20 64 2c 32 ; F,1, E,2, F,1, G,2, F,1, E,2, C,1, D,2, E,1 &35a4 2c 20 65 2c 31 2c 20 66 2c 32 2c 20 65 2c 31 2c &35b4 20 64 2c 32 2c 20 63 2c 31 2c 20 41 23 2c 32 2c &35c4 20 41 2c 31 2c 20 41 23 2c 32 2c 20 63 2c 31 2c &35d4 20 64 2c 32 2c 20 63 2c 31 2c 20 41 23 2c 32 2c &35e4 20 41 2c 31 2c 20 47 2c 32 2c 20 46 2c 31 2c 20 &35f4 45 2c 32 2c 20 46 2c 31 2c 20 47 2c 32 2c 20 46 &3604 2c 31 2c 20 45 2c 32 2c 20 43 2c 31 2c 20 44 2c &3614 32 2c 20 45 2c 31 0d &361b 00 f0 93 dc 20 46 2c 31 2c 20 46 2c 31 2c 20 46 ; 240DATA F,1, F,1, F,1, F,3, F,1, F,1, F,1, F,3, F,1, F,1, F,1, F,3, &362b 2c 31 2c 20 46 2c 33 2c 20 46 2c 31 2c 20 46 2c ; F,1, F,1, F,1, F,3, C,2, f,1, e,2, d,1, c,2, A#,1, A,2, &363b 31 2c 20 46 2c 31 2c 20 46 2c 33 2c 20 46 2c 31 ; G,1, F,3, A,3, F,6, dne,0 &364b 2c 20 46 2c 31 2c 20 46 2c 31 2c 20 46 2c 33 2c &365b 20 46 2c 31 2c 20 46 2c 31 2c 20 46 2c 31 2c 20 &366b 46 2c 33 2c 20 43 2c 32 2c 20 66 2c 31 2c 20 65 &367b 2c 32 2c 20 64 2c 31 2c 20 63 2c 32 2c 20 41 23 &368b 2c 31 2c 20 41 2c 32 2c 20 47 2c 31 2c 20 46 2c &369b 33 2c 20 41 2c 33 2c 20 46 2c 36 2c 20 64 6e 65 &36ab 2c 30 0d &36ae ff # End of BASIC program ; entry_point # Position-independent code; can be run at any address &36af a2 ff LDX #&ff &36b1 9a TXS &36b2 a9 16 LDA #&16 # Change to MODE 7 &36b4 20 ee ff JSR &ffee ; OSWRCH &36b7 a9 07 LDA #&07 &36b9 20 ee ff JSR &ffee ; OSWRCH &36bc a9 1c LDA #&1c # define text window x:(&00, &27), y:(&14, &18) &36be 20 ee ff JSR &ffee ; OSWRCH &36c1 a9 00 LDA #&00 &36c3 20 ee ff JSR &ffee ; OSWRCH &36c6 a9 18 LDA #&18 &36c8 20 ee ff JSR &ffee ; OSWRCH &36cb a9 27 LDA #&27 &36cd 20 ee ff JSR &ffee ; OSWRCH &36d0 a9 14 LDA #&14 &36d2 20 ee ff JSR &ffee ; OSWRCH &36d5 a9 46 LDA #&46 ; "F" &36d7 8d 00 01 STA &0100 ; command &36da a9 58 LDA #&58 ; "X" &36dc 8d 01 01 STA &0101 ; command + 1 &36df a9 32 LDA #&32 ; "2" &36e1 8d 02 01 STA &0102 ; command + 2 &36e4 a9 30 LDA #&30 ; "0" &36e6 8d 03 01 STA &0103 ; command + 3 &36e9 a9 30 LDA #&30 ; "0" &36eb 8d 04 01 STA &0104 ; command + 4 &36ee a9 2c LDA #&2c ; "," &36f0 8d 05 01 STA &0105 ; command + 5 &36f3 a9 33 LDA #&33 ; "3" &36f5 8d 06 01 STA &0106 ; command + 6 &36f8 a9 0d LDA #&0d ; CR &36fa 8d 07 01 STA &0107 ; command + 7 &36fd a2 00 LDX #&00 &36ff a0 01 LDY #&01 &3701 20 f7 ff JSR &fff7 ; OSCLI # *FX 200,3 (clear memory on break) &3704 a9 54 LDA #&54 ; "T" &3706 8d 00 01 STA &0100 ; command &3709 a9 2e LDA #&2e ; "." &370b 8d 01 01 STA &0101 ; command + 1 &370e a9 0d LDA #&0d ; CR &3710 8d 02 01 STA &0102 ; command + 2 &3713 a2 00 LDX #&00 ; &0100 = command &3715 a0 01 LDY #&01 &3717 20 f7 ff JSR &fff7 ; OSCLI # *TAPE &371a a9 4c LDA #&4c ; "L" &371c 8d 00 01 STA &0100 ; command &371f a9 2e LDA #&2e ; "." &3721 8d 01 01 STA &0101 ; command + 1 &3724 a9 46 LDA #&46 ; "F" &3726 8d 02 01 STA &0102 ; command + 2 &3729 a9 72 LDA #&72 ; "r" &372b 8d 03 01 STA &0103 ; command + 3 &372e a9 61 LDA #&61 ; "a" &3730 8d 04 01 STA &0104 ; command + 4 &3733 a9 6b LDA #&6b ; "k" &3735 8d 05 01 STA &0105 ; command + 5 &3738 a9 53 LDA #&53 ; "S" &373a 8d 06 01 STA &0106 ; command + 6 &373d a9 63 LDA #&63 ; "c" &373f 8d 07 01 STA &0107 ; command + 7 &3742 a9 72 LDA #&72 ; "r" &3744 8d 08 01 STA &0108 ; command + 8 &3747 a9 0d LDA #&0d ; CR &3749 8d 09 01 STA &0109 ; command + 9 &374c a2 00 LDX #&00 ; &0100 = command &374e a0 01 LDY #&01 &3750 20 f7 ff JSR &fff7 ; OSCLI # *LOAD FrakScr &3753 a9 c9 LDA #&c9 ; osfile_block_address_high &3755 8d 00 01 STA &0100 ; osword_block &3758 a9 00 LDA #&00 &375a 8d 01 01 STA &0101 ; osword_block + 1 &375d 8d 02 01 STA &0102 ; osword_block + 2 &3760 8d 03 01 STA &0103 ; osword_block + 3 &3763 a9 c0 LDA #&c0 &3765 8d 04 01 STA &0104 ; osword_block + 4 &3768 a2 00 LDX #&00 ; &0100 = osword_block &376a a0 01 LDY #&01 &376c a9 06 LDA #&06 ; Write I/O processor memory # Set osfile_block_address_high = &c0 &376e 20 f1 ff JSR &fff1 ; OSWORD &3771 a9 52 LDA #&52 ; "R" &3773 8d 00 01 STA &0100 ; command &3776 a9 2e LDA #&2e ; "." &3778 8d 01 01 STA &0101 ; command + 1 &377b a9 46 LDA #&46 ; "F" &377d 8d 02 01 STA &0102 ; command + 2 &3780 a9 72 LDA #&72 ; "r" &3782 8d 03 01 STA &0103 ; command + 3 &3785 a9 61 LDA #&61 ; "a" &3787 8d 04 01 STA &0104 ; command + 4 &378a a9 6b LDA #&6b ; "k" &378c 8d 05 01 STA &0105 ; command + 5 &378f a9 32 LDA #&32 ; "2" &3791 8d 06 01 STA &0106 ; command + 6 &3794 a9 0d LDA #&0d ; CR &3796 8d 07 01 STA &0107 ; command + 7 &3799 a2 00 LDX #&00 ; &0100 = command &379b a0 01 LDY #&01 &379d 4c f7 ff JMP &fff7 ; OSCLI # *RUN Frak2 ; FrakScr ; ffff7c00 00000000 0320 &7c00 82 9d 85 28 43 29 20 41 61 72 64 76 61 72 6b 8d ; "...(C) Aardvark.F R A K !.Software 1984 " &7c10 46 20 52 20 41 20 4b 20 21 8c 53 6f 66 74 77 61 ; "...A ..F R A K ! " &7c20 72 65 20 31 39 38 34 20 82 9d 85 41 20 20 20 20 ; " " &7c30 20 20 20 20 20 20 8d 85 46 20 52 20 41 20 4b 20 ; ".Move.trogg.around.the.ladders.&.levels." &7c40 21 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; " " &7c50 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; " .Pick.up.Bulbs.&.Gems.for.bonuses!! " &7c60 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; " " &7c70 20 20 20 20 20 20 20 20 82 4d 6f 76 65 85 74 72 ; ".Collect all the.Keys.for a.Time.Bonus!!" &7c80 6f 67 67 82 61 72 6f 75 6e 64 82 74 68 65 86 6c ; " " &7c90 61 64 64 65 72 73 82 26 86 6c 65 76 65 6c 73 2e ; " " &7ca0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; ".Watch.out.for.the.Balloons.&.Daggers..." &7cb0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; "........................................" &7cc0 20 20 20 20 20 20 20 20 20 20 82 50 69 63 6b 82 ; "...Z. .,...X. . Moves trogg left,right. " &7cd0 75 70 83 42 75 6c 62 73 82 26 83 47 65 6d 73 82 ; " . . " &7ce0 66 6f 72 85 62 6f 6e 75 73 65 73 21 21 20 20 20 ; ".../. .,...:. . Moves up (jumps),down. " &7cf0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; " ...RETURN . . Throws Yoyo. " &7d00 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; "...Q. .,...S. . Turn sound.OFF.,.ON.. " &7d10 20 20 20 20 20 20 20 20 82 43 6f 6c 6c 65 63 74 ; " ...ESCAPE. . . Leaves game. " &7d20 20 61 6c 6c 20 74 68 65 83 4b 65 79 73 82 66 6f ; "...DELETE. .,...COPY. .Freeze,unfreeze. " &7d30 72 20 61 85 54 69 6d 65 85 42 6f 6e 75 73 21 21 ; "........................................" &7d40 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &7d50 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &7d60 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &7d70 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &7d80 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &7d90 81 57 61 74 63 68 81 6f 75 74 82 66 6f 72 82 74 &7da0 68 65 81 42 61 6c 6c 6f 6f 6e 73 82 26 81 44 61 &7db0 67 67 65 72 73 2e 2e 2e 82 2e 2e 2e 2e 2e 2e 2e &7dc0 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e &7dd0 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e &7de0 84 9d 86 5a 82 20 9c 2c 84 9d 86 58 82 20 9c 20 &7df0 4d 6f 76 65 73 20 74 72 6f 67 67 20 6c 65 66 74 &7e00 2c 72 69 67 68 74 2e 20 20 20 20 20 20 20 20 20 &7e10 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 82 &7e20 20 9c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 &7e30 84 9d 86 2f 82 20 9c 2c 84 9d 86 3a 82 20 9c 20 &7e40 4d 6f 76 65 73 20 75 70 20 28 6a 75 6d 70 73 29 &7e50 2c 64 6f 77 6e 2e 20 20 20 20 86 9d 84 52 45 54 &7e60 55 52 4e 20 20 9c 20 20 20 20 86 20 20 54 68 72 &7e70 6f 77 73 20 59 6f 79 6f 2e 20 20 20 20 20 20 20 &7e80 84 9d 86 51 82 20 9c 2c 84 9d 86 53 82 20 9c 20 &7e90 54 75 72 6e 20 73 6f 75 6e 64 81 4f 46 46 82 2c &7ea0 81 4f 4e 82 2e 20 20 20 20 20 86 9d 84 45 53 43 &7eb0 41 50 45 82 20 9c 20 20 20 20 86 20 20 4c 65 61 &7ec0 76 65 73 20 67 61 6d 65 2e 20 20 20 20 20 20 20 &7ed0 84 9d 86 44 45 4c 45 54 45 82 20 9c 2c 84 9d 86 &7ee0 43 4f 50 59 86 20 9c 46 72 65 65 7a 65 2c 75 6e &7ef0 66 72 65 65 7a 65 2e 20 82 2e 2e 2e 2e 2e 2e 2e &7f00 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e &7f10 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e ; Frak2 ; 00003000 ffff209f 05ed # Actually loads at &204c ; call_code_address &204c 6c 94 00 JMP (&0094) ; code_address ; get_byte &204f b1 92 LDA (&92),Y ; data_address ; skip_byte &2051 e6 92 INC &92 ; data_address_low &2053 d0 02 BNE &2057 ; leave &2055 e6 93 INC &93 ; data_address_high ; leave &2057 60 RTS ; decrypt_memory &2058 18 CLC &2059 b8 CLV &205a d8 CLD &205b 78 SEI &205c a2 00 LDX #&00 &205e a0 01 LDY #&01 &2060 68 PLA # Parameters follow function call &2061 85 92 STA &92 ; data_address_low &2063 68 PLA &2064 85 93 STA &93 ; data_address_high &2066 20 4f 20 JSR &204f ; get_byte &2069 85 94 STA &94 ; code_address_low &206b 20 4f 20 JSR &204f ; get_byte &206e 85 95 STA &95 ; code_address_high &2070 20 4f 20 JSR &204f ; get_byte &2073 85 96 STA &96 ; count_low &2075 20 4f 20 JSR &204f ; get_byte &2078 85 97 STA &97 ; count_high &207a a5 93 LDA &93 ; data_address_high &207c 48 PHA # Leave via decrypted memory on return &207d a5 92 LDA &92 ; data_address_low &207f 48 PHA &2080 86 98 STX &98 ; rolling_add ; decrypt_memory_loop &2082 20 4f 20 JSR &204f ; get_byte &2085 20 4c 20 JSR &204c ; call_code_address &2088 81 92 STA (&92,X) ; data_address &208a e6 96 INC &96 ; count_low &208c d0 f4 BNE &2082 ; decrypt_memory_loop &208e e6 97 INC &97 ; count_high &2090 d0 f0 BNE &2082 ; decrypt_memory_loop &2092 f0 c3 BEQ &2057 ; leave # Always branches ; decrypt_using_eor &2094 45 0e EOR &0e ; #&63 &2096 60 RTS ; decrypt_using_add &2097 65 98 ADC &98 ; rolling_add &2099 85 98 STA &98 ; rolling_add &209b 60 RTS ; decrypt_using_fixed_add &209c 65 1e ADC &1e ; #&2a &209e 60 RTS ; entry_point &209f a2 90 LDX #&90 &20a1 a0 00 LDY #&00 &20a3 98 TYA &20a4 38 SEC &20a5 6a ROR A &20a6 6a ROR A &20a7 8d 00 0d STA &0d00 ; nmi_handler # Set NMI handler to &40 (RTI) &20aa 8a TXA ; initialise_zero_page_loop # Initialise &0000 - &008f &20ab 79 ea 24 ADC &24ea,Y ; obfuscated_initial_zero_page_values &20ae 9d ff ff STA &ffff,X ; &0000 - 1 &20b1 c8 INY &20b2 ca DEX &20b3 d0 f6 BNE &20ab ; initialise_zero_page_loop &20b5 ae 4e 20 LDX &204e ; #&00 &20b8 a5 6e LDA &6e ; #&0f ; Flush all buffers &20ba 20 f4 ff JSR &fff4 ; OSBYTE &20bd 20 58 20 JSR &2058 ; decrypt_memory &20c0 94 20 da fb # Decrypt &20c4 - &24e9 using &2094 (decrypt_using_eor) &20c4 a9 57 LDA #&57 ; "W" &20c6 20 ee ff JSR &ffee ; OSWRCH &20c9 20 58 20 JSR &2058 ; decrypt_memory &20cc 97 20 e6 fb # Decrypt &20d0 - &24e9 using &2097 (decrypt_using_add) &20d0 a9 61 LDA #&61 ; "a" &20d2 20 ee ff JSR &ffee ; OSWRCH &20d5 20 58 20 JSR &2058 ; decrypt_memory &20d8 97 20 f2 fb # Decrypt &20dc - &24e9 using &2097 (decrypt_using_add) &20dc a9 69 LDA #&69 ; "i" &20de 20 ee ff JSR &ffee ; OSWRCH &20e1 20 58 20 JSR &2058 ; decrypt_memory &20e4 97 20 fe fb # Decrypt &20e8 - &24e9 using &2097 (decrypt_using_add) &20e8 a9 74 LDA #&74 ; "t" &20ea 20 ee ff JSR &ffee ; OSWRCH &20ed 20 58 20 JSR &2058 ; decrypt_memory &20f0 97 20 0a fc # Decrypt &20f4 - &24e9 using &2097 (decrypt_using_add) &20f4 a9 20 LDA #&20 ; " " &20f6 20 ee ff JSR &ffee ; OSWRCH &20f9 20 58 20 JSR &2058 ; decrypt_memory &20fc 97 20 16 fc # Decrypt &2100 - &24e9 using &2097 (decrypt_using_add) &2100 a9 61 LDA #&61 ; "a" &2102 20 ee ff JSR &ffee ; OSWRCH &2105 20 58 20 JSR &2058 ; decrypt_memory &2108 94 20 22 fc # Decrypt &210c - &24e9 using &2094 (decrypt_using_eor) &210c a9 20 LDA #&20 ; " " &210e 20 ee ff JSR &ffee ; OSWRCH &2111 20 58 20 JSR &2058 ; decrypt_memory &2114 97 20 2e fc # Decrypt &2118 - &24e9 using &2097 (decrypt_using_add) &2118 a9 6d LDA #&6d ; "m" &211a 20 ee ff JSR &ffee ; OSWRCH &211d a9 6f LDA #&6f ; "o" &211f 20 ee ff JSR &ffee ; OSWRCH &2122 a6 6d LDX &6d ; #&28 &2124 9a TXS &2125 20 75 24 JSR &2475 ; wipe_memory &2128 ff 03 00 fc # Wipe &0400 - &07ff &212c a9 2e LDA #&2e ; "." &212e 20 ee ff JSR &ffee ; OSWRCH &2131 20 75 24 JSR &2475 ; wipe_memory &2134 ff 08 00 fc # Wipe &0900 - &0cff &2138 a9 2e LDA #&2e ; "." &213a 20 ee ff JSR &ffee ; OSWRCH &213d 20 75 24 JSR &2475 ; wipe_memory &2140 00 0d b5 ec # Wipe &0d01 - &204b &2144 a9 2e LDA #&2e ; "." &2146 20 ee ff JSR &ffee ; OSWRCH &2149 20 75 24 JSR &2475 ; wipe_memory &214c 38 26 39 aa # Wipe &2639 - &7bff &2150 a9 2e LDA #&2e ; "." &2152 20 ee ff JSR &ffee ; OSWRCH &2155 a4 6e LDY &6e ; #&0f ; wipe_sideways_ram_and_remove_roms_loop &2157 84 90 STY &90 ; slot &2159 8c 30 fe STY &fe30 ; Paged ROM latch &215c 84 f4 STY &f4 ; os_ram_copy_of_currently_selected_rom_number &215e 20 75 24 JSR &2475 ; wipe_memory &2161 ff 7f 00 c0 # Wipe &8000 - &bfff &2165 a5 96 LDA &96 ; count_low ; #&00 &2167 a4 90 LDY &90 ; slot &2169 99 a1 02 STA &02a1,Y ; os_paged_rom_type_table # Remove paged ROMs from ROM information table &216c 88 DEY &216d 10 e8 BPL &2157 ; wipe_sideways_ram_and_remove_roms_loop &216f ae b7 ff LDX &ffb7 ; os_rom_default_vector_table_address_low &2172 ac b8 ff LDY &ffb8 ; os_rom_default_vector_table_address_high &2175 86 90 STX &90 ; default_os_vector_table_address_low &2177 84 91 STY &91 ; default_os_vector_table_address_high &2179 ac 5f 20 LDY &205f ; #&01 &217c b1 90 LDA (&90),Y ; default_os_vector_table_address &217e 10 6c BPL &21ec ; is_os_1.00 &2180 ac b6 ff LDY &ffb6 ; os_rom_vector_table_length &2183 d0 71 BNE &21f6 ; reset_os_vector_table_loop ; is_os_0.10_or_electron &2185 20 75 24 JSR &2475 ; wipe_memory &2188 eb 21 77 fd # Wipe &21bf &218c 20 75 24 JSR &2475 ; wipe_memory &218f 57 20 cc fe # Wipe &2058 &2193 ac 5f 20 LDY &205f ; #&01 &2196 ae 4e 20 LDX &204e ; #&00 &2199 a5 60 LDA &60 ; #&89 ; Cassette motor control &219b 20 f4 ff JSR &fff4 ; OSBYTE # Turn off cassette motor &219e 00 BRK &219f 00 &21a0 16 07 ; MODE 7 &21a2 20 20 53 6f 72 72 79 2c 20 62 75 74 20 46 72 61 ; " Sorry, but Fra &21b2 6b 20 72 65 71 75 69 72 65 73 20 61 20 42 42 43 ; "k requires a BBC &21c2 20 4d 69 63 72 6f 20 20 20 20 20 20 20 4d 6f 64 ; " Micro Mod &21d2 65 6c 20 42 20 77 69 74 68 20 4f 53 20 31 2e 30 ; "el B with OS 1.0 &21e2 2b 20 74 6f 20 72 75 6e 2e 00 ; "+ to run" ; is_os_1.00 &21ec a5 26 LDA &26 ; #&41 ; &d941 = os_1.00_rom_default_vector_table &21ee 85 90 STA &90 ; default_os_vector_table_address_low &21f0 a5 24 LDA &24 ; #&d9 &21f2 85 91 STA &91 ; default_os_vector_table_address_high &21f4 a0 36 LDY #&36 ; reset_os_vector_table_loop &21f6 88 DEY &21f7 b1 90 LDA (&90),Y ; default_os_vector_table_address &21f9 99 00 02 STA &0200,Y ; os_vector_table &21fc 98 TYA &21fd d0 f7 BNE &21f6 ; reset_os_vector_table_loop &21ff 20 58 20 JSR &2058 ; decrypt_memory &2202 9c 20 91 fd # Decrypt &2206 - &2474 using &209c (decrypt_using_fixed_add) &2206 20 58 20 JSR &2058 ; decrypt_memory &2209 97 20 ce fd # Decrypt &220d - &243e using &2097 (decrypt_using_add) &220d 20 58 20 JSR &2058 ; decrypt_memory &2210 97 20 d5 fd # Decrypt &2214 - &243e using &2097 (decrypt_using_add) &2214 20 58 20 JSR &2058 ; decrypt_memory &2217 97 20 dc fd # Decrypt &221b - &243e using &2097 (decrypt_using_add) &221b 20 58 20 JSR &2058 ; decrypt_memory &221e 97 20 e3 fd # Decrypt &2222 - &243e using &2097 (decrypt_using_add) &2222 ac 4e 20 LDY &204e ; #&00 &2225 a6 6c LDX &6c ; #&ff ; keyboard selected, RS-423 enabled &2227 ad 54 20 LDA &2054 ; #&02 ; Specify input stream &222a 20 f4 ff JSR &fff4 ; OSBYTE &222d a4 6c LDY &6c ; #&ff &222f ae 4e 20 LDX &204e ; #&00 &2232 ad 88 20 LDA &2088 ; #&81 ; Check machine type &2235 20 f4 ff JSR &fff4 ; OSBYTE &2238 e0 01 CPX #&01 ; Electron &223a d0 03 BNE &223f ; not_electron &223c 4c 85 21 JMP &2185 ; is_os_0.10_or_electron ; not_electron &223f a5 1c LDA &1c ; #&12 ; Reset function key definitions &2241 20 f4 ff JSR &fff4 ; OSBYTE &2244 ae 4e 20 LDX &204e ; #&00 &2247 a5 61 LDA &61 ; #&8c ; Select Tape FS at default speed &2249 20 f4 ff JSR &fff4 ; OSBYTE &224c a4 6c LDY &6c ; #&ff &224e ae 4e 20 LDX &204e ; #&00 &2251 a5 07 LDA &07 ; #&eb ; Read speech processor presence &2253 20 f4 ff JSR &fff4 ; OSBYTE &2256 8a TXA &2257 f0 0a BEQ &2263 ; skip_speech_processor &2259 a4 34 LDY &34 ; #&70 ; reset speech processor &225b ae 4e 20 LDX &204e ; #&00 &225e a5 40 LDA &40 ; #&9f ; Write to speech processor &2260 20 f4 ff JSR &fff4 ; OSBYTE ; skip_speech_processor &2263 ac 4e 20 LDY &204e ; #&00 &2266 a6 6c LDX &6c ; #&ff ; disable BASIC ROM &2268 a5 7b LDA &7b ; #&bb ; Read/Write ROM number of BASIC &226a 20 f4 ff JSR &fff4 ; OSBYTE &226d ac 4e 20 LDY &204e ; #&00 &2270 a6 8e LDX &8e ; #&08 ; 8 bit &2272 a5 19 LDA &19 ; #&be ; Set ADC resolution &2274 20 f4 ff JSR &fff4 ; OSBYTE &2277 ac 4e 20 LDY &204e ; #&00 &227a a6 6f LDX &6f ; #&03 ; Clear memory on next reset &227c a5 1d LDA &1d ; #&c8 ; Read/Write BREAK/ESCAPE effect &227e 20 f4 ff JSR &fff4 ; OSBYTE &2281 ac 4e 20 LDY &204e ; #&00 &2284 ae 4e 20 LDX &204e ; #&00 ; enable keyboard &2287 a5 4f LDA &4f ; #&c9 ; Read/Write keyboard Enable/Disable &2289 20 f4 ff JSR &fff4 ; OSBYTE &228c ac 4e 20 LDY &204e ; #&00 &228f ae 4e 20 LDX &204e ; #&00 ; disable call interception &2292 a5 5a LDA &5a ; #&ce ; Read/Write ECONET call interception &2294 20 f4 ff JSR &fff4 ; OSBYTE &2297 ac 4e 20 LDY &204e ; #&00 &229a ae 4e 20 LDX &204e ; #&00 ; disable input interception &229d a5 16 LDA &16 ; #&cf ; Read/Write ECONET input interception &229f 20 f4 ff JSR &fff4 ; OSBYTE &22a2 ac 4e 20 LDY &204e ; #&00 &22a5 ae 4e 20 LDX &204e ; #&00 ; disable output interception &22a8 ad 53 20 LDA &2053 ; #&d0 ; Read/Write ECONET output interception &22ab 20 f4 ff JSR &fff4 ; OSBYTE &22ae ac 4e 20 LDY &204e ; #&00 &22b1 ae 66 20 LDX &2066 ; #&20 ; disable speech &22b4 a5 3b LDA &3b ; #&d1 ; Read/Write speech suppression status &22b6 20 f4 ff JSR &fff4 ; OSBYTE &22b9 ac 4e 20 LDY &204e ; #&00 &22bc ae 4e 20 LDX &204e ; #&00 &22bf a5 77 LDA &77 ; #&da ; Read/Write VDU queue length &22c1 20 f4 ff JSR &fff4 ; OSBYTE &22c4 ac 4e 20 LDY &204e ; #&00 &22c7 ae 4e 20 LDX &204e ; #&00 ; cause escape conditions &22ca a5 8a LDA &8a ; #&e5 ; Read/Write ESCAPE key status &22cc 20 f4 ff JSR &fff4 ; OSBYTE &22cf ac 4e 20 LDY &204e ; #&00 &22d2 ae 4e 20 LDX &204e ; #&00 ; disable tube &22d5 a5 46 LDA &46 ; #&ea ; Read/Write Tube present flag &22d7 20 f4 ff JSR &fff4 ; OSBYTE &22da ac 4e 20 LDY &204e ; #&00 &22dd ae 4e 20 LDX &204e ; #&00 ; all forms of break act as reset &22e0 a5 3a LDA &3a ; #&f7 ; Define action of BREAK key &22e2 20 f4 ff JSR &fff4 ; OSBYTE &22e5 ae 4e 20 LDX &204e ; #&00 ; output buffer empty event &22e8 a5 7f LDA &7f ; #&0d ; Disable event &22ea 20 f4 ff JSR &fff4 ; OSBYTE &22ed ae 5f 20 LDX &205f ; #&01 ; input buffer full &22f0 a5 7f LDA &7f ; #&0d ; Disable event &22f2 20 f4 ff JSR &fff4 ; OSBYTE &22f5 a6 31 LDX &31 ; #&02 ; character entering buffer &22f7 a5 7f LDA &7f ; #&0d ; Disable event &22f9 20 f4 ff JSR &fff4 ; OSBYTE &22fc a6 6f LDX &6f ; #&03 ; ADC conversion complete &22fe a5 7f LDA &7f ; #&0d ; Disable event &2300 20 f4 ff JSR &fff4 ; OSBYTE &2303 a6 66 LDX &66 ; #&04 ; v-sync event &2305 a5 5b LDA &5b ; #&0e ; Enable event &2307 20 f4 ff JSR &fff4 ; OSBYTE &230a a6 05 LDX &05 ; #&05 ; interval timer crossed zero &230c a5 7f LDA &7f ; #&0d ; Disable event &230e 20 f4 ff JSR &fff4 ; OSBYTE &2311 a6 3e LDX &3e ; #&06 ; ESCAPE pressed event &2313 a5 7f LDA &7f ; #&0d ; Disable event &2315 20 f4 ff JSR &fff4 ; OSBYTE &2318 a6 73 LDX &73 ; #&07 ; RS423 error &231a a5 7f LDA &7f ; #&0d ; Disable event &231c 20 f4 ff JSR &fff4 ; OSBYTE &231f a6 8e LDX &8e ; #&08 ; network error &2321 a5 7f LDA &7f ; #&0d ; Disable event &2323 20 f4 ff JSR &fff4 ; OSBYTE &2326 ac 4e 20 LDY &204e ; #&00 &2329 ae 4e 20 LDX &204e ; #&00 ; restore *OPT default values &232c a5 71 LDA &71 ; #&8b ; Set filing system attributes &232e 20 f4 ff JSR &fff4 ; OSBYTE &2331 a9 b7 LDA #&b7 ; &23b7 = event_handler &2333 8d 20 02 STA &0220 ; event_vector_low &2336 a9 23 LDA #&23 &2338 8d 21 02 STA &0221 ; event_vector_high &233b a6 6c LDX &6c ; #&ff &233d 9a TXS &233e 20 e7 ff JSR &ffe7 ; OSNEWL &2341 58 CLI &2342 a5 86 LDA &86 ; #&c0 &2344 85 c9 STA &c9 ; osfile_block_address_high &2346 ee 06 01 INC &0106 ; command + 6 # Increment "R.Frak2" to "R.Frak3" &2349 e8 INX &234a ac 5f 20 LDY &205f ; #&01 &234d a5 6c LDA &6c ; #&ff ; &fff6 = OSCLI -1 &234f 48 PHA # Leave to OSCLI on return &2350 a5 04 LDA &04 ; #&f6 &2352 48 PHA &2353 60 RTS # *RUN Frak3 ; decrypt_using_key &2354 85 9a STA &9a ; input_byte &2356 a5 98 LDA &98 ; rolling_add &2358 61 90 ADC (&90,X) ; key_address &235a 65 9a ADC &9a ; input_byte &235c 85 98 STA &98 ; rolling_add &235e e6 90 INC &90 ; key_address_low &2360 d0 02 BNE &2364 ; skip_page &2362 e6 91 INC &91 ; key_address_high ; skip_page &2364 48 PHA ; output_byte &2365 a5 90 LDA &90 ; key_address_low # Use &204c - &2638 as key for decryption &2367 49 39 EOR #&39 ; &2639 = end_of_frak2 &2369 d0 10 BNE &237b ; skip_wraparound &236b a5 91 LDA &91 ; key_address_high &236d 49 26 EOR #&26 &236f d0 0a BNE &237b ; skip_wraparound &2371 ad 86 20 LDA &2086 ; #&4c ; &204c = start_of_frak2 &2374 85 90 STA &90 ; key_address_low &2376 ad 66 20 LDA &2066 ; #&20 &2379 85 91 STA &91 ; key_address_high ; skip_wraparound &237b 68 PLA ; output_byte &237c 60 RTS ; decrypt_main_binary &237d 38 SEC &237e a6 6c LDX &6c ; #&ff # Decrypt &3000 - &5c4a using &2354 (decrypt_using_key) &2380 a4 56 LDY &56 ; #&2f &2382 86 92 STX &92 ; data_address_low &2384 84 93 STY &93 ; data_address_high &2386 a6 82 LDX &82 ; #&b5 &2388 a4 36 LDY &36 ; #&d3 &238a 86 96 STX &96 ; count_low &238c 84 97 STY &97 ; count_high &238e ae 86 20 LDX &2086 ; #&4c ; &204c = start_of_frak2 &2391 ac 66 20 LDY &2066 ; #&20 &2394 86 90 STX &90 ; key_address_low &2396 84 91 STY &91 ; key_address_high &2398 a6 7d LDX &7d ; #&54 ; &2354 = decrypt_using_key &239a a4 62 LDY &62 ; #&23 &239c 86 94 STX &94 ; code_address_low &239e 84 95 STY &95 ; code_address_high &23a0 ae 4e 20 LDX &204e ; #&00 &23a3 ac 5f 20 LDY &205f ; #&01 &23a6 84 98 STY &98 ; rolling_add &23a8 a5 06 LDA &06 ; #&46 ; &468a = main binary entry_point - 1 &23aa 48 PHA &23ab a5 6a LDA &6a ; #&8a &23ad 48 PHA &23ae ad 66 20 LDA &2066 ; #&20 ; &2081 = decrypt_memory_loop - 1 &23b1 48 PHA &23b2 ad 88 20 LDA &2088 ; #&81 &23b5 48 PHA &23b6 60 RTS # Call decrypt_memory_loop, then main binary entry_point ; event_handler &23b7 08 PHP &23b8 48 PHA ; tmp_a &23b9 8a TXA &23ba 48 PHA ; tmp_x &23bb 98 TYA &23bc 48 PHA ; tmp_y &23bd a5 06 LDA &06 ; #&46 ; "F" # Do the spare byte of the tape block contain "Frak"? &23bf cd cb 03 CMP &03cb ; tape_block_spare_bytes &23c2 d0 4e BNE &2412 ; leave_after_restoring_registers &23c4 a5 12 LDA &12 ; #&72 ; "r" &23c6 cd cc 03 CMP &03cc ; tape_block_spare_bytes + 1 &23c9 d0 47 BNE &2412 ; leave_after_restoring_registers &23cb a5 45 LDA &45 ; #&61 ; "a" &23cd cd cd 03 CMP &03cd ; tape_block_spare_bytes + 2 &23d0 d0 40 BNE &2412 ; leave_after_restoring_registers &23d2 a5 41 LDA &41 ; #&6b ; "k" &23d4 cd ce 03 CMP &03ce ; tape_block_spare_bytes + 3 &23d7 d0 39 BNE &2412 ; leave_after_restoring_registers &23d9 ce cd 03 DEC &03cd ; tape_block_spare_bytes + 2 # If so, &23dc ad 4e 20 LDA &204e ; #&00 # Set load address to &00003000 &23df 8d be 03 STA &03be ; tape_load_address &23e2 a5 53 LDA &53 ; #&30 &23e4 8d bf 03 STA &03bf ; tape_load_address + 1 &23e7 a5 6c LDA &6c ; #&ff &23e9 8d c0 03 STA &03c0 ; tape_load_address + 2 &23ec 8d c1 03 STA &03c1 ; tape_load_address + 3 &23ef ad 4e 20 LDA &204e ; #&00 &23f2 8d c8 03 STA &03c8 ; tape_block_length &23f5 ad 5f 20 LDA &205f ; #&01 &23f8 8d c9 03 STA &03c9 ; tape_block_length + 1 &23fb ad ca 03 LDA &03ca ; tape_block_flags &23fe 10 12 BPL &2412 ; leave_after_restoring_registers &2400 a5 7e LDA &7e ; #&7d # Set execution address to &ffff237d (decrypt_main_binary) &2402 8d c2 03 STA &03c2 ; tape_execution_address &2405 a5 62 LDA &62 ; #&23 &2407 8d c3 03 STA &03c3 ; tape_execution_address + 1 &240a a5 6c LDA &6c ; #&ff &240c 8d c4 03 STA &03c4 ; tape_execution_address + 2 &240f 8d c5 03 STA &03c5 ; tape_execution_address + 3 ; leave_after_restoring_registers &2412 68 PLA ; tmp_y &2413 a8 TAY &2414 68 PLA ; tmp_x &2415 aa TAX &2416 68 PLA ; tmp_a &2417 28 PLP &2418 60 RTS ; unused &2419 20 28 2e 2e 2e 53 6f 72 72 79 20 50 65 74 65 72 ; " (...Sorry Peter &2429 21 29 20 2e 2e 2e 6e 65 61 72 6c 79 20 74 68 65 ; "!) ...nearly the &2439 72 65 2e 2e 2e 20 20 59 6f 75 20 61 72 65 20 69 ; "re... You are i &2449 6e 20 61 20 6d 61 7a 65 20 6f 66 20 41 63 72 6f ; "n a maze of Acro &2459 6e 73 66 6f 74 20 61 64 76 65 6e 74 75 72 65 73 ; "nsfot adventures &2469 2c 20 61 6c 6c 20 61 6c 69 6b 65 20 ; ", all alike " ; wipe_memory &2475 68 PLA # Parameters follow function call &2476 85 92 STA &92 ; data_address_low &2478 68 PLA &2479 85 93 STA &93; data_address_high &247b ae 4e 20 LDX &204e ; #&00 &247e ac 5f 20 LDY &205f ; #&01 &2481 20 4f 20 JSR &204f ; get_byte &2484 85 94 STA &94 ; start_address_low &2486 20 4f 20 JSR &204f ; get_byte &2489 85 95 STA &95 ; start_address_high &248b 20 4f 20 JSR &204f ; get_byte &248e 85 96 STA &96 ; count_low &2490 20 4f 20 JSR &204f ; get_byte &2493 85 97 STA &97 ; count_high &2495 a5 93 LDA &93 ; data_address_high &2497 48 PHA # Return to code after end of parameters &2498 a5 95 LDA &95 ; start_address_high &249a 85 93 STA &93 ; data_address_high &249c a5 92 LDA &92 ; data_address_low &249e 48 PHA &249f a5 94 LDA &94 ; start_address_low &24a1 85 92 STA &92 ; data_address_low ; wipe_memory_loop &24a3 20 51 20 JSR &2051 ; skip_byte &24a6 8a TXA &24a7 81 92 STA (&92,X) ; data_address &24a9 e6 96 INC &96 ; count_low &24ab d0 f6 BNE &24a3 ; wipe_memory_loop &24ad e6 97 INC &97 ; count_high &24af d0 f2 BNE &24a3 ; wipe_memory_loop &24b1 60 RTS ; unused &24b2 20 59 6f 75 20 61 72 65 20 69 6e 20 61 20 6d 61 ; " You are in a ma" &24c2 7a 65 20 6f 66 20 74 77 69 73 74 79 20 6c 69 74 ; "ze of twisty lit" &24d2 74 6c 65 20 70 61 73 73 61 67 65 73 2c 20 61 6c ; "tle passages, al" &24e2 6c 20 61 6c 69 6b 65 20 ; "l alike " ; obfuscated_initial_zero_page_values &24ea d7 a0 07 ae f4 32 d3 fb 4f bb 0d e3 2e d6 17 b7 &24fa 88 6f d7 5d 09 67 86 ce 62 5a 52 52 2e 66 1d ed &250a 8a 0b 19 d7 37 53 a0 95 d2 71 54 cb 12 ec 68 fd &251a b3 13 29 26 6e bf 78 c8 9c 83 bd 53 ef 71 1e d3 &252a 35 ab 95 20 8b af 14 be 46 6b 77 04 e2 a6 7c 33 &253a d5 91 c4 34 d2 25 18 6f 17 3d e2 ba 01 9b f4 f1 &254a 9f 2b c7 73 b1 33 a2 ae 47 c9 d7 bf 94 b6 8a 25 &255a f4 61 9d 4a 1d b0 de 2a a7 3e f1 24 af dd 5f b0 &256a 3b a5 3c d9 72 d8 5f 99 2d 5b be f0 77 be 5a 69 ; unused # Unencrypted &257a 28 43 29 20 41 61 72 64 76 61 72 6b 20 53 6f 66 ; "(C) Aardvark Sof" &258a 74 77 61 72 65 20 31 39 38 34 2e 20 55 6e 61 75 ; "tware 1984. Unau" &259a 74 68 6f 72 69 73 65 64 20 63 6f 70 79 69 6e 67 ; "thorised copying" &25aa 20 6f 66 20 74 68 65 20 70 72 6f 67 72 61 6d 20 ; " of the program " &25ba 63 6f 6e 74 61 69 6e 65 64 20 68 65 72 65 69 6e ; "contained herein" &25ca 2c 20 69 74 73 20 69 6d 61 67 65 73 2c 20 74 75 ; ", its images, tu" &25da 6e 65 73 2c 20 63 6c 65 76 65 72 20 62 69 74 73 ; "nes, clever bits" &25ea 2c 20 61 6e 64 20 69 74 73 20 70 61 63 6b 61 67 ; ", and its packag" &25fa 69 6e 67 20 69 73 20 61 6e 20 4f 46 46 45 4e 43 ; "ing is an OFFENC" &260a 45 2c 20 61 6e 64 20 6d 61 79 20 70 72 6f 76 65 ; "E, and may prove" &261a 20 64 65 74 72 69 6d 65 6e 74 61 6c 20 74 6f 20 ; " detrimental to " &262a 79 6f 75 72 20 68 65 61 6c 74 68 2e 2e 2e 2e ; "your health...." Game disassembly ================ ; Frak3 ; 3ad2fc42 208c9734 2c4b # Actually loads at &3000, executes at &468b # &3000 - &31f2 is moved to &0b00 - &0cf2 at &46a9 ; object_class_data ; s m l 84218421 &0b00 00 00 54 ; OBJECT_CLASS_T (player) : slots &00 - &02, ........, "T" # &01 OBJECT_CLASS_IS_DEADLY &0b03 03 09 44 ; OBJECT_CLASS_D (daggers) : slots &03 - &0c, ....8..1, "D" # &02 OBJECT_CLASS_IS_PLATFORM &0b06 0d 09 42 ; OBJECT_CLASS_B (balloons) : slots &0d - &16, ....8..1, "B" # &04 OBJECT_CLASS_IS_LADDER &0b09 17 50 4b ; OBJECT_CLASS_K (collectables) : slots &17 - &25, .4.1...., "K" # &08 OBJECT_CLASS_IS_YOYOABLE &0b0c 26 c9 4d ; OBJECT_CLASS_M (monsters) : slots &26 - &2f, 8.2.8..1, "M" # &10 OBJECT_CLASS_IS_COLLECTABLE &0b0f 30 02 46 ; OBJECT_CLASS_F (platform) : slots &30 - &5c, ......2., "F" # &20 (unused) &0b12 5d 04 4c ; OBJECT_CLASS_L (ladder) : slots &5d - &7a, .....4.., "L" # &40 (unused) &0b15 7b 00 00 # &80 OBJECT_CLASS_IS_YOYOABLE_IN_DARK ; plot_object_with_background &0b18 a9 40 LDA #&40 ; PLOT_BACKGROUND &0b1a 10 09 BPL &0b25 ; consider_plotting_or_unplotting_sprite ; unplot_object_without_background &0b1c a9 80 LDA #&80 ; PLOT_UNPLOT &0b1e 30 05 BMI &0b25 ; consider_plotting_or_unplotting_sprite ; plot_object_without_background &0b20 a9 00 LDA #&00 # &80 clear to plot, &40 clear to plot only sprite &0b22 cd a9 c0 CMP &c0a9 ; unplot_object_with_background #0b23 LDA #&c0 ; PLOT_UNPLOT | PLOT_BACKGROUND ; consider_plotting_or_unplotting_sprite &0b25 20 3c 0b JSR &0b3c ; get_object_position_and_sprite # Returns carry set if not a valid sprite, preserves AX &0b28 b0 07 BCS &0b31 ; leave &0b2a 86 33 STX &33 ; object_being_checked &0b2c 20 cf 1c JSR &1ccf ; plot_or_unplot_or_unplot_sprite_with_or_without_background &0b2f a6 33 LDX &33 ; object_being_checked ; leave &0b31 60 RTS ; plot_sprite_A_at_X_Y &0b32 86 11 STX &11 ; sprite_x &0b34 84 12 STY &12 ; sprite_y &0b36 a8 TAY &0b37 a9 00 LDA #&00 # &80 clear to plot, &40 clear to plot only sprite &0b39 4c cf 1c JMP &1ccf ; plot_or_unplot_or_unplot_sprite_with_or_without_background ; get_object_position_and_sprite &0b3c bc 68 03 LDY &0368,X ; objects_x &0b3f 84 11 STY &11 ; sprite_x &0b41 bc e3 03 LDY &03e3,X ; objects_y &0b44 84 12 STY &12 ; sprite_y &0b46 bc 5e 04 LDY &045e,X ; objects_sprite &0b49 c0 5c CPY #&5c ; SPRITE_LAST + 1 # Leave with carry set if not a valid sprite &0b4b 60 RTS ; wait_to_start_game &0b4c 20 27 0c JSR &0c27 ; stop_timer &0b4f a9 ff LDA #&ff &0b51 85 2f STA &2f ; suppress_tune # Set to negative to suppress tune &0b53 85 86 STA &86 ; keyboard_or_joystick # Set to negative to indicate SPACE or fire not pressed &0b55 20 77 19 JSR &1977 ; high_score_screen # Returns carry set if starting game ; consider_starting_game &0b58 90 f2 BCC &0b4c ; wait_to_start_game ; start_game &0b5a a9 03 LDA #&03 &0b5c 85 3b STA &3b ; player_lives &0b5e a9 00 LDA #&00 &0b60 85 3c STA &3c ; level &0b62 85 3d STA &3d ; round &0b64 85 38 STA &38 ; score &0b66 85 39 STA &39 ; score + 1 &0b68 85 3a STA &3a ; score + 2 ; start_level &0b6a a6 3c LDX &3c ; level &0b6c a4 3d LDY &3d ; round &0b6e 20 cd 14 JSR &14cd ; initialise_screen &0b71 38 SEC &0b72 a9 0b LDA #&0b &0b74 e5 3d SBC &3d ; round &0b76 0a ASL A &0b77 0a ASL A &0b78 85 89 STA &89 ; new_balloon_or_dagger_frequency &0b7a bd 6b 19 LDA &196b,X ; level_data_addresses_low &0b7d 85 6d STA &6d ; level_data_address_low &0b7f bd 6e 19 LDA &196e,X ; level_data_addresses_high &0b82 85 6e STA &6e ; level_data_address_high &0b84 bd 71 19 LDA &1971,X ; level_times &0b87 85 83 STA &83 ; time_remaining + 1 &0b89 bd 74 19 LDA &1974,X ; level_tunes &0b8c 20 b4 18 JSR &18b4 ; start_tune # Start level tune &0b8f 20 65 15 JSR &1565 ; wipe_status_buffer &0b92 a2 00 LDX #&00 &0b94 86 32 STX &32 ; player_horizontal_frame &0b96 86 7b STX &7b ; player_is_dead &0b98 86 55 STX &55 ; yoyo_active # Set to positive to indicate yoyo not active &0b9a 86 54 STX &54 ; player_on_ladder &0b9c 86 53 STX &53 ; player_not_supported &0b9e 86 82 STX &82 ; time_remaining &0ba0 86 85 STX &85 ; time_has_elapsed # &00 to indicate time has not elapsed &0ba2 e8 INX ; 1 &0ba3 86 57 STX &57 ; player_direction &0ba5 86 88 STX &88 ; new_balloon_or_dagger_cooldown &0ba7 a9 32 LDA #&32 &0ba9 85 84 STA &84 ; time_remaining_fraction &0bab 20 db 0d JSR &0ddb ; wipe_objects &0bae 20 b8 17 JSR &17b8 ; initialise_level &0bb1 20 ff 13 JSR &13ff ; plot_objects &0bb4 20 db 15 JSR &15db ; plot_status &0bb7 c6 70 DEC &70 ; status_has_changed # Set to negative to update status &0bb9 a9 17 LDA #&17 ; SPRITE_KEY &0bbb a0 09 LDY #&09 ; OBJECT_CLASS_K &0bbd 20 7e 1b JSR &1b7e ; count_objects_of_sprite_A_in_class_Y # Returns X = number of objects &0bc0 ca DEX &0bc1 86 7a STX &7a ; keys_remaining &0bc3 a5 44 LDA &44 ; frame_counter &0bc5 85 71 STA &71 ; previous_frame_counter ; main_game_loop &0bc7 20 ac 11 JSR &11ac ; update_player &0bca 24 7b BIT &7b ; player_is_dead # Negative if player has died &0bcc 30 0f BMI &0bdd ; level_failed &0bce 24 7a BIT &7a ; keys_remaining # Negative if all keys have been collected &0bd0 30 22 BMI &0bf4 ; level_completed &0bd2 20 2c 0c JSR &0c2c ; update_time_and_check_for_keypresses # Returns non-zero if ESCAPE pressed &0bd5 d0 1a BNE &0bf1 ; to_wait_to_start_game &0bd7 20 a2 1b JSR &1ba2 ; update_balloons_and_daggers &0bda 4c c7 0b JMP &0bc7 ; main_game_loop ; level_failed &0bdd 20 27 0c JSR &0c27 ; stop_timer &0be0 a9 82 LDA #&82 &0be2 20 3c 16 JSR &163c ; update_time_and_check_for_keypresses_for_Y_frames &0be5 c6 3b DEC &3b ; player_lives &0be7 d0 3b BNE &0c24 ; to_start_level &0be9 20 4d 16 JSR &164d ; check_for_high_score &0bec 90 03 BCC &0bf1 ; to_wait_to_start_game &0bee 4c 5a 0b JMP &0b5a ; start_game ; to_wait_to_start_game &0bf1 4c 4c 0b JMP &0b4c ; wait_to_start_game ; level_completed &0bf4 20 cc 18 JSR &18cc ; completion_screen &0bf7 c6 2f DEC &2f ; suppress_tune # Set to negative to suppress tune &0bf9 a0 0a LDY #&0a &0bfb 84 3f STY &3f ; count ; add_ten_times_time_remaining_loop &0bfd a5 82 LDA &82 ; time_remaining &0bff 20 b8 15 JSR &15b8 ; add_to_score &0c02 a6 83 LDX &83 ; time_remaining + 1 &0c04 f0 08 BEQ &0c0e ; skip_minutes ; add_sixty_times_minutes_loop &0c06 a9 60 LDA #&60 &0c08 20 b8 15 JSR &15b8 ; add_to_score &0c0b ca DEX &0c0c d0 f8 BNE &0c06 ; add_sixty_times_minutes_loop ; skip_minutes &0c0e c6 3f DEC &3f ; count &0c10 d0 eb BNE &0bfd ; add_ten_times_time_remaining_loop &0c12 e6 3c INC &3c ; level &0c14 a5 3c LDA &3c ; level &0c16 c9 03 CMP #&03 &0c18 90 0a BCC &0c24 ; to_start_level &0c1a a9 00 LDA #&00 &0c1c 85 3c STA &3c ; level &0c1e 65 3d ADC &3d ; round &0c20 29 07 AND #&07 &0c22 85 3d STA &3d ; round ; to_start_level &0c24 4c 6a 0b JMP &0b6a ; start_level ; stop_timer &0c27 a9 40 LDA #&40 &0c29 85 85 STA &85 ; time_has_elapsed # Set &40 to indicate darkness has fallen &0c2b 60 RTS ; update_time_and_check_for_keypresses &0c2c 8a TXA &0c2d 48 PHA ; tmp_x &0c2e 98 TYA &0c2f 48 PHA ; tmp_y &0c30 24 85 BIT &85 ; time_has_elapsed # Negative if time needs updating &0c32 10 55 BPL &0c89 ; skip_updating_time &0c34 e6 85 INC &85 ; time_has_elapsed # Set to positive to indicate time doesn't need updating &0c36 38 SEC &0c37 f8 SED &0c38 a5 82 LDA &82 ; time_remaining &0c3a e9 01 SBC #&01 &0c3c b0 04 BCS &0c42 ; skip_underflow &0c3e c6 83 DEC &83 ; time_remaining + 1 &0c40 a9 59 LDA #&59 ; skip_underflow &0c42 85 82 STA &82 ; time_remaining &0c44 d8 CLD &0c45 20 db 15 JSR &15db ; plot_status &0c48 c6 70 DEC &70 ; status_has_changed # Set to negative to update status &0c4a a5 82 LDA &82 ; time_remaining &0c4c 05 83 ORA &83 ; time_remaining + 1 &0c4e d0 39 BNE &0c89 ; skip_updating_time # Has the player run out of time? &0c50 a9 40 LDA #&40 &0c52 85 85 STA &85 ; time_has_elapsed # Set &40 to indicate darkness has fallen &0c54 38 SEC &0c55 a5 89 LDA &89 ; new_balloon_or_dagger_frequency &0c57 e9 0a SBC #&0a # Balloons and daggers are more frequent in the dark &0c59 85 89 STA &89 ; new_balloon_or_dagger_frequency &0c5b a5 3d LDA &3d ; round &0c5d 4a LSR A &0c5e d0 0d BNE &0c6d ; not_regular_background # On rounds 0 and 1, set background to black &0c60 20 21 0d JSR &0d21 ; write_string &0c63 13 00 00 00 00 00 ; set colour 0 to black &0c69 ea NOP &0c6a 4c 89 0c JMP &0c89 ; skip_updating_time ; not_regular_background &0c6d 4a LSR A &0c6e 90 19 BCC &0c89 ; skip_updating_time # On rounds 4 and 5, do nothing &0c70 d0 0d BNE &0c7f ; is_black_background ; is_white_background # On rounds 2 and 3, flash white/black &0c72 20 21 0d JSR &0d21 ; write_string &0c75 13 03 0f 00 00 00 ; set colour 0 to flashing white/black &0c7b ea NOP &0c7c 4c 89 0c JMP &0c89 ; skip_updating_time ; is_black_background # On rounds 6 and 7, flash black/white &0c7f 20 21 0d JSR &0d21 ; write_string &0c82 13 03 08 00 00 00 ; set colour 0 to flashing black/white &0c88 ea NOP ; skip_updating_time &0c89 a9 ef LDA #&ef ; Q &0c8b a6 4b LDX &4b ; sound_muted # Negative if sound is muted &0c8d 10 02 BPL &0c91 ; check_for_sound_keypress &0c8f a9 ae LDA #&ae ; S ; check_for_sound_keypress &0c91 20 9c 0d JSR &0d9c ; check_for_keypress &0c94 f0 13 BEQ &0ca9 ; skip_toggling_sound_muted &0c96 8a TXA &0c97 49 ff EOR #&ff &0c99 85 4b STA &4b ; sound_muted &0c9b 10 0c BPL &0ca9 ; skip_toggling_sound_muted # Positive if sound is now enabled &0c9d a9 15 LDA #&15 ; Flush selected buffer &0c9f a2 04 LDX #&04 ; Sound channel 0 ; mute_channels_loop # If not, flush channels 0 - 3 and speech &0ca1 20 fb 0d JSR &0dfb ; safe_osbyte &0ca4 e8 INX &0ca5 e0 09 CPX #&09 &0ca7 90 f8 BCC &0ca1 ; mute_channels_loop ; skip_toggling_sound_muted &0ca9 a9 a6 LDA #&a6 ; DELETE &0cab 20 9c 0d JSR &0d9c ; check_for_keypress &0cae f0 3a BEQ &0cea ; skip_pausing # If DELETE is pressed, &0cb0 a9 96 LDA #&96 ; COPY &0cb2 20 9c 0d JSR &0d9c ; check_for_keypress &0cb5 d0 33 BNE &0cea ; skip_pausing # and COPY isn't, pause the game &0cb7 c6 92 DEC &92 ; game_is_paused &0cb9 24 85 BIT &85 ; time_has_elapsed &0cbb 30 02 BMI &0cbf ; write_freeze # Negative if time needs updating &0cbd 70 17 BVS &0cd6 ; wait_for_copy # &40 set if darkness has fallen ; write_freeze # i.e. write string if darkness hasn't fallen &0cbf 20 21 0d JSR &0d21 ; write_string &0cc2 1e ; HOME &0cc3 20 2a 2a 2a 20 46 72 65 65 7a 65 20 2a 2a 2a 20 ; " *** Freeze *** " &0cd3 ea NOP &0cd4 c6 70 DEC &70 ; status_has_changed # Set to negative to update status ; wait_for_copy &0cd6 a9 96 LDA #&96 ; COPY &0cd8 20 9c 0d JSR &0d9c ; check_for_keypress &0cdb f0 f9 BEQ &0cd6 ; wait_for_copy &0cdd 24 85 BIT &85 ; time_has_elapsed &0cdf 30 02 BMI &0ce3 ; not_dark # Negative if time needs updating &0ce1 70 05 BVS &0ce8 ; skip_replotting_status # &40 set if darkness has fallen ; not_dark # i.e. replot status if darkness hasn't fallen &0ce3 20 db 15 JSR &15db ; plot_status &0ce6 c6 70 DEC &70 ; status_has_changed # Set to negative to update status ; skip_replotting_status &0ce8 e6 92 INC &92 ; game_is_paused ; skip_pausing &0cea 68 PLA ; tmp_y &0ceb a8 TAY &0cec 68 PLA ; tmp_x &0ced aa TAX &0cee a9 8f LDA #&8f ; ESCAPE &0cf0 4c 9c 0d JMP &0d9c ; check_for_keypress # Leave with non-zero if ESCAPE pressed # &31f3 - &44ea is moved to &0d01 - &1ff8 at &46b2 ; wait_for_vsync &0d01 a5 44 LDA &44 ; frame_counter ; wait_for_vsync_loop &0d03 c5 44 CMP &44 ; frame_counter &0d05 f0 fc BEQ &0d03 ; wait_for_vsync_loop &0d07 60 RTS ; wait_to_plot_object_X &0d08 bd e3 03 LDA &03e3,X ; objects_y ; wait_to_plot_row_A &0d0b 45 74 EOR &74 ; level_is_inverted # Negative if level is inverted &0d0d 24 74 BIT &74 ; level_is_inverted &0d0f 10 03 BPL &0d14 ; skip_inversion &0d11 38 SEC &0d12 e9 1c SBC #&1c ; skip_inversion &0d14 4a LSR A &0d15 4a LSR A &0d16 18 CLC &0d17 69 ff ADC #&ff &0d19 29 3f AND #&3f ; wait_for_timer_loop &0d1b cd 69 fe CMP &fe69 ; User VIA timer 2 counter MSB &0d1e 90 fb BCC &0d1b ; wait_for_timer_loop &0d20 60 RTS ; write_string &0d21 68 PLA # String starts after function call &0d22 85 29 STA &29 ; text_address_low &0d24 68 PLA &0d25 85 2a STA &2a ; text_address_high &0d27 98 TYA &0d28 48 PHA ; tmp_y &0d29 4c 37 0d JMP &0d37 ; next_character ; write_string_loop &0d2c a0 00 LDY #&00 &0d2e b1 29 LDA (&29),Y ; next_character &0d30 c9 ea CMP #&ea ; NOP # &ea (NOP) marks end of string &0d32 f0 0b BEQ &0d3f ; leave_after_restoring_Y &0d34 20 ee ff JSR &ffee ; OSWRCH ; next_character &0d37 e6 29 INC &29 ; text_address_low &0d39 d0 f1 BNE &0d2c ; write_string_loop &0d3b e6 2a INC &2a ; text_address_high &0d3d d0 ed BNE &0d2c ; write_string_loop ; leave_after_restoring_Y &0d3f 68 PLA ; tmp_y &0d40 a8 TAY &0d41 6c 29 00 JMP (&0029) ; text_address # Return to code after end of string ; event_handler &0d44 08 PHP &0d45 48 PHA ; tmp_a &0d46 a9 50 LDA #&50 &0d48 8d 68 fe STA &fe68 ; User VIA timer 2 counter LSB &0d4b a9 46 LDA #&46 &0d4d 8d 69 fe STA &fe69 ; User VIA timer 2 counter MSB &0d50 24 92 BIT &92 ; game_is_paused # Negative if game is paused &0d52 30 12 BMI &0d66 ; leave_after_restoring_A &0d54 e6 44 INC &44 ; frame_counter &0d56 24 85 BIT &85 ; time_has_elapsed &0d58 30 02 BMI &0d5c ; reduce_time_remaining_fraction # Negative if time needs updating &0d5a 70 0a BVS &0d66 ; leave_after_restoring_A # &40 set if darkness has fallen ; reduce_time_remaining_fraction # i.e. reduce fraction if darkness hasn't fallen &0d5c c6 84 DEC &84 ; time_remaining_fraction &0d5e d0 06 BNE &0d66 ; leave_after_restoring_A &0d60 a9 32 LDA #&32 &0d62 85 84 STA &84 ; time_remaining_fraction &0d64 c6 85 DEC &85 ; time_has_elapsed # Set to negative to indicate time needs updating ; leave_after_restoring_A &0d66 68 PLA ; tmp_a &0d67 28 PLP &0d68 60 RTS ; irq1_handler &0d69 08 PHP &0d6a 48 PHA ; tmp_a &0d6b a9 20 LDA #&20 &0d6d 2c 6d fe BIT &fe6d ; User VIA interrupt flag register &0d70 f0 12 BEQ &0d84 ; skip_copying_status_buffer # &20 set if timer 2 interrupt has occurred &0d72 2c 68 fe BIT &fe68 ; User VIA timer 2 counter LSB # Clear timer 2 interrupt &0d75 24 70 BIT &70 ; status_has_changed # Negative if status has changed &0d77 10 0b BPL &0d84 ; skip_copying_status_buffer &0d79 98 TYA &0d7a 48 PHA ; tmp_y &0d7b a9 00 LDA #&00 &0d7d 85 70 STA &70 ; status_has_changed # Set to positive to indicate status hasn't changed &0d7f 20 4b 14 JSR &144b ; copy_status_buffer_to_screen &0d82 68 PLA ; tmp_y &0d83 a8 TAY ; skip_copying_status_buffer &0d84 2c 6d fe BIT &fe6d ; User VIA interrupt flag register &0d87 50 0e BVC &0d97 ; skip_updating_tune # &40 set if timer 1 interrupt has occurred &0d89 2c 64 fe BIT &fe64 ; User VIA timer 1 counter LSB # Clear timer 1 interrupt &0d8c a5 2f LDA &2f ; suppress_tune # Negative if tune suppressed &0d8e 05 92 ORA &92 ; game_is_paused # Negative if game is paused &0d90 30 05 BMI &0d97 ; skip_updating_tune &0d92 c6 91 DEC &91 ; tune_cooldown &0d94 20 6b 18 JSR &186b ; update_tune ; skip_updating_tune &0d97 68 PLA ; tmp_a &0d98 28 PLP &0d99 6c 4e 00 JMP (&004e) ; previous_irq1_vector ; check_for_keypress &0d9c 85 21 STA &21 ; keycode &0d9e 8a TXA &0d9f 48 PHA ; tmp_x &0da0 98 TYA &0da1 48 PHA ; tmp_y &0da2 a6 21 LDX &21 ; keycode &0da4 a0 ff LDY #&ff &0da6 a9 81 LDA #&81 ; Scan for a particular key &0da8 20 fb 0d JSR &0dfb ; safe_osbyte &0dab 68 PLA ; tmp_y &0dac a8 TAY &0dad 68 PLA ; tmp_x &0dae e0 00 CPX #&00 &0db0 08 PHP ; key pressed &0db1 aa TAX &0db2 a5 21 LDA &21 ; keycode &0db4 28 PLP ; key pressed &0db5 60 RTS # Leave with non-zero if key pressed ; rnd &0db6 85 26 STA &26 ; limit &0db8 a9 80 LDA #&80 ; calculate_mask_loop &0dba 24 26 BIT &26 ; limit &0dbc d0 05 BNE &0dc3 ; set_mask &0dbe 4a LSR A &0dbf 90 f9 BCC &0dba ; calculate_mask_loop &0dc1 a9 01 LDA #&01 ; set_mask &0dc3 38 SEC &0dc4 e9 01 SBC #&01 &0dc6 2a ROL A &0dc7 85 27 STA &27 ; mask ; rnd_loop &0dc9 a5 28 LDA &28 ; rnd_state &0dcb 69 63 ADC #&63 &0dcd 85 28 STA &28 ; rnd_state &0dcf 4d 64 fe EOR &fe64 ; User VIA timer 1 counter LSB &0dd2 25 27 AND &27 ; mask &0dd4 c5 26 CMP &26 ; limit &0dd6 f0 02 BEQ &0dda ; leave &0dd8 b0 ef BCS &0dc9 ; rnd_loop ; leave &0dda 60 RTS ; wipe_objects &0ddb a0 7b LDY #&7b &0ddd a9 ff LDA #&ff ; SPRITE_NONE ; wipe_objects_sprite_loop &0ddf 99 5d 04 STA &045d,Y ; objects_sprite - 1 # Wipe &045e - &04d8 with &ff &0de2 88 DEY &0de3 d0 fa BNE &0ddf ; wipe_objects_sprite_loop &0de5 a2 17 LDX #&17 ; wipe_objects_velocity_loop &0de7 a9 ff LDA #&ff &0de9 9d ef 04 STA &04ef,X ; objects_y_velocity - 1 # Wipe &04f0 - &0506 with &ff &0dec 98 TYA ; 0 &0ded 9d d8 04 STA &04d8,X ; objects_x_velocity - 1 # Wipe &04d9 - &04ef with &00 &0df0 ca DEX &0df1 d0 f4 BNE &0de7 ; wipe_objects_velocity_loop ; leave &0df3 60 RTS ; keyboard_handler &0df4 70 fd BVS &0df3 ; leave &0df6 90 fb BCC &0df3 ; leave # Leave unless scanning keyboard &0df8 6c 4c 00 JMP (&004c) ; previous_keyboard_vector_low ; safe_osbyte &0dfb c6 93 DEC &93 ; in_system_call # Set to negative to indicate in system call &0dfd 20 f4 ff JSR &fff4 ; OSBYTE &0e00 e6 93 INC &93 ; in_system_call # Set to positive to indicate not in system call &0e02 60 RTS ; safe_osword &0e03 c6 93 DEC &93 ; in_system_call # Set to negative to indicate in system call &0e05 20 f1 ff JSR &fff1 ; OSWORD &0e08 e6 93 INC &93 ; in_system_call # Set to positive to indicate not in system call &0e0a 60 RTS ; check_if_player_is_on_ladder # Called with A = player object &0e0b 85 26 STA &26 ; object &0e0d 8a TXA &0e0e 48 PHA ; tmp_x &0e0f 98 TYA &0e10 48 PHA ; tmp_y &0e11 a6 26 LDX &26 ; object &0e13 38 SEC &0e14 e9 0e SBC #&0e # Consider player's feet, not player's centre &0e16 85 48 STA &48 ; object_min_y &0e18 18 CLC &0e19 69 1e ADC #&1e # Consider player's head &0e1b 85 47 STA &47 ; object_max_y &0e1d bc 68 03 LDY &0368,X ; objects_x &0e20 84 45 STY &45 ; object_min_x # Player must be approximately aligned with ladder &0e22 c8 INY &0e23 84 46 STY &46 ; object_max_x &0e25 a9 04 LDA #&04 ; OBJECT_CLASS_IS_LADDER &0e27 20 72 14 JSR &1472 ; check_if_region_overlaps_classes # Returns carry set if object overlaps &0e2a 68 PLA ; tmp_y &0e2b a8 TAY &0e2c 68 PLA ; tmp_x &0e2d aa TAX &0e2e 60 RTS # Leave with carry set if player on ladder ; consider_starting_to_climb_ladder # Called with Y = new player_y &0e2f a9 00 LDA #&00 ; OBJECT_PLAYER &0e31 20 0b 0e JSR &0e0b ; check_if_player_is_on_ladder # Returns carry set if player on ladder &0e34 90 28 BCC &0e5e ; leave &0e36 24 53 BIT &53 ; player_not_supported # Negative if player is not supported &0e38 30 1b BMI &0e55 ; start_climbing_ladder # i.e. player is jumping onto ladder &0e3a cc e3 03 CPY &03e3 ; player_y &0e3d 08 PHP ; player y direction &0e3e 86 26 STX &26 ; tmp_x &0e40 a6 64 LDX &64 ; overlapping_object &0e42 bd e3 03 LDA &03e3,X ; objects_y &0e45 cd e3 03 CMP &03e3 ; player_y # Carry set if ladder is above player &0e48 6a ROR A &0e49 a6 26 LDX &26 ; tmp_x &0e4b 85 26 STA &26 ; ladder_sign # Negative if ladder is above player &0e4d 28 PLP ; player y direction # Carry set if player is moving up &0e4e 6a ROR A # Negative if player is moving up &0e4f 18 CLC &0e50 45 26 EOR &26 ; ladder_sign # If ladder is in wrong direction, &0e52 30 0a BMI &0e5e ; leave # Leave with carry clear to indicate not climbing ladder &0e54 38 SEC ; start_climbing_ladder &0e55 c6 54 DEC &54 ; player_on_ladder # Set to negative to indicate player is on ladder &0e57 a9 00 LDA #&00 &0e59 8d d9 04 STA &04d9 ; player_x_velocity &0e5c a2 13 LDX #&13 ; SPRITE_TROGG_CLIMBING ; leave &0e5e 60 RTS # Leave with carry set to indicate player climbing ladder ; check_if_player_is_on_platform # Called with A = new player_y &0e5f 85 47 STA &47 ; object_max_y &0e61 85 48 STA &48 ; object_min_y &0e63 c6 48 DEC &48 ; object_min_y &0e65 8a TXA &0e66 48 PHA ; tmp_x &0e67 98 TYA &0e68 48 PHA ; tmp_y &0e69 a2 00 LDX #&00 ; OBJECT_PLAYER &0e6b bd 68 03 LDA &0368,X ; objects_x &0e6e 85 45 STA &45 ; object_min_x &0e70 85 46 STA &46 ; object_max_x &0e72 e6 46 INC &46 ; object_max_x &0e74 a9 02 LDA #&02 ; OBJECT_CLASS_IS_PLATFORM &0e76 20 72 14 JSR &1472 ; check_if_region_overlaps_classes # Returns carry set if object overlaps &0e79 68 PLA ; tmp_y &0e7a a8 TAY &0e7b 68 PLA ; tmp_x &0e7c aa TAX &0e7d 60 RTS # Returns carry set if player on platform ; yoyo_body_sprites &0e7e 0e ; SPRITE_YOYO_LEFT &0e7f 0d ; SPRITE_YOYO_RIGHT &0e80 0f ; SPRITE_YOYO_RIGHT_INVERTED &0e81 10 ; SPRITE_YOYO_LEFT_INVERTED ; yoyo_string_sprites &0e82 ff ; SPRITE_NONE &0e83 28 ; SPRITE_YOYO_STRING_ONE &0e84 29 ; SPRITE_YOYO_STRING_TWO &0e85 2a ; SPRITE_YOYO_STRING_THREE &0e86 2b ; SPRITE_YOYO_STRING_FOUR &0e87 2c ; SPRITE_YOYO_STRING_FIVE &0e88 2d ; SPRITE_YOYO_STRING_SIX &0e89 2e ; SPRITE_YOYO_STRING_SEVEN &0e8a 2f ; SPRITE_YOYO_STRING_EIGHT &0e8b 30 ; SPRITE_YOYO_STRING_NINE &0e8c 31 ; SPRITE_YOYO_STRING_TEN &0e8d 32 ; SPRITE_YOYO_STRING_ELEVEN &0e8e 33 ; SPRITE_YOYO_STRING_TWELVE ; release_yoyo &0e8f 86 58 STX &58 ; player_sprite_on_platform &0e91 c6 55 DEC &55 ; yoyo_active # Set to negative to indicate yoyo active &0e93 a9 00 LDA #&00 &0e95 8d d9 04 STA &04d9 ; player_x_velocity &0e98 a2 02 LDX #&02 ; OBJECT_YOYO_BODY &0e9a 18 CLC &0e9b a5 57 LDA &57 ; player_direction &0e9d 9d d9 04 STA &04d9,X ; objects_x_velocity # Yoyo moves in direction player is facing &0ea0 6d 68 03 ADC &0368 ; player_x &0ea3 24 57 BIT &57 ; player_direction &0ea5 10 03 BPL &0eaa ; set_yoyo_body_x &0ea7 38 SEC # Offset position if player is facing left &0ea8 e9 02 SBC #&02 ; set_yoyo_body_x &0eaa 9d 68 03 STA &0368,X ; objects_x &0ead 85 65 STA &65 ; yoyo_start_x &0eaf 18 CLC &0eb0 69 02 ADC #&02 &0eb2 8d 69 03 STA &0369 ; objects_x + 1 (OBJECT_YOYO_STRING) &0eb5 18 CLC &0eb6 ad e3 03 LDA &03e3 ; player_y &0eb9 69 0b ADC #&0b &0ebb 8d e4 03 STA &03e4 ; objects_y + 1 (OBJECT_YOYO_STRING) &0ebe 8d e5 03 STA &03e5 ; objects_y + 2 (OBJECT_YOYO_BODY) &0ec1 ee e4 03 INC &03e4 ; objects_y + 1 (OBJECT_YOYO_STRING) &0ec4 a0 01 LDY #&01 &0ec6 84 79 STY &79 ; yoyo_string_length_delta # Yoyo is extending &0ec8 88 DEY ; 0 &0ec9 84 66 STY &66 ; yoyo_frame &0ecb 88 DEY ; &ff &0ecc 84 67 STY &67 ; yoyo_state # Will be incremented on first update &0ece 84 78 STY &78 ; yoyo_string_length # Will be incremented on first update &0ed0 a2 3d LDX #&3d ; SPRITE_TROGG_LEFT_RELEASED &0ed2 a5 57 LDA &57 ; player_direction &0ed4 30 04 BMI &0eda ; set_yoyo_string_x_velocity &0ed6 a9 00 LDA #&00 &0ed8 a2 3c LDX #&3c ; SPRITE_TROGG_RIGHT_RELEASED ; set_yoyo_string_x_velocity &0eda 8d da 04 STA &04da ; objects_x_velocity + 1 (OBJECT_YOYO_STRING) ; move_player_with_yoyo_active &0edd 8a TXA &0ede 48 PHA ; player sprite &0edf a2 00 LDX #&00 ; OBJECT_PLAYER &0ee1 20 08 0d JSR &0d08 ; wait_to_plot_object_X &0ee4 e6 67 INC &67 ; yoyo_state &0ee6 f0 0f BEQ &0ef7 ; skip_unplotting_yoyo &0ee8 e8 INX ; 1 = OBJECT_YOYO_STRING &0ee9 bd 5e 04 LDA &045e,X ; objects_sprite &0eec c9 ff CMP #&ff ; SPRITE_NONE &0eee f0 03 BEQ &0ef3 ; skip_unplotting_yoyo &0ef0 20 23 0b JSR &0b23 ; unplot_object_with_background # Unplot yoyo string &0ef3 e8 INX ; 2 = OBJECT_YOYO_BODY &0ef4 20 23 0b JSR &0b23 ; unplot_object_with_background # Unplot yoyo body ; skip_unplotting_yoyo &0ef7 a2 02 LDX #&02 ; OBJECT_YOYO_BODY &0ef9 18 CLC &0efa a5 66 LDA &66 ; yoyo_frame &0efc 7d d9 04 ADC &04d9,X ; objects_x_velocity # Animate yoyo body &0eff 30 08 BMI &0f09 ; wraparound_floor &0f01 c9 04 CMP #&04 &0f03 90 06 BCC &0f0b ; set_yoyo_frame &0f05 a9 00 LDA #&00 &0f07 f0 02 BEQ &0f0b ; set_yoyo_frame # Always branches ; wraparound_floor &0f09 a9 03 LDA #&03 ; set_yoyo_frame &0f0b 85 66 STA &66 ; yoyo_frame &0f0d aa TAX &0f0e bd 7e 0e LDA &0e7e,X ; yoyo_body_sprites &0f11 a2 02 LDX #&02 ; OBJECT_YOYO_BODY &0f13 9d 5e 04 STA &045e,X ; objects_sprite # Set sprite for yoyo body &0f16 a5 57 LDA &57 ; player_direction &0f18 cd db 04 CMP &04db ; objects_x_velocity + 2 (OBJECT_YOYO_BODY) &0f1b d0 19 BNE &0f36 ; skip_setting_yoyo_returning # If yoyo is not already returning, &0f1d bd 68 03 LDA &0368,X ; objects_x &0f20 c9 c8 CMP #&c8 &0f22 b0 0f BCS &0f33 ; to_set_yoyo_returning # If yoyo is at edge of screen, set returning &0f24 a5 67 LDA &67 ; yoyo_state &0f26 c9 05 CMP #&05 &0f28 90 0c BCC &0f36 ; skip_setting_yoyo_returning # Yoyo extends for four updates &0f2a c9 0b CMP #&0b &0f2c b0 05 BCS &0f33 ; to_set_yoyo_returning # Yoyo returns after eleven updates &0f2e 20 59 13 JSR &1359 ; check_for_player_fire # Return non-zero if player pressed fire &0f31 d0 03 BNE &0f36 ; skip_setting_yoyo_returning # In between, fire must be pressed to stop returning ; to_set_yoyo_returning &0f33 20 74 10 JSR &1074 ; set_yoyo_returning ; skip_setting_yoyo_returning ; apply_yoyo_velocities_loop # Apply velocities to yoyo string and body &0f36 18 CLC &0f37 bd 68 03 LDA &0368,X ; objects_x &0f3a 7d d9 04 ADC &04d9,X ; objects_x_velocity &0f3d 18 CLC &0f3e 7d d9 04 ADC &04d9,X ; objects_x_velocity &0f41 9d 68 03 STA &0368,X ; objects_x &0f44 ca DEX &0f45 d0 ef BNE &0f36 ; apply_yoyo_velocities_loop &0f47 18 CLC &0f48 a5 78 LDA &78 ; yoyo_string_length &0f4a 65 79 ADC &79 ; yoyo_string_length_delta # Extend or shorten yoyo string &0f4c 85 78 STA &78 ; yoyo_string_length &0f4e a8 TAY &0f4f b9 82 0e LDA &0e82,Y ; yoyo_string_sprites &0f52 8d 5f 04 STA &045f ; objects_sprite + 1 (OBJECT_YOYO_STRING) # Set sprite for yoyo string &0f55 ad 6a 03 LDA &036a ; objects_x + 2 (OBJECT_YOYO_BODY) &0f58 c5 65 CMP &65 ; yoyo_start_x &0f5a f0 74 BEQ &0fd0 ; remove_yoyo # If the yoyo has returned to the player, remove it &0f5c a2 02 LDX #&02 ; OBJECT_YOYO_BODY &0f5e a9 08 LDA #&08 ; OBJECT_CLASS_IS_YOYOABLE &0f60 24 85 BIT &85 ; time_has_elapsed &0f62 30 04 BMI &0f68 ; check_if_yoyo_has_hit_something # Negative if time needs updating &0f64 50 02 BVC &0f68 ; check_if_yoyo_has_hit_something # &40 clear if darkness hasn't fallen &0f66 a9 80 LDA #&80 ; OBJECT_CLASS_IS_YOYOABLE_IN_DARK ; check_if_yoyo_has_hit_something &0f68 20 bd 1c JSR &1cbd ; check_if_object_overlaps_classes # Returns carry set if object overlaps &0f6b b0 0c BCS &0f79 ; yoyo_hit_object ; plot_yoyo_loop &0f6d 20 20 0b JSR &0b20 ; plot_object_without_background &0f70 ca DEX &0f71 d0 fa BNE &0f6d ; plot_yoyo_loop &0f73 68 PLA ; player sprite &0f74 aa TAX ; leave_with_player_y &0f75 ac e3 03 LDY &03e3 ; player_y &0f78 60 RTS ; yoyo_hit_object &0f79 a2 ac LDX #&ac ; sound_1 &0f7b 20 a9 18 JSR &18a9 ; play_sound # Play sound for yoyo hitting something &0f7e a5 94 LDA &94 ; overlapping_class &0f80 c9 0c CMP #&0c ; OBJECT_CLASS_M &0f82 d0 36 BNE &0fba ; not_monster # Did the yoyo hit a monster? ; yoyo_hit_monster &0f84 a2 01 LDX #&01 ; OBJECT_YOYO_STRING &0f86 20 20 0b JSR &0b20 ; plot_object_without_background # Plot yoyo string &0f89 e8 INX ; 2 = OBJECT_YOYO_BODY &0f8a 20 20 0b JSR &0b20 ; plot_object_without_background # Plot yoyo body &0f8d a6 64 LDX &64 ; overlapping_object &0f8f a9 05 LDA #&05 &0f91 85 34 STA &34 ; count ; animate_flying_monster_loop &0f93 20 01 0d JSR &0d01 ; wait_for_vsync &0f96 20 08 0d JSR &0d08 ; wait_to_plot_object_X &0f99 20 23 0b JSR &0b23 ; unplot_object_with_background # Unplot monster &0f9c bd 68 03 LDA &0368,X ; objects_x &0f9f a0 08 LDY #&08 &0fa1 18 CLC ; add_player_direction_times_eight_loop &0fa2 65 57 ADC &57 ; player_direction # Move monster left or right &0fa4 88 DEY &0fa5 d0 fa BNE &0fa1 ; add_player_direction_times_eight_loop &0fa7 9d 68 03 STA &0368,X ; objects_x &0faa 20 20 0b JSR &0b20 ; plot_object_without_background # Replot monster &0fad c6 34 DEC &34 ; count &0faf d0 e2 BNE &0f93 ; animate_flying_monster_loop &0fb1 a2 01 LDX #&01 ; OBJECT_YOYO_STRING &0fb3 20 23 0b JSR &0b23 ; unplot_object_with_background # Unplot yoyo string &0fb6 e8 INX ; 2 = OBJECT_YOYO_BODY &0fb7 20 23 0b JSR &0b23 ; unplot_object_with_background # Unplot yoyo body ; not_monster &0fba 20 74 10 JSR &1074 ; set_yoyo_returning &0fbd a6 64 LDX &64 ; overlapping_object &0fbf 20 a0 12 JSR &12a0 ; collect_object_without_sound &0fc2 a9 25 LDA #&25 # Score 250 for hitting something with yoyo &0fc4 20 b8 15 JSR &15b8 ; add_to_score &0fc7 20 db 15 JSR &15db ; plot_status &0fca c6 70 DEC &70 ; status_has_changed # Set to negative to update status &0fcc a2 02 LDX #&02 ; OBJECT_YOYO_BODY &0fce d0 9d BNE &0f6d ; plot_yoyo_loop # Always branches ; remove_yoyo &0fd0 e6 55 INC &55 ; yoyo_active # Set to positive to indicate yoyo not active &0fd2 a9 ff LDA #&ff ; SPRITE_NONE &0fd4 8d 5f 04 STA &045f ; objects_sprite + 1 (OBJECT_YOYO_STRING) # Remove yoyo string &0fd7 8d 60 04 STA &0460 ; objects_sprite + 2 (OBJECT_YOYO_BODY) # Remove yoyo body &0fda 68 PLA ; player sprite &0fdb a6 58 LDX &58 ; player_sprite_on_platform # Use sprite prior to yoyo release &0fdd d0 96 BNE &0f75 ; leave_with_player_y # Always branches ; to_release_yoyo &0fdf 4c 8f 0e JMP &0e8f ; release_yoyo ; to_move_player_on_ladder &0fe2 4c 3b 11 JMP &113b ; move_player_on_ladder ; to_move_player_not_on_platform_or_ladder &0fe5 4c de 10 JMP &10de ; move_player_not_on_platform_or_ladder ; to_move_player_with_yoyo_active &0fe8 4c dd 0e JMP &0edd ; move_player_with_yoyo_active ; move_player &0feb 46 5d LSR &5d ; jump_roller &0fed ae 5e 04 LDX &045e ; player_sprite &0ff0 ac e3 03 LDY &03e3 ; player_y &0ff3 24 55 BIT &55 ; yoyo_active # Negative if yoyo is active &0ff5 30 f1 BMI &0fe8 ; to_move_player_with_yoyo_active &0ff7 24 53 BIT &53 ; player_not_supported # Negative if player is not supported &0ff9 30 ea BMI &0fe5 ; to_move_player_not_on_platform_or_ladder &0ffb 24 54 BIT &54 ; player_on_ladder # Negative if player is on ladder &0ffd 30 e3 BMI &0fe2 ; to_move_player_on_ladder ; move_player_on_platform &0fff a2 00 LDX #&00 &1001 20 f9 12 JSR &12f9 ; check_for_player_horizontal_movement &1004 8e d9 04 STX &04d9 ; player_x_velocity &1007 8a TXA &1008 f0 02 BEQ &100c ; skip_setting_player_direction &100a 86 57 STX &57 ; player_direction ; skip_setting_player_direction &100c ae 5e 04 LDX &045e ; player_sprite &100f 86 58 STX &58 ; player_sprite_on_platform &1011 20 1d 13 JSR &131d ; check_for_player_vertical_movement # Returns Y = new player_y &1014 cc e3 03 CPY &03e3 ; player_y &1017 f0 16 BEQ &102f ; no_vertical_movement &1019 20 2f 0e JSR &0e2f ; consider_starting_to_climb_ladder # Returns carry set if player starting to climb ladder &101c b0 4b BCS &1069 ; leave &101e cc e3 03 CPY &03e3 ; player_y &1021 ac e3 03 LDY &03e3 ; player_y &1024 90 09 BCC &102f ; no_vertical_movement # Carry clear if player isn't moving upwards &1026 24 5d BIT &5d ; jump_roller &1028 50 0a BVC &1034 ; skip_jump_roller # &40 set if player hasn't recently moved vertically &102a 90 03 BCC &102f ; no_vertical_movement # Unnecessary code &102c 4c cb 10 JMP &10cb ; start_jump ; no_vertical_movement &102f 06 5d ASL &5d ; jump_roller &1031 38 SEC # Set top bit of jump_roller when not moving vertically &1032 66 5d ROR &5d ; jump_roller ; skip_jump_roller &1034 ad d9 04 LDA &04d9 ; player_x_velocity &1037 f0 20 BEQ &1059 ; no_horizontal_movement &1039 30 11 BMI &104c ; moving_left ; moving_right &103b a6 32 LDX &32 ; player_horizontal_frame &103d e8 INX &103e e0 04 CPX #&04 &1040 90 02 BCC &1044 ; skip_wraparound &1042 a2 00 LDX #&00 ; skip_wraparound &1044 86 32 STX &32 ; player_horizontal_frame &1046 bd 8a 12 LDA &128a,X ; player_right_sprites &1049 aa TAX &104a d0 0d BNE &1059 ; no_horizontal_movement # Always branches ; moving_left &104c a6 32 LDX &32 ; player_horizontal_frame &104e ca DEX &104f 10 02 BPL &1053 ; skip_wraparound &1051 a2 03 LDX #&03 ; skip_wraparound &1053 86 32 STX &32 ; player_horizontal_frame &1055 bd 8e 12 LDA &128e,X ; player_left_sprites &1058 aa TAX ; no_horizontal_movement &1059 20 59 13 JSR &1359 ; check_for_player_fire # Return non-zero if player pressed fire &105c d0 81 BNE &0fdf ; to_release_yoyo &105e a9 00 LDA #&00 ; OBJECT_PLAYER &1060 20 85 10 JSR &1085 ; check_if_player_hit_platform # Returns carry set if player hit platform &1063 b0 05 BCS &106a ; put_player_on_platform &1065 a9 ff LDA #&ff &1067 85 53 STA &53 ; player_not_supported # Set to negative to indicate player is not supported ; leave &1069 60 RTS ; put_player_on_platform &106a a4 64 LDY &64 ; overlapping_object &106c 84 77 STY &77 ; unused # Unused variable &106e b9 e3 03 LDA &03e3,Y ; objects_y &1071 a8 TAY &1072 c8 INY # Set player y to one row above platform &1073 60 RTS ; set_yoyo_returning &1074 a9 ff LDA #&ff &1076 85 79 STA &79 ; yoyo_string_length_delta # Set yoyo string shortening &1078 a5 57 LDA &57 ; player_direction &107a 49 fe EOR #&fe # towards player &107c 8d db 04 STA &04db ; objects_x_velocity + 2 (OBJECT_YOYO_BODY) &107f 30 e8 BMI &1069 ; leave &1081 8d da 04 STA &04da ; objects_x_velocity + 1 (OBJECT_YOYO_STRING) &1084 60 RTS ; check_if_player_hit_platform &1085 85 26 STA &26 ; player_object &1087 8a TXA &1088 48 PHA ; tmp_x &1089 98 TYA &108a 48 PHA ; tmp_y &108b a6 26 LDX &26 ; player_object &108d 18 CLC &108e bd 68 03 LDA &0368,X ; objects_x &1091 7d d9 04 ADC &04d9,X ; objects_x_velocity &1094 85 45 STA &45 ; object_min_x &1096 85 46 STA &46 ; object_max_x &1098 e6 46 INC &46 ; object_max_x &109a 18 CLC &109b bd e3 03 LDA &03e3,X ; objects_y &109e 85 47 STA &47 ; object_max_y &10a0 7d f0 04 ADC &04f0,X ; objects_y_velocity &10a3 85 48 STA &48 ; object_min_y &10a5 bd f0 04 LDA &04f0,X ; objects_y_velocity &10a8 10 1b BPL &10c5 ; leave_with_sign_of_A_in_carry # Leave with carry clear if jumping &10aa a9 02 LDA #&02 ; OBJECT_CLASS_IS_PLATFORM &10ac 20 72 14 JSR &1472 ; check_if_region_overlaps_classes # Returns carry set if object overlaps &10af 90 15 BCC &10c6 ; leave_after_restoring_registers # Leave with carry clear if not overlapping platform &10b1 a6 33 LDX &33 ; object_being_checked # If the player overlaps with a platform, &10b3 a9 f6 LDA #&f6 &10b5 dd f0 04 CMP &04f0,X ; objects_y_velocity # and the player is falling very fast, &10b8 b0 0c BCS &10c6 ; leave_after_restoring_registers # leave with carry set to indicate player hit platform &10ba a6 64 LDX &64 ; overlapping_object &10bc 38 SEC &10bd bd e3 03 LDA &03e3,X ; objects_y # If (platform_y - (player_y + velocity) - 5) < 0, &10c0 e5 48 SBC &48 ; object_min_y &10c2 38 SEC &10c3 e9 05 SBC #&05 ; leave_with_sign_of_A_in_carry &10c5 0a ASL A # leave with carry set to indicate player hit platform ; leave_after_restoring_registers &10c6 68 PLA ; tmp_x &10c7 a8 TAY &10c8 68 PLA ; tmp_y &10c9 aa TAX &10ca 60 RTS ; start_jump &10cb a9 05 LDA #&05 &10cd 8d f0 04 STA &04f0 ; player_y_velocity # Set player jumping up &10d0 c6 53 DEC &53 ; player_not_supported # Set to negative to indicate player is not supported &10d2 ad d9 04 LDA &04d9 ; player_x_velocity &10d5 f0 07 BEQ &10de ; move_player_not_on_platform_or_ladder &10d7 a2 36 LDX #&36 ; SPRITE_TROGG_RIGHT_HOLDING_THREE # Spread legs when jumping horizontally &10d9 0a ASL A &10da 90 02 BCC &10de ; move_player_not_on_platform_or_ladder &10dc a2 3a LDX #&3a ; SPRITE_TROGG_LEFT_HOLDING_THREE ; move_player_not_on_platform_or_ladder &10de 20 1d 13 JSR &131d ; check_for_player_vertical_movement # Returns Y = new player_y &10e1 18 CLC &10e2 ad e3 03 LDA &03e3 ; player_y &10e5 6d f0 04 ADC &04f0 ; player_y_velocity &10e8 2c f0 04 BIT &04f0 ; player_y_velocity &10eb 10 06 BPL &10f3 ; is_jumping &10ed b0 12 BCS &1101 ; is_falling &10ef a0 00 LDY #&00 # Don't allow player to fall through floor &10f1 f0 33 BEQ &1126 ; has_hit_platform # Always branches ; is_jumping &10f3 c9 de CMP #&de &10f5 90 0a BCC &1101 ; is_falling # Has the player hit the ceiling? &10f7 a9 00 LDA #&00 &10f9 ed f0 04 SBC &04f0 ; player_y_velocity # If so, invert y velocity &10fc 8d f0 04 STA &04f0 ; player_y_velocity &10ff a9 de LDA #&de # and clip player_y to ceiling ; is_falling &1101 ce f0 04 DEC &04f0 ; player_y_velocity # Player accelerates downwards &1104 cc e3 03 CPY &03e3 ; player_y &1107 08 PHP ; player y comparison &1108 a8 TAY &1109 28 PLP ; player y comparison &110a f0 0c BEQ &1118 ; skip_ladder_check # Has the player changed position vertically? &110c ad f0 04 LDA &04f0 ; player_y_velocity &110f c9 f9 CMP #&f9 # Can't climb ladder if falling too fast &1111 30 05 BMI &1118 ; skip_ladder_check &1113 20 2f 0e JSR &0e2f ; consider_starting_to_climb_ladder # Returns carry set if player starting to climb ladder &1116 b0 0e BCS &1126 ; has_hit_platform ; skip_ladder_check &1118 a9 00 LDA #&00 ; OBJECT_PLAYER &111a 20 85 10 JSR &1085 ; check_if_player_hit_platform # Returns carry set if player hit platform &111d 90 1b BCC &113a ; leave &111f a4 64 LDY &64 ; overlapping_object &1121 b9 e3 03 LDA &03e3,Y ; objects_y &1124 a8 TAY # Set player y to one row above platform &1125 c8 INY ; has_hit_platform &1126 e6 53 INC &53 ; player_not_supported # Set to positive to indicate player is supported &1128 ad f0 04 LDA &04f0 ; player_y_velocity &112b c9 f9 CMP #&f9 &112d 10 06 BPL &1135 ; not_deadly_fall &112f c9 f9 CMP #&f9 &1131 b0 02 BCS &1135 ; not_deadly_fall &1133 c6 7b DEC &7b ; player_is_dead # Kill player for falling too fast ; not_deadly_fall &1135 a9 ff LDA #&ff &1137 8d f0 04 STA &04f0 ; player_y_velocity ; leave &113a 60 RTS ; move_player_on_ladder # Called with Y = player_y &113b a9 00 LDA #&00 ; OBJECT_PLAYER &113d 20 0b 0e JSR &0e0b ; check_if_player_is_on_ladder # Returns carry set if player on ladder &1140 90 5d BCC &119f ; falling_off_ladder &1142 20 1d 13 JSR &131d ; check_for_player_vertical_movement # Returns Y = new player_y &1145 ad 5e 04 LDA &045e ; player_sprite &1148 cc e3 03 CPY &03e3 ; player_y &114b f0 02 BEQ &114f ; skip_climbing_animation # Has the player changed position vertically? &114d 49 07 EOR #&07 ; SPRITE_TROGG_CLIMBING ^ SPRITE_TROGG_CLIMBING_TWO ; skip_climbing_animation &114f 48 PHA ; sprite &1150 a6 64 LDX &64 ; overlapping_object &1152 a9 02 LDA #&02 # Get a random number between 0 and 1 &1154 20 b6 0d JSR &0db6 ; rnd &1157 4a LSR A # Carry set if one time in two &1158 a9 00 LDA #&00 &115a 90 0a BCC &1166 ; set_player_x_velocity &115c 38 SEC &115d bd 68 03 LDA &0368,X ; objects_x &1160 ed 68 03 SBC &0368 ; player_x &1163 20 ae 15 JSR &15ae ; get_direction_from_sign # Align player with ladder ; set_player_x_velocity &1166 8d d9 04 STA &04d9 ; player_x_velocity &1169 98 TYA &116a dd e3 03 CMP &03e3,X ; objects_y &116d b0 18 BCS &1187 ; above_bottom_of_ladder ; below_bottom_of_ladder &116f cc e3 03 CPY &03e3 ; player_y &1172 b0 28 BCS &119c ; still_on_ladder &1174 98 TYA &1175 20 5f 0e JSR &0e5f ; check_if_player_is_on_platform # Returns carry set if player on platform &1178 90 22 BCC &119c ; still_on_ladder ; returning_to_platform &117a a6 64 LDX &64 ; overlapping_object &117c bd e3 03 LDA &03e3,X ; objects_y &117f a8 TAY # Set player y to one row above platform &1180 c8 INY &1181 e6 54 INC &54 ; player_on_ladder # Set to positive to indicate player not on ladder &1183 a6 58 LDX &58 ; player_sprite_on_platform &1185 68 PLA ; sprite &1186 60 RTS ; above_bottom_of_ladder &1187 cc e3 03 CPY &03e3 ; player_y &118a 90 10 BCC &119c ; still_on_ladder &118c f0 0e BEQ &119c ; still_on_ladder &118e ad e3 03 LDA &03e3 ; player_y &1191 20 5f 0e JSR &0e5f ; check_if_player_is_on_platform # Returns carry set if player on platform &1194 90 06 BCC &119c ; still_on_ladder &1196 98 TYA &1197 20 5f 0e JSR &0e5f ; check_if_player_is_on_platform # Returns carry set if player on platform &119a 90 de BCC &117a ; returning_to_platform ; still_on_ladder &119c 68 PLA ; sprite &119d aa TAX &119e 60 RTS ; falling_off_ladder &119f e6 54 INC &54 ; player_on_ladder # Set to positive to indicate player not on ladder &11a1 c6 53 DEC &53 ; player_not_supported # Set to negative to indicate player not supported &11a3 a9 00 LDA #&00 &11a5 8d d9 04 STA &04d9 ; player_x_velocity &11a8 a6 58 LDX &58 ; player_sprite_on_platform &11aa 60 RTS ; unused &11ab 60 RTS ; update_player ; wait_for_frame_counter &11ac a5 44 LDA &44 ; frame_counter # Wait for four frames between updates &11ae 38 SEC &11af e5 71 SBC &71 ; previous_frame_counter &11b1 c9 04 CMP #&04 &11b3 90 f7 BCC &11ac ; wait_for_frame_counter &11b5 a5 44 LDA &44 ; frame_counter &11b7 85 71 STA &71 ; previous_frame_counter &11b9 a9 00 LDA #&00 &11bb 85 52 STA &52 ; scrolling_occurred # Set to zero to indicate no scrolling occurred &11bd ac e3 03 LDY &03e3 ; player_y &11c0 20 eb 0f JSR &0feb ; move_player &11c3 18 CLC &11c4 ad 68 03 LDA &0368 ; player_x &11c7 6d d9 04 ADC &04d9 ; player_x_velocity &11ca c9 04 CMP #&04 &11cc 90 04 BCC &11d2 ; use_player_x &11ce c9 c4 CMP #&c4 &11d0 90 03 BCC &11d5 ; set_object_x ; use_player_x &11d2 ad 68 03 LDA &0368 ; player_x # Stop player going beyond edges of level ; set_object_x &11d5 85 69 STA &69 ; object_x &11d7 86 68 STX &68 ; object_sprite &11d9 84 6a STY &6a ; object_y &11db cd 68 03 CMP &0368 ; player_x &11de f0 23 BEQ &1203 ; skip_scrolling # Has the player changed position horizontally? &11e0 90 12 BCC &11f4 ; consider_scrolling_left ; consider_scrolling_right &11e2 c9 a0 CMP #&a0 &11e4 b0 1d BCS &1203 ; skip_scrolling &11e6 c9 29 CMP #&29 &11e8 90 19 BCC &1203 ; skip_scrolling &11ea a9 80 LDA #&80 ; SCROLL_RIGHT &11ec 85 52 STA &52 ; scrolling_occurred &11ee 20 e5 13 JSR &13e5 ; scroll_screen_right &11f1 4c 03 12 JMP &1203 ; skip_scrolling ; consider_scrolling_left &11f4 c9 28 CMP #&28 &11f6 90 0b BCC &1203 ; skip_scrolling &11f8 c9 9f CMP #&9f &11fa b0 07 BCS &1203 ; skip_scrolling &11fc a9 40 LDA #&40 ; SCROLL_LEFT &11fe 85 52 STA &52 ; scrolling_occurred &1200 20 cb 13 JSR &13cb ; scroll_screen_left ; skip_scrolling &1203 a2 00 LDX #&00 ; OBJECT_PLAYER &1205 20 3f 1c JSR &1c3f ; compare_object_details # Returns non-zero if object has changed &1208 f0 3c BEQ &1246 ; skip_replotting_player # Has the player changed position or sprite? &120a a5 6a LDA &6a ; object_y &120c 4a LSR A &120d 4a LSR A &120e 8d b8 01 STA &01b8 ; sound_2 + 4 (pitch) &1211 a2 b4 LDX #&b4 ; sound_2 &1213 20 a9 18 JSR &18a9 ; play_sound # Play sound for player changing position vertically &1216 a2 00 LDX #&00 ; OBJECT_PLAYER &1218 24 55 BIT &55 ; yoyo_active # Negative if yoyo is active &121a 30 06 BMI &1222 ; skip_wait &121c 20 01 0d JSR &0d01 ; wait_for_vsync &121f 20 08 0d JSR &0d08 ; wait_to_plot_object_X ; skip_wait &1222 20 28 14 JSR &1428 ; set_crtc_screen_start &1225 a5 52 LDA &52 ; scrolling_occurred &1227 f0 02 BEQ &122b ; skip_replotting_status # Zero if no scrolling occurred &1229 c6 70 DEC &70 ; status_has_changed # Set to negative to update status ; skip_replotting_status &122b a2 00 LDX #&00 ; OBJECT_PLAYER &122d 20 1c 0b JSR &0b1c ; unplot_object_without_background # Unplot player &1230 a5 68 LDA &68 ; object_sprite &1232 a6 69 LDX &69 ; object_x &1234 a4 6a LDY &6a ; object_y &1236 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &1239 a5 6a LDA &6a ; object_y &123b 20 0b 0d JSR &0d0b ; wait_to_plot_row_A &123e a2 00 LDX #&00 ; OBJECT_PLAYER &1240 20 18 0b JSR &0b18 ; plot_object_with_background # Plot player beneath background &1243 20 53 1c JSR &1c53 ; set_object_details ; skip_replotting_player &1246 20 20 0b JSR &0b20 ; plot_object_without_background # Play player on top of background &1249 a9 10 LDA #&10 ; OBJECT_CLASS_IS_COLLECTABLE # Check for collectable objects &124b 20 bd 1c JSR &1cbd ; check_if_object_overlaps_classes # Returns carry set if object overlaps &124e 90 0c BCC &125c ; not_collecting_object &1250 a6 64 LDX &64 ; overlapping_object &1252 bd 5e 04 LDA &045e,X ; objects_sprite &1255 a0 00 LDY #&00 # Consider collectable objects &1257 20 d1 12 JSR &12d1 ; call_sprite_update_routine # Collect object &125a a2 00 LDX #&00 ; OBJECT_PLAYER ; not_collecting_object &125c bd e3 03 LDA &03e3,X ; objects_y # Has the player hit the bottom of the screen? &125f f0 07 BEQ &1268 ; kill_player # If so, kill the player &1261 a9 01 LDA #&01 ; OBJECT_CLASS_IS_DEADLY # Check for deadly objects &1263 20 bd 1c JSR &1cbd ; check_if_object_overlaps_classes # Returns carry set if object overlaps &1266 90 02 BCC &126a ; not_touching_deadly_object ; kill_player &1268 c6 7b DEC &7b ; player_is_dead # Set to negative to indicate player is dead ; not_touching_deadly_object &126a 24 7b BIT &7b ; player_is_dead &126c 10 10 BPL &127e ; not_dead &126e a9 8e LDA #&8e ; tune_start_positions + 3 &1270 20 b4 18 JSR &18b4 ; start_tune # Start failure tune &1273 ae 68 03 LDX &0368 ; player_x &1276 ac e3 03 LDY &03e3 ; player_y &1279 a9 5b LDA #&5b ; SPRITE_FRAK_OFFSET &127b 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y # Plot "FRAK!" next to player ; not_dead &127e 24 52 BIT &52 ; scrolling_occurred &1280 70 05 BVS &1287 ; to_plot_objects_on_left_edge # &40 (SCROLL_LEFT) set if scrolling right &1282 10 24 BPL &12a8 ; leave # &80 (SCROLL_RIGHT) set if scrolling left &1284 4c f3 13 JMP &13f3 ; plot_objects_on_right_edge ; to_plot_objects_on_left_edge &1287 4c d9 13 JMP &13d9 ; plot_objects_on_left_edge ; player_right_sprites &128a 34 ; SPRITE_TROGG_RIGHT_HOLDING &128b 35 ; SPRITE_TROGG_RIGHT_HOLDING_TWO &128c 36 ; SPRITE_TROGG_RIGHT_HOLDING_THREE &128d 37 ; SPRITE_TROGG_RIGHT_HOLDING_FOUR ; player_left_sprites &128e 3b ; SPRITE_TROGG_LEFT_HOLDING_FOUR &128f 3a ; SPRITE_TROGG_LEFT_HOLDING_THREE &1290 39 ; SPRITE_TROGG_LEFT_HOLDING_TWO &1291 38 ; SPRITE_TROGG_LEFT_HOLDING ; collect_key &1292 a9 50 LDA #&50 # Score 500 for collecting key &1294 20 b8 15 JSR &15b8 ; add_to_score &1297 c6 7a DEC &7a ; keys_remaining ; collect_object &1299 a2 bc LDX #&bc ; sound_3 &129b 20 a9 18 JSR &18a9 ; play_sound # Play sound for collecting object &129e a6 64 LDX &64 ; overlapping_object ; collect_object_without_sound &12a0 20 23 0b JSR &0b23 ; unplot_object_with_background # Unplot object &12a3 a9 ff LDA #&ff ; SPRITE_NONE &12a5 9d 5e 04 STA &045e,X ; objects_sprite # Remove object ; leave &12a8 60 RTS ; collect_gem &12a9 a9 15 LDA #&15 # Score 150 for collecting gem &12ab 20 b8 15 JSR &15b8 ; add_to_score ; collect_object_without_scoring &12ae 20 99 12 JSR &1299 ; collect_object &12b1 20 db 15 JSR &15db ; plot_status &12b4 c6 70 DEC &70 ; status_has_changed # Set to negative to update status ; leave &12b6 60 RTS ; collect_bulb &12b7 24 85 BIT &85 ; time_has_elapsed &12b9 30 02 BMI &12bd ; add_time # Negative if time needs updating &12bb 70 f9 BVS &12b6 ; leave # &40 set if darkness has fallen ; add_time # i.e. add time if darkness hasn't fallen &12bd 18 CLC &12be f8 SED &12bf a5 82 LDA &82 ; time_remaining &12c1 69 10 ADC #&10 # Gain 10 seconds for collecting bulb &12c3 c9 60 CMP #&60 &12c5 90 04 BCC &12cb ; skip_overflow &12c7 e9 60 SBC #&60 &12c9 e6 83 INC &83 ; time_remaining + 1 ; skip_overflow &12cb 85 82 STA &82 ; time_remaining &12cd d8 CLD &12ce 4c ae 12 JMP &12ae ; collect_object_without_scoring ; call_sprite_update_routine ; find_sprite_update_routine_loop &12d1 d9 ea 12 CMP &12ea,Y ; sprite_update_routine_addresses &12d4 f0 05 BEQ &12db ; found_sprite_update_routine &12d6 c8 INY &12d7 c8 INY &12d8 c8 INY &12d9 d0 f6 BNE &12d1 ; find_sprite_update_routine_loop # Always branches ; found_sprite_update_routine &12db 48 PHA ; tmp_a &12dc b9 eb 12 LDA &12eb,Y ; sprite_update_routine_addresses + 1 &12df 85 29 STA &29 ; sprite_update_routine_address_low &12e1 b9 ec 12 LDA &12ec,Y ; sprite_update_routine_addresses + 2 &12e4 85 2a STA &2a ; sprite_update_routine_address_high &12e6 68 PLA ; tmp_a &12e7 6c 29 00 JMP (&0029) ; sprite_update_routine_address ; sprite_update_routine_addresses ; s addr &12ea 17 92 12 ; &00 : SPRITE_KEY : &1292 = collect_key &12ed 23 b7 12 ; &03 : SPRITE_BULB : &12b7 = collect_bulb &12f0 16 a9 12 ; &06 : SPRITE_GEM : &12a9 = collect_gem &12f3 27 68 1c ; &09 : SPRITE_BALLOON : &1c68 = update_balloon &12f6 25 79 1c ; &0c : SPRITE_DAGGER : &1c79 = update_dagger ; check_for_player_horizontal_movement &12f9 a5 86 LDA &86 ; keyboard_or_joystick &12fb d0 11 BNE &130e ; is_joystick &12fd a9 9e LDA #&9e ; Z &12ff 20 9c 0d JSR &0d9c ; check_for_keypress &1302 f0 01 BEQ &1305 ; z_not_pressed &1304 ca DEX ; left_not_pressed &1305 a9 bd LDA #&bd ; X &1307 20 9c 0d JSR &0d9c ; check_for_keypress &130a f0 01 BEQ &130d ; x_not_pressed ; move_right &130c e8 INX ; right_not_pressed ; leave &130d 60 RTS ; is_joystick &130e a9 01 LDA #&01 ; First joystick left/right &1310 20 76 13 JSR &1376 ; read_adc_channel_preserving_registers &1313 c9 64 CMP #&64 &1315 90 f5 BCC &130c ; move_right &1317 c9 9c CMP #&9c &1319 90 f2 BCC &130d ; leave &131b ca DEX &131c 60 RTS ; check_for_player_vertical_movement # Called with Y = player_y &131d a5 86 LDA &86 ; keyboard_or_joystick &131f d0 1e BNE &133f ; is_joystick &1321 a9 b7 LDA #&b7 ; : &1323 20 9c 0d JSR &0d9c ; check_for_keypress &1326 f0 03 BEQ &132b ; up_not_pressed &1328 20 4c 13 JSR &134c ; move_up ; up_not_pressed &132b a9 97 LDA #&97 ; / &132d 20 9c 0d JSR &0d9c ; check_for_keypress &1330 f0 0c BEQ &133e ; down_not_pressed ; move_up &1332 88 DEY &1333 88 DEY &1334 88 DEY &1335 24 74 BIT &74 ; level_is_inverted # Negative if level is inverted &1337 10 05 BPL &133e ; down_not_pressed &1339 18 CLC &133a 98 TYA &133b 69 06 ADC #&06 &133d a8 TAY ; down_not_pressed &133e 60 RTS # Returns Y = new player_y ; is_joystick &133f a9 02 LDA #&02 ; First joystick up/down &1341 20 76 13 JSR &1376 ; read_adc_channel_preserving_registers &1344 c9 64 CMP #&64 &1346 90 ea BCC &1332 ; move_up &1348 c9 9c CMP #&9c &134a 90 f2 BCC &133e ; down_not_pressed ; move_up &134c c8 INY &134d c8 INY &134e c8 INY &134f 24 74 BIT &74 ; level_is_inverted # Negative if level is inverted &1351 10 05 BPL &1358 ; leave &1353 38 SEC &1354 98 TYA &1355 e9 06 SBC #&06 &1357 a8 TAY ; leave &1358 60 RTS # Returns Y = new player_y ; check_for_player_fire &1359 a5 86 LDA &86 ; keyboard_or_joystick &135b d0 05 BNE &1362 ; is_joystick &135d a9 b6 LDA #&b6 ; RETURN &135f 4c 9c 0d JMP &0d9c ; check_for_keypress # Leave with non-zero if RETURN pressed ; is_joystick &1362 8a TXA &1363 48 PHA ; tmp_y &1364 98 TYA &1365 48 PHA ; tmp_x &1366 a9 00 LDA #&00 ; Joystick buttons &1368 20 8a 13 JSR &138a ; read_adc_channel &136b 86 26 STX &26 ; result &136d 68 PLA ; tmp_y &136e a8 TAY &136f 68 PLA ; tmp_x &1370 aa TAX &1371 a5 26 LDA &26 ; result &1373 29 01 AND #&01 # Leave with non-zero if fire pressed &1375 60 RTS ; read_adc_channel_preserving_registers &1376 85 26 STA &26 ; channel &1378 8a TXA &1379 48 PHA ; tmp_x &137a 98 TYA &137b 48 PHA ; tmp_y &137c a5 26 LDA &26 ; channel &137e 20 8a 13 JSR &138a ; read_adc_channel &1381 84 26 STY &26 ; result &1383 68 PLA ; tmp_y &1384 a8 TAY &1385 68 PLA ; tmp_x &1386 aa TAX &1387 a5 26 LDA &26 ; result &1389 60 RTS ; read_adc_channel &138a aa TAX &138b a9 80 LDA #&80 ; Read I/O device or buffer status &138d 4c fb 0d JMP &0dfb ; safe_osbyte ; wipe_column &1390 a2 20 LDX #&20 &1392 a5 26 LDA &26 # Unnecessary code &1394 a9 00 LDA #&00 &1396 85 3f STA &3f ; wipe_address_low &1398 a4 0c LDY &0c ; screen_start_address_low &139a a5 0d LDA &0d ; screen_start_address_high ; wipe_column_loop &139c 85 40 STA &40 ; wipe_address_high &139e a9 00 LDA #&00 &13a0 91 3f STA (&3f),Y ; wipe_address &13a2 c8 INY &13a3 91 3f STA (&3f),Y ; wipe_address &13a5 c8 INY &13a6 91 3f STA (&3f),Y ; wipe_address &13a8 c8 INY &13a9 91 3f STA (&3f),Y ; wipe_address &13ab c8 INY &13ac 91 3f STA (&3f),Y ; wipe_address &13ae c8 INY &13af 91 3f STA (&3f),Y ; wipe_address &13b1 c8 INY &13b2 91 3f STA (&3f),Y ; wipe_address &13b4 c8 INY &13b5 91 3f STA (&3f),Y ; wipe_address &13b7 ca DEX &13b8 f0 10 BEQ &13ca ; leave &13ba 18 CLC &13bb 98 TYA &13bc 69 79 ADC #&79 # Move down a group &13be a8 TAY &13bf a5 40 LDA &40 ; wipe_address_high &13c1 69 02 ADC #&02 &13c3 10 d7 BPL &139c ; wipe_column_loop &13c5 38 SEC &13c6 e9 50 SBC #&50 # Wrap around end of screen &13c8 10 d2 BPL &139c ; wipe_column_loop ; leave &13ca 60 RTS ; scroll_screen_left &13cb a0 f8 LDY #&f8 &13cd a9 ff LDA #&ff &13cf 20 11 14 JSR &1411 ; add_to_screen_start_address # Subtract 8 from screen start address &13d2 20 90 13 JSR &1390 ; wipe_column &13d5 c6 10 DEC &10 ; level_scroll &13d7 18 CLC &13d8 60 RTS ; plot_objects_on_left_edge &13d9 a9 01 LDA #&01 &13db 85 0f STA &0f ; right_clip &13dd 20 ff 13 JSR &13ff ; plot_objects &13e0 a9 50 LDA #&50 &13e2 85 0f STA &0f ; right_clip &13e4 60 RTS ; scroll_screen_right &13e5 20 90 13 JSR &1390 ; wipe_column &13e8 a0 08 LDY #&08 &13ea a9 00 LDA #&00 &13ec 20 11 14 JSR &1411 ; add_to_screen_start_address # Add 8 to screen start address &13ef e6 10 INC &10 ; level_scroll &13f1 18 CLC &13f2 60 RTS ; plot_objects_on_right_edge &13f3 a9 4f LDA #&4f &13f5 85 0e STA &0e ; left_clip &13f7 20 ff 13 JSR &13ff ; plot_objects &13fa a9 00 LDA #&00 &13fc 85 0e STA &0e ; left_clip &13fe 60 RTS ; plot_objects &13ff a2 7a LDX #&7a ; plot_objects_loop &1401 bd 5e 04 LDA &045e,X ; objects_sprite &1404 c9 ff CMP #&ff ; SPRITE_NONE &1406 f0 03 BEQ &140b ; consider_next_object &1408 20 20 0b JSR &0b20 ; plot_object_without_background ; consider_next_object &140b ca DEX &140c e0 ff CPX #&ff &140e d0 f1 BNE &1401 ; plot_objects_loop &1410 60 RTS ; add_to_screen_start_address &1411 48 PHA ; tmp_a &1412 18 CLC &1413 98 TYA &1414 65 0c ADC &0c ; screen_start_address_low &1416 85 0c STA &0c ; screen_start_address_low &1418 68 PLA ; tmp_a &1419 65 0d ADC &0d ; screen_start_address_high &141b 10 02 BPL &141f ; skip_wraparound_at_end &141d e9 4f SBC #&4f ; skip_wraparound_at_end &141f c9 00 CMP #&00 &1421 b0 02 BCS &1425 ; skip_wraparound_at_start &1423 69 50 ADC #&50 ; skip_wraparound_at_start &1425 85 0d STA &0d ; screen_start_address_high &1427 60 RTS ; set_crtc_screen_start &1428 a5 0c LDA &0c ; screen_start_address_low &142a 85 3f STA &3f ; crtc_address_low &142c a5 0d LDA &0d ; screen_start_address_high &142e 4a LSR A &142f 66 3f ROR &3f ; crtc_address_low &1431 4a LSR A &1432 66 3f ROR &3f ; crtc_address_low &1434 4a LSR A &1435 66 3f ROR &3f ; crtc_address_low &1437 a2 0c LDX #&0c ; R12: Displayed screen start address register (high) &1439 78 SEI &143a 8e 00 fe STX &fe00 ; video register number &143d 8d 01 fe STA &fe01 ; video register value &1440 e8 INX ; &0d ; R13: Displayed screen start address register (low) &1441 a5 3f LDA &3f ; crtc_address_low &1443 8e 00 fe STX &fe00 ; video register number &1446 8d 01 fe STA &fe01 ; video register value &1449 58 CLI &144a 60 RTS ; copy_status_buffer_to_screen &144b a0 07 LDY #&07 &144d 38 SEC &144e 98 TYA &144f 65 0c ADC &0c ; screen_start_address_low &1451 85 24 STA &24 ; status_screen_address_low &1453 a9 00 LDA #&00 ; plot_leading_blank_loop &1455 91 0c STA (&0c),Y ; screen_start_address &1457 88 DEY &1458 10 fb BPL &1455 ; plot_leading_blank_loop &145a 65 0d ADC &0d ; screen_start_address_high &145c 85 25 STA &25 ; status_screen_address_high &145e c8 INY ; copy_status_buffer_loop &145f b9 00 09 LDA &0900,Y ; status_buffer &1462 91 24 STA (&24),Y ; status_screen_address &1464 c8 INY &1465 d0 f8 BNE &145f ; copy_status_buffer_loop &1467 98 TYA &1468 e6 25 INC &25 ; status_screen_address_high &146a a0 07 LDY #&07 ; plot_trailing_blank_loop &146c 91 24 STA (&24),Y ; status_screen_address &146e 88 DEY &146f 10 fb BPL &146c ; plot_trailing_blank_loop &1471 60 RTS ; check_if_region_overlaps_classes &1472 85 5a STA &5a ; classes_to_check &1474 86 33 STX &33 ; object_being_checked &1476 20 19 1d JSR &1d19 ; calculate_scrolled_clips # Resets list of bounding boxes &1479 20 9c 1d JSR &1d9c ; add_region_to_bounding_boxes_list ; check_for_overlap_with_classes &147c 8a TXA &147d 48 PHA ; tmp_x &147e 98 TYA &147f 48 PHA ; tmp_y &1480 a5 11 LDA &11 ; sprite_x &1482 48 PHA ; previous_sprite_x &1483 a5 12 LDA &12 ; sprite_y &1485 48 PHA ; previous_sprite_y &1486 a0 00 LDY #&00 ; check_for_overlap_class_loop # For each class of objects, &1488 84 95 STY &95 ; object_class_offset &148a b9 02 0b LDA &0b02,Y ; object_class_data + 2 # Zero if end of classes &148d f0 32 BEQ &14c1 ; no_overlap &148f a5 5a LDA &5a ; classes_to_check &1491 c9 ff CMP #&ff # &ff to check all objects &1493 f0 05 BEQ &149a ; check_class &1495 39 01 0b AND &0b01,Y ; object_class_data + 1 # Should this class be checked? &1498 f0 22 BEQ &14bc ; consider_next_object_class ; check_class &149a be 00 0b LDX &0b00,Y ; object_class_data # First slot for class ; check_for_overlap_object_loop # If so, for each object in the class &149d e4 33 CPX &33 ; object_being_checked &149f f0 12 BEQ &14b3 ; consider_next_object &14a1 20 3c 0b JSR &0b3c ; get_object_position_and_sprite # Returns carry set if no object in slot &14a4 b0 0d BCS &14b3 ; consider_next_object &14a6 20 b1 1c JSR &1cb1 ; check_object_against_bounding_boxes # Returns carry clear if no overlap &14a9 90 08 BCC &14b3 ; consider_next_object &14ab 86 64 STX &64 ; overlapping_object &14ad a4 95 LDY &95 ; object_class_offset &14af 84 94 STY &94 ; overlapping_class &14b1 b0 0f BCS &14c2 ; leave_after_restoring_variables # Leave with carry set to indicate overlap; always branches ; consider_next_object &14b3 e8 INX &14b4 a4 95 LDY &95 ; object_class_offset &14b6 8a TXA &14b7 d9 03 0b CMP &0b03,Y ; object_class_data + 3 # First slot for next class (i.e. last slot plus one) &14ba 90 e1 BCC &149d ; check_for_overlap_object_loop ; consider_next_object_class &14bc c8 INY &14bd c8 INY &14be c8 INY &14bf d0 c7 BNE &1488 ; check_for_overlap_class_loop # Always branches ; no_opverlap &14c1 18 CLC # Leave with carry clear to indicate no overlap ; leave_after_restoring_variables &14c2 68 PLA ; previous_sprite_y &14c3 85 12 STA &12 ; sprite_y &14c5 68 PLA ; previous_sprite_x &14c6 85 11 STA &11 ; sprite_x &14c8 68 PLA ; tmp_y &14c9 a8 TAY &14ca 68 PLA ; tmp_x &14cb aa TAX &14cc 60 RTS ; initialise_screen # Called with X = level, Y = round &14cd a9 00 LDA #&00 &14cf 85 10 STA &10 ; level_scroll ; initialise_screen_without_resetting_level_scroll &14d1 a9 00 LDA #&00 ; &3000 = screen memory &14d3 85 0c STA &0c ; screen_start_address_low &14d5 a9 30 LDA #&30 &14d7 85 0d STA &0d ; screen_start_address_high &14d9 a9 00 LDA #&00 &14db 85 0e STA &0e ; left_clip &14dd a9 50 LDA #&50 &14df 85 0f STA &0f ; right_clip &14e1 a9 00 LDA #&00 &14e3 85 74 STA &74 ; level_is_inverted # Set to positive to indicate level is not inverted &14e5 98 TYA &14e6 4a LSR A &14e7 90 02 BCC &14eb ; not_inverted # Odd rounds are inverted &14e9 c6 74 DEC &74 ; level_is_inverted # Set to negative to indicate level is inverted ; not_inverted &14eb 20 21 0d JSR &0d21 ; write_string &14ee 16 01 ; MODE 1 &14f0 13 01 05 00 00 00 ; set colour 1 to magenta &14f6 13 02 03 00 00 00 ; set colour 2 to yellow &14fc 11 82 ; COLOUR 128 + 2 &14fe 13 03 00 00 00 00 ; set colour 3 to black &1504 ea NOP &1505 20 74 15 JSR &1574 ; disable_cursor &1508 98 TYA &1509 4a LSR A &150a 4a LSR A &150b b0 1c BCS &1529 ; use_black_and_white &150d 08 PHP ; round comparison &150e bd 68 19 LDA &1968,X ; level_colours # Rounds 0 and 1 use background colour &1511 28 PLP ; round comparison &1512 f0 02 BEQ &1516 ; use_background_colour &1514 a9 00 LDA #&00 # Rounds 4 and 5 use black background ; use_background_colour &1516 48 PHA ; background colour &1517 20 21 0d JSR &0d21 ; write_string &151a 13 00 ; set colour &151c ea NOP &151d 68 PLA ; background colour &151e 20 ee ff JSR &ffee ; OSWRCH &1521 20 21 0d JSR &0d21 ; write_string &1524 00 00 00 &1527 ea NOP &1528 60 RTS ; use_black_and_white &1529 d0 1d BNE &1548 ; use_white_on_black ; use_black_on_white # Rounds 2 and 3 use white with black sprites &152b 20 21 0d JSR &0d21 ; write_string &152e 13 00 07 00 00 00 ; set colour 0 to white &1534 13 01 07 00 00 00 ; set colour 1 to white &153a 13 02 07 00 00 00 ; set colour 2 to white &1540 13 03 00 00 00 00 ; set colour 3 to black &1546 ea NOP &1547 60 RTS ; use_white_on_black # Rounds 6 and 7 use black with white sprites &1548 20 21 0d JSR &0d21 ; write_string &154b 13 00 00 00 00 00 ; set colour 0 to black &1551 13 01 00 00 00 00 ; set colour 1 to black &1557 13 02 00 00 00 00 ; set colour 2 to black &155d 13 03 07 00 00 00 ; set colour 3 to white &1563 ea NOP &1564 60 RTS ; wipe_status_buffer &1565 a0 00 LDY #&00 &1567 98 TYA ; wipe_status_buffer_loop # Wipe &0900 - &09ff &1568 99 00 09 STA &0900,Y ; status_buffer &156b 88 DEY &156c d0 fa BNE &1568 ; wipe_status_buffer_loop &156e a9 09 LDA #&09 ; &0900 = status_buffer &1570 8d 51 03 STA &0351 ; os_screen_start_address_high # Plot characters to status buffer &1573 60 RTS ; disable_cursor &1574 20 21 0d JSR &0d21 ; write_string &1577 17 01 00 00 00 00 00 00 00 00 ; disable cursor &1581 ea NOP &1582 60 RTS ; enable_cursor &1583 20 21 0d JSR &0d21 ; write_string &1586 17 01 01 00 00 00 00 00 00 00 ; enable cursor &1590 ea NOP &1591 60 RTS ; calculate_object_min_and_max_x_and_y &1592 18 CLC &1593 a5 11 LDA &11 ; sprite_x &1595 71 00 ADC (&00),Y ; sprite_x_offsets_address &1597 85 45 STA &45 ; object_min_x &1599 b1 08 LDA (&08),Y ; sprite_widths_address &159b 0a ASL A &159c 4a LSR A &159d 65 45 ADC &45 ; object_min_x &159f 85 46 STA &46 ; object_max_x &15a1 18 CLC &15a2 a5 12 LDA &12 ; sprite_y &15a4 71 02 ADC (&02),Y ; sprite_y_offsets_address &15a6 85 48 STA &48 ; object_min_y &15a8 18 CLC &15a9 71 0a ADC (&0a),Y ; sprite_heights_address &15ab 85 47 STA &47 ; object_max_y &15ad 60 RTS ; get_direction_from_sign &15ae f0 07 BEQ &15b7 ; leave &15b0 30 03 BMI &15b5 ; leave_with_minus_one &15b2 a9 01 LDA #&01 &15b4 60 RTS ; leave_with_minus_one &15b5 a9 ff LDA #&ff ; leave &15b7 60 RTS ; add_to_score # Add AY to score &15b8 a0 00 LDY #&00 &15ba 18 CLC &15bb f8 SED &15bc 65 38 ADC &38 ; score &15be 85 38 STA &38 ; score &15c0 a5 39 LDA &39 ; score + 1 &15c2 85 26 STA &26 ; previous_score &15c4 98 TYA &15c5 65 39 ADC &39 ; score + 1 &15c7 85 39 STA &39 ; score + 1 &15c9 45 26 EOR &26 ; previous_score &15cb 29 20 AND #&20 &15cd 48 PHA ; score and &20 &15ce a9 00 LDA #&00 &15d0 65 3a ADC &3a ; score + 2 &15d2 85 3a STA &3a ; score + 2 &15d4 d8 CLD &15d5 68 PLA ; score and &20 &15d6 f0 02 BEQ &15da ; leave &15d8 e6 3b INC &3b ; player_lives # Extra life every 20000 points ; leave &15da 60 RTS ; plot_status &15db 20 65 15 JSR &1565 ; wipe_status_buffer &15de a9 1e LDA #&1e ; HOME &15e0 20 ee ff JSR &ffee ; OSWRCH &15e3 38 SEC &15e4 a5 83 LDA &83 ; time_remaining + 1 # Write time remaining &15e6 20 2f 16 JSR &162f ; write_one_digit_number &15e9 a9 3a LDA #&3a ; ":" &15eb 20 ee ff JSR &ffee ; OSWRCH &15ee 38 SEC &15ef a5 82 LDA &82 ; time_remaining &15f1 20 24 16 JSR &1624 ; write_two_digit_number &15f4 a9 09 LDA #&09 ; RIGHT &15f6 20 ee ff JSR &ffee ; OSWRCH &15f9 38 SEC &15fa a5 3b LDA &3b ; player_lives # Write lives &15fc e9 01 SBC #&01 &15fe 38 SEC &15ff 20 2f 16 JSR &162f ; write_one_digit_number &1602 a9 09 LDA #&09 ; RIGHT &1604 20 ee ff JSR &ffee ; OSWRCH &1607 18 CLC # Clear carry to skip leading zeros &1608 a5 3a LDA &3a ; score + 2 # Write score &160a 20 2f 16 JSR &162f ; write_one_digit_number &160d a5 39 LDA &39 ; score + 1 &160f 20 24 16 JSR &1624 ; write_two_digit_number &1612 90 06 BCC &161a ; skip_comma &1614 a9 2c LDA #&2c "," &1616 20 ee ff JSR &ffee ; OSWRCH &1619 38 SEC ; skip_comma &161a a5 38 LDA &38 ; score &161c 20 24 16 JSR &1624 ; write_two_digit_number &161f a9 30 LDA #&30 ; "0" &1621 4c ee ff JMP &ffee ; OSWRCH ; write_two_digit_number &1624 48 PHA ; number &1625 08 PHP ; use leading zeros &1626 4a LSR A &1627 4a LSR A &1628 4a LSR A &1629 4a LSR A &162a 28 PLP ; use leading zeros &162b 20 2f 16 JSR &162f ; write_one_digit_number &162e 68 PLA ; number ; write_one_digit_number &162f 29 0f AND #&0f &1631 d0 02 BNE &1635 ; not_zero &1633 90 06 BCC &163b ; leave # Carry clear if skipping leading zeros ; not_zero &1635 09 30 ORA #&30 ; "0" &1637 20 ee ff JSR &ffee ; OSWRCH &163a 38 SEC # Set carry to write subsequent zeros ; leave &163b 60 RTS ; update_time_and_check_for_keypresses_for_Y_frames &163c a8 TAY ; update_time_and_check_for_keypresses_for_Y_frames_loop &163d 20 2c 0c JSR &0c2c ; update_time_and_check_for_keypresses # Returns non-zero if ESCAPE pressed &1640 f0 04 BEQ &1646 ; skip_check &1642 24 86 BIT &86 ; keyboard_or_joystick # Negative if SPACE or fire hasn't been pressed &1644 10 06 BPL &164c ; leave ; skip_check &1646 20 01 0d JSR &0d01 ; wait_for_vsync &1649 88 DEY &164a d0 f1 BNE &163d ; update_time_and_check_for_keypresses_for_Y_frames ; leave &164c 60 RTS ; check_for_high_score &164d ba TSX &164e 86 7e STX &7e ; stack_pointer_to_start_game &1650 a9 06 LDA #&06 &1652 85 42 STA &42 ; rank &1654 a0 ff LDY #&ff &1656 a2 1e LDX #&1e ; 30 = 5 * 6 ; check_high_scores_loop # For each rank, &1658 a5 38 LDA &38 ; score # Is the player's score the same or better? &165a dd 85 08 CMP &0885,X ; high_scores + 5 &165d a5 39 LDA &39 ; score + 1 &165f fd 84 08 SBC &0884,X ; high_scores + 4 &1662 a5 3a LDA &3a ; score + 2 &1664 fd 83 08 SBC &0883,X ; high_scores + 3 &1667 90 09 BCC &1672 ; new_high_score &1669 c6 42 DEC &42 ; rank &166b 8a TXA &166c a8 TAY &166d e9 06 SBC #&06 &166f aa TAX &1670 10 e6 BPL &1658 ; check_high_scores_loop ; new_high_score &1672 98 TYA &1673 30 d7 BMI &164c ; leave &1675 84 26 STY &26 ; offset &1677 a2 23 LDX #&23 ; 35 = 5 * 6 + 5 ; shuffle_high_scores_loop # Move all lower scores down a rank &1679 bd 7a 08 LDA &087a,X ; high_scores - 6 &167c 9d 80 08 STA &0880,X ; high_scores &167f ca DEX &1680 e4 26 CPX &26 ; offset &1682 10 f5 BPL &1679 ; shuffle_high_scores_loop &1684 a5 38 LDA &38 ; score # Put player's score in high scores &1686 99 85 08 STA &0885,Y ; high_scores + 5 &1689 a5 39 LDA &39 ; score + 1 &168b 99 84 08 STA &0884,Y ; high_scores + 4 &168e a5 3a LDA &3a ; score + 2 &1690 99 83 08 STA &0883,Y ; high_scores + 3 &1693 a9 20 LDA #&20 ; " " # Default name " " &1695 99 80 08 STA &0880,Y ; high_scores &1698 99 81 08 STA &0881,Y ; high_scores + 1 &169b 99 82 08 STA &0882,Y ; high_scores + 2 &169e 84 3f STY &3f ; player_name_offset &16a0 a5 0c LDA &0c ; screen_start_address_low &16a2 8d 50 03 STA &0350 ; os_screen_start_address_low &16a5 a5 0d LDA &0d ; screen_start_address_high &16a7 8d 51 03 STA &0351 ; os_screen_start_address_high &16aa 20 da 19 JSR &19da ; plot_high_score_screen &16ad 20 21 0d JSR &0d21 ; write_string &16b0 11 82 ; COLOUR 128 + 2 &16b2 1f 09 11 ; TAB(&09, &11) &16b5 3c 2d 2b 2d 3e 20 74 6f 20 73 65 6c 65 63 74 20 ; "<-+-> to select letter" &16c5 6c 65 74 74 65 72 &16cb 1f 09 13 ; TAB(&09, &13) &16ce 27 4a 75 6d 70 27 20 74 6f 20 65 6e 74 65 72 20 ; "'Jump' to enter letter" &16de 6c 65 74 74 65 72 &16e4 ea NOP &16e5 20 83 15 JSR &1583 ; enable_cursor &16e8 a4 42 LDY &42 ; rank &16ea 20 b3 1a JSR &1ab3 ; tab_to_high_score_position &16ed a9 03 LDA #&03 &16ef 85 42 STA &42 ; characters_remaining &16f1 a9 41 LDA #&41 ; "A" &16f3 85 41 STA &41 ; character ; enter_name_loop &16f5 a5 41 LDA &41 ; character &16f7 20 ee ff JSR &ffee ; OSWRCH &16fa a9 08 LDA #&08 &16fc 20 ee ff JSR &ffee ; OSWRCH &16ff 20 2c 0c JSR &0c2c ; update_time_and_check_for_keypresses # Returns non-zero if ESCAPE pressed &1702 d0 56 BNE &175a ; leave_with_carry_clear &1704 a5 87 LDA &87 ; previous_keyboard_or_joystick &1706 85 86 STA &86 ; keyboard_or_joystick &1708 a6 41 LDX &41 ; character &170a 20 f9 12 JSR &12f9 ; check_for_player_horizontal_movement &170d e4 41 CPX &41 ; character &170f f0 19 BEQ &172a ; skip_changing_character &1711 e0 7f CPX #&7f ; DELETE &1713 90 04 BCC &1719 ; skip_wraparound &1715 a2 20 LDX #&20 ; " " &1717 b0 06 BCS &171f ; set_character # Always branches ; skip_wraparound &1719 e0 20 CPX #&20 ; " " &171b b0 02 BCS &171f ; set_character &171d a2 7e LDX #&7e ; "~" ; set_character &171f 8a TXA &1720 85 41 STA &41 ; character &1722 20 ee ff JSR &ffee ; OSWRCH &1725 a9 08 LDA #&08 ; LEFT &1727 20 ee ff JSR &ffee ; OSWRCH ; skip_changing_character &172a a0 ff LDY #&ff &172c 20 1d 13 JSR &131d ; check_for_player_vertical_movement # Returns Y = new player_y &172f 98 TYA &1730 30 18 BMI &174a ; skip_entering_character &1732 a4 3f LDY &3f ; player_name_offset &1734 a5 41 LDA &41 ; character &1736 99 80 08 STA &0880,Y ; high_scores &1739 20 ee ff JSR &ffee ; OSWRCH &173c e6 3f INC &3f ; player_name_offset &173e c6 42 DEC &42 ; characters_remaining &1740 f0 10 BEQ &1752 ; finished_entering_name &1742 a9 14 LDA #&14 &1744 20 c7 1a JSR &1ac7 ; update_time_and_check_for_keypresses_for_Y_frames &1747 4c f5 16 JMP &16f5 ; enter_name_loop ; skip_entering_character &174a a9 05 LDA #&05 &174c 20 c7 1a JSR &1ac7 ; update_time_and_check_for_keypresses_for_Y_frames &174f 4c ff 16 JMP &16ff ; finished_entering_name &1752 20 74 15 JSR &1574 ; disable_cursor &1755 a9 50 LDA #&50 &1757 20 c7 1a JSR &1ac7 ; update_time_and_check_for_keypresses_for_Y_frames ; leave_with_carry_clear &175a 18 CLC &175b 60 RTS ; sprite_set_g_data &175c 00 34 ff ; OBJECT_CLASS_T : SPRITE_TROGG_RIGHT_HOLDING &175f 12 4a 4b 4c 4d ff ; OBJECT_CLASS_L : SPRITE_CHAIN_* (ONE, TWO, THREE, FOUR) &1765 0f 15 3e 3f 40 41 42 43 ff ; OBJECT_CLASS_F : SPRITE_GIRDER_* (ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) &176e 0c 1d ff ; OBJECT_CLASS_M : SPRITE_HOOTER &1771 09 17 23 16 ff ; OBJECT_CLASS_K : SPRITE_KEY, SPRITE_BULB, SPRITE_GEM &1776 ff ; end of list ; sprite_set_j_data &1777 00 34 ff ; OBJECT_CLASS_T : SPRITE_TROGG_RIGHT_HOLDING &177a 0f 44 45 46 47 48 49 ff ; OBJECT_CLASS_F : SPRITE_LOG_* (FIVE, SEVEN, SEVEN_TWO, ELEVEN, TWO, ONE) &1782 12 00 54 55 56 ff ; OBJECT_CLASS_L : SPRITE_ROPE_* (ONE, TWO, THREE, FOUR) &1788 0c 00 1e ff ; OBJECT_CLASS_M : SPRITE_ROPE_ONE, SPRITE_POGLET &178c 09 17 23 16 ff ; OBJECT_CLASS_K : SPRITE_KEY, SPRITE_BULB, SPRITE_GEM &1791 ff ; end of list ; sprite_set_c_data &1792 00 34 ff ; OBJECT_CLASS_T : SPRITE_TROGG_RIGHT_HOLDING &1795 0c 12 ff ; OBJECT_CLASS_M : SPRITE_SCRUBBLY &1798 09 17 23 16 ff ; OBJECT_CLASS_K : SPRITE_KEY, SPRITE_BULB, SPRITE_GEM &179d 12 24 57 58 59 5a ff ; OBJECT_CLASS_L : SPRITE_LADDER_* (ONE, TWO, THREE, FOUR, FIVE) &17a4 0f 11 4e 4f 50 51 52 53 ff ; OBJECT_CLASS_F : SPRITE_PLATFORM_* (ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) &17ad ff ; end of list ; sprite_set_data_addresses &17ae 47 5c 17 ; "G" : &175c = sprite_set_g_data &17b1 43 92 17 ; "C" : &1792 = sprite_set_c_data &17b4 4a 77 17 ; "J" : &1777 = sprite_set_j_data &17b7 ff ; end of list ; initialise_level &17b8 a2 00 LDX #&00 &17ba a1 6d LDA (&6d,X) ; level_data_address # First byte of level data specifies sprite set to use &17bc 85 26 STA &26 ; sprite_set ; find_sprite_set_loop &17be bd ae 17 LDA &17ae,X ; sprite_set_data_addresses # Negative at end of list &17c1 30 2f BMI &17f2 ; level_data_is_bad # If so, sprite set is unmatched; level is bad &17c3 c5 26 CMP &26 ; sprite_set &17c5 f0 05 BEQ &17cc ; set_sprite_set_data_address &17c7 e8 INX &17c8 e8 INX &17c9 e8 INX &17ca d0 f2 BNE &17be ; find_sprite_set_loop # Always branches ; set_sprite_set_data_address &17cc bd af 17 LDA &17af,X ; sprite_set_data_addresses + 1 &17cf 85 6b STA &6b ; sprite_set_data_address_low &17d1 bd b0 17 LDA &17b0,X ; sprite_set_data_addresses + 2 &17d4 85 6c STA &6c ; sprite_set_data_address_high &17d6 e6 6d INC &6d ; level_data_address_low &17d8 d0 02 BNE &17dc ; skip_page &17da e6 6e INC &6e ; level_data_address_high ; skip_page ; initialise_object_classes_loop &17dc a2 00 LDX #&00 &17de a0 00 LDY #&00 &17e0 a1 6d LDA (&6d,X) ; level_data_address # Get a byte of level data for object class identifier &17e2 30 13 BMI &17f7 ; leave # Top bit set indicates end of level data ; find_object_class_data_loop &17e4 b9 02 0b LDA &0b02,Y ; object_class_data + 2 # Zero marks end of object classes &17e7 f0 09 BEQ &17f2 ; level_data_is_bad # If so, object class is unmatched; level is bad &17e9 c1 6d CMP (&6d,X) ; level_data_address &17eb f0 13 BEQ &1800 ; initialise_object_class &17ed c8 INY &17ee c8 INY &17ef c8 INY &17f0 d0 f2 BNE &17e4 ; find_object_class_data_loop # Always branches ; level_data_is_bad &17f2 a9 07 LDA #&07 ; BELL &17f4 20 ee ff JSR &ffee ; OSWRCH ; leave &17f7 60 RTS ; consider_next_object_class &17f8 e6 6d INC &6d ; level_data_address_low # Move to next byte of level data &17fa d0 e0 BNE &17dc ; initialise_object_classes_loop &17fc e6 6e INC &6e ; level_data_address_high &17fe d0 dc BNE &17dc ; initialise_object_classes_loop # Always branches ; initialise_object_class &1800 84 5c STY &5c ; object_class_offset &1802 b9 03 0b LDA &0b03,Y ; object_class_data + 3 # First slot for next class (i.e. last slot plus one) &1805 85 40 STA &40 ; end_slot &1807 be 00 0b LDX &0b00,Y ; object_class_data # First slot for this class &180a a0 00 LDY #&00 &180c e6 6d INC &6d ; level_data_address_low # Move to next byte of level data &180e d0 02 BNE &1812 ; skip_page &1810 e6 6e INC &6e ; level_data_address_high ; skip_page ; find_object_class_in_sprite_set_loop &1812 b1 6b LDA (&6b),Y ; sprite_set_data_address # Get byte of sprite set data for object class identifier &1814 30 dc BMI &17f2 ; level_data_is_bad # Negative at end of sprite set data; if so, level is bad &1816 c5 5c CMP &5c ; object_class_offset &1818 f0 08 BEQ &1822 ; set_first_sprite_in_class_offset ; find_start_of_object_class_loop &181a c8 INY &181b b1 6b LDA (&6b),Y ; sprite_set_data_address # Move past list of sprites &181d 10 fb BPL &181a ; find_start_of_object_class_loop # Negative at end of sprites for object class &181f c8 INY &1820 d0 f0 BNE &1812 ; find_object_class_in_sprite_set_loop # Always branches ; set_first_sprite_in_class_offset &1822 84 3f STY &3f ; first_sprite_in_class_offset ; initialise_object_types_in_class_loop &1824 a0 00 LDY #&00 &1826 38 SEC &1827 b1 6d LDA (&6d),Y ; level_data_address # Get byte of level data for type and number of objects &1829 48 PHA ; level data byte &182a 29 07 AND #&07 # .....421 object type &182c 65 3f ADC &3f ; first_sprite_in_class_offset &182e a8 TAY &182f b1 6b LDA (&6b),Y ; sprite_set_data_address &1831 85 35 STA &35 ; sprite &1833 68 PLA ; level data byte &1834 4a LSR A &1835 4a LSR A &1836 4a LSR A &1837 f0 bf BEQ &17f8 ; consider_next_object_class &1839 85 26 STA &26 ; count # 84218... number of objects, or zero for end of class &183b a0 00 LDY #&00 &183d ca DEX ; initialise_objects_loop # For each object, &183e e8 INX &183f e4 40 CPX &40 ; end_slot # Are there too many objects already in this class? &1841 b0 af BCS &17f2 ; level_data_is_bad # If so, level is bad &1843 bd 5e 04 LDA &045e,X ; objects_sprite # Find a free slot for the object &1846 c9 ff CMP #&ff ; SPRITE_NONE &1848 d0 f4 BNE &183e ; initialise_objects_loop &184a c8 INY &184b b1 6d LDA (&6d),Y ; level_data_address # Get a byte of level data for x position &184d 9d 68 03 STA &0368,X ; objects_x &1850 c8 INY &1851 b1 6d LDA (&6d),Y ; level_data_address # Get a byte of level data for y position &1853 9d e3 03 STA &03e3,X ; objects_y &1856 a5 35 LDA &35 ; sprite &1858 9d 5e 04 STA &045e,X ; objects_sprite &185b c6 26 DEC &26 ; count &185d d0 df BNE &183e ; initialise_objects_loop &185f 38 SEC # Move past data for objects &1860 98 TYA &1861 65 6d ADC &6d ; level_data_address_low &1863 85 6d STA &6d ; level_data_address_low &1865 90 bd BCC &1824 ; initialise_object_types_in_class_loop &1867 e6 6e INC &6e ; level_data_address_high &1869 b0 b9 BCS &1824 ; initialise_object_types_in_class_loop # Always branches ; update_tune &186b a5 2f LDA &2f ; suppress_tune # Negative if tune suppressed &186d 05 93 ORA &93 ; in_system_call # Negative if in system call &186f 30 37 BMI &18a8 ; leave &1871 24 91 BIT &91 ; tune_cooldown &1873 10 33 BPL &18a8 ; leave # Is it time to play the next note? &1875 8a TXA &1876 48 PHA ; tmp_x &1877 98 TYA &1878 48 PHA ; tmp_y &1879 a4 90 LDY &90 ; tune_position &187b be 07 05 LDX &0507,Y ; tune_data # Get byte of tune data &187e c8 INY &187f 8a TXA &1880 29 7c AND #&7c # .42184.. pitch &1882 8d a8 01 STA &01a8 ; sound_0 + 4 (pitch) &1885 8a TXA &1886 10 0a BPL &1892 ; not_end_of_tune # 8....... end of tune if set &1888 a6 8a LDX &8a ; current_tune &188a b4 00 LDY &00,X ; tune_start_positions - &8b # Restart tune &188c e0 8e CPX #&8e ; tune_start_positions + 3 # if level tune, but not failure or completion tune &188e 90 02 BCC &1892 ; not_end_of_tune &1890 c6 2f DEC &2f ; suppress_tune # Set to negative to suppress tune ; not_end_of_tune &1892 29 03 AND #&03 # ......21 duration &1894 38 SEC &1895 69 00 ADC #&00 &1897 0a ASL A &1898 0a ASL A &1899 65 91 ADC &91 ; tune_cooldown &189b 85 91 STA &91 ; tune_cooldown &189d 84 90 STY &90 ; tune_position &189f a2 a4 LDX #&a4 ; sound_0 &18a1 20 a9 18 JSR &18a9 ; play_sound # Play sound for tune &18a4 68 PLA ; tmp_y &18a5 a8 TAY &18a6 68 PLA ; tmp_x &18a7 aa TAX ; leave &18a8 60 RTS ; play_sound &18a9 a0 01 LDY #&01 &18ab 24 4b BIT &4b ; sound_muted # Negative if sound muted &18ad 30 f9 BMI &18a8 ; leave &18af a9 07 LDA #&07 ; Generate a sound &18b1 4c 03 0e JMP &0e03 ; safe_osword ; start_tune # Called with A = tune to play &18b4 aa TAX &18b5 86 8a STX &8a ; current_tune &18b7 b5 00 LDA &00,X ; tune_start_positions - &8b &18b9 85 90 STA &90 ; tune_position &18bb a2 a8 LDX #&a8 # Set speed of tune &18bd a0 61 LDY #&61 &18bf 8c 65 fe STY &fe65 ; User VIA timer 1 counter MSB &18c2 8e 64 fe STX &fe64 ; User VIA timer 1 counter LSB &18c5 a9 00 LDA #&00 &18c7 85 91 STA &91 ; tune_cooldown &18c9 85 2f STA &2f ; suppress_tune # Set to positive to enable tune &18cb 60 RTS ; completion_screen &18cc a9 8f LDA #&8f ; tune_start_positions + 4 &18ce 20 b4 18 JSR &18b4 ; start_tune # Play completion tune &18d1 20 27 0c JSR &0c27 ; stop_timer # Returns A = &40 &18d4 85 70 STA &70 ; status_has_changed # Set to positive to suppress updating status &18d6 a6 3c LDX &3c ; level &18d8 a4 3d LDY &3d ; round &18da 20 d1 14 JSR &14d1 ; initialise_screen_without_resetting_level_scroll &18dd 20 1f 1b JSR &1b1f ; plot_completion_screen &18e0 a9 ff LDA #&ff &18e2 85 70 STA &70 ; status_has_changed # Set to negative to update status &18e4 a9 01 LDA #&01 # Use SPRITE_TROGG_RIGHT_HOLDING &18e6 8d f0 04 STA &04f0 ; player_y_velocity # Used as offset into high_score_screen_animation_sprites &18e9 a9 3c LDA #&3c &18eb 85 34 STA &34 ; count &18ed a2 01 LDX #&01 &18ef 8e d9 04 STX &04d9 ; player_x_velocity # Set sprite moving right &18f2 ca DEX ; 0 = OBJECT_PLAYER &18f3 20 20 0b JSR &0b20 ; plot_object_without_background &18f6 38 SEC # Set carry to suppress checking for SPACE or fire &18f7 b0 29 BCS &1922 ; to_high_score_screen_animation_loop # Always branches ; high_score_screen_scrubbly_animation &18f9 a9 50 LDA #&50 # Set x position to &50 &18fb 48 PHA ; x position &18fc a0 ff LDY #&ff # Set sprite moving left &18fe a9 06 LDA #&06 # Use SPRITE_SCRUBBLY &1900 a2 01 LDX #&01 # Use object slot 1 &1902 d0 09 BNE &190d ; high_score_screen_animation # Always branches ; high_score_screen_trogg_animation &1904 a9 00 LDA #&00 # Set x position to 0 &1906 48 PHA ; x position &1907 a0 01 LDY #&01 # Set sprite moving right &1909 a9 01 LDA #&01 # Use SPRITE_TROGG_RIGHT_HOLDING &190b a2 00 LDX #&00 # Use object slot 0 ; high_score_screen_animation &190d 9d f0 04 STA &04f0,X ; objects_y_velocity # Used as offset into high_score_screen_animation_sprites &1910 98 TYA &1911 9d d9 04 STA &04d9,X ; objects_x_velocity &1914 68 PLA ; x position &1915 9d 68 03 STA &0368,X ; objects_x &1918 a9 1f LDA #&1f &191a 85 34 STA &34 ; count &191c a9 52 LDA #&52 &191e 9d e3 03 STA &03e3,X ; objects_y &1921 18 CLC # Clear carry to allow checking for SPACE or fire ; to_high_score_screen_animation_loop &1922 08 PHP ; check for space or fire if carry clear ; high_score_screen_animation_loop &1923 a9 04 LDA #&04 &1925 20 3c 16 JSR &163c ; update_time_and_check_for_keypresses_for_Y_frames &1928 28 PLP ; check for space or fire if carry clear &1929 08 PHP ; check for space or fire if carry clear &192a b0 03 BCS &192f ; skip_check &192c 20 d7 1a JSR &1ad7 ; check_for_space_or_fire # Doesn't return if SPACE or fire pressed ; skip_check &192f 20 08 0d JSR &0d08 ; wait_to_plot_object_X &1932 20 1c 0b JSR &0b1c ; unplot_object_without_background &1935 18 CLC &1936 bd 68 03 LDA &0368,X ; objects_x &1939 7d d9 04 ADC &04d9,X ; objects_x_velocity &193c 9d 68 03 STA &0368,X ; objects_x &193f bc f0 04 LDY &04f0,X ; objects_y_velocity # Used as offset into high_score_screen_animation_sprites ; move_to_next_frame_of_animation &1942 c8 INY &1943 b9 60 19 LDA &1960,Y ; high_score_screen_animation_sprites &1946 10 08 BPL &1950 ; set_objects_sprite ; find_start_of_animation_loop &1948 88 DEY &1949 b9 60 19 LDA &1960,Y ; high_score_screen_animation_sprites &194c 10 fa BPL &1948 ; find_start_of_animation_loop &194e 30 f2 BMI &1942 ; move_to_next_frame_of_animation ; set_objects_sprite &1950 9d 5e 04 STA &045e,X ; objects_sprite &1953 98 TYA &1954 9d f0 04 STA &04f0,X ; objects_y_velocity &1957 20 20 0b JSR &0b20 ; plot_object_without_background &195a c6 34 DEC &34 ; count &195c d0 c5 BNE &1923 ; high_score_screen_animation_loop &195e 28 PLP ; check for space or fire if carry clear &195f 60 RTS ; high_score_screen_animation_sprites &1960 ff ; &00 : SPRITE_NONE &1961 34 ; &01 : SPRITE_TROGG_RIGHT_HOLDING &1962 35 ; &02 : SPRITE_TROGG_RIGHT_HOLDING_TWO &1963 36 ; &03 : SPRITE_TROGG_RIGHT_HOLDING_THREE &1964 37 ; &04 : SPRITE_TROGG_RIGHT_HOLDING_FOUR &1965 ff ; &05 : SPRITE_NONE &1966 12 ; &06 : SPRITE_SCRUBBLY &1967 ff ; &07 : SPRITE_NONE ; level_colours &1968 06 02 01 ; level_data_addresses_low &196b d4 89 3c ; level_data_addresses_high &196e 05 06 07 ; level_times &1971 02 03 04 ; level_tunes &1974 8b 8c 8d ; high_score_screen &1977 ba TSX &1978 86 7e STX &7e ; stack_pointer_to_start_game &197a a2 01 LDX #&01 # Use level 1 &197c a0 00 LDY #&00 # Use round 0 &197e 20 cd 14 JSR &14cd ; initialise_screen &1981 a9 03 LDA #&03 &1983 20 b6 0d JSR &0db6 ; rnd # Pick random sprite for high score screen &1986 a8 TAY &1987 b9 1b 1b LDA &1b1b,Y ; high_score_screen_sprites &198a 85 7c STA &7c ; sprite &198c a9 7d LDA #&7d &198e 85 7d STA &7d ; count ; plot_random_sprites_loop &1990 a9 50 LDA #&50 &1992 20 b6 0d JSR &0db6 ; rnd # Pick random x position &1995 aa TAX &1996 20 01 0d JSR &0d01 ; wait_for_vsync &1999 a9 ff LDA #&ff &199b 20 b6 0d JSR &0db6 ; rnd # Pick random y position &199e a8 TAY &199f a5 7c LDA &7c ; sprite &19a1 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &19a4 20 d7 1a JSR &1ad7 ; check_for_space_or_fire # Doesn't return if SPACE or fire pressed &19a7 c6 7d DEC &7d ; count &19a9 d0 e5 BNE &1990 ; plot_random_sprites_loop &19ab 20 da 19 JSR &19da ; plot_high_score_screen &19ae a9 1a LDA #&1a &19b0 20 ee ff JSR &ffee ; OSWRCH &19b3 20 74 15 JSR &1574 ; disable_cursor &19b6 a9 0c LDA #&0c &19b8 85 0e STA &0e ; left_clip &19ba a9 44 LDA #&44 &19bc 85 0f STA &0f ; right_clip &19be 20 04 19 JSR &1904 ; high_score_screen_trogg_animation &19c1 20 f9 18 JSR &18f9 ; high_score_screen_scrubbly_animation &19c4 a9 4b LDA #&4b &19c6 20 3c 16 JSR &163c ; update_time_and_check_for_keypresses_for_Y_frames &19c9 a9 5b LDA #&5b ; SPRITE_FRAK_OFFSET &19cb ae 68 03 LDX &0368 ; player_x &19ce a0 52 LDY #&52 &19d0 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &19d3 a9 fa LDA #&fa &19d5 20 c7 1a JSR &1ac7 ; update_time_and_check_for_keypresses_for_Y_frames &19d8 18 CLC # Leave with carry clear to indicate not starting game &19d9 60 RTS ; plot_high_score_screen &19da 20 21 0d JSR &0d21 ; write_string &19dd 11 80 ; COLOUR 128 + 0 &19df 1c 06 16 21 08 ; define text window x:(&06, &21), y:(&08, &16) &19e4 19 04 bf 00 1f 01 ; MOVE &00bf, &011f &19ea 19 01 81 03 00 00 ; DRAW +&0381, +&0000 &19f0 19 01 00 00 e1 01 ; DRAW +&0000, +&01e1 &19f6 19 01 7f fc 00 00 ; DRAW -&0381, +&0000 &19fc 19 01 00 00 1f fe ; DRAW +&0000, -&01e1 &1a02 0c ; CLS &1a03 1f 07 00 ; TAB(&07, &00) &1a06 47 72 61 6e 64 6d 61 73 74 65 72 20 46 72 61 6b ; "Grandmaster Frak..." &1a16 2e 2e 2e &1a19 1f 02 02 ; TAB(&02, &02) &1a1c 2e 2e 2e 61 6e 64 20 74 68 65 20 46 75 72 69 6f ; "...and the Furious Five" &1a2c 75 73 20 46 69 76 65 &1a33 1f 01 0e ; TAB(&01, &0e) &1a36 28 43 29 20 41 61 72 64 76 61 72 6b 20 53 6f 66 ; "(C) Aardvark Software 1984" &1a46 74 77 61 72 65 20 31 39 38 34 &1a50 1a ; restore default windows &1a51 ea NOP &1a52 a2 00 LDX #&00 &1a54 86 60 STX &60 ; offset ; write_high_scores_loop # For each high score, &1a56 a4 60 LDY &60 ; offset &1a58 20 b3 1a JSR &1ab3 ; tab_to_high_score_position &1a5b a0 03 LDY #&03 ; write_high_score_name_loop # Write name &1a5d bd 80 08 LDA &0880,X ; high_scores &1a60 20 ee ff JSR &ffee ; OSWRCH &1a63 e8 INX &1a64 88 DEY &1a65 d0 f6 BNE &1a5d ; write_high_score_name_loop &1a67 a9 20 LDA #&20 ; " " &1a69 20 ee ff JSR &ffee ; OSWRCH &1a6c a0 03 LDY #&03 &1a6e 18 CLC ; write_high_score_score_loop # Write score &1a6f bd 80 08 LDA &0880,X ; high_scores &1a72 99 ff 00 STA &00ff,Y ; score_for_code - 1 # Copy score to &0100 - &0102 &1a75 99 02 01 STA &0102,Y ; score_for_code + 3 - 1 # and &0103 - &0105 for calculating code &1a78 20 24 16 JSR &1624 ; write_two_digit_number &1a7b e8 INX &1a7c 88 DEY &1a7d d0 f0 BNE &1a6f ; write_high_score_score_loop &1a7f a9 30 LDA #&30 ; "0" &1a81 20 ee ff JSR &ffee ; OSWRCH &1a84 a4 60 LDY &60 ; offset &1a86 20 b3 1a JSR &1ab3 ; tab_to_high_score_position &1a89 a9 09 LDA #&09 &1a8b a0 0b LDY #&0b ; RIGHT ; move_right_loop &1a8d 20 ee ff JSR &ffee ; OSWRCH &1a90 88 DEY &1a91 d0 fa BNE &1a8d ; move_right_loop &1a93 20 21 0d JSR &0d21 ; write_string # Write code &1a96 28 ; "(" &1a97 ea NOP &1a98 a9 63 LDA #&63 &1a9a 20 f9 1a JSR &1af9 ; write_score_code_character &1a9d a9 2a LDA #&2a &1a9f 20 f9 1a JSR &1af9 ; write_score_code_character &1aa2 a9 f7 LDA #&f7 &1aa4 20 f9 1a JSR &1af9 ; write_score_code_character &1aa7 20 21 0d JSR &0d21 ; write_string &1aaa 29 ; ")" &1aab ea NOP &1aac e6 60 INC &60 ; offset &1aae e0 24 CPX #&24 &1ab0 90 a4 BCC &1a56 ; write_high_scores_loop &1ab2 60 RTS ; tab_to_high_score_position &1ab3 b9 c1 1a LDA &1ac1,Y ; high_scores_y &1ab6 48 PHA ; high_score_y &1ab7 20 21 0d JSR &0d21 ; write_string &1aba 1f 11 ; TAB(&11, ...) &1abc ea NOP &1abd 68 PLA ; high_score_y &1abe 4c ee ff JMP &ffee ; OSWRCH ; high_scores_y &1ac1 09 0b 0c 0d 0e 0f ; update_time_and_check_for_keypresses_for_Y_frames &1ac7 a8 TAY ; update_time_and_check_for_keypresses_for_Y_frames_loop &1ac8 20 2c 0c JSR &0c2c ; update_time_and_check_for_keypresses # Returns non-zero if ESCAPE pressed &1acb d0 09 BNE &1ad6 ; leave &1acd 20 01 0d JSR &0d01 ; wait_for_vsync &1ad0 20 d7 1a JSR &1ad7 ; check_for_space_or_fire # Doesn't return if SPACE or fire pressed &1ad3 88 DEY &1ad4 d0 f2 BNE &1ac8 ; update_time_and_check_for_keypresses_for_Y_frames_loop ; leave &1ad6 60 RTS ; check_for_space_or_fire &1ad7 a5 87 LDA &87 ; previous_keyboard_or_joystick &1ad9 85 86 STA &86 ; keyboard_or_joystick &1adb a9 9d LDA #&9d ; SPACE &1add 20 9c 0d JSR &0d9c ; check_for_keypress &1ae0 d0 12 BNE &1af4 ; space_pressed &1ae2 a9 01 LDA #&01 &1ae4 85 86 STA &86 ; keyboard_or_joystick # Set to one to check joystick ; check_for_space_or_fire_loop &1ae6 20 59 13 JSR &1359 ; check_for_player_fire # Return non-zero if player pressed fire &1ae9 d0 05 BNE &1af0 ; return_or_fire_pressed &1aeb c6 86 DEC &86 ; keyboard_or_joystick # Set to zero to check keyboard &1aed 10 f7 BPL &1ae6 ; check_for_space_or_fire_loop &1aef 60 RTS ; return_or_fire_pressed &1af0 a5 86 LDA &86 ; keyboard_or_joystick &1af2 85 87 STA &87 ; previous_keyboard_or_joystick ; space_pressed &1af4 a6 7e LDX &7e ; stack_pointer_to_start_game &1af6 9a TXS # Leave high_score_screen, check_for_high_score or update_title_screen on return &1af7 38 SEC # Leave with carry set to indicate starting game &1af8 60 RTS ; write_score_code_character &1af9 85 29 STA &29 ; eor &1afb 4a LSR A &1afc b9 00 01 LDA &0100,Y ; score_for_code &1aff 79 01 01 ADC &0101,Y ; score_for_code + 1 &1b02 f9 02 01 SBC &0102,Y ; score_for_code + 2 &1b05 45 29 EOR &29 ; eor ; find_modulus_loop &1b07 c9 24 CMP #&24 &1b09 90 04 BCC &1b0f ; skip_wraparound &1b0b e9 24 SBC #&24 &1b0d b0 f8 BCS &1b07 ; find_modulus_loop ; skip_wraparound &1b0f 84 29 STY &29 ; tmp_y &1b11 a8 TAY &1b12 b9 5a 1b LDA &1b5a,Y ; score_code_characters &1b15 a4 29 LDY &29 ; tmp_y &1b17 c8 INY &1b18 4c ee ff JMP &ffee ; OSWRCH ; high_score_screen_sprites &1b1b 22 ; SPRITE_FRAK &1b1c 34 ; SPRITE_TROGG_RIGHT_HOLDING &1b1d 12 ; SPRITE_SCRUBBLY &1b1e 1d ; SPRITE_HOOTER ; plot_completion_screen &1b1f 20 21 0d JSR &0d21 ; write_string &1b22 1c 0b 12 1c 0e ; define text window x:(&0b, &1c), y:(&0e, &12) &1b27 19 04 5f 01 9f 01 ; MOVE &015f, &019f &1b2d 19 01 41 02 00 00 ; DRAW +&0241, +&0000 &1b33 19 01 00 00 a1 00 ; DRAW +&0000, +&00a1 &1b39 19 01 bf fd 00 00 ; DRAW -&0241, +&0000 &1b3f 19 01 00 00 5f ff ; DRAW +&0000, -&00a1 &1b45 0c ; CLS &1b46 1f 02 02 ; TAB(&02, &02) &1b49 57 65 27 76 65 20 64 6f 6e 65 20 69 74 21 ; "We've done it!" &1b57 1a ; restore default windows &1b58 ea NOP &1b59 60 RTS ; score_code_characters &1b5a 38 34 42 51 52 4a 46 49 5a 4d 41 58 47 43 53 32 ; "84BQRJFIZMAXGCS2" &1b6a 36 4e 31 4c 45 4f 4b 57 37 35 33 30 48 59 50 55 ; "6N1LEOKW7530HYPU" &1b7a 54 39 56 44 ; "T9VD" ; count_objects_of_sprite_A_in_class_Y # Called with A = sprite, Y = object class offset &1b7e 85 26 STA &26 ; sprite &1b80 a2 00 LDX #&00 &1b82 86 60 STX &60 ; count &1b84 be 00 0b LDX &0b00,Y ; object_class_data # First slot for class ; count_objects_of_sprite_A_in_class_Y_loop &1b87 bd 5e 04 LDA &045e,X ; objects_sprite &1b8a c5 26 CMP &26 ; sprite &1b8c d0 02 BNE &1b90 ; skip_counting &1b8e e6 60 INC &60 ; count ; skip_counting &1b90 e8 INX &1b91 8a TXA &1b92 d9 03 0b CMP &0b03,Y ; object_class_data + 3 # First slot for next class (i.e. last slot plus one) &1b95 90 f0 BCC &1b87 ; count_objects_of_sprite_A_in_class_Y_loop &1b97 a5 26 LDA &26 ; sprite &1b99 a6 60 LDX &60 ; count # Leave with X = number of objects &1b9b 60 RTS ; no_slot_for_new_object &1b9c 68 PLA ; sprite &1b9d 68 PLA ; x &1b9e 68 PLA ; y &1b9f 4c fa 1b JMP &1bfa ; leave ; update_balloons_and_daggers &1ba2 a0 06 LDY #&06 ; OBJECT_CLASS_B &1ba4 20 fb 1b JSR &1bfb ; update_objects_of_class_Y # Update balloons &1ba7 a0 03 LDY #&03 ; OBJECT_CLASS_D &1ba9 20 fb 1b JSR &1bfb ; update_objects_of_class_Y # Update daggers &1bac c6 88 DEC &88 ; new_balloon_or_dagger_cooldown &1bae d0 4a BNE &1bfa ; leave # Is it time to add a new balloon or dagger? &1bb0 a5 89 LDA &89 ; new_balloon_or_dagger_frequency &1bb2 85 88 STA &88 ; new_balloon_or_dagger_cooldown &1bb4 a9 03 LDA #&03 &1bb6 20 b6 0d JSR &0db6 ; rnd &1bb9 a8 TAY &1bba f0 12 BEQ &1bce ; add_dagger # One in four chance of dagger, otherwise balloon ; add_balloon &1bbc a9 08 LDA #&08 # Balloons start at bottom of screen &1bbe 48 PHA ; y &1bbf a0 06 LDY #&06 ; OBJECT_CLASS_B &1bc1 a9 50 LDA #&50 # Balloons start at random horizontal positions &1bc3 20 b6 0d JSR &0db6 ; rnd &1bc6 18 CLC &1bc7 65 10 ADC &10 ; level_scroll &1bc9 48 PHA ; x &1bca a9 27 LDA #&27 ; SPRITE_BALLOON &1bcc d0 12 BNE &1be0 ; add_object # Always branches ; add_dagger &1bce a9 fa LDA #&fa # Daggers start at top of screen &1bd0 48 PHA ; y &1bd1 a0 03 LDY #&03 ; OBJECT_CLASS_D &1bd3 a9 28 LDA #&28 # Dagger start randomly in right half of screen &1bd5 20 b6 0d JSR &0db6 ; rnd &1bd8 18 CLC &1bd9 65 10 ADC &10 ; level_scroll &1bdb 69 32 ADC #&32 &1bdd 48 PHA ; x &1bde a9 25 LDA #&25 ; SPRITE_DAGGER ; add_object &1be0 48 PHA ; sprite &1be1 20 97 1c JSR &1c97 ; find_slot_for_object_class_Y # Returns carry clear if slot found; X = slot &1be4 b0 b6 BCS &1b9c ; no_slot_for_new_object &1be6 68 PLA ; sprite &1be7 9d 5e 04 STA &045e,X ; objects_sprite &1bea 68 PLA ; x &1beb 9d 68 03 STA &0368,X ; objects_x &1bee 68 PLA ; y &1bef 9d e3 03 STA &03e3,X ; objects_y &1bf2 a9 14 LDA #&14 # Balloons and daggers stay paused for 20 frames &1bf4 9d d9 04 STA &04d9,X ; objects_x_velocity # Used as cooldown for movement &1bf7 20 20 0b JSR &0b20 ; plot_object_without_background ; leave &1bfa 60 RTS ; update_objects_of_class_Y &1bfb 84 5b STY &5b ; object_class_offset &1bfd be 00 0b LDX &0b00,Y ; object_class_data # First slot for class ; update_objects_of_class_Y_loop &1c00 20 0d 1c JSR &1c0d ; update_object &1c03 a4 5b LDY &5b ; object_class_offset &1c05 e8 INX &1c06 8a TXA &1c07 d9 03 0b CMP &0b03,Y ; object_class_data + 3 # First slot for next class (i.e. last slot plus one) &1c0a 90 f4 BCC &1c00 ; update_objects_of_class_Y_loop ; leave &1c0c 60 RTS ; update_object &1c0d 20 2f 1c JSR &1c2f ; get_object_details &1c10 a5 68 LDA &68 ; object_sprite &1c12 c9 ff CMP #&ff ; SPRITE_NONE &1c14 f0 f6 BEQ &1c0c ; leave &1c16 a0 09 LDY #&09 # Only consider balloons and daggers &1c18 20 d1 12 JSR &12d1 ; call_sprite_update_routine &1c1b 20 3f 1c JSR &1c3f ; compare_object_details # Returns non-zero if object has changed &1c1e f0 ec BEQ &1c0c ; leave # Has the object changed? &1c20 20 23 0b JSR &0b23 ; unplot_object_with_background # If so, unplot it &1c23 20 53 1c JSR &1c53 ; set_object_details &1c26 a5 68 LDA &68 ; object_sprite &1c28 c9 ff CMP #&ff ; SPRITE_NONE &1c2a f0 e0 BEQ &1c0c ; leave # Is the object still present? &1c2c 4c 20 0b JMP &0b20 ; plot_object_without_background # If so, replot it ; get_object_details &1c2f bd 5e 04 LDA &045e,X ; objects_sprite &1c32 85 68 STA &68 ; object_sprite &1c34 bd 68 03 LDA &0368,X ; objects_x &1c37 85 69 STA &69 ; object_x &1c39 bd e3 03 LDA &03e3,X ; objects_y &1c3c 85 6a STA &6a ; object_y &1c3e 60 RTS ; compare_object_details &1c3f bd 5e 04 LDA &045e,X ; objects_sprite &1c42 c5 68 CMP &68 ; object_sprite &1c44 d0 0c BNE &1c52 ; leave &1c46 bd 68 03 LDA &0368,X ; objects_x &1c49 c5 69 CMP &69 ; object_x &1c4b d0 05 BNE &1c52 ; leave &1c4d bd e3 03 LDA &03e3,X ; objects_y &1c50 c5 6a CMP &6a ; object_y ; leave &1c52 60 RTS # Leave with zero set if object hasn't changed ; set_object_details &1c53 a5 68 LDA &68 ; object_sprite &1c55 9d 5e 04 STA &045e,X ; objects_sprite &1c58 a5 69 LDA &69 ; object_x &1c5a 9d 68 03 STA &0368,X ; objects_x &1c5d a5 6a LDA &6a ; object_y &1c5f 9d e3 03 STA &03e3,X ; objects_y &1c62 60 RTS ; remove_object &1c63 a9 ff LDA #&ff ; SPRITE_NONE &1c65 85 68 STA &68 ; object_sprite &1c67 60 RTS ; update_balloon &1c68 20 8c 1c JSR &1c8c ; check_object_movement_cooldown # Returns non-zero if object waiting to move &1c6b d0 1e BNE &1c8b ; leave &1c6d 18 CLC &1c6e a5 6a LDA &6a ; object_y &1c70 69 06 ADC #&06 # Move balloon up &1c72 85 6a STA &6a ; object_y &1c74 c9 f0 CMP #&f0 &1c76 b0 eb BCS &1c63 ; remove_object # Balloons disappear at top of screen &1c78 60 RTS ; update_dagger &1c79 20 8c 1c JSR &1c8c ; check_object_movement_cooldown # Returns non-zero if object waiting to move &1c7c d0 0d BNE &1c8b ; leave &1c7e 38 SEC &1c7f a5 6a LDA &6a ; object_y &1c81 e9 02 SBC #&02 # Move dagger down &1c83 85 6a STA &6a ; object_y &1c85 c9 14 CMP #&14 &1c87 90 da BCC &1c63 ; remove_object # Daggers disappear at bottom of screen &1c89 c6 69 DEC &69 ; object_x # Move dagger left ; leave &1c8b 60 RTS ; check_object_movement_cooldown &1c8c bc d9 04 LDY &04d9,X ; objects_x_velocity # Used as cooldown for movement &1c8f f0 05 BEQ &1c96 ; leave &1c91 88 DEY &1c92 98 TYA &1c93 9d d9 04 STA &04d9,X ; objects_x_velocity # Used as cooldown for movement ; leave &1c96 60 RTS ; find_slot_for_object_class_Y &1c97 be 00 0b LDX &0b00,Y ; object_class_data # First slot for class ; find_slot_for_object_class_Y_loop &1c9a bd 5e 04 LDA &045e,X ; objects_sprite &1c9d c9 ff CMP #&ff ; SPRITE_NONE &1c9f f0 08 BEQ &1ca9 ; leave_with_carry_clear &1ca1 e8 INX &1ca2 8a TXA &1ca3 d9 03 0b CMP &0b03,Y ; object_class_data + 3 # First slot for next class (i.e. last slot plus one) &1ca6 90 f2 BCC &1c9a ; find_slot_for_object_class_Y_loop &1ca8 60 RTS # Leave with carry set if no free slot available ; leave_with_carry_clear &1ca9 18 CLC # Leave with carry clear if free slot found; X = slot &1caa 60 RTS ; process_sprite_routine_addresses &1cab 98 1d ; &1d98 = add_sprite_to_bounding_boxes_list - 1 &1cad c9 1d ; &1dc9 = check_sprite_against_bounding_boxes_list - 1 &1caf 1d 1e ; &1e1d = plot_or_unplot_sprite_with_or_without_background - 1 ; check_object_against_bounding_boxes &1cb1 a5 50 LDA &50 ; processing_mode &1cb3 48 PHA ; previous_processing_mode &1cb4 a9 02 LDA #&02 ; CHECK_BOUNDING_BOXES_LIST &1cb6 20 2e 1d JSR &1d2e ; process_sprite # Check object's sprite(s) for overlap with bounding boxes &1cb9 68 PLA ; previous_processing_mode &1cba 85 50 STA &50 ; processing_mode &1cbc 60 RTS # Leave with carry set if overlap ; check_if_object_overlaps_classes &1cbd 85 5a STA &5a ; classes_to_check &1cbf 86 33 STX &33 ; object_being_checked &1cc1 20 3c 0b JSR &0b3c ; get_object_position_and_sprite &1cc4 20 19 1d JSR &1d19 ; calculate_scrolled_clips # Resets list of bounding boxes &1cc7 a9 00 LDA #&00 ; ADD_TO_BOUNDING_BOXES_LIST &1cc9 20 2e 1d JSR &1d2e ; process_sprite # Create list of bounding boxes for object's sprite(s) &1ccc 4c 7c 14 JMP &147c ; check_for_overlap_with_classes # Use this to check for overlap with specified classes ; plot_or_unplot_or_unplot_sprite_with_or_without_background # Called with Y = sprite &1ccf 85 5e STA &5e ; sprite_plotting_mode &1cd1 98 TYA &1cd2 48 PHA ; sprite &1cd3 20 19 1d JSR &1d19 ; calculate_scrolled_clips # Resets list of bounding boxes &1cd6 a9 04 LDA #&04 ; PLOT_SPRITE &1cd8 20 2e 1d JSR &1d2e ; process_sprite # Plot sprite &1cdb 68 PLA ; sprite &1cdc a8 TAY &1cdd 24 5e BIT &5e ; sprite_plotting_mode # &40 (PLOT_BACKGROUND) set if including background &1cdf 50 37 BVC &1d18 ; leave &1ce1 a5 6f LDA &6f ; bounding_boxes_offset &1ce3 f0 33 BEQ &1d18 ; leave &1ce5 a9 ff LDA #&ff &1ce7 85 5f STA &5f ; replot_overlaps # Set to negative to replot objects that are overlapped &1ce9 85 5a STA &5a ; classes_to_check # Set to &ff to consider overlaps for all classes &1ceb a5 0e LDA &0e ; left_clip &1ced 48 PHA ; previous_left_clip &1cee 38 SEC &1cef a5 75 LDA &75 ; scrolled_right_clip &1cf1 e5 10 SBC &10 ; level_scroll &1cf3 c5 0e CMP &0e ; left_clip &1cf5 30 06 BMI &1cfd ; skip_setting_left_clip &1cf7 c5 0f CMP &0f ; right_clip &1cf9 10 02 BPL &1cfd ; skip_setting_left_clip &1cfb 85 0e STA &0e ; left_clip ; skip_setting_left_clip &1cfd a5 0f LDA &0f ; right_clip &1cff 48 PHA ; previous_right_clip &1d00 38 SEC &1d01 a5 76 LDA &76 ; scrolled_left_clip &1d03 e5 10 SBC &10 ; level_scroll &1d05 c5 0f CMP &0f ; right_clip &1d07 10 06 BPL &1d0f ; skip_setting_right_clip &1d09 c5 0e CMP &0e ; left_clip &1d0b 30 02 BMI &1d0f ; skip_setting_right_clip &1d0d 85 0f STA &0f ; right_clip ; skip_setting_right_clip &1d0f 20 7c 14 JSR &147c ; check_for_overlap_with_classes # Replots objects that are overlapped, i.e. background &1d12 68 PLA ; previous_right_clip &1d13 85 0f STA &0f ; right_clip &1d15 68 PLA ; previous_left_clip &1d16 85 0e STA &0e ; left_clip ; leave &1d18 60 RTS ; calculate_scrolled_clips &1d19 18 CLC &1d1a a5 10 LDA &10 ; level_scroll &1d1c 65 0f ADC &0f ; right_clip &1d1e 85 75 STA &75 ; scrolled_right_clip &1d20 18 CLC &1d21 a5 10 LDA &10 ; level_scroll &1d23 65 0e ADC &0e ; left_clip &1d25 85 76 STA &76 ; scrolled_left_clip &1d27 a9 00 LDA #&00 &1d29 85 6f STA &6f ; bounding_boxes_offset # Reset list of bounding boxes &1d2b 85 5f STA &5f ; replot_overlaps # Set to positive to only check, not replot overlaps &1d2d 60 RTS ; process_sprite &1d2e 85 50 STA &50 ; processing_mode ; process_subsprite # Called with Y = sprite &1d30 b1 08 LDA (&08),Y ; sprite_widths_address &1d32 0a ASL A # If lowest seven bits of width are zero, &1d33 f0 0f BEQ &1d44 ; process_sprite_composed_of_other_sprites # sprite is composed of other sprites &1d35 84 26 STY &26 ; sprite &1d37 a4 50 LDY &50 ; processing_mode &1d39 b9 ac 1c LDA &1cac,Y ; process_sprite_routine_addresses + 1 &1d3c 48 PHA &1d3d b9 ab 1c LDA &1cab,Y ; process_sprite_routine_addresses &1d40 48 PHA &1d41 a4 26 LDY &26 ; sprite &1d43 60 RTS # Call plot sprite routine ; process_sprite_composed_of_other_sprites # Can be called recursively &1d44 a5 1e LDA &1e ; count &1d46 48 PHA ; previous_count &1d47 a5 1f LDA &1f ; sprite_data_address_low &1d49 48 PHA ; previous_sprite_data_address_low &1d4a a5 20 LDA &20 ; sprite_data_address_high &1d4c 48 PHA ; previous_sprite_data_address_high &1d4d b1 0a LDA (&0a),Y ; sprite_heights_address # Used as number of subsprites &1d4f 85 1e STA &1e ; count &1d51 18 CLC &1d52 a5 00 LDA &00 ; sprite_x_offsets_address_low &1d54 71 04 ADC (&04),Y ; sprite_data_offsets_low_address &1d56 85 1f STA &1f ; sprite_data_address_low &1d58 a5 01 LDA &01 ; sprite_x_offsets_address_high &1d5a 71 06 ADC (&06),Y ; sprite_data_offsets_high_address &1d5c 85 20 STA &20 ; sprite_data_address_high ; process_sprite_composed_of_other_sprites_loop # Three bytes of sprite data per subsprite &1d5e a0 02 LDY #&02 &1d60 a5 12 LDA &12 ; sprite_y &1d62 48 PHA ; previous_sprite_y &1d63 18 CLC &1d64 71 1f ADC (&1f),Y ; sprite_data_address # Third byte is y offset of subsprite &1d66 85 12 STA &12 ; sprite_y &1d68 88 DEY &1d69 a5 11 LDA &11 ; sprite_x &1d6b 48 PHA ; previous_sprite_x &1d6c 18 CLC &1d6d 71 1f ADC (&1f),Y ; sprite_data_address # Second byte is x offset of subsprite &1d6f 85 11 STA &11 ; sprite_x &1d71 88 DEY &1d72 b1 1f LDA (&1f),Y ; sprite_data_address # First byte is sprite of subsprite &1d74 a8 TAY &1d75 20 30 1d JSR &1d30 ; process_subsprite &1d78 68 PLA ; previous_sprite_x &1d79 85 11 STA &11 ; sprite_x &1d7b 68 PLA ; previous_sprite_y &1d7c 85 12 STA &12 ; sprite_y &1d7e b0 0f BCS &1d8f ; skip_remaining_sprites &1d80 a5 1f LDA &1f ; sprite_data_address_low &1d82 69 03 ADC #&03 &1d84 85 1f STA &1f ; sprite_data_address_low &1d86 90 02 BCC &1d8a ; skip_page &1d88 e6 20 INC &20 ; sprite_data_address_high ; skip_page &1d8a c6 1e DEC &1e ; count &1d8c d0 d0 BNE &1d5e ; process_sprite_composed_of_other_sprites_loop &1d8e 18 CLC ; skip_remaining_sprites &1d8f 68 PLA ; previous_sprite_data_address_high &1d90 85 20 STA &20 ; sprite_data_address_high &1d92 68 PLA ; previous_sprite_data_address_low &1d93 85 1f STA &1f ; sprite_data_address_low &1d95 68 PLA ; previous_count &1d96 85 1e STA &1e ; count &1d98 60 RTS ; add_sprite_to_bounding_boxes_list # Called with Y = sprite &1d99 20 92 15 JSR &1592 ; calculate_object_min_and_max_x_and_y ; add_region_to_bounding_boxes_list &1d9c 98 TYA &1d9d 48 PHA ; tmp_y &1d9e a4 6f LDY &6f ; bounding_boxes_offset &1da0 a5 45 LDA &45 ; object_min_x &1da2 99 00 01 STA &0100,Y ; bounding_boxes_min_x &1da5 c5 75 CMP &75 ; scrolled_right_clip &1da7 10 02 BPL &1dab ; skip_setting_scrolled_right_clip &1da9 85 75 STA &75 ; scrolled_right_clip ; skip_setting_scrolled_right_clip &1dab a5 46 LDA &46 ; object_max_x &1dad 99 01 01 STA &0101,Y ; bounding_boxes_max_x &1db0 c5 76 CMP &76 ; scrolled_left_clip &1db2 30 02 BMI &1db6 ; skip_setting_scrolled_left_clip &1db4 85 76 STA &76 ; scrolled_left_clip ; skip_setting_scrolled_left_clip &1db6 a5 48 LDA &48 ; object_min_y &1db8 99 02 01 STA &0102,Y ; bounding_boxes_min_y &1dbb a5 47 LDA &47 ; object_max_y &1dbd 99 03 01 STA &0103,Y ; bounding_boxes_max_y &1dc0 18 CLC &1dc1 98 TYA &1dc2 69 04 ADC #&04 &1dc4 85 6f STA &6f ; bounding_boxes_offset &1dc6 68 PLA ; tmp_y &1dc7 a8 TAY &1dc8 18 CLC # Unnecessary code &1dc9 60 RTS ; check_sprite_against_bounding_boxes_list &1dca 8a TXA &1dcb 48 PHA ; tmp_x &1dcc a2 00 LDX #&00 ; check_sprite_against_bounding_boxes_list_loop # For each bounding box in the list, &1dce e4 6f CPX &6f ; bounding_boxes_offset &1dd0 b0 3d BCS &1e0f ; leave_with_carry_clear_after_restoring_x &1dd2 a5 11 LDA &11 ; sprite_x &1dd4 71 00 ADC (&00),Y ; sprite_x_offsets_address &1dd6 dd 01 01 CMP &0101,X ; bounding_boxes_max_x &1dd9 10 3c BPL &1e17 ; consider_next_bounding_box # does the sprite overlap the bounding box? &1ddb 85 26 STA &26 ; min_x &1ddd b1 08 LDA (&08),Y ; sprite_widths_address &1ddf 0a ASL A # Clear top bit &1de0 4a LSR A &1de1 65 26 ADC &26 ; min_x &1de3 dd 00 01 CMP &0100,X ; bounding_boxes_min_x &1de6 f0 2f BEQ &1e17 ; consider_next_bounding_box &1de8 30 2d BMI &1e17 ; consider_next_bounding_box &1dea 18 CLC &1deb a5 12 LDA &12 ; sprite_y &1ded 71 02 ADC (&02),Y ; sprite_y_offsets_address &1def dd 03 01 CMP &0103,X ; bounding_boxes_max_y &1df2 10 23 BPL &1e17 ; consider_next_bounding_box &1df4 18 CLC &1df5 71 0a ADC (&0a),Y ; sprite_heights_address &1df7 dd 02 01 CMP &0102,X ; bounding_boxes_min_y &1dfa f0 1b BEQ &1e17 ; consider_next_bounding_box &1dfc 30 19 BMI &1e17 ; consider_next_bounding_box &1dfe 24 5f BIT &5f ; replot_overlaps # Negative if overlaps should be replotted &1e00 10 11 BPL &1e13 ; leave_with_carry_set_after_restoring_x &1e02 a5 5e LDA &5e ; sprite_plotting_mode &1e04 48 PHA ; previous_sprite_plotting_mode &1e05 a9 00 LDA #&00 # &80 clear to plot, &40 clear to plot only sprite &1e07 85 5e STA &5e ; sprite_plotting_mode &1e09 20 36 1e JSR &1e36 ; plot_or_unplot_sprite &1e0c 68 PLA ; previous_sprite_plotting_mode &1e0d 85 5e STA &5e ; sprite_plotting_mode ; leave_with_carry_clear_after_restoring_x &1e0f 68 PLA ; tmp_x &1e10 aa TAX ; leave_with_carry_clear &1e11 18 CLC # Leave with carry clear to indicate no overlap &1e12 60 RTS ; leave_with_carry_set_after_restoring_x &1e13 68 PLA ; tmp_x &1e14 aa TAX &1e15 38 SEC # Leave with carry set to indicate overlap &1e16 60 RTS ; consider_next_bounding_box &1e17 e8 INX # Move to next bounding box in list &1e18 e8 INX &1e19 e8 INX &1e1a e8 INX &1e1b 4c ce 1d JMP &1dce ; check_sprite_against_bounding_boxes_list_loop ; plot_or_unplot_sprite_with_or_without_background &1e1e a5 5e LDA &5e ; sprite_plotting_mode &1e20 f0 02 BEQ &1e24 ; plot_without_background_or_unplot # &80 clear if plotting, &40 clear if without background &1e22 10 0d BPL &1e31 ; plot_with_background # or &80 set if unplotting ; plot_without_background_or_unplot &1e24 98 TYA &1e25 48 PHA ; tmp_y &1e26 20 36 1e JSR &1e36 ; plot_or_unplot_sprite # Returns carry set if sprite beyond edge of screen &1e29 68 PLA ; tmp_y &1e2a a8 TAY &1e2b b0 e4 BCS &1e11 ; leave_with_carry_clear # Don't plot background if beyond edge of screen &1e2d 24 5e BIT &5e ; sprite_plotting_mode &1e2f 50 e0 BVC &1e11 ; leave_with_carry_clear # &40 set if unplotting with background ; plot_with_background &1e31 4c 99 1d JMP &1d99 ; add_sprite_to_bounding_boxes_list ; leave_with_carry_set &1e34 38 SEC # Leave with carry set to indicate sprite not plotted &1e35 60 RTS ; plot_or_unplot_sprite &1e36 38 SEC &1e37 a5 11 LDA &11 ; sprite_x &1e39 e5 10 SBC &10 ; level_scroll &1e3b 18 CLC &1e3c 71 00 ADC (&00),Y ; sprite_x_offsets_address &1e3e c5 0f CMP &0f ; right_clip # Is the sprite completely clipped to right? &1e40 10 f2 BPL &1e34 ; leave_with_carry_set # If so, leave with carry set to indicate not plotted &1e42 85 21 STA &21 ; screen_x &1e44 b1 08 LDA (&08),Y ; sprite_widths_address &1e46 0a ASL A # Clear top bit &1e47 4a LSR A &1e48 85 17 STA &17 ; width &1e4a 65 21 ADC &21 ; screen_x &1e4c c5 0e CMP &0e ; left_clip # Is the sprite completely clipped to left? &1e4e 30 e4 BMI &1e34 ; leave_with_carry_set # If so, leave with carry set to indicate not plotted &1e50 18 CLC &1e51 a5 12 LDA &12 ; sprite_y &1e53 71 02 ADC (&02),Y ; sprite_y_offsets_address &1e55 85 22 STA &22 ; bottom_row &1e57 b1 0a LDA (&0a),Y ; sprite_heights_address &1e59 85 18 STA &18 ; height &1e5b 24 74 BIT &74 ; level_is_inverted # Negative if level is inverted &1e5d 10 07 BPL &1e66 ; skip_inversion &1e5f 18 CLC &1e60 65 22 ADC &22 ; bottom_row &1e62 45 74 EOR &74 ; level_is_inverted ; #&ff &1e64 85 22 STA &22 ; bottom_row ; skip_inversion &1e66 18 CLC &1e67 b1 04 LDA (&04),Y ; sprite_data_offsets_low_address &1e69 65 00 ADC &00 ; sprite_x_offsets_address_low &1e6b 85 13 STA &13 ; sprite_address_low &1e6d b1 06 LDA (&06),Y ; sprite_data_offsets_high_address # If top bit set, &1e6f 30 13 BMI &1e84 ; plot_using_pixel_value # use a fixed pixel value for the whole sprite ; plot_using_sprite_data # Otherwise, use sprite data &1e71 65 01 ADC &01 ; sprite_x_offsets_address_high &1e73 85 14 STA &14 ; sprite_address_high &1e75 a5 74 LDA &74 ; level_is_inverted &1e77 29 02 AND #&02 ; PLOT_MODE_PLOT_INVERTED_SPRITE # &02 set if level is inverted &1e79 aa TAX &1e7a b1 08 LDA (&08),Y ; sprite_widths_address # Top bit set if sprite is inverted &1e7c 10 0c BPL &1e8a ; set_some_plot_type &1e7e 8a TXA &1e7f 49 02 EOR #&02 ; PLOT_MODE_PLOT_INVERTED_SPRITE ^ PLOT_MODE_PLOT_UNINVERTED_SPRITE &1e81 aa TAX &1e82 10 06 BPL &1e8a ; set_plotting_mode # Always branches ; plot_using_pixel_value &1e84 b1 04 LDA (&04),Y ; sprite_data_offsets_low_address &1e86 85 59 STA &59 ; pixel_value &1e88 a2 04 LDX #&04 ; PLOT_MODE_PLOT_PIXEL_VALUE ; set_plotting_mode &1e8a 86 1b STX &1b ; group_plotting_mode &1e8c 20 a9 1f JSR &1fa9 ; calculate_screen_address &1e8f a5 1b LDA &1b ; group_plotting_mode &1e91 24 5e BIT &5e ; sprite_plotting_mode # &80 (PLOT_UNPLOT) set if unplotting sprite &1e93 10 03 BPL &1e98 ; not_unplotting &1e95 18 CLC &1e96 69 06 ADC #&06 ; PLOT_MODE_UNPLOT_UNINVERTED_SPRITE - PLOT_MODE_PLOT_INVERTED_SPRITE ; not_unplotting &1e98 aa TAX &1e99 bd 9d 1f LDA &1f9d,X ; plot_byte_of_sprite_routine_addresses &1e9c 8d c5 01 STA &01c5 ; plot_group_of_sprite_8 + 1 &1e9f 8d c8 01 STA &01c8 ; plot_group_of_sprite_7 + 1 &1ea2 8d cb 01 STA &01cb ; plot_group_of_sprite_6 + 1 &1ea5 8d ce 01 STA &01ce ; plot_group_of_sprite_5 + 1 &1ea8 8d d1 01 STA &01d1 ; plot_group_of_sprite_4 + 1 &1eab 8d d4 01 STA &01d4 ; plot_group_of_sprite_3 + 1 &1eae 8d d7 01 STA &01d7 ; plot_group_of_sprite_2 + 1 &1eb1 8d da 01 STA &01da ; plot_group_of_sprite_1 + 1 &1eb4 bd 9e 1f LDA &1f9e,X ; plot_byte_of_sprite_routine_addresses + 1 &1eb7 8d c6 01 STA &01c6 ; plot_group_of_sprite_8 + 2 &1eba 8d c9 01 STA &01c9 ; plot_group_of_sprite_7 + 2 &1ebd 8d cc 01 STA &01cc ; plot_group_of_sprite_6 + 2 &1ec0 8d cf 01 STA &01cf ; plot_group_of_sprite_5 + 2 &1ec3 8d d2 01 STA &01d2 ; plot_group_of_sprite_4 + 2 &1ec6 8d d5 01 STA &01d5 ; plot_group_of_sprite_3 + 2 &1ec9 8d d8 01 STA &01d8 ; plot_group_of_sprite_2 + 2 &1ecc 8d db 01 STA &01db ; plot_group_of_sprite_1 + 2 &1ecf a5 22 LDA &22 ; bottom_row &1ed1 29 07 AND #&07 &1ed3 0a ASL A &1ed4 aa TAX &1ed5 bd 31 1f LDA &1f31,X ; plot_group_of_sprite_routine_addresses &1ed8 85 1c STA &1c ; plot_group_of_sprite_routine_address_low &1eda bd 32 1f LDA &1f32,X ; plot_group_of_sprite_routine_addresses + 1 &1edd 85 1d STA &1d ; plot_group_of_sprite_routine_address_high &1edf a5 13 LDA &13 ; sprite_address_low &1ee1 d0 02 BNE &1ee5 ; skip_page &1ee3 c6 14 DEC &14 ; sprite_address_high ; skip_page &1ee5 c6 13 DEC &13 ; sprite_address_low &1ee7 a2 00 LDX #&00 ; plot_sprite_column_loop &1ee9 a4 18 LDY &18 ; height &1eeb a5 21 LDA &21 ; screen_x &1eed c5 0e CMP &0e ; left_clip &1eef 30 07 BMI &1ef8 ; skip_plotting_column &1ef1 c5 0f CMP &0f ; right_clip &1ef3 10 37 BPL &1f2c ; leave_with_carry_clear &1ef5 20 2e 1f JSR &1f2e ; plot_group_of_sprite_routine_address ; skip_plotting_column &1ef8 c6 17 DEC &17 ; width &1efa f0 30 BEQ &1f2c ; leave_with_carry_clear &1efc e6 21 INC &21 ; screen_x &1efe 18 CLC &1eff 98 TYA &1f00 65 13 ADC &13 ; sprite_address_low &1f02 85 13 STA &13 ; sprite_address_low &1f04 90 02 BCC &1f08 ; skip_page &1f06 e6 14 INC &14 ; sprite_address_high ; skip_page &1f08 18 CLC &1f09 a9 08 LDA #&08 &1f0b 65 15 ADC &15 ; row_screen_address_low &1f0d 85 15 STA &15 ; row_screen_address_low &1f0f 85 19 STA &19 ; screen_address_low &1f11 8a TXA &1f12 65 16 ADC &16 ; row_screen_address_high &1f14 85 16 STA &16 ; row_screen_address_high &1f16 85 1a STA &1a ; screen_address_high &1f18 a5 18 LDA &18 ; height &1f1a 65 19 ADC &19 ; screen_address_low &1f1c 8a TXA &1f1d 65 1a ADC &1a ; screen_address_high &1f1f 10 c8 BPL &1ee9 ; plot_sprite_column_loop &1f21 38 SEC &1f22 a5 1a LDA &1a ; screen_address_high &1f24 e9 50 SBC #&50 &1f26 85 1a STA &1a ; screen_address_high &1f28 85 16 STA &16 ; row_screen_address_high &1f2a 10 bd BPL &1ee9 ; plot_sprite_column_loop ; leave_with_carry_clear &1f2c 18 CLC # Leave with carry clear to indicate sprite plotted &1f2d 60 RTS ; call_plot_group_of_sprite &1f2e 6c 1c 00 JMP (&001c) ; plot_group_of_sprite_routine_address ; plot_group_of_sprite_routine_addresses &1f31 c4 01 ; &01c4 = plot_group_of_sprite_8 &1f33 c7 01 ; &01c7 = plot_group_of_sprite_7 &1f35 ca 01 ; &01ca = plot_group_of_sprite_6 &1f37 cd 01 ; &01cd = plot_group_of_sprite_5 &1f39 d0 01 ; &01d0 = plot_group_of_sprite_4 &1f3b d3 01 ; &01d3 = plot_group_of_sprite_3 &1f3d d6 01 ; &01d6 = plot_group_of_sprite_2 &1f3f d9 01 ; &01d9 = plot_group_of_sprite_1 ; plot_byte_of_uninverted_sprite &1f41 b1 13 LDA (&13),Y ; sprite_address &1f43 85 80 STA &80 ; mask_table_address_low &1f45 a1 80 LDA (&80,X) ; mask_table_address # X = 0 here &1f47 31 19 AND (&19),Y ; screen_address &1f49 05 80 ORA &80 ; mask_table_address_low &1f4b 91 19 STA (&19),Y ; screen_address &1f4d 88 DEY &1f4e f0 15 BEQ &1f65 ; leave_plot_group_of_sprite_after_restoring_Y &1f50 60 RTS ; plot_byte_of_inverted_sprite &1f51 e6 13 INC &13 ; sprite_address_low &1f53 f0 15 BEQ &1f6a ; next_page ; skip_page &1f55 a1 13 LDA (&13,X) ; sprite_address # X = 0 here &1f57 85 80 STA &80 ; mask_table_address_low &1f59 a1 80 LDA (&80,X) ; mask_table_address &1f5b 31 19 AND (&19),Y ; screen_address &1f5d 05 80 ORA &80 ; mask_table_address_low &1f5f 91 19 STA (&19),Y ; screen_address &1f61 88 DEY &1f62 f0 03 BEQ &1f67 ; leave_plot_group_of_sprite &1f64 60 RTS ; leave_plot_group_of_sprite_after_restoring_Y &1f65 a4 18 LDY &18 ; height ; leave_plot_group_of_sprite &1f67 68 PLA # Leave plot_group_of_sprite on return &1f68 68 PLA &1f69 60 RTS ; next_page &1f6a e6 14 INC &14 ; sprite_address_high &1f6c d0 e7 BNE &1f55 ; skip_page # Always branches ; plot_byte &1f6e a5 59 LDA &59 ; pixel_value &1f70 91 19 STA (&19),Y ; screen_address &1f72 88 DEY &1f73 f0 f2 BEQ &1f67 ; leave_plot_group_of_sprite &1f75 60 RTS ; unplot_byte_of_uninverted_sprite &1f76 b1 13 LDA (&13),Y ; sprite_address &1f78 49 ff EOR #&ff &1f7a 31 19 AND (&19),Y ; screen_address &1f7c 91 19 STA (&19),Y ; screen_address &1f7e 88 DEY &1f7f f0 e4 BEQ &1f65 ; leave_plot_group_of_sprite_after_restoring_Y &1f81 60 RTS ; unplot_byte_of_inverted_sprite &1f82 e6 13 INC &13 ; sprite_address_low &1f84 f0 13 BEQ &1f99 ; next_page ; skip_page &1f86 a1 13 LDA (&13,X) ; sprite_address # X = 0 here &1f88 49 ff EOR #&ff &1f8a 31 19 AND (&19),Y ; screen_address &1f8c 91 19 STA (&19),Y ; screen_address &1f8e 88 DEY &1f8f f0 d6 BEQ &1f67 ; leave_plot_group_of_sprite &1f91 60 RTS ; unplot_byte &1f92 8a TXA # X = 0 here &1f93 91 19 STA (&19),Y ; screen_address &1f95 88 DEY &1f96 f0 cf BEQ &1f67 ; leave_plot_group_of_sprite &1f98 60 RTS ; next_page &1f99 e6 14 INC &14 ; sprite_address_high &1f9b d0 e9 BNE &1f86 ; skip_page # Always branches ; plot_byte_of_sprite_routine_addresses &1f9d 41 1f ; &00 : PLOT_MODE_PLOT_UNINVERTED_SPRITE : &1f41 = plot_byte_of_uninverted_sprite &1f9f 51 1f ; &02 : PLOT_MODE_PLOT_INVERTED_SPRITE : &1f51 = plot_byte_of_inverted_sprite &1fa1 6e 1f ; &04 : PLOT_MODE_PLOT_PIXEL_VALUE : &1f6e = plot_byte &1fa3 76 1f ; &06 : PLOT_MODE_UNPLOT_UNINVERTED_SPRITE : &1f76 = unplot_byte_of_uninverted_sprite &1fa5 82 1f ; &08 : PLOT_MODE_UNPLOT_INVERTED_SPRITE : &1f82 = unplot_byte_of_inverted_sprite &1fa7 92 1f ; &0a : PLOT_MODE_UNPLOT_PIXEL_VALUE : &1f92 = unplot_byte ; calculate_screen_address &1fa9 a9 00 LDA #&00 &1fab 85 16 STA &16 ; row_screen_address_high &1fad a5 22 LDA &22 ; bottom_row &1faf 49 ff EOR #&ff &1fb1 aa TAX &1fb2 29 07 AND #&07 &1fb4 85 23 STA &23 ; row_in_group &1fb6 8a TXA &1fb7 4a LSR A &1fb8 4a LSR A &1fb9 09 01 ORA #&01 &1fbb a8 TAY &1fbc a5 21 LDA &21 ; screen_x &1fbe 0a ASL A &1fbf 26 16 ROL &16 ; row_screen_address_high &1fc1 0a ASL A &1fc2 26 16 ROL &16 ; row_screen_address_high &1fc4 0a ASL A &1fc5 26 16 ROL &16 ; row_screen_address_high &1fc7 05 23 ORA &23 ; row_in_group &1fc9 71 e0 ADC (&e0),Y ; os_row_multiplication_table &1fcb aa TAX &1fcc 88 DEY &1fcd a5 16 LDA &16 ; row_screen_address_high &1fcf 71 e0 ADC (&e0),Y ; os_row_multiplication_table &1fd1 a8 TAY &1fd2 8a TXA &1fd3 65 0c ADC &0c ; screen_start_address_low &1fd5 aa TAX &1fd6 98 TYA &1fd7 65 0d ADC &0d ; screen_start_address_high &1fd9 24 21 BIT &21 ; screen_x &1fdb 10 02 BPL &1fdf ; x_not_negative &1fdd e9 07 SBC #&07 &1fdf a8 TAY ; x_not_negative &1fe0 10 06 BPL &1fe8 ; skip_wraparound ; wraparound &1fe2 38 SEC &1fe3 e9 50 SBC #&50 &1fe5 30 fb BMI &1fe2 ; wraparound &1fe7 a8 TAY ; skip_wraparound &1fe8 38 SEC &1fe9 8a TXA &1fea e5 18 SBC &18 ; height &1fec aa TAX &1fed b0 01 BCS &1ff0 ; y_not_negative &1fef 88 DEY ; y_not_negative &1ff0 86 19 STX &19 ; screen_address_low &1ff2 84 1a STY &1a ; screen_address_high &1ff4 86 15 STX &15 ; row_screen_address_low &1ff6 84 16 STY &16 ; row_screen_address_high &1ff8 60 RTS # &44eb - &4542 is moved to &01a4 - &01fb at &46df ; sound_0 # Tune ; chan vol pitch dur &01a4 13 00 01 00 00 00 ff 00 # Pitch is modified ; sound_1 # Yoyo hit something ; chan vol pitch dur &01ac 11 00 03 00 78 00 ff 00 ; sound_2 # Player changing position vertically ; chan vol pitch dur &01b4 12 00 02 00 00 00 ff 00 # Pitch is modified ; sound_3 # Collecting object ; chan vol pitch dur &01bc 11 00 04 00 5a 00 ff 00 ; plot_group_of_sprite_8 &01c4 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite ; plot_group_of_sprite_7 &01c7 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite ; plot_group_of_sprite_6 &01ca 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite ; plot_group_of_sprite_5 &01cd 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite ; plot_group_of_sprite_4 &01d0 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite ; plot_group_of_sprite_3 &01d3 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite ; plot_group_of_sprite_2 &01d6 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite ; plot_group_of_sprite_1 &01d9 20 ff ff JSR &ffff # Doesn't return if end of column # actually JSR plot_byte_of_sprite &01dc 38 SEC &01dd a5 19 LDA &19 ; screen_address_low &01df e9 78 SBC #&78 # Move up a group &01e1 85 19 STA &19 ; screen_address_low &01e3 a5 1a LDA &1a ; screen_address_high &01e5 e9 02 SBC #&02 &01e7 85 1a STA &1a ; screen_address_high &01e9 18 CLC &01ea 98 TYA &01eb 65 19 ADC &19 ; screen_address_low &01ed 8a TXA &01ee 65 1a ADC &1a ; screen_address_high &01f0 c9 30 CMP #&30 &01f2 b0 d0 BCS &01c4 ; plot_group_of_sprite_8 &01f4 a5 1a LDA &1a ; screen_address_high &01f6 69 50 ADC #&50 # Wrap around start of screen &01f8 85 1a STA &1a ; screen_address_high &01fa 90 c8 BCC &01c4 ; plot_group_of_sprite_8 # Always branches # &4543 - &4652 is moved to &0380 - &048f at &46e8 ; title_screen &0380 a2 01 LDX #&01 # Use level 1 &0382 a0 00 LDY #&00 # Use round 0 &0384 20 cd 14 JSR &14cd ; initialise_screen &0387 58 CLI &0388 20 21 0d JSR &0d21 ; write_string &038b 11 80 ; COLOUR 128 + 0 &038d 1f 10 03 ; TAB(&10, &03) &0390 54 68 65 20 43 61 73 74 ; "The Cast" &0398 1f 10 04 ; TAB(&10, &04) &039b 2d 2d 2d 2d 2d 2d 2d 2d ; "--------" &03a3 1f 1a 07 ; TAB(&1a, &07) &03a6 54 72 6f 67 67 ; "Trogg" &03ab 1f 13 09 ; TAB(&13, &09) &03ae 76 73 2e ; "vs." &03b1 1f 19 0d ; TAB(&19, &0d) &03b4 53 63 72 75 62 62 6c 79 ; "Scrubbly &03bc 1f 1a 11 ; TAB(&1a, &11) &03bf 48 6f 6f 74 65 72 ; "Hooter" &03c5 1f 1a 15 ; TAB(&1a, &15) &03c8 50 6f 67 6c 65 74 ; "Poglet" &03ce ea NOP &03cf a9 22 LDA #&22 ; SPRITE_FRAK &03d1 a2 22 LDX #&22 &03d3 a0 ea LDY #&ea &03d5 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &03d8 a9 35 LDA #&35 ; SPRITE_TROGG_RIGHT_HOLDING_TWO &03da a2 16 LDX #&16 &03dc a0 b7 LDY #&b7 &03de 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &03e1 a9 12 LDA #&12 ; SPRITE_SCRUBBLY &03e3 a2 15 LDX #&15 &03e5 a0 85 LDY #&85 &03e7 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &03ea a9 1d LDA #&1d ; SPRITE_HOOTER &03ec a2 15 LDX #&15 &03ee a0 6b LDY #&6b &03f0 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &03f3 a9 1e LDA #&1e ; SPRITE_POGLET &03f5 a2 16 LDX #&16 &03f7 a0 58 LDY #&58 &03f9 20 32 0b JSR &0b32 ; plot_sprite_A_at_X_Y &03fc 20 21 0d JSR &0d21 ; write_string &03ff 1c 00 1f 27 19 ; define text window x:(&00, &27), y:(&19, &1f) &0404 11 82 ; COLOUR 128 + 2 &0406 0c ; CLS &0407 1f 05 01 ; TAB(&05, &01) &040a 47 61 6d 65 20 63 6f 6e 63 65 70 74 73 20 62 79 ; "Game concepts by DCE,OMP & BOF" &041a 20 44 43 45 2c 4f 4d 50 20 26 20 42 4f 46 &0428 1f 01 03 ; TAB(&01, &03) &042b 50 72 6f 67 72 61 6d 6d 69 6e 67 20 62 65 79 6f ; "Programming beyond belief by *Orlando*" &043b 6e 64 20 62 65 6c 69 65 66 20 62 79 20 2a 4f 72 &044b 6c 61 6e 64 6f 2a &0451 1f 07 05 ; TAB(&07, &05) &0454 28 43 29 20 41 61 72 64 76 61 72 6b 20 53 6f 66 ; "(C) Aardvark Software 1984" &0464 74 77 61 72 65 20 31 39 38 34 &046e 19 04 00 00 e0 00 ; MOVE &0000, &00e0 &0474 19 01 00 05 00 00 ; DRAW +&0500, +&0000 &047a ea NOP &047b 20 81 04 JSR &0481 ; update_title_screen # Returns carry set if starting game &047e 4c 58 0b JMP &0b58 ; consider_starting_game ; update_title_screen &0481 ba TSX &0482 86 7e STX &7e ; stack_pointer_to_start_game &0484 a2 07 LDX #&07 ; update_title_screen_loop &0486 a9 00 LDA #&00 &0488 20 c7 1a JSR &1ac7 ; update_time_and_check_for_keypresses_for_Y_frames &048b ca DEX &048c d0 f8 BNE &0486 ; update_title_screen_loop &048e 18 CLC # Leave with carry clear to indicate not starting game &048f 60 RTS ; envelope_1 # Tune &4653 01 01 00 00 00 01 01 01 64 f6 fe fc 64 3c ; envelope_2 # Player changing position vertically &4661 02 01 00 00 00 01 01 01 64 9c 9c 9c 64 00 ; envelope_3 # Yoyo hit something &466f 03 82 00 02 fd 02 06 04 3c 07 f2 f2 3c 6e ; envelope_4 # Collecting object &467d 04 82 00 fc 02 03 03 28 28 fc fb fb 78 74 ; entry_point &468b 78 SEI &468c a2 a2 LDX #&a2 &468e 9a TXS &468f d8 CLD &4690 a9 8c LDA #&8c ; Select Tape FS &4692 a2 03 LDX #&03 ; 300 baud &4694 20 f4 ff JSR &fff4 ; OSBYTE &4697 a9 40 LDA #&40 ; RTI &4699 8d 00 0d STA &0d00 ; nmi_handler &469c a0 0f LDY #&0f &469e a9 00 LDA #&00 ; remove_roms_loop &46a0 99 a1 02 STA &02a1,Y ; os_paged_rom_type_table # Remove paged ROMs from ROM information table &46a3 88 DEY &46a4 10 fa BPL &46a0 ; remove_roms_loop &46a6 20 df 47 JSR &47df ; move_memory &46a9 00 30 00 0b f3 01 # Move &3000 - &31f2 to &0b00 - &0cf2 &46af 20 df 47 JSR &47df ; move_memory &46b2 f3 31 01 0d eb 14 # Move &31f3 - &46dd to &0d01 - &21eb &46b8 20 df 47 JSR &47df ; move_memory &46bb 2c 48 fd 1f 03 10 # Move &482c - &582e to &1ffd - &2fff &46c1 20 df 47 JSR &47df ; move_memory &46c4 2f 59 07 05 f8 02 # Move &592f - &5c26 to &0507 - &07fe &46ca 20 df 47 JSR &47df ; move_memory &46cd 27 5c 80 08 24 00 # Move &5c27 - &5c4a to &0880 - &08a3 &46d3 20 df 47 JSR &47df ; move_memory &46d6 2f 58 00 0a 00 01 # Move &582f - &592e to &0a00 - &0aff &46dc 20 df 47 JSR &47df ; move_memory &46df eb 44 a4 01 5c 00 # Move &44eb - &4546 to &01a4 - &01ff &46e5 20 df 47 JSR &47df ; move_memory &46e8 43 45 80 03 10 01 # Move &4543 - &4652 to &0380 - &048f &46ee a2 53 LDX #&53 ; &4653 = envelope_1 &46f0 a0 46 LDY #&46 &46f2 a9 08 LDA #&08 ; Define a sound envelope &46f4 20 03 0e JSR &0e03 ; safe_osword &46f7 a2 61 LDX #&61 ; &4661 = envelope_2 &46f9 a0 46 LDY #&46 &46fb a9 08 LDA #&08 ; Define a sound envelope &46fd 20 03 0e JSR &0e03 ; safe_osword &4700 a2 6f LDX #&6f ; &466f = envelope_3 &4702 a0 46 LDY #&46 &4704 a9 08 LDA #&08 ; Define a sound envelope &4706 20 03 0e JSR &0e03 ; safe_osword &4709 a2 7d LDX #&7d ; &467d = envelope_4 &470b a0 46 LDY #&46 &470d a9 08 LDA #&08 ; Define a sound envelope &470f 20 03 0e JSR &0e03 ; safe_osword &4712 a2 44 LDX #&44 ; &0d44 = event_handler &4714 a0 0d LDY #&0d &4716 8c 21 02 STY &0221 ; event_vector_high &4719 8e 20 02 STX &0220 ; event_vector_low &471c ac 29 02 LDY &0229 ; keyboard_vector_high &471f ae 28 02 LDX &0228 ; keyboard_vector_low &4722 84 4d STY &4d ; previous_keyboard_vector_high &4724 86 4c STX &4c ; previous_keyboard_vector_low &4726 a2 04 LDX #&04 ; v-sync event &4728 a9 0e LDA #&0e ; Enable event &472a 20 fb 0d JSR &0dfb ; safe_osbyte &472d ac 05 02 LDY &0205 ; irq1_vector_high &4730 ae 04 02 LDX &0204 ; irq1_vector_low &4733 84 4f STY &4f ; previous_irq1_vector_high &4735 86 4e STX &4e ; previous_irq1_vector_low &4737 a2 69 LDX #&69 ; &0d69 = irq1_handler &4739 a0 0d LDY #&0d &473b 8c 05 02 STY &0205 ; irq1_vector_high &473e 8e 04 02 STX &0204 ; irq1_vector_low &4741 a2 00 LDX #&00 &4743 86 4b STX &4b ; sound_muted &4745 86 70 STX &70 ; status_has_changed &4747 86 74 STX &74 ; level_is_inverted &4749 86 87 STX &87 ; previous_keyboard_or_joystick &474b 86 92 STX &92 ; game_is_paused &474d 86 93 STX &93 ; in_system_call # Set to positive to indicate not in system call &474f ca DEX ; &ff &4750 86 2f STX &2f ; suppress_tune # Set to negative to suppress tune &4752 86 86 STX &86 ; keyboard_or_joystick # Set to negative to indicate SPACE or fire not pressed &4754 20 27 0c JSR &0c27 ; stop_timer &4757 a2 fd LDX #&fd ; &1ffd = sprite_x_offsets_table &4759 a0 1f LDY #&1f &475b 84 01 STY &01 ; sprite_x_offsets_address_high &475d 86 00 STX &00 ; sprite_x_offsets_address_low &475f a2 59 LDX #&59 ; &2059 = sprite_y_offsets_table &4761 a0 20 LDY #&20 &4763 84 03 STY &03 ; sprite_y_offsets_address_high &4765 86 02 STX &02 ; sprite_y_offsets_address_low &4767 a2 b5 LDX #&b5 ; &20b5 = sprite_data_offsets_low_table &4769 a0 20 LDY #&20 &476b 84 05 STY &05 ; sprite_data_offsets_low_address_high &476d 86 04 STX &04 ; sprite_data_offsets_low_address_low &476f a2 11 LDX #&11 ; &2111 = sprite_data_offsets_high_table &4771 a0 21 LDY #&21 &4773 84 07 STY &07 ; sprite_data_offsets_high_address_high &4775 86 06 STX &06 ; sprite_data_offsets_high_address_low &4777 a2 6d LDX #&6d ; &216d = sprite_widths_table &4779 a0 21 LDY #&21 &477b 84 09 STY &09 ; sprite_widths_address_high &477d 86 08 STX &08 ; sprite_widths_address_low &477f a2 c9 LDX #&c9 ; &21c9 = sprite_heights_table &4781 a0 21 LDY #&21 &4783 84 0b STY &0b ; sprite_heights_address_high &4785 86 0a STX &0a ; sprite_heights_address_low &4787 a9 0a LDA #&0a ; &0a00 = mask_table &4789 85 81 STA &81 ; mask_table_address_high &478b a0 cf LDY #&cf &478d a2 20 LDX #&20 ; Enable CAPS LOCK, disable SHIFT LOCK &478f a9 ca LDA #&ca ; Read/Write Keyboard Status &4791 20 fb 0d JSR &0dfb ; safe_osbyte &4794 a0 00 LDY #&00 &4796 a2 08 LDX #&08 ; 8-bit &4798 a9 be LDA #&be ; Read/Write ADC type &479a 20 fb 0d JSR &0dfb ; safe_osbyte &479d a9 76 LDA #&76 ; Reflect keyboard status in LEDs &479f 20 fb 0d JSR &0dfb ; safe_osbyte &47a2 a2 28 LDX #&28 ; 40 # First flash colour is twice as long as second &47a4 a9 09 LDA #&09 ; Set first flash colour duration &47a6 20 fb 0d JSR &0dfb ; safe_osbyte &47a9 a2 14 LDX #&14 ; 20 &47ab a9 0a LDA #&0a ; Set second flash colour duration &47ad 20 fb 0d JSR &0dfb ; safe_osbyte &47b0 a9 e0 LDA #&e0 # Enable interrupts for User VIA timers 1 and 2 &47b2 8d 6e fe STA &fe6e ; User VIA interrupt enable register &47b5 a9 40 LDA #&40 # Set User VIA timer 1 to continuous &47b7 8d 6b fe STA &fe6b ; User VIA auxiliary control register &47ba a0 00 LDY #&00 &47bc a2 8b LDX #&8b ; tune_start_positions ; set_tune_start_positions_loop &47be 94 00 STY &00,X ; tune_start_positions - &8b ; find_tune_start_position_loop &47c0 c8 INY &47c1 b9 06 05 LDA &0506,Y ; tune_data - 1 &47c4 10 fa BPL &47c0 ; find_tune_start_position_loop &47c6 e8 INX &47c7 e0 8f CPX #&8f ; tune_start_positions + 4 &47c9 90 f3 BCC &47be ; set_tune_start_positions_loop &47cb 94 00 STY &00,X ; tune_start_positions - &8b &47cd a2 f4 LDX #&f4 ; &0df4 = keyboard_handler &47cf a0 0d LDY #&0d &47d1 8c 29 02 STY &0229 ; keyboard_vector_high &47d4 8e 28 02 STX &0228 ; keyboard_vector_low &47d7 a9 01 LDA #&01 # Enable interrupts for System VIA CA2 (key presses) &47d9 8d 4e fe STA &fe4e ; System VIA interrupt enable register &47dc 4c 80 03 JMP &0380 ; title_screen ; move_memory &47df 68 PLA # Parameters follow function call &47e0 85 29 STA &29 ; parameters_address_low &47e2 68 PLA &47e3 85 2a STA &2a ; parameters_address_high &47e5 a0 01 LDY #&01 &47e7 b1 29 LDA (&29),Y ; parameters_address &47e9 85 3f STA &3f ; source_address_low &47eb c8 INY &47ec b1 29 LDA (&29),Y ; parameters_address &47ee 85 40 STA &40 ; source_address_high &47f0 c8 INY &47f1 b1 29 LDA (&29),Y ; parameters_address &47f3 85 41 STA &41 ; target_address_low &47f5 c8 INY &47f6 b1 29 LDA (&29),Y ; parameters_address &47f8 85 42 STA &42 ; target_address_high &47fa c8 INY &47fb b1 29 LDA (&29),Y ; parameters_address &47fd aa TAX &47fe c8 INY &47ff b1 29 LDA (&29),Y ; parameters_address &4801 85 26 STA &26 ; count_high &4803 a0 00 LDY #&00 ; move_memory_loop &4805 b1 3f LDA (&3f),Y ; source_address &4807 91 41 STA (&41),Y ; target_address &4809 8a TXA &480a d0 02 BNE &480e ; skip_underflow &480c c6 26 DEC &26 ; count_high ; skip_underflow &480e ca DEX &480f 8a TXA &4810 05 26 ORA &26 ; count_high &4812 f0 0a BEQ &481e ; finished_moving_memory &4814 c8 INY &4815 d0 ee BNE &4805 ; move_memory_loop &4817 e6 40 INC &40 ; source_address_high &4819 e6 42 INC &42 ; target_address_high &481b 4c 05 48 JMP &4805 ; move_memory_loop ; finished_moving_memory &481e 18 CLC &481f a5 29 LDA &29 ; parameters_address_low &4821 69 06 ADC #&06 &4823 aa TAX &4824 a5 2a LDA &2a ; parameters_address_high &4826 69 00 ADC #&00 &4828 48 PHA # Return to code after end of parameters &4829 8a TXA &482a 48 PHA &482b 60 RTS # &482c - &582e is moved to &1ffd - &2fff at &46bb ; sprite_x_offsets_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &1ffd 00 01 01 01 00 01 02 01 01 ff 00 ff 01 00 00 00 ; &00 &200d 00 00 fd fe fe 00 ff fe 00 00 00 00 00 ff fd 00 ; &10 &201d 00 00 00 00 ff ff ff 00 00 00 00 00 00 00 00 00 ; &20 &202d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &30 &203d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &40 &204d 00 00 00 00 00 00 00 00 00 00 00 00 ; &50 ; sprite_y_offsets_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &2059 00 00 00 00 00 00 00 00 00 00 00 01 02 00 00 00 ; &00 &2069 00 f3 00 00 00 f3 00 00 f5 f5 f5 f2 f5 00 ef 00 ; &10 &2079 00 00 00 00 00 fb fb 00 00 00 00 00 00 00 00 00 ; &20 &2089 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &30 &2099 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &40 &20a9 00 00 00 00 00 00 00 00 00 00 00 00 ; &50 ; sprite_data_offsets_low_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &20b5 28 5c 93 ca fc 3b 72 a3 e5 27 f7 c7 84 25 31 25 ; &00 &20c5 31 3d 73 e8 b1 7d a7 bf fb 07 13 36 63 87 fa c6 ; &10 &20d5 d2 ee 0a 00 2d 56 56 77 ff ff ff ff ff ff ff ff ; &20 &20e5 ff ff ff ff 95 9b a1 a7 ad b3 b9 bf c5 cb d1 d7 ; &30 &20f5 dd e3 e9 ef f5 0a 25 40 67 73 7c 85 91 a0 b2 b8 ; &40 &2105 be c4 ca d0 d6 dc e2 e8 ee f4 fa 00 ; &50 ; sprite_data_offsets_high_table ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &2111 02 02 02 02 02 03 03 03 03 04 04 05 06 07 07 07 ; &00 &2121 07 07 07 08 09 0a 0a 0a 0a 0b 0b 0b 0b 0b 0b 0c ; &10 &2131 0c 0c 0d 0e 0e 0e 0e 0e ff ff ff ff ff ff ff ff ; &20 &2141 ff ff ff ff 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e ; &30 &2151 0e 0e 0e 0e 0e 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ; &40 &2161 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 10 ; &50 ; sprite_widths_table # Lowest seven bits are width of sprite in bytes ; 0 1 2 3 4 5 6 7 8 9 a b c d e f # or zero if sprite is composed of subsprites &216d 02 04 04 04 05 04 04 05 05 07 07 07 06 02 02 82 ; &00 # Top bit set if sprite is inverted &217d 82 04 09 05 05 03 03 06 01 01 03 03 03 05 06 02 ; &10 &218d 02 02 0d 03 03 03 83 03 02 04 06 08 0a 0c 0e 10 ; &20 &219d 12 14 16 18 00 00 00 00 00 00 00 00 00 00 00 00 ; &30 &21ad 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; &40 &21bd 00 00 00 00 00 00 00 00 00 00 00 00 ; &50 ; sprite_heights_table # Height of sprite in rows or number of subsprites ; 0 1 2 3 4 5 6 7 8 9 a b c d e f &21c9 1a 0b 0b 0b 0b 0b 0b 0b 0b 1a 1a 18 17 06 06 06 ; &00 &21d9 06 0e 2a 22 22 0e 09 0a 0c 0c 0c 0f 0c 17 22 06 ; &10 &21e9 0e 0e 13 0f 0e 0b 0b 0a 01 01 01 01 01 01 01 01 ; &20 &21f9 01 01 01 01 02 02 02 02 02 02 02 02 02 02 02 02 ; &30 &2209 02 02 02 02 07 09 09 0d 04 03 03 04 05 06 02 02 ; &40 &2219 02 02 02 02 02 02 02 02 02 02 02 01 ; &50 ; sprite_00 (SPRITE_ROPE_ONE) &2225 f9 f9 f9 f9 f9 f9 f8 74 74 f8 f9 f9 f9 f9 f8 74 &2235 74 74 74 74 f8 f9 f9 f9 f9 f9 00 00 00 00 00 00 &2245 88 88 88 88 00 00 00 00 88 88 88 88 88 88 88 00 &2255 00 00 00 00 ; sprite_01 (SPRITE_FEET_RIGHT) &2259 11 11 00 00 00 00 11 11 33 23 33 ff 8f cf 67 df &2269 8f 9f 1f 3f 0f ff ff 3f 1f 1f 0f 8f 8f cf cf 8f &2279 ff 00 00 00 88 88 88 88 bb df 1f ff 00 00 00 00 &2289 00 00 00 00 00 00 00 ; sprite_02 (SPRITE_FEET_RIGHT_TWO) &2290 11 00 00 11 33 67 47 47 67 33 00 ff 8f 8f 8f 8f &22a0 4f 4f cf 4f 8f ff ff 2e 2e 2e 6e 4c cc ff df 1f &22b0 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &22c0 00 00 00 00 00 00 00 ; sprite_03 (SPRITE_FEET_RIGHT_THREE) &22c7 11 00 00 11 33 77 47 47 67 23 33 ff 8f 8f 8f 0f &22d7 1f 3f 7f 7f 1f ff ff 2e 2e 7f 9f 1f 1f 9f 8f cf &22e7 77 00 00 00 00 00 00 ee ae 2e ee cc 00 00 00 00 &22f7 00 00 ; sprite_04 (SPRITE_FEET_RIGHT_FOUR) &22f9 00 00 00 00 00 11 11 11 11 00 00 11 00 11 11 77 &2309 cf 0f 1f 9f 8f ff ff 8f 8f 0f 1f 2f 6f ef ef cf &2319 ff ff 2e 6e ae 2e 2e 6e 7f 6f 0f ff 00 00 00 00 &2329 00 00 00 88 88 88 88 00 00 00 00 00 00 00 00 ; sprite_05 (SPRITE_FEET_LEFT) &2338 00 00 00 11 11 11 11 dd bf 8f ff ff cf 8f 8f 0f &2348 1f 1f 3f 3f 1f ff ff 1f 3f 6e bf 1f 9f 8f cf 0f &2358 ff cc 88 00 00 00 00 88 88 cc 4c cc 00 00 00 00 &2368 00 00 00 00 00 00 00 ; sprite_06 (SPRITE_FEET_LEFT_TWO) &236f ff 47 47 47 67 23 33 ff bf 8f ff ff 1f 1f 1f 1f &237f 2f 2f 3f 2f 1f ff 88 00 00 88 cc 6e 2e 2e 6e cc &238f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &239f 00 ; sprite_07 (SPRITE_FEET_LEFT_THREE) &23a0 00 00 00 00 00 00 77 57 47 77 33 ff 47 47 ef 9f &23b0 8f 8f 9f 1f 3f ee ff 1f 1f 1f 0f 8f cf ef ef 8f &23c0 ff 88 00 00 88 cc ee 2e 2e 6e 4c cc 00 00 00 00 &23d0 00 00 00 00 00 00 00 33 23 67 47 cf 0f 3f 6e 7f &23e0 3f ff ; sprite_08 (SPRITE_FEET_LEFT_FOUR) &23e2 00 00 00 00 00 00 00 11 11 11 11 ff 47 67 57 47 &23f2 47 67 ef 6f 0f ff ff 1f 1f 0f 8f 4f 6f 7f 7f 3f &2402 ff 88 00 88 88 ee 3f 0f 8f 9f 1f ff 00 00 00 00 &2412 00 88 88 88 88 00 00 33 23 67 47 cf 0f 3f 6e 7f &2422 3f ff ; sprite_09 (SPRITE_BODY_LEFT_HOLDING) &2424 00 00 00 33 23 33 00 00 00 00 00 00 00 00 00 00 &2434 00 00 00 00 00 00 00 00 00 00 00 11 23 ef 0f ff &2444 33 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &2454 00 00 00 00 ff ff d3 e9 e9 0f df 3f ff 77 67 67 &2464 ef fb fb ff cf cf ff fc 76 33 11 00 00 00 88 ee &2474 ff ff ff ff bf 8f 0f 2f 2f 3f 1f 8f ff ff 6f 0f &2484 ff f0 f0 f0 f8 00 00 00 00 00 88 cc ff ff ff 3f &2494 1f 0f 0f 0f 8f cf ff cf 0f 0f ff f0 f0 f0 f1 00 &24a4 00 00 00 00 00 00 00 88 00 88 ee ff df 6f 6f 3f &24b4 1f 1f 1f 3f ff f1 f3 f6 ff 77 77 33 00 00 00 00 &24c4 00 00 00 00 00 00 88 88 88 cc 4c 4c 4c 6e 3f 1f &24d4 df f3 fd ff ff ee 11 33 67 df 67 33 11 00 00 00 &24e4 00 00 00 00 00 00 4c f4 ff 85 20 a9 80 24 20 d0 ; sprite_0a (SPRITE_BODY_RIGHT_HOLDING) &24f4 00 00 00 00 00 00 00 00 00 00 11 11 11 33 23 23 &2504 23 67 cf 8f bf fc fb ff ff 77 00 00 00 00 00 11 &2514 00 11 77 cf 8f 0f 1f 1f 3f 2f 7f 7c fc 7c fe f7 &2524 ff ee ee cc 00 00 11 33 ff ff ff df 0f 0f 0f 3f &2534 ef 0f 0f 1f ff f0 f0 f0 f0 f0 f8 00 00 00 11 77 &2544 ff ff ff ff df e7 fb f9 fd fd fc fc f8 f8 f0 f0 &2554 f0 f0 f0 f0 f1 00 00 00 ff ff bc 79 79 0f bf cf &2564 7f 2e 3f 9f 9f df d7 f7 f3 f1 f1 f1 f3 e6 cc 00 &2574 00 00 00 88 4c 7f 0f ff cc 88 00 00 00 00 00 00 &2584 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 cc &2594 4c cc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &25a4 00 00 00 00 00 00 11 33 67 df 67 33 11 00 00 00 &25b4 00 00 00 00 00 00 4c f4 ff 85 20 a9 80 24 20 d0 ; sprite_0b (SPRITE_BODY_LEFT_RELEASED) &25c4 00 00 00 77 47 77 00 00 00 00 00 00 00 00 00 00 &25d4 00 11 11 11 77 47 77 00 11 33 56 df 1f ef 77 23 &25e4 11 00 11 11 11 11 11 11 33 ff 7f 9f 3f 6e cc 00 &25f4 ff ff b7 d3 d3 1f bf 6f cf 8f 8f cf c7 c7 e7 e3 &2604 f3 f0 f0 f8 fc 76 33 00 00 cc ff ff ff ff 7f 0f &2614 0f 0f 0f cf bf 1f 0f 0f ff f0 f0 f0 f0 f0 f8 00 &2624 00 00 00 88 ee ff ee ff 7f 1f 0f 0f 0f cf 7f 1f &2634 ff f0 f0 f0 f0 f0 f1 00 00 00 00 00 00 00 00 00 &2644 00 88 ee 3f 1f 1f 0f 8f 8f 8f cf cf cf 8f cf 77 &2654 00 00 00 00 00 00 00 00 00 00 00 00 00 88 88 88 &2664 88 88 88 88 88 88 88 88 00 00 00 00 00 00 00 00 &2674 00 00 00 00 00 00 11 33 67 57 67 33 11 ; sprite_0c (SPRITE_BODY_RIGHT_RELEASED) &2681 00 00 00 00 00 00 00 00 11 33 77 df 9f bf af af &2691 bf fe 76 32 32 33 11 00 00 00 11 77 ff 77 ef cf &26a1 8f 8f 0f 0f 3f 5f 0f ff f0 f0 f0 f0 f0 f8 00 33 &26b1 ff ff ff ff ef fb 7d 7e 3f 1f 0f 0f 8f cf ef f3 &26c1 f1 f0 f0 f0 f1 ff ff de bc bc 8f df 6f bf 9f 9f &26d1 cf cf 6f 6f 3f 1f 0f cf f7 f3 ee 88 88 cc a6 bf &26e1 8f 7f ee 4c 88 00 88 88 88 88 88 88 cc ff 6f 1f &26f1 cf 67 33 00 00 00 ee 2e ee 00 00 00 00 00 00 00 &2701 00 00 00 00 88 88 88 ee 2e ee 00 00 00 00 00 00 &2711 00 00 00 00 00 00 00 00 00 00 00 22 33 31 31 33 &2721 22 ; sprite_0d (SPRITE_YOYO_RIGHT) ; sprite_0f (SPRITE_YOYO_RIGHT_INVERTED) &2722 77 fc ff ff ff 77 cc e6 e2 ea ee cc ; sprite_0e (SPRITE_YOYO_LEFT) ; sprite_10 (SPRITE_YOYO_LEFT_INVERTED) &272e 77 fc f9 fb ff 77 cc e6 ee ee ee cc ; sprite_11 (SPRITE_PLATFORM_ONE) &273a 66 bf 0f 0f 0f ff fb 76 33 11 11 00 00 00 ff 8f &274a 0f 0f ff fb f4 fb fa f5 fa fd f9 ea 44 bf 0f 0f &275a 3f fe fd f2 fd f2 fd f2 fd f9 dd 2f 0f 0f ef fb &276a f5 ea c4 cc 88 88 ; sprite_12 (SPRITE_SCRUBBLY) &2770 00 00 00 00 00 00 00 00 00 00 00 00 11 33 00 00 &2780 11 33 77 67 cf df bf ff 99 99 11 33 67 67 cf df &2790 ff dd 99 88 44 00 00 00 00 00 00 00 00 11 11 11 &27a0 00 00 00 33 77 ef ff 33 67 cf 8f 8f 0f 0f 0f 0f &27b0 0f 0f 0f 1f 1f 0f 0f 0f 0f 0f 0f 8f 8f 8f cf 77 &27c0 33 32 33 11 00 77 cf 9f 6e 88 00 33 ef cf 0f 0f &27d0 8f 0f 0f 3f 7e fc f8 f9 f9 fd 7f 0f 0f 7f f8 f8 &27e0 f8 fd 7d 7d 7f 2f 2f 0f 0f 0f ff f3 f0 ff 77 ef &27f0 3f 8f ef 67 ef 8f 0f 0f 0f 0f 0f 0f 0f ef f3 f1 &2800 fd ff ff ef cf 0f 0f 5f ef 8f 8f 8f 0f 0f 0f 0f &2810 0f 0f 0f 0f 0f ff cc 88 dd 7f 6f 0f 1f 3f 3f 0f &2820 0f 0f 0f 0f 0f 0f 0f 3f 7e 7c 7d 7f 7f 3f 1f 0f &2830 0f 5f bf 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ff &2840 11 00 ff 8f 2f ff 99 00 88 ee 3f 1f 0f 0f 0f 0f &2850 0f ef f3 f1 f8 fc fc fd ff 0f 0f 7f f8 f8 f8 fd &2860 7d 7d 7f 2f 2f 0f 0f 0f 7f fe f8 ff 88 cc 4c 4c &2870 cc 00 00 00 88 ee 7f 3f ff 6e 3f 1f 0f 8f 8f 8f &2880 8f 8f 0f 0f 0f 4f cf 8f 8f 8f 0f 0f 0f 0f 0f 0f &2890 1f 3f ee e2 e6 cc 00 00 00 00 00 00 00 00 00 00 &28a0 00 88 cc 66 00 88 cc ee 7f 3f 1f 5f 6f 7f 4c 4c &28b0 4c 6e 3f 3f 1f 5f 7f dd cc 88 99 00 00 00 00 00 &28c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &28d0 00 00 00 00 88 88 88 88 88 88 00 00 00 00 88 88 &28e0 88 88 88 88 00 ; sprite_13 (SPRITE_TROGG_CLIMBING) &28e5 00 00 00 00 00 33 67 cf bf 8f cf 67 33 11 11 11 &28f5 11 11 11 11 11 11 00 00 00 00 00 00 00 00 00 00 &2905 00 00 11 33 33 77 77 ff ff ff ff 7f 0f 0f 0f 8f &2915 0f 0f 3f fe f0 f0 f0 f8 fc ff 8f 8f cf cf 47 47 &2925 47 67 47 77 ff ff ff ff ff ff ff ff ff ff 1f 3f &2935 3e 7e 7c fc f8 f0 f0 f0 f0 f1 f3 ff 5d 5d cc 4c &2945 4c 5d dd 5d 4c cc 88 cc cc ff ef ef ff ff fd f9 &2955 f3 e3 e3 e3 f3 f1 f0 f0 f0 f0 f0 ff 0f 0f 1f bf &2965 9f df bf 9f 3f ee 00 00 00 00 00 88 cc 4c 6e ee &2975 bf 1f 3f ee cc 4c 4c cc c4 c4 c4 c4 cc 88 88 88 &2985 88 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &2995 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &29a5 00 00 00 00 00 00 00 00 00 ; sprite_14 (SPRITE_TROGG_CLIMBING_TWO) &29ae 00 00 00 11 33 23 67 77 cf 8f cf 77 33 33 23 33 &29be 32 32 32 32 33 11 11 11 11 00 00 00 00 00 00 00 &29ce 00 00 11 33 33 ff 7f 7f ff ff 1f 0f 0f 0f 0f 0f &29de 7f fc f0 f0 f0 f0 f0 ff 0f 0f 8f df 9f bf df 9f &29ee cf 77 00 00 ff ff ff ff ff ff ff ff ff ff 3f 3e &29fe 7e fc f8 f0 f0 f0 f0 f0 f0 f8 fc ff ab ab 23 33 &2a0e 23 ab bb ab 23 33 88 cc cc ee ee ff ff ff fb f3 &2a1e e3 e7 c7 d7 c7 e7 f3 f1 f0 f0 f0 f1 f3 ff 1f 1f &2a2e 1f 3f 2e 2e 2e ee 2e ee 00 00 00 00 00 cc 6e 3f &2a3e df 1f 3f 6e cc 88 88 88 88 88 88 88 88 88 00 00 &2a4e 00 00 00 00 00 00 00 00 00 00 01 77 00 00 00 00 &2a5e 01 77 00 00 00 00 00 00 00 00 00 00 11 33 67 df &2a6e 67 33 11 00 00 00 00 00 00 00 00 00 ; sprite_15 (SPRITE_GIRDER_ONE) &2a7a ff f8 fb fd 76 33 11 11 33 76 fd fb f8 ff ff f0 &2a8a ff 99 ff f6 f9 f9 f6 ff 99 ff f0 ff ff f1 fd fb &2a9a e6 cc 88 88 cc e6 fb fd f1 ff ; sprite_16 (SPRITE_GEM) &2aa4 33 76 fd fc 76 33 11 00 00 ff f0 ff f0 f0 f1 fb &2ab4 ee 44 88 cc e6 e6 cc 88 ; sprite_17 (SPRITE_KEY) &2abc 00 00 00 ff f8 ff 74 74 75 66 00 00 00 ff f0 ff &2acc e2 e2 ea 66 00 00 00 ff f0 ff 00 00 00 00 00 11 &2adc 33 fe f0 fe 33 11 00 00 ff f9 f0 f3 f3 f3 f0 f9 &2aec ff 00 00 88 cc c4 c4 c4 cc 88 00 00 ; sprite_18 (SPRITE_LOG_LEFT) &2af8 77 67 af bf af bf af af bf af 67 77 ; sprite_19 (SPRITE_LOG_RIGHT) &2b04 ee 2e 7f 9f 3f df 1f 1f ff 3f 2e ee ; sprite_1a (SPRITE_LOG_MIDDLE) &2b10 ff 0f 3f cf 0f ff 0f 0f ff 0f 0f ff ff 0f cf 3f &2b20 0f 8f 7f 0f cf 3f 0f ff ff 0f 0f ff 0f ff 0f 0f &2b30 3f cf 0f ; sprite_1b (SPRITE_LOG_MIDDLE_WITH_BRANCH) &2b33 ff 0f 0f ff 0f 9f 6f 0f ff 0f 0f ff 11 00 00 ff &2b43 0f ff 0f 3f cf 0f 7f 8f 3f 1f 1f cf 77 11 ff 0f &2b53 ef 1f cf 3f 0f ef 1f cf 77 99 cc 4c cc ; sprite_1c (SPRITE_LOG_MIDDLE_WITH_KNOT) &2b60 ff 0f 1f ef 0f 8f 6f 1f cf 3f 0f ff ff 0f ff 0f &2b70 ff ff 0f ff 0f ff 0f ff ff 0f 8f 7f 0f 3f 4f 8f &2b80 3f cf 0f ff ; sprite_1d (SPRITE_HOOTER) &2b84 77 dd cc 00 11 11 33 67 47 cf 9f 9f 9f af ef 23 &2b94 23 33 11 00 33 cf ff 00 77 fc fb fb fc 7f 0f 9f &2ba4 9f af 3f 2f 3f 1f 0f 0f 0f 8f ff 1f 8f ff 00 bb &2bb4 fe bf bf fe bf af 1f 1f ef 1f 0f 1f ff 0f 0f 0f &2bc4 0f ff 11 ab bb 11 dd e6 ea fb f7 df 0f 2f 2f bf &2bd4 9f 9f 8f 0f 0f 0f 1f 3f ee 1f 2f ff cc 66 66 00 &2be4 00 00 88 88 cc 4c 6e 2e 2e ae ee 88 88 88 00 00 &2bf4 88 6e ee ; sprite_1e (SPRITE_POGLET) &2bf7 00 00 00 00 00 00 00 00 00 00 11 11 33 32 32 32 &2c07 32 32 33 11 11 11 00 00 00 77 fc f9 f9 fd 75 ef &2c17 8f ff 00 00 00 11 33 32 76 74 ff cf cf c7 c7 e7 &2c27 f7 c4 c4 c4 e6 e2 f3 f9 ff 23 ef eb e3 ff 11 bb &2c37 ef cf ef bb 00 33 ef cf f3 e6 cc 88 88 88 7f 7c &2c47 7e fb fb f9 fb eb fb 74 23 ef 0f 0f 0f 0f 0f 0f &2c57 8f ff 6e 3f 3e ff 00 ff 1f 1f ff 00 00 00 11 33 &2c67 ef e3 e7 fd fd f9 fd 7d fd e2 4c 7f 0f 0f 1f 1f &2c77 1f 1f 1f ff 77 fc f1 ff 00 00 00 00 00 00 00 00 &2c87 ee 2e 2e 2e 2e 6e 88 00 00 00 00 00 00 88 cc ea &2c97 ea f3 f2 f3 f3 f3 f3 e7 ef 33 00 00 00 00 00 00 &2ca7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 &2cb7 00 00 00 cc e6 e2 e2 e6 c4 ee 2e ee ; sprite_1f (SPRITE_CHAIN_BOTTOM) &2cc3 ea ea fb f9 fc 77 75 75 fd f9 f3 ee ; sprite_20 (SPRITE_CHAIN_MIDDLE) &2ccf ea fb eb f9 fc ff ae ae ff fc f9 eb fb ea 75 fd &2cdf 3f 9f d7 df 57 57 df d7 9f 3f fd 75 ; sprite_21 (SPRITE_CHAIN_TOP) &2ceb ff f8 fc 77 23 23 33 dd bf fc f9 eb fb ea ff f1 &2cfb f3 ee 4c 6e 3f 9f 9f 9f 3f 7d fd 75 ; sprite_22 (SPRITE_FRAK) &2d07 00 33 76 fc f8 f8 f8 f8 f8 f8 f8 fc 76 33 00 00 &2d17 00 00 33 ff f8 f0 f3 f3 f3 f3 f3 f3 f3 f3 f3 f0 &2d27 f8 ff 33 76 fc ff ff f0 f0 ff ff f0 f0 fe fe f0 &2d37 f0 f0 f0 f0 f0 f1 f3 ee 88 ff f0 f0 fb fb f3 f3 &2d47 f3 f3 f3 f3 f3 f0 f0 ff 88 00 00 00 ff f0 f0 ff &2d57 ff f1 f1 ff fe f7 f3 f1 f0 f0 ff 00 00 00 00 ff &2d67 f0 f0 f0 f9 f9 f9 f1 f1 f1 f9 f9 f0 f0 ff 00 00 &2d77 00 00 ff f0 f0 ff ff f8 f8 ff ff f8 f8 f8 f0 f0 &2d87 ff 00 00 00 00 ff f0 f0 f8 fc fc fc fc fc fc fc &2d97 fc f0 f0 ff 00 00 00 00 ff f0 f0 fc fc fd ff ff &2da7 ff fd fc fc f0 f0 ff 00 00 00 00 ff f0 f0 f6 fe &2db7 fc f8 f0 f8 fc fe f6 f0 f0 ff 00 00 00 00 ff f0 &2dc7 f0 f3 f3 f3 f3 f3 f3 f0 f3 f3 f0 f0 ff 00 00 00 &2dd7 00 cc f7 f1 f0 f0 f0 f0 f0 f0 f0 f0 f0 f1 f7 cc &2de7 00 00 00 00 00 00 88 cc c4 c4 c4 c4 c4 c4 c4 cc &2df7 88 00 00 00 00 00 ; sprite_23 (SPRITE_BULB) &2dfd 00 11 00 00 00 11 11 33 76 74 74 74 76 33 11 ff &2e0d ff ff ff f9 f9 f0 f0 f0 f0 f0 f0 f0 f0 ff 00 88 &2e1d 00 00 00 88 88 cc e6 e2 e2 e2 e6 cc 88 ; sprite_24 (SPRITE_LADDER) &2e2a 00 00 ff f8 ff 00 00 00 00 ff f8 ff 00 00 f9 f9 &2e3a f9 ff f9 f9 f9 f9 f9 f9 ff f9 f9 f9 00 00 ff f1 &2e4a ff 00 00 00 00 ff f1 ff 00 ; sprite_25 (SPRITE_DAGGER) ; sprite_26 (SPRITE_DAGGER_INVERTED) &2e53 00 11 00 00 00 11 11 32 75 66 88 00 88 dd 77 fb &2e63 f1 e2 cc 00 00 00 88 cc ee 88 00 88 cc 44 00 00 &2e73 00 ; sprite_27 (SPRITE_BALLOON) &2e74 11 67 8f 8f 8f 8f 8f 67 11 00 ff 0f 3c 1e 0f 0f &2e84 0f 0f ff 66 88 6e 1f 97 97 1f 1f 6e 88 00 ; sprite_34 (SPRITE_TROGG_RIGHT_HOLDING) &2e92 0a fd 08 ; SPRITE_BODY_RIGHT_HOLDING &2e95 01 fd 00 ; SPRITE_FEET_RIGHT ; sprite_35 (SPRITE_TROGG_RIGHT_HOLDING_TWO) &2e98 0a fd 08 ; SPRITE_BODY_RIGHT_HOLDING &2e9b 02 fd 00 ; SPRITE_FEET_RIGHT_TWO ; sprite_36 (SPRITE_TROGG_RIGHT_HOLDING_THREE) &2e9e 0a fd 08 ; SPRITE_BODY_RIGHT_HOLDING &2ea1 03 fd 00 ; SPRITE_FEET_RIGHT_THREE ; sprite_37 (SPRITE_TROGG_RIGHT_HOLDING_FOUR) &2ea4 0a fd 08 ; SPRITE_BODY_RIGHT_HOLDING &2ea7 04 fd 00 ; SPRITE_FEET_RIGHT_FOUR ; sprite_38 (SPRITE_TROGG_LEFT_HOLDING) &2eaa 09 fd 08 ; SPRITE_BODY_LEFT_HOLDING &2ead 05 fd 00 ; SPRITE_FEET_LEFT ; sprite_39 (SPRITE_TROGG_LEFT_HOLDING_TWO) &2eb0 09 fd 08 ; SPRITE_BODY_LEFT_HOLDING &2eb3 06 fd 00 ; SPRITE_FEET_LEFT_TWO ; sprite_3a (SPRITE_TROGG_LEFT_HOLDING_THREE) &2eb6 09 fd 08 ; SPRITE_BODY_LEFT_HOLDING &2eb9 07 fd 00 ; SPRITE_FEET_LEFT_THREE ; sprite_3b (SPRITE_TROGG_LEFT_HOLDING_FOUR) &2ebc 09 fd 08 ; SPRITE_BODY_LEFT_HOLDING &2ebf 08 fd 00 ; SPRITE_FEET_LEFT_FOUR ; sprite_3c (SPRITE_TROGG_RIGHT_RELEASED) &2ec2 0c fd 09 ; SPRITE_BODY_RIGHT_RELEASED &2ec5 04 fd 00 ; SPRITE_FEET_RIGHT_FOUR ; sprite_3d (SPRITE_TROGG_LEFT_RELEASED) &2ec8 0b fd 09 ; SPRITE_BODY_LEFT_RELEASED &2ecb 08 fd 00 ; SPRITE_FEET_LEFT_FOUR ; sprite_3e (SPRITE_GIRDER_TWO) &2ece 15 00 00 ; SPRITE_GIRDER_ONE &2ed1 15 03 00 ; SPRITE_GIRDER_ONE ; sprite_3f (SPRITE_GIRDER_THREE) &2ed4 15 00 00 ; SPRITE_GIRDER_ONE &2ed7 3e 03 00 ; SPRITE_GIRDER_TWO ; sprite_40 (SPRITE_GIRDER_FOUR) &2eda 15 00 00 ; SPRITE_GIRDER_ONE &2edd 3f 03 00 ; SPRITE_GIRDER_THREE ; sprite_41 (SPRITE_GIRDER_FIVE) &2ee0 15 00 00 ; SPRITE_GIRDER_ONE &2ee3 40 03 00 ; SPRITE_GIRDER_FOUR ; sprite_42 (SPRITE_GIRDER_SIX) &2ee6 15 00 00 ; SPRITE_GIRDER_ONE &2ee9 41 03 00 ; SPRITE_GIRDER_FIVE ; sprite_43 (SPRITE_GIRDER_SEVEN) &2eec 15 00 00 ; SPRITE_GIRDER_ONE &2eef 42 03 00 ; SPRITE_GIRDER_SIX ; sprite_44 (SPRITE_LOG_FIVE) &2ef2 18 00 00 ; SPRITE_LOG_LEFT &2ef5 1a 01 00 ; SPRITE_LOG_MIDDLE &2ef8 1b 04 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2efb 1c 07 00 ; SPRITE_LOG_MIDDLE_WITH_KNOT &2efe 1b 0a 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f01 1c 0d 00 ; SPRITE_LOG_MIDDLE_WITH_KNOT &2f04 19 10 00 ; SPRITE_LOG_RIGHT ; sprite_45 (SPRITE_LOG_SEVEN) &2f07 18 00 00 ; SPRITE_LOG_LEFT &2f0a 1a 01 00 ; SPRITE_LOG_MIDDLE &2f0d 1a 04 00 ; SPRITE_LOG_MIDDLE &2f10 1b 07 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f13 1b 0a 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f16 1c 0d 00 ; SPRITE_LOG_MIDDLE_WITH_KNOT &2f19 1b 10 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f1c 1a 13 00 ; SPRITE_LOG_MIDDLE &2f1f 19 16 00 ; SPRITE_LOG_RIGHT ; sprite_46 (SPRITE_LOG_SEVEN_TWO) &2f22 18 00 00 ; SPRITE_LOG_LEFT &2f25 1b 01 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f28 1c 04 00 ; SPRITE_LOG_MIDDLE_WITH_KNOT &2f2b 1c 07 00 ; SPRITE_LOG_MIDDLE_WITH_KNOT &2f2e 1a 0a 00 ; SPRITE_LOG_MIDDLE &2f31 1b 0d 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f34 1a 10 00 ; SPRITE_LOG_MIDDLE &2f37 1a 13 00 ; SPRITE_LOG_MIDDLE &2f3a 19 16 00 ; SPRITE_LOG_RIGHT ; sprite_47 (SPRITE_LOG_ELEVEN) &2f3d 18 00 00 ; SPRITE_LOG_LEFT &2f40 1a 01 00 ; SPRITE_LOG_MIDDLE &2f43 1a 04 00 ; SPRITE_LOG_MIDDLE &2f46 1a 07 00 ; SPRITE_LOG_MIDDLE &2f49 1b 0a 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f4c 1a 0d 00 ; SPRITE_LOG_MIDDLE &2f4f 1c 10 00 ; SPRITE_LOG_MIDDLE_WITH_KNOT &2f52 1a 13 00 ; SPRITE_LOG_MIDDLE &2f55 1a 16 00 ; SPRITE_LOG_MIDDLE &2f58 1b 19 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f5b 1a 1c 00 ; SPRITE_LOG_MIDDLE &2f5e 1a 1f 00 ; SPRITE_LOG_MIDDLE &2f61 19 22 00 ; SPRITE_LOG_RIGHT ; sprite_48 (SPRITE_LOG_TWO) &2f64 18 00 00 ; SPRITE_LOG_LEFT &2f67 1c 01 00 ; SPRITE_LOG_MIDDLE_WITH_KNOT &2f6a 1b 04 00 ; SPRITE_LOG_MIDDLE_WITH_BRANCH &2f6d 19 07 00 ; SPRITE_LOG_RIGHT ; sprite_49 (SPRITE_LOG_ONE) &2f70 18 00 00 ; SPRITE_LOG_LEFT &2f73 1a 01 00 ; SPRITE_LOG_MIDDLE &2f76 19 04 00 ; SPRITE_LOG_RIGHT ; sprite_4a (SPRITE_CHAIN_ONE) &2f79 1f 00 00 ; SPRITE_CHAIN_BOTTOM &2f7c 20 00 06 ; SPRITE_CHAIN_MIDDLE &2f7f 21 00 14 ; SPRITE_CHAIN_TOP ; sprite_4b (SPRITE_CHAIN_TWO) &2f82 1f 00 00 ; SPRITE_CHAIN_BOTTOM &2f85 20 00 06 ; SPRITE_CHAIN_MIDDLE &2f88 20 00 14 ; SPRITE_CHAIN_MIDDLE &2f8b 21 00 22 ; SPRITE_CHAIN_TOP ; sprite_4c (SPRITE_CHAIN_THREE) &2f8e 1f 00 00 ; SPRITE_CHAIN_BOTTOM &2f91 20 00 06 ; SPRITE_CHAIN_MIDDLE &2f94 20 00 14 ; SPRITE_CHAIN_MIDDLE &2f97 20 00 22 ; SPRITE_CHAIN_MIDDLE &2f9a 21 00 30 ; SPRITE_CHAIN_TOP ; sprite_4d (SPRITE_CHAIN_FOUR) &2f9d 1f 00 00 ; SPRITE_CHAIN_BOTTOM &2fa0 20 00 06 ; SPRITE_CHAIN_MIDDLE &2fa3 20 00 14 ; SPRITE_CHAIN_MIDDLE &2fa6 20 00 22 ; SPRITE_CHAIN_MIDDLE &2fa9 20 00 30 ; SPRITE_CHAIN_MIDDLE &2fac 21 00 3e ; SPRITE_CHAIN_TOP ; sprite_4e (SPRITE_PLATFORM_TWO) &2faf 11 00 00 ; SPRITE_PLATFORM_ONE &2fb2 11 04 00 ; SPRITE_PLATFORM_ONE ; sprite_4f (SPRITE_PLATFORM_THREE) &2fb5 11 00 00 ; SPRITE_PLATFORM_ONE &2fb8 4e 04 00 ; SPRITE_PLATFORM_TWO ; sprite_50 (SPRITE_PLATFORM_FOUR) &2fbb 11 00 00 ; SPRITE_PLATFORM_ONE &2fbe 4f 04 00 ; SPRITE_PLATFORM_THREE ; sprite_51 (SPRITE_PLATFORM_FIVE) &2fc1 11 00 00 ; SPRITE_PLATFORM_ONE &2fc4 50 04 00 ; SPRITE_PLATFORM_FOUR ; sprite_52 (SPRITE_PLATFORM_SIX) &2fc7 11 00 00 ; SPRITE_PLATFORM_ONE &2fca 51 04 00 ; SPRITE_PLATFORM_FIVE ; sprite_53 (SPRITE_PLATFORM_SEVEN) &2fcd 11 00 00 ; SPRITE_PLATFORM_ONE &2fd0 52 04 00 ; SPRITE_PLATFORM_SIX ; sprite_54 (SPRITE_ROPE_TWO) &2fd3 00 00 00 ; SPRITE_ROPE_ONE &2fd6 00 00 19 ; SPRITE_ROPE_ONE ; sprite_55 (SPRITE_ROPE_THREE) &2fd9 00 00 00 ; SPRITE_ROPE_ONE &2fdc 54 00 19 ; SPRITE_ROPE_TWO ; sprite_56 (SPRITE_ROPE_FOUR) &2fdf 00 00 00 ; SPRITE_ROPE_ONE &2fe2 55 00 19 ; SPRITE_ROPE_THREE ; sprite_57 (SPRITE_LADDER_TWO) &2fe5 24 00 00 ; SPRITE_LADDER &2fe8 24 00 0e ; SPRITE_LADDER ; sprite_58 (SPRITE_LADDER_THREE) &2feb 24 00 00 ; SPRITE_LADDER &2fee 57 00 0e ; SPRITE_LADDER_TWO ; sprite_59 (SPRITE_LADDER_FOUR) &2ff1 24 00 00 ; SPRITE_LADDER &2ff4 58 00 0e ; SPRITE_LADDER_THREE ; sprite_5a (SPRITE_LADDER_FIVE) &2ff7 24 00 00 ; SPRITE_LADDER &2ffa 59 00 0e ; SPRITE_LADDER_FOUR ; sprite_5b (SPRITE_FRAK_OFFSET) &2ffd 22 03 1a ; SPRITE_FRAK # &582f - &592e is moved to &0a00 - &0aff at &46d6 ; mask_table &0a00 ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11 00 &0a10 ee ee cc cc aa aa 88 88 66 66 44 44 22 22 00 00 &0a20 dd cc dd cc 99 88 99 88 55 44 55 44 11 00 11 00 &0a30 cc cc cc cc 88 88 88 88 44 44 44 44 00 00 00 00 &0a40 bb aa 99 88 bb aa 99 88 33 22 11 00 33 22 11 00 &0a50 aa aa 88 88 aa aa 88 88 22 22 00 00 22 22 00 00 &0a60 99 88 99 88 99 88 99 88 11 00 11 00 11 00 11 00 &0a70 88 88 88 88 88 88 88 88 00 00 00 00 00 00 00 00 &0a80 77 66 55 44 33 22 11 00 77 66 55 44 33 22 11 00 &0a90 66 66 44 44 22 22 00 00 66 66 44 44 22 22 00 00 &0aa0 55 44 55 44 11 00 11 00 55 44 55 44 11 00 11 00 &0ab0 44 44 44 44 00 00 00 00 44 44 44 44 00 00 00 00 &0ac0 33 22 11 00 33 22 11 00 33 22 11 00 33 22 11 00 &0ad0 22 22 00 00 22 22 00 00 22 22 00 00 22 22 00 00 &0ae0 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 &0af0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # &592f - &5c26 is moved to &0507 - &07fe at &46c4 ; tune_data ; tune_0_data # Level 1 &0507 21 21 29 31 36 22 29 36 21 20 29 36 22 29 35 3d &0517 41 45 4a 36 3d 4a 28 28 2c 30 34 4a 35 34 3d 48 &0527 48 45 49 4d 52 3d 3c 45 52 30 34 30 38 3c 52 3d &0537 3c 45 50 54 58 41 34 3d 36 34 16 14 1a 18 1e 1c &0547 20 1c 20 25 2c a5 ; tune_1_data # Level 2 &054d 0f 3d 0d 1b 49 19 0d 3d 0d 19 49 19 3d 0d 2b 51 &055d 29 09 59 09 0d 3d 29 21 0d 19 21 15 6d 0f 6d 0d &056d 1b 55 19 0d 51 0d 19 51 19 49 0d 2b 51 29 09 59 &057d 09 0d 3d 29 23 1b 15 d9 ; tune_2_data # Level 3 &0585 23 0d 11 17 31 2d 29 11 0d 1d 21 0d 15 1d 23 0d &0595 11 17 31 2d 29 21 1d 15 0d 15 19 1d 23 0d 15 21 &05a5 29 2d 31 37 31 35 3b 35 39 23 1d 19 15 33 2d 29 &05b5 11 0d 1d 21 3c 3d 44 bd ; tune_3_data # Failure &05bd 5d 48 51 48 3d af ; tune_4_data # Completion &05c5 44 45 52 50 54 59 50 46 41 3c 44 3c 51 40 45 37 &05d5 e7 ; level_1_data &05d4 43 ; use sprite set "C" &05d5 54 ; add objects from class "T" &05d6 08 ; 1 object of type 0 (SPRITE_TROGG_RIGHT_HOLDING) &05d7 0a 30 ; at (&0a, &30) &05d9 00 ; end of class &05da 4d ; add objects from class "M" &05db 38 ; 7 objects of type 0 (SPRITE_SCRUBBLY) &05dc 33 bc ; at (&33, &bc) &05de 7b 7e ; at (&7b, &7e) &05e0 4c 30 ; at (&4c, &30) &05e2 69 30 ; at (&69, &30) &05e4 33 70 ; at (&33, &70) &05e6 17 bc ; at (&17, &bc) &05e8 a7 bc ; at (&a7, &bc) &05ea 00 ; end of class &05eb 4b ; add objects from class "K" &05ec 18 ; 3 objects of type 0 (SPRITE_KEY) &05ed a8 2e ; at (&a8, &2e) &05ef 7b 2f ; at (&7b, &2f) &05f1 5b bb ; at (&5b, &bb) &05f3 09 ; 1 object of type 1 (SPRITE_BULB) &05f4 3d bc ; at (&3d, &bc) &05f6 2a ; 5 objects of type 2 (SPRITE_GEM) &05f7 2a 2f ; at (&2a, &2f) &05f9 14 7d ; at (&14, &7d) &05fb a8 7d ; at (&a8, &7d) &05fd 69 7d ; at (&69, &7d) &05ff 4c 7d ; at (&4c, &7d) &0601 00 ; end of class &0602 46 ; add objects from class "F" &0603 f8 ; 31 object of type 1 (SPRITE_PLATFORM_TWO) &0604 08 2f ; at (&08, &2f) &0606 28 7c ; at (&28, &7c) &0608 28 2f ; at (&28, &2f) &060a 2d 76 ; at (&2d, &76) &060c 32 6f ; at (&32, &6f) &060e 37 66 ; at (&37, &66) &0610 3c 5d ; at (&3c, &5d) &0612 4b 7c ; at (&4b, &7c) &0614 4f 91 ; at (&4f, &91) &0616 53 a6 ; at (&53, &a6) &0618 5f a6 ; at (&5f, &a6) &061a 63 91 ; at (&63, &91) &061c 7a 7d ; at (&7a, &7d) &061e 80 8a ; at (&80, &8a) &0620 86 98 ; at (&86, &98) &0622 8d a6 ; at (&8d, &a6) &0624 94 b3 ; at (&94, &b3) &0626 80 77 ; at (&80, &77) &0628 86 6c ; at (&86, &6c) &062a 8d 60 ; at (&8d, &60) &062c 94 53 ; at (&94, &53) &062e 94 2e ; at (&94, &2e) &0630 a6 bb ; at (&a6, &bb) &0632 a6 7d ; at (&a6, &7d) &0634 a6 2e ; at (&a6, &2e) &0636 3c 7c ; at (&3c, &7c) &0638 5f 89 ; at (&5f, &89) &063a 4f 74 ; at (&4f, &74) &063c 53 89 ; at (&53, &89) &063e 63 74 ; at (&63, &74) &0640 67 7c ; at (&67, &7c) &0642 41 ; 8 objects of type 1 (SPRITE_PLATFORM_TWO) &0643 95 bb ; at (&95, &bb) &0645 3b 2f ; at (&3b, &2f) &0647 49 2f ; at (&49, &2f) &0649 57 bb ; at (&57, &bb) &064b 66 2f ; at (&66, &2f) &064d 77 2f ; at (&77, &2f) &064f 77 bb ; at (&77, &bb) &0651 57 9e ; at (&57, &9e) &0653 0c ; 1 object of type 4 (SPRITE_PLATFORM_FIVE) &0654 09 7c ; at (&09, &7c) &0656 15 ; 2 objects of type 2 (SPRITE_PLATFORM_THREE) &0657 09 bb ; at (&09, &bb) &0659 28 bb ; at (&28, &bb) &065b 00 ; end of class &065c 4c ; add objects from class "L" &065d 40 ; 8 objects of type 0 (SPRITE_LADDER_ONE) &065e 3e 42 ; at (&3e, &42) &0660 51 76 ; at (&51, &76) &0662 55 8b ; at (&55, &8b) &0664 59 a0 ; at (&59, &a0) &0666 60 8b ; at (&60, &8b) &0668 96 38 ; at (&96, &38) &066a 64 76 ; at (&64, &76) &066c 5c a0 ; at (&5c, &a0) &066e 29 ; 5 objects of type 1 (SPRITE_LADDER_TWO) &066f a8 54 ; at (&a8, &54) &0671 0a 92 ; at (&0a, &92) &0673 3e 92 ; at (&3e, &92) &0675 29 92 ; at (&29, &92) &0677 7b 92 ; at (&7b, &92) &0679 0a ; 1 object of type 2 (SPRITE_LADDER_THREE) &067a a8 84 ; at (&a8, &84) &067c 2b ; 5 objects of type 3 (SPRITE_LADDER_FOUR) &067d 68 38 ; at (&68, &38) &067f 0a 37 ; at (&0a, &37) &0681 29 37 ; at (&29, &37) &0683 4d 37 ; at (&4d, &37) &0685 7b 38 ; at (&7b, &38) &0687 00 ; end of class &0688 ff ; end of level data ; level_2_data &0689 4a ; use sprite set "J" &068a 54 ; add objects from class "T" &068b 08 ; 1 object of type 0 (SPRITE_TROGG_RIGHT_HOLDING) &068c 07 38 ; at (&07, &38) &068e 00 ; end of class &068f 4d ; add objects from class "M" &0690 41 ; 8 objects of type 1 (SPRITE_POGLET) &0691 6f 2f ; at (&6f, &2f) &0693 64 89 ; at (&64, &89) &0695 16 90 ; at (&16, &90) &0697 7d 2a ; at (&7d, &2a) &0699 42 57 ; at (&42, &57) &069b 2f 28 ; at (&2f, &28) &069d 48 e6 ; at (&48, &e6) &069f 2a cd ; at (&2a, &cd) &06a1 00 ; end of class &06a2 4b ; add objects from class "K" &06a3 20 ; 4 objects of type 0 (SPRITE_KEY) &06a4 05 90 ; at (&05, &90) &06a6 34 42 ; at (&34, &42) &06a8 87 17 ; at (&87, &17) &06aa 86 94 ; at (&86, &94) &06ac 09 ; 1 object of type 1 (SPRITE_BULB) &06ad 5f d5 ; at (&5f, &d5) &06af 12 ; 2 objects of type 2 (SPRITE_GEM) &06b0 04 bc ; at (&04, &bc) &06b2 21 a2 ; at (&21, &a2) &06b4 00 ; end of class &06b5 46 ; add objects from class "F" &06b6 30 ; 6 objects of type 0 (SPRITE_LOG_FIVE) &06b7 00 bb ; at (&00, &bb) &06b9 50 71 ; at (&50, &71) &06bb 34 89 ; at (&34, &89) &06bd 41 45 ; at (&41, &45) &06bf 6e 60 ; at (&6e, &60) &06c1 7a 17 ; at (&7a, &17) &06c3 09 ; 7 objects of type 1 (SPRITE_LOG_SEVEN) &06c4 1a 16 ; at (&1a, &16) &06c6 0a ; 1 object of type 2 (SPRITE_LOG_SEVEN_TWO) &06c7 00 37 ; at (&00, &37) &06c9 0b ; 1 object of type 3 (SPRITE_LOG_ELEVEN) &06ca 43 d4 ; at (&43, &d4) &06cc 5c ; 11 object of type 4 (SPRITE_LOG_TWO) &06cd 15 69 ; at (&15, &69) &06cf 26 bb ; at (&26, &bb) &06d1 2f 58 ; at (&2f, &58) &06d3 47 1b ; at (&47, &1b) &06d5 72 d7 ; at (&72, &d7) &06d7 79 af ; at (&79, &af) &06d9 75 9a ; at (&75, &9a) &06db 7a 79 ; at (&7a, &79) &06dd 03 90 ; at (&03, &90) &06df 2b 71 ; at (&2b, &71) &06e1 69 17 ; at (&69, &17) &06e3 ad ; 21 object of type 5 (SPRITE_LOG_ONE) &06e4 22 79 ; at (&22, &79) &06e6 12 90 ; at (&12, &90) &06e8 27 92 ; at (&27, &92) &06ea 19 bb ; at (&19, &bb) &06ec 35 b5 ; at (&35, &b5) &06ee 41 ae ; at (&41, &ae) &06f0 4d a8 ; at (&4d, &a8) &06f2 39 1b ; at (&39, &1b) &06f4 59 1c ; at (&59, &1c) &06f6 5c 28 ; at (&5c, &28) &06f8 5f 34 ; at (&5f, &34) &06fa 62 40 ; at (&62, &40) &06fc 6c 79 ; at (&6c, &79) &06fe 6c a1 ; at (&6c, &a1) &0700 84 94 ; at (&84, &94) &0702 37 28 ; at (&37, &28) &0704 33 42 ; at (&33, &42) &0706 35 35 ; at (&35, &35) &0708 19 cb ; at (&19, &cb) &070a 16 d7 ; at (&16, &d7) &070c 1f a1 ; at (&1f, &a1) &070e 00 ; end of class &070f 4c ; add objects from class "L" &0710 68 ; 13 objects of type 0 (SPRITE_ROPE_ONE) &0711 15 44 ; at (&15, &44) &0713 50 af ; at (&50, &af) &0715 4a 20 ; at (&4a, &20) &0717 35 64 ; at (&35, &64) &0719 29 96 ; at (&29, &96) &071b 50 4c ; at (&50, &4c) &071d 6e 3b ; at (&6e, &3b) &071f 79 b2 ; at (&79, &b2) &0721 80 8a ; at (&80, &8a) &0723 6e 7c ; at (&6e, &7c) &0725 0e 96 ; at (&0e, &96) &0727 23 7c ; at (&23, &7c) &0729 7d 3b ; at (&7d, &3b) &072b 21 ; 4 objects of type 1 (SPRITE_ROPE_TWO) &072c 16 99 ; at (&16, &99) &072e 42 4b ; at (&42, &4b) &0730 2f 1a ; at (&2f, &1a) &0732 1c 2b ; at (&1c, &2b) &0734 0a ; 1 object of type 2 (SPRITE_ROPE_THREE) &0735 64 7d ; at (&64, &7d) &0737 0b ; 1 object of type 3 (SPRITE_ROPE_FOUR) &0738 72 67 ; at (&72, &67) &073a 00 ; end of class &073b ff ; end of level data ; level_3_data &073c 47 ; use sprite set "G" &073d 54 ; add objects from class "T" &073e 08 ; 1 object of type 0 (SPRITE_TROGG_RIGHT_HOLDING) &073f 06 3a ; at (&06, &3a) &0741 00 ; end of class &0742 4d ; add objects from class "M" &0743 50 ; 10 objects of type 0 (SPRITE_HOOTER) &0744 40 94 ; at (&40, &94) &0746 0f b0 ; at (&0f, &b0) &0748 1f 91 ; at (&1f, &91) &074a 2e 4a ; at (&2e, &4a) &074c 99 1f ; at (&99, &1f) &074e b0 90 ; at (&b0, &90) &0750 21 4a ; at (&21, &4a) &0752 4f 1f ; at (&4f, &1f) &0754 85 1f ; at (&85, &1f) &0756 7d c8 ; at (&7d, &c8) &0758 00 ; end of class &0759 4b ; add objects from class "K" &075a 20 ; 4 objects of type 0 (SPRITE_KEY) &075b 0d 90 ; at (&0d, &90) &075d 57 6f ; at (&57, &6f) &075f 8a c2 ; at (&8a, &c2) &0761 b6 8f ; at (&b6, &8f) &0763 21 ; 4 objects of type 1 (SPRITE_BULB) &0764 18 6d ; at (&18, &6d) &0766 13 6d ; at (&13, &6d) &0768 5a d1 ; at (&5a, &d1) &076a 24 16 ; at (&24, &16) &076c 22 ; 4 objects of type 2 (SPRITE_GEM) &076d 19 b0 ; at (&19, &b0) &076f 7c 8c ; at (&7c, &8c) &0771 45 28 ; at (&45, &28) &0773 8f 1f ; at (&8f, &1f) &0775 00 ; end of class &0776 46 ; add objects from class "F" &0777 a0 ; 20 objects of type 0 (SPRITE_GIRDER_ONE) &0778 06 af ; at (&06, &af) &077a 0f af ; at (&0f, &af) &077c 18 af ; at (&18, &af) &077e 1f 90 ; at (&1f, &90) &0780 16 90 ; at (&16, &90) &0782 0c 90 ; at (&0c, &90) &0784 2e 49 ; at (&2e, &49) &0786 3b 49 ; at (&3b, &49) &0788 45 52 ; at (&45, &52) &078a 3b 5c ; at (&3b, &5c) &078c 85 1e ; at (&85, &1e) &078e 8e 1e ; at (&8e, &1e) &0790 99 1e ; at (&99, &1e) &0792 99 71 ; at (&99, &71) &0794 a2 71 ; at (&a2, &71) &0796 98 80 ; at (&98, &80) &0798 a4 8f ; at (&a4, &8f) &079a 97 8f ; at (&97, &8f) &079c 7d c7 ; at (&7d, &c7) &079e a2 1e ; at (&a2, &1e) &07a0 59 ; 11 object of type 1 (SPRITE_GIRDER_TWO) &07a1 6e 5a ; at (&6e, &5a) &07a3 7d 41 ; at (&7d, &41) &07a5 28 8d ; at (&28, &8d) &07a7 1a 33 ; at (&1a, &33) &07a9 1c 3f ; at (&1c, &3f) &07ab 1e 49 ; at (&1e, &49) &07ad 41 27 ; at (&41, &27) &07af 57 d0 ; at (&57, &d0) &07b1 6e b9 ; at (&6e, &b9) &07b3 6e c7 ; at (&6e, &c7) &07b5 9c af ; at (&9c, &af) &07b7 32 ; 6 objects of type 2 (SPRITE_GIRDER_THREE) &07b8 56 6f ; at (&56, &6f) &07ba a2 62 ; at (&a2, &62) &07bc 72 1e ; at (&72, &1e) &07be 45 66 ; at (&45, &66) &07c0 7b 8b ; at (&7b, &8b) &07c2 b0 8f ; at (&b0, &8f) &07c4 1b ; 3 objects of type 3 (SPRITE_GIRDER_FOUR) &07c5 4f 1e ; at (&4f, &1e) &07c7 22 da ; at (&22, &da) &07c9 24 15 ; at (&24, &15) &07cb 14 ; 2 objects of type 4 (SPRITE_GIRDER_FIVE) &07cc 02 39 ; at (&02, &39) &07ce 3c 93 ; at (&3c, &93) &07d0 1e ; 3 objects of type 6 (SPRITE_GIRDER_SEVEN) &07d1 4f a7 ; at (&4f, &a7) &07d3 3c da ; at (&3c, &da) &07d5 82 df ; at (&82, &df) &07d7 00 ; end of class &07d8 4c ; add objects from class "L" &07d9 30 ; 6 objects of type 0 (SPRITE_CHAIN_ONE) &07da 22 ab ; at (&22, &ab) &07dc 4f ab ; at (&4f, &ab) &07de 2e 1a ; at (&2e, &1a) &07e0 72 2b ; at (&72, &2b) &07e2 95 b0 ; at (&95, &b0) &07e4 a9 33 ; at (&a9, &33) &07e6 19 ; 3 objects of type 1 (SPRITE_CHAIN_TWO) &07e7 57 32 ; at (&57, &32) &07e9 81 4e ; at (&81, &4e) &07eb 3c 9d ; at (&3c, &9d) &07ed 12 ; 2 objects of type 2 (SPRITE_CHAIN_THREE) &07ee 2c 8f ; at (&2c, &8f) &07f0 82 94 ; at (&82, &94) &07f2 2b ; 5 objects of type 3 (SPRITE_CHAIN_FOUR) &07f3 06 56 ; at (&06, &56) &07f5 41 3a ; at (&41, &3a) &07f7 6e 60 ; at (&6e, &60) &07f9 9d 56 ; at (&9d, &56) &07fb 9f 56 ; at (&9f, &56) &07fd 00 ; end of class &07fe ff ; end of level data # &5c27 - &5c4a is moved to &0880 - &08a3 at &46cd ; high_scores &0880 76 26 6f 00 01 00 ; "v&o", 1000 &0886 4e 49 4b 00 01 00 ; "NIK", 1000 &088c 42 4f 46 00 01 00 ; "BOF", 1000 &0892 43 41 50 00 01 00 ; "CAP", 1000 &0898 50 41 4d 00 01 00 ; "PAM", 1000 &089e 44 43 45 00 01 00 ; "DCE", 1000