Way Of The Exploding Fist loader program, LOADER. An example of decryption and custom tape loading
This routine is called at &F08 to 'randomise' a seed for decryption. See end of article for program to 'zap' the loader.
0EEC LDA &0F02 0EEF AND #&48 0EF1 ADC #&38 0EF3 ASL A 0EF4 ASL A 0EF5 ROL &0F04 0EF8 ROL &0F03 0EFB ROL &0F02 0EFE LDA &0F02 0F01 RTS 0F02 EQUB &44 \Seeds for 0F03 EQUB &73 \random (but predictable) 0F04 EQUB &AF \number generator
Program executes at &F05:
0F05 LDX #&00 0F07 CLC 0F08 JSR &0EEC \randomize 0F0B EOR &1000,X \and decrypt page &10 0F0E EOR &0EEC,X 0F11 STA &1000,X 0F14 LDA &FFB7 \get address of default vector table 0F17 STA &70 \in os rom and store in &70/&71 0F19 LDA &FFB8 0F1C STA &71 0F1E LDY &FFB6 \get vector table length 0F21 LDA (&70),Y \copy default vectors 0F23 STA &0200,Y \ensures any naughty user-defined ones 0F26 DEY \are removed 0F27 BPL &0F21 0F29 LDA #3 \Disable Escape and clear memory on break 0F2B STA &0258 \*FX200,3 equivalent 0F2E INX 0F2F CPX #&FE \until reached &10FE 0F31 BCC &0F08 0F33 LDA #15 \*FX15,0 0F35 LDX #0 \clear keyboard buffer 0F37 JSR OSbyte 0F3A LDX #0 \VDU codes 0F3C LDA &0FAF,X \at &FAF-&FFF 0F3F JSR OSwrch 0F42 INX 0F43 CPX #&51 0F45 BNE &0F3C
This next section is specifies how many pages of data to load using the custom tape loader at &1022.
0F47 LDX #&00 \ 0F49 LDY #&04 \load address &400 0F4B LDA #&55 \EOR value &55 0F4D STA &76 0F4F LDA #&05 \load &500 bytes 0F51 JSR &1022 \to &400-&900 0F54 LDY #&0F 0F56 STY &0DE6 0F59 LDA #0 \clear 0F5B STA &02A1,Y \&2A1-&2B0 0F5E DEY 0F5F BPL &0F5B 0F61 LDA #&FE 0F63 STA &0DF8 0F66 LDA #&60 \change opcode to RTS 0F68 STA &0637 \disables latter part of event, cf &101A 0F6B LDA #&20 \user event routine 0F6D STA &0220 \at &0620 0F70 LDA #&06 0F72 STA &0221 0F75 LDA #14 \*FX14,4 0F77 LDX #4 \enable start-of-vertical sync event 0F79 JSR OSbyte 0F7C LDA #14 \*FX14,5 0F7E LDX #5 \enable interval timer crossing zero event 0F80 JSR OSbyte 0F83 LDY #&00 0F85 LDA #&FF \fill &5800-&5BBF 0F87 STA &7F00,Y \&7D80-&7FFF 0F8A STA &7E00,Y \with white 0F8D STA &7D80,Y 0F90 STA &5800,Y 0F93 STA &5900,Y 0F96 STA &5A00,Y 0F99 STA &5AC0,Y 0F9C DEY 0F9D BNE &0F85 0F9F LDX #&80 \load address 0FA1 LDY #&5F \&5F80 0FA3 LDA #&AA \EOR value &AA 0FA5 STA &76 0FA7 LDA #&0F \load &F00 bytes 0FA9 JSR &1022 \to &5F80-&6E80 (banner) 0FAC JMP &1000 \jump to &1000 to continue execution
VDU sequence used at &F3A. Equivalent of Basic MODE 5:VDU 23,1,0,0,0,0,0,0,0,0:COLOUR 1:PRINT TAB(3,14)"THE WAY OF THE"''' " EXPLODING FIST":COLOUR 3:PRINT'''"(C)1986,M.A. Simpson":VDU26:PRINT'''
0FA8 ** ** ** ** ** ** ** 16 . 0FB0 05 17 01 00 00 00 00 00 ........ 0FB8 00 00 00 11 01 1F 03 14 ........ 0FC0 54 48 45 20 57 41 59 20 THE WAY 0FC8 4F 46 20 54 48 45 0A 0A OF THE.. 0FD0 0D 20 20 20 45 58 50 4C . EXPL 0FD8 4F 44 49 4E 47 20 46 49 ODING FI 0FE0 53 54 11 03 0A 0A 0A 0D ST...... 0FE8 28 43 29 31 39 38 36 2C (C)1986, 0FF0 4D 2E 41 2E 20 53 69 6D M.A. Sim 0FF8 70 73 6F 6E 1A 0A 0A 0A pson.... 1000 LDX #&00 \ 1002 LDY #&09 \load address &900 1004 LDA #&33 \EOR value &33 1006 STA &76 1008 LDA #&07 \load &700 bytes 100A JSR &1022 \to &900-&1000 100D LDX #&00 \ 100F LDY #&11 \load address &1100 1011 LDA #&BD \EOR value &BD 1013 STA &76 1015 LDA #&47 \load &4700 bytes 1017 JSR &1022 \to &1100-&5800 101A LDA #&20 \change opcode to JMP 101C STA &0637 \in event 101F JMP &1ED0 \start game
Next bit is custom tape loader
1022 STX &70 \YX=load address 1024 STY &71 1026 STA &72 \A=decryption EOR value 1028 LDX #0 \print 102A JSR &1071 \Searching message 102D LDA #&E8 \%11 101 00 0 102F STA &FE07 \Cassette motor on (bit 7=1) \Caps Lk on (bit 6=1) \Mode 5 (bits 3-5=5) \Cassette input (bits 1-2=0) \Bit 0 is not used 1032 LDA #0 \Ensure cassette receive mode 1034 STA &FE06 \all bits of &FE06 are zero 1037 LDA &FE00 \Bit 5 is set if 'receive mode full' 103A AND #&40 \ie high tone signal detected 103C BEQ &1037 \no - loop till get the tone 103E STA &FE05 \?&FE05=&40 clear high tone 1041 JSR &10EF \Load byte in 1044 CMP #&2A \is it ASC"*", our signal byte 1046 BNE &1041 \no 1048 LDY #&00 \Yes, try loading 104A JSR &10D2 104D STY &74 \Y=0 104F JSR &107D 1052 EOR &76 \EOR with given decrypt byte 1054 STA (&70),Y \store in memory 1056 EOR &74 \?&74=0 so ?&74=copy of data byte 1058 STA &74 105A INY \memory=memory+1 105B BNE &104F \done 105D JSR &107D \delay 1060 CMP &74 \?&74 is checksum 1062 BNE &1095 \if no match print Rewind tape 1064 INC &71 \memory=memory+&100 1066 DEC &72 \until page count is zero 1068 BNE &104A 106A LDA #&A8 \%10 101 000 106C STA &FE07 \Caps lock on (bit 7=1) \Cassette motor off (bit 6=0) \Bits 0-5 as before - see &102F 106F LDX #&24 \print blank space \Entry point for message printing \X=offset into messages table at &109F 1071 LDA &109F,X \load character of tape message 1074 JSR OSwrch 1077 INX 1078 CMP #&0D \until char is a CR 107A BNE &1071 107C RTS 107D LDX #&10 \count 16 bits, each data byte dupliacted 107F STX &75 \and we have 16 attempts to load it 1081 LDA &FE00 \from tape 1084 AND #&10 \Bit 4 of &FE00 set 1086 BEQ &108C \when 8 bits = 1 byte read in 1088 LDA &FE04 \okay so 108B RTS \return with byte in A 108C DEX \decrement bit count 108D BNE &1081 \and loop 108F DEC &75 \problem if we reach here 1091 BNE &1081 \so try again 1093 PLA \have failed to load byte so 1094 PLA \discard return address because we 1095 LDX #&18 \print 1097 JSR &1071 \Rewind tape 109A LDY #&00 \and 109C JMP &104A \return to main loop. \Tape messages \Offset &00=Searching \ &0C=Loading \ &18=Rewind tape \ &24=(blank) 1098 ** ** ** ** ** ** ** 53 S 10A0 65 61 72 63 68 69 6E 67 earching 10A8 20 20 0D 4C 6F 61 64 69 .Loadi 10B0 6E 67 20 20 20 20 0D 52 ng .R 10B8 65 77 69 6E 64 20 74 61 ewind ta 10C0 70 65 0D 20 20 20 20 20 pe. 10C8 20 20 20 20 0D ** ** ** 10CD LDX #&18 \ 10CF JSR &1071 \Rewind tape \entry point from &104A 10D2 JSR &10EF \REPEAT get byte 10D5 CMP #&23 \=ASC"#" 10D7 BNE &10D2 \UNTIL ="#" 10D9 JSR &10EF \get a byte from tape 10DC LDX #&0C \prepare Loading tape message 10DE CMP &72 \is it same as page count 10E0 BEQ &10EC \yes - carry on 10E2 BCC &10CD \less than value so Rewind 10E4 LDX #&00 \more than value so 10E6 JSR &1071 \Searching 10E9 JMP &10D2 \loop till correct byte found 10EC JMP &1071 \Print loading and continue \Routine to get a byte from tape once the necessary \flag bytes have been found 10EF LDA &FE00 \REPEAT 10F2 AND #&10 \if bit 4 of &FE00 is set we have not read 10F4 BEQ &10EF \in a full byte of data 10F6 LDA &FE04 \Get the byte 10F9 RTS \and return 10FA EOR &5341 10FD BRK
Appendix: Program to zap tape loader and save out as LOADERZ for inspection in a disassembler.
10 REM WOTEF LOADER zapper by Dr.W 20 *L.LOADER 1EEC 30 *L.LOADER 21EC 40 REM relocate absolute addresses +&1000 50 FORx=0TO4:READy:y?&1E00=y?&1E00+&10:NEXT 60 FORx=0TO253:!&70=USR&1EEC 65 FORy=0TO2:y?&2202=y?&1F02:NEXT 70 x?&2300=x?&2300 EOR?&70 EOR x?&21EC 80 NEXT 90 *SAVE LOADERZ 21EC+214 F05 EEC 100 DATA&EE,&F7,&FA,&FD,&100
Mr Spock 27 Mar 2004