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
Fix gamecube games not noticing disc changes #8571
Conversation
275b3e8
to
f67c7b5
Compare
f67c7b5
to
f67c489
Compare
|
I've added some new fixes for resetting the drive from the emulated software (both on GameCube and Wii). This allows removal of a hack where the drive would act as if it was spun up when reading the disc ID, even if it shouldn't have been in that state. It also fixes bug 12017 (caused by MaxPlay stopping the motor and then resetting the drive; since the reset wasn't implemented it would error since, well, the motor was stopped). Note that I have not hardware tested the exact behavior of Take a look at
|
| // HACK However, resetting DI will reset the DTK config, which is set by the system menu | ||
| // (and not by MIOS), causing games that use DTK to break. Perhaps MIOS doesn't actually | ||
| // reset DI fully, in such a way that the DTK config isn't cleared? | ||
| // DVDInterface::Reset(); | ||
| // DVDInterface::ResetDrive(true); |
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.
I'm less sure that MIOS is even supposed to reset DI in the first place. It does make some writes to PI_RESET_CODE, but I haven't seen it actually write anything other than 7 (there is code that can do it, but I don't think it's live). Of course, if it did write something else, that would be properly emulated because we actually run (the PPC part of) MIOS. I don't see any writes to it from the ARM part of MIOS, nor from BC, but I might be missing them.
I also did a very basic hardware test of listening to the disc drive while launching a GameCube game; it didn't sound like it triggered a reset.
|
Rebasing to fix conflict with #8733 (i.e. don't change DILENGTH/DIMAR in the case of |
f67c489
to
cf6e2af
Compare
e6738ca
to
e06b312
Compare
…acies In particular: - Trying to play audio in a non-ready state returns the state-specific error, not an audio buf error - Audio status cannot be requested in non-ready states - The audio buffer cannot be configured in states other than ReadyNoReadsMade - Using the stop motor command while the motor is already stopped doesn't change states Additionally, the internal state IDs are used (which distinguish ReadyNoReadsMade and Ready), instead of the state IDs exposed in request error. This makes some of the weird behavior a bit more obvious. State and error behavior of the seek command was not implemented in this commit.
Turns out, Gamecube games actually do check DILENGTH, and if DILENGTH is at 0, they'll think the transfer completed successfully even if DEINT is used, since after all, surely that means everything was sent. That caused all sorts of issues, from audio looping when a disc is removed since it's re-using the same buffer to just flat-out crashing instead of showing the disc removed screen.
Resetting the DI registers disables interrupts, which means any errors reported (for instance) are just not sent though.
Since both GameCube and Wii resets now work correctly, this hack is not needed anymore.
It only resets the registers, which isn't something that needs to be done except for in DVDInterface::Init
|
Great work, thank you! |
Fixes issue 9019.
The problems:
Changing a disc reset the drive state completely (which was something I added in 55a88ba). This included the DI registers, meaning interrupts would no longer be sent (so the drive errors that were supposed to be sent in that case just weren't making it anywhere). Now it only resets "internal" properties. I don't know if this is 100% accurate behavior (and I only changed it for disc changes; other places that reset it were not changed)
Although that allowed games to detect disc errors if they happened on e.g. request stream status, they still didn't care about errors on the read command (which are far more likely). This happened to be because games look at
DILENGTH, and if it's 0 they assume the read was successful even ifDEINTwas fired instead ofTCINT. I touched related code in 3110599 but didn't actually think about the error case. Note that YAGCD mentions that DILENGTH can indicate the amount of data left over for transfer, but it isn't explicit about that being used in errors.One possible change here is that it might be possible for commands (especially reads) to fail partway through, in which case DILENGTH would maybe be half-updated instead of the current all-or-nothing situation. But all-or-nothing seems sufficient for most games.
There were some other inaccuracies with drive state behavior, based on attempts at reverse-engineering the drive firmware. There are some old half-archived notes here, which was enough for me to get started (but it's very hard to understand). These changes required a savestate version bump.
One thing this fixes (when combined with the other changes) is the AudioStream command, which gave the wrong error code in some states, which games wouldn't know what to do with and would then crash.
A note: at least with Alien Hominid, if a game using DTK is ejected while it is streaming, upon reinsertion it'll start the stream from the beginning again. I tested and confirmed this behavior on console (specifically my Wii).