It is currently Fri Sep 22, 2017 3:38 pm

All times are UTC - 7 hours



Forum rules


Related:



Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Tue Aug 08, 2017 10:47 pm 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1338
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:
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 ^-^


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 7:39 am 
Offline

Joined: Sat Apr 25, 2015 1:47 pm
Posts: 325
Location: FL
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?


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 7:56 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19003
Location: NE Indiana, USA (NTSC)
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.


Top
 Profile  
 
PostPosted: Wed Aug 09, 2017 8:20 am 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1338
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.


Top
 Profile  
 
PostPosted: Thu Aug 10, 2017 6:11 pm 
Offline

Joined: Wed Jul 09, 2008 8:46 pm
Posts: 234
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...


Top
 Profile  
 
PostPosted: Thu Aug 10, 2017 6:34 pm 
Offline

Joined: Fri Jul 04, 2014 9:31 pm
Posts: 760
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group