I've been trying to come up with a way of rapidly sending a large number of fairly small chunks of data to VRAM, and I hit on the idea of resetting $43xx with DMA. So I made a test code, and it works perfectly in ZSNES and no$sns, but not in Snes9X, bsnes, or on my real SNES.
I don't try to reset the channel I'm using for the reset, just the other seven. Registers not used by DMA ($43x7-$43xF) are set to zero. The other seven channels alternate between resetting the VRAM address and writing to the VRAM data port.
Expected behaviour is a 32x32 square of hex characters in the middle of a mauve screen. Actual behaviour is just the mauve screen (which is turned on after the DMA section, so plainly the CPU hasn't hung or anything).
Is there some reason you can't do this? Or did I mess up something obscure that can in principle be fixed?
EDIT: There is a reason you can't do this, per AWJ below. Oh well...
Are you writing vram during vblank? iirc both zsnes and no$sns allow writing to vram during scanning, which would not write vram on a real console. I would suggest removing zsnes from your tests as it's a broken mess that'll only waste your time. And don't trust no$sns too much, it's the most accurate either.
I'm using Neviksti's InitializeSNES code, which leaves the machine in forced blank. Then I do all the DMA, and then I set up the screen and turn it on. No interrupts or reloading.
The Snes9X debugger indicates that the DMA registers aren't even being properly initialized. The first transfer after the attempt at DMAing the channel settings has a length of zero, and the rest of the channels seem to be uniformly $FFFFFFFFFFFFFF...
I know no$sns isn't trustworthy, and I know ZSNES is less so. My Super Everdrive is, as always, the gold standard, with higan accuracy not far behind. But the fact that it does work on the lower-grade emulators (and no$sns has a really nice debugger, so I can see that it's working in multiple ways) indicates that I haven't made a really simple error like writing the wrong values or targeting the wrong registers. I'm expecting an obscure issue, because ZSNES or no$sns would have tripped over an obvious one.
93143 wrote:
My Super Everdrive is, as always, the gold standard
Only if you initialize all the registers and memory yourself, as it's menu code will have set things up a certain way.
You can't use DMA to read or write to S-CPU registers ($40xx, $42xx, $43xx). They aren't on either the A-bus or the B-bus.
Thank you; that's the sort of thing I wanted to know.
Well, shucks. I guess I'll have to reset the channels manually...
If you're bored, try and write a cyclical DMA that writes to $420b to restart the DMA on ZSNES/no$sns :P
> because ZSNES or no$sns would have tripped over an obvious one.
Not really. Most emulators don't bother trying to block disallowed behaviors, because what game is going to rely on a disallowed behavior, short of bugs in game code? (and even then, they usually get worked around with game-specific patches.)
Emulating disallowed behaviors incur speed hits yet show no visible improvements to the end users. Even finding said behaviors is very challenging and time-consuming to narrow down.
Also, don't be too confident in your Everdrive. Copier BIOSes usually flush/initialize/dirty all of the memory and registers. Once you've fully initialized everything, you'll probably be okay. But even then, my Super UFO always asserted every SNES bus address, which effectively broke the MDR ("open bus"). It's still definitely your first stop though, as it's certainly the most accurate of anything.
byuu wrote:
But even then, my Super UFO always asserted every SNES bus address, which effectively broke the MDR ("open bus").
My NES PowerPak has pull-ups that likewise break the NES CPU's open bus (but not the PPU's separate MDR). See
Riding the open bus.
Exactly the same behavior here, actually. PPU1/PPU2 MDR's continue to work on the UFO (for obvious reasons, of course.)
Thankfully, due to blargg's generosity, I now use a dev cart and bypass copiers entirely :D