Galaforce 2 (Hacking Tips #7)

By Mr. Spock

Originally published in EUG #71

Galaforce 2 - a Kevin Edwards self-decrypting loader which loads in the main game files, decrypts the main game file and executes an RTS - to an execute address purposely pushed onto the stack beforehand.

0400 LDA #15
0402 LDX #0	\*FX15,0
0404 JSR OSbyte	\Clear keyboard
0407 SEI 	\disable interrupts
0408 LDA #0
040A LDX #15
040C STA &02A1,X
040F DEX	\Ensure no foreign ROMs 
0410 BPL &040C	\are present
0412 LDY &FFB6	\and no foreign vectors
0415 DEY	\by copying default address 
0416 LDA &FFB7	\vectors from OS ROM.
0419 STA &70
041B LDA &FFB8
041E STA &71
0420 LDA (&70),Y
0422 STA &0200,Y
0425 DEY 
0426 BPL &0420
0428 JMP &04E2	\continue execution at 4E2

\Kevin advertises himself in this next bit

0428 ** ** ** 50 72 6F 74 65    Prote
0430 63 74 69 6F 6E 20 64 65 ction de
0438 73 69 67 6E 20 26 20 63 sign & C
0440 6F 64 69 6E 67 20 28 63 oding (c
0448 29 20 4B 65 76 69 6E 20 ) Kevin 
0450 45 64 77 61 72 64 73 20 Edwards 
0458 31 39 38 38 2D 2D 2D 2D 1988----
0460 2D 2D 2D 2D 2D 2D 2D 2D --------
0468 2D 2D 2D 2D 2D 2D 2D 2D --------
0470 2D 2D 2D 2D 2D 2D 2D 2D --------
0478 2D 2D 2D 2D 2D 2D 2D 2D --------
0480 2D 2D 2D 2D 2D 2D 2D 2D --------
0488 2D 2D 2D 2D 2D 2D 2D 2D --------
0490 2D 2D 2D 2D 2D 2D 2D 2D --------
0498 2D 2D 2D 2D 2D 2D 2D 2D --------
04A0 2D 2D 2D 2D 2D 2D 2D 2D --------
04A8 2D 2D 2D 2D 2D 2D 2D 2D --------
04B0 2D 2D 2D 2D 2D 2D 2D 2D --------
04B8 2D 2D 2D 2D 2D 2D 2D 2D --------
04C0 2D 2D 2D 2D 2D 2D 2D 2D --------
04C8 2D 2D 2D 2D 2D 2D 2D 2D --------
04D0 2D 2D 2D 2D 2D 2D 2D 2D --------
04D8 2D 2D 2D 2D 2D 2D 2D 2D --------
04E0 2D 2D ** ** ** ** ** ** --


04E2 SEI	\disable interrupts 
04E3 LDX #255
04E5 TXS	\reset stack pointer 
04E6 INX	\X=0 
04E7 LDA #3
04E9 STA &0258	\*FX200,3
04EC LDA #75
04EE STA &70
04F0 LDA #69
04F2 STA &71
04F4 LDA #86
04F6 STA &72
04F8 LDA #73
04FA STA &73
04FC LDA #78	\Store values used in
04FE STA &74	\decryption

0500 LDA &0500
0503 EOR &70
0505 INC &0511
0508 EOR &72
050A INC &71
050C INC &71
050E EOR &71
0510 EOR #237
0512 EOR &0600,X
0515 LDY &74
0517 STY &051B
051A EOR #236
051C EOR &0601,X
051F EOR &73
0521 STA &0600,X
0524 LDA &73
0526 EOR &74
0528 STA &73
052A CLC 
052B ADC #244
052D STA &74
052F EOR &0511
0532 STA &72
0534 LSR A
0535 EOR &74
0537 STA &70
0539 INX 
053A BNE &0500

053C LDY #3	\*FX200,3
053E STY &0258
0541 LDA #&4C	\&4C is code for JMP
0543 STA &0287	\When break is pressed, if ?&287=&4C
0546 LDA #&87	\we JMP to the address in &288/9
0548 STA &0288	\which is
054B DEY	\Y=2 
054C STY &0289	\&24C
054F LDA #64
0551 STA &0D00
0554 LDA &FFFA
0557 BNE &05B4
0559 LDA &FFFB
055C CMP #13
055E BNE &05B4
0560 INC &0501
0563 BNE &0500
0565 LDA #0
0567 STA &70
0569 STA &71
056B TAY 
056C LDA &71
056E EOR &0600,Y
0571 STA &71
0573 LDX #8
0575 LDA &71
0577 ROL A
0578 BCC &0586
057A LDA &71
057C EOR #8
057E STA &71
0580 LDA &70
0582 EOR #16
0584 STA &70
0586 ROL &70
0588 ROL &71
058A DEX 
058B BNE &0575
058D INY 
058E CPY #20
0590 BNE &056C
0592 LDA &70	\Checksum, match
0594 CMP &06FE	\contents of &70/71
0597 BNE &05AD	\against &6FE/6FF
0599 LDA &71
059B CMP &06FF
059E BEQ &0600	\If matched, continue at &600
05A0 BNE &05AD	\Otherwise loop forever

\Kevin says hello
05A0 ** ** 48 69 20 42 54 57   Hi BTW
05A8 20 2E 2E 2E 2E ** ** **   ...   

\Come to this bit if checksums don't match
05AD LDA #200
05AF LDX #3
05B1 JSR OSbyte	\*FX200,3
05B4 STA &0600,Y	\Clear memory
05B7 INY 
05B8 JMP &05B4	\Loop forever

\Next bit is padding, as you can see from the
\repeated PAD word
05B8 ** ** ** 20 28 63 29 20     (c) 
05C0 4B 65 76 69 6E 20 45 64 Kevin Ed
05C8 77 61 72 64 73 20 31 39 wards 19
05D0 38 38 20 20 20 20 20 50 88     P
05D8 41 44 50 41 44 50 41 44 ADPADPAD
05E0 50 41 44 50 41 44 50 41 PADPADPA
05E8 44 50 41 44 50 41 44 50 DPADPADP
05F0 41 44 50 41 44 50 41 44 ADPADPAD
05F8 50 41 44 50 41 44 50 41 PADPADPA


0600 LDX #239	\Set stack pointer
0602 TXS 	\to 239
0603 LDA #&57	\execution point
0605 PHA 	\of game minus 1
0606 LDA #&FF	\ie &5800
0608 PHA 
0609 LDA #209
060B PHA 
060C LDA #99
060E PHA 
060F LDX #53	\Check that there are no foreign
0611 LDA &0200,X	\vectors by loading their hi bytes.
0614 BPL &05B4	\If they are <&80 (+ve) then
0616 DEX 	\user has fiddled so jump to
0617 DEX 	\loop-forever routine.
0618 BPL &0611
061A LDA #0
061C TAY 
061D STA &0600,Y	\Clear memory up to current point
0620 INY 	\&600-628
0621 CPY #29
0623 BNE &061D
0625 CLI 
0626 LDA #140	\*TAPE
0628 LDX #12
062A JSR OSbyte
062D LDX #&BC	\*command at &6BC
062F LDY #&06	\*L.GAME? 900
0631 JSR OScli 
0634 LDX #&CC	\*command at &6CC
0636 LDY #&06	\*L.GAME2?? E00
0638 JSR OScli 
063B LDA #15
063D LDX #0	\*FX15,0
063F JSR OSbyte	\clear kbd
0642 SEI	\disable interrupts
0643 LDA #3
0645 STA &0258	\*FX200,3
0648 LDA &0287
064B CMP #76	\If contents of &287
064D BEQ &0652	\are <> 76 jump to
064F JMP &05B4	\loop-forever routine

0652 LDY #0
0654 LDX #78
0656 PLA	\Value put on stack at &60C 
0657 STA &70	\?&70=99	
0659 STA &71	\?&71=99
065B PLA 
065C STA &72	\?&72=209
065E LDA &0E00,Y	\Decode game code
0661 EOR &70
0663 DEC &71
0665 EOR &71
0667 EOR &72
0669 STA &0E00,Y
066C INC &72
066E LDA &72
0670 SEC 
0671 SBC #95
0673 EOR &71
0675 STA &72
0677 EOR &70
0679 STA &70
067B EOR #228
067D STA &71
067F EOR &72
0681 INY 
0682 BNE &065E
0684 INC &0660
0687 INC &066B
068A DEX 
068B BNE &065E
068D STX &0287
0690 CLI	\reneable interrupts
0691 RTS	\return to address on stack ie &5800. 

\More PADding
0690 ** ** 50 84 44 50 41 81   PADPAD
0698 50 41 44 95 41 44 50 84 PADPADPA
06A0 44 50 41 44 50 41 44 50 DPADPADP
06A8 41 44 50 41 44 50 41 44 ADPADPAD
06B0 50 41 44 95 41 44 50 84 PADPADPA
06B8 44 50 41 81 4C 4F 41 81 DPADLOAD
06C0 20 47 61 6D 65 83 7F 20  Game..
06C8 39 30 30 0D 4C 4F 41 44 900.LOAD
06D0 20 47 61 A8 65 32 84 BA  Game2..
06D8 20 45 30 F5 0D 50 72 AA  E0..Pro
06E0 74 65 63 74 69 6F 6E 20 tection 
06E8 28 63 29 20 4B 65 76 69 (c) Kevi
06F0 6E 20 45 A1 77 61 72 A1 n Edward
06F8 73 20 31 FC 38 38 34 74 s 19884t

Mr Spock 1 Feb 2005