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