all repos — mgba @ 000e965b7480de20157a76ee7189df78e08fd6ca

mGBA Game Boy Advance Emulator

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}