Qt: Switch to new GBA lockstep driver

This commit is contained in:
Vicki Pfau 2024-08-25 02:48:50 -07:00
parent 0955b94466
commit cd8933415c
2 changed files with 88 additions and 49 deletions

View File

@ -7,6 +7,7 @@
#include "CoreController.h"
#include "LogController.h"
#include "utils.h"
#ifdef M_CORE_GBA
#include <mgba/internal/gba/gba.h>
@ -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<GBASIOLockstep*>(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<GBA*>(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<mLockstepThreadUser*>(ctx);
LockstepUser* user = static_cast<LockstepUser*>(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<QString, QString> 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<GBA*>(thread->core->board);
GBASIOLockstepNode* node = reinterpret_cast<GBASIOLockstepNode*>(gba->sio.drivers.multiplayer);
GBASIOLockstepDriver* node = reinterpret_cast<GBASIOLockstepDriver*>(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<QString, QString> 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;
int num = 0;
switch (m_platform) {
case mPLATFORM_GB:
num = m_lockstep.attached;
break;
case mPLATFORM_GBA:
num = saturateCast<int>(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<GBA*>(p.controller->thread()->core->board);
GBASIOLockstepNode* node = reinterpret_cast<GBASIOLockstepNode*>(gba->sio.drivers.multiplayer);
m_players[node->id] = pid;
GBASIOLockstepDriver* node = reinterpret_cast<GBASIOLockstepDriver*>(gba->sio.drivers.multiplayer);
m_players[node->d.deviceId(&node->d)] = pid;
}
break;
#endif

View File

@ -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<int, Player> m_pids;
QList<int> m_players;
QMutex m_lock;
QHash<QPair<QString, QString>, int> m_claimed;
QHash<QPair<QString, QString>, int> m_claimedSaves;
};
}