Shonumi wrote:
I think the OAM DMA isn't the DMA you should be looking at. Try looking at HDMA. I just fixed this game in my emulator, and here's what I noticed.
The game transfers data to VRAM from line 74 to 144 via HDMA. Normally, the usual method of transferring large amounts of data for multiple scanlines is simply done by specifying how many lines the HDMA should run (Bits 0-6 of the HDMA5 register). Instead of doing that, Wacky Races manually triggers about 70 individual HDMA transfers (70 separate writes to HMDA5), each with a length of 0, meaning it runs for just one line. After an HDMA transfer, I believe the addresses in HDMA1/2 and HDMA3/4 are incremented automatically (but I have not devised a test on real HW yet), so that's how all of these HDMAs work correctly since the source/destinations are updated just fine.
My problem was that I wasn't correctly incrementing HDMA1/2 and HDMA3/4. I was updating the start/destination addresses internally based on length, however, since the length was always 0 for each HDMA transfer, none of my addresses turned out to be right. I fixed it by reading from HDMA1/2 and HDMA3/4 at the start of the DMA, incrementing a 16-bit variable that represented each address, then writing back each address to HDMA1/2 and HDMA3/4.
For what it's worth, this auto-increment behavior was responsible for a host of graphical glitches in Ken Griffey Jr.'s Slugfest in GBE+, but now those are fixed along with Wacky Races.
Thanks so much. I just tested that idea and you're completely right! It apparently uses the high/low source/destination registers as moving pointers during the transfer. And, they retain the transfer length increment even after DMA is completed, enabling successive DMA to continue where the last one left off. Simply amazing. We really should be updating the wiki with these details.