Pseudonym's Williams High Score Patches |
---|
Theory | |
|
There are many ways to approach such a patch.
Somewhere in the code there must be a routine which compares the player's score to the current high score table to determing where the score belongs in the list [we'll call this position x[. Next the code must compare the player's initials with the initials currently in the high score table, and discern where the player's 5th set of initials is in the table, [we'll call this position y]. [If the initials appear in the high score table fewer than 5 times y is just the end of table.] If x<=y then positions x to y-1 are moved to positions x+1 to y, and the current score is inserted at position x. Otherwise the new score is just discarded. Some of the obvious ways to approach the patch are as follows:
An important concern with any patch is to make as FEW changes to the code as possible, so that the checksums can be patched to ensure the ROM tests pass. Fixing the checksums in the checksum table is viable, but in most cases, this would require that more than 1 EPROM be reburned. It is preferable to patch the code such that some portion is never executed, and the vestigal code fragment can be munched to account for the changed checksums. After poking around with the robotron (orange/yellow) code, I chose to judiciously modify the initials compare routine, which allows the code to be patched [including checksum repairs] in just a handful of bytes. |
Method | |
|
At the request of Steve Zeuner, I started by looking at the Robotron roms. In robotron, the high scores are saved in a 4-bit battery backed ram. Since the memory accesses must be done 4 bits at a time, special routines are required to read from and write to the RAM.
In the Yellow-Orange romset, the read routine is at 0xD512:
The write routine is found at 0xD52B:
Well, that's all well and good, but how does that really help us? -- It doesn't. First of all, note that these routines aren't called directly, but are only accessed from JMPs in a subroutine vector table at 0xD000. [This is actually quite clever, programming-wise, since you don't need to update labels in other parts of the rom, and you can assemble 1 rom at a time.] Before we can do much more, we need to analyze the format of the high score table, to make it easier to find meaningful reads and writes. By playing the game and setting different scores, then dumping the ram, I was able to extract the following format:
Given the position of the initials for the top score [0xCD32], we can meaningfully search the code for references and analyze it. Searching the code, I found an apparently meaningul reference in a routine at 0xE830.
As you can see, we have some options in what to change here. We could increase the constant in the "LDA #$04" at 0xE837, but that would make the checksum difficult to patch, as it would leave no free code. It's easier just to patch the code to always return 0xFE, to signify few matches. to accomplish this, we make the following changes:
...and that's about it. We fire it up in MAME to test it, and the sixth and higher scores are saved happily. [In the included rom files, I patched the code in the initials compare routine at 0xE85B, but on futher reflection, it's easier to make the changes here, and requires changing only two bytes! All that work and analysis for such a simple change. Crazy, isn't it?] |
Notes on Other Games | |
|
The Robotron patches above were the basis for similar patches to Joust, Stargate, Bubbles, and Splat!. The routines to read/write to the NOVRAM were identical, as was the initals compare routine, other than the address where the current initials set was stored. Since I knew the high score tables were different I chose to make the code mods in in initials compare routine, so I wouldn't need to do the extra step of finding the instance counting routine.
Blaster was similar to Robotron, but had MANY more roms to search through. Additionally, Blaster users a 16-bit checksum instead of the 8 bit used by the earlier games, which made munging the bytes of unused code a littler trickier. Turkey Shoot uses a completely different structure than the other games and was a real pain to figure out. It has an 8-bit NOVRAM, so no special routines are neeed to access the high score table, so I had to once again map out the NOVRAM to determine the positions of certain elements of the high score table and search the code based on that information. To complicate things, the initial comparisons are not put into a separate routine, and are achieved with an 8 bit and a 16 bit compare, so the routine was difficult to locate. Although, I expected them to be similar to Turkey Shoot, as they run on the same hardware, Inferno, Joust 2, and Mysic marathon were code-wise very similar to Robotron.
Defender only saves 10 scores and will save all initials, so no patch is needed.
...and who cares about Lotto Fun anyway? |
Files | |
|
This is your last chance to avoid a guilty conscience! Stargate [ROM 11]
Joust (Solid Red) [ROM 5]
Robotron (Yellow/Orange) [ROM 11]
Bubbles (Blue) [ROM 11] Splat! [ROM 5] Blaster [ROM 3] Turkey Shoot [ROM 2] Inferno [ROM 18] Joust 2 [ROM 13] Mystic Marathon [ROM 17]
|