Cx4, ROM, SRAM, SD2SNES and saved states

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224255)
Hi =^-^= I make the practice ROMs for the SNES Rockman X games. They add features like giving you the appropriate items for the route when selecting stages, and importantly, adding saved states.

With X2 and X3, the practice ROM can of course only run flash carts that have a way to support Cx4 games. SD2SNES supports up to 256 kilobytes of SRAM, which is enough to store a SNES saved state.

X2 and X3 put their NMI handlers into WRAM instead of ROM. Is this because the Cx4 locks out the 65816 from ROM access sometimes?

I need to add a considerable amount of code to the NMI handler for the saved state system. If the Cx4 locks out ROM, can I put my extra NMI code into SRAM instead? Because there are no native Cx4 games with SRAM, whether SRAM gets locked out while the Cx4 is locking out ROM is entirely defined by the SD2SNES, as the only cartridge that supports Cx4 with SRAM. I don't know how to determine whether the SD2SNES locks out SRAM like this, though.

Finally, how could I save and restore the state of the Cx4 in my saved state system?
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224258)
The Cx4 locks out both ROM and SRAM whenever it's accessing either of them. Most of the time it's either running code from its internal cache or not running at all, but otherwise it claims the cartridge bus when caching a new code page, performing DMA, or reading/writing individual ROM/RAM addresses.

ikari_01 put a bunch of relatively recent Cx4 documentation here, though basically none of it is currently implemented in the sd2snes, so the current firmware shouldn't be considered an accurate reference implementation at this point. I've been implementing as much as possible of it in bsnes-plus, but I can't claim 100% accuracy with that either, but those notes are based on actual hardware behavior.

Some of the Cx4's state is available via memory-mapped registers, though there are some important parts (particularly the cache status) which I don't think are externally accessible, so I'm not sure that saving/restoring its state via the SNES CPU is actually meaningfully possible.
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224269)
Revenant wrote:
The Cx4 locks out both ROM and SRAM whenever it's accessing either of them. Most of the time it's either running code from its internal cache or not running at all, but otherwise it claims the cartridge bus when caching a new code page, performing DMA, or reading/writing individual ROM/RAM addresses.


Is the 65816 halted during this? If it's halted, why is the NMI handler in WRAM instead of ROM?

How is it known that the Cx4 locks out SRAM, since X2 and X3 don't have SRAM?

Thanks!
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224274)
Nothing can stop the SNES's CPU other than its own DMA unit; it has to wait for the CX4 to be done.

The CX4 has a 32 bytes of RAM that replace all of the SNES's vectors while the CX4 is hogging the ROM. The game has to use this to point to an alternative vector in the SNES's own WRAM.
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224278)
Myria wrote:
How is it known that the Cx4 locks out SRAM, since X2 and X3 don't have SRAM?

RAM areas read back all zeroes whenever there's none available (or when the Cx4 is accessing the bus).
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224351)
lidnariq wrote:
The CX4 has a 32 bytes of RAM that replace all of the SNES's vectors while the CX4 is hogging the ROM. The game has to use this to point to an alternative vector in the SNES's own WRAM.


Looking at X2, I don't see anything on the 65816 side writing to 7F60. The NMI and IRQ handler addresses in the ROM header point to WRAM.

Revenant wrote:
RAM areas read back all zeroes whenever there's none available (or when the Cx4 is accessing the bus).


That sounds very bad to me, because it means that I need to find a place to store several kilobytes of extra code in WRAM. I can't use ROM because the Cx4 locks it out (same reason NMI handler is in WRAM), but it sounds like I can't use SRAM, either, because that's locked out too.
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224360)
Myria wrote:
That sounds very bad to me, because it means that I need to find a place to store several kilobytes of extra code in WRAM. I can't use ROM because the Cx4 locks it out (same reason NMI handler is in WRAM), but it sounds like I can't use SRAM, either, because that's locked out too.

Depends on when you need to access SRAM. The CX4 seems to be used mainly for executing "small math functions", and it stops running after each such function call (not to mention that you could also manually pause/unpause the CX4 if needed).
Just hook the original code so that your own code gets executed when none of that CX4 functions is being executed - then you have full access to SRAM (and ROM).

