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 if (--controller->m_asleep[id] == 0) {
27 mCoreThreadStopWaiting(game->thread());
28 }
29 controller->m_lock.unlock();
30 };
31 m_lockstep.wait = [](GBASIOLockstep* lockstep, int id) {
32 MultiplayerController* controller = static_cast<MultiplayerController*>(lockstep->context);
33 controller->m_lock.lock();
34 GameController* game = controller->m_players[id];
35 if (++controller->m_asleep[id] == 1) {
36 mCoreThreadWaitFromThread(game->thread());
37 } else if (controller->m_asleep[id] == 0) {
38 mCoreThreadStopWaiting(game->thread());
39 }
40 if (controller->m_asleep[id] > 1) {
41 //abort();
42 }
43 controller->m_lock.unlock();
44 };
45}
46
47MultiplayerController::~MultiplayerController() {
48 GBASIOLockstepDeinit(&m_lockstep);
49}
50
51bool MultiplayerController::attachGame(GameController* controller) {
52 if (m_lockstep.attached == MAX_GBAS) {
53 return false;
54 }
55
56 mCoreThread* thread = controller->thread();
57 if (!thread) {
58 return false;
59 }
60
61#ifdef M_CORE_GBA
62 if (controller->platform() == PLATFORM_GBA) {
63 GBA* gba = static_cast<GBA*>(thread->core->board);
64
65 GBASIOLockstepNode* node = new GBASIOLockstepNode;
66 GBASIOLockstepNodeCreate(node);
67 GBASIOLockstepAttachNode(&m_lockstep, node);
68 m_players.append(controller);
69 m_asleep.append(0);
70
71 GBASIOSetDriver(&gba->sio, &node->d, SIO_MULTI);
72 GBASIOSetDriver(&gba->sio, &node->d, SIO_NORMAL_32);
73
74 emit gameAttached();
75 return true;
76 }
77#endif
78
79 return false;
80}
81
82void MultiplayerController::detachGame(GameController* controller) {
83 if (!m_players.contains(controller)) {
84 return;
85 }
86 mCoreThread* thread = controller->thread();
87 if (!thread) {
88 return;
89 }
90#ifdef M_CORE_GBA
91 if (controller->platform() == PLATFORM_GBA) {
92 GBA* gba = static_cast<GBA*>(thread->core->board);
93 GBASIOLockstepNode* node = reinterpret_cast<GBASIOLockstepNode*>(gba->sio.drivers.multiplayer);
94 GBASIOSetDriver(&gba->sio, nullptr, SIO_MULTI);
95 GBASIOSetDriver(&gba->sio, nullptr, SIO_NORMAL_32);
96 if (node) {
97 GBASIOLockstepDetachNode(&m_lockstep, node);
98 delete node;
99 }
100 }
101#endif
102 int i = m_players.indexOf(controller);
103 m_players.removeAt(i);
104 m_players.removeAt(i);
105 emit gameDetached();
106}
107
108int MultiplayerController::playerId(GameController* controller) {
109 return m_players.indexOf(controller);
110}
111
112int MultiplayerController::attached() {
113 int num;
114 num = m_lockstep.attached;
115 return num;
116}