In Warren Pilkington’s latest long read for Commodore Format, the former Gamebuster finds something amiss in one of the ’90s most treasured games and sets about sorting things out. Waz […]
In Warren Pilkington’s latest long read for Commodore Format, the former Gamebuster finds something amiss in one of the ’90s most treasured games and sets about sorting things out. Waz takes it from here…
Mayhem in Monsterland should need no introduction to any Commodore 64 owning gamer in the 1990s. Released in 1993 by Apex Computer Productions, it was a definite final swansong of commercial game releases at the time for the C64, and had full screen full scrolling levels, masses of colour, and the sad and happy level plots gave you different obstacles and enemies to overcome whilst always being enjoyable and playable. John and Steve Rowlands along with Andy Roberts deserve full credit for the effort they put into this game, and for me it is still one I enjoy playing today.
At the time of course, there was the now infamous Commodore Format review, which gave the game 100%. Although I can understand the reasoning behind it, in terms of urging readers to part with their hard-earned cash and send off their orders to Apex, I personally didn’t feel comfortable with that rating, as 100% should be reserved for perfection. I definitely would give it mid to high 90s though for definite, although there’s actually one main reason that I couldn’t give this game 100%. And that’s the bug I found when playing the game, which became one of the most infamous game bugs for its time.
During the game’s production, I read the development diaries in Commodore Format diaries and spoke to Andy Roberts often about the game’s production when on the phone to him discussing the latest listing POKEs I was submitting to the Gamebusters section, I knew that a lot of hard work had gone in. I had of course planned to put an order in, but Andy very kindly negotiated with Apex so as a little reward for my CF contributions, they had agreed to sell me the game at half price – which was very fair of them.
DISCOVERING THE BUG
The game arrived on disk to my house, and it all looked and played as good as it did in the review. It certainly was enjoyable and I can remember the evening I had it delivered and switching the C64 on, I got a good few hours’ worth of play in whilst I got used to the controls and the way that when you picked up the lightning bolt on the happy level of Jellyland, how useful it was to be able to charge into the enemies and pick up the stars and valuable points, which is what you needed to complete the level.
It was during one session of play that I felt pretty chuffed that I had made it onwards to the second level, Pipeland. It was then that I discovered that something was amiss. I had made it to Pipeland with 10 lives, and was pleased that I had done so well. I then whilst attempting to get one of the stars in the sad level missed the jump and fell to some impending doom. I was expecting to go down to 9 lives, still plenty of course to be able to get through as much of the level as I could. But no! It said zero lives, and therefore had to be pretty careful or else it was game over. Granted, I could use a continue, but still, that was not pleasing.
At first, I thought that it was a possible disk loading error, so just to be sure, I played the game from the start from a fresh load. I played through the first level, doing even better than last time and having 10 lives still to play with. Then, I deliberately lost a life to see what would happen. And it went to 0. Something was amiss here. As Andy Roberts had admitted later on, it was because the three of them were so good at the game by the time it was released, they never got to the point where they would lose a life at 10 lives (or 20, going down to 19 for example) so as such, it wasn’t obvious on play unless you happened to be playing the game more for the first time and encountered that lives loss.
I must admit I did feel a little crestfallen, and for that reason alone, I couldn’t possibly agree with the infamous 100% review. However, I was not to be deterred and as one customer services course had taught me, it is always better to state a problem if you have a solution (or at least an idea of one) – so it was time to head out with the Action Replay cartridge in tow, and start examining the code to see what was happening and if I could fix the bug – then concocting a listing for the disk version, passing on all the info to Andy so he could get Martin Pugh (another CF Gamebuster – Ed) to do the same for the tape version.
EXAMINING THE CODE
I knew that the lives counter must have been stored in two different bytes in memory, as normally subtracting one from ten if held in a single byte of memory would have easily gone down to nine. Based on the score display, I could see that the lives counter had 03, 04 etc, assuming that if you got to more than 10 you could rack up the extra lives for the trickier later levels. Since then, I’ve seen the game completed with 25+ lives remaining, so you can understand what would happen.
I let the game load all the way to the title page, and thought it was a sensible time to freeze the game and see what was going on. The first thing was to either find the lives counter, or get infinite lives, either way would be useful (I’d obviously utilise the latter in a later listing POKE.) So, I looked for anything that loaded the number 3 into memory, as you started with 3 lives. And found this code at $3E72, which was self-explanatory:
So, the screen was being set to black ($D021 = 53281) and locations $CF81 and $CF82 were set to the number of lives. To test this out, I changed the 03 here to 09, but that didn’t work, even though it may have done. However, a further check of memory also saw this at $E545:
I changed the original instruction back to 03, and changed the one here to 09, and started the game. 9 lives. So it was the correct counter after all. I was in business.
That also meant I knew where to look in terms of being able to find what was happening with the lives counter, both for infinite lives when I went to write a listing POKE, but also to see what happened if you went down from 10 to 09. So, if $CF82 was being subtracted in any way, I needed to see what was happening.
It didn’t take me long to find the instruction I needed to subtract the lives from $CF82 (which of course I could change if I wanted infinite lives) and the code was here at $BDC6 onwards:
So, if I wanted to have infinite lives, easy, I change the 01 in the SBC #$01 instruction to 00, so it doesn’t subtract any lives, and job done. Infinite lives would be mine.
FIXING THE BUG
I noted also that both bytes of the lives counter are referenced. So, if you had 3 lives, it would reduce by 1 and check if any carry was set – if so, store the new value in $CF82. If the carry was cleared (because the value was set below 0) then subtract from the left-hand lives counter value in $CF81, and then… ah. Surely, you’d want to then set $CF82 to 9 instead of 0, so going from 10 to 09 would work wouldn’t it?
I extracted the code out and relocated it to $1000, with the game reset, to do various tests, and constructed a bit of BASIC to do this – note 53122 and 53122 are decimal for $CF81 and $CF82 in hexadecimal.
10 A=1:B=0: C=53121: D=53122
20 POKE C,A:POKE D,B
30 SYS 4096
40 PRINT PEEK (C);PEEK(D)
Doing a RUN showed 0 0 which meant that if you had 10 lives, it went down to 0. Changing line 10 so A was set to 2 showed it went down from 20 to 10 lives.
I then modified the code so that the LDA #$00 STA $CF82 command was set to LDA #$09 instead. I ran the BASIC program above. This time I got 0 9 which is what we want. The below shows the BASIC, and the two RUNs with me changing the instruction in the machine code in between.
So back to the game, I loaded it back up, and at the title screen, made the modification at $BDD1 in the Action Replay monitor to read LDA #$09:
I then restarted the game. And played it well enough to get to 10 lives, and then deliberately lost one. And badabing! It went back to 9 lives. I lost another one just to be sure it went back to 8, and it did. So at least for those with an Action Replay cartridge, you could convert $BDD2 back to decimal and so the POKE would be this:
(for those of you who don’t know, in the Action Replay freeze menu, E allows you to enter the POKE as above, then you can restart the game.)
CHECKING AND CONSTRUCTING THE LISTING POKE
One thing was for sure though: I would need to create a listing POKE for those users who don’t have an Action Replay cartridge but would still want to play the game properly, and not feel cheated if they got to 10 lives and lost a life. In theory, the game should be loaded, and you would then set the location as needed, and off you went, right? Well, almost.
What I did notice was that when dissecting the disk loader and the way that the game was loaded, the loading routine would be loaded first, and this would load the introduction sequence. Once this was loaded, you would then see that there was some code to load the main part of the game up to the copy protection sequence, and at this point, the memory location for the byte I needed to fix for the lives bug was set.
I froze the game during the introductory sequence and found that the code loaded the main part, and then was going to do a JMP $0180 to go into the main game, which was what I needed to intercept to put the POKE in. However, that code was already there in the intro sequence ready to go to $0180, moved down from $5700 to $0180 before the game loaded. Note what I saw here:
So, in effect the game data would load, and then be relocated upwards in memory, so whatever was in $A800 would be stored in $FF00, $A700 would be stored in $FE00 and so on. Now, because the original code starts at $BDC1, with the location needed to be changed at $BDD2, that location would actually load at $66D2 instead. To prove this, I changed the JMP $0180 instruction to jump back to itself (this was at $54FC), let the rest of the game load, and at the black screen, froze the game. Here’s what I saw:
Exactly as I thought! So, all I needed now was to construct a bit of machine code that did the following:
⦁ Load the file marked “2” from the disk side A (this was similar to the way the small fix for Retrograde allowed Oceanic drives to load the game)
⦁ Change the code in the initial loader to divert back to my code before the intro sequence runs
⦁ Change the code that called JMP $0180 to divert back to my code before the game shows the protection screen
⦁ Modify $66C2 with the value of 09 and then JMP $0180 to start the game.
I knew that in effect $C500 upwards in memory wasn’t touched until the game loaded the protection screen and moved the code around, so wrote the following code:
In case you’re wondering what the bytes at $C523-$C525 are about, work out what the ASCII equivalents are for those characters. Just a little something I added in case someone decided to copy the listing and give themselves false credit.
I then translated that code into the following listing – this was my original:
0 REM MAYHEM LIVES BUG FIXER BY WAZ
1 REM ZAW PRODUCTION #31D FOR APEX!
3 IFC<>7599 THEN PRINT”ERROR!”:END
4 PRINT CHR$(147);”INSERT MAYHEM DISK SIDE A AND HIT A KEY”
10 DATA 169,001,168,162,008,032,186,255
11 DATA 169,001,162,051,160,197,032,189
12 DATA 255,169,000,032,213,255,169,038
13 DATA 141,043,195,169,197,141,044,195
14 DATA 076,064,194,087,065,090,169,052
15 DATA 141,253,084,169,197,141,254,084
16 DATA 076,237,082,050,169,009,141,210
17 DATA 102,076,128,001
And yes, due to my C64 demo group being Zaw Productions, and being like Factory Records in that everything I did to a degree was part of its discography, I had already allocated this ZAW #31D in what I then called the “Zawography” (ZAW #31A and ZAW #31B were the actual cheat listings for the tape and disk versions I did later on, ZAW #31C would have been the fix for the cassette version if I did one, but Martin Pugh would sort that, so I didn’t need to do that myself)
I then posted a disk off to Andy Roberts with the disk fix listing, and it was appreciated that not only had I reported the bug, but also had the common sense to go and track down a solution and make it happen. Andy was able to pass on all the information on to Martin Pugh, and the cassette version of the same bug fix happened. Both listings would eventually appear in issue 45 of Commodore Format in Andy’s Gamebusters section, but Apex also pulled off the very wise move of shipping out a printed copy of the listing for those who then purchased the game, so they could enter the listing themselves and not have their enjoyment spoiled otherwise.
When Mayhem in Monsterland was re-issued by Psytronik, first for its 15th anniversary and then 25th anniversary editions, Jason Mackenzie (Psytronik head honcho – Ed) very sensibly had the lives bug fixed by Jon Wells (in a similar way I had done) so that when the game was remastered with a new introduction screen, showing Mayhem in C64 form like the original game’s artwork, it was all present and correct, and didn’t need to have the handiwork on to fix the lives bug. I must admit it was nice seeing it given due love and attention, and showed just what an impact the game had back then, and still does now. It’s almost gone down in folklore because of the controversial review but just as much for the lives bug. Hopefully you’ll see it wasn’t too difficult to spot and fix. CF