-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
ProcessorInterface: Implement PI_FIFO_RESET #10454
Conversation
@@ -111,7 +112,9 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) | |||
|
|||
mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead<u32>(), | |||
MMIO::ComplexWrite<u32>([](u32, u32 val) { | |||
WARN_LOG_FMT(PROCESSORINTERFACE, "Fifo reset ({:08x})", val); | |||
INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_FIFO_RESET: {:08x}", val); | |||
if (val != 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably only a single bit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed. My attempt at hardware-testing found that writing 2
seemed to hang everything, though I also ran into other issues (after calling GX_AbortFrame
other drawing commands stopped working, but I might be doing something wrong)
19c62cf
to
89e1e30
Compare
Sounds reasonable but it'd be nice to figure out if it's really correct to ignore everything but the LSB. |
if we only know + implement what bit 0 does, but log all bits, seems ok? |
For what it's worth, here's my attempted hardware test - build with |
What's the state of this, should we merge this? |
Did you try dumping the register before modifying it / just modifying the low bit? Maybe you accidentally change other bits (but it’s unlikely I guess) also, it looks like libogc has extra code in this path on wii hardware which waits for pixel engine memory access to stop (__GX_WaitAbortPixelEngine) maybe this impacts your test. |
I'm not confident that this is correct currently. It fixes some things, but I'm unsure about both the implementation and the hardware behavior it's implementing. So it shouldn't be merged currently.
I don't remember if I did this. However, Libogc's
I did try that (by calling
|
Fixes unknown opcodes 0x0f and 0xff when resetting titles, e.g. https://bugs.dolphin-emu.org/issues/12492
FifoCI detected that this change impacts graphical rendering. Here are the behavior differences detected by the system:
automated-fifoci-reporter |
This isn't getting much attention in a while, and there are speedruns that rely on reset, along with things like the VC games that randomly break on this. I think it's a fairly safe thing to do. |
Fixes unknown opcodes 0x0f and 0xff when resetting titles, e.g. https://bugs.dolphin-emu.org/issues/12492.
I was able to consistently reproduce and test this by recording a movie with the GameCube Preview Disc. I eventually ended up getting lucky and reproducing the issue the first time around, giving a very short movie file that allowed for fast testing. I also hex-edited the movie to set it to dual core, and confirmed that the same issue happened there (and the movies synced with that change, surprisingly). PreviewDiscUnknownOpcode.zip
Here are some log files from reproducing the issue before and after this PR, with additional debug logging: OOT_old.log OOT_new.log Preview_old.log Preview_new.log (the preview ones are with PreviewDiscUnknownOpcodeShort.dtm; the OOT ones are two separate runs).
Changes I made to add more logging:
I had noticed that extra data was present in the FIFO when
FIFO_RW_DISTANCE_HI
was present, and while adding logging to try to figure out when it first appeared, I spotted the existing warning message aboutPI_FIFO_RESET
and figured it might be relevant.Basically, when resetting or changing games, the existing contents of the fifo don't matter since it's not going to be drawn anymore.
GXAbortFrame
(or something like that) is called to reset the contents of the fifo, which it does by writing 1 toPI_FIFO_RESET
, waiting a bit, and then writing 0 toPI_FIFO_RESET
. Then, after the new game is loaded (or the existing game is reloaded), which might be a few seconds later,GXInit
is called, which sets up the fifo again and then writes some initialization stuff into it. The first data it writes is from__GX_FlushTextureState
, which contains aBPMEM_IND_IMASK
command (I don't actually know what that one does and Dolphin doesn't implement it, but that doesn't matter). That hex data for that command is61 0f 0000ff
. Other commands follow afterwards:BPMEM_BUSCLOCK1
(0x69) andBPMEM_BUSCLOCK0
(0x46).We weren't handling
PI_FIFO_RESET
, so the contents of the FIFO weren't cleared. In many cases that won't be a problem, as if there are unprocessed graphics commands in there, it doesn't matter if we process it or not (to my understanding, only the FIFO is being reset, not the actual graphics state; the game will need to reconfigure everything from a previously-unknown state anyways). But graphics commands are done using multiple writes; for instance, BP commands are usually done by first writing the byte0x61
and then doing a 4-byte write corresponding to the BP register and the 3-byte value (but they can also be done using 4 separate single-byte writes). If the reset happens at that point, and the game then stops what it was doing, the command will be partially written. Then, when later commands are written during the initialization process, they won't decode properly. For instance, if the game started writing a BP command before it got reset, and had written61
, then when61 0f 0000ff
is written the whole stream will instead be read as61 61 0f0000 ff
: a BP command writing to BP register 61 (BPMEM_PRELOAD_TMEMEVEN
) with a value of0f0000
, followed byff
which is an unknown opcode. And similarly, if it had written the 4 of the 5 bytes in a BP command, for instance61 4e 00 01
, then the whole stream will be parsed as61 4e 000161 0f 00 00 ff
, a write of value000161
toBPMEM_COPYYSCALE
, followed by0f
which is an unknown opcode, followed by 00 which is treated as NOP and ignored (twice), followed byff
which is also an unknown opcode. HandlingPI_FIFO_RESET
prevents this entirely.The old approach prior to #8090 worked because part of the fifo-initializing process is writing to
FIFO_RW_DISTANCE_HI
. But, that happens several seconds later, and (presumably, I haven't actually confirmed this) games might write toFIFO_RW_DISTANCE_HI
in other cases (and also, we were only resetting when writing toFIFO_RW_DISTANCE_HI
, notFIFO_RW_DISTANCE_LO
, which just seems odd).I haven't performed any hardware testing here yet, but this behavior seems fairly plausible.