Return of the Waz! Commodore Format’s Warren Pilkington is back, this time walking you through how he made one of his most loved listings. Waz takes it from here. 

Whenever I’m asked a question about the listing POKEs I contributed to Zzap!64 and Commodore Format, one question that comes up a lot was how I ended up writing a multihack listing POKE which covered over 140 different C64 games from publishers such as Codemasters, Mastertronic, Zeppelin, and other publishers who occasionally used the same loading system. With this in mind, I thought I’d go into the history behind its creation, and take a technical dive into its inner workings.

THE BEGINNING

1991 was quite a difficult year for me personally: the job I was working in was made redundant, and despite a small redundancy payout, it was difficult to purchase any games for the Commodore 64 as my priorities were, quite rightly, elsewhere. I was thankful at this time that some of the contributions I had made to Zzap!64 had earned me some software vouchers to buy games with, and I’d also managed to acquire some games from people who were moving on to other formats. Robin Hogg’s packages arriving in the post with games to hack also helped me keep focused and motivated.
When I sensed that Zzap!64 was about to go under with the collapse of Newsfield, they kindly published my address for readers who wanted to obtain POKEs for games or simply get in touch. Over time, some people didn’t just want a return letter with a listing POKE (printed out on my trusty Commodore MPS-803 printer), and also sent games for me to hack. Of course in those days, everyone sent and swapped packages by mail; that may seem like a slow process now, but that’s all we had (when I was a lad… – Ed).

In October 1991, someone sent a package which must have contained 30 or so Codemasters and Mastertronic games, along with a letter stating “You deserve a medal if you get through these!” As I began to play a considerable number of these games, complete with trusty Action Replay cartridge on hand, I saw a similar and recurring pattern; it was this that led me to create my first ever multihack for later Mastertronic releases that used either Invad-a-Load or Load-n-Play, both of which used the same loader. But what about those Codemasters games…?

bod_squad_gameplay
1992 arcade platformer The Bod Squad was a great looker but hard as nails. That wasn’t uncommon for budget games of the time. Fortunately, Waz’s hacks let everybody see even the toughest of games right to the end. Check the list at the end of this article for every game this hack works with (and yep, The Bod Squad is in there – Ed)

THE TECHNICAL BIT

The first thing to do when creating anything like a multihack is to determine which parts of the code are common across all games: if you’re going to intercept the game code and add your own code (which is essentially how listings work – Ed), you need to know where to safely place your code so that it remains constant. Analysis was key here because although much of the loading routine remained the same, there was the occasional slight variance here and there. In hindsight, of course, this would have been easier with an emulator and built in monitor, but back then it was a lot harder.

Generally, timing was key. For example, if the game had a loading screen, you normally had a window of opportunity of a few seconds where you were able to freeze the game, look at the loader code underneath, and then restart the game (which, in most cases, would continue to load). It also meant I could compare code from other games by loading a previously saved loader into a different part of memory to see if it was the same. Initially, I thought that a border colour change would be easy enough to intercept, but sometimes the memory location would change slightly. What was common was a routine at $0344 in memory, which held the machine code instruction BIT $DC0D. That memory location holds the status of interrupt timer 1, but crucially also the signal for input from the cassette port, so I knew that this was either loading in data or checking it. So, if I stashed the status of the accumulator and diverted the code elsewhere from that point, I could in theory put my own code in there.

So I simply needed to change the BIT $DC0D instruction to go to a free memory location, save the accumulator status using the PHA commend, enter the POKEs for the game, restore the accumulator status using the PLA commend, and restore the original instruction before jumping back (easy when you know how – Ed).

Essentially, the loader was behaving the same in terms of what it was supposed to do, but its code was being code intercepted at every single moment possible. Therefore, the POKEs would always be constantly applied during loading and I wouldn’t have to intercept any calls to start the game, making for better consistency across multiple games. I’d managed to get infinite lives on Poltergeist using the first part of hacking the code, so was pretty sure that the method should work elsewhere. Indeed, trying out a few more Codemasters games with the “freeze at the loading screen” trick appeared to work nicely.

THE AUTO-RUN BIT

You might have noticed that even if you type the word LOAD (instead of using the Shift and Run/Stop keys) the game’s loader automatically starts even if you don’t want it to. I can remember some older cheats in Zzap!64 which changed some of the registers (normally with POKE 43,255:LOAD) so that the code would report an error when it got to the auto start part, meaning you could effectively change what was needed at that point. A bit unwieldy, but it worked by simply changing the load address so that the computer didn’t see any free memory to run the code it had loaded (very clever – Ed).

