From cd8933415cfcc25452ecfcb95292faa8ea9c74b3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 25 Aug 2024 02:48:50 -0700 Subject: [PATCH] Qt: Switch to new GBA lockstep driver --- src/platform/qt/MultiplayerController.cpp | 120 ++++++++++++++-------- src/platform/qt/MultiplayerController.h | 17 ++- 2 files changed, 88 insertions(+), 49 deletions(-) diff --git a/src/platform/qt/MultiplayerController.cpp b/src/platform/qt/MultiplayerController.cpp index 149df2386..c142fe126 100644 --- a/src/platform/qt/MultiplayerController.cpp +++ b/src/platform/qt/MultiplayerController.cpp @@ -7,6 +7,7 @@ #include "CoreController.h" #include "LogController.h" +#include "utils.h" #ifdef M_CORE_GBA #include @@ -27,8 +28,14 @@ MultiplayerController::Player::Player(CoreController* coreController) int MultiplayerController::Player::id() const { switch (controller->platform()) { #ifdef M_CORE_GBA - case mPLATFORM_GBA: - return node.gba->id; + case mPLATFORM_GBA: { + int id = node.gba->d.deviceId(&node.gba->d); + if (id >= 0) { + return id; + } else { + return preferredId; + } + } #endif #ifdef M_CORE_GB case mPLATFORM_GB: @@ -89,25 +96,7 @@ MultiplayerController::MultiplayerController() { switch (player->controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - if (!id) { - for (int i = 1; i < controller->m_players.count(); ++i) { - player = controller->player(i); - if (player->node.gba->d.p->mode > GBA_SIO_MULTI) { - player->controller->setSync(true); - continue; - } - player->controller->setSync(false); - player->cyclesPosted += cycles; - if (player->awake < 1) { - player->node.gba->nextEvent += player->cyclesPosted; - } - mCoreThreadStopWaiting(player->controller->thread()); - player->awake = 1; - } - } else { - player->controller->setSync(true); - player->cyclesPosted += cycles; - } + abort(); break; #endif #ifdef M_CORE_GB @@ -169,7 +158,6 @@ MultiplayerController::MultiplayerController() { switch (player->controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - player->cyclesPosted += reinterpret_cast(lockstep)->players[0]->eventDiff; break; #endif #ifdef M_CORE_GB @@ -184,7 +172,6 @@ MultiplayerController::MultiplayerController() { switch (player->controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - player->node.gba->nextEvent += player->cyclesPosted; break; #endif #ifdef M_CORE_GB @@ -214,11 +201,11 @@ bool MultiplayerController::attachGame(CoreController* controller) { interrupters.append(p.controller); } - if (m_lockstep.attached == 0) { + if (attached() == 0) { switch (controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - GBASIOLockstepInit(&m_gbaLockstep); + GBASIOLockstepCoordinatorInit(&m_gbaCoordinator); break; #endif #ifdef M_CORE_GB @@ -240,28 +227,53 @@ bool MultiplayerController::attachGame(CoreController* controller) { } Player player{controller}; + for (int i = 0; i < MAX_GBAS; ++i) { + if (m_claimedIds & (1 << i)) { + continue; + } + player.preferredId = i; + m_claimedIds |= 1 << i; + break; + } switch (controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: { - if (m_lockstep.attached >= MAX_GBAS) { + if (attached() >= MAX_GBAS) { return false; } GBA* gba = static_cast(thread->core->board); - GBASIOLockstepNode* node = new GBASIOLockstepNode; - GBASIOLockstepNodeCreate(node); - GBASIOLockstepAttachNode(&m_gbaLockstep, node); + GBASIOLockstepDriver* node = new GBASIOLockstepDriver; + LockstepUser* user = new LockstepUser; + mLockstepThreadUserInit(user, thread); + user->controller = this; + user->pid = m_nextPid; + user->d.requestedId = [](mLockstepUser* ctx) { + mLockstepThreadUser* tctx = reinterpret_cast(ctx); + LockstepUser* user = static_cast(tctx); + MultiplayerController* controller = user->controller; + const auto iter = controller->m_pids.find(user->pid); + if (iter == controller->m_pids.end()) { + return -1; + } + const Player& p = iter.value(); + return p.preferredId; + }; + + GBASIOLockstepDriverCreate(node, &user->d); + GBASIOLockstepCoordinatorAttach(&m_gbaCoordinator, node); player.node.gba = node; GBASIOSetDriver(&gba->sio, &node->d, GBA_SIO_MULTI); + GBASIOSetDriver(&gba->sio, &node->d, GBA_SIO_NORMAL_8); GBASIOSetDriver(&gba->sio, &node->d, GBA_SIO_NORMAL_32); break; } #endif #ifdef M_CORE_GB case mPLATFORM_GB: { - if (m_lockstep.attached >= 2) { + if (attached() >= 2) { return false; } @@ -281,7 +293,7 @@ bool MultiplayerController::attachGame(CoreController* controller) { } QPair path(controller->path(), controller->baseDirectory()); - int claimed = m_claimed[path]; + int claimed = m_claimedSaves[path]; int saveId = 0; mCoreConfigGetIntValue(&controller->thread()->core->config, "savePlayerId", &saveId); @@ -304,7 +316,7 @@ bool MultiplayerController::attachGame(CoreController* controller) { } else { player.saveId = 1; } - m_claimed[path] |= 1 << (player.saveId - 1); + m_claimedSaves[path] |= 1 << (player.saveId - 1); m_pids.insert(m_nextPid, player); ++m_nextPid; @@ -328,8 +340,7 @@ void MultiplayerController::detachGame(CoreController* controller) { for (int i = 0; i < m_players.count(); ++i) { Player* p = player(i); if (!p) { - LOG(QT, ERROR) << tr("Trying to detach a multiplayer player that's not attached"); - return; + continue; } CoreController* playerController = p->controller; if (playerController == controller) { @@ -337,15 +348,21 @@ void MultiplayerController::detachGame(CoreController* controller) { } interrupters.append(playerController); } + if (pid < 0) { + LOG(QT, WARN) << tr("Trying to detach a multiplayer player that's not attached"); + return; + } switch (controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: { GBA* gba = static_cast(thread->core->board); - GBASIOLockstepNode* node = reinterpret_cast(gba->sio.drivers.multiplayer); + GBASIOLockstepDriver* node = reinterpret_cast(gba->sio.drivers.multiplayer); GBASIOSetDriver(&gba->sio, nullptr, GBA_SIO_MULTI); + GBASIOSetDriver(&gba->sio, nullptr, GBA_SIO_NORMAL_8); GBASIOSetDriver(&gba->sio, nullptr, GBA_SIO_NORMAL_32); if (node) { - GBASIOLockstepDetachNode(&m_gbaLockstep, node); + GBASIOLockstepCoordinatorDetach(&m_gbaCoordinator, node); + delete node->user; delete node; } break; @@ -371,14 +388,20 @@ void MultiplayerController::detachGame(CoreController* controller) { QPair path(controller->path(), controller->baseDirectory()); Player& p = m_pids.find(pid).value(); if (!p.saveId) { - LOG(QT, ERROR) << "Clearing invalid save ID"; + LOG(QT, WARN) << "Clearing invalid save ID"; } else { - m_claimed[path] &= ~(1 << (p.saveId - 1)); - if (!m_claimed[path]) { - m_claimed.remove(path); + m_claimedSaves[path] &= ~(1 << (p.saveId - 1)); + if (!m_claimedSaves[path]) { + m_claimedSaves.remove(path); } } + if (p.preferredId < 0) { + LOG(QT, WARN) << "Clearing invalid preferred ID"; + } else { + m_claimedIds &= ~(1 << p.preferredId); + } + m_pids.remove(pid); if (m_pids.size() == 0) { m_platform = mPLATFORM_NONE; @@ -417,8 +440,17 @@ int MultiplayerController::saveId(CoreController* controller) const { } int MultiplayerController::attached() { - int num; - num = m_lockstep.attached; + int num = 0; + switch (m_platform) { + case mPLATFORM_GB: + num = m_lockstep.attached; + break; + case mPLATFORM_GBA: + num = saturateCast(GBASIOLockstepCoordinatorAttached(&m_gbaCoordinator)); + break; + default: + break; + } return num; } @@ -456,8 +488,8 @@ void MultiplayerController::fixOrder() { for (int pid : m_pids.keys()) { Player& p = m_pids.find(pid).value(); GBA* gba = static_cast(p.controller->thread()->core->board); - GBASIOLockstepNode* node = reinterpret_cast(gba->sio.drivers.multiplayer); - m_players[node->id] = pid; + GBASIOLockstepDriver* node = reinterpret_cast(gba->sio.drivers.multiplayer); + m_players[node->d.deviceId(&node->d)] = pid; } break; #endif diff --git a/src/platform/qt/MultiplayerController.h b/src/platform/qt/MultiplayerController.h index b5582319f..9eaf20b16 100644 --- a/src/platform/qt/MultiplayerController.h +++ b/src/platform/qt/MultiplayerController.h @@ -49,7 +49,7 @@ signals: private: union Node { GBSIOLockstepNode* gb; - GBASIOLockstepNode* gba; + GBASIOLockstepDriver* gba; }; struct Player { Player(CoreController* controller); @@ -63,6 +63,11 @@ private: int32_t cyclesPosted = 0; unsigned waitMask = 0; int saveId = 1; + int preferredId = 0; + }; + struct LockstepUser : mLockstepThreadUser { + MultiplayerController* controller; + int pid; }; Player* player(int id); @@ -73,18 +78,20 @@ private: mLockstep m_lockstep; #ifdef M_CORE_GB GBSIOLockstep m_gbLockstep; -#endif -#ifdef M_CORE_GBA - GBASIOLockstep m_gbaLockstep; #endif }; +#ifdef M_CORE_GBA + GBASIOLockstepCoordinator m_gbaCoordinator; +#endif + mPlatform m_platform = mPLATFORM_NONE; int m_nextPid = 0; + int m_claimedIds = 0; QHash m_pids; QList m_players; QMutex m_lock; - QHash, int> m_claimed; + QHash, int> m_claimedSaves; }; }