TASEmulators / TASEmulators/BizHawk
Gambatte emu.frameadvance() + "Equal Length Frames" causing callbacks to run during DMA
Nobody has claimed this yet.
- 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:
- Don't use that setting (unfortunately many of the users of my script use it for better audio)
- Register a memoryexecute handler on the vblank handler (what I've done)
- Translate between RAM addresses and system domains (annoying because
I'm told Sameboy and Gambatte have different domain namesnobody 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:
- Sound resampling for Gambatte so that the option isn't needed (unlikely)
- Skip lua callbacks if a DMA is in progress (might not be desired)
- Attempt to run forward a bit more if DMA is in progress (??)
Repro
- Ensure "Equal Length Frames" is set in Gambatte
- Load up Link's Awakening DX in Gambatte
- 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
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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