Articles posted May 2007 |
Good News/Bad News
Having recently touched all of the TMS34010-based games led me to start looking into some long-standing issues with some of the Williams/Midway Z/Y/X/Wolf-unit games. The first thing to do was to add save state support to them, because playing Revolution X more than once to get to the place where the video craps out is not for the faint of heart. This was relatively straightforward, and also had the side benefit of making some useful data available in the debugger (such as the local_videoram array and the dma_registers array).
Side note: any array or pointer you register with state_save_register_global_array/_pointer automatically becomes a viewable option in a memory window in the debugger. This is very handy if you need to expose any internal state.
Anyway, it turned out that the Revolution X bug was caused by over-aggressive masking in the blitter code. It was masking out one too many bits in the clipping window and this led to the right edge of the clip window being less than the left edge, effectively clipping out everything during the blit. Hence the black screen.
Save states also helped find the Rampage World Tour bug that led to a hang. It turns out that there was code that would read the incorrect status register in the blitter chip to see if it was done. The top bit is the important one, and happened to be 0 most of the time, so most of these incorrect checks happened to work. Occasionally, however, a certain blit would be issued that caused this bit to be set to 1, and then this check tended to fail and just hang indefinitely waiting for a phantom blit to finish.
Finally, I took a look at the Mortal Kombat 3 bug where the palette on the character selection screen or the intro screen is all wrong. This turns out to be a cycle counting issue. The code that builds up these screens sets up a queue of palette entries to change. Each character that is displayed has its own palette, so if there are a lot of characters, there are a lot of palette changes to queue. But palettes are only changed in the VBLANK routine, so it's possible for the queue to get too full, depending on how quickly the game accumulates entries in the queue. When it hits its limit, it fortunately doesn't corrupt memory (good), but instead throws everything out of the queue (bad), leaving you with a bunch of missed palette changes.
This queueing behavior is why the problem gets worse if you have unlocked a bunch of characters, because more characters are displayed on the screen, and thus more palettes get queued.
The reason this worked on a real machine is probably due to the TMS34010's cache. We don't emulate the cache behavior in MAME; rather, we act like all instructions are in the cache, and count the minimum number of cycles for each instruction. This is generally the right approach, but in this case it works against us because we allow the code that sets up the palette queues to run too fast, overflowing the queues before the VBLANK comes in and clears everything out.
So for now, we'll just have to live with it. The 34010 cache is described in gory detail in the manual, so it is possible to simulate it eventually. But for now, a little color glitch isn't going to hurt anything.