Of course, for a listing POKE that method’s not going to work, so I needed to figure out what was going on. It was then when I realised some clever mastering trickery was at work: whenever you get to the point when the game is FOUND, a small amount of data is written to the cassette buffer and lower memory. The key here is locations $033D-$0340. These four bytes contain the hex values 9F 02 C0 03, which when translated into lo/hi bytes meant that the loader code was being loaded from $029F to $03C0 ($0341 onwards is the filename that has been found).

However, when that part of the code is loaded, it’s also overwriting some of the memory from $0300 onwards. Locations $0306 and $0307 store the address of the BASIC token decoder, which normally points to a memory location where the BASIC interpreter resides. However, these values are changed and instead point to $02A8, where there’s a bit of machine code that’s called before jumping to the main loader routine. As this area of memory is being written into, intercepting that routine is not so easy.

I went back to the old POKE 43,255:LOAD command and considered the values I’d found earlier; what if I changed the four bytes during FOUND to load the next part into a different memory location, so that $0306 and $0307 wouldn’t be overwritten? I changed the 02 and 03 to 10 and 11, primarily as I knew that the memory area above $1000 should be reasonably safe. As suspected, the next part loaded, but didn’t run. Excellent – now I could intercept the code properly!

cjloader
CJ’s Elephant Antics was one of the surprise late hits for the Commodore 64 in 1991. Kids took the elephant to heart, spawning a sequel and a clutch of other Codemasters games that looked a lot like it. Use Waz’s hack on this one too!

FINAL INTERCEPTION

So now I knew how to load the initial auto-run code elsewhere, a check of the newly-relocated code showed that it was just doing some bits of bumping and counting via a Kernal ROM routine, then setting the mode to direct mode and calling the loader’s routine at $0378. In fact, none of that was required at all, and the code could simply call $0378 directly when it was loaded correctly into memory. Basically, I needed to change the instruction I found earlier so that the code would be located at $1144 instead of $0344. Then once amended, I’d need to move the code from $109F-$11C0 back down to $029F where it was originally and call the loader at $0378 as per normal.

During initial testing, I’d also added an extra instruction to change the border colour, primarily so I could see if the code I’d added was working. I actually meant to take this out for the final listing in order to save three bytes and didn’t, but that wasn’t a bad thing as it was easier to see that the hack was working its magic. So next it was a case of getting the assembled routine together, with a pointer to add in where the data lines would go.

The master code ended up looking like this:

codemasters_mastercode

Location $0245 onwards is where the corresponding code for each game would reside, POKEing the relevant values for infinite lives, time, etc. before returning with RTS back to the loader.

CONSTRUCTING THE LISTING

Now that I had the master code as a proper piece of machine code, it was time to get the values needed for the BASIC listing (which would be read from DATA statements and POKEd into memory to form the code seen above). However, as this code resided at $0200 (which is overwritten when calling direct mode commands), I loaded the code into location $1000 and did this:

FOR WA=4096 TO 4164: ? PEEK (WA);:NEXT

This then gave me a nice on-screen view of the values in memory for the main data lines. As I normally did back then, I added zeroes in front of any number under 100, so the data lines would appear nice and neat:

10 DATA 032,044,247,056,169,016,141,062
11 DATA 003,169,017,141,064,003,032,108
12 DATA 245,169,032,141,068,017,169,057
13 DATA 141,069,017,169,002,141,070,017
14 DATA 162,255,189,193,016,157,193,002
15 DATA 202,208,247,162,033,189,159,016
16 DATA 157,159,002,202,208,247,076,120
17 DATA 003,072,206,032,208,032,069,002
18 DATA 104,044,013,220,096

It was then a case of constructing the rest of the listing so that the main part reads the initial DATA statements that would be POKEd from 512 to 580 and generate an error if the checksum value was incorrect. The additional DATA lines for each game would then have their code loaded from 581 to effectively translate whatever cheat POKEs were required into their machine code equivalent, and end with a -1 value to tell the program that the extra DATA lines had finished and it was time to call the routine to load the game.

0 REM CODEMASTERS MULTIHACK SIMULATOR
1 REM BY WARREN PILKINGTON
2 FOR WA=512 TO 580:READ Z:C=C+Z:POKE WA,Z:NEXT
3 IF C<>7483 THEN PRINT “DATA ERROR”:END
4 READ Z:IF Z=-1 THEN POKE 157,128:SYS 512
5 POKE WA,Z:WA=WA+1:GOTO 4

Line 2 is a simple FOR NEXT loop to read the data lines, and POKE the value into its memory location, using the variable C as a checksum (this is basically the sum total of all the numbers).

