aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Edvalson2016-04-22 16:43:59 -0400
committerThomas Edvalson2016-04-22 16:43:59 -0400
commit1531b4ddbf685f22970b7365515318b847e4f4f3 (patch)
treea736ba317f2b1b7b137f0f21286ae8ae5d27a029
parentbfb9ecec3573ed07bc9639426efd8289d05e00a6 (diff)
downloadscummvm-rg350-1531b4ddbf685f22970b7365515318b847e4f4f3.tar.gz
scummvm-rg350-1531b4ddbf685f22970b7365515318b847e4f4f3.tar.bz2
scummvm-rg350-1531b4ddbf685f22970b7365515318b847e4f4f3.zip
3DS: Add config class/dialog, c-pad cursor control, and option to disable screens
-rw-r--r--backends/platform/3ds/app/scummvm.rsf1
-rw-r--r--backends/platform/3ds/config.cpp87
-rw-r--r--backends/platform/3ds/config.h45
-rw-r--r--backends/platform/3ds/main.cpp14
-rw-r--r--backends/platform/3ds/module.mk2
-rw-r--r--backends/platform/3ds/options-dialog.cpp98
-rw-r--r--backends/platform/3ds/options-dialog.h70
-rw-r--r--backends/platform/3ds/osystem-audio.cpp4
-rw-r--r--backends/platform/3ds/osystem-events.cpp130
-rw-r--r--backends/platform/3ds/osystem-graphics.cpp153
-rw-r--r--backends/platform/3ds/osystem.cpp24
-rw-r--r--backends/platform/3ds/osystem.h27
12 files changed, 556 insertions, 99 deletions
diff --git a/backends/platform/3ds/app/scummvm.rsf b/backends/platform/3ds/app/scummvm.rsf
index d403bdbe91..a4518949bb 100644
--- a/backends/platform/3ds/app/scummvm.rsf
+++ b/backends/platform/3ds/app/scummvm.rsf
@@ -170,6 +170,7 @@ AccessControlInfo:
- soc:U
- ssl:C
- y2r:u
+ - gsp::Lcd
SystemControlInfo:
diff --git a/backends/platform/3ds/config.cpp b/backends/platform/3ds/config.cpp
new file mode 100644
index 0000000000..117b979d9f
--- /dev/null
+++ b/backends/platform/3ds/config.cpp
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "osystem.h"
+#include "options-dialog.h"
+#include "common/config-manager.h"
+#include <3ds.h>
+
+namespace _3DS {
+
+Config config;
+static Common::String prefix = "3ds_";
+
+static bool confGetBool(Common::String key, bool defaultVal) {
+ if (ConfMan.hasKey(prefix + key))
+ return ConfMan.getBool(prefix + key);
+ return defaultVal;
+}
+
+static void confSetBool(Common::String key, bool val) {
+ ConfMan.setBool(prefix + key, val);
+}
+
+static int confGetInt(Common::String key, int defaultVal) {
+ if (ConfMan.hasKey(prefix + key))
+ return ConfMan.getInt(prefix + key);
+ return defaultVal;
+}
+
+static void confSetInt(Common::String key, int val) {
+ ConfMan.setInt(prefix + key, val);
+}
+
+void loadConfig() {
+ config.showCursor = confGetBool("showcursor", true);
+ config.snapToBorder = confGetBool("snaptoborder", true);
+ config.stretchToFit = confGetBool("stretchtofit", false);
+ config.sensitivity = confGetInt("sensitivity", -5);
+ config.screen = confGetInt("screen", kScreenBoth);
+
+ // Turn off the backlight of any screen not used
+ if (R_SUCCEEDED(gspLcdInit())) {
+ if (config.screen == kScreenTop) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_TOP);
+ GSPLCD_PowerOffBacklight(GSPLCD_SCREEN_BOTTOM);
+ } else if (config.screen == kScreenBottom) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTTOM);
+ GSPLCD_PowerOffBacklight(GSPLCD_SCREEN_TOP);
+ } else
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
+ gspLcdExit();
+ }
+
+ OSystem_3DS *osys = (OSystem_3DS *)g_system;
+ osys->updateConfig();
+}
+
+void saveConfig() {
+ confSetBool("showcursor", config.showCursor);
+ confSetBool("snaptoborder", config.snapToBorder);
+ confSetBool("stretchtofit", config.stretchToFit);
+ confSetInt("sensitivity", config.sensitivity);
+ confSetInt("screen", config.screen);
+ ConfMan.flushToDisk();
+}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/config.h b/backends/platform/3ds/config.h
new file mode 100644
index 0000000000..c8b75736ad
--- /dev/null
+++ b/backends/platform/3ds/config.h
@@ -0,0 +1,45 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CONFIG_3DS_H
+#define CONFIG_3DS_H
+
+#include "common/str.h"
+
+namespace _3DS {
+
+struct Config {
+ bool showCursor;
+ bool snapToBorder;
+ bool stretchToFit;
+ int sensitivity;
+ int screen;
+};
+
+extern Config config;
+
+void loadConfig();
+void saveConfig();
+
+} // namespace _3DS
+
+#endif // CONFIG_3DS_H
diff --git a/backends/platform/3ds/main.cpp b/backends/platform/3ds/main.cpp
index 4b5dbbbbd2..6cc2c5cf5d 100644
--- a/backends/platform/3ds/main.cpp
+++ b/backends/platform/3ds/main.cpp
@@ -20,8 +20,6 @@
*
*/
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
-
#include "osystem.h"
#include <3ds.h>
@@ -32,7 +30,7 @@ int main(int argc, char *argv[]) {
osSetSpeedupEnable(true);
// consoleInit(GFX_TOP, NULL);
- g_system = new OSystem_3DS();
+ g_system = new _3DS::OSystem_3DS();
assert(g_system);
// Invoke the actual ScummVM main entry point
@@ -42,8 +40,14 @@ int main(int argc, char *argv[]) {
// res = scummvm_main(argc, argv);
scummvm_main(0, nullptr);
- delete dynamic_cast<OSystem_3DS*>(g_system);
-
+ delete dynamic_cast<_3DS::OSystem_3DS*>(g_system);
+
+ // Turn on both screen backlights before exiting.
+ if (R_SUCCEEDED(gspLcdInit())) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
+ gspLcdExit();
+ }
+
cfguExit();
gfxExit();
return 0;
diff --git a/backends/platform/3ds/module.mk b/backends/platform/3ds/module.mk
index 9c1e26b181..3eb15aef81 100644
--- a/backends/platform/3ds/module.mk
+++ b/backends/platform/3ds/module.mk
@@ -5,6 +5,8 @@ MODULE_OBJS := \
shader.shbin.o \
sprite.o \
gui.o \
+ config.o \
+ options-dialog.o \
osystem.o \
osystem-graphics.o \
osystem-audio.o \
diff --git a/backends/platform/3ds/options-dialog.cpp b/backends/platform/3ds/options-dialog.cpp
new file mode 100644
index 0000000000..0f8bfd0c66
--- /dev/null
+++ b/backends/platform/3ds/options-dialog.cpp
@@ -0,0 +1,98 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "options-dialog.h"
+#include "config.h"
+#include "gui/dialog.h"
+#include "gui/gui-manager.h"
+#include "gui/widgets/list.h"
+#include "gui/widgets/tab.h"
+#include "osystem.h"
+#include "engines/scumm/scumm.h"
+#include "gui/widgets/popup.h"
+
+#include "common/translation.h"
+
+namespace _3DS {
+
+bool optionMenuOpened = false;
+
+OptionsDialog::OptionsDialog() : GUI::Dialog(20, 20, 280, 200) {
+
+ optionMenuOpened = true;
+
+ new GUI::ButtonWidget(this, 120, 180, 72, 16, _("~C~lose"), 0, GUI::kCloseCmd);
+ new GUI::ButtonWidget(this, 200, 180, 72, 16, _("~S~ave"), 0, GUI::kOKCmd);
+
+ _showCursorCheckbox = new GUI::CheckboxWidget(this, 5, 5, 130, 20, _("Show mouse cursor"), 0, 0, 'T');
+ _showCursorCheckbox->setState(config.showCursor);
+
+ _snapToBorderCheckbox = new GUI::CheckboxWidget(this, 5, 22, 130, 20, _("Snap to edges"), 0, 0, 'T');
+ _snapToBorderCheckbox->setState(config.snapToBorder);
+
+ _stretchToFitCheckbox = new GUI::CheckboxWidget(this, 140, 5, 130, 20, _("Stretch to fit"), 0, 0, 'T');
+ _stretchToFitCheckbox->setState(config.stretchToFit);
+
+ new GUI::StaticTextWidget(this, 0, 60, 110, 15, _("Use Screen:"), Graphics::kTextAlignRight);
+ _screenRadioGroup = new GUI::RadiobuttonGroup(this, kScreenRadioGroup);
+ _screenTopRadioWidget = new GUI::RadiobuttonWidget(this, 120, 50, 60, 20, _screenRadioGroup, kScreenTop, _("Top"));
+ _screenBottomRadioWidget = new GUI::RadiobuttonWidget(this, 190, 50, 80, 20, _screenRadioGroup, kScreenBottom, _("Bottom"));
+ _screenBothRadioWidget = new GUI::RadiobuttonWidget(this, 155, 70, 80, 20, _screenRadioGroup, kScreenBoth, _("Both"));
+ _screenRadioGroup->setValue(config.screen);
+
+ new GUI::StaticTextWidget(this, 0, 100, 110, 15, _("C-Pad Sensitivity:"), Graphics::kTextAlignRight);
+ _sensitivity = new GUI::SliderWidget(this, 115, 100, 160, 15, "TODO: Add tooltip", 1);
+ _sensitivity->setMinValue(-15);
+ _sensitivity->setMaxValue(30);
+ _sensitivity->setValue(config.sensitivity);
+ _sensitivity->setFlags(GUI::WIDGET_CLEARBG);
+}
+
+OptionsDialog::~OptionsDialog() {
+ optionMenuOpened = false;
+}
+
+void OptionsDialog::updateConfigManager() {
+ config.showCursor = _showCursorCheckbox->getState();
+ config.snapToBorder = _snapToBorderCheckbox->getState();
+ config.stretchToFit = _stretchToFitCheckbox->getState();
+ config.sensitivity = _sensitivity->getValue();
+ config.screen = _screenRadioGroup->getValue();
+ saveConfig();
+ loadConfig();
+}
+
+void OptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+ switch(cmd) {
+ case GUI::kOKCmd:
+ updateConfigManager();
+ // Fall through
+ case GUI::kCloseCmd:
+ close();
+ break;
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ break;
+ }
+}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/options-dialog.h b/backends/platform/3ds/options-dialog.h
new file mode 100644
index 0000000000..6673b88e7b
--- /dev/null
+++ b/backends/platform/3ds/options-dialog.h
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef OPTIONS_DIALOG_3DS_H
+#define OPTIONS_DIALOG_3DS_H
+
+
+#include "common/scummsys.h"
+#include "common/str.h"
+#include "gui/object.h"
+#include "gui/widget.h"
+#include "gui/dialog.h"
+#include "gui/widgets/tab.h"
+#include "scumm/dialogs.h"
+
+namespace _3DS {
+
+enum {
+ kSave = 0x10000000,
+ kScreenRadioGroup,
+ kScreenTop,
+ kScreenBottom,
+ kScreenBoth,
+};
+
+extern bool optionMenuOpened;
+
+class OptionsDialog : public GUI::Dialog {
+
+public:
+ OptionsDialog();
+ ~OptionsDialog();
+
+protected:
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ void updateConfigManager();
+
+ GUI::SliderWidget *_sensitivity;
+ GUI::CheckboxWidget *_showCursorCheckbox;
+ GUI::CheckboxWidget *_snapToBorderCheckbox;
+ GUI::CheckboxWidget *_stretchToFitCheckbox;
+
+ GUI::RadiobuttonGroup *_screenRadioGroup;
+ GUI::RadiobuttonWidget *_screenTopRadioWidget;
+ GUI::RadiobuttonWidget *_screenBottomRadioWidget;
+ GUI::RadiobuttonWidget *_screenBothRadioWidget;
+};
+
+} // namespace _3DS
+
+#endif // OPTIONS_DIALOG_3DS_H
diff --git a/backends/platform/3ds/osystem-audio.cpp b/backends/platform/3ds/osystem-audio.cpp
index da74ab6d8a..17e419c36d 100644
--- a/backends/platform/3ds/osystem-audio.cpp
+++ b/backends/platform/3ds/osystem-audio.cpp
@@ -23,6 +23,8 @@
#include "osystem.h"
#include "audio/mixer.h"
+namespace _3DS {
+
static bool hasAudio = false;
static void audioThreadFunc(void *arg) {
@@ -104,3 +106,5 @@ Audio::Mixer *OSystem_3DS::getMixer() {
assert(_mixer);
return _mixer;
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index 5135e3ac1b..ae8a9b8b2b 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -21,12 +21,20 @@
*/
#include "backends/timer/default/default-timer.h"
+#include "engines/engine.h"
#include "gui.h"
+#include "options-dialog.h"
+#include "config.h"
#include "osystem.h"
+namespace _3DS {
+
static Common::Mutex *eventMutex;
static InputMode inputMode = MODE_DRAG;
static aptHookCookie cookie;
+static bool optionMenuOpening = false;
+static Common::String messageOSD;
+static bool showMessageOSD = false;
static void pushEventQueue(Common::Queue<Common::Event> *queue, Common::Event &event) {
Common::StackLock lock(*eventMutex);
@@ -40,6 +48,12 @@ static void eventThreadFunc(void *arg) {
uint32 touchStartTime = osys->getMillis();
touchPosition lastTouch = {0, 0};
bool isRightClick = false;
+ float cursorX = 0;
+ float cursorY = 0;
+ float cursorDeltaX = 0;
+ float cursorDeltaY = 0;
+ int circleDeadzone = 20;
+ int borderSnapZone = 6;
Common::Event event;
while (!osys->exiting) {
@@ -49,12 +63,35 @@ static void eventThreadFunc(void *arg) {
hidScanInput();
touchPosition touch;
+ circlePosition circle;
u32 held = hidKeysHeld();
u32 keysPressed = hidKeysDown();
u32 keysReleased = hidKeysUp();
+ // C-Pad used to control the cursor
+ hidCircleRead(&circle);
+ if (circle.dx < circleDeadzone && circle.dx > -circleDeadzone)
+ circle.dx = 0;
+ if (circle.dy < circleDeadzone && circle.dy > -circleDeadzone)
+ circle.dy = 0;
+ cursorDeltaX = (0.0002f + config.sensitivity / 100000.f) * circle.dx * abs(circle.dx);
+ cursorDeltaY = (0.0002f + config.sensitivity / 100000.f) * circle.dy * abs(circle.dy);
+
+ // Touch screen events
if (held & KEY_TOUCH) {
hidTouchRead(&touch);
+ if (config.snapToBorder) {
+ if (touch.px < borderSnapZone)
+ touch.px = 0;
+ if (touch.px > 319 - borderSnapZone)
+ touch.px = 319;
+ if (touch.py < borderSnapZone)
+ touch.py = 0;
+ if (touch.py > 239 - borderSnapZone)
+ touch.py = 239;
+ }
+ cursorX = touch.px;
+ cursorY = touch.py;
osys->transformPoint(touch);
osys->warpMouse(touch.px, touch.py);
@@ -89,7 +126,24 @@ static void eventThreadFunc(void *arg) {
event.type = isRightClick ? Common::EVENT_RBUTTONUP : Common::EVENT_LBUTTONUP;
pushEventQueue(eventQueue, event);
}
+ } else if (cursorDeltaX != 0 || cursorDeltaY != 0) {
+ cursorX += cursorDeltaX;
+ cursorY -= cursorDeltaY;
+ if (cursorX < 0) cursorX = 0;
+ if (cursorY < 0) cursorY = 0;
+ if (cursorX > 320) cursorX = 320;
+ if (cursorY > 240) cursorY = 240;
+ lastTouch.px = cursorX;
+ lastTouch.py = cursorY;
+ osys->transformPoint(lastTouch);
+ osys->warpMouse(lastTouch.px, lastTouch.py);
+ event.mouse.x = lastTouch.px;
+ event.mouse.y = lastTouch.py;
+ event.type = Common::EVENT_MOUSEMOVE;
+ pushEventQueue(eventQueue, event);
}
+
+ // Button events
if (keysPressed & KEY_R) {
if (inputMode == MODE_DRAG) {
inputMode = MODE_HOVER;
@@ -99,22 +153,24 @@ static void eventThreadFunc(void *arg) {
osys->displayMessageOnOSD("Drag Mode");
}
}
- if (keysPressed & KEY_A || keysPressed & KEY_DLEFT) {
+ if (keysPressed & KEY_A || keysPressed & KEY_DLEFT || keysReleased & KEY_A || keysReleased & KEY_DLEFT) {
// SIMULATE LEFT CLICK
event.mouse.x = lastTouch.px;
event.mouse.y = lastTouch.py;
- event.type = Common::EVENT_LBUTTONDOWN;
- pushEventQueue(eventQueue, event);
- event.type = Common::EVENT_LBUTTONUP;
+ if (keysPressed & KEY_A || keysPressed & KEY_DLEFT)
+ event.type = Common::EVENT_LBUTTONDOWN;
+ else
+ event.type = Common::EVENT_LBUTTONUP;
pushEventQueue(eventQueue, event);
}
- if (keysPressed & KEY_X || keysPressed & KEY_DUP) {
+ if (keysPressed & KEY_X || keysPressed & KEY_DUP || keysReleased & KEY_X || keysReleased & KEY_DUP) {
// SIMULATE RIGHT CLICK
event.mouse.x = lastTouch.px;
event.mouse.y = lastTouch.py;
- event.type = Common::EVENT_RBUTTONDOWN;
- pushEventQueue(eventQueue, event);
- event.type = Common::EVENT_RBUTTONUP;
+ if (keysPressed & KEY_X || keysPressed & KEY_DUP)
+ event.type = Common::EVENT_RBUTTONDOWN;
+ else
+ event.type = Common::EVENT_RBUTTONUP;
pushEventQueue(eventQueue, event);
}
if (keysPressed & KEY_L) {
@@ -126,8 +182,8 @@ static void eventThreadFunc(void *arg) {
pushEventQueue(eventQueue, event);
}
if (keysPressed & KEY_SELECT) {
- event.type = Common::EVENT_RTL;
- pushEventQueue(eventQueue, event);
+ if (!optionMenuOpened)
+ optionMenuOpening = true;
}
if (keysPressed & KEY_B || keysReleased & KEY_B || keysPressed & KEY_DDOWN || keysReleased & KEY_DDOWN) {
if (keysPressed & KEY_B || keysPressed & KEY_DDOWN)
@@ -146,25 +202,32 @@ static void eventThreadFunc(void *arg) {
}
static void aptHookFunc(APT_HookType hookType, void *param) {
- auto eventQueue = (Common::Queue<Common::Event> *)param;
OSystem_3DS *osys = (OSystem_3DS *)g_system;
- Common::Event event;
switch (hookType) {
case APTHOOK_ONSUSPEND:
case APTHOOK_ONSLEEP:
- event.type = Common::EVENT_MAINMENU;
- pushEventQueue(eventQueue, event);
+ if (g_engine)
+ g_engine->pauseEngine(true);
osys->sleeping = true;
+ if (R_SUCCEEDED(gspLcdInit())) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
+ gspLcdExit();
+ }
break;
case APTHOOK_ONRESTORE:
case APTHOOK_ONWAKEUP:
+ if (g_engine)
+ g_engine->pauseEngine(false);
osys->sleeping = false;
+ loadConfig();
break;
- default:
+ default: {
+ Common::StackLock lock(*eventMutex);
+ Common::Event event;
event.type = Common::EVENT_QUIT;
- pushEventQueue(eventQueue, event);
- break;
+ g_system->getEventManager()->pushEvent(event);
+ }
}
}
@@ -172,9 +235,8 @@ static void timerThreadFunc(void *arg) {
OSystem_3DS *osys = (OSystem_3DS *)arg;
DefaultTimerManager *tm = (DefaultTimerManager *)osys->getTimerManager();
while (!osys->exiting) {
- tm->handler();
g_system->delayMillis(10);
- aptMainLoop(); // Call apt hook when necessary
+ tm->handler();
}
}
@@ -185,7 +247,7 @@ void OSystem_3DS::initEvents() {
_timerThread = threadCreate(&timerThreadFunc, this, 32 * 1024, prio - 1, -2, false);
_eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 32 * 1024, prio - 1, -2, false);
- aptHook(&cookie, aptHookFunc, &_eventQueue);
+ aptHook(&cookie, aptHookFunc, this);
}
void OSystem_3DS::destroyEvents() {
@@ -199,21 +261,33 @@ void OSystem_3DS::destroyEvents() {
void OSystem_3DS::transformPoint(touchPosition &point) {
if (!_overlayVisible) {
- point.px = static_cast<float>(point.px) / _gameTexture.getScaleX() - _gameX;
- point.py = static_cast<float>(point.py) / _gameTexture.getScaleY() - _gameY;
+ point.px = static_cast<float>(point.px) / _gameBottomTexture.getScaleX() - _gameBottomX;
+ point.py = static_cast<float>(point.py) / _gameBottomTexture.getScaleY() - _gameBottomY;
}
}
void OSystem_3DS::displayMessageOnOSD(const char *msg) {
- _messageOSD = msg;
- _showMessageOSD = true;
+ messageOSD = msg;
+ showMessageOSD = true;
}
bool OSystem_3DS::pollEvent(Common::Event &event) {
- if (_showMessageOSD) {
- _showMessageOSD = false;
- StatusMessageDialog dialog(_messageOSD, 800);
+ if (showMessageOSD) {
+ showMessageOSD = false;
+ StatusMessageDialog dialog(messageOSD, 800);
+ dialog.runModal();
+ }
+
+ aptMainLoop(); // Call apt hook when necessary
+
+ if (optionMenuOpening) {
+ optionMenuOpening = false;
+ OptionsDialog dialog;
+ if (g_engine)
+ g_engine->pauseEngine(true);
dialog.runModal();
+ if (g_engine)
+ g_engine->pauseEngine(false);
}
Common::StackLock lock(*eventMutex);
@@ -224,3 +298,5 @@ bool OSystem_3DS::pollEvent(Common::Event &event) {
event = _eventQueue.pop();
return true;
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 0e50d2b911..0cfd70c9cd 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -24,6 +24,8 @@
#include "backends/platform/3ds/osystem.h"
#include "backends/platform/3ds/shader_shbin.h"
#include "common/rect.h"
+#include "options-dialog.h"
+#include "config.h"
// Used to transfer the final rendered display to the framebuffer
#define DISPLAY_TRANSFER_FLAGS \
@@ -32,6 +34,8 @@
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
+namespace _3DS {
+
void OSystem_3DS::initGraphics() {
_pfGame = Graphics::PixelFormat::createFormatCLUT8();
_pfGameTexture = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
@@ -79,7 +83,8 @@ void OSystem_3DS::initGraphics() {
void OSystem_3DS::destroyGraphics() {
_gameScreen.free();
- _gameTexture.free();
+ _gameTopTexture.free();
+ _gameBottomTexture.free();
_overlay.free();
shaderProgramFree(&_program);
@@ -92,16 +97,12 @@ void OSystem_3DS::destroyGraphics() {
}
bool OSystem_3DS::hasFeature(OSystem::Feature f) {
- return (f == OSystem::kFeatureFullscreenMode ||
- f == OSystem::kFeatureCursorPalette ||
+ return (f == OSystem::kFeatureCursorPalette ||
f == OSystem::kFeatureOverlaySupportsAlpha);
}
void OSystem_3DS::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- _isFullscreen = enable;
- break;
case OSystem::kFeatureCursorPalette:
_cursorPaletteEnabled = enable;
flushCursor();
@@ -113,8 +114,6 @@ void OSystem_3DS::setFeatureState(OSystem::Feature f, bool enable) {
bool OSystem_3DS::getFeatureState(OSystem::Feature f) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- return _isFullscreen;
case OSystem::kFeatureCursorPalette:
return _cursorPaletteEnabled;
default:
@@ -147,7 +146,7 @@ void OSystem_3DS::initSize(uint width, uint height,
debug("3ds initsize w:%d h:%d", width, height);
_gameWidth = width;
_gameHeight = height;
- _gameTexture.create(width, height, _pfGameTexture);
+ _gameTopTexture.create(width, height, _pfGameTexture);
_overlay.create(getOverlayWidth(), getOverlayHeight(), _pfGameTexture);
if (format) {
@@ -160,30 +159,48 @@ void OSystem_3DS::initSize(uint width, uint height,
_focusDirty = true;
_focusRect = Common::Rect(_gameWidth, _gameHeight);
- if (_isFullscreen) {
- _gameRatio = 320.f / 240.f;
- _gameX = _gameY = 0;
- _gameTexture.setScale(320.f / width, 240.f / height);
+ updateSize();
+}
+
+void OSystem_3DS::updateSize() {
+ if (config.stretchToFit) {
+ _gameTopX = _gameTopY = _gameBottomX = _gameBottomY = 0;
+ _gameTopTexture.setScale(400.f / _gameWidth, 240.f / _gameHeight);
+ _gameBottomTexture.setScale(320.f / _gameWidth, 240.f / _gameHeight);
} else {
- _gameRatio = static_cast<float>(width) / height;
- if (width > height) {
- _gameX = 0;
- _gameY = (240.f - 320.f / width * height) / 2.f;
+ float ratio = static_cast<float>(_gameWidth) / _gameHeight;
+
+ if (ratio > 400.f / 240.f) {
+ float r = 400.f / _gameWidth;
+ _gameTopTexture.setScale(r, r);
+ _gameTopX = 0;
+ _gameTopY = (240.f - r * _gameHeight) / 2.f;
} else {
- _gameY = 0;
- _gameX = (320.f - 240.f / height * width) / 2.f;
+ float r = 240.f / _gameHeight;
+ _gameTopTexture.setScale(r, r);
+ _gameTopY = 0;
+ _gameTopX = (400.f - r * _gameWidth) / 2.f;
+ }
+ if (ratio > 320.f / 240.f) {
+ float r = 320.f / _gameWidth;
+ _gameBottomTexture.setScale(r, r);
+ _gameBottomX = 0;
+ _gameBottomY = (240.f - r * _gameHeight) / 2.f;
+ } else {
+ float r = 240.f / _gameHeight;
+ _gameBottomTexture.setScale(r, r);
+ _gameBottomY = 0;
+ _gameBottomX = (320.f - r * _gameWidth) / 2.f;
}
- _gameTexture.setScale((width > 320) ? 320.f / width : 1.f,
- (height > 240) ? 240.f / height : 1.f);
}
- _gameTexture.setPosition(_gameX, _gameY);
- _cursorTexture.setScale(_gameTexture.getScaleX(), _gameTexture.getScaleY());
-
- float ratio = 400.f / _gameWidth;
- int y = (_gameHeight * ratio - 240.f) / 2;
- Mtx_Identity(&_focusMatrix);
- Mtx_Translate(&_focusMatrix, 0, -y, 0);
- Mtx_Scale(&_focusMatrix, ratio, ratio, 1.f);
+ _gameTopTexture.setPosition(_gameTopX, _gameTopY);
+ _gameBottomTexture.setPosition(_gameBottomX, _gameBottomY);
+ if (_overlayVisible)
+ _cursorTexture.setScale(1.f, 1.f);
+ else if (config.screen == kScreenTop)
+ _cursorTexture.setScale(_gameTopTexture.getScaleX(), _gameTopTexture.getScaleY());
+ else
+ _cursorTexture.setScale(_gameBottomTexture.getScaleX(), _gameBottomTexture.getScaleY());
}
Common::List<Graphics::PixelFormat> OSystem_3DS::getSupportedFormats() const {
@@ -225,17 +242,17 @@ void OSystem_3DS::copyRectToScreen(const void *buf, int pitch, int x,
Graphics::Surface subSurface = _gameScreen.getSubArea(rect);
Graphics::Surface *convertedSubSurface = subSurface.convertTo(_pfGameTexture, _palette);
- _gameTexture.copyRectToSurface(*convertedSubSurface, x, y, Common::Rect(w, h));
+ _gameTopTexture.copyRectToSurface(*convertedSubSurface, x, y, Common::Rect(w, h));
convertedSubSurface->free();
delete convertedSubSurface;
- _gameTexture.markDirty();
+ _gameTopTexture.markDirty();
}
void OSystem_3DS::flushGameScreen() {
Graphics::Surface *converted = _gameScreen.convertTo(_pfGameTexture, _palette);
- _gameTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
- _gameTexture.markDirty();
+ _gameTopTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
+ _gameTopTexture.markDirty();
converted->free();
delete converted;
}
@@ -257,23 +274,36 @@ void OSystem_3DS::updateScreen() {
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
// Render top screen
C3D_FrameDrawOn(_renderTargetTop);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionTop);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, &_focusMatrix);
- _gameTexture.render();
- _gameTexture.render();
+ if (config.screen == kScreenTop || config.screen == kScreenBoth) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionTop);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameTopTexture.getMatrix());
+ _gameTopTexture.render();
+ _gameTopTexture.render();
+ if (_overlayVisible && config.screen == kScreenTop) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
+ _overlay.render();
+ }
+ if (_cursorVisible && config.showCursor && config.screen == kScreenTop) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
+ _cursorTexture.render();
+ }
+ }
// Render bottom screen
C3D_FrameDrawOn(_renderTargetBottom);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionBottom);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameTexture.getMatrix());
- _gameTexture.render();
- if (_overlayVisible) {
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
- _overlay.render();
- }
- if (_cursorVisible) {
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
- _cursorTexture.render();
+ if (config.screen == kScreenBottom || config.screen == kScreenBoth) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionBottom);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameBottomTexture.getMatrix());
+ _gameTopTexture.render();
+ _gameTopTexture.render();
+ if (_overlayVisible) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
+ _overlay.render();
+ }
+ if (_cursorVisible && config.showCursor) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
+ _cursorTexture.render();
+ }
}
C3D_FrameEnd(0);
}
@@ -281,7 +311,8 @@ void OSystem_3DS::updateScreen() {
void OSystem_3DS::setShakePos(int shakeOffset) {
// TODO: implement this in overlay, top screen, and mouse too
_screenShakeOffset = shakeOffset;
- _gameTexture.setPosition(_gameX, _gameY + shakeOffset);
+ _gameTopTexture.setPosition(_gameTopX, _gameTopY + _gameTopTexture.getScaleY() * shakeOffset);
+ _gameBottomTexture.setPosition(_gameBottomX, _gameBottomY + _gameBottomTexture.getScaleY() * shakeOffset);
}
void OSystem_3DS::setFocusRectangle(const Common::Rect &rect) {
@@ -363,13 +394,13 @@ void OSystem_3DS::updateFocus() {
void OSystem_3DS::showOverlay() {
_overlayVisible = true;
- _cursorTexture.setScale(1.f, 1.f);
+ updateSize();
updateScreen();
}
void OSystem_3DS::hideOverlay() {
_overlayVisible = false;
- _cursorTexture.setScale(_gameTexture.getScaleX(), _gameTexture.getScaleY());
+ updateSize();
updateScreen();
}
@@ -410,9 +441,25 @@ bool OSystem_3DS::showMouse(bool visible) {
void OSystem_3DS::warpMouse(int x, int y) {
_cursorX = x;
_cursorY = y;
+ warning("x:%d y:%d", x, y);
// TODO: adjust for _cursorScalable ?
- _cursorTexture.setPosition(x - _cursorHotspotX + (_overlayVisible ? 0 : _gameX),
- y - _cursorHotspotY + (_overlayVisible ? 0 : _gameY));
+ int offsetx = 0;
+ int offsety = 0;
+ x -= _cursorHotspotX;
+ y -= _cursorHotspotY;
+ if (!_overlayVisible) {
+ offsetx += config.screen == kScreenTop ? _gameTopX : _gameBottomX;
+ offsety += config.screen == kScreenTop ? _gameTopY : _gameBottomY;
+ }
+ float scalex = config.screen == kScreenTop ? (float)_gameTopTexture.actualWidth / _gameWidth : 1.f;
+ float scaley = config.screen == kScreenTop ? (float)_gameTopTexture.actualHeight / _gameHeight : 1.f;
+ _cursorTexture.setPosition(scalex * x + offsetx,
+ scaley * y + offsety);
+}
+
+void OSystem_3DS::setCursorDelta(float deltaX, float deltaY) {
+ _cursorDeltaX = deltaX;
+ _cursorDeltaY = deltaY;
}
void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
@@ -466,3 +513,5 @@ void OSystem_3DS::flushCursor() {
}
}
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index af0b7b5700..f6278eb16b 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -33,12 +33,15 @@
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/str.h"
+#include "config.h"
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.h"
#include <unistd.h>
#include <time.h>
+namespace _3DS {
+
OSystem_3DS::OSystem_3DS():
_focusDirty(true),
_focusRect(Common::Rect(1, 1)),
@@ -55,19 +58,20 @@ OSystem_3DS::OSystem_3DS():
_focusStepScaleX(0.f),
_focusStepScaleY(0.f),
_focusClearTime(0),
- _showMessageOSD(false),
- _isFullscreen(false),
+ _cursorPaletteEnabled(false),
_cursorVisible(false),
_cursorScalable(false),
- _cursorPaletteEnabled(false),
_cursorX(0),
_cursorY(0),
_cursorHotspotX(0),
_cursorHotspotY(0),
- _gameX(0),
- _gameY(0),
+ _gameTopX(0),
+ _gameTopY(0),
+ _gameBottomX(0),
+ _gameBottomY(0),
_gameWidth(320),
_gameHeight(240),
+ _overlayVisible(false),
exiting(false),
sleeping(false)
{
@@ -91,6 +95,7 @@ void OSystem_3DS::quit() {
}
void OSystem_3DS::initBackend() {
+ loadConfig();
ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", true);
if (!ConfMan.hasKey("vkeybd_pack_name"))
@@ -111,6 +116,13 @@ void OSystem_3DS::initBackend() {
EventsBaseBackend::initBackend();
}
+void OSystem_3DS::updateConfig() {
+ if (_gameScreen.getPixels()) {
+ updateSize();
+ warpMouse(_cursorX, _cursorY);
+ }
+}
+
Common::String OSystem_3DS::getDefaultConfigFileName() {
return "/3ds/scummvm/scummvm.ini";
}
@@ -177,3 +189,5 @@ void OSystem_3DS::fatalError() {
void OSystem_3DS::logMessage(LogMessageType::Type type, const char *message) {
printf("3DS log: %s\n", message);
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index a8c2a909f1..478085acba 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -35,7 +35,9 @@
#include "common/queue.h"
#define TICKS_PER_MSEC 268123
-
+
+namespace _3DS {
+
enum {
GFX_LINEAR = 0,
GFX_NEAREST = 1
@@ -54,7 +56,7 @@ static const OSystem::GraphicsMode s_graphicsModes[] = {
class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
public:
OSystem_3DS();
- ~OSystem_3DS();
+ virtual ~OSystem_3DS();
volatile bool exiting;
volatile bool sleeping;
@@ -130,9 +132,14 @@ public:
const Graphics::PixelFormat *format = NULL);
void setCursorPalette(const byte *colors, uint start, uint num);
+ // Transform point from touchscreen coords into gamescreen coords
void transformPoint(touchPosition &point);
+ void setCursorDelta(float deltaX, float deltaY);
+
void updateFocus();
+ void updateConfig();
+ void updateSize();
private:
void initGraphics();
@@ -150,8 +157,8 @@ protected:
private:
u16 _gameWidth, _gameHeight;
- u16 _gameX, _gameY;
- float _gameRatio;
+ u16 _gameTopX, _gameTopY;
+ u16 _gameBottomX, _gameBottomY;
// Audio
Thread audioThread;
@@ -164,12 +171,12 @@ private:
byte _cursorPalette[3 * 256];
Graphics::Surface _gameScreen;
- Sprite _gameTexture;
+ Sprite _gameTopTexture;
+ Sprite _gameBottomTexture;
Sprite _overlay;
int _screenShakeOffset;
bool _overlayVisible;
- bool _isFullscreen;
DVLB_s *_dvlb;
shaderProgram_s _program;
@@ -196,9 +203,6 @@ private:
Thread _eventThread;
Thread _timerThread;
Common::Queue<Common::Event> _eventQueue;
-
- Common::String _messageOSD;
- bool _showMessageOSD;
// Cursor
Graphics::Surface _cursor;
@@ -206,9 +210,12 @@ private:
bool _cursorPaletteEnabled;
bool _cursorVisible;
bool _cursorScalable;
- int _cursorX, _cursorY;
+ float _cursorX, _cursorY;
+ float _cursorDeltaX, _cursorDeltaY;
int _cursorHotspotX, _cursorHotspotY;
uint32 _cursorKeyColor;
};
+} // namespace _3DS
+
#endif