As someone who has contributed many games tips, cheat POKEs, and listings for the Commodore 64 over the years, hopefully to provide some joy to games players with infinite lives and so on, I can remember back in late 1991 being still, unfortunately, out of work at the time. This was a demoralising time for me in several ways, although thankfully, light was appearing at the end of a tunnel with a job interview and a new job starting early on in 1992. What did keep me going was the fact that I was able to create and send in POKEs and cheats to Zzap! 64 and later Commodore Format, and so with any vouchers won for my submissions, plus any games I would have sent to me, that did keep the brain occupied nicely.
Although the Codemasters Multihack Simulator would come along a little later, which I documented over at the Commodore Format Archive, that hack would also be suitable for earlier Mastertronic games, as they used the same loading system (often called Visiload.) There was a sensible pattern occurring amongst most software companies in that if they had a reliable loading system that they could use when mastering, they would apply that consistently to their titles, such as Paul Hughes’ Freeload at Ocean for example. It also meant that mastering was generally an easier process and when you are attempting to manufacture en masse and for a low retail price as Mastertronic would do, having something reliable was key.
This will detail my work into creating the multihack for games which used the Invade-a-Load loader, which also was compatible with the earlier Load’n’Play loading game, and was utilised without any loading game for several early Rack-It releases too. This made its debut in Issue 80 (January 1992) of Zzap! 64, just prior to my agreement to contribute exclusively to Commodore Format later. So here goes, with plenty of detail and some fun facts, with surprises along the way.
Inspiration via Wildsave
In an earlier issue of Zzap! 64, I had noted that fellow creator of POKEs and listings, Martin Pugh (a long-time member of the Gamebase 64 team – if you see anything cracked by Pugsy, that is him) had created a multihack for Commodore 64 games which used the loading system created by Andrew Challis for both Interceptor and Players games, called Wildsave. As Players were the budget arm with some good releases, it made sense to use a similar loading system for their mastering, which even made its way into full price games for other companies such as Quedex and Predator. Effectively when the loader code is the same, you can intercept the code in the same way, redirect to the routine of your choice, and enter the relevant cheats as you need. For the listing itself, you had a master which loaded the consistent code into memory, and then the data lines for the cheats themselves, or if you needed to intercept a decompressor routine if the game was saved via a freezer cartridge such as the Action Replay or Expert, you could add the code there too. So that gave me the idea – what if other loaders did the same thing?
Intercepting Invade-a-Load
I first looked at several games that I had which involved Invade-a-Load. This loaded the machine code routine for the loader first, then loaded the Invade-a-Load game complete with Rob Hubbard’s music from One Man and His Droid, and whilst you played that, would then load the game into memory and usually then either start the game natively or decompress into memory if using the Expert or Action Replay as mentioned above. This did make the additional step for the DATA lines a little trickier, but we would get on to that later. The loader would load the code into memory, turn the screen black, and have a black border with flashes of white to indicate loading. This meant that if the screen border colour was being changed, that would be a relatively good piece of target code to intercept. Having checked a few games, the instructions were at the same location in memory, so that did make some sense.
What I discovered was that if you used the Kernel routine JSR $F556 (hence the fact you would see data lines of 32, 86 and 245 to resemble the decimal equivalents, with the JSR instruction being $20 in hex) and then made your code loop on itself, the loader would load but not start, which means we can put any changes to the loader at that point. Upon closer inspection, when the game reaches FOUND, the tape buffer stores the load and end addresses, which shows $0326 as the start and $0500 as the high. During the LOADING part that follows, $0326 is populated with the bytes $40 and $03, and using lo/hi addressing, that is $0340. Now when you consider that is the execution address of the CHROUT routine, clearly it is being used to start the main loader instead. Checking the code at $0340 shows this. It is also why you briefly see characters on the screen because the loader is using parts of the Commodore 64’s default screen area to store the code, a neat way of stopping those with just a reset switch.
So, with the loader code checked and verified, and knowing a JSR $F556 is enough to load that loader, add the code in and return, I noted that there are two calls to change the screen border colour: one to increase at $0496 and one to decrease at $049F. I could choose either and redirect this to my own code instead. Normally the available memory from $0200-$029F can be available, so stuck with using $0210 in case any loaders did something with the first few bytes there. What I then initially did was have something which re-routed the change border colour call to my code, re-instate the instruction, and then use that for any cheats I wanted to add and then call a RTS to return. As the border colour would constantly change during load, it would also mean repeated efforts at writing the code for the cheat, saving any further interceptions at this stage. What I also did, deliberately, was during re-instatement to increase the border colour instead of decrease. This meant, visually, I knew that the hack was working, and left it in.
The Initial Hack
So, once I had got that far, the code would look like this, and in effect, it would then be adding the data lines accordingly:
.C:0210 20 56 F5 JSR $F556 - load the initial loader code .C:0213 A9 20 LDA #$20 - amend instruction at $049F .C:0215 8D 9F 04 STA $049F to read JSR $0226 instead .C:0218 A9 26 LDA #$26 of DEC $D020 (decrease .C:021a 8D A0 04 STA $04A0 border colour) .C:021d A9 02 LDA #$02 .C:021f 8D A1 04 STA $04A1 .C:0222 60 RTS - go back to auto-start loader .C:0223 57 41 SRE $41,X - ASCII bytes, for protection .C:0225 5A NOOP .C:0226 EE 20 D0 INC $D020 - increase border colour .C:0229 – cheats go here with a RTS at the end to return back
If you are wondering what the three ASCII bytes are doing in there, it was a safeguard to see if the listing had been stolen. I would have a way of knowing and proving that was the case.
I was able to PEEK the values that had been set here, and these would form the initial DATA lines for the listing. So, it did not take long to concoct this. In case you are wondering why I went with loader v3, this was because the Burner loader and Visiload had preceded them, so was an easy way to identify it in my mind. And the REM statement in line 2 was just to re-iterate which game loaders it would cover, as when checking both, the loader code itself was the same, so made sense. The checksum basically adds all the values in the DATA statements for the main listing, and if it does not total 2673, that was a safeguard to prevent errors. The check for -1 means to end the POKEs being written and start the code in line 5.
0 REM MASTERTRONIC LOADER V3 MULTIHACKS 1 REM (C) WAZ 28/11/1991 2 REM FOR INVADE-A-LOAD, LOAD N PLAY, RACK IT 3 FOR WA=528 TO 552:READ Z:C=C+Z:POKE WA,Z:NEXT 4 IF C<>2673 THEN PRINT "ERROR!":END 5 READ Z:IF Z=-1 THEN POKE 157,128:SYS528 6 POKE WA,Z:WA=WA+1:GOTO 5 10 DATA 032,086,245,169,032,141,159,004 11 DATA 169,038,141,160,004,169,002,141 12 DATA 161,004,096,087,065,090,238,032 13 DATA 208
So, with that in mind, the fun part (sort of) – getting the individual data lines for the games together based on the POKE found for infinite lives, time and so on. Or was it? Not quite. I will explain why:
Expert Cruncher
As mentioned, many of the games that were mastered by this loading system were in fact frozen with a freezer cartridge, most likely upon inspection, Trilogic’s Expert Cartridge, although some others were compressed differently and they needed another routine, which we will come to later. Effectively, when the game loads, it points itself to where the executable routine for decrunching (aka decompressing) is, normally at $081B (so SYS 2075 if in BASIC.) One thing that the routine does do during its decrunch is that it cleverly uses the EOR instruction for exclusive OR, and uses EOR #$5D as its value to exclusively OR with – a neat way of deterring.
In effect, if you have a POKE which changes DEC $2000 (CE 00 20) to LDA $2000 (AD 00 20) (so nothing is decreased) by changing the first value, you would need to look for what the original instruction is after EOR #$5D is taking place. So:
$CE EOR $5D = $93 $00 EOR $5D = $5D $20 EOR $5D = $7D
Which means that when the game is almost loaded and prior to decrunch, I would freeze the game with my Action Replay cartridge, check the monitor, and would need to hunt down the bytes 93 5D 7D to see the original instruction. What you would want to do is change the first one to AD, but you would need to EOR #$5D to get the actual value. So:
$AD EOR $5D = F0
Using the game Beat-It as a further and real-world example, the original infinite lives POKE I made effectively changes the instruction DEC $CE0E (CE 0E CE) to LDA $CE0E (AD OE CE). Using EOR with #$5D meant that I was looking for the bytes 93 53 93, and so once I had found those in memory (at $0D9F) I would change the first byte to $F0 (as we know with EOR this becomes $AD as above) and then road test it. The data line would be
20 DATA 169,240,141,159,013,096,-1
The 169 and 240 is LDA #$F0 and the 141,159,013 is STA $0D9F (remember, lo/hi byte representation is used here), the 096 is RTS and the value -1 when read in the BASIC program means to stop POKEing bytes and start the loading routine off.
So, in effect, it was not just about finding out the POKEs needed for infinite lives, time, energy and so on, but translating that to the way that the decruncher worked so when decrunched, your amended value was used instead and thus would load with the cheats. But that was not quite the end of the story.
Double Crunch
Some of the games that were mastered with Invade-a-Load especially, such as Agent X II, used two forms of decompression, but both of which thankfully kept the machine code values as they were in the second decompression without the use of any EOR to contend with. However, there was at least a consistent pattern that happened with those.
In effect, the first decompression routine would have this instruction located at $093A:
$093A JMP $0810
This would call the routine at $0810 to perform its final decompression, so instead of doing a JMP to that, you would effectively change the bytes at $093B and $093C to go back to your code. As luck would have it, the first decompression routine did not touch anything under $0400 whatsoever, so our code at $0200 was left intact. Nice.
So, when added to the original hack code, this is how it looks at $0229 onwards:
.C:0229 A9 20 LDA #$34 - amend instruction at $093A .C:022B 8D 3B 09 STA $093B to read JMP $0234 instead .C:022E A9 26 LDA #$02 of JMP $0810 .C:0230 8D A0 04 STA $093c .C:0233 60 RTS - go back to loader .C:0234 – insert cheats here and end with JMP $0810
You would still need to check for the original instruction that contained your cheat, as it would be in a different memory location prior to starting the final decompression, but would be much easier to locate as you did not need to EOR anything as noted. This would mean that the DATA lines for this including the cheat when translated to decimal would look like this:
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,173,141,119,134 22 DATA 076,016,008,-1
For Agent X II, parts one and three would use the same routine. Part two was slightly different in that the first decompression call went to call $C000 instead, and on next compression then the instruction appears at $093A for JMP $0810. So, you need to redirect twice over:
.C:0229 A9 4C LDA #$4C - amend instruction at $08e6 .C:022b 8D E6 08 STA $08E6 to read JMP $0239 instead .C:022e A9 39 LDA #$39 of JSR $C000 .C:0230 8D E7 08 STA $08E7 .C:0233 A9 02 LDA #$02 .C:0235 8D E8 08 STA $08E8 .C:0238 60 RTS - go back to loader .C:0239 A9 46 LDA #$46 - amend instruction at $093A .C:023b 8D 3B 09 STA $093B to read JMP $0246 instead .C:023e A9 02 LDA #$02 of JMP $0810 .C:0240 8D 3C 09 STA $093C .C:0243 4C 00 C0 JMP $C000 - call first decompression .C:0246 A9 A5 LDA #$A5 - enter cheats .C:0248 8D 37 81 STA $8137 .C:024b 4C 10 08 JMP $0810 - go to final decompression
This would of course result in a longer set of DATA lines to reflect this:
20 DATA 169,076,141,230,008,169,057,141 21 DATA 231,008,169,002,141,232,008,060 22 DATA 169,070,141,059,009,169,002,141 23 DATA 060,009,096,169,165,141,055,129 24 DATA 076,016,008,-1
Unfortunately, some of the DATA lines that went in Zzap! 64 were published incorrect, which is why I am going to re-add them all at the end which have been fully re-tested and verified.
Thank Crunchie It’s Friday
And in some cases, there were either compression whatsoever, more so with some of the earlier Rack-It releases which used the same loader, or that they had a compressed routine that you could see the original code in that you needed to amend. This therefore meant a straight translation of the POKE used for infinite lives and so on or amending to suit where it was in the compressed code, and adding a relevant DATA line to set that. Much easier all told once the cheat itself had been found. Later Rack It releases tended to either use a different loader routine, or in the case of re-releases such as Sanxion and Shockway Rider, their original loader.
Listing and Original Published Data Lines
So here it is, in all its glory. Type in the master listing below and save it to tape or disk, ensuring you have done so carefully. Load back in as needed, add in the data lines for the game you wish to cheat on, and when you RUN, press play on the tape recorder to load in the game with your cheats. These have all been re-tested to ensure they work, and any incorrect DATA lines from its original appearance have been corrected.
As per usual, I have added extra zeros in front of any number under 100. This is so the DATA lines will align on screen correctly and make things easier to spot for you if you do make an error.
Reminder: The screen border will show different colours than normal. This is to show that the hack is working.
0 REM MASTERTRONIC LOADER V3 MULTIHACKS 1 REM (C) WAZ 28/11/1991 2 REM FOR INVADE-A-LOAD, LOAD N PLAY, RACK-IT 3 FOR WA=528 TO 552:READ Z:C=C+Z:POKE WA,Z:NEXT 4 IF C<>2673 THEN PRINT "ERROR!":END 5 READ Z:IF Z=-1 THEN POKE 157,128:SYS528 6 POKE WA,Z:WA=WA+1:GOTO 5 10 DATA 032,086,245,169,032,141,159,004 11 DATA 169,038,141,160,004,169,002,141 12 DATA 161,004,096,087,065,090,238,032 13 DATA 208
Invade-a-Load (Mastertronic) – Infinite Lives on the loading game
20 DATA 169,173,141,122,254,096,-1
Agent X II part 1 (Mastertronic) – Infinite Energy
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,173,141,119,134 22 DATA 076,016,008,-1
Agent X II part 2 (Mastertronic) – Infinite Lives
20 DATA 169,076,141,230,008,169,057,141 21 DATA 231,008,169,002,141,232,008,060 22 DATA 169,070,141,059,009,169,002,141 23 DATA 060,009,096,169,165,141,055,129 24 DATA 076,016,008,-1
Agent X II part 3 (Mastertronic) – Infinite Energy
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,000,141,192,049 22 DATA 076,016,008,-1
Anarchy (Rack-It) – Immunity and Infinite Time
20 DATA 169,000,141,202,032,169,096,141 21 DATA 103,031,096,-1
Battle Valley (Rack-It) – Infinite Ammo and Energy
20 DATA 169,000,141,067,050,141,046,058 21 DATA 169,165,141,171,058,096,-1
Beat It (Mastertronic) – Infinite Lives
20 DATA 169,240,141,159,013,096,-1
Knight Tyme (MAD) – Infinite Energy
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,000,141,039,023 22 DATA 076,016,008,-1
Motos (MAD) – Infinite Lives
20 DATA 169,093,141,092,097,096,-1
Night Racer (Mastertronic) – Computer Car Cannot Win
20 DATA 169,000,141,129,020,096,-1
Pulse Warrior (Mastertronic) – Infinite Lives
20 DATA 169,173,141,116,021,141,147,021 21 DATA 096,-1
Rollaround (Mastertronic) – Infinite Lives
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,240,141,060,122 22 DATA 076,027,008,-1
Scumball (Bulldog) – Infinite Lives
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,000,141,253,050 22 DATA 076,016,008,-1
Skate Rock Simulator (Ricochet) – Infinite Lives and Time
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,165,141,146,010 22 DATA 141,113,029,076,016,008,-1
Spore (Bulldog) – Infinite Energy
20 DATA 169,189,141,044,029,096,-1
Starlifter (Mastertronic) – Infinite Lives
20 DATA 169,248,141,113,024,096,-1
Stormbringer (MAD) – Infinite Energy
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,000,141,131,027 22 DATA 076,016,008,-1
Subterranea (Rack-It) – Infinite Lives
20 DATA 169,173,141,217,027,096,-1
Exclusive New Data Lines
But I did not want to stop there, oh no. How about some brand new, previously unpublished data lines, which increases the number of games available to cheat on from 16 to 25? Well, here you go, with some more for you – and there may be more to come too in future.
Bosconian 87 (Mastertronic / MAD) – Infinite Lives
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,173,141,077,032 22 DATA 076,016,008,-1
Energy Warrior (MAD X) – Infinite Energy
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,093,141,155,125 22 DATA 076,027,008,-1
Gaplus (Mastertronic) – Infinite Lives
20 DATA 169,032,141,141,010,169,057,141 21 DATA 142,010,169,002,141,143,010,096 22 DATA 169,076,141,064,009,169,073,141 23 DATA 065,009,169,002,141,066,009,096 24 DATA 169,173,141,153,101,076,028,008 25 DATA -1
Rockford (MAD X) – Infinite Lives and Time
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,165,141,217,151 22 DATA 141,151,129,141,254,143,141,225 23 DATA 151,076,016,008,-1
Scout (Mastertronic) – Infinite Lives
20 DATA 169,052,141,059,009,169,002,141 21 DATA 060,009,096,169,173,141,245,012 22 DATA 076,027,008,-1
Star Force Fighter (Mastertronic) – Infinite Lives
20 DATA 169,173,141,165,014,096,-1
Sunburst (Rack-It) – Infinite Lives
20 DATA 169,240,141,120,098,096,-1
Sweep! (Mastertronic) – Infinite Lives
20 DATA 169,173,141,031,098,096,-1
UCM: Ultimate Combat Mission (MAD) – Infinite Lives
20 DATA 169,189,141,052,027,096,-1
In Summary
So that was a long and detailed look at my first ever multihack, and one that I enjoyed doing. As you can imagine, the time was more spent with being able to find the POKEs for the game as well as being able to work out the compression methods used so I could get the DATA lines compiled. At the time there were some changes forthcoming to my life, but being able to still submit listings and POKEs to Commodore Format and have a regular income of some games (including one I should have kept) was very useful. I hope you enjoyed this look back.
Leave a Reply