Add ioMode setting in arcadedefs.

Only relevant for Pac Man Battle Royale for now.
This commit is contained in:
Jean-Philip Desjardins 2024-06-08 09:42:46 -04:00
parent a226cafb05
commit 68ee945e5c
6 changed files with 133 additions and 71 deletions

View file

@ -78,6 +78,11 @@ std::string CSys147::GetFunctionName(unsigned int functionId) const
return "unknown"; return "unknown";
} }
void CSys147::SetIoMode(IO_MODE ioMode)
{
m_ioMode = ioMode;
}
void CSys147::SetButton(unsigned int switchIndex, unsigned int padNumber, PS2::CControllerInfo::BUTTON button) void CSys147::SetButton(unsigned int switchIndex, unsigned int padNumber, PS2::CControllerInfo::BUTTON button)
{ {
m_switchBindings[{padNumber, button}] = switchIndex; m_switchBindings[{padNumber, button}] = switchIndex;
@ -90,59 +95,63 @@ void CSys147::SetButtonState(unsigned int padNumber, PS2::CControllerInfo::BUTTO
{ {
m_switchStates[binding->second] = pressed ? 0xFF : 0x00; m_switchStates[binding->second] = pressed ? 0xFF : 0x00;
} }
if(padNumber != 0) return;
//Player Switches if(m_ioMode == IO_MODE::AI)
//4 nibbles, one for each player {
//In one nibble: if(padNumber != 0) return;
//Bit 0 - Up
//Bit 1 - Down
//Bit 2 - Right
//Bit 3 - Left
//System Switches //Player Switches
//Bit 0 - Select Down //4 nibbles, one for each player
//Bit 1 - Select Up //In one nibble:
//Bit 2 - Enter //Bit 0 - Up
//Bit 3 - Test //Bit 1 - Down
//Bit 5 - Service //Bit 2 - Right
//Bit 8 - P1 Enter //Bit 3 - Left
//Bit 9 - P3 Enter
//Bit 10 - P2 Enter //System Switches
//Bit 11 - P4 Enter //Bit 0 - Select Down
uint16 systemSwitchMask = 0; //Bit 1 - Select Up
uint16 playerSwitchMask = 0; //Bit 2 - Enter
switch(button) //Bit 3 - Test
{ //Bit 5 - Service
case PS2::CControllerInfo::L1: //Bit 8 - P1 Enter
systemSwitchMask = 0x0008; //Test Button //Bit 9 - P3 Enter
break; //Bit 10 - P2 Enter
case PS2::CControllerInfo::DPAD_UP: //Bit 11 - P4 Enter
systemSwitchMask = 0x0002; //Select Up uint16 systemSwitchMask = 0;
playerSwitchMask = 0x0010; uint16 playerSwitchMask = 0;
break; switch(button)
case PS2::CControllerInfo::DPAD_DOWN: {
systemSwitchMask = 0x0001; //Select Down case PS2::CControllerInfo::L1:
playerSwitchMask = 0x0020; systemSwitchMask = 0x0008; //Test Button
break; break;
case PS2::CControllerInfo::DPAD_LEFT: case PS2::CControllerInfo::DPAD_UP:
playerSwitchMask = 0x0080; systemSwitchMask = 0x0002; //Select Up
break; playerSwitchMask = 0x0010;
case PS2::CControllerInfo::DPAD_RIGHT: break;
playerSwitchMask = 0x0040; case PS2::CControllerInfo::DPAD_DOWN:
break; systemSwitchMask = 0x0001; //Select Down
case PS2::CControllerInfo::CROSS: playerSwitchMask = 0x0020;
systemSwitchMask = 0x0404; //Enter break;
break; case PS2::CControllerInfo::DPAD_LEFT:
default: playerSwitchMask = 0x0080;
break; break;
} case PS2::CControllerInfo::DPAD_RIGHT:
m_systemSwitchState &= ~systemSwitchMask; playerSwitchMask = 0x0040;
m_playerSwitchState &= ~playerSwitchMask; break;
if(!pressed) case PS2::CControllerInfo::CROSS:
{ systemSwitchMask = 0x0404; //Enter
m_systemSwitchState |= systemSwitchMask; break;
m_playerSwitchState |= playerSwitchMask; default:
break;
}
m_systemSwitchState &= ~systemSwitchMask;
m_playerSwitchState &= ~playerSwitchMask;
if(!pressed)
{
m_systemSwitchState |= systemSwitchMask;
m_playerSwitchState |= playerSwitchMask;
}
} }
} }
@ -468,23 +477,38 @@ bool CSys147::Invoke99(uint32 method, uint32* args, uint32 argsSize, uint32* ret
} }
else if(packet->command == 0x10) else if(packet->command == 0x10)
{ {
//Some kind of I/O device related response
//Animal Kaiser uses this for dispenser
//Pac Man Battle Royale uses this for switch state
if(m_ioMode == IO_MODE::AI)
{
{
MODULE_99_PACKET reply = {};
reply.type = 2;
reply.command = 0x10;
reply.data[0] = static_cast<uint8>(m_systemSwitchState);
reply.data[1] = static_cast<uint8>(m_systemSwitchState >> 8);
reply.checksum = ComputePacketChecksum(reply);
m_pendingReplies.emplace_back(reply);
}
{
MODULE_99_PACKET reply = {};
reply.type = 3;
reply.command = 0x10;
reply.data[0x32] = 0x20;
reply.data[0x36] = static_cast<uint8>(m_playerSwitchState);
reply.data[0x37] = static_cast<uint8>(m_playerSwitchState >> 8);
reply.checksum = ComputePacketChecksum(reply);
m_pendingReplies.emplace_back(reply);
}
}
else
{ {
MODULE_99_PACKET reply = {}; MODULE_99_PACKET reply = {};
reply.type = 2; reply.type = 2;
reply.command = 0x10; reply.command = 0x10;
reply.data[0] = static_cast<uint8>(m_systemSwitchState); reply.data[0] = packet->data[0];
reply.data[1] = static_cast<uint8>(m_systemSwitchState >> 8);
reply.checksum = ComputePacketChecksum(reply);
m_pendingReplies.emplace_back(reply);
}
{
MODULE_99_PACKET reply = {};
reply.type = 3;
reply.command = 0x10;
reply.data[0x32] = 0x20;
reply.data[0x36] = static_cast<uint8>(m_playerSwitchState);
reply.data[0x37] = static_cast<uint8>(m_playerSwitchState >> 8);
reply.checksum = ComputePacketChecksum(reply); reply.checksum = ComputePacketChecksum(reply);
m_pendingReplies.emplace_back(reply); m_pendingReplies.emplace_back(reply);
} }

View file

@ -13,6 +13,12 @@ namespace Iop
class CSys147 : public CModule, public CPadInterface class CSys147 : public CModule, public CPadInterface
{ {
public: public:
enum class IO_MODE
{
DEFAULT,
AI,
};
CSys147(CSifMan&, const std::string&); CSys147(CSifMan&, const std::string&);
virtual ~CSys147() = default; virtual ~CSys147() = default;
@ -20,6 +26,7 @@ namespace Iop
std::string GetFunctionName(unsigned int) const override; std::string GetFunctionName(unsigned int) const override;
void Invoke(CMIPS&, unsigned int) override; void Invoke(CMIPS&, unsigned int) override;
void SetIoMode(IO_MODE);
void SetButton(unsigned int, unsigned int, PS2::CControllerInfo::BUTTON); void SetButton(unsigned int, unsigned int, PS2::CControllerInfo::BUTTON);
//CPadInterface //CPadInterface
@ -79,15 +86,18 @@ namespace Iop
std::string m_gameId; std::string m_gameId;
std::map<ButtonSelector, uint8> m_switchBindings; std::map<ButtonSelector, uint8> m_switchBindings;
IO_MODE m_ioMode = IO_MODE::DEFAULT;
std::vector<MODULE_99_PACKET> m_pendingReplies; std::vector<MODULE_99_PACKET> m_pendingReplies;
std::map<uint8, uint8> m_switchStates; std::map<uint8, uint8> m_switchStates;
//AI board state
uint16 m_systemSwitchState = ~0U;
uint16 m_playerSwitchState = ~0U;
std::unique_ptr<Framework::CHttpServer> m_ioServer; std::unique_ptr<Framework::CHttpServer> m_ioServer;
std::mutex m_barcodeMutex; std::mutex m_barcodeMutex;
std::string m_currentBarcode; std::string m_currentBarcode;
uint16 m_systemSwitchState = ~0U;
uint16 m_playerSwitchState = ~0U;
}; };
} }
} }

