From f80a8b7fd6617556372ebc4909becf090ee3040c Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Wed, 25 Aug 2021 22:21:58 +0100 Subject: [PATCH] DS: WIP virtual keyboard support --- backends/events/ds/ds-events.cpp | 34 +++--- backends/events/ds/ds-events.h | 5 +- backends/platform/ds/ds-graphics.cpp | 36 +++++-- backends/platform/ds/keyboard.cpp | 149 +++++++++++++++++++++++++++ backends/platform/ds/keyboard.h | 56 ++++++++++ backends/platform/ds/module.mk | 1 + backends/platform/ds/osystem_ds.cpp | 4 +- backends/platform/ds/osystem_ds.h | 4 + 8 files changed, 263 insertions(+), 26 deletions(-) create mode 100644 backends/platform/ds/keyboard.cpp create mode 100644 backends/platform/ds/keyboard.h diff --git a/backends/events/ds/ds-events.cpp b/backends/events/ds/ds-events.cpp index 95bd038a84e..0f9a05266f7 100644 --- a/backends/events/ds/ds-events.cpp +++ b/backends/events/ds/ds-events.cpp @@ -69,25 +69,27 @@ void DSEventSource::addEventsToQueue() { uint32 held = keysHeld(), keysPressed = keysDown(), keysReleased = keysUp(); // Touch screen events - if (held & KEY_TOUCH) { - touchPosition touchPos; - touchRead(&touchPos); - event.mouse = dynamic_cast(g_system)->transformPoint(touchPos.px, touchPos.py); + if (_handleTouch) { + if (held & KEY_TOUCH) { + touchPosition touchPos; + touchRead(&touchPos); + event.mouse = dynamic_cast(g_system)->transformPoint(touchPos.px, touchPos.py); - if (event.mouse.x != _lastTouch.x || event.mouse.y != _lastTouch.y) { - event.type = Common::EVENT_MOUSEMOVE; + if (event.mouse.x != _lastTouch.x || event.mouse.y != _lastTouch.y) { + event.type = Common::EVENT_MOUSEMOVE; + _eventQueue.push(event); + } + if (keysPressed & KEY_TOUCH) { + event.type = Common::EVENT_LBUTTONDOWN; + _eventQueue.push(event); + } + + _lastTouch = event.mouse; + } else if (keysReleased & KEY_TOUCH) { + event.mouse = _lastTouch; + event.type = Common::EVENT_LBUTTONUP; _eventQueue.push(event); } - if (keysPressed & KEY_TOUCH) { - event.type = Common::EVENT_LBUTTONDOWN; - _eventQueue.push(event); - } - - _lastTouch = event.mouse; - } else if (keysReleased & KEY_TOUCH) { - event.mouse = _lastTouch; - event.type = Common::EVENT_LBUTTONUP; - _eventQueue.push(event); } // Button events diff --git a/backends/events/ds/ds-events.h b/backends/events/ds/ds-events.h index d3fa3e46ee5..f2ea7f003ea 100644 --- a/backends/events/ds/ds-events.h +++ b/backends/events/ds/ds-events.h @@ -30,17 +30,20 @@ */ class DSEventSource : public Common::EventSource { public: - DSEventSource() : _firstPoll(true) {} + DSEventSource() : _firstPoll(true), _handleTouch(true) {} /** * Gets and processes events. */ virtual bool pollEvent(Common::Event &event); + virtual void handleTouch(bool enabled) { _handleTouch = enabled; } + protected: Common::Queue _eventQueue; Common::Point _lastTouch; bool _firstPoll; + bool _handleTouch; void addEventsToQueue(); void addJoyButtonEvent(u32 keysPressed, u32 keysReleased, u32 ndsKey, uint8 svmButton); diff --git a/backends/platform/ds/ds-graphics.cpp b/backends/platform/ds/ds-graphics.cpp index 61158226986..e320431be37 100644 --- a/backends/platform/ds/ds-graphics.cpp +++ b/backends/platform/ds/ds-graphics.cpp @@ -149,6 +149,7 @@ void initHardware() { videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); vramSetBankA(VRAM_A_MAIN_BG_0x06000000); vramSetBankB(VRAM_B_MAIN_BG_0x06020000); + vramSetBankC(VRAM_C_SUB_BG_0x06200000); vramSetBankD(VRAM_D_MAIN_BG_0x06040000); vramSetBankE(VRAM_E_MAIN_SPRITE); @@ -159,19 +160,15 @@ void initHardware() { subScTargetX = 0; subScTargetY = 0; - lcdMainOnBottom(); - //irqs are nice irqSet(IRQ_VBLANK, VBlankHandler); irqEnable(IRQ_VBLANK); #ifndef DISABLE_TEXT_CONSOLE - videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); - vramSetBankH(VRAM_H_SUB_BG); - consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true); + videoSetModeSub(MODE_0_2D); + consoleInit(NULL, 1, BgType_Text4bpp, BgSize_T_256x256, 30, 0, false, true); #else videoSetModeSub(MODE_3_2D | DISPLAY_BG3_ACTIVE); - vramSetBankC(VRAM_C_SUB_BG_0x06200000); #endif } @@ -180,10 +177,15 @@ void initHardware() { void OSystem_DS::initGraphics() { DS::initHardware(); + setSwapLCDs(false); + oamInit(&oamMain, SpriteMapping_Bmp_1D_128, false); _cursorSprite = oamAllocateGfx(&oamMain, SpriteSize_64x64, SpriteColorFormat_Bmp); _overlay.create(256, 192, true, 2, false, 0, false); + + _keyboard = new DS::Keyboard(_eventManager->getEventDispatcher()); + _keyboard->init(0, 34, 1, false); } void OSystem_DS::setMainScreen(int32 x, int32 y, int32 sx, int32 sy) { @@ -199,22 +201,42 @@ void OSystem_DS::setSubScreen(int32 x, int32 y, int32 sx, int32 sy) { } bool OSystem_DS::hasFeature(Feature f) { - return (f == kFeatureCursorPalette) || (f == kFeatureStretchMode); + return (f == kFeatureCursorPalette) || (f == kFeatureStretchMode) || (f == kFeatureVirtualKeyboard); } void OSystem_DS::setFeatureState(Feature f, bool enable) { if (f == kFeatureCursorPalette) { _disableCursorPalette = !enable; _cursorDirty = true; + } else if (f == kFeatureVirtualKeyboard) { + if (enable) { + setSwapLCDs(true); + _keyboard->show(); + } else { + _keyboard->hide(); + setSwapLCDs(false); + } } } bool OSystem_DS::getFeatureState(Feature f) { if (f == kFeatureCursorPalette) return !_disableCursorPalette; + else if (f == kFeatureVirtualKeyboard) + return _keyboard->isVisible(); return false; } +void OSystem_DS::setSwapLCDs(bool swap) { + if (swap) { + lcdMainOnTop(); + _eventSource->handleTouch(false); + } else { + lcdMainOnBottom(); + _eventSource->handleTouch(true); + } +} + static const OSystem::GraphicsMode graphicsModes[] = { { "NONE", _s("Unscaled"), GFX_NOSCALE }, { "HW", _s("Hardware scale (fast, but low quality)"), GFX_HWSCALE }, diff --git a/backends/platform/ds/keyboard.cpp b/backends/platform/ds/keyboard.cpp new file mode 100644 index 00000000000..d7f1064f19c --- /dev/null +++ b/backends/platform/ds/keyboard.cpp @@ -0,0 +1,149 @@ +/* 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 + +#include "backends/platform/ds/keyboard.h" +#include "common/system.h" + +namespace DS { + +Keyboard::Keyboard(Common::EventDispatcher *eventDispatcher) : + _eventDispatcher(eventDispatcher), + _lastKey(NOKEY), + _visible(false) { + _eventDispatcher->registerSource(this, false); + _eventDispatcher->registerObserver(this, 10, false); +} + +Keyboard::~Keyboard() { + _eventDispatcher->unregisterObserver(this); + _eventDispatcher->unregisterSource(this); +} + +void Keyboard::init(int layer, int mapBase, int tileBase, bool mainDisplay) { + keyboardInit(nullptr, layer, BgType_Text4bpp, BgSize_T_256x512, mapBase, tileBase, mainDisplay, true); +} + +void Keyboard::show() { + keyboardShow(); + _visible = true; +} + +void Keyboard::hide() { + keyboardHide(); + _visible = false; +} + +bool Keyboard::mapKey(int key, Common::KeyState &ks) { + switch (key) { + case DVK_BACKSPACE: + ks = Common::KeyState(Common::KEYCODE_BACKSPACE, Common::ASCII_BACKSPACE); + break; + case DVK_TAB: + ks = Common::KeyState(Common::KEYCODE_TAB, Common::ASCII_TAB); + break; + case DVK_ENTER: + ks = Common::KeyState(Common::KEYCODE_RETURN, Common::ASCII_RETURN); + break; + case DVK_SPACE: + ks = Common::KeyState(Common::KEYCODE_SPACE, Common::ASCII_SPACE); + break; + case DVK_MENU: + ks = Common::KeyState(Common::KEYCODE_MENU); + break; + case DVK_SHIFT: + ks = Common::KeyState(Common::KEYCODE_LSHIFT); + break; + case DVK_CAPS: + ks = Common::KeyState(Common::KEYCODE_CAPSLOCK); + break; + case DVK_CTRL: + ks = Common::KeyState(Common::KEYCODE_LCTRL); + break; + case DVK_UP: + ks = Common::KeyState(Common::KEYCODE_UP); + break; + case DVK_RIGHT: + ks = Common::KeyState(Common::KEYCODE_RIGHT); + break; + case DVK_DOWN: + ks = Common::KeyState(Common::KEYCODE_DOWN); + break; + case DVK_LEFT: + ks = Common::KeyState(Common::KEYCODE_LEFT); + break; + case DVK_FOLD: + ks = Common::KeyState(Common::KEYCODE_ESCAPE, Common::ASCII_ESCAPE); + break; + case DVK_ALT: + ks = Common::KeyState(Common::KEYCODE_LALT); + break; + default: + if (key < Common::KEYCODE_SPACE || key > Common::KEYCODE_z) + return false; + ks = Common::KeyState((Common::KeyCode)tolower(key), key); + break; + } + + return true; +} + +bool Keyboard::pollEvent(Common::Event &event) { + if (!_visible) + return false; + + int key = keyboardUpdate(); + if (key == _lastKey) + return false; + + if (key == NOKEY) { + event.type = Common::EVENT_KEYUP; + if (!mapKey(_lastKey, event.kbd)) + return false; + } else { + event.type = Common::EVENT_KEYDOWN; + if (!mapKey(key, event.kbd)) + return false; + } + + _lastKey = key; + + // TODO: Handle flags + + return true; +} + +bool Keyboard::notifyEvent(const Common::Event &event) { +#if 0 + if (event.type == Common::EVENT_VIRTUAL_KEYBOARD) { + if (g_system->getFeatureState(OSystem::kFeatureVirtualKeyboard)) + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + else + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + return true; + } +#endif + return false; +} + +} // End of namespace DS diff --git a/backends/platform/ds/keyboard.h b/backends/platform/ds/keyboard.h new file mode 100644 index 00000000000..332d4efb0ae --- /dev/null +++ b/backends/platform/ds/keyboard.h @@ -0,0 +1,56 @@ +/* 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 DS_KEYBOARD_H +#define DS_KEYBOARD_H + +#include "common/events.h" + +namespace DS { + +class Keyboard : public Common::EventSource, public Common::EventObserver { +public: + Keyboard(Common::EventDispatcher *eventDispatcher); + ~Keyboard(); + + void init(int layer, int mapBase, int tileBase, bool mainDisplay); + + void show(); + void hide(); + inline bool isVisible() const { return _visible; } + + // Implementation of the EventSource interface + virtual bool pollEvent(Common::Event &event); + + virtual bool notifyEvent(const Common::Event &event) override; + +protected: + Common::EventDispatcher *_eventDispatcher; + int _lastKey; + bool _visible; + + bool mapKey(int key, Common::KeyState &ks); +}; + +} // End of namespace DS + +#endif // #ifndef DS_KEYBOARD_H diff --git a/backends/platform/ds/module.mk b/backends/platform/ds/module.mk index 27204b94139..0a689453a1b 100644 --- a/backends/platform/ds/module.mk +++ b/backends/platform/ds/module.mk @@ -5,6 +5,7 @@ MODULE_OBJS := \ blitters_arm.o \ ds-graphics.o \ dsmain.o \ + keyboard.o \ osystem_ds.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. diff --git a/backends/platform/ds/osystem_ds.cpp b/backends/platform/ds/osystem_ds.cpp index 2c2c0d32a8f..ea05259bcbf 100644 --- a/backends/platform/ds/osystem_ds.cpp +++ b/backends/platform/ds/osystem_ds.cpp @@ -71,8 +71,6 @@ void timerTickHandler() { } void OSystem_DS::initBackend() { - initGraphics(); - defaultExceptionHandler(); ConfMan.setInt("autosave_period", 0); @@ -88,6 +86,8 @@ void OSystem_DS::initBackend() { _mixerManager = new MaxModMixerManager(11025, 32768); _mixerManager->init(); + initGraphics(); + BaseBackend::initBackend(); } diff --git a/backends/platform/ds/osystem_ds.h b/backends/platform/ds/osystem_ds.h index e3c83e6bb0e..b1b7a09dffc 100644 --- a/backends/platform/ds/osystem_ds.h +++ b/backends/platform/ds/osystem_ds.h @@ -28,6 +28,7 @@ #include "backends/events/ds/ds-events.h" #include "backends/mixer/mixer.h" #include "backends/platform/ds/background.h" +#include "backends/platform/ds/keyboard.h" #include "graphics/surface.h" #include "graphics/palette.h" @@ -60,6 +61,7 @@ protected: bool _cursorVisible; DSEventSource *_eventSource; + DS::Keyboard *_keyboard; void initGraphics(); @@ -145,6 +147,8 @@ public: virtual void setCursorPalette(const byte *colors, uint start, uint num); + void setSwapLCDs(bool swap); + void refreshCursor(u16 *dst, const Graphics::Surface &src, const uint16 *palette); virtual void logMessage(LogMessageType::Type type, const char *message);