Line 3 then looks at the checksum to verify that you’ve typed the initial lines all correctly. If not an error stops you going any further.

Line 4 reads the values for the game-specific data lines (normally line 20 onwards as published). If it read -1, then you’d use POKE 157,128 (for direct mode, without this you would have code overwritten) and then use SYS 512 to run the code from memory location 512 ($0200 in hex).

If it didn’t read -1, then in Line 5 the value is POKED into the next memory location, the counter is increased by 1, and loops back to line 4 to read the next value.

Eagle-eyed readers will notice that in all my listings I used WA and Z for two for the variables, because when you had the POKE WA,Z command it virtually spelt out my handle of WAZ. It also meant that those unscrupulous scoundrels who copied my listings and sent them to other magazines would be easily identifiable! When it was published in Commodore Format, the variables were changed to be X and Y instead of WA and Z to keep the listing consistent with other listing POKEs in the magazine. I knew I’d be properly credited, but I do wish that Andy Roberts had left it in as it was (even though I did appreciate the reasoning!).

GIVE ME ALL THE DATA

Constructing the main listing was actually the easy part, and once I’d tried it on a few games with some DATA lines I’d created everything appeared to be working well. The bulk of the work was performed between October 1991 and March 1992, and luckily the massive bundle of games I mentioned earlier became ideal test material for the initial batch of testing.

Constructing the additional DATA lines was a multiple part process:

Load the game and find POKEs for infinite lives, time and so on (depending on the game this was typically the longest part of the process).

