From 87c4b1e3568d6def805dfba06a61dc11cd1666c0 Mon Sep 17 00:00:00 2001 From: crediar Date: Sun, 10 Aug 2025 17:33:38 +0200 Subject: [PATCH] Added missing game IDs and titles to game setting files Removed unused code related to s_segaboot Removed unused variable s_segaboot Optimized code related to the AMMB DI Inquiry command Moved AMMB DI commands to their own enum Changed code to not use pointers related to IOFile Removed unused code in DVDInterface::ExecuteCommand() Changed code to use UniqueBuffer instead of new Remove unused code in JVSIOCommand::GeneralDriverOutput Fixed a bug that broke Triforce disc key setup when using NetPlay Made SIDEVICE_AM_BASEBOARD count as an GC controller for SIDevice_IsGCController Added functions for NetPlay: MapPadStatus/HandleButtonCombos/GetData/SendCommand/SetOrigin/HandleMoviePadStatus/GetPadStatus Updated NetPlayClient::UpdateDevices for handling the SIDEVICE_AM_BASEBOARD correctly and not always connect a GC controller Added NetPlay_GetInput/NetPlay_InGamePadToLocalPad function for the AMBaseboard General code formatting Fixed typo in header name --- Data/Sys/GameSettings/SBEY.ini | 2 + Data/Sys/GameSettings/SBGG.ini | 2 + Data/Sys/GameSettings/SBHA.ini | 2 + Data/Sys/GameSettings/SBHN.ini | 2 + Data/Sys/GameSettings/SBHZ.ini | 2 + Data/Sys/GameSettings/SBJA.ini | 2 + Data/Sys/GameSettings/SBLK.ini | 2 + Data/Sys/GameSettings/SBLL.ini | 2 + Source/Core/Core/Boot/Boot_BS2Emu.cpp | 5 +- Source/Core/Core/HW/DVD/AMMediaboard.cpp | 136 ++++------ Source/Core/Core/HW/DVD/AMMediaboard.h | 22 +- Source/Core/Core/HW/DVD/DVDInterface.cpp | 15 +- .../Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp | 62 ++--- Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h | 2 +- Source/Core/Core/HW/GCPadEmu.h | 2 +- Source/Core/Core/HW/SI/SI_Device.cpp | 1 + .../Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp | 255 +++++++++++++++--- Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h | 67 ++++- .../Core/Core/HW/SI/SI_DeviceGCController.h | 3 + Source/Core/Core/NetPlayClient.cpp | 27 +- 20 files changed, 421 insertions(+), 192 deletions(-) diff --git a/Data/Sys/GameSettings/SBEY.ini b/Data/Sys/GameSettings/SBEY.ini index 912626553a..2e79beb657 100644 --- a/Data/Sys/GameSettings/SBEY.ini +++ b/Data/Sys/GameSettings/SBEY.ini @@ -1,2 +1,4 @@ +# SBEY - Virtua Striker 2002 (Export, Japan, Type 3) + [Core] FPRF = True diff --git a/Data/Sys/GameSettings/SBGG.ini b/Data/Sys/GameSettings/SBGG.ini index 412b5048c7..6296633236 100644 --- a/Data/Sys/GameSettings/SBGG.ini +++ b/Data/Sys/GameSettings/SBGG.ini @@ -1,3 +1,5 @@ +# SBGG - F-ZERO AX + [Core] FPRF = True CPUThread = True diff --git a/Data/Sys/GameSettings/SBHA.ini b/Data/Sys/GameSettings/SBHA.ini index 412b5048c7..b62a599c92 100644 --- a/Data/Sys/GameSettings/SBHA.ini +++ b/Data/Sys/GameSettings/SBHA.ini @@ -1,3 +1,5 @@ +# SBHA - F-ZERO AX (Monster) + [Core] FPRF = True CPUThread = True diff --git a/Data/Sys/GameSettings/SBHN.ini b/Data/Sys/GameSettings/SBHN.ini index 912626553a..31be499dca 100644 --- a/Data/Sys/GameSettings/SBHN.ini +++ b/Data/Sys/GameSettings/SBHN.ini @@ -1,2 +1,4 @@ +# SBHN - VIRTUA STRIKER 4 VER.A + [Core] FPRF = True diff --git a/Data/Sys/GameSettings/SBHZ.ini b/Data/Sys/GameSettings/SBHZ.ini index 912626553a..a15b861658 100644 --- a/Data/Sys/GameSettings/SBHZ.ini +++ b/Data/Sys/GameSettings/SBHZ.ini @@ -1,2 +1,4 @@ +# SBHZ - VIRTUA STRIKER 4 (Asia) + [Core] FPRF = True diff --git a/Data/Sys/GameSettings/SBJA.ini b/Data/Sys/GameSettings/SBJA.ini index 912626553a..028fd4b6c0 100644 --- a/Data/Sys/GameSettings/SBJA.ini +++ b/Data/Sys/GameSettings/SBJA.ini @@ -1,2 +1,4 @@ +# SBJA - VIRTUA STRIKER 4 (Export) + [Core] FPRF = True diff --git a/Data/Sys/GameSettings/SBLK.ini b/Data/Sys/GameSettings/SBLK.ini index 912626553a..8931c60490 100644 --- a/Data/Sys/GameSettings/SBLK.ini +++ b/Data/Sys/GameSettings/SBLK.ini @@ -1,2 +1,4 @@ +# SBLK - VIRTUA STRIKER 4 Ver.2006 (Japan) + [Core] FPRF = True diff --git a/Data/Sys/GameSettings/SBLL.ini b/Data/Sys/GameSettings/SBLL.ini index 912626553a..deb8b08379 100644 --- a/Data/Sys/GameSettings/SBLL.ini +++ b/Data/Sys/GameSettings/SBLL.ini @@ -1,2 +1,4 @@ +# SBLL - VIRTUA STRIKER 4 Ver.2006 (Export) + [Core] FPRF = True diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index 57112245db..01a7a97caf 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -229,10 +229,7 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard branch_watch.SetRecordingActive(guard, resume_branch_watch); - // Check for Triforce board being connected - const ExpansionInterface::EXIDeviceType Type = Config::Get(Config::MAIN_SERIAL_PORT_1); - bool enable_gcam = (Type == ExpansionInterface::EXIDeviceType::Baseboard) ? 1 : 0; - if (enable_gcam) + if (system.IsTriforce()) { auto& memory = system.GetMemory(); u32 dsize = volume.GetDataSize(); diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.cpp b/Source/Core/Core/HW/DVD/AMMediaboard.cpp index 6aecfb6370..8af430f090 100644 --- a/Source/Core/Core/HW/DVD/AMMediaboard.cpp +++ b/Source/Core/Core/HW/DVD/AMMediaboard.cpp @@ -81,8 +81,7 @@ static int WSAGetLastError(void) namespace AMMediaboard { -static bool s_firmwaremap = false; -static bool s_segaboot = false; +static bool s_firmware_map = false; static bool s_test_menu = false; static SOCKET s_namco_cam = 0; static u32 s_timeouts[3] = {20000, 20000, 20000}; @@ -92,11 +91,11 @@ static u32 s_GCAM_key_a = 0; static u32 s_GCAM_key_b = 0; static u32 s_GCAM_key_c = 0; -static File::IOFile* s_netcfg = nullptr; -static File::IOFile* s_netctrl = nullptr; -static File::IOFile* s_extra = nullptr; -static File::IOFile* s_backup = nullptr; -static File::IOFile* s_dimm = nullptr; +static File::IOFile s_netcfg = nullptr; +static File::IOFile s_netctrl = nullptr; +static File::IOFile s_extra = nullptr; +static File::IOFile s_backup = nullptr; +static File::IOFile s_dimm = nullptr; static u8* s_dimm_disc = nullptr; @@ -157,7 +156,7 @@ static inline void PrintMBBuffer(u32 address, u32 length) void FirmwareMap(bool on) { - s_firmwaremap = on; + s_firmware_map = on; } void InitKeys(u32 key_a, u32 key_b, u32 key_c) @@ -167,14 +166,14 @@ void InitKeys(u32 key_a, u32 key_b, u32 key_c) s_GCAM_key_c = key_c; } -static File::IOFile* OpenOrCreateFile(const std::string& filename) +static File::IOFile OpenOrCreateFile(const std::string& filename) { // Try opening for read/write first if (File::Exists(filename)) - return new File::IOFile(filename, "rb+"); + return File::IOFile(filename, "rb+"); // Create new file - return new File::IOFile(filename, "wb+"); + return File::IOFile(filename, "wb+"); } void Init(void) @@ -185,8 +184,7 @@ void Init(void) memset(s_firmware, -1, sizeof(s_firmware)); memset(s_sockets, SOCKET_ERROR, sizeof(s_sockets)); - s_segaboot = false; - s_firmwaremap = false; + s_firmware_map = false; s_test_menu = false; s_last_error = SSC_SUCCESS; @@ -203,15 +201,15 @@ void Init(void) s_dimm = OpenOrCreateFile(base_path + "tridimm_" + SConfig::GetInstance().GetGameID() + ".bin"); s_backup = OpenOrCreateFile(base_path + "backup_" + SConfig::GetInstance().GetGameID() + ".bin"); - if (!s_netcfg) + if (!s_netcfg.IsOpen()) PanicAlertFmt("Failed to open/create: {}", base_path + "s_netcfg.bin"); - if (!s_netctrl) + if (!s_netctrl.IsOpen()) PanicAlertFmt("Failed to open/create: {}", base_path + "s_netctrl.bin"); - if (!s_extra) + if (!s_extra.IsOpen()) PanicAlertFmt("Failed to open/create: {}", base_path + "s_extra.bin"); - if (!s_dimm) + if (!s_dimm.IsOpen()) PanicAlertFmt("Failed to open/create: {}", base_path + "s_dimm.bin"); - if (!s_backup) + if (!s_backup.IsOpen()) PanicAlertFmt("Failed to open/create: {}", base_path + "s_backup.bin"); // This is the firmware for the Triforce @@ -252,7 +250,7 @@ u8* InitDIMM(u32 size) } } - s_firmwaremap = 0; + s_firmware_map = 0; return s_dimm_disc; } @@ -396,7 +394,7 @@ static void FileWriteData(File::IOFile* file, u32 seek_pos, const u8* data, size file->WriteBytes(data, length); file->Flush(); } -u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) +u32 ExecuteCommand(std::array& DICMDBUF, u32* DIIMMBUF, u32 address, u32 length) { auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); @@ -413,8 +411,8 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) /* Key setup for Triforce IPL: - These RAM offset always hold the keys for the next command and since it sends two dummy - commands before a real read we can just use the key from RAM without missing any real commands. +These RAM offsets always hold the key for the next command. Since two dummy commands are sent before +any real ones, you can just use the key from RAM without missing a real command. */ if (s_GCAM_key_a == 0) { @@ -430,13 +428,6 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) u32 command = DICMDBUF[0] << 24; u32 offset = DICMDBUF[1] << 2; - // SegaBoot adds bits for some reason to offset/length - // also adds 0x20 to offset - if (offset == 0x00100440) - { - s_segaboot = true; - } - INFO_LOG_FMT(DVDINTERFACE_AMMB, "GC-AM: {:08x} {:08x} DMA=addr:{:08x},len:{:08x} Keys: {:08x} {:08x} {:08x}", command, offset, address, length, s_GCAM_key_a, s_GCAM_key_b, s_GCAM_key_c); @@ -450,33 +441,34 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) // Don't map firmware while in SegaBoot if (memory.Read_U32(0x8006BF70) != 0x0A536567) { - s_firmwaremap = 1; + s_firmware_map = 1; } } } - switch (AMMBCommand(command >> 24)) + switch (AMMBDICommand(command >> 24)) { - case AMMBCommand::Inquiry: - if (s_firmwaremap) + case AMMBDICommand::Inquiry: + if (s_firmware_map) { - s_firmwaremap = false; - s_segaboot = false; + s_firmware_map = false; } // Returned value is used to set the protocol version. switch (GetGameType()) { default: - return Version1; + *DIIMMBUF = Version1; + return 0; case KeyOfAvalon: case MarioKartGP: case MarioKartGP2: case FirmwareUpdate: - return Version2; + *DIIMMBUF = Version2; + return 0; } break; - case AMMBCommand::Read: + case AMMBDICommand::Read: if ((offset & 0x8FFF0000) == 0x80000000) { switch (offset) @@ -523,16 +515,16 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) // Network configuration if (offset == 0x00000000 && length == 0x80) { - s_netcfg->Seek(0, File::SeekOrigin::Begin); - s_netcfg->ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_netcfg.Seek(0, File::SeekOrigin::Begin); + s_netcfg.ReadBytes(memory.GetSpanForAddress(address).data(), length); return 0; } // media crc check on/off if (offset == DIMMExtraSettings && length == 0x20) { - s_extra->Seek(0, File::SeekOrigin::Begin); - s_extra->ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_extra.Seek(0, File::SeekOrigin::Begin); + s_extra.ReadBytes(memory.GetSpanForAddress(address).data(), length); return 0; } @@ -540,8 +532,8 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) if (offset >= DIMMMemory && offset <= 0x1F800000) { u32 dimmoffset = offset - DIMMMemory; - s_dimm->Seek(dimmoffset, File::SeekOrigin::Begin); - s_dimm->ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_dimm.Seek(dimmoffset, File::SeekOrigin::Begin); + s_dimm.ReadBytes(memory.GetSpanForAddress(address).data(), length); return 0; } @@ -1044,15 +1036,15 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) if (offset >= DIMMMemory2 && offset <= 0xFF800000) { u32 dimmoffset = offset - DIMMMemory2; - s_dimm->Seek(dimmoffset, File::SeekOrigin::Begin); - s_dimm->ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_dimm.Seek(dimmoffset, File::SeekOrigin::Begin); + s_dimm.ReadBytes(memory.GetSpanForAddress(address).data(), length); return 0; } if (offset == NetworkControl && length == 0x20) { - s_netctrl->Seek(0, File::SeekOrigin::Begin); - s_netctrl->ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_netctrl.Seek(0, File::SeekOrigin::Begin); + s_netctrl.ReadBytes(memory.GetSpanForAddress(address).data(), length); return 0; } @@ -1063,13 +1055,8 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) return 0; } - if (s_firmwaremap) + if (s_firmware_map) { - if (s_segaboot) - { - DICMDBUF[1] &= ~0x00100000; - DICMDBUF[1] -= 0x20; - } memcpy(memory.GetSpanForAddress(address).data(), s_firmware + offset, length); return 0; } @@ -1082,23 +1069,23 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) return 1; break; - case AMMBCommand::Write: + case AMMBDICommand::Write: /* These two magic writes allow a new firmware to be programmed */ if ((offset == FirmwareMagicWrite1) && (length == 0x20)) { - s_firmwaremap = true; + s_firmware_map = true; return 0; } if ((offset == FirmwareMagicWrite2) && (length == 0x20)) { - s_firmwaremap = true; + s_firmware_map = true; return 0; } - if (s_firmwaremap) + if (s_firmware_map) { // Firmware memory (2MB) if ((offset >= 0x00400000) && (offset <= 0x600000)) @@ -1112,21 +1099,21 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) // Network configuration if ((offset == 0x00000000) && (length == 0x80)) { - FileWriteData(s_netcfg, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_netcfg, 0, memory.GetSpanForAddress(address).data(), length); return 0; } // media crc check on/off if ((offset == DIMMExtraSettings) && (length == 0x20)) { - FileWriteData(s_extra, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_extra, 0, memory.GetSpanForAddress(address).data(), length); return 0; } // Backup memory (8MB) if ((offset >= BackupMemory) && (offset <= 0x00800000)) { - FileWriteData(s_backup, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_backup, 0, memory.GetSpanForAddress(address).data(), length); return 0; } @@ -1134,7 +1121,7 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) if ((offset >= DIMMMemory) && (offset <= 0x1F800000)) { u32 dimmoffset = offset - DIMMMemory; - FileWriteData(s_dimm, dimmoffset, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_dimm, dimmoffset, memory.GetSpanForAddress(address).data(), length); return 0; } @@ -1320,13 +1307,13 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) if ((offset >= DIMMMemory2) && (offset <= 0xFF800000)) { u32 dimmoffset = offset - 0xFF000000; - FileWriteData(s_dimm, dimmoffset, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_dimm, dimmoffset, memory.GetSpanForAddress(address).data(), length); return 0; } if ((offset == NetworkControl) && (length == 0x20)) { - FileWriteData(s_netctrl, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_netctrl, 0, memory.GetSpanForAddress(address).data(), length); return 0; } @@ -1337,7 +1324,7 @@ u32 ExecuteCommand(std::array& DICMDBUF, u32 address, u32 length) PanicAlertFmtT("Unhandled Media Board Write:{0:08x}", offset); } break; - case AMMBCommand::Execute: + case AMMBDICommand::Execute: if ((offset == 0) && (length == 0)) { // Recast for easier access @@ -1818,20 +1805,11 @@ bool GetTestMenu(void) } void Shutdown(void) { - if (s_netcfg) - s_netcfg->Close(); - - if (s_netctrl) - s_netctrl->Close(); - - if (s_extra) - s_extra->Close(); - - if (s_backup) - s_backup->Close(); - - if (s_dimm) - s_dimm->Close(); + s_netcfg.Close(); + s_netctrl.Close(); + s_extra.Close(); + s_backup.Close(); + s_dimm.Close(); if (s_dimm_disc) { diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.h b/Source/Core/Core/HW/DVD/AMMediaboard.h index 192a551331..d41894f23a 100644 --- a/Source/Core/Core/HW/DVD/AMMediaboard.h +++ b/Source/Core/Core/HW/DVD/AMMediaboard.h @@ -32,7 +32,7 @@ enum GameType VirtuaStriker4, GekitouProYakyuu, KeyOfAvalon, - FirmwareUpdate + FirmwareUpdate, }; enum MediaType { @@ -54,28 +54,32 @@ enum MediaBoardStatus TestingGameProgram = 3, LoadingGameProgram = 4, LoadedGameProgram = 5, - Error = 6 + Error = 6, }; enum InquiryType { Version1 = 0x21484100, - Version2 = 0x29484100 + Version2 = 0x29484100, }; #define SocketCheck(x) (x <= 0x3F ? x : 0) namespace AMMediaboard { + +enum class AMMBDICommand : u16 +{ + Inquiry = 0x12, + Read = 0xA8, + Write = 0xAA, + Execute = 0xAB, +}; + enum class AMMBCommand : u16 { Unknown_000 = 0x000, GetDIMMSize = 0x001, - Inquiry = 0x12, - Read = 0xa8, - Write = 0xaa, - Execute = 0xab, - GetMediaBoardStatus = 0x100, GetSegaBootVersion = 0x101, GetSystemFlags = 0x102, @@ -209,7 +213,7 @@ void Init(void); void FirmwareMap(bool on); u8* InitDIMM(u32 size); void InitKeys(u32 KeyA, u32 KeyB, u32 KeyC); -u32 ExecuteCommand(std::array& DICMDBUF, u32 Address, u32 Length); +u32 ExecuteCommand(std::array& DICMDBUF, u32* DIIMMBUF, u32 Address, u32 Length); u32 GetGameType(void); u32 GetMediaType(void); bool GetTestMenu(void); diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index 6b81eafa08..5ed8e03524 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -766,12 +766,8 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type) if (m_system.IsTriforce()) { - u32 ret = AMMediaboard::ExecuteCommand(m_DICMDBUF, m_DIMAR, m_DILENGTH); - if (ret != 1) + if (!AMMediaboard::ExecuteCommand(m_DICMDBUF, &m_DIIMMBUF, m_DIMAR, m_DILENGTH)) { - if (m_DICMDBUF[0] == 0x12000000) - m_DIIMMBUF = ret; - // Transfer is done m_DICR.TSTART = 0; m_DIMAR += m_DILENGTH; @@ -784,15 +780,6 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type) // Normal read command pass on to normal handling } - // Swaps endian of Triforce DI commands, and zeroes out random bytes to prevent unknown read - // subcommand errors - auto& dvd_thread = m_system.GetDVDThread(); - if (dvd_thread.HasDisc() && dvd_thread.GetDiscType() == DiscIO::Platform::Triforce) - { - // TODO(C++23): Use std::byteswap and a bitwise AND for increased clarity - m_DICMDBUF[0] <<= 24; - } - // DVDLowRequestError needs access to the error code set by the previous command if (static_cast(m_DICMDBUF[0] >> 24) != DICommand::RequestError) SetDriveError(DriveError::None); diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp index e728aaf250..46aff6f009 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp @@ -16,6 +16,7 @@ #include "Common/IOFile.h" #include "Common/IniFile.h" #include "Common/Logging/Log.h" +#include "Common/Buffer.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/Config/MainSettings.h" @@ -76,17 +77,14 @@ CEXIBaseboard::CEXIBaseboard(Core::System& system) : IEXIDevice(system), m_posit std::string backup_Filename(File::GetUserPath(D_TRIUSER_IDX) + "tribackup_" + SConfig::GetInstance().GetGameID().c_str() + ".bin"); - if (File::Exists(backup_Filename)) + m_backup = File::IOFile(backup_Filename, "rb+"); + if (!m_backup.IsOpen()) { - m_backup = new File::IOFile(backup_Filename, "rb+"); - } - else - { - m_backup = new File::IOFile(backup_Filename, "wb+"); + m_backup = File::IOFile(backup_Filename, "wb+"); } // Some games share the same ID Client/Server - if (!m_backup->IsGood()) + if (!m_backup.IsGood()) { PanicAlertFmt("Failed to open {}\nFile might be in use.", backup_Filename.c_str()); @@ -95,7 +93,7 @@ CEXIBaseboard::CEXIBaseboard(Core::System& system) : IEXIDevice(system), m_posit backup_Filename = File::GetUserPath(D_TRIUSER_IDX) + "tribackup_tmp_" + std::to_string(rand()) + SConfig::GetInstance().GetGameID().c_str() + ".bin"; - m_backup = new File::IOFile(backup_Filename, "wb+"); + m_backup = File::IOFile(backup_Filename, "wb+"); } // Virtua Striker 4 and Gekitou Pro Yakyuu need a higher FIRM version @@ -103,32 +101,28 @@ CEXIBaseboard::CEXIBaseboard(Core::System& system) : IEXIDevice(system), m_posit if (AMMediaboard::GetGameType() == VirtuaStriker4 || AMMediaboard::GetGameType() == GekitouProYakyuu) { - if (m_backup->GetSize() != 0) + if (m_backup.GetSize() != 0) { - u8* data = new u8[m_backup->GetSize()]; - - m_backup->ReadBytes(data, m_backup->GetSize()); + Common::UniqueBuffer data(m_backup.GetSize()); + m_backup.ReadBytes(data.data(), data.size()); // Set FIRM version - *(u16*)(data + 0x12) = 0x1703; - *(u16*)(data + 0x212) = 0x1703; + reinterpret_cast(data[0x12]) = 0x1703; + reinterpret_cast(data[0x212]) = 0x1703; // Update checksum - *(u16*)(data + 0x0A) = Common::swap16(CheckSum(data + 0xC, 0x1F4)); - *(u16*)(data + 0x20A) = Common::swap16(CheckSum(data + 0x20C, 0x1F4)); + reinterpret_cast(data[0x0A]) = Common::swap16(CheckSum(&data[0xC], 0x1F4)); + reinterpret_cast(data[0x20A]) = Common::swap16(CheckSum(&data[0x20C], 0x1F4)); - m_backup->Seek(0, File::SeekOrigin::Begin); - m_backup->WriteBytes(data, m_backup->GetSize()); - m_backup->Flush(); - - delete[] data; + m_backup.Seek(0, File::SeekOrigin::Begin); + m_backup.WriteBytes(data.data(), data.size()); + m_backup.Flush(); } } } CEXIBaseboard::~CEXIBaseboard() { - m_backup->Close(); - delete m_backup; + m_backup.Close(); } void CEXIBaseboard::SetCS(int cs) @@ -165,11 +159,11 @@ void CEXIBaseboard::DMAWrite(u32 addr, u32 size) NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Write: {:08x} {:x}", addr, size); - m_backup->Seek(m_backoffset, File::SeekOrigin::Begin); + m_backup.Seek(m_backoffset, File::SeekOrigin::Begin); - m_backup->WriteBytes(memory.GetSpanForAddress(addr).data(), size); + m_backup.WriteBytes(memory.GetSpanForAddress(addr).data(), size); - m_backup->Flush(); + m_backup.Flush(); } void CEXIBaseboard::DMARead(u32 addr, u32 size) @@ -179,11 +173,11 @@ void CEXIBaseboard::DMARead(u32 addr, u32 size) NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Read: {:08x} {:x}", addr, size); - m_backup->Seek(m_backoffset, File::SeekOrigin::Begin); + m_backup.Seek(m_backoffset, File::SeekOrigin::Begin); - m_backup->Flush(); + m_backup.Flush(); - m_backup->ReadBytes(memory.GetSpanForAddress(addr).data(), size); + m_backup.ReadBytes(memory.GetSpanForAddress(addr).data(), size); } void CEXIBaseboard::TransferByte(u8& _byte) @@ -225,13 +219,13 @@ void CEXIBaseboard::TransferByte(u8& _byte) case BackupOffsetSet: m_backoffset = (m_command[1] << 8) | m_command[2]; DEBUG_LOG_FMT(SP1, "AM-BB: COMMAND: BackupOffsetSet:{:04x}", m_backoffset); - m_backup->Seek(m_backoffset, File::SeekOrigin::Begin); + m_backup.Seek(m_backoffset, File::SeekOrigin::Begin); _byte = 0x01; break; case BackupWrite: DEBUG_LOG_FMT(SP1, "AM-BB: COMMAND: BackupWrite:{:04x}-{:02x}", m_backoffset, m_command[1]); - m_backup->WriteBytes(&m_command[1], 1); - m_backup->Flush(); + m_backup.WriteBytes(&m_command[1], 1); + m_backup.Flush(); _byte = 0x01; break; case BackupRead: @@ -292,8 +286,8 @@ void CEXIBaseboard::TransferByte(u8& _byte) { // 1 byte out case BackupRead: - m_backup->Flush(); - m_backup->ReadBytes(&_byte, 1); + m_backup.Flush(); + m_backup.ReadBytes(&_byte, 1); break; case DMAOffsetLengthSet: _byte = 0x01; diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h index 8fdc7d8ffd..ccc8b45a8f 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h @@ -59,7 +59,7 @@ private: u32 m_backup_dma_length; u8 m_command[4]; u16 m_backoffset; - File::IOFile* m_backup; + File::IOFile m_backup; protected: void TransferByte(u8& _uByte) override; diff --git a/Source/Core/Core/HW/GCPadEmu.h b/Source/Core/Core/HW/GCPadEmu.h index 1918b34659..6e244d139f 100644 --- a/Source/Core/Core/HW/GCPadEmu.h +++ b/Source/Core/Core/HW/GCPadEmu.h @@ -30,7 +30,7 @@ enum class PadGroup Rumble, Mic, Options, - Triforce + Triforce, }; class GCPad : public ControllerEmu::EmulatedController diff --git a/Source/Core/Core/HW/SI/SI_Device.cpp b/Source/Core/Core/HW/SI/SI_Device.cpp index 2bfd150bea..c826cf345b 100644 --- a/Source/Core/Core/HW/SI/SI_Device.cpp +++ b/Source/Core/Core/HW/SI/SI_Device.cpp @@ -140,6 +140,7 @@ bool SIDevice_IsGCController(SIDevices type) case SIDEVICE_GC_TARUKONGA: case SIDEVICE_DANCEMAT: case SIDEVICE_GC_STEERING: + case SIDEVICE_AM_BASEBOARD: return true; default: return false; diff --git a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp index cf8f833a48..9675d2d50e 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp @@ -13,6 +13,8 @@ #include +#include "Common/Buffer.h" +#include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Config/Config.h" #include "Common/FileUtil.h" @@ -20,6 +22,8 @@ #include "Common/IOFile.h" #include "Common/IniFile.h" #include "Common/Logging/Log.h" +#include "Common/MsgHandler.h" +#include "Common/Swap.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/Config/MainSettings.h" @@ -28,15 +32,19 @@ #include "Core/ConfigLoaders/NetPlayConfigLoader.h" #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "Core/CoreTiming.h" #include "Core/HW/DVD/AMMediaboard.h" #include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/EXI/EXI.h" +#include "Core/HW/GCPad.h" #include "Core/HW/MMIO.h" #include "Core/HW/Memmap.h" +#include "Core/HW/ProcessorInterface.h" #include "Core/HW/SI/SI.h" #include "Core/HW/SI/SI_Device.h" #include "Core/HW/SI/SI_DeviceGCController.h" #include "Core/HW/Sram.h" +#include "Core/HW/SystemTimers.h" #include "Core/HW/WiimoteReal/WiimoteReal.h" #include "Core/Movie.h" #include "Core/NetPlayProto.h" @@ -44,6 +52,7 @@ #include "Core/System.h" #include "Core/WiiRoot.h" #include "DiscIO/Enums.h" +#include "InputCommon/GCPadStatus.h" namespace SerialInterface { @@ -1997,7 +2006,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) break; } - u8* buf = new u8[bytes]; + Common::UniqueBuffer buf(bytes); for (u32 i = 0; i < bytes; ++i) { @@ -2008,32 +2017,12 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) SERIALINTERFACE_JVSIO, "JVS-IO: Command 0x32, GPO: {:02x} {:02x} {} {:02x}{:02x}{:02x} ({:02x})", delay, m_rx_reply, bytes, buf[0], buf[1], buf[2], - Common::swap16(*(u16*)(buf + 1)) >> 2); + Common::swap16(*reinterpret_cast(&buf[1])) >> 2); - // TODO: figure this out - - u8 trepl[] = { - 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, - 0xD0, 0xE0, 0xF0, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, - 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, - 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, 0x04, 0x14, 0x24, 0x34, - 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, - 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, - 0xE5, 0xF5, 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 0x86, 0x96, 0xA6, - 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, - 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, 0x09, 0x19, 0x29, 0x39, 0x49, - 0x59, 0x69, 0x79, 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, 0x0A, 0x1A, - 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, - 0xFA, 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, - 0xCC, 0xDC, 0xEC, 0xFC, 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, 0x8D, - 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, - 0x6E, 0x7E, 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE}; - - static u32 off = 0; - if (off > sizeof(trepl)) - off = 0; - - switch (Common::swap16(*(u16*)(buf + 1)) >> 2) + /* + Handling of the motion seat used in F-Zero AXs DX version + */ + switch (Common::swap16(*reinterpret_cast(&buf[1])) >> 2) { case 0x70: delay++; @@ -2050,13 +2039,6 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) case 0x60: break; } - ////if( buf[1] == 1 && buf[2] == 0x80 ) - ////{ - //// INFO_LOG_FMT(DVDINTERFACE, "GCAM: PC:{:08x}", PC); - //// PowerPC::breakpoints.Add( PC+8, false ); - ////} - - delete[] buf; } break; } @@ -2080,7 +2062,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) else { message.addData(StatusOkay); - ERROR_LOG_FMT(SERIALINTERFACE_JVSIO, "JVS-IO:Unknown:{:02x}", cmd_); + ERROR_LOG_FMT(SERIALINTERFACE_JVSIO, "JVS-IO: Unknown:{:02x}", cmd_); } break; } @@ -2170,19 +2152,210 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) return buffer_position; } -// Unused -DataResponse CSIDevice_AMBaseboard::GetData(u32& _Hi, u32& _Low) +u32 CSIDevice_AMBaseboard::MapPadStatus(const GCPadStatus& pad_status) { - _Low = 0; - _Hi = 0x00800000; + // Thankfully changing mode does not change the high bits ;) + u32 hi = 0; + hi = pad_status.stickY; + hi |= pad_status.stickX << 8; + hi |= (pad_status.button | PAD_USE_ORIGIN) << 16; + return hi; +} + +CSIDevice_AMBaseboard::EButtonCombo +CSIDevice_AMBaseboard::HandleButtonCombos(const GCPadStatus& pad_status) +{ + // Keep track of the special button combos (embedded in controller hardware... :( ) + EButtonCombo temp_combo; + if ((pad_status.button & 0xff00) == (PAD_BUTTON_Y | PAD_BUTTON_X | PAD_BUTTON_START)) + temp_combo = COMBO_ORIGIN; + else if ((pad_status.button & 0xff00) == (PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_START)) + temp_combo = COMBO_RESET; + else + temp_combo = COMBO_NONE; + + if (temp_combo != m_last_button_combo) + { + m_last_button_combo = temp_combo; + if (m_last_button_combo != COMBO_NONE) + m_timer_button_combo_start = m_system.GetCoreTiming().GetTicks(); + } + + if (m_last_button_combo != COMBO_NONE) + { + const u64 current_time = m_system.GetCoreTiming().GetTicks(); + const u32 ticks_per_second = m_system.GetSystemTimers().GetTicksPerSecond(); + if (u32(current_time - m_timer_button_combo_start) > ticks_per_second * 3) + { + if (m_last_button_combo == COMBO_RESET) + { + INFO_LOG_FMT(SERIALINTERFACE, "PAD - COMBO_RESET"); + m_system.GetProcessorInterface().ResetButton_Tap(); + } + else if (m_last_button_combo == COMBO_ORIGIN) + { + INFO_LOG_FMT(SERIALINTERFACE, "PAD - COMBO_ORIGIN"); + SetOrigin(pad_status); + } + + m_last_button_combo = COMBO_NONE; + return temp_combo; + } + } + + return COMBO_NONE; +} + +// GetData + +// Return true on new data (max 7 Bytes and 6 bits ;) +// [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r] +// |\_ ERR_LATCH (error latched - check SISR) +// |_ ERR_STATUS (error on last GetData or SendCmd?) +DataResponse CSIDevice_AMBaseboard::GetData(u32& hi, u32& low) +{ + GCPadStatus pad_status = GetPadStatus(); + + if (!pad_status.isConnected) + return DataResponse::ErrorNoResponse; + + if (HandleButtonCombos(pad_status) == COMBO_ORIGIN) + pad_status.button |= PAD_GET_ORIGIN; + + hi = MapPadStatus(pad_status); + + // Low bits are packed differently per mode + if (m_mode == 0 || m_mode == 5 || m_mode == 6 || m_mode == 7) + { + low = (pad_status.analogB >> 4); // Top 4 bits + low |= ((pad_status.analogA >> 4) << 4); // Top 4 bits + low |= ((pad_status.triggerRight >> 4) << 8); // Top 4 bits + low |= ((pad_status.triggerLeft >> 4) << 12); // Top 4 bits + low |= ((pad_status.substickY) << 16); // All 8 bits + low |= ((pad_status.substickX) << 24); // All 8 bits + } + else if (m_mode == 1) + { + low = (pad_status.analogB >> 4); // Top 4 bits + low |= ((pad_status.analogA >> 4) << 4); // Top 4 bits + low |= (pad_status.triggerRight << 8); // All 8 bits + low |= (pad_status.triggerLeft << 16); // All 8 bits + low |= ((pad_status.substickY >> 4) << 24); // Top 4 bits + low |= ((pad_status.substickX >> 4) << 28); // Top 4 bits + } + else if (m_mode == 2) + { + low = pad_status.analogB; // All 8 bits + low |= pad_status.analogA << 8; // All 8 bits + low |= ((pad_status.triggerRight >> 4) << 16); // Top 4 bits + low |= ((pad_status.triggerLeft >> 4) << 20); // Top 4 bits + low |= ((pad_status.substickY >> 4) << 24); // Top 4 bits + low |= ((pad_status.substickX >> 4) << 28); // Top 4 bits + } + else if (m_mode == 3) + { + // Analog A/B are always 0 + low = pad_status.triggerRight; // All 8 bits + low |= (pad_status.triggerLeft << 8); // All 8 bits + low |= (pad_status.substickY << 16); // All 8 bits + low |= (pad_status.substickX << 24); // All 8 bits + } + else if (m_mode == 4) + { + low = pad_status.analogB; // All 8 bits + low |= pad_status.analogA << 8; // All 8 bits + // triggerLeft/Right are always 0 + low |= pad_status.substickY << 16; // All 8 bits + low |= pad_status.substickX << 24; // All 8 bits + } return DataResponse::Success; } -void CSIDevice_AMBaseboard::SendCommand(u32 _Cmd, u8 _Poll) +void CSIDevice_AMBaseboard::SendCommand(u32 command, u8 poll) { - ERROR_LOG_FMT(SERIALINTERFACE, "Unknown direct command (0x{})", _Cmd); - PanicAlertFmt("SI: (GCAM) Unknown direct command"); + UCommand controller_command(command); + + if (static_cast(controller_command.command) == EDirectCommands::CMD_WRITE) + { + const u32 type = controller_command.parameter1; // 0 = stop, 1 = rumble, 2 = stop hard + + // get the correct pad number that should rumble locally when using netplay + const int pad_num = NetPlay_InGamePadToLocalPad(m_device_number); + + if (pad_num < 4) + { + const SIDevices device = m_system.GetSerialInterface().GetDeviceType(pad_num); + if (type == 1) + CSIDevice_GCController::Rumble(pad_num, 1.0, device); + else + CSIDevice_GCController::Rumble(pad_num, 0.0, device); + } + + if (poll == 0) + { + m_mode = controller_command.parameter2; + INFO_LOG_FMT(SERIALINTERFACE, "PAD {} set to mode {}", m_device_number, m_mode); + } + } + else if (controller_command.command != 0x00) + { + // Costis sent 0x00 in some demos :) + ERROR_LOG_FMT(SERIALINTERFACE, "Unknown direct command ({:#x})", command); + PanicAlertFmt("SI: Unknown direct command"); + } +} + +void CSIDevice_AMBaseboard::SetOrigin(const GCPadStatus& pad_status) +{ + m_origin.origin_stick_x = pad_status.stickX; + m_origin.origin_stick_y = pad_status.stickY; + m_origin.substick_x = pad_status.substickX; + m_origin.substick_y = pad_status.substickY; + m_origin.trigger_left = pad_status.triggerLeft; + m_origin.trigger_right = pad_status.triggerRight; +} + +void CSIDevice_AMBaseboard::HandleMoviePadStatus(Movie::MovieManager& movie, int device_number, + GCPadStatus* pad_status) +{ + movie.SetPolledDevice(); + if (NetPlay_GetInput(device_number, pad_status)) + { + } + else if (movie.IsPlayingInput()) + { + movie.PlayController(pad_status, device_number); + movie.InputUpdate(); + } + else if (movie.IsRecordingInput()) + { + movie.RecordInput(pad_status, device_number); + movie.InputUpdate(); + } + else + { + movie.CheckPadStatus(pad_status, device_number); + } +} + +GCPadStatus CSIDevice_AMBaseboard::GetPadStatus() +{ + GCPadStatus pad_status = {}; + + // For netplay, the local controllers are polled in GetNetPads(), and + // the remote controllers receive their status there as well + if (!NetPlay::IsNetPlayRunning()) + { + pad_status = Pad::GetStatus(m_device_number); + } + + // Our GCAdapter code sets PAD_GET_ORIGIN when a new device has been connected. + // Watch for this to calibrate real controllers on connection. + if (pad_status.button & PAD_GET_ORIGIN) + SetOrigin(pad_status); + + return pad_status; } } // namespace SerialInterface diff --git a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h index dc79df72a3..e7ca8574e0 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h +++ b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h @@ -4,15 +4,18 @@ #pragma once #include -#include -#include -#include -#include -#include +#include #include "Common/CommonTypes.h" #include "Common/Flag.h" +#include "Core/HW/GCPad.h" #include "Core/HW/SI/SI_Device.h" +#include "InputCommon/GCPadStatus.h" + +namespace Movie +{ +class MovieManager; +} namespace SerialInterface { @@ -229,7 +232,7 @@ private: u32 m_fzdx_sensor_left; u8 m_rx_reply; - // F-Zero AX (CryCraft) + // F-Zero AX (CyCraft) u32 m_fzcc_seatbelt; u32 m_fzcc_sensor; u32 m_fzcc_emergency; @@ -237,6 +240,44 @@ private: void ICCardSendReply(ICCommand* iccommand, u8* buffer, u32* length); +protected: + struct SOrigin + { + u16 button; + u8 origin_stick_x; + u8 origin_stick_y; + u8 substick_x; + u8 substick_y; + u8 trigger_left; + u8 trigger_right; + u8 unk_4; + u8 unk_5; + }; + + enum EButtonCombo + { + COMBO_NONE = 0, + COMBO_ORIGIN, + COMBO_RESET + }; + + // struct to compare input against + // Set on connection to perfect neutral values + // (standard pad only) Set on button combo to current input state + SOrigin m_origin = {}; + + // PADAnalogMode + // Dunno if we need to do this, game/lib should set it? + u8 m_mode = 0x3; + + // Timer to track special button combos: + // y, X, start for 3 seconds updates origin with current status + // Technically, the above is only on standard pad, wavebird does not support it for example + // b, x, start for 3 seconds triggers reset (PI reset button interrupt) + u64 m_timer_button_combo_start = 0; + // Type of button combo from the last/current poll + EButtonCombo m_last_button_combo = COMBO_NONE; + public: // constructor CSIDevice_AMBaseboard(Core::System& system, SIDevices device, int device_number); @@ -249,6 +290,20 @@ public: // send a command directly void SendCommand(u32 command, u8 poll) override; + + virtual GCPadStatus GetPadStatus(); + virtual u32 MapPadStatus(const GCPadStatus& pad_status); + virtual EButtonCombo HandleButtonCombos(const GCPadStatus& pad_status); + + static void HandleMoviePadStatus(Movie::MovieManager& movie, int device_number, + GCPadStatus* pad_status); + + // Send and Receive pad input from network + static bool NetPlay_GetInput(int pad_num, GCPadStatus* status); + static int NetPlay_InGamePadToLocalPad(int pad_num); + +protected: + void SetOrigin(const GCPadStatus& pad_status); }; } // namespace SerialInterface diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCController.h b/Source/Core/Core/HW/SI/SI_DeviceGCController.h index 19b5bdb14b..f4dc5768c9 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceGCController.h +++ b/Source/Core/Core/HW/SI/SI_DeviceGCController.h @@ -3,8 +3,11 @@ #pragma once +#include #include +#include "Common/CommonTypes.h" +#include "Common/Flag.h" #include "Core/HW/GCPad.h" #include "Core/HW/SI/SI_Device.h" #include "InputCommon/GCPadStatus.h" diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 3f4344ad88..bfda17a715 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -54,6 +54,7 @@ #include "Core/HW/GCPad.h" #include "Core/HW/SI/SI.h" #include "Core/HW/SI/SI_Device.h" +#include "Core/HW/SI/SI_DeviceAMBaseboard.h" #include "Core/HW/SI/SI_DeviceGCController.h" #include "Core/HW/Sram.h" #include "Core/HW/WiiSave.h" @@ -1891,6 +1892,8 @@ void NetPlayClient::UpdateDevices() auto& si = Core::System::GetInstance().GetSerialInterface(); for (auto player_id : m_pad_map) { + const SerialInterface::SIDevices si_device = Config::Get(Config::GetInfoForSIDevice(local_pad)); + if (m_gba_config[pad].enabled && player_id > 0) { si.ChangeDevice(SerialInterface::SIDEVICE_GC_GBA_EMULATED, pad); @@ -1898,8 +1901,6 @@ void NetPlayClient::UpdateDevices() else if (player_id == m_local_player->pid) { // Use local controller types for local controllers if they are compatible - const SerialInterface::SIDevices si_device = - Config::Get(Config::GetInfoForSIDevice(local_pad)); if (SerialInterface::SIDevice_IsGCController(si_device)) { si.ChangeDevice(si_device, pad); @@ -1917,7 +1918,8 @@ void NetPlayClient::UpdateDevices() } else if (player_id > 0) { - si.ChangeDevice(SerialInterface::SIDEVICE_GC_CONTROLLER, pad); + if (si_device != SerialInterface::SIDEVICE_AM_BASEBOARD) + si.ChangeDevice(SerialInterface::SIDEVICE_GC_CONTROLLER, pad); } else { @@ -2780,6 +2782,16 @@ bool SerialInterface::CSIDevice_GCController::NetPlay_GetInput(int pad_num, GCPa return false; } +bool SerialInterface::CSIDevice_AMBaseboard::NetPlay_GetInput(int pad_num, GCPadStatus* status) +{ + std::lock_guard lk(NetPlay::crit_netplay_client); + + if (NetPlay::netplay_client) + return NetPlay::netplay_client->GetNetPads(pad_num, NetPlay::s_si_poll_batching, status); + + return false; +} + bool NetPlay::NetPlay_GetWiimoteData(const std::span& entries) { std::lock_guard lk(crit_netplay_client); @@ -2852,3 +2864,12 @@ int SerialInterface::CSIDevice_GCController::NetPlay_InGamePadToLocalPad(int num return numPAD; } +int SerialInterface::CSIDevice_AMBaseboard::NetPlay_InGamePadToLocalPad(int numPAD) +{ + std::lock_guard lk(NetPlay::crit_netplay_client); + + if (NetPlay::netplay_client) + return NetPlay::netplay_client->InGamePadToLocalPad(numPAD); + + return numPAD; +}