src/platform/qt/MultiplayerController.cpp (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "MultiplayerController.h"
7
8#include "GameController.h"
9
10extern "C" {
11#ifdef M_CORE_GBA
12#include "gba/gba.h"
13#endif
14}
15
16
17using namespace QGBA;
18
19MultiplayerController::MultiplayerController() {
20 GBASIOLockstepInit(&m_lockstep);
21 m_lockstep.context = this;
22 m_lockstep.signal = [](GBASIOLockstep* lockstep, int id) {
23 MultiplayerController* controller = static_cast<MultiplayerController*>(lockstep->context);
24 GameController* game = controller->m_players[id];
25 controller->m_lock.lock();
26 ++controller->m_awake[id];
27 mCoreThreadStopWaiting(game->thread());
28 controller->m_lock.unlock();
29 };
30 m_lockstep.wait = [](GBASIOLockstep* lockstep, int id) {
31 MultiplayerController* controller = static_cast<MultiplayerController*>(lockstep->context);
32 controller->m_lock.lock();
33 controller->m_awake[id] = 0;
34 GameController* game = controller->m_players[id];
35 mCoreThreadWaitFromThread(game->thread());
36 controller->m_lock.unlock();
37 };
38}
39
40MultiplayerController::~MultiplayerController() {
41 GBASIOLockstepDeinit(&m_lockstep);
42}
43
44bool MultiplayerController::attachGame(GameController* controller) {
45 if (m_lockstep.attached == MAX_GBAS) {
46 return false;
47 }
48
49 mCoreThread* thread = controller->thread();
50 if (!thread) {
51 return false;
52 }
53
54#ifdef M_CORE_GBA
55 if (controller->platform() == PLATFORM_GBA) {
56 GBA* gba = static_cast<GBA*>(thread->core->board);
57
58 GBASIOLockstepNode* node = new GBASIOLockstepNode;
59 GBASIOLockstepNodeCreate(node);
60 GBASIOLockstepAttachNode(&m_lockstep, node);
61 m_players.append(controller);
62 m_awake.append(1);
63
64 GBASIOSetDriver(&gba->sio, &node->d, SIO_MULTI);
65 GBASIOSetDriver(&gba->sio, &node->d, SIO_NORMAL_32);
66
67 emit gameAttached();
68 return true;
69 }
70#endif
71
72 return false;
73}
74
75void MultiplayerController::detachGame(GameController* controller) {
76 if (!m_players.contains(controller)) {
77 return;
78 }
79 mCoreThread* thread = controller->thread();
80 if (!thread) {
81 return;
82 }
83#ifdef M_CORE_GBA
84 if (controller->platform() == PLATFORM_GBA) {
85 GBA* gba = static_cast<GBA*>(thread->core->board);
86 GBASIOLockstepNode* node = reinterpret_cast<GBASIOLockstepNode*>(gba->sio.drivers.multiplayer);
87 GBASIOSetDriver(&gba->sio, nullptr, SIO_MULTI);
88 GBASIOSetDriver(&gba->sio, nullptr, SIO_NORMAL_32);
89 if (node) {
90 GBASIOLockstepDetachNode(&m_lockstep, node);
91 delete node;
92 }
93 }
94#endif
95 int i = m_players.indexOf(controller);
96 m_players.removeAt(i);
97 m_players.removeAt(i);
98 emit gameDetached();
99}
100
101int MultiplayerController::playerId(GameController* controller) {
102 return m_players.indexOf(controller);
103}
104
105int MultiplayerController::attached() {
106 int num;
107 num = m_lockstep.attached;
108 return num;
109}