diff options
author | Thomas Edvalson | 2016-04-22 16:43:59 -0400 |
---|---|---|
committer | Thomas Edvalson | 2016-04-22 16:43:59 -0400 |
commit | 1531b4ddbf685f22970b7365515318b847e4f4f3 (patch) | |
tree | a736ba317f2b1b7b137f0f21286ae8ae5d27a029 /backends | |
parent | bfb9ecec3573ed07bc9639426efd8289d05e00a6 (diff) | |
download | scummvm-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
Diffstat (limited to 'backends')
-rw-r--r-- | backends/platform/3ds/app/scummvm.rsf | 1 | ||||
-rw-r--r-- | backends/platform/3ds/config.cpp | 87 | ||||
-rw-r--r-- | backends/platform/3ds/config.h | 45 | ||||
-rw-r--r-- | backends/platform/3ds/main.cpp | 14 | ||||
-rw-r--r-- | backends/platform/3ds/module.mk | 2 | ||||
-rw-r--r-- | backends/platform/3ds/options-dialog.cpp | 98 | ||||
-rw-r--r-- | backends/platform/3ds/options-dialog.h | 70 | ||||
-rw-r--r-- | backends/platform/3ds/osystem-audio.cpp | 4 | ||||
-rw-r--r-- | backends/platform/3ds/osystem-events.cpp | 130 | ||||
-rw-r--r-- | backends/platform/3ds/osystem-graphics.cpp | 153 | ||||
-rw-r--r-- | backends/platform/3ds/osystem.cpp | 24 | ||||
-rw-r--r-- | backends/platform/3ds/osystem.h | 27 |
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 |