Monday, January 31, 2005

Chain reaction

It seems that whenever I look at a driver, I find something to fix in it
In this case, while looking at TNZS, I noticed that some games, e.g. Insector X and Plump Pop, were quite obviously running at 30 fps instead of the normal 60. This makes a lot of difference in the smoothness, strange that nobody ever noticed. Anyway, this was caused by missing support for sprite banking, a feature of the hardware which was already supported by seta.c (the games running in this driver use Seta custom chips). It's now fixed so Insector X looks better than ever :) The improved emulation also fixed the various gfx issues with Kabuki Z.

Sunday, January 30, 2005

Some bugs never die

Fascinating how some bugs have stayed with us for years, even if the solution was simple and obvious.

There had been two bugs plaguing emulation of The New Zealand Story:
  1. A hanging bug, which would make the game simply stop, while music was still playing. This happened randomly at some key points, typically the end of a level when you touched the cage. This was caused by a bug in the original program (a RET NZ instead of RET Z), which would cause no apparent problem on the real hardware, but could be deadly in MAME.
    This bug had been fixed for a long time, 0.91 contains a cleaner workaround but the behaviour is the same.
  2. A crashing bug, happening at different times in the three different versions of the game. For example, in the current main set, it would happen when the cannon-firing sheep was on the screen. This was caused by a known limitation in the MAME handling of banked ROM areas. It is not a big problem, and we know how to deal with it, and there was code in the driver to do that. Unfortunately, the code was copying the wrong data! It has been like this forever, and nobody ever noticed. But at last it has been discovered, so I can promise you, from 0.91u2 TNZS will no longer crash :)

Saturday, January 29, 2005

Kram is working!

I have finished the manual decryption. By that I mean that I made tables that list all addresses of encrypted instructions, and what to replace them with. The total number of entries in the tables is 7926. This is not an optimal solution but since I doubt I will manage to understand the algorithm it's the only thing I can do.

An interested thing I found out when hooking up the tables in the driver is that for two-byte opcodes, only the first byte is encrypted, the second is unencrypted. This wasn't the case with the Konami-1 CPU, where both bytes are encrypted. Odd.

Reaching a brick wall

No progress on the Kram encryption algorithm. Changing even a single bit of the address changes the result in an unpredictable way. At this point I'm doubting that I'll be able to derive the algorithm.

Manual decryption of the game, instead, is proceeding. I'm at about 80%, I think. The service menus are working, while the game is still booting to a black screen.

Friday, January 28, 2005

Kram hurdles

Looking for "good" keys didn't work, there are no bit permutations that show noticeably better applicability than others, the only thing I found is that a 0x22 final xor is significantly more common, which is good on one side, but not that good on the other side because it cannot be the ONLY xor - there must be others.

The manual decryption by comparison with the other sets is almost complete, CPU #2 is 100% while CPU #1 is maybe 75%. The code is different in a few places because this version doesn't have the MCU, and actually there seems to be a large chunk of code in the encrypted version that isn't in the others, so I might not be able to do a complete decryption if I don't break the encryption algorithm.

One interesting thing to note is that the code has been reassembled with a different assembler, which generates different (but equivalent) instructions in some cases. Here is an example:

not encrypted version:

D08D: CE B8 D3      LDU   #$B8D3
D090: EC 84 LDD ,X
D092: 81 29 CMPA #$29
encrypted version:

D082: CE B8 D3      LDU   #$B8D3
D085: EC 00 LDD $0000,X
D087: 81 29 CMPA #$29
the middle instruction does the same thing but with a different opcode.

Yesterday I verified that bytes at the same address are decrypted in the same way, and that in that case changing one bit in the encrypted value changes one bit in the decrypted value. Tomorrow I will try pairs of addresses only differing by one bit, and see if there is a similar regularity. From what I could see, however, I'm not very optimistic.

Wednesday, January 26, 2005

Kram progress

My intuition was right: the two Kram CPUs use the same encryption. Every time there is the same encrypted value at the same address in the two CPUs, it decrypts to the same value.

Not only that but, at a given address, if N bits change in the encrypted value, then N bits change in the decrypted value. This proves that the encryption consists of a bitswap and a xor.


That was the good news. The bad news is that the encryption changes with the address, and there isn't much data to analyze. For most addresses I have only one encrypted-decrypted pair, for a few I have two. There is no way to obtain more than what I have without physical access to the CPU.


Of course, since for now we have to assume that the encryption consists of a free bitswap + free xor, this means that given a single pair it could be decrypted correctly with any of 8! = 8*7*6*5*4*3*2*1 = 40320 different keys: just pick any of the 8! possible permutations of the bits, and then select the 8-bit xor that fixes the result.


What I need to do now is try to figure out the relation between address and key, which isn't obvious at the moment. The total possible keys are 8! * 2^8 = 10321920, which isn't too much. What I plan to do is check how many values are decrypted correctly by each one of them (or better, by a subset of them). If we are lucky, some keys will show a significantly better success rate, meaning they are "good" ones. If we are not lucky, it will mean that bitswap and xor are independently affected by the address.


Kram encryption

And of course, another still unsolved issue with the Qix driver is the encrypted version of Kram.


This is unusual because it's possibly the only time that Taito used encryption instead of MCU protection (off the top of my head, I can't think of any other encrypted Taito game). It is also a rare example of an encrypted 6809 game - again, the only other 6809 encrypted games that come to mind are the ones using the Konami-1 CPU.


I had looked at this encryption other times in the past, with no success. There probably isn't enough data to figure it out, but comparison with the other version of Kram will at least be enough to decrypt it, even if it will mean using a large hardcoded table - and who knows, in the process I might discover something new.


The encryption only works on opcodes, leaving data decrypted, which is good because you can easily align code from the encrypted and unencrypted versions of the game. Unlike the 68000, where everything that is fetched in the process of executing an instruction (plus PC-relative indirect memory accesess) is considered program space, and only memory accesses caused by an instuuction are considered data space, in the 6809 only the first byte of an instruction (the opcode itself) is encrypted, while the other bytes of a multibyte instruction are left unencrypted. This means that when comparing encrypted and decrypted blocks of code you have plenty of reference to align them perfectly.


The encrypted version of Kram should actually be almost identical to the other two, minus the MCU handling which isn't present in that version since it was protected in another way (Sega, anyone?). I should be able to do most of the decryption automatically and fill a couple of holes manually in the places that are different. Since both 6809 are encrypted, my hope is that they use the same encryption, so I might discover something more about it by comparing encrypted bytes at the same address on the two CPUs.

Fix one thing, discover another

Electric Yo-Yo was easy to fix, it was crashing because of a synchronization issue between the two CPUs - increasing interleaving fixed the problem.


Looking at the schematics surely was interesting, for example I discovered that the video ROM bank latch (which is a late addition only present in Zookeeper) is mapped on a mirror address of the diagnostic LED / palette bank latch. This explains why they oddly mapped the ROM banking bit on data bit 2, instead of the more obvious bit 0. That's because bits 0 and 1 are the ones that control the palette bank, and since the ROM bank latch is at a mirror address of the palette bank latch, whenver the former is written to, the latter is affected as well. So whenever the game wants to set the ROM bank, it also copies the palette bank in bits 0 and 1 to avoid unwanted side effects.

Tuesday, January 25, 2005

Memories...

I'm looking at the good old Qix driver at the moment. This was one of the first drivers in MAME, and at the time it seemed really complex, with its three CPUs and the need to synchronize them with a certain degree of accuracy.

The driver is already very well written and documented, but I'm checking the schematics again to verify that everything is correct, then I'll try to fix the Electric Yo-Yo hang during attract mode.