Way Of The Exploding Fist (Hacking Tips #11)

By Mr. Spock

Originally published in EUG #71

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