View file

@ -8,6 +8,13 @@
struct ARCADE_MACHINE_DEF struct ARCADE_MACHINE_DEF
{ {
enum DRIVER
{
UNKNOWN,
NAMCO_SYSTEM_246,
NAMCO_SYSTEM_147,
};
enum class INPUT_MODE enum class INPUT_MODE
{ {
DEFAULT, DEFAULT,
@ -17,13 +24,12 @@ struct ARCADE_MACHINE_DEF
TOUCH, TOUCH,
}; };
enum DRIVER enum class IO_MODE
{ {
UNKNOWN, DEFAULT,
NAMCO_SYSTEM_246, SYS147_AI,
NAMCO_SYSTEM_147,
}; };
struct PATCH struct PATCH
{ {
uint32 address = 0; uint32 address = 0;
@ -43,6 +49,7 @@ struct ARCADE_MACHINE_DEF
std::map<std::string, uint32> nandMounts; std::map<std::string, uint32> nandMounts;
std::map<unsigned int, ButtonSelector> buttons; std::map<unsigned int, ButtonSelector> buttons;
INPUT_MODE inputMode = INPUT_MODE::DEFAULT; INPUT_MODE inputMode = INPUT_MODE::DEFAULT;
IO_MODE ioMode = IO_MODE::DEFAULT;
std::array<float, 4> screenPosXform = {65535, 0, 65535, 0}; std::array<float, 4> screenPosXform = {65535, 0, 65535, 0};
uint32 eeFreqScaleNumerator = 1; uint32 eeFreqScaleNumerator = 1;
uint32 eeFreqScaleDenominator = 1; uint32 eeFreqScaleDenominator = 1;

View file

@ -48,6 +48,12 @@ static const std::pair<const char*, ARCADE_MACHINE_DEF::INPUT_MODE> g_inputModeV
{ "drive", ARCADE_MACHINE_DEF::INPUT_MODE::DRIVE }, { "drive", ARCADE_MACHINE_DEF::INPUT_MODE::DRIVE },
{ "touch", ARCADE_MACHINE_DEF::INPUT_MODE::TOUCH }, { "touch", ARCADE_MACHINE_DEF::INPUT_MODE::TOUCH },
}; };
static const std::pair<const char*, ARCADE_MACHINE_DEF::IO_MODE> g_ioModeValues[] =
{
{ "default", ARCADE_MACHINE_DEF::IO_MODE::DEFAULT },
{ "sys147_ai", ARCADE_MACHINE_DEF::IO_MODE::SYS147_AI },
};
// clang-format on // clang-format on
template <typename ValueType> template <typename ValueType>
@ -183,6 +189,11 @@ ARCADE_MACHINE_DEF ReadArcadeMachineDefinition(const fs::path& arcadeDefPath)
std::string inputModeString = defJson["inputMode"]; std::string inputModeString = defJson["inputMode"];
def.inputMode = ParseEnumValue(inputModeString.c_str(), std::begin(g_inputModeValues), std::end(g_inputModeValues)); def.inputMode = ParseEnumValue(inputModeString.c_str(), std::begin(g_inputModeValues), std::end(g_inputModeValues));
} }
if(defJson.contains("ioMode"))
{
std::string ioModeString = defJson["ioMode"];
def.ioMode = ParseEnumValue(ioModeString.c_str(), std::begin(g_ioModeValues), std::end(g_ioModeValues));
}
if(defJson.contains("screenPosXform")) if(defJson.contains("screenPosXform"))
{ {
auto screenPosXformArray = defJson["screenPosXform"]; auto screenPosXformArray = defJson["screenPosXform"];

View file

@ -27,6 +27,15 @@ void CNamcoSys147Driver::PrepareEnvironment(CPS2VM* virtualMachine, const ARCADE
{ {
auto sys147Module = std::make_shared<Iop::Namco::CSys147>(*iopBios->GetSifman(), def.id); auto sys147Module = std::make_shared<Iop::Namco::CSys147>(*iopBios->GetSifman(), def.id);
switch(def.ioMode)
{
case ARCADE_MACHINE_DEF::IO_MODE::SYS147_AI:
sys147Module->SetIoMode(Iop::Namco::CSys147::IO_MODE::AI);
break;
default:
assert(false);
break;
}
iopBios->RegisterModule(sys147Module); iopBios->RegisterModule(sys147Module);
iopBios->RegisterHleModuleReplacement("S147LINK", sys147Module); iopBios->RegisterHleModuleReplacement("S147LINK", sys147Module);
virtualMachine->m_pad->InsertListener(sys147Module.get()); virtualMachine->m_pad->InsertListener(sys147Module.get());

View file

@ -11,6 +11,7 @@
"atfile1": 131072 "atfile1": 131072
} }
}, },
"ioMode": "sys147_ai",
"boot": "atfile0:pacmanBR.elf", "boot": "atfile0:pacmanBR.elf",
"patches": "patches":
[ [