TASEmulators / TASEmulators/BizHawk

Gambatte emu.frameadvance() + "Equal Length Frames" causing callbacks to run during DMA

Open
#3,711 12 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

App: EmuHawk Needs domain knowledge for triage re: Lua API/scripting Repro: Affects 2.8
Dominant language
C#
Stars
2.8k
Forks
468
PR merge metrics
No merged PRs in 30d

Description

Summary

When running with "Equal Length Frames", calling emu.frameadvance can lead to lua running during a DMA operation. This will lead to garbage WRAM reads (open bus?) when doing a general "System Bus" read. See https://gbdev.io/pandocs/OAM_DMA_Transfer.html for a vague idea of what's happening. This may be desired behavior for some applications, but is probably unexpected for most users/script authors. I specifically saw this behavior in Link's Awakening DX.

In my specific case this causes issues with doing networked reads over RAM. I'm aware there are several workarounds:

  1. Don't use that setting (unfortunately many of the users of my script use it for better audio)
  2. Register a memoryexecute handler on the vblank handler (what I've done)
  3. Translate between RAM addresses and system domains (annoying because I'm told Sameboy and Gambatte have different domain names nobody wants to do math on memory addresses in lua)

This was repro'd specifically on 2.8, but I've had reports of 2.9 as well and can repro there if desired. This could either be regarded as a BizHawk bug or a Gambatte bug, I'm happy to report to Gambatte, if given a url. I also understand if this is closed as expected behavior - technically it is "correct" by some reading of Bizhawk's docs and of the Gambatte setting description. I'm not sure what the fix here would be. Possibilities:

  1. Sound resampling for Gambatte so that the option isn't needed (unlikely)
  2. Skip lua callbacks if a DMA is in progress (might not be desired)
  3. Attempt to run forward a bit more if DMA is in progress (??)
Repro
  1. Ensure "Equal Length Frames" is set in Gambatte
  2. Load up Link's Awakening DX in Gambatte
  3. Load up this script
while true do
    local sb = memory.read_bytes_as_array(0xC0FB, 4, "System Bus")
    local wr = memory.read_bytes_as_array(0x0FB, 4, "WRAM")

    if sb[1] ~= wr[1] then
        print("Hit error:")
        print(sb)
        print(wr)

        local pc = emu.getregister('PC')
        print(string.format("Bad PC: %04X", pc))
    end
    
    emu.frameadvance()
end
  1. Exit Tarin's house, go walk around opening and closing the menu and doing screen transitions
Output
"1": "120"
"2": "120"
"3": "120"
"4": "120"

"1": "0"
"2": "0"
"3": "0"
"4": "0"

Bad PC: FFC6
Host env.
  • BizHawk 2.8, Win64
  • Reports on 2.9, haven't personally reproduced but can if needed

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No source file or test is named. Start with the supplied Lua reproduction using Gambatte's “Equal Length Frames” setting, Link's Awakening DX, and the System Bus versus WRAM reads; trace when emu.frameadvance callbacks run relative to DMA. Done means the behavior is resolved or explicitly documented with a verified reproduction result.

Written by the indexing model from the issue text.

Assessment

Tech stack
lua
Domain
tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.