Convert those POKEs into machine code instructions (so for example POKE 8192,173 would be LDA #$AD, STA $2000).

Print a PEEK of the machine code instruction values (169, 173, 141, 000, 032).

Construct the DATA line using the PEEKs and add 096, -1 at the end of the final data line.

I’d then road test each set of data lines by adding the DATA lines to the master listing and then loading the game to ensure everything worked as intended. At first, the main focus was on Codemasters releases as I knew pretty much all of them used the same loading routine and mastering technique. The first release was 21st October 1991, around the time I’d switched over to contributing to Commodore Format. However, it very nearly went to Zzap!64 – as they say, timing is everything!

As well as games I’d been sent to hack, I also had numerous budget titles in my own collection, allowing me to take a batch of Mastertronic games, verify that the loader was the same, and construct additional DATA lines. Naturally, testing dozens of cassette games did take some time (thankfully I didn’t have to type in master listing each time, of course).

In some cases, typically when games appeared in compilations, the remastering seemed to affect portions of the code so that the games would load in different places compared to the original. This actually required new POKEs in these instances, as well as new DATA lines. A case in point here was Spellbound Dizzy, but thankfully I’d been sent the compilation release so I could check the differences and produce DATA lines for each version.

sleepwalkercover
Now here’s an underplayed game. Zeppelin’s version of Sleepwalker (not to be confused by the 1993 Ocean release) is a quirky outing that’s even more fun with these data lines.

APPEARANCES IN CF

The main listing and initial data lines went to Andy Roberts, and were first published in issue 23’s Gamebusters section. The next three issues, 24-26, contained the next three batches of data lines, all for Codemasters games. The Multihack continued in issues 28 and 29 with Mastertronic games, and in issue 30 with some Zeppelin and Hi-Tec titles (the culmination of months of additional effort. Find every issue of CF and see the work here).

It wasn’t the end of the data lines, though – far from it. Issue 32 saw several Zeppelin titles added to the list of data lines, and more games also featured in issue 37. The final batch appeared in issue 46, and included two Firebird games which, unusually, also used the same loader instead of their typical Bleepload loading system. There was one final appearance in issue 55, when the Multihack was re-branded as the Dizzy Hack for a shed load of Dizzy games.

Additionally, the Multihack also made an appearance on issue 51’s Power Pack, which Andy Roberts himself had kindly put together. It had a menu system which allowed you to easily select a game, check out the cheats available, and then press fire to load the game in question. It was great work by Andy, which also included graphics from Armalyte by Robin Levy and a music track called Crimson by Richard Rinn (Deek). There were 144 different games covered (see list below), which shows just what a mammoth effort it was.

EXCLUSIVE NEW DATA LINES!

But wait! There’s more! This article wouldn’t be complete without some brand new and exclusive data lines, which brings the total number of games covered to over 150. First off, here’s the master listing once again. Type it very carefully, save it, add the DATA lines you need for a particular game, then RUN the program. If successful, you’ll be asked to PRESS PLAY ON TAPE and you can then load the game with the relevant cheats. If you get an error, check your typing carefully.

0 REM CODEMASTERS MULTIHACK SIMULATOR
1 REM BY WARREN PILKINGTON
2 FOR WA=512 TO 580:READ Z:C=C+Z:POKE WA,Z:NEXT
3 IF C<>7483 THEN PRINT “DATA ERROR”:END
4 READ Z:IF Z=-1 THEN POKE 157,128:SYS 512
5 POKE WA,Z:WA=WA+1:GOTO 4
10 DATA 032,044,247,056,169,016,141,062
11 DATA 003,169,017,141,064,003,032,108
12 DATA 245,169,032,141,068,017,169,057
13 DATA 141,069,017,169,002,141,070,017
14 DATA 162,255,189,193,016,157,193,002
15 DATA 202,208,247,162,033,189,159,016
16 DATA 157,159,002,202,208,247,076,120
17 DATA 003,072,206,032,208,032,069,002
18 DATA 104,044,013,220,096

Cosmonut (Codemasters)
Infinite lives and energy
20 DATA 169,173,141,076,150,141,217,151
21 DATA 141,160,175,169,165,141,160,127
22 DATA 096,-1

Fruit Machine Simulator 2 (Codemasters)
Infinite credits
20 DATA 169,173,141,096,099,141,211,043
21 DATA 096,-1

Mean Machine (Codemasters)
Infinite lives and time
20 DATA 169,000,141,229,032,169,173,141
21 DATA 102,041,096,-1

Soccer Pinball (Codemasters)
Infinite balls player 1
20 DATA 169,173,141,041,075,096,-1

Tarzan Goes Ape (Codemasters)
Infinite lives
20 DATA 169,234,141,072,030,096,-1

Draconus (Zeppelin)
Infinite lives and flames
20 DATA 169,173,141,198,038,141,183,042
21 DATA 141,050,021,141,053,021,096,-1

Fist Fighter (Zeppelin)
Infinite energy player 1
20 DATA 169,173,141,192,161,096,-1

That was a long but hopefully enjoyable look into perhaps one of the most well-known listing POKEs in Commodore Format’s history, and one that, looking back, was a real sense of achievement at the time. I’m still always humbled by the fact I would occasionally get a thank you letter from gamers who had got frustrated with a game but had managed to get further due to the hack and data lines for games they were stuck on. In an age of when all mail wasn’t electronic, having those was a huge boost and really did help, more than perhaps anyone would ever suspect. CF

THE FULL LIST OF MULTIHACK GAMES

Out of the original 144 data lines, 72 are Codemasters, with 44 being Mastertronic and associated labels (MAD, Entertainment USA, Bulldog) and 18 Zeppelin titles. Clearly it was a very popular loading system, primarily due to its rock solid reliability, even if it wasn’t the quickest. But, if it isn’t broken, why try to fix it? In fact very few Codemasters games used a different loading system at all, aside from a handful of later titles where the game was double compressed and crunched with a utility cartridge (SAS Combat Simulator and Pro Powerboat Simulator are two that come to mind).

11-A-Side Soccer (Codemasters)
1985 (Mastertronic)
Action Biker (Mastertronic)
Advanced Pinball Simulator (Codemasters)
American 3D Pool (Zeppelin)
Arcade Flight Simulator (Codemasters)
Armourdillo (Codemasters)
Army Moves Part 1 (Imagine)
Army Moves Part 2 (Imagine)
Arnie (Zeppelin)
Arnie 2 (Zeppelin)
ATV Simulator (Codemasters)
Back To Reality (Mastertronic)
Ball Crazy (Mastertronic)
Bigfoot (Codemasters)
Big Mac (Mastertronic)
Big Nose’s American Adventure (Codemasters)
Bionic Ninja (Zeppelin)
Blinky’s Scary School (Zeppelin)
Blue Baron (Zeppelin)
BMX Freestyle (Codemasters)
BMX Racers (Mastertronic) (2nd version, not the 1st with the oil and grannies)
BMX Simulator (Codemasters)
BMX Simulator 2 (Codemasters)
BMX Trials (Mastertronic)
Bod Squad (Zeppelin)
Bubble Dizzy (Codemasters)
Bump Set Spike (Entertainment USA)
Cage Match (Entertainment USA)
Captain Dynamo (Codemasters)
The Captive (Mastertronic)
Championship Jetski (Codemasters)
Chiller (Mastertronic) (2nd version, not the first with the banned music)
CJ’s Elephant Antics (Codemasters)
CJ In the USA (Codemasters)
Countdown To Meltdown (MAD)
The Curse of Sherwood (Mastertronic)
Demons of Topaz (Firebird)
Destructo (Bulldog)
Dizzy (Codemasters)
Dizzy Down The Rapids (Codemasters)
Dizzy Panic (Codemasters)
Dizzy: Prince of the Yolkfolk (Codemasters)
DJ Puff’s Volcanic Capers (Codemasters)
Edd The Duck (Zeppelin)
Elite (Firebird)
Excaliba (Mastertronic)
F1 Tornado (Zeppelin)
Fantasy World Dizzy (Codemasters)
Fast Food (Codemasters)
Finders Keepers (Mastertronic)
Formula 1 Simulator (Mastertronic)
Frankenstein (Zeppelin)
Frankenstein Jnr (Codemasters)
Fruit Machine Simulator (Codemasters)
Game Over (Imagine)
Game Over 2 Part 1 (Imagine)
Game Over 2 Part 2 (Imagine)
Ghost Hunters (Codemasters)
Grand Prix Simulator (Codemasters)
Grand Prix Simulator 2 (Codemasters)
Guardian Angel (Codemasters)
Hero of the Golden Talisman (MAD)
Hollywood Or Bust (Mastertronic)
Human Race (Mastertronic)
Hunter Patrol (Mastertronic)
International Rugby Simulator (Codemasters)
IO (Zeppelin) (note, the Zeppelin re-release only)
Kamikaze (Codemasters)
Kane (Mastertronic)
KGB Superspy (Codemasters)
Kick Box Vigilante (Zeppelin)
Kikstart (Mastertronic)
Kikstart 2 (Mastertronic)
Kwik Snax (Codemasters)
The Last V8 (MAD)
Lazer Force (Codemasters)
Little Puff (Codemasters)
Los Angeles SWAT (Entertainment USA)
Magicland Dizzy (Codemasters)
Miami Chase (Codemasters)
Mig-29 (Codemasters)
Monte Carlo Casino (Codemasters)
Moto-X (Codemasters)
Mr Angry (Codemasters)
Murray Mouse Supercop (Codemasters)
Navy Moves Part 1 (Dinamic)
Navy Moves Part 2 (Dinamic)
Ninja Commando (Zeppelin)
Ninja Massacre (Codemasters)
Nonterraqueous (Mastertronic)
Olli and Lissa 3 (Codemasters)
One Man and His Droid (Mastertronic)
Panther (Entertainment USA)
Phileas Fogg’s Balloon Battles (Zeppelin)
POD (Mastertronic)
Poltergeist (Codemasters)
Prince Clumsy (Codemasters)
Pro BMX Simulator (Codemasters)
Pro Skateboard Simulator (Codemasters)
Pro Ski Simulator (Codemasters)
Pro Tennis Simulator (Codemasters)
Pub Trivia Simulator (Codemasters)
Q10 Tankbuster (Zeppelin)
The Race Against Time (Codemasters)
Rally Cross Simulator (Codemasters)
Rapid Fire (Mastertronic)
Red Max (Codemasters)
Revenge II (Mastertronic)
Seymour Goes To Hollywood (Codemasters)
Skyhigh Stuntman (Codemasters)
Skyjet (Mastertronic)
Sleepwalker (Zeppelin)
SOS (Mastertronic)
Space Hunter (Mastertronic)
Speed King (Mastertronic)
Spellbound (MAD)
Spellbound Dizzy (Codemasters) (the original and compilation versions had different data lines)
Spike In Transylvania (Codemasters)
Spooks (Mastertronic)
Stack Up (Zeppelin)
Starforce Nova (Mastertronic)
Street Surfer (Entertainment USA)
Stuntman Seymour (Codemasters)
Super G-Man (Codemasters)
Superhero (Codemasters)
Super Pipeline 2 (Mastertronic)
Super Robin Hood (Codemasters)
Super Seymour (Codemasters)
Super Stuntman (Codemasters)
Supertank (Codemasters)
Terra Cognita (Codemasters) (the original and Quattro versions needed different DATA lines)
Thunderbolt (Codemasters)
Tilt (Codemasters)
Treasure Island Dizzy (Codemasters) (the original and compilation versions needed different DATA lines)
Titanic Blinky (Zeppelin)
Vampire (Codemasters)
Video Meanies (Mastertronic)
Video Poker (Entertainment USA)
Voidrunner (Mastertronic)
Wacky Darts (Codemasters)
Wild West Seymour (Codemasters)
Wizard Willy (Codemasters)
Yogi Bear and the Greed Monster (Hi-Tec) CF