Holy shit. Our entire SPC7110 emulation is substantially wrong in so many, many ways ... this is the most poorly emulated of coprocessor of all at this point, even beating out the terrible SA-1 knowledge.
http://byuu.org/temp/spc7110-mmio.txt
http://byuu.org/temp/spc7110-mcu.txt (updated slightly)
Where do I even begin ... well, notes are below.
nocash, if you'd like to work with me on reverse engineering this more (now, or sometime in the future), feel free to reach me on IRC or somewhere else, and I can run hardware tests that you request and see what happens.
Decompression Unit
$480b.d1 does not select between "0 = stream unmodified data ROM data; 1 = stream decompressed data ROM data." As far as I can tell, it has no effect. At least, not on my sample decompression.
$480b.d0, however ... wow. Complete mindfuck here. When this bit is set (eg $480b = #$01 or #$03), then $4807 has radical effects on the decompressed output.
I posted the tables of various values of $4807 in the mmio.txt file to show what effects it has on the sample decompressed output. I tried to replicate it under emulation through various means (add it to table address index, increment the data ROM read offset by $4807 instead of by 1, etc) to no avail. It ... almost looks like higher values 'compacts' the data more, but ... not quite. It's absolutely screwy. I could **really** use some help here. My worst fear is that this isn't a simple change in the decompression engine, and that there's a lot of additional functionality that we don't yet emulate. That algorithm was absolutely brutal even for neviksti to figure out.
I've also confirmed there's nothing special about $50:xxxx. It's a big literal mirror of $4800. Nothing more, nothing less.
The DCU status register ($480c) is substantially complex. I've been able to set and clear d0, d1, d2, d4 and d7 bits in it with various parameters. What's most wild is that it seems to start with d7 clear, then after a while d7 gets set forever, until you start a new DMA or read one byte MORE than you set for the compression length. Almost like it forces the chip to start decompressing again? And as we already knew, there's substantial waiting periods that increase more and more when you set a larger index into the decompressed data output (the chip has to decompress up to 64KB before it can start giving valid output.)
The data ROM read address is affected by $4834 (but not by $4830-4833.)
Data ROM read unit
First of all, the unlocking stuff is bullshit. It was a really awful guess to pass the SPC7110 first-boot self-test.
Basically, after power on, if you read from $4810 or $481a before writing to either $4813 or $4818, it returns 0x00.
All subsequent reads work as expected. Even without ever writing to any registers.
$4813/$4818 writes fill in the buffer, and reads from the buffer cause the SPC7110 to fetch the next byte then.
Much worse, however, is that absolutely nothing I try will allow me to read from $481a. The SPC7110 self-test does so, and ends up reading two different values from the port. I mimicked all SPC7110 register writes and reads just like my FEoEZ does, and all I ever get is 0x00.
Also, I really hate $4818.d5-d6, it feels like we are emulating two unique settings packed into one. And we still need to find out what happens if you force modes 3-255. Harder to do since I can't modify the data ROM, so we'll have to pick an arbitrary spot to start decoding against.
The data ROM read address is affected by $4834 (but not by $4830-4833.)
ALU
So there are very, very short delays before MUL/DIV results are valid. The delay length is constant (doesn't short-circuit for easier values, at least as far as my limited testing can tell.) I can't really get exact cycle counts because it completes too fast (1-2 instructions for MUL, 2-3 for DIV.) Reading early gives you pre-computed values. We *may* be able to reverse the algorithm this way, but ... fuck will that be annoying. It was hard enough for the SNES CPU.
d0 of $482f (ALU status register) returns 1 if the last operation was a multiply, and 0 if it was a division. Nifty.
At least our division by zero emulation was correct.
$482e resetting all the registers was complete nonsense. It does no such thing. The only thing that register is for is for setting the signed mul/div mode.
Side note: nocash, -0x80000000 / -1 = $4828[00 00 00 80; 00 00; 01 00] {482e=1}. Nothing unusual there.
MCU
Nothing more than I've already found here. Still can't get $4830.d0-2 to do anything useful.
I did verify that even with non-zero data read from $4800 and $4810, when you read from data ROM address 0x400000+ with $4834.d0-2 = #$00-#$02 (eg not #$03), it still always returns 0x00. Same for the empty bits in registers. There doesn't appear to be an exposed MDR for the SPC7110.
RTC
This thing has a whole ton of commands I don't yet support. But I see you've already realized that yourself. Curious how you verified exactly what type of RTC it was? Does it say it on the PCB or something? Some of the functionality of that chip will be nigh impossible to properly emulate ...
EDIT: okay, it's a separate chip entirely with a nice part marking, neat.
Can I ask where you got your data sheet from? The one I found is much less verbose.
I went ahead and emulated all of the chip functionality.
I do have some additional questions that I'm hoping you'll know (or the doc will say.)
1. you list WRAP for minute, hour, day, month, day of week. But if I set all of those bits to 1 (and clear them all on CE=low of course), it breaks the FEoEZ self-test sequence. Only doing it for minute alone works as expected.
2. might be easier to understand if you list the duty cycle as 1/128th a second to match the first rate setting's description as 1/64th. Easy enough to figure out.
3. say you set an hour IRQ, does the bit get set when the hour counter is incremented in R4-R5? Or does it do it an hour after IRQs are enabled? Or does it do it every hour after the cart was powered on, or possibly after CE is set to high?
4. will the IRQ still fire if the chip is in stop, hold or reset?
5. what is the difference between stop and hold?
6. is Epson completely silent about the test register? If it's not too screwy, maybe I'll have to stab at that one myself ...
7. are the RTC regs cached on CE=low, or are they real-time values? That you say you have to bail out when wrap is set suggests the former ... but that seems wasteful to have all that extra RAM.
8. how does wrapping of bad values work? Eg we can test if(++seconds >= 60) minute(); or if((seconds %= 60) == 0) minute(); You mention that time/date can be corrupted on changing AM/PM ... is that from the manual? Any details on how it can be corrupted?
9. there is $4840.d1 ... I wonder what that bit is used for. Boy I sure hope it's another RTC stop bit </sarcasm>
10. I don't think our $4842.d7 flag is good enough. It's locking up on rare occasion when I support an actual delay for clearing the flag. I will have to test that further.
Looks like the start date is limited to 1995-2014. Guess we better get the game translated before then, huh? :P
MMIO
In general, the CPU MDR doesn't fill in the empty bits of MMIO regs either. They're always zero no matter what.
But there are registers the SPC7110 doesn't respond to at all. Those return the CPU MDR.
And there's no other mirroring other than the repeat in banks $00-3f|80-bf. It's only in $4800-4842.
There's a slight persistence to the registers even across power cycles.
It's possible to fail out the self-boot test with rapid power cycles (obviously once you pass the test once it never runs again, until you wipe the SRAM.)