diff --git a/pcsx2/SIO/Multitap/MultitapProtocol.cpp b/pcsx2/SIO/Multitap/MultitapProtocol.cpp index 77840029cb8e8..31a498f8f339a 100644 --- a/pcsx2/SIO/Multitap/MultitapProtocol.cpp +++ b/pcsx2/SIO/Multitap/MultitapProtocol.cpp @@ -16,6 +16,7 @@ #include "PrecompiledHeader.h" #include "Common.h" +#include "StateWrapper.h" #include "SIO/Multitap/MultitapProtocol.h" @@ -25,8 +26,7 @@ #define MT_LOG_ENABLE 0 #define MT_LOG if (MT_LOG_ENABLE) DevCon -MultitapProtocol g_MultitapPort0; -MultitapProtocol g_MultitapPort1; +std::array g_MultitapArr; void MultitapProtocol::SupportCheck() { @@ -114,6 +114,16 @@ void MultitapProtocol::FullReset() this->currentMemcardSlot = 0; } +bool MultitapProtocol::DoState(StateWrapper& sw) +{ + if (!sw.DoMarker("Multitap")) + return false; + + sw.Do(¤tPadSlot); + sw.Do(¤tMemcardSlot); + return true; +} + u8 MultitapProtocol::GetPadSlot() { return this->currentPadSlot; diff --git a/pcsx2/SIO/Multitap/MultitapProtocol.h b/pcsx2/SIO/Multitap/MultitapProtocol.h index db0bd0b133324..62ee3bbea5761 100644 --- a/pcsx2/SIO/Multitap/MultitapProtocol.h +++ b/pcsx2/SIO/Multitap/MultitapProtocol.h @@ -15,6 +15,12 @@ #pragma once +#include "SIO/SioTypes.h" + +#include + +class StateWrapper; + enum class MultitapMode { NOT_SET = 0xff, @@ -39,6 +45,7 @@ class MultitapProtocol void SoftReset(); void FullReset(); + bool DoState(StateWrapper& sw); u8 GetPadSlot(); u8 GetMemcardSlot(); @@ -46,6 +53,5 @@ class MultitapProtocol void SendToMultitap(); }; -extern MultitapProtocol g_MultitapPort0; -extern MultitapProtocol g_MultitapPort1; +extern std::array g_MultitapArr; diff --git a/pcsx2/SIO/Pad/Pad.cpp b/pcsx2/SIO/Pad/Pad.cpp index a95e9fdca8eea..be87a99e06c3c 100644 --- a/pcsx2/SIO/Pad/Pad.cpp +++ b/pcsx2/SIO/Pad/Pad.cpp @@ -49,8 +49,7 @@ namespace Pad static const char* GetControllerTypeName(Pad::ControllerType type); - static std::unique_ptr CreatePad(u8 unifiedSlot, Pad::ControllerType controllerType); - static PadBase* ChangePadType(u8 unifiedSlot, Pad::ControllerType controllerType); + static PadBase* CreatePad(u8 unifiedSlot, Pad::ControllerType controllerType, size_t ejectTicks = 0); static void LoadMacroButtonConfig( const SettingsInterface& si, u32 pad, const ControllerInfo* ci, const std::string& section); @@ -91,7 +90,6 @@ void Pad::LoadConfig(const SettingsInterface& si) { s_macro_buttons = {}; - // This is where we would load controller types, if onepad supported them. for (u32 i = 0; i < Pad::NUM_CONTROLLER_PORTS; i++) { const std::string section = GetConfigSection(i); @@ -99,11 +97,12 @@ void Pad::LoadConfig(const SettingsInterface& si) pxAssert(ci); // If a pad is not yet constructed, at minimum place a NotConnected pad in the slot. - // Do not abort the for loop - If there pad settings, we want those to be applied to the slot. + // Do not abort the for loop - If there are pad settings, we want those to be applied to the slot. PadBase* pad = Pad::GetPad(i); + if (!pad || pad->GetType() != ci->type) { - pad = Pad::ChangePadType(i, ci->type); + pad = Pad::CreatePad(i, ci->type); pxAssert(pad); } @@ -471,22 +470,22 @@ std::string Pad::GetConfigSection(u32 pad_index) return fmt::format("Pad{}", pad_index + 1); } -std::unique_ptr Pad::CreatePad(u8 unifiedSlot, ControllerType controllerType) +// Create a new pad instance, update the smart pointer for this pad slot, and return a dumb pointer to the new pad. +PadBase* Pad::CreatePad(u8 unifiedSlot, ControllerType controllerType, size_t ejectTicks) { switch (controllerType) { case ControllerType::DualShock2: - return std::make_unique(unifiedSlot); + s_controllers[unifiedSlot] = std::make_unique(unifiedSlot, ejectTicks); + break; case ControllerType::Guitar: - return std::make_unique(unifiedSlot); + s_controllers[unifiedSlot] = std::make_unique(unifiedSlot, ejectTicks); + break; default: - return std::make_unique(unifiedSlot); + s_controllers[unifiedSlot] = std::make_unique(unifiedSlot, ejectTicks); + break; } -} -PadBase* Pad::ChangePadType(u8 unifiedSlot, ControllerType controllerType) -{ - s_controllers[unifiedSlot] = CreatePad(unifiedSlot, controllerType); return s_controllers[unifiedSlot].get(); } @@ -532,7 +531,7 @@ bool Pad::Freeze(StateWrapper& sw) if (sw.HasError()) return false; - std::unique_ptr tempPad; + PadBase* tempPad; PadBase* pad = GetPad(unifiedSlot); if (!pad || pad->GetType() != type) { @@ -551,7 +550,7 @@ bool Pad::Freeze(StateWrapper& sw) // But we still need to pull the data from the state.. tempPad = CreatePad(unifiedSlot, type); - pad = tempPad.get(); + pad = tempPad; } if (!pad->Freeze(sw)) diff --git a/pcsx2/SIO/Sio2.cpp b/pcsx2/SIO/Sio2.cpp index f985bcae01183..dfb0ea29fc764 100644 --- a/pcsx2/SIO/Sio2.cpp +++ b/pcsx2/SIO/Sio2.cpp @@ -144,9 +144,7 @@ void Sio2::SetRecv1(u32 value) void Sio2::Pad() { - MultitapProtocol& mtap = (port ? g_MultitapPort1 : g_MultitapPort0); - - // Send PAD our current port, and get back whatever it says the first response byte should be. + MultitapProtocol& mtap = g_MultitapArr.at(port); PadBase* pad = Pad::GetPad(port, mtap.GetPadSlot()); // Update the third nibble with which ports have been accessed @@ -177,10 +175,9 @@ void Sio2::Pad() } g_Sio2FifoOut.push_back(0xff); - - // Then for every byte in g_Sio2FifoIn, pass to PAD and see what it kicks back to us. pad->SoftReset(); + // Then for every byte in g_Sio2FifoIn, pass to PAD and see what it kicks back to us. while (!g_Sio2FifoIn.empty()) { const u8 commandByte = g_Sio2FifoIn.front(); @@ -208,8 +205,8 @@ void Sio2::Multitap() // This bit is always set, whether the pad is present or missing this->recv1 |= Recv1::NO_DEVICES_MISSING; - // If the currently accessed pad is missing, also tick those bits. - // MTAPMAN is special - at least, the variant found in Gauntlet: Dark Legacy. + // If the currently accessed multitap is missing, also tick those bits. + // MTAPMAN is special though. // // For PADMAN and pads, the bits represented by PORT_1_MISSING and PORT_2_MISSING // are always faithful - suppose your game only opened port 2 for some reason, @@ -223,18 +220,7 @@ void Sio2::Multitap() this->recv1 |= Recv1::PORT_1_MISSING; } - switch (this->port) - { - case 0: - g_MultitapPort0.SendToMultitap(); - break; - case 1: - g_MultitapPort1.SendToMultitap(); - break; - default: - Console.Warning("%s() Port value from SEND3 out of bounds! (%d)", __FUNCTION__, this->port); - break; - } + g_MultitapArr.at(this->port).SendToMultitap(); } void Sio2::Infrared() @@ -252,7 +238,7 @@ void Sio2::Infrared() void Sio2::Memcard() { - MultitapProtocol& mtap = (port ? g_MultitapPort1 : g_MultitapPort0); + MultitapProtocol& mtap = g_MultitapArr.at(this->port); mcd = &mcds[port][mtap.GetMemcardSlot()]; @@ -511,7 +497,6 @@ bool Sio2::DoState(StateWrapper& sw) sw.Do(&unknown2); sw.Do(&iStat); sw.Do(&port); - sw.Do(&slot); sw.Do(&send3Read); sw.Do(&send3Position); sw.Do(&commandLength); diff --git a/pcsx2/SIO/Sio2.h b/pcsx2/SIO/Sio2.h index 2f0caac08ab6b..ffe3f5ea6233f 100644 --- a/pcsx2/SIO/Sio2.h +++ b/pcsx2/SIO/Sio2.h @@ -40,7 +40,6 @@ class Sio2 u32 iStat; // 0x1f808280 u8 port = 0; - u8 slot = 0; // The current working index of SEND3. The SEND3 register is a 16 position // array of command descriptors. Each descriptor describes the port the command diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index bed63cc1bd6df..fbe54cc801bc3 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -33,6 +33,7 @@ #include "R3000A.h" #include "SIO/Sio0.h" #include "SIO/Sio2.h" +#include "SIO/Multitap/MultitapProtocol.h" #include "SPU2/spu2.h" #include "SaveState.h" #include "StateWrapper.h" @@ -259,6 +260,9 @@ bool SaveStateBase::FreezeInternals() okay = okay && g_Sio0.DoState(sw); okay = okay && g_Sio2.DoState(sw); + okay = okay && g_MultitapArr.at(0).DoState(sw); + okay = okay && g_MultitapArr.at(1).DoState(sw); + if (!okay || !sw.IsGood()) return false; diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index 6b5c804c9e407..5ee8130d52ff3 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -37,7 +37,7 @@ enum class FreezeAction // [SAVEVERSION+] // This informs the auto updater that the users savestates will be invalidated. -static const u32 g_SaveVersion = (0x9A48 << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A49 << 16) | 0x0000; // the freezing data between submodules and core