From dffb5eec30663812a9e83b599cf93500b6250c57 Mon Sep 17 00:00:00 2001
From: Jeffrey Pfau <jeffrey@endrift.com>
Date: Thu, 18 Feb 2016 21:54:06 -0800
Subject: [PATCH] GB: Rotation support

---
 src/core/core.h                    |  1 +
 src/gb/core.c                      |  6 +++++
 src/gba/core.c                     |  6 +++++
 src/platform/3ds/main.c            | 43 +++++++++++++++++++++++++-----
 src/platform/qt/GameController.cpp | 19 ++++++++++---
 src/platform/wii/main.c            |  2 +-
 6 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/src/core/core.h b/src/core/core.h
index 1432b37d3..45dfbcd36 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -91,6 +91,7 @@ struct mCore {
 	void (*getGameCode)(struct mCore*, char* title);
 
 	void (*setRTC)(struct mCore*, struct mRTCSource*);
+	void (*setRotation)(struct mCore*, struct mRotationSource*);
 };
 
 #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
diff --git a/src/gb/core.c b/src/gb/core.c
index 386f46222..39f84fd25 100644
--- a/src/gb/core.c
+++ b/src/gb/core.c
@@ -239,6 +239,11 @@ static void _GBCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
 	gb->memory.rtc = rtc;
 }
 
+static void _GBCoreSetRotation(struct mCore* core, struct mRotationSource* rotation) {
+	struct GB* gb = core->board;
+	gb->memory.rotation = rotation;
+}
+
 struct mCore* GBCoreCreate(void) {
 	struct GBCore* gbcore = malloc(sizeof(*gbcore));
 	struct mCore* core = &gbcore->d;
@@ -278,5 +283,6 @@ struct mCore* GBCoreCreate(void) {
 	core->getGameTitle = _GBCoreGetGameTitle;
 	core->getGameCode = _GBCoreGetGameCode;
 	core->setRTC = _GBCoreSetRTC;
+	core->setRotation = _GBCoreSetRotation;
 	return core;
 }
diff --git a/src/gba/core.c b/src/gba/core.c
index fd700aa6d..85da81a4d 100644
--- a/src/gba/core.c
+++ b/src/gba/core.c
@@ -272,6 +272,11 @@ static void _GBACoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
 	gba->rtcSource = rtc;
 }
 
