Mastertronic Commodore 64 Invade-a-Load Multihack

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.

Please follow and like us:

Be the first to comment

Leave a Reply

Your email address will not be published.


*