-
Notifications
You must be signed in to change notification settings - Fork 375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Weird mem callback issue with high address locations under genplus-gx #3862
Comments
Setting a write breakpoint at 0xfff600 means writes specifically at 0xfff600, not any kind of mirrors to that address. Are you sure the game is specifically writing to that address and not say some mirror address? |
Some testing and it seems the game writes to the 0xFFFFF600 mirror address. This is ultimately just standard mem hook behavior. |
Sorry, I'm confused... it's standard behaviour that it simply doesn't work? As I said, 0xfff370 works perfectly while 0xfff600 doesn't. I can't see a reason why one would work and the other would not. |
The address you see in the tracelog is the one for which hooks will trigger, not any mirrors. You can imagine EmuHawk having more "magic", but we're not in a position to improve that behaviour right now. |
To be clear, the Genesis m68k has a 24 bit address space, its RAM is mirrored across the address range 0xE00000-0xFFFFFF but the normal behaviour is the access 0xFF0000-0xFFFFFF.... so 0xFFF600, which is what I was checking against, is the correct hardware address... accessing 0xFFFFF600 is impossible because that address doesn't physically exist, it's being truncated down. The address registers may technically be 32 bits, but only the 24 bit address space and 16 bit external bus are used. The top byte of the address register is discarded and only the bottom 2 bytes get written to the pins. Heck, I have the disassembly in front of me, so I can actually give you the exact instruction being used:
It's a single byte immediate write, the EA is encoded in the instruction as a 16 bit address, it would have to be The writes to 0xFFF370 are harder to show since the sound driver is all relative addressing, but it should be a combination of these two instructions:
though other parts are handled like one of these two instructions:
Where the former is encoding an address literal in the ROM and the latter is how some of the relative addresses of the sound driver are referenced. I can't follow what possible address magic would cause What am I missing here? |
The write callback is simply passed the address which the core is using internally ( BizHawk/waterbox/gpgx/core/m68k/m68kcpu.h Lines 927 to 970 in b10f896
|
Hmmm... are those involved in macro rewritten calls somewhere? I can't see anything that actually calls them. I think I can guess what's happening though.
The callback being fired at step 3 is consistent with it triggering against the bus address, but the issue is that there's no sanity applied to the value in The IOP that is using an address register is applying bit masking to correctly emulate the address bus being 24 bits wide. Dunno precisely where in the sequence the value is being masked but it'll be before use. This instruction fires the callback handler correctly. The IOP that is using an immediate address is storing the address pulled from the operand in local variable, it sign extends that value in that variable and then passes that to the write which passes it through unhindered to the callback. What it doesn't do is mask to 24 bits... the sign extension is either 32 bit (size of a data register) or 64 bit (from size of the type), so the bus write is address that's impossible on hardware. Likely this isn't showing issues anywhere else since the masking in step 4 doesn't care how big the address is, it's just the call back that's getting inconsistent behaviour due to different move instructions generating drastically different address sizes. The only other place I could imagine this causing an issue is if there's some odd case where an immediate loaded address is compared against a value rather than being used to memory address, but I'd have to guess that all the comparison and test instructions apply a mask to both values (after operands have been resolved) to enforce the data size part of the opcode. If the intent is for bus callbacks to fire against addresses on the bus in a hardware accurate way, they should really be masked to the correct width for the architecture, thus 24 bit here. That all said... doesn't the callback registration code apply a range sanity to make sure that address requested lies within the domain requested? I thought it generated an error when you tried to use an invalid address. If the trap is constrained to legal bus addresses then it's impossible to trap a 32 bit memory address write regardless. |
I'll be honest, I didn't understand any of that.
I'm not seeing one. But the sysbus is indeed 24 bits, and that's enforced by the peek/poke callbacks: BizHawk/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IMemoryDomains.cs Lines 82 to 94 in 3f92764
|
Could I ask this be reopened? |
Oops. |
Summary
Frankly, I have no idea how or why this is broken beyond that it seems to have no obvious reason. But hey, it seems super reproducible, so there's that: OnMemoryWrite and on_bus_write callbacks registered for bus addresses around 0xFFF600-0xFFFFFF never fire.
event.onmemorywrite(trapper, 0xfff370)
is the highest address I've managed to find that works and is written to by the rom I'm testing withevent.onmemorywrite(trapper, 0xfff600)
never fires even as I'm watching the values changing in the hex editorevent.onmemorywrite(trapper, 0xfff400)
doesn't seem to fire but I say that with the caveat that I wrote to that via the hex editor because the rom doesn't use that memory area (to be exact, it seems to be allocated to the sound engine but that channel is dead code or something)event.onmemorywrite(trapper, 0xffff3)
is the address I tested going the other way, doesn't fire... probably safe to assume it's all the way to 0xffffff with that.I could thus assume that any address above 0xfff400 doesn't work, but I can't narrow the error bars further than F370-F600.
This is the upper kilobyte of the M68k's RAM, a bit frustrating for me because that's where a lot of the game engine values are.
I'm testing with Sonic 1, Rev 0 from 1991, hash
1BC674BE034E43C96B86487AC69D9293
... in case you're wondering, 0xFFF600 is the game mode byte and changes every 30 seconds at most when the game is looping through the Sega/Title/Demo sequence ... I don't think it's specific to that game though, that'd be weird.I did a cursory scan through trying to see if there was anything that would break the setting of the callback and abandoned the exercise when I'd gotten all the way to the gpgx cinterface without seeing anything that would logically lead to callbacks not working for only a range. If it were a higher or lower cutoff I might guess some kind of sign conversion shenanigans, but the addresses I tested suggest not. It shouldn't be a byte flip either, with those bit patterns.
To rule out some more possibles, I've tested this on Bizhawk 2.9 on Linux and Bizhawk 2.8 on Windows, obviously accounting for the expected difference that 2.8 doesn't have params for memory callbacks, and I'm seeing the same behaviour, so likely not a bug added during the big 2.9 memory changes or platform specific.
On 2.9 the RAM Watch and it's Breakpoints work correctly, and reading the bytes directly returns correct info, sooooo something magical that's specific to an interaction of
EventsLuaLibrary.cs
? Yeah, I'm out of ideas.Repro
Wait for something... you get a param error when it fires on 2.8, I'm getting the sound of silence on that address.
The text was updated successfully, but these errors were encountered: