New HDMA emulation finding

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

New HDMA emulation finding

Post by Near »

SMW Central ROM hacker Ladida showed up on my forum with a bug that triggered on real hardware, but on no emulators. They were nice enough to make a test ROM, so I looked into it and found a possible solution.

Test code: https://pastebin.com/g7f4GmnA
Test ROM: http://www.mediafire.com/file/v09cewlzi ... da_lol.sfc
How it should look: https://gfycat.com/gifs/detail/Shameful ... igerbeetle

I've come up with an initial solution that matches hardware for this test ROM, and also doesn't seem to break any of the most HDMA intensive SNES games I'm aware of (Energy Breaker, Dai Kaijuu Monogatari, etc.) But it's possible it's not correct.

What looks to be happening is that only when HDMA init runs (eg there are channels enabled at the start of a frame when HDMA init triggers), it initially sets the DoTransfer flag to true (see anomie's documentation for an explanation of DoTransfer.) It does this even if the specific channel is disabled. Then, if the channel is enabled, it will perform an hdmaUpdate(), which will fetch the line counter for you.

So if you try to enable an HDMA channel halfway through the frame, that DoTransfer flag will still be set, and on the very next HDMA, it will perform a transfer anyway, but without the line fetch. This will most likely cause a read offset against your HDMA table, and things will go very badly. It essentially runs a line sooner than you'd expect (which is why there's no extra white line in the test ROM, and why the color is green instead of a red gradient.)

Interestingly, if you do not have any HDMA channels enabled at the start of a frame, and the true HDMA init is skipped entirely, then the DoTransfer flag is most likely cleared, but possibly left alone. As a result, when you enable the HDMA later, it won't do an HDMA transfer on the next Hblank, it will instead do a line counter fetch, and will start the actual transfer one scanline later (this is the reason for the white line in the test ROM.)

Obviously, the hard part will be now devising a test ROM to run on real hardware to ensure this is really what's going on. I'm thinking I'll push it temporarily to a WIP release (not an official release) to gather feedback and see if anyone can quickly confirm my solution wrong by finding a game regression. If that does happen (and it's quite likely), then we'll be back to the drawing board on this one.

But regardless, I'm about 95% confident the cause of the issue is DoTransfer being set in one case, and not in the other, in said test ROM.

My solution:

Code: Select all

auto CPU::hdmaInitReset() -> void {
  for(auto n : range(8)) {
    channel[n].hdmaCompleted = false;
    channel[n].hdmaDoTransfer = false;  //***** this is now under debate, may not be necessary *****
  }
}

auto CPU::hdmaInit() -> void {
  dmaStep(8);
  dmaWrite(false);

  for(auto n : range(8)) {
    channel[n].hdmaDoTransfer = true;  //***** ADD THIS LINE *****
    if(!channel[n].hdmaEnabled) continue;
    channel[n].dmaEnabled = false;  //HDMA init during DMA will stop DMA mid-transfer

    channel[n].hdmaAddress = channel[n].sourceAddress;
    channel[n].lineCounter = 0;
    hdmaUpdate(n);
  }

  status.irqLock = true;
}
Side tangent: I sincerely hope that if anyone out there knew about this behavior but chose not to tell anyone, that they keep it to themselves instead of trying to retroactively claim credit for fixing this first. If someone were keeping this knowledge to themselves, then that would look really bad on their part. Now if such a person existed, and they wanted to chime in with a more proper fix, all would be forgiven of course ^-^
Revenant
Posts: 462
Joined: Sat Apr 25, 2015 1:47 pm
Location: FL

Re: New HDMA emulation finding

Post by Revenant »

byuu wrote: Obviously, the hard part will be now devising a test ROM to run on real hardware to ensure this is really what's going on. I'm thinking I'll push it temporarily to a WIP release (not an official release) to gather feedback and see if anyone can quickly confirm my solution wrong by finding a game regression. If that does happen (and it's quite likely), then we'll be back to the drawing board on this one.
I guess the obvious way to find regressions would be to check games that would enable HDMA mid-frame, but are there even any that are known to do that?
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: New HDMA emulation finding

Post by tepples »

Do games that use letterboxing to increase VRAM bandwidth, like Final Fight and Street Fighter II, enable anything mid-frame? I know Super Street Fighter II uses both line scrolling and letterboxing. Star Fox rotates its backdrop with a combination of OPT and line scrolling and is also letterboxed. What does Super Mario Kart do? I know it has that black band between the players' views.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: New HDMA emulation finding

Post by Near »

Hope you're not asking me.

The big testing spree where I remembered all the obscure games with weird issues and behaviors was 7-13 years ago. I can't remember things I said or did two weeks ago anymore >_>

I have a hard time believing there's no games that have a single HDMA channel disabled at V=0, and then turn it on later in the frame, when using HDMA init. And yet ... this change of behavior marks a direct incompatibility, so if they did, we would have known. So ... I don't know.

We need to devise a way to test for this. It's tricky because DoTransfer isn't a flag you can toggle easily, it's internal state.
KungFuFurby
Posts: 275
Joined: Wed Jul 09, 2008 8:46 pm

Re: New HDMA emulation finding

Post by KungFuFurby »

nocash noted that Super Ghouls 'N Ghosts starts its HDMA mid-frame. Although I don't know where it uses it myself at the moment...
93143
Posts: 1715
Joined: Fri Jul 04, 2014 9:31 pm

Re: New HDMA emulation finding

Post by 93143 »

Just starting HDMA mid-frame isn't enough. It has to enable an HDMA channel mid-frame while HDMA is already running.

I've started HDMA mid-frame myself. The first transfer starts one line late, and every emulator I've tried (except ZSNES) gets it right.
Post Reply