Skip to content

Commit

Permalink
Create new pads from settings instead of using sstate copy on type mi…
Browse files Browse the repository at this point in the history
…smatch
  • Loading branch information
RedPanda4552 committed Nov 24, 2023
1 parent 309793a commit fa5111b
Showing 1 changed file with 28 additions and 19 deletions.
47 changes: 28 additions & 19 deletions pcsx2/SIO/Pad/Pad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,35 +536,44 @@ bool Pad::Freeze(StateWrapper& sw)

for (u32 unifiedSlot = 0; unifiedSlot < NUM_CONTROLLER_PORTS; unifiedSlot++)
{
ControllerType type;
sw.Do(&type);
PadBase* currentPad = GetPad(unifiedSlot);
const ControllerType currentPadType = currentPad->GetType();
ControllerType statePadType;

sw.Do(&statePadType);

if (sw.HasError())
return false;

PadBase* tempPad;
PadBase* pad = GetPad(unifiedSlot);
if (!pad || pad->GetType() != type)

// If the currently configured pad is of a different type than the pad which was used during the savestate...
if (!currentPad || currentPad->GetType() != statePadType)
{
const auto& [port, slot] = sioConvertPadToPortAndSlot(unifiedSlot);
Host::AddIconOSDMessage(fmt::format("UnfreezePad{}Changed", unifiedSlot), ICON_FA_GAMEPAD,
fmt::format(TRANSLATE_FS("Pad",
"Controller port {0}, slot {1} has a {2} connected, but the save state has a "
"{3}.\nLeaving the original controller type connected, but this may cause issues."),
"{3}.\nEjecting {3} and replacing it with {2}."),
port, slot,
GetControllerTypeName(pad ? pad->GetType() : Pad::ControllerType::NotConnected),
GetControllerTypeName(type)));

// Reset the transfer etc state of the pad, at least it has a better chance of surviving.
if (pad)
pad->SoftReset();

// But we still need to pull the data from the state..
tempPad = CreatePad(unifiedSlot, type);
pad = tempPad;
GetControllerTypeName(currentPad ? currentPad->GetType() : Pad::ControllerType::NotConnected),
GetControllerTypeName(statePadType)));

// Run the freeze, using a new pad instance of the old type just so we make sure all those attributes
// from the state are read out and we aren't going to run into some sort of consistency problem.
currentPad = CreatePad(unifiedSlot, statePadType);
currentPad->Freeze(sw);

// Now immediately discard whatever malformed pad state we just created, and replace it with a fresh pad loaded
// using whatever the current user settings are. Savestates are, by definition, never going to occur in the middle
// of a transfer between SIO2 and the peripheral, since they aren't captured until the VM is at a point where everything
// is "stoppable". For all intents and purposes, by the time a savestate is captured, the IOP is "done" and there is no
// "pending work" left hanging in SIO2 or the pads. So there is nothing actually lost from just throwing the pad away and making a new one here.
currentPad = CreatePad(unifiedSlot, currentPadType, Pad::DEFAULT_EJECT_TICKS);
}

if (!pad->Freeze(sw))
// ... else, just run the freeze normally.
else if (!currentPad->Freeze(sw))
{
return false;
}
}
}
else
Expand Down

0 comments on commit fa5111b

Please sign in to comment.