Project

General

Profile

Actions

Emulator Issues #10764

closed

When using the GC adapter, loading a savestate made with the standard input, then loading one made with the GC adapter before the controller change from the original savestate is detected will break all input

Added by NarryG over 6 years ago. Updated over 5 years ago.

Status:
Fixed
Priority:
Normal
Assignee:
% Done:

0%

Operating system:
N/A
Issue type:
Bug
Milestone:
Regression:
No
Relates to usability:
No
Relates to performance:
No
Easy:
No
Relates to maintainability:
No
Regression start:
Fixed in:
5.0-9514

Description

Game Name?

Any Gamecube game (didn't test Wii)
Primarily tested on Twilight Princess but it happened on other games

Game ID? (right click the game in the game list, properties, info tab)

Does not apply

MD5 Hash? (right click the game in the game list, properties, info tab, MD5 Hash: Compute)

Does not apply

What's the problem? Describe what went wrong.
When you load a savestate made using a different control option, there's a short period of time after loading where all inputs wont work. This lasts about half a second.
If you're using the GC adapter, load a savestate made with the standard controller, then in that short period where inputs aren't recognized load a state which was made with the GC adapter, all input will break until you swap controller mode or restart the game.

What steps will reproduce the problem?
Load up a gamecube game with the standard controller as the input
Create a savestate
Quit the game
Load up a gamecube game with the Gamecube adapter for WiiU set
Create a savestate
Load the savestate made with the standard controller, then right after that (within the ~.5 second window of no input) load the savestate made with the gamecube adapter
All input should now be broken

Is the issue present in the latest development version? For future reference, please also write down the version number of the latest development version.

Yes
5.0-6112

Is the issue present in the latest stable version?

Yes
5.0 Stable

What are your PC specifications? (CPU, GPU, Operating System, more)
Windows 10 Fall Creator's Update
i7-6700k
GTX 1080 Ti

Is there anything else that can help developers narrow down the issue? (e.g. logs, screenshots,
configuration files, savefiles, savestates)

I don't know if this could affect it, but I'm using the Mayflash adapter, not the first party one.

Actions #1

Updated by NarryG over 6 years ago

Update: Alternate method of triggering it

Load up a gamecube game with the Gamecube adapter for WiiU set
Create a savestate
Quit the game
Load up a gamecube game with the standard controller set
Load the savestate made with the GC controller, then within that small period, load the same savestate again
All input will now be broken

Actions #2

Updated by NarryG over 6 years ago

Update: Alternate method of triggering it

Load up a gamecube game with the Gamecube adapter for WiiU set
Create a savestate
Quit the game
Load up a gamecube game with the standard controller set
Load the savestate made with the GC controller, then within that small period, load the same savestate again
All input will now be broken

This method is both simpler to execute, and more likely to happen to the average user. It's easy to accidentally push the button twice, resulting in broken input.

Actions #3

Updated by NarryG over 6 years ago

I traced the code and found where the issue stems from. Not quite sure how you'd want this issue fixed so I'm not going to submit a pull request fixing it myself

Here's the important details

si.cpp
Within DoState()

    else
    {
      // If no movie is active, we'll assume the user wants to keep their current devices
      // instead of the ones they had when the savestate was created.
      // But we need to restore the current devices first just in case.
      SIDevices original_device = device->GetDeviceType();
      std::unique_ptr<ISIDevice> save_device = SIDevice_Create(type, i);
      save_device->DoState(p);
      AddDevice(std::move(save_device));
      ChangeDeviceDeterministic(original_device, i);
    }

And then in ChangeDeviceDeterministic

  if (GetDeviceType(channel) != device)
  {
    CoreTiming::ScheduleEvent(0, s_change_device_event, ((u64)channel << 32) | SIDEVICE_NONE);
    CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond(), s_change_device_event,
                              ((u64)channel << 32) | device);
  }

This is where the issue lies.

When you call ChangeDeviceDeterministic the first time, it disconnects the currently connected controller. If you then load the state again before it initializes the correct controller, the code in DoState to grab the currently connected controller grabs SIDEVICE_NONE as the controller had previously been disconnected. It then swaps the active controller to SIDEVICE_NONE instead of the correct device.

Actions #4

Updated by leoetlino over 6 years ago

  • Status changed from New to Accepted
Actions #5

Updated by Billiard26 over 5 years ago

  • Status changed from Accepted to Fix pending
  • Assignee set to Billiard26
Actions #6

Updated by Billiard26 over 5 years ago

  • Status changed from Fix pending to Fixed
  • Fixed in set to 5.0-9514
Actions

Also available in: Atom PDF