Here is part of that loader:
| EA7 | JSR &ECB:STA &64 \Get address, &ECB is routine to get JSR &ECB:STA &65 \one byte from tape ... |
|
| EB7 | JMP (&64) |
If you poke an instruction in at &EB7 to divert the routine through some code:
P%=&EB7:[JMP &900:]
P%=&900:[PHA:LDA &5E:JSR &B545:LDA &64:JSR &B545:PLA:JMP (&64):]
then this will keep a watch on where the routine goes to load in the next page (&E57 for BIRDSTRIKE, until loading is complete when it is &600).
The following poke:
P%=&900:[PHA:LDA &5E:JSR &B545:PLA:JMP (&64):]
shows you which page the code is being loaded into - page &06, page &1E ... &2F, &07.
Note that &B545 is the address of a routine in BASIC 2 to print the accumulator in hex and, in the case of BIRDSTRIKE, &5E/F contains the address where the code is being loaded.
Armed with this information we can intercept the program just before it JuMPs to &600 to decrypt and execute, and save it to disk!
This technique worked perfectly on BIRDSTRIKE, THE HACKER and VIDEO CLASSICS. Unfortunately, it doesn't work with STAR DRIFTER and so far I've drawn a blank at decrypting this last title. Does anyone reading this have any ideas?
The tape loaders in this contain purported 'nonsense code' but I worked out that the decryption routine contains 'undocumented' (useless but harmless) codes interspersed with real machine code. This decrypts a page of machine code proper to load in the game by BGETting the bytes from tape, plus some fancy code makes the tape counter look like it's counting down instead of up. (It appears as 00, FF, FE, FD, etc on screen.)
There are originally four parts to this game so putting it on disc is made much more difficult as I do not know what instruction is executed when the end of any part is reached. I presume it will try to *RUN the next part from tape, because the game is so big it needed to have all disc systems disabled before it runs proper.
I ended up writing a (rudimentary) menu system to allow the user to select which of the four parts he wished to play every time the game loaded. In time I might be able to do some more surgery on the game code to re-select the disc system for loading the next part. But that does seem rather difficult - ordinarily it's impossible to reinitialise a system like ADFS after its workspace has been corrupted with game data!
Both the JSW games will not run unless the small tape loader program is resident in zero page. Therefore, a bit of twiddling with the machine code and this game can quite easily be put into memory. The disc version simply *LOADs the loader a second time after the download is complete.
WLOAD is an example of a loader program that depends on the state of the cassette workspace (&380-&3DF) after loading. There's a JMP (&3CB) at the end of the tape loader. &3B2-&3D0 contain information about the most recent tape block read, and in this case, when loading from tape, &3CB and &3CC contain &1100 after the last block.
Of course, if you transfer the file to disc then load it, these two locations are empty and so JMP (&3CB) won't work! After downloading all the parts, the solution is just to jump to address we know - JMP &1100 - instead.
This protection is some of the most difficult I have encountered on a game. The program needs to be arrested to save the code onto disk. The loader program decrypts itself then deletes itself as it goes along! e.g.
| 603 | LDA #&28:PHA | \Return address of &28FF so exec | |
| LDA #&FF:PHA | \address of game &2900 | ||
| LDA #26:PHA:LDA #22:PHA | \used for decryption | ||
| ... | |||
| 61D | STA &600,Y | \Delete code from &600-&61E | |
| INY:CPY #&1D:BNE &61D | |||
| PLA:STA &70:STA &71:PLA:STA &72 | |||
| ... (decryption routine) | |||
| 678 | STA &600,X | \Delete code at &601-&677 | |
| DEX:BNE &678 | |||
| RTS | |||
The puzzling RTS at the end (Where does it return to?) makes sense when you realise that a new return address minus one had been pushed onto the stack beforehand.
Part of the loader program on tape was encrypted:
| 900 | LDY #0 | |
| 902 | LDA &915,Y:EOR #&55:STA &915,Y LDA &A15,Y:EOR #&55:STA &A15,Y INY:BNE &902 |
|
| 915 | \ This bit is decoded by the time it is reached. The file LASTBIT is loaded in and decrypted using a simple loop to EOR all bytes with &FF and execution is at &3C00. |
I hope that's given a bit of insight into the methods commerical programmers used to protect their programs. I'm busy working on lots more conversions from tape to disc and will see you all in the next EUG!
Mr Spock, EUG #65