Splat! Patches

Back in 1995 I was given a copy of the ROM image for the unreleased Williams game Splat! I was told that the game used the 2nd version of the Special Chips, but no one was sure what the differences were. I burned a copy into EPROMs and put it in my Joust machine and got the normal rug RAM test, followed by corrupt graphics. But there was a pattern to the corruption, and disassembling the ROM image pointed out the difference: where Special Chip 1 required the width and height written to the chip to be XORed with 4, Special Chip 2 did not. So I created a patch that consisted of 2 subroutines: the first XORed the A and B registers with 4, wrote them to the width/height register, XORed them again to restore their original values, then returned. The second was used in a few places where only the width register was written, so it just XORed, wrote, and restored the A register.

This enabled the Splat! ROM images to run using Special Chip 1, but added several cycles per blit for the patch. So I built a circuit to XOR the bits without any patches necessary, and included that in the multigames I built.

Fast forward 20 (!) years, and I get an email asking about the patch. Someone had downloaded pre-patched Splat! ROM images from a web site, but when they played the game, objects were leaving pixels on the screen. I had never seen that before, but hadn't run the patched version of Splat! since I built the first hardware hack. I downloaded the patched ROMs, and noticed that they were definitely based on my patch, but were slightly different. Instead of XORing the A and B registers with 4 a second time to restore them, the code pushed A and B on the stack, wrote them to the width/height register, then pulled them back off the stack and returned. In addition, they also pushed and pulled the CPU condition codes. This is safer than my code, since if the code that was patched used any of the condition codes, they would be set differently after my patch ran. So I checked each location in the code that called my patches, and none of them used the condition codes. Usually, right after the patch returned, the next statement loaded the B register with more data to be written to the blitter, wiping out the previous condition codes anyway. But the pushes and pulls added even more cycles to the patches, which might have been causing the pixel garbage.

My first thought was to patch all the width and height data once, instead of patching it as it was written to the registers. So I looked at all the places the width/height registers were written. Sometimes the data was loaded into the A and B registers immediately before writing it to the blitter, so those would be easy to patch. In other cases, the data was read from memory, usually using an indexed instruction. Those would be a little more difficult to patch, but using MAME to help would make it possible. But when I looked harder at the code, I noticed that it sometimes used the width data after writing it to the blitter register; that was the reason I had to restore the data in my patch. If I XORed all the data beforehand, then when the data was used by that other code, it would have those bits flipped, and wouldn't be correct. For example, 00 was in some cases used to indicate the end of data; but 00 would be patched as 04 (and vice versa) messing up that code.

Even though my subroutine always restored the A and B registers, they weren't always used again. Many times, the B register was immediately loaded with data, so there was no reason to restore it. And sometimes the data in the A register was not used again, either. So I created a total of 7 subroutines to account for all the different possibilities. That way, each patch would add the fewest number of additional cycles possible. I also patched the data that was directly loaded into the A and B registers, instead of calling a patch subroutine, unless that data was later used again.

I tested the code in MAME and it seemed to work fine, so I emailed it to the guy who asked me about it. He burned it into EPROMs, and it worked, with no pixel garbage. I later burned 3 sets of ROM images for testing on my multigame: my original patch, my new optimized patch, and the patched ROMs from the other web site. I played each of these and compared them to the unpatched ROMs using my hardware hack. In all, I was surprised at how well all the patched games played. I remembered seeing slowdowns that affected game play, but those weren't very evident now. I can tell the difference, especially in the later waves, but the patched versions aren't too bad. I do get higher scores with the patched ROMs from the other web site, and much lower scores with the unpatched ROMs, since the patches slow down game play, and give me more time to react. I did not see the pixel garbage with any of the ROM images, though.

back to Arcade Game Info page

back to Home page