-
Notifications
You must be signed in to change notification settings - Fork 6
External registers behaviour
The SVP chip doesn't only contain the now-famous SSP160x DSP, but also some external circuitry that allows the DSP to access other resources like the DRAM memory chip in the cartridge or allowing synchronization with the Mega Drive. These can be accessed by using the external registers in the DSP code. A large part of the behavior of these external components is now understood as part of the effort done back in 2007 to emulate Virtua Racing (mainly by Notaz and Tasco Deluxe).
The goal of this document is to verify these behaviors in real hardware and to uncover any unknown processes that, not being required to run Virtua Racing, ended up forgotten.
My idea with this guide is that it ends up as a complete guide for the behavior of all external registers in the SVP chip. This will include what's already understood about it, given that it's verified on hardware. But the current focus of it is to uncover unknown behaviors.
The ST register has four pins that are used for bi-directional communications between the DSP and the external world. Two of them are used to send data to the chip (we'll call them GPI0 and GPI1), and the other two are used to send data from the DSP to the rest of the circuitry in the chip. I'll call them UP0 and UP1 to follow the same naming as found in the docs of the SSP160x's distant cousin CD2450.
UP0 corresponds to bit 5 in the ST register. UP1 to bit 6. When these are set, some of the external registers change their behavior. It's important to know this when programming to be sure the chip is going to do what we want.
Note: Virtua Racing usually activates UP0 or the combination of UP0 and UP1 to make some of the external registers to access external memory (ST = 0x0020 or 0x0060). Funnily it never uses the value 0x0040 (just UP1), and my current tests have showed me that just setting UP1 is not enough to change their behavior. So I'm under the impression that only UP0 is responsible of that, and maybe UP1 modifies other aspects that are still unknown. Gotta research this.
TODO: most of this is covered by notaz's guide. Will test and describe more details in the future.
Currently understood behavior of EXT1 shows that it allows accessing external memory for reads or writes when UP0 is active. Currently tested behaviors besides that:
- EXT1 behaves as a programmable memory register for reads when UP0 and UP1 are not set.
- EXT1 can't write to external memory when UP0 and UP1 are not set.
- This seems to imply that writes to EXT1 in those conditions serve another function (still unknown).
Currently understood behavior of EXT2 shows that it allows accessing external memory for reads or writes when UP0 is active. Currently tested behaviors besides that:
- Reads from EXT2 when UP0 and UP1 aren't set return random values. Not sure if they have any meaning yet.
- Writes to EXT2 when UP0 and UP1 don't seem to write values into external memory. Not sure if they have any meaning yet.
TODO: most of this is covered by notaz's guide. Will test and describe more details in the future.
TODO: most of this is covered by notaz's guide. Will test and describe more details in the future.
This register wasn't covered at all by any of the previous guides, so it's the one that I'm interested the most :D. Currently tested behaviors:
- EXT5 can be used for writes to external memory when UP0 is active. But it doesn't read from external memory in any case.
This register is the one that allows the external memory adapter to be programmed, and it's one of the most heavily used ones. As most of the bits that are used in the mode programming are understood already, I've focused so far in unknown behaviors for combination of parameters that aren't used by Virtua Racing.
Note: I'll use Notaz's naming convention for these bits: dsnnnv?? ???aaaaa
-
dandnnnbits are compatible, and they work as expected (tested value:0x9018). -
dandsbits are also compatible. The difference, besides the auto-decrementing, is that it decrements 31 positions when the current address is even, and 1 when the current address is odd. (i.e.:0xC000, starting from address0x0099: first write to0x0099, second to0x0098, third to0x0079). - The overwrite (
v) bit doesn't have any effect in reads, as far as I could see. - Setting any of the unknown (
?) bits seemed to cause the programming to fail. I only tested setting them separately, still have to try different combinations. After setting them, the selected external register continued working as if they hadn't been reprogrammed at all.
TODO: most of this is covered by notaz's guide. Will test and describe more details in the future.