mirror of https://github.com/mgba-emu/mgba.git
Qt: Create MultiplayerController
This commit is contained in:
parent
5b40951c05
commit
6e467a0332
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "AudioProcessor.h"
|
#include "AudioProcessor.h"
|
||||||
#include "InputController.h"
|
#include "InputController.h"
|
||||||
|
#include "MultiplayerController.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
@ -41,6 +42,7 @@ GameController::GameController(QObject* parent)
|
||||||
, m_turbo(false)
|
, m_turbo(false)
|
||||||
, m_turboForced(false)
|
, m_turboForced(false)
|
||||||
, m_inputController(nullptr)
|
, m_inputController(nullptr)
|
||||||
|
, m_multiplayer(nullptr)
|
||||||
{
|
{
|
||||||
m_renderer = new GBAVideoSoftwareRenderer;
|
m_renderer = new GBAVideoSoftwareRenderer;
|
||||||
GBAVideoSoftwareRendererCreate(m_renderer);
|
GBAVideoSoftwareRendererCreate(m_renderer);
|
||||||
|
@ -140,12 +142,30 @@ GameController::~GameController() {
|
||||||
m_audioThread->quit();
|
m_audioThread->quit();
|
||||||
m_audioThread->wait();
|
m_audioThread->wait();
|
||||||
disconnect();
|
disconnect();
|
||||||
|
clearMultiplayerController();
|
||||||
closeGame();
|
closeGame();
|
||||||
GBACheatDeviceDestroy(&m_cheatDevice);
|
GBACheatDeviceDestroy(&m_cheatDevice);
|
||||||
delete m_renderer;
|
delete m_renderer;
|
||||||
delete[] m_drawContext;
|
delete[] m_drawContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameController::setMultiplayerController(std::shared_ptr<MultiplayerController> controller) {
|
||||||
|
if (controller == m_multiplayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearMultiplayerController();
|
||||||
|
m_multiplayer = controller;
|
||||||
|
controller->attachGame(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameController::clearMultiplayerController() {
|
||||||
|
if (!m_multiplayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_multiplayer->detachGame(this);
|
||||||
|
m_multiplayer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void GameController::setOverride(const GBACartridgeOverride& override) {
|
void GameController::setOverride(const GBACartridgeOverride& override) {
|
||||||
m_threadContext.override = override;
|
m_threadContext.override = override;
|
||||||
m_threadContext.hasOverride = true;
|
m_threadContext.hasOverride = true;
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "gba/cheats.h"
|
#include "gba/cheats.h"
|
||||||
#include "gba/hardware.h"
|
#include "gba/hardware.h"
|
||||||
|
@ -32,6 +34,7 @@ namespace QGBA {
|
||||||
|
|
||||||
class AudioProcessor;
|
class AudioProcessor;
|
||||||
class InputController;
|
class InputController;
|
||||||
|
class MultiplayerController;
|
||||||
|
|
||||||
class GameController : public QObject {
|
class GameController : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -59,6 +62,9 @@ public:
|
||||||
void setInputController(InputController* controller) { m_inputController = controller; }
|
void setInputController(InputController* controller) { m_inputController = controller; }
|
||||||
void setOverrides(Configuration* overrides) { m_threadContext.overrides = overrides; }
|
void setOverrides(Configuration* overrides) { m_threadContext.overrides = overrides; }
|
||||||
|
|
||||||
|
void setMultiplayerController(std::shared_ptr<MultiplayerController> controller);
|
||||||
|
void clearMultiplayerController();
|
||||||
|
|
||||||
void setOverride(const GBACartridgeOverride& override);
|
void setOverride(const GBACartridgeOverride& override);
|
||||||
void clearOverride() { m_threadContext.hasOverride = false; }
|
void clearOverride() { m_threadContext.hasOverride = false; }
|
||||||
|
|
||||||
|
@ -162,6 +168,7 @@ private:
|
||||||
bool m_turboForced;
|
bool m_turboForced;
|
||||||
|
|
||||||
InputController* m_inputController;
|
InputController* m_inputController;
|
||||||
|
std::shared_ptr<MultiplayerController> m_multiplayer;
|
||||||
|
|
||||||
struct GameControllerLux : GBALuminanceSource {
|
struct GameControllerLux : GBALuminanceSource {
|
||||||
GameController* p;
|
GameController* p;
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "MultiplayerController.h"
|
#include "MultiplayerController.h"
|
||||||
|
|
||||||
|
#include "GameController.h"
|
||||||
|
|
||||||
using namespace QGBA;
|
using namespace QGBA;
|
||||||
|
|
||||||
MultiplayerController::MultiplayerController() {
|
MultiplayerController::MultiplayerController() {
|
||||||
|
@ -16,5 +18,46 @@ MultiplayerController::~MultiplayerController() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MultiplayerController::attachGame(GameController* controller) {
|
bool MultiplayerController::attachGame(GameController* controller) {
|
||||||
return false;
|
MutexLock(&m_lockstep.mutex);
|
||||||
|
if (m_lockstep.attached == MAX_GBAS) {
|
||||||
|
MutexUnlock(&m_lockstep.mutex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GBASIOLockstepNode* node = new GBASIOLockstepNode;
|
||||||
|
GBASIOLockstepNodeCreate(node);
|
||||||
|
GBASIOLockstepAttachNode(&m_lockstep, node);
|
||||||
|
MutexUnlock(&m_lockstep.mutex);
|
||||||
|
|
||||||
|
controller->threadInterrupt();
|
||||||
|
GBAThread* thread = controller->thread();
|
||||||
|
if (controller->isLoaded()) {
|
||||||
|
GBASIOSetDriver(&thread->gba->sio, &node->d, SIO_MULTI);
|
||||||
|
}
|
||||||
|
thread->sioDrivers.multiplayer = &node->d;
|
||||||
|
controller->threadContinue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerController::detachGame(GameController* controller) {
|
||||||
|
controller->threadInterrupt();
|
||||||
|
MutexLock(&m_lockstep.mutex);
|
||||||
|
GBAThread* thread = nullptr;
|
||||||
|
for (int i = 0; i < m_lockstep.attached; ++i) {
|
||||||
|
thread = controller->thread();
|
||||||
|
if (thread->sioDrivers.multiplayer == &m_lockstep.players[i]->d) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
thread = nullptr;
|
||||||
|
}
|
||||||
|
if (thread) {
|
||||||
|
GBASIOLockstepNode* node = reinterpret_cast<GBASIOLockstepNode*>(thread->sioDrivers.multiplayer);
|
||||||
|
if (controller->isLoaded()) {
|
||||||
|
GBASIOSetDriver(&thread->gba->sio, nullptr, SIO_MULTI);
|
||||||
|
}
|
||||||
|
thread->sioDrivers.multiplayer = nullptr;
|
||||||
|
GBASIOLockstepDetachNode(&m_lockstep, node);
|
||||||
|
delete node;
|
||||||
|
}
|
||||||
|
MutexUnlock(&m_lockstep.mutex);
|
||||||
|
controller->threadContinue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ public:
|
||||||
~MultiplayerController();
|
~MultiplayerController();
|
||||||
|
|
||||||
bool attachGame(GameController*);
|
bool attachGame(GameController*);
|
||||||
|
void detachGame(GameController*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GBASIOLockstep m_lockstep;
|
GBASIOLockstep m_lockstep;
|
||||||
|
|
Loading…
Reference in New Issue