Myria wrote:
Looking at X2, I don't see anything on the 65816 side writing to 7F60. The NMI and IRQ handler addresses in the ROM header point to WRAM.

Look again ; ) 7F6xh is written in the very first function being called after reset/entrypoint at 0:8000h.
Also mind that the ROM vectors MUST point to the same addresses as the 7F6xh vectors (see the warning about possible problems in fullsnes.htm) (and the thread with ikari's newer CX4 findings has later confirmed that the ROM vectors really cannot be disabled when CX4 gets paused).

Btw. the reason why ROM+SRAM are both disabled when CX4 is running is seen in the CX4 pinout: It's having two address/data busses, one for "SNES" and one for "ROM/SRAM". So if CX4 is accessing ROM or SRAM, then SNES accesses cannot be forwarded to the ROM/SRAM bus (if you are wondering if the SRAM was really supposed to be wired to the ROM/SRAM bus: it must be so because ikari mentioned that CX4 can do DMA to/from SRAM, which won't work if SRAM were wired to SNES bus).
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224480)
Quote:
and the thread with ikari's newer CX4 findings has later confirmed that the ROM vectors really cannot be disabled when CX4 gets paused


Wait ... so the Cx4 always overrides the ROM vectors, no matter what?

So in that case, it's not possible to dump the actual values in the mask ROM chips through the SNES cartridge bus, and instead you get whatever the Cx4 initializes those registers to, yes? Not a real problem in context, but ... very interesting.
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224500)
No, I meant this:
CX4 running --> use 7F6xh vectors (from I/O ports)
CX4 paused --> use FFExh vectors (from ROM)
CX4 just changing between run/pause state --> possibly use a mixup of low-byte and high-byte from ROM and I/O vectors
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224894)
Is there a way to know whether the Cx4 is currently locking out ROM and SRAM? Also, will the Cx4 take control of ROM/SRAM suddenly, or does it have to be triggered by something on the 65816?
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#224895)
Lower level details in ikari_01's post and some programmer's details in nocash's documentation.

Direct answers:
[$007F53] & 128 indicates if the CX4 is hogging the bus

If the CX4 is still executing code, it can steal the bus at any time. This could either be loading a new 512b cache line, or just using its own "access ROM/RAM" opcode. The CX4 can choose to stop itself. The SNES can tell the CX4 to stop indefinitely or for a predetermined short number of cycles.
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#225070)
As for being able to make the SNES save the state of the Cx4, I suppose you could modify the $7fxx writes to also keep track of them somewhere else in RAM to be able to read/reapply them later, or possibly use the status flags to determine whether or not attempting to restore the entire Cx4 state is even necessary at a given point (i.e. if it's not currently running, you probably only need to save/restore its internal RAM and maybe preload cache pages again without having to actually rerun any Cx4 code).

There are a lot of features of the chip that neither game actually uses, and I don't think any of the Cx4 routines in either game ever cross over to adjacent pages, so you could probably at least assume that whichever pages are precached/directly referenced by the game will still be valid if the Cx4 is still running when a state is saved. Unfortunately when loading the state you'd probably have to basically restart whatever routine was being executed without some specific state information, which would likely lead to some minor sync issues (but at least it should be consistent when repeatedly reloading the same state?)
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#225135)
Adding fuel to the speculation fire that MMX3 is just a ROM hack of MMX2 ... the Cx4 programs on both carts are identical save for a single byte (not even sure what the one byte change was for.)

Also, there's a command to suspend the Cx4 indefinitely from the CPU side, then you can just unpause it when you're ready.

It's lucky for emudevs, but unlucky for hackers, that the SuperFX and Cx4 don't bother with bus contention handling like the SA-1.
Re: Cx4, ROM, SRAM, SD2SNES and saved states
by on (#225181)
byuu wrote:
Adding fuel to the speculation fire that MMX3 is just a ROM hack of MMX2 ... the Cx4 programs on both carts are identical save for a single byte (not even sure what the one byte change was for.)

That's like arguing that Super Mario Kart is just a ROM hack of Pilotwings... because they are using the exact same DSP-1 code! ; )
The (two) changed bytes in the CX4 code are described in "SNES Cart Capcom CX4 - Functions" chapter in fullsnes.htm.
It's quite unlikely that average amateur graphics ROM hackers would know how to patch that two bytes.