From c07f862ef2d483d0140fe3113a6fe123369ec5a6 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 16 May 2023 09:43:21 +0200 Subject: [PATCH] ggpo: exchange vf4 cards when starting the session --- core/hw/maple/maple_cfg.h | 2 ++ core/hw/maple/maple_devs.cpp | 52 +++++++++++++++++++++++++++++++----- core/network/ggpo.cpp | 26 +++++++++++++++++- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/core/hw/maple/maple_cfg.h b/core/hw/maple/maple_cfg.h index 949080be5..ccd8b1cdd 100644 --- a/core/hw/maple/maple_cfg.h +++ b/core/hw/maple/maple_cfg.h @@ -108,3 +108,5 @@ void mcfg_DeserializeDevices(Deserializer& deser); bool maple_atomiswave_coin_chute(int slot); void push_vmu_screen(int bus_id, int bus_port, u8* buffer); void insertRfidCard(int playerNum); +const u8 *getRfidCardData(int playerNum); +void setRfidCardData(int playerNum, u8 *data); diff --git a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp index edad7e409..a00dd2488 100755 --- a/core/hw/maple/maple_devs.cpp +++ b/core/hw/maple/maple_devs.cpp @@ -6,6 +6,7 @@ #include "oslib/audiostream.h" #include "oslib/oslib.h" #include "hw/aica/sgc_if.h" +#include "cfg/option.h" #include #include @@ -1499,14 +1500,24 @@ struct RFIDReaderWriter : maple_base void OnSetup() override { memset(cardData, 0, sizeof(cardData)); + transientData = false; } - std::string getCardPath() const { - return hostfs::getArcadeFlashPath() + "-p" + std::to_string(player_num + 1) + ".card"; - } - - bool loadCard() + std::string getCardPath() const { + int playerNum; + if (config::GGPOEnable && !config::ActAsServer) + // Always load P1 card with GGPO to be consistent with P1 inputs being used + playerNum = 1; + else + playerNum = player_num + 1; + return hostfs::getArcadeFlashPath() + "-p" + std::to_string(playerNum) + ".card"; + } + + void loadCard() + { + if (transientData) + return; std::string path = getCardPath(); FILE *fp = nowide::fopen(path.c_str(), "rb"); if (fp == nullptr) @@ -1538,12 +1549,12 @@ struct RFIDReaderWriter : maple_base WARN_LOG(NAOMI, "Truncated or empty card file: %s" ,path.c_str()); fclose(fp); } - - return true; } void saveCard() const { + if (transientData) + return; std::string path = getCardPath(); FILE *fp = nowide::fopen(path.c_str(), "wb"); if (fp == nullptr) @@ -1579,10 +1590,21 @@ struct RFIDReaderWriter : maple_base loadCard(); } + const u8 *getCardData() { + loadCard(); + return cardData; + } + + void setCardData(u8 *data) { + memcpy(cardData, data, sizeof(cardData)); + transientData = true; + } + u8 cardData[128]; bool d4Seen = false; bool cardInserted = false; bool cardLocked = false; + bool transientData = false; }; void insertRfidCard(int playerNum) @@ -1592,6 +1614,22 @@ void insertRfidCard(int playerNum) ((RFIDReaderWriter *)mapleDev)->insertCard(); } +void setRfidCardData(int playerNum, u8 *data) +{ + maple_device *mapleDev = MapleDevices[1 + playerNum][5]; + if (mapleDev != nullptr && mapleDev->get_device_type() == MDT_RFIDReaderWriter) + ((RFIDReaderWriter *)mapleDev)->setCardData(data); +} + +const u8 *getRfidCardData(int playerNum) +{ + maple_device *mapleDev = MapleDevices[1 + playerNum][5]; + if (mapleDev != nullptr && mapleDev->get_device_type() == MDT_RFIDReaderWriter) + return ((RFIDReaderWriter *)mapleDev)->getCardData(); + else + return nullptr; +} + maple_device* maple_Create(MapleDeviceType type) { maple_device* rv=0; diff --git a/core/network/ggpo.cpp b/core/network/ggpo.cpp index 0652ae1e8..344ae1dc7 100644 --- a/core/network/ggpo.cpp +++ b/core/network/ggpo.cpp @@ -174,13 +174,18 @@ static_assert(BTN_TRIGGER_RIGHT < (1 << 20)); struct GameEvent { enum : char { - Chat + Chat, + VF4Card } type; union { struct { u8 playerNum; char message[512 - sizeof(playerNum) - sizeof(type)]; } chat; + struct { + u8 playerNum; + u8 data[128]; + } card; } u; constexpr static int chatMessageLen(int len) { return len - sizeof(u.chat.playerNum) - sizeof(type); } @@ -451,6 +456,10 @@ static void on_message(u8 *msg, int len) chatCallback(event->u.chat.playerNum, std::string(event->u.chat.message, GameEvent::chatMessageLen(len))); break; + case GameEvent::VF4Card: + setRfidCardData(event->u.card.playerNum, event->u.card.data); + break; + default: WARN_LOG(NETWORK, "Unknown app message type %d", event->type); break; @@ -817,6 +826,21 @@ std::future startNetwork() getInput(state); } #endif + if (active() && (settings.content.gameId == "VIRTUA FIGHTER 4 JAPAN" + || settings.content.gameId == "VF4 EVOLUTION JAPAN" + || settings.content.gameId == "VF4 FINAL TUNED JAPAN")) + { + // Send the local P1 card + const u8 *cardData = getRfidCardData(0); + if (cardData != nullptr) + { + GameEvent event; + event.type = GameEvent::VF4Card; + event.u.card.playerNum = config::ActAsServer ? 0 : 1; + memcpy(event.u.card.data, cardData, sizeof(event.u.card.data)); + ggpo_send_message(ggpoSession, &event, sizeof(event.type) + sizeof(event.u.card), true); + } + } emu.setNetworkState(active()); return active(); });