+static void _GBACoreSetRotation(struct mCore* core, struct mRotationSource* rotation) {
+	struct GBA* gba = core->board;
+	gba->rotationSource = rotation;
+}
+
 struct mCore* GBACoreCreate(void) {
 	struct GBACore* gbacore = malloc(sizeof(*gbacore));
 	struct mCore* core = &gbacore->d;
@@ -311,5 +316,6 @@ struct mCore* GBACoreCreate(void) {
 	core->getGameTitle = _GBACoreGetGameTitle;
 	core->getGameCode = _GBACoreGetGameCode;
 	core->setRTC = _GBACoreSetRTC;
+	core->setRotation = _GBACoreSetRotation;
 	return core;
 }
diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c
index 28ab8d495..c016d8ddc 100644
--- a/src/platform/3ds/main.c
+++ b/src/platform/3ds/main.c
@@ -4,10 +4,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifdef M_CORE_GBA
 #include "gba/gba.h"
 #include "gba/gui/gui-runner.h"
 #include "gba/input.h"
 #include "gba/video.h"
+#endif
+#ifdef M_CORE_GB
+#include "gb/gb.h"
+#endif
 #include "util/gui.h"
 #include "util/gui/file-select.h"
 #include "util/gui/font.h"
@@ -249,9 +254,7 @@ static void _guiFinish(void) {
 }
 
 static void _setup(struct mGUIRunner* runner) {
-	if (runner->core->platform(runner->core) == PLATFORM_GBA) {
-		((struct GBA*) runner->core->board)->rotationSource = &rotation.d;
-	}
+	runner->core->setRotation(runner->core, &rotation.d);
 	if (hasSound != NO_SOUND) {
 		runner->core->setAVStream(runner->core, &stream);
 	}
@@ -279,13 +282,26 @@ static void _setup(struct mGUIRunner* runner) {
 }
 
 static void _gameLoaded(struct mGUIRunner* runner) {
-	if (runner->core->platform(runner->core) == PLATFORM_GBA) {
+	switch (runner->core->platform(runner->core)) {
+#ifdef M_CORE_GBA
+	case PLATFORM_GBA:
 		if (((struct GBA*) runner->core->board)->memory.hw.devices & HW_TILT) {
 			HIDUSER_EnableAccelerometer();
 		}
 		if (((struct GBA*) runner->core->board)->memory.hw.devices & HW_GYRO) {
 			HIDUSER_EnableGyroscope();
 		}
+		break;
+#endif
+#ifdef M_CORE_GB
+	case PLATFORM_GB:
+		if (((struct GB*) runner->core->board)->memory.mbcType == GB_MBC7) {
+			HIDUSER_EnableAccelerometer();
+		}
+		break;
+#endif
+	default:
+		break;
 	}
 	osSetSpeedupEnable(true);
 
@@ -318,13 +334,26 @@ static void _gameUnloaded(struct mGUIRunner* runner) {
 	}
 	osSetSpeedupEnable(false);
 
-	if (runner->core->platform(runner->core) == PLATFORM_GBA) {
+	switch (runner->core->platform(runner->core)) {
+#ifdef M_CORE_GBA
+	case PLATFORM_GBA:
 		if (((struct GBA*) runner->core->board)->memory.hw.devices & HW_TILT) {
 			HIDUSER_DisableAccelerometer();
 		}
 		if (((struct GBA*) runner->core->board)->memory.hw.devices & HW_GYRO) {
 			HIDUSER_DisableGyroscope();
 		}
+		break;
+#endif
+#ifdef M_CORE_GB
+	case PLATFORM_GB:
+		if (((struct GB*) runner->core->board)->memory.mbcType == GB_MBC7) {
+			HIDUSER_DisableAccelerometer();
+		}
+		break;
+#endif
+	default:
+		break;
 	}
 }
 
@@ -507,8 +536,8 @@ static enum GUICursorState _pollCursor(unsigned* x, unsigned* y) {
 static void _sampleRotation(struct mRotationSource* source) {
 	struct GBA3DSRotationSource* rotation = (struct GBA3DSRotationSource*) source;
 	// Work around ctrulib getting the entries wrong
-	rotation->accel = *(accelVector*)& hidSharedMem[0x48];
-	rotation->gyro = *(angularRate*)& hidSharedMem[0x5C];
+	rotation->accel = *(accelVector*) &hidSharedMem[0x48];
+	rotation->gyro = *(angularRate*) &hidSharedMem[0x5C];
 }
 
 static int32_t _readTiltX(struct mRotationSource* source) {
diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp
index 0af9bcead..e3d57b35c 100644
--- a/src/platform/qt/GameController.cpp
+++ b/src/platform/qt/GameController.cpp
@@ -20,12 +20,16 @@
 extern "C" {
 #include "core/config.h"
 #include "core/directories.h"
-#include "gba/audio.h"
+#ifdef M_CORE_GBA
 #include "gba/bios.h"
 #include "gba/core.h"
 #include "gba/gba.h"
 #include "gba/serialize.h"
 #include "gba/sharkport.h"
+#endif
+#ifdef M_CORE_GB
+#include "gb/gb.h"
+#endif
 #include "util/vfs.h"
 }
 
@@ -85,12 +89,19 @@ GameController::GameController(QObject* parent)
 		}
 		mRTCGenericSourceInit(&controller->m_rtc, context->core);
 		context->core->setRTC(context->core, &controller->m_rtc.d);
+		context->core->setRotation(context->core, controller->m_inputController->rotationSource());
 
-		if (context->core->platform(context->core) == PLATFORM_GBA) {
-			GBA* gba = static_cast<GBA*>(context->core->board);
+#ifdef M_CORE_GBA
+		GBA* gba = static_cast<GBA*>(context->core->board);
+#endif
+#ifdef M_CORE_GB
+		GB* gb = static_cast<GB*>(context->core->board);
+#endif
+		switch (context->core->platform(context->core)) {
+#ifdef M_CORE_GBA
+		case PLATFORM_GBA:
 			gba->luminanceSource = &controller->m_lux;
 			gba->rumble = controller->m_inputController->rumble();
-			gba->rotationSource = controller->m_inputController->rotationSource();
 			gba->audio.psg.forceDisableCh[0] = !controller->m_audioChannels[0];
 			gba->audio.psg.forceDisableCh[1] = !controller->m_audioChannels[1];
 			gba->audio.psg.forceDisableCh[2] = !controller->m_audioChannels[2];
diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c
index a34798a67..ff348f8d7 100644
--- a/src/platform/wii/main.c
+++ b/src/platform/wii/main.c
@@ -523,8 +523,8 @@ void _guiFinish(void) {
 void _setup(struct mGUIRunner* runner) {
 	if (runner->core->platform(runner->core) == PLATFORM_GBA) {
 		((struct GBA*) runner->core->board)->rumble = &rumble;
-		((struct GBA*) runner->core->board)->rotationSource = &rotation;
 	}
+	runner->core->setRotation(runner->core, &rotation);
 
 	_mapKey(&runner->core->inputMap, GCN1_INPUT, PAD_BUTTON_A, GBA_KEY_A);
 	_mapKey(&runner->core->inputMap, GCN1_INPUT, PAD_BUTTON_B, GBA_KEY_B);