Boulderdash - example of self-decrypting loader, called CODE on tape, plus decryption of game before execution.
0A00 LDA #15 \*FX15,0 0A02 LDX #0 \Clear keyboard 0A04 JSR OSbyte 0A07 LDX #0 0A09 SEI \Disable interrupts 0A0A LDA &0B00 0A0D CLC 0A0E ADC #33 0A10 EOR &0A00,X 0A13 EOR #78 0A15 SEC 0A16 SBC &0A14 0A19 EOR &0A00,X 0A1C EOR #43 0A1E CLC 0A1F ADC #33 0A21 EOR #102 0A23 SEC 0A24 SBC #13 0A26 EOR &0A00,X 0A29 INX 0A2A BNE &0A0D 0A2C STA &0B00 0A2F LDA #1 \Disable Escape 0A31 STA &0258 \*FX200,1 equivalent 0A34 LDA #&4C \Code for JMP 0A36 STA &0287 \ 0A39 LDA #&5C \store &A5C so when Break 0A3B STA &0288 \pressed JMP &A5C 0A3E LDA #&0A \ 0A40 STA &0289 0A43 INC &0A14 0A46 DEC &0A0F 0A49 INC &0A0B 0A4C INC &0A2D 0A4F BNE &0A0A 0A51 LDA &0BFF \Checksum 0A54 CMP &0BF0 \If doesn't match go to 0A57 BNE &0A5C \loop-forever routine 0A59 JMP &0B00 \else continue
This is the address to which the Electron jumps on pressing Break or if checksums don't match at &A51.
0A5C LDA #0 0A5E STA &70 0A60 LDA #&0B 0A62 STA &71 0A64 LDY #0 0A66 LDA #0 \In Basic this will be 0A68 STA (&70),Y \FOR A%=&B00 TO &7FFF 0A6A INY \?A%=0:NEXT 0A6B BNE &0A66 0A6D INC &71 0A6F LDA &71 0A71 CMP #&80 0A73 BNE &0A66 0A75 BEQ &0A5C \loop forever
The code from &B00 was decoded using the following Basic program. It copies some of the code to (displacing +&2000 bytes for easy reference) and adds instructions to affect the relocated code as well as the original code where appropriate. This is necessary as the decryption routine relies on self-changing code to work - so putting an RTS at &A59 for example will fail.
10 REM BOULDERDASH CODE zapper 20 *L.CODE A00 30 FORX%=&0ATO&2E:X%?&2A00=X%?&A00:NEXT 40 P%=&2A2F:[INC&A14:INC&2A14 50 DEC&A0F:DEC&2A0F 60 INC&A0B:INC&2A0B 70 INC&A2D:INC&2A2D:BNE&2A0A 80 RTS:] 90 X%=0:CALL&2A0A 0B00 LDA &0258 \Check that *FX200,1 0B03 CMP #1 \has been set 0B05 BEQ &0B0A \ 0B07 JMP &0A5C \if not go to memory clearing routine 0B0A LDX #0 0B0C LDA #0 \zeroise &2A1-&2AF 0B0E STA &02A1,X 0B11 INX 0B12 CPX #15 0B14 BNE &0B0C 0B16 LDY &FFB6 \Y=length of default vector table 0B19 LDA &FFB7 \copy vector table address in OS rom 0B1C STA &70 \to &70/1 0B1E LDA &FFB8 0B21 STA &71 0B23 LDA (&70),Y \copy default vectors 0B25 STA &0200,Y \so any naughty ones the user has set up 0B28 DEY \won't work 0B29 BNE &0B23 0B2B LDX #&38 \command line 0B2D LDY #&0B \at &B38 0B2F JSR OScli \*load file at &1300 0B32 JSR &0B47 \decrypt game code 0B35 JMP &31C0 \and execute Block containing command line "LOAD ___1___ 1300" 0B30 ** ** ** ** ** 4C C0 31 L.1 0B38 4C 2E 5F 5F 5F 31 5F 5F L.___1__ 0B40 5F 20 31 33 30 30 0D ** _ 1300
The following routine decrypts the main game code at &B47. In Basic it would be:
j=51:k=152:A%=&1300 REPEAT FOR Y%=0 TO &FF:Y%?A%=Y%?A% EOR j EOR k k=(k-2) AND &FF NEXT j=(j-1) AND &FF A%=A%+&100 UNTIL A%=&5800 0B47 LDA #0 0B49 STA &70 0B4B TAY \Y%=0 0B4C LDA #&13 \A%=&1300:j=51:k=152 0B4E STA &71 0B50 LDA (&70),Y \REPEAT 0B52 EOR #&33 \?A%=?A% EOR j 0B54 EOR #&98 \EOR k 0B56 STA (&70),Y 0B58 DEC &0B55 \k=(k-2)AND&FF 0B5B DEC &0B55 0B5E BNE &0B63 0B60 DEC &0B53 \j=(j-1)AND&FF 0B63 INY \(Y%=Y%+1)AND&FF 0B64 BNE &0B50 \UNTIL Y%=0 0B66 INC &71 0B68 LDA &71 \A%=A%+&100 0B6A CMP #&58 \UNTIL A%=&5800 0B6C BNE &0B50 0B6E RTS
Mr Spock 26 Mar 2004