mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-13 11:39:09 +00:00
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
This commit is contained in:
parent
92265a7158
commit
87c4b1e356
20 changed files with 421 additions and 192 deletions
|
@ -1,2 +1,4 @@
|
|||
# SBEY - Virtua Striker 2002 (Export, Japan, Type 3)
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# SBGG - F-ZERO AX
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
CPUThread = True
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# SBHA - F-ZERO AX (Monster)
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
CPUThread = True
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
# SBHN - VIRTUA STRIKER 4 VER.A
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
# SBHZ - VIRTUA STRIKER 4 (Asia)
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
# SBJA - VIRTUA STRIKER 4 (Export)
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
# SBLK - VIRTUA STRIKER 4 Ver.2006 (Japan)
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
# SBLL - VIRTUA STRIKER 4 Ver.2006 (Export)
|
||||
|
||||
[Core]
|
||||
FPRF = True
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<u32, 3>& DICMDBUF, u32 address, u32 length)
|
||||
u32 ExecuteCommand(std::array<u32, 3>& DICMDBUF, u32* DIIMMBUF, u32 address, u32 length)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
@ -413,8 +411,8 @@ u32 ExecuteCommand(std::array<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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<u32, 3>& 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)
|
||||
{
|
||||
|
|
|
@ -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<u32, 3>& DICMDBUF, u32 Address, u32 Length);
|
||||
u32 ExecuteCommand(std::array<u32, 3>& DICMDBUF, u32* DIIMMBUF, u32 Address, u32 Length);
|
||||
u32 GetGameType(void);
|
||||
u32 GetMediaType(void);
|
||||
bool GetTestMenu(void);
|
||||
|
|
|
@ -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<DICommand>(m_DICMDBUF[0] >> 24) != DICommand::RequestError)
|
||||
SetDriveError(DriveError::None);
|
||||
|
|
|
@ -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<u8> data(m_backup.GetSize());
|
||||
m_backup.ReadBytes(data.data(), data.size());
|
||||
|
||||
// Set FIRM version
|
||||
*(u16*)(data + 0x12) = 0x1703;
|
||||
*(u16*)(data + 0x212) = 0x1703;
|
||||
reinterpret_cast<u16&>(data[0x12]) = 0x1703;
|
||||
reinterpret_cast<u16&>(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<u16&>(data[0x0A]) = Common::swap16(CheckSum(&data[0xC], 0x1F4));
|
||||
reinterpret_cast<u16&>(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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -30,7 +30,7 @@ enum class PadGroup
|
|||
Rumble,
|
||||
Mic,
|
||||
Options,
|
||||
Triforce
|
||||
Triforce,
|
||||
};
|
||||
|
||||
class GCPad : public ControllerEmu::EmulatedController
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#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<u8> 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<u16*>(&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<u16*>(&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<EDirectCommands>(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
|
||||
|
|
|
@ -4,15 +4,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <array>
|
||||
|
||||
#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
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
#include <array>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Flag.h"
|
||||
#include "Core/HW/GCPad.h"
|
||||
#include "Core/HW/SI/SI_Device.h"
|
||||
#include "InputCommon/GCPadStatus.h"
|
||||
|
|
|
@ -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<NetPlayClient::WiimoteDataBatchEntry>& 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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue