diff options
-rw-r--r-- | backends/platform/psp/README.PSP | 136 | ||||
-rw-r--r-- | backends/platform/psp/README.PSP.in | 136 | ||||
-rw-r--r-- | backends/platform/psp/cursor.h | 2 | ||||
-rw-r--r-- | backends/platform/psp/display_client.h | 1 | ||||
-rw-r--r-- | backends/platform/psp/input.cpp | 583 | ||||
-rw-r--r-- | backends/platform/psp/input.h | 154 | ||||
-rw-r--r-- | backends/platform/psp/pspkeyboard.cpp | 22 | ||||
-rw-r--r-- | backends/platform/psp/pspkeyboard.h | 8 |
8 files changed, 702 insertions, 340 deletions
diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP index ebafdb0b17..fc49f3fd60 100644 --- a/backends/platform/psp/README.PSP +++ b/backends/platform/psp/README.PSP @@ -3,79 +3,95 @@ ScummVM-PSP 1.3.0svn README Installation ============ - - Copy the relevant game datafiles to your memory stick (location - doesn't matter). - - Install ScummVM like any other homebrew - - Run ScummVM and use the launcher to add games and run them - + - Copy the relevant game datafiles to your memory stick (location doesn't matter). + - Install ScummVM like any other homebrew. + - Run ScummVM and use the launcher to add games and run them. Controls ======== - -Left trigger - ESC Right trigger - Modifier key (see below for uses) +Left trigger - ESC (Usually skips cutscenes. Depends on game) Analog - Mouse movement -Right trigger + Analog - Fine control mouse -Directions - Arrow keys -Directions + Right Trigger - Diagonal arrow keys -Triangle - Enter -Cross - Mouse button 1 -Circle - Mouse button 2 -Square - '.' (skip dialogue in some games) -Start - F5 (Main Menu) -Right trigger + Start - Return-To-Launcher menu - -Virtual Keyboard -================ - -Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen. -Start - Enter -Right trigger - Switch to/between letter modes -Left trigger - Switch to/between numbers and symbols -D-Pad - Select square of characters -Buttons/Triggers - Choose a specific character - +Right trigger + Analog - Fine mouse movement +D-Pad - Arrow keys (useful mostly in SCI and AGI games) +D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) +Triangle - Enter (useful for some dialogs) +Cross - Left Mouse Button (usually the main button) +Circle - Right Mouse Button (secondary button in some games) +Square - '.' (skip dialogue in some games e.g. Scumm) +Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) +Start - Global Menu. Allows you to 'Return To Launcher' to play another game +Right trigger + Start - F5 (Main Menu in some games) +Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). + +Virtual Keyboard Mode +===================== +Start - Enter key. Also exits virtual keyboard mode +Select - Exit the virtual keyboard mode +Right trigger - Input letters: lowercase/uppercase (press to toggle) +Left trigger - Input numbers/symbols (press to toggle) +D-Pad - Select square of characters (up, down, left or right) +Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen + by the button in the corresponding position. The 2 top characters are chosen by the + triggers. +Analog - Moves in a direction (left/right/up/down) (Useful to keep moving + while typing in AGI games among other things) + +1st Person Game Mode (Can be ignored by most users) +==================== +This is a special mode built for 1st person games like Lands of Lore. If you don't have these games you can +safely ignore this mode. To enter or leave this mode, use the combo: + +Right Trigger + Left Trigger + Square + +Some buttons have been switched around to make these games more playable: +Square - Is the modifier key instead of Right Trigger. +Left/Right Trigger - Strafe left/right +D-Pad Left/Right - Turn left/right +Square + D-Pad - F1/F2/F3/F4 +Square + Start - Esc (shows game menu) + + Notes ===== - -- Plugin files are NOT interchangeable between versions! You must copy ALL the - plugin files that come with every version of scummvm. They sit in the /plugin +- Notice that you can switch between games! This is much faster than quitting + and having to start ScummVM all over again. Go to the global menu and choose 'Return To Launcher'. + (Some games may not have the Return To Launcher option available yet.) + +- The PSP version of ScummVM uses the Media Engine to accelerate decoding of MP3 files. This means + that if you have the choice of compressing using Ogg files or MP3 files, choose MP3 -- the game + will generally run faster. + +- Plugin files are NOT interchangeable between ScummVM versions! You must copy ALL the + plugin files that come with every version of ScummVM. They sit in the /plugin subdirectory. If you get a crash upon startup, try deleting all the existing plugin files in the plugin directory and copying the new ones over again. -- While it's possible to compress certain game resources to reduce their size, - this can (and usually will) cause games (especially animation) to be choppy - sometimes, as it ofcourse needs extra CPU power to decode these files. - As such, it is recommended to play games in their original, uncompressed, - form whenever possible. - - This README may be outdated, for more up-to-date instructions and notes see the PSP Port Wiki: http://wiki.scummvm.org/index.php/PlayStation_Portable Frequently Asked Questions ========================== -Q: Pressing select doesn't make the virtual keyboard show up on screen! -A: You need to make sure that the kbd.zip file is in the same directory as the scummvm executable. - Q: Scummvm crashes upon starting up! A: See the first note above. +Q: Pressing select doesn't make the virtual keyboard show up on screen! +A: You need to make sure that the kbd.zip file is in the same directory as the ScummVM executable. + Q: What do I need to run the games? -A: A 1.00 or 1.50 firmware PSP (or an EBOOT loader on firmware 2.00 or - higher), and the necessary datafiles for the game you want to play and - obviously this ScummVM port. +A: A PSP that can run homebrew and the necessary datafiles for the game you want to play. Q: Can I run game X with this? A: You can find the list of supported games on the compatibility page - on http://www.scummvm.org. - Note that ScummVM is NOT a 'DOS (game) emulator', but written - specifically for certain games/engines. + at http://www.scummvm.org + Note that ScummVM is NOT an emulator. The supported games engines have been painstakingly rewritten. + It's not easy to add support for a game you want that currently isn't supported. Q: My Monkey Island 1 doesn't have any music, what gives? A: If your version of Monkey Island came on a CD then it has the music - as CD Audio tracks. You need to rip those to MP3/Ogg and copy them - to the same directory as the game datafiles for music to work. + as CD Audio tracks. You need to rip those to MP3/Ogg (MP3 is preferred), naming them track1.mp3 track2.mp3 + etc. and copy them to the same directory as the game datafiles for music to work. Q: Game X crashes, or feature Y doesn't work. Can you fix this? A: Possibly. @@ -83,21 +99,23 @@ A: Possibly. played them all start-to-finish on the PSP, so it's possible there are bugs or issues that we're not aware of. When you encounter such a bug, please use the "Bug Tracker" you find linked - on the ScummVM website, and mention all relevant info (i.e. that you're + on the ScummVM website, and mention all relevant info i.e. that you're using the PSP version, which ScummVM version it is, if the problem exists - in a recent PC SVN version, a detailed description of the problem, - and if at all possible a nearby savegame), this will make it much easier + in a recent PC version, a detailed description of the problem, + and if at all possible a nearby savegame. This will make it much easier for us to reproduce (and hopefully fix) the problem. Building the source code ======================== To build ScummVM for PSP you need: +- ScummVM source code (svn co https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk) + - PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) - PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) - Note: This usually gets installed by the PSP toolchain, - so you don't have to do it manually. + Note: This usually gets installed by the PSP toolchain, + so you don't have to do it manually. - zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) @@ -107,21 +125,15 @@ To build ScummVM for PSP you need: - libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) - - (*) = optional -When you've installed these libraries (read their README.PSP for instructions), -type "make" in the backends/platform/psp directory to build a 1.00 firmware -EBOOT.PBP, or "make kxploit" to build the 1.50/kxploit EBOOT.PBPs - -You can control most of the build process (engines and libraries used) from -the Makefile. - +Once you've installed these libraries (read their README.PSP for instructions), +create a subdirectory in your ScummVM folder called 'builds/psp'. Then, in this folder, type +'../../configure --host=psp --enable-plugins --default-dynamic'. If everything is installed +correctly, ScummVM will inform you as it finds the right components. Finally type 'make' to build. Port Authors ============ - Joost Peters (joostp@scummvm.org) Paolo Costabel (paoloc@pacbell.net) Thomas Mayer (tommybear@internode.on.net) diff --git a/backends/platform/psp/README.PSP.in b/backends/platform/psp/README.PSP.in index 2d53fd3b47..1d48780d3c 100644 --- a/backends/platform/psp/README.PSP.in +++ b/backends/platform/psp/README.PSP.in @@ -3,79 +3,95 @@ ScummVM-PSP @VERSION@ README Installation ============ - - Copy the relevant game datafiles to your memory stick (location - doesn't matter). - - Install ScummVM like any other homebrew - - Run ScummVM and use the launcher to add games and run them - + - Copy the relevant game datafiles to your memory stick (location doesn't matter). + - Install ScummVM like any other homebrew. + - Run ScummVM and use the launcher to add games and run them. Controls ======== - -Left trigger - ESC Right trigger - Modifier key (see below for uses) +Left trigger - ESC (Usually skips cutscenes. Depends on game) Analog - Mouse movement -Right trigger + Analog - Fine control mouse -Directions - Arrow keys -Directions + Right Trigger - Diagonal arrow keys -Triangle - Enter -Cross - Mouse button 1 -Circle - Mouse button 2 -Square - '.' (skip dialogue in some games) -Start - F5 (Main Menu) -Right trigger + Start - Return-To-Launcher menu - -Virtual Keyboard -================ - -Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen. -Start - Enter -Right trigger - Switch to/between letter modes -Left trigger - Switch to/between numbers and symbols -D-Pad - Select square of characters -Buttons/Triggers - Choose a specific character - +Right trigger + Analog - Fine mouse movement +D-Pad - Arrow keys (useful mostly in SCI and AGI games) +D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) +Triangle - Enter (useful for some dialogs) +Cross - Left Mouse Button (usually the main button) +Circle - Right Mouse Button (secondary button in some games) +Square - '.' (skip dialogue in some games e.g. Scumm) +Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) +Start - Global Menu. Allows you to 'Return To Launcher' to play another game +Right trigger + Start - F5 (Main Menu in some games) +Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). + +Virtual Keyboard Mode +===================== +Start - Enter key. Also exits virtual keyboard mode +Select - Exit the virtual keyboard mode +Right trigger - Input letters: lowercase/uppercase (press to toggle) +Left trigger - Input numbers/symbols (press to toggle) +D-Pad - Select square of characters (up, down, left or right) +Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen + by the button in the corresponding position. The 2 top characters are chosen by the + triggers. +Analog - Moves in a direction (left/right/up/down) (Useful to keep moving + while typing in AGI games among other things) + +1st Person Game Mode (Can be ignored by most users) +==================== +This is a special mode built for 1st person games like Lands of Lore. If you don't have these games you can +safely ignore this mode. To enter or leave this mode, use the combo: + +Right Trigger + Left Trigger + Square + +Some buttons have been switched around to make these games more playable: +Square - Is the modifier key instead of Right Trigger. +Left/Right Trigger - Strafe left/right +D-Pad Left/Right - Turn left/right +Square + D-Pad - F1/F2/F3/F4 +Square + Start - Esc (shows game menu) + + Notes ===== - -- Plugin files are NOT interchangeable between versions! You must copy ALL the - plugin files that come with every version of scummvm. They sit in the /plugin +- Notice that you can switch between games! This is much faster than quitting + and having to start ScummVM all over again. Go to the global menu and choose 'Return To Launcher'. + (Some games may not have the Return To Launcher option available yet.) + +- The PSP version of ScummVM uses the Media Engine to accelerate decoding of MP3 files. This means + that if you have the choice of compressing using Ogg files or MP3 files, choose MP3 -- the game + will generally run faster. + +- Plugin files are NOT interchangeable between ScummVM versions! You must copy ALL the + plugin files that come with every version of ScummVM. They sit in the /plugin subdirectory. If you get a crash upon startup, try deleting all the existing plugin files in the plugin directory and copying the new ones over again. -- While it's possible to compress certain game resources to reduce their size, - this can (and usually will) cause games (especially animation) to be choppy - sometimes, as it ofcourse needs extra CPU power to decode these files. - As such, it is recommended to play games in their original, uncompressed, - form whenever possible. - - This README may be outdated, for more up-to-date instructions and notes see the PSP Port Wiki: http://wiki.scummvm.org/index.php/PlayStation_Portable Frequently Asked Questions ========================== -Q: Pressing select doesn't make the virtual keyboard show up on screen! -A: You need to make sure that the kbd.zip file is in the same directory as the scummvm executable. - Q: Scummvm crashes upon starting up! A: See the first note above. +Q: Pressing select doesn't make the virtual keyboard show up on screen! +A: You need to make sure that the kbd.zip file is in the same directory as the ScummVM executable. + Q: What do I need to run the games? -A: A 1.00 or 1.50 firmware PSP (or an EBOOT loader on firmware 2.00 or - higher), and the necessary datafiles for the game you want to play and - obviously this ScummVM port. +A: A PSP that can run homebrew and the necessary datafiles for the game you want to play. Q: Can I run game X with this? A: You can find the list of supported games on the compatibility page - on http://www.scummvm.org. - Note that ScummVM is NOT a 'DOS (game) emulator', but written - specifically for certain games/engines. + at http://www.scummvm.org + Note that ScummVM is NOT an emulator. The supported games engines have been painstakingly rewritten. + It's not easy to add support for a game you want that currently isn't supported. Q: My Monkey Island 1 doesn't have any music, what gives? A: If your version of Monkey Island came on a CD then it has the music - as CD Audio tracks. You need to rip those to MP3/Ogg and copy them - to the same directory as the game datafiles for music to work. + as CD Audio tracks. You need to rip those to MP3/Ogg (MP3 is preferred), naming them track1.mp3 track2.mp3 + etc. and copy them to the same directory as the game datafiles for music to work. Q: Game X crashes, or feature Y doesn't work. Can you fix this? A: Possibly. @@ -83,21 +99,23 @@ A: Possibly. played them all start-to-finish on the PSP, so it's possible there are bugs or issues that we're not aware of. When you encounter such a bug, please use the "Bug Tracker" you find linked - on the ScummVM website, and mention all relevant info (i.e. that you're + on the ScummVM website, and mention all relevant info i.e. that you're using the PSP version, which ScummVM version it is, if the problem exists - in a recent PC SVN version, a detailed description of the problem, - and if at all possible a nearby savegame), this will make it much easier + in a recent PC version, a detailed description of the problem, + and if at all possible a nearby savegame. This will make it much easier for us to reproduce (and hopefully fix) the problem. Building the source code ======================== To build ScummVM for PSP you need: +- ScummVM source code (svn co https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk) + - PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) - PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) - Note: This usually gets installed by the PSP toolchain, - so you don't have to do it manually. + Note: This usually gets installed by the PSP toolchain, + so you don't have to do it manually. - zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) @@ -107,21 +125,15 @@ To build ScummVM for PSP you need: - libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) - - (*) = optional -When you've installed these libraries (read their README.PSP for instructions), -type "make" in the backends/platform/psp directory to build a 1.00 firmware -EBOOT.PBP, or "make kxploit" to build the 1.50/kxploit EBOOT.PBPs - -You can control most of the build process (engines and libraries used) from -the Makefile. - +Once you've installed these libraries (read their README.PSP for instructions), +create a subdirectory in your ScummVM folder called 'builds/psp'. Then, in this folder, type +'../../configure --host=psp --enable-plugins --default-dynamic'. If everything is installed +correctly, ScummVM will inform you as it finds the right components. Finally type 'make' to build. Port Authors ============ - Joost Peters (joostp@scummvm.org) Paolo Costabel (paoloc@pacbell.net) Thomas Mayer (tommybear@internode.on.net) diff --git a/backends/platform/psp/cursor.h b/backends/platform/psp/cursor.h index c3d4d76803..2ff0415c6c 100644 --- a/backends/platform/psp/cursor.h +++ b/backends/platform/psp/cursor.h @@ -26,6 +26,8 @@ #ifndef MOUSE_H #define MOUSE_H +#include "backends/platform/psp/default_display_client.h" + class Cursor : public DefaultDisplayClient { private: int _hotspotX, _hotspotY; diff --git a/backends/platform/psp/display_client.h b/backends/platform/psp/display_client.h index d05b0b046c..feec477282 100644 --- a/backends/platform/psp/display_client.h +++ b/backends/platform/psp/display_client.h @@ -30,6 +30,7 @@ #include "graphics/surface.h" #include "common/system.h" #include "backends/platform/psp/memory.h" +#include "backends/platform/psp/psppixelformat.h" #define MAX_TEXTURE_SIZE 512 diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp index 4fe7cb3f92..3ea2d4365d 100644 --- a/backends/platform/psp/input.cpp +++ b/backends/platform/psp/input.cpp @@ -23,238 +23,272 @@ * */ -// Todo: handle events that should fire because of shift going off -// Solution: handle shift on a button-by-button basis, only allowing it when the button is up. Also a inputmap-wide button. At buttonup, shiftstate is inspected per button. +#include <pspctrl.h> +#include "gui/message.h" +#include "backends/platform/psp/input.h" //#define __PSP_DEBUG_FUNCS__ /* Uncomment for debugging the stack */ //#define __PSP_DEBUG_PRINT__ /* Uncomment for debug prints */ - #include "backends/platform/psp/trace.h" -#include "backends/platform/psp/psppixelformat.h" -#include "backends/platform/psp/input.h" - // Defines for working with PSP buttons -#define CHANGED(x) (_buttonsChanged & (x)) -#define PRESSED(x) ((_buttonsChanged & (x)) && (pad.Buttons & (x))) -#define UNPRESSED(x) ((_buttonsChanged & (x)) && !(pad.Buttons & (x))) -#define DOWN(x) (pad.Buttons & (x)) +#define DOWN(x) ((pad.Buttons & (x)) == (x)) #define UP(x) (!(pad.Buttons & (x))) #define PSP_DPAD (PSP_CTRL_DOWN|PSP_CTRL_UP|PSP_CTRL_LEFT|PSP_CTRL_RIGHT) #define PSP_4BUTTONS (PSP_CTRL_CROSS | PSP_CTRL_CIRCLE | PSP_CTRL_TRIANGLE | PSP_CTRL_SQUARE) #define PSP_TRIGGERS (PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER) +#define PSP_ALL_BUTTONS (PSP_DPAD | PSP_4BUTTONS | PSP_TRIGGERS | PSP_CTRL_START | PSP_CTRL_SELECT) #define PAD_CHECK_TIME 53 -void InputHandler::init() { - sceCtrlSetSamplingCycle(0); // set sampling to vsync. n = n usecs - sceCtrlSetSamplingMode(1); // analog +Button::Button() { + clear(); } -bool InputHandler::getAllInputs(Common::Event &event) { - DEBUG_ENTER_FUNC(); - - uint32 time = g_system->getMillis(); // may not be necessary with read - if (time - _lastPadCheckTime < PAD_CHECK_TIME) { - return false; - } - - _lastPadCheckTime = time; - SceCtrlData pad; - - sceCtrlPeekBufferPositive(&pad, 1); // Peek ignores sleep. Read sleeps thread - - bool haveEvent; - - memset(&event, 0, sizeof(event)); - - if (_keyboard->isVisible()) - haveEvent = _keyboard->processInput(event, pad); - else - haveEvent = getEvent(event, pad); +inline void Button::clear() { + _key = Common::KEYCODE_INVALID; + _ascii = 0; + _flag = 0; + _pspEventDown.clear(); + _pspEventUp.clear(); +} - if (haveEvent) { - PSP_DEBUG_PRINT("Have event[%s]\n", haveEvent ? "true" : "false"); - PSP_DEBUG_PRINT("event.type[%d]\n", event.type); +inline bool Button::getEvent(Common::Event &event, PspEvent &pspEvent, bool down) { + if (down) { + if (!_pspEventDown.isEmpty()) + pspEvent = _pspEventDown; + } else { // up + if (!_pspEventUp.isEmpty()) + pspEvent = _pspEventUp; + } + if (_key != Common::KEYCODE_INVALID) { + event.type = down ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; + event.kbd.keycode = _key; + event.kbd.ascii = _ascii; + event.kbd.flags |= _flag; + return true; + } else if (_flag) { // handle flag only events + event.type = down ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; + event.kbd.flags |= down ? _flag : 0; + return true; } - - return haveEvent; + return false; } -bool InputHandler::getEvent(Common::Event &event, SceCtrlData &pad) { - DEBUG_ENTER_FUNC(); - - _buttonsChanged = pad.Buttons ^ _prevButtons; - bool haveEvent = false; - - // Collect events from different sources - haveEvent = getDpadEvent(event, pad); - - if (!haveEvent) - haveEvent = getButtonEvent(event, pad); - - if (!haveEvent) - haveEvent = getNubEvent(event, pad); - - _prevButtons = pad.Buttons; - - return haveEvent; +void Button::setPspEvent(PspEventType typeDown, uint32 dataDown, PspEventType typeUp, uint32 dataUp) { + _pspEventDown.type = typeDown; + _pspEventDown.data = dataDown; + _pspEventUp.type = typeUp; + _pspEventUp.data = dataUp; +} + +// Translates bitfields to our constants +// We put combined bitfields first to make sure we pick up diagonals +const uint32 ButtonPad::_buttonMap[] = { + PSP_CTRL_UP | PSP_CTRL_LEFT, + PSP_CTRL_UP | PSP_CTRL_RIGHT, + PSP_CTRL_DOWN | PSP_CTRL_RIGHT, + PSP_CTRL_DOWN | PSP_CTRL_LEFT, + PSP_CTRL_RIGHT, PSP_CTRL_DOWN, PSP_CTRL_LEFT, PSP_CTRL_UP, + PSP_CTRL_CROSS, PSP_CTRL_CIRCLE, PSP_CTRL_TRIANGLE, PSP_CTRL_SQUARE, + PSP_CTRL_LTRIGGER, PSP_CTRL_RTRIGGER, PSP_CTRL_START, PSP_CTRL_SELECT +}; + +ButtonPad::ButtonPad() : _prevButtonState(0), _shifted(UNSHIFTED), _padMode(PAD_MODE_NORMAL), + _comboMode(false) { + for (int i = UNSHIFTED; i < SHIFTED_MODE_LAST; i++) + _buttonsChanged[i] = 0; + clearButtons(); } -bool InputHandler::getDpadEvent(Common::Event &event, SceCtrlData &pad) { - DEBUG_ENTER_FUNC(); - - int newDpadX = 0, newDpadY = 0; - bool haveEvent = false; - - if (DOWN(PSP_CTRL_UP)) { - newDpadY++; - if (DOWN(PSP_CTRL_RTRIGGER)) // Shifting causes diagonals - newDpadX++; - } - if (DOWN(PSP_CTRL_RIGHT)) { - newDpadX++; - if (DOWN(PSP_CTRL_RTRIGGER)) - newDpadY--; +void ButtonPad::clearButtons() { + for (int i = BTN_UP_LEFT; i < BTN_LAST; i++) { + _button[i][UNSHIFTED].clear(); + _button[i][SHIFTED].clear(); } - if (DOWN(PSP_CTRL_DOWN)) { - newDpadY--; - if (DOWN(PSP_CTRL_RTRIGGER)) - newDpadX--; - } - if (DOWN(PSP_CTRL_LEFT)) { - newDpadX--; - if (DOWN(PSP_CTRL_RTRIGGER)) - newDpadY++; - } - - if (newDpadX != _dpadX || newDpadY != _dpadY) { - if (_dpadX == 0 && _dpadY == 0) { // We were in the middle so we pressed dpad - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = translateDpad(newDpadX, newDpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; // Get ascii - _dpadX = newDpadX; - _dpadY = newDpadY; - } else if (newDpadX == 0 && newDpadY == 0) {// We're now centered so we unpressed dpad - event.type = Common::EVENT_KEYUP; - event.kbd.keycode = translateDpad(_dpadX, _dpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; - _dpadX = newDpadX; - _dpadY = newDpadY; - } else { // we moved from one pressed dpad direction to another one - event.type = Common::EVENT_KEYUP; // first release the last dpad direction - event.kbd.keycode = translateDpad(_dpadX, _dpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; - _dpadX = 0; // so that we'll pick up a new dpad movement the next round - _dpadY = 0; - } +} - PSP_DEBUG_PRINT("Keypad event. DpadX[%d], DpadY[%d]\n", _dpadX, _dpadY); - haveEvent = true; +void ButtonPad::initButtons() { + switch (_padMode) { + case PAD_MODE_NORMAL: + initButtonsNormalMode(); + break; + case PAD_MODE_LOL: + initButtonsLolMode(); + break; + default: + break; } - - return haveEvent; } -inline Common::KeyCode InputHandler::translateDpad(int x, int y) { +void ButtonPad::initButtonsNormalMode() { DEBUG_ENTER_FUNC(); - Common::KeyCode key; - - if (x == -1) { - if (y == -1) - key = Common::KEYCODE_KP1; - else if (y == 0) - key = Common::KEYCODE_KP4; - else /* y == 1 */ - key = Common::KEYCODE_KP7; - } else if (x == 0) { - if (y == -1) - key = Common::KEYCODE_KP2; - else /* y == 1 */ - key = Common::KEYCODE_KP8; - } else {/* x == 1 */ - if (y == -1) - key = Common::KEYCODE_KP3; - else if (y == 0) - key = Common::KEYCODE_KP6; - else /* y == 1 */ - key = Common::KEYCODE_KP9; - } - - return key; + PSP_DEBUG_PRINT("initializing buttons for normal mode\n"); + clearButtons(); + + // Dpad + _button[BTN_UP_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP7, '7'); + _button[BTN_LEFT][SHIFTED].setKey(Common::KEYCODE_KP7, '7'); // same as up_left + _button[BTN_UP][UNSHIFTED].setKey(Common::KEYCODE_KP8, '8'); + _button[BTN_UP_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP9, '9'); + _button[BTN_UP][SHIFTED].setKey(Common::KEYCODE_KP9, '9'); // same as up_right + _button[BTN_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP4, '4'); + _button[BTN_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP6, '6'); + _button[BTN_DOWN_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP1, '1'); + _button[BTN_DOWN][SHIFTED].setKey(Common::KEYCODE_KP1, '1'); // same as down_left + _button[BTN_DOWN][UNSHIFTED].setKey(Common::KEYCODE_KP2, '2'); + _button[BTN_DOWN_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP3, '3'); + _button[BTN_RIGHT][SHIFTED].setKey(Common::KEYCODE_KP3, '3'); // same as down_right + + // Other buttons + _button[BTN_CROSS][UNSHIFTED].setPspEvent(PSP_EVENT_LBUTTON, true, PSP_EVENT_LBUTTON, false); + _button[BTN_CIRCLE][UNSHIFTED].setPspEvent(PSP_EVENT_RBUTTON, true, PSP_EVENT_RBUTTON, false); + _button[BTN_TRIANGLE][UNSHIFTED].setKey(Common::KEYCODE_RETURN, '\r'); + _button[BTN_SQUARE][UNSHIFTED].setKey(Common::KEYCODE_PERIOD, '.'); + _button[BTN_SQUARE][SHIFTED].setKey(Common::KEYCODE_SPACE, ' '); + _button[BTN_LTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_ESCAPE, 27); + _button[BTN_RTRIGGER][SHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + _button[BTN_RTRIGGER][UNSHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + _button[BTN_RTRIGGER][SHIFTED].setKey(Common::KEYCODE_INVALID, 0, Common::KBD_SHIFT); + _button[BTN_RTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_INVALID, 0, Common::KBD_SHIFT); + _button[BTN_START][SHIFTED].setKey(Common::KEYCODE_F5, Common::ASCII_F5); + _button[BTN_START][UNSHIFTED].setKey(Common::KEYCODE_F5, Common::ASCII_F5, Common::KBD_CTRL); + _button[BTN_SELECT][UNSHIFTED].setPspEvent(PSP_EVENT_SHOW_VIRTUAL_KB, true, PSP_EVENT_NONE, 0); +} + +void ButtonPad::initButtonsLolMode() { + DEBUG_ENTER_FUNC(); + initButtonsNormalMode(); // set normal button configuration + PSP_DEBUG_PRINT("initializing buttons for LOL mode\n"); + + // Square is our new shift button + _button[BTN_SQUARE][UNSHIFTED].clear(); + _button[BTN_SQUARE][UNSHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + _button[BTN_SQUARE][SHIFTED].clear(); + _button[BTN_SQUARE][SHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + + // Dpad + _button[BTN_LEFT][UNSHIFTED].clear(); + _button[BTN_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP7, '7'); + _button[BTN_LEFT][SHIFTED].clear(); + _button[BTN_LEFT][SHIFTED].setKey(Common::KEYCODE_F1, Common::ASCII_F1); + _button[BTN_UP][SHIFTED].clear(); + _button[BTN_UP][SHIFTED].setKey(Common::KEYCODE_F2, Common::ASCII_F2); + _button[BTN_RIGHT][UNSHIFTED].clear(); + _button[BTN_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP9, '9'); + _button[BTN_RIGHT][SHIFTED].clear(); + _button[BTN_RIGHT][SHIFTED].setKey(Common::KEYCODE_F3, Common::ASCII_F3); + _button[BTN_DOWN][SHIFTED].clear(); + _button[BTN_DOWN][SHIFTED].setKey(Common::KEYCODE_F4, Common::ASCII_F4); + + // Buttons + _button[BTN_LTRIGGER][UNSHIFTED].clear(); + _button[BTN_LTRIGGER][SHIFTED].clear(); + _button[BTN_LTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_KP4, '4'); // Triggers turn + _button[BTN_RTRIGGER][UNSHIFTED].clear(); + _button[BTN_RTRIGGER][SHIFTED].clear(); + _button[BTN_RTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_KP6, '6'); + _button[BTN_START][SHIFTED].clear(); + _button[BTN_START][SHIFTED].setKey(Common::KEYCODE_ESCAPE, 27); } - -bool InputHandler::getButtonEvent(Common::Event &event, SceCtrlData &pad) { +bool ButtonPad::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { DEBUG_ENTER_FUNC(); - bool haveEvent = false; + + //PSP_DEBUG_PRINT("buttons[%x]\n", pad.Buttons); + + uint32 curButtonState = PSP_ALL_BUTTONS & pad.Buttons; // we only care about these + + modifyButtonsForCombos(pad); // change buttons for combos + + return getEventFromButtonState(event, pspEvent, curButtonState); +} - if (PRESSED(PSP_CTRL_SELECT)) - _keyboard->setVisible(true); - - else if (CHANGED(PSP_4BUTTONS | PSP_TRIGGERS | PSP_CTRL_START)) { - if (CHANGED(PSP_CTRL_CROSS)) { - event.type = DOWN(PSP_CTRL_CROSS) ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP; - event.mouse.x = _cursor->getX(); // Could this have to do with SCI enter problem? - event.mouse.y = _cursor->getY(); - PSP_DEBUG_PRINT("%s\n", event.type == Common::EVENT_LBUTTONDOWN ? "LButtonDown" : "LButtonUp"); - } else if (CHANGED(PSP_CTRL_CIRCLE)) { - event.type = DOWN(PSP_CTRL_CIRCLE) ? Common::EVENT_RBUTTONDOWN : Common::EVENT_RBUTTONUP; - event.mouse.x = _cursor->getX(); - event.mouse.y = _cursor->getY(); - PSP_DEBUG_PRINT("%s\n", event.type == Common::EVENT_LBUTTONDOWN ? "RButtonDown" : "RButtonUp"); - } else { - //any of the other buttons. - event.type = _buttonsChanged & pad.Buttons ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; - event.kbd.ascii = 0; - event.kbd.flags = 0; - - if (CHANGED(PSP_CTRL_LTRIGGER)) { - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = 27; - } else if (CHANGED(PSP_CTRL_START)) { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = Common::ASCII_F5; - if (DOWN(PSP_CTRL_RTRIGGER)) { - event.kbd.flags |= Common::KBD_CTRL; // Main menu to allow RTL +bool ButtonPad::getEventFromButtonState(Common::Event &event, PspEvent &pspEvent, uint32 buttonState) { + DEBUG_ENTER_FUNC(); + _buttonsChanged[_shifted] |= buttonState ^ _prevButtonState; // add any buttons that changed + _prevButtonState = buttonState; + + for (int shiftState = UNSHIFTED; shiftState < SHIFTED_MODE_LAST; shiftState++) { + if (_buttonsChanged[shiftState]) { // any button to address? + PSP_DEBUG_PRINT("found changed buttons\n"); + ButtonType buttonType = BTN_LAST; + bool buttonDown = false; // normally we release a button (as in when we're in a different shiftmode) + + for (int i = BTN_UP_LEFT; i < BTN_LAST; i++) { + uint32 buttonCode = _buttonMap[i]; + if ((_buttonsChanged[shiftState] & buttonCode) == buttonCode) { // check for this changed button + buttonType = (ButtonType)i; // we know which button changed + _buttonsChanged[shiftState] &= ~buttonCode; // save the fact that we treated this button + if (shiftState == _shifted) + buttonDown = buttonState & buttonCode ? true : false; // pressed or released? + + PSP_DEBUG_PRINT("button[%i] pressed\n", i); + break; } - } else if (CHANGED(PSP_CTRL_SQUARE)) { - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = '.'; - } else if (CHANGED(PSP_CTRL_TRIANGLE)) { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = '\r'; - } else if (DOWN(PSP_CTRL_RTRIGGER)) { // An event - event.kbd.flags |= Common::KBD_SHIFT; } - PSP_DEBUG_PRINT("Ascii[%d]. Key %s.\n", event.kbd.ascii, event.type == Common::EVENT_KEYDOWN ? "down" : "up"); + + assert (buttonType < BTN_LAST); + bool haveEvent = _button[buttonType][shiftState].getEvent(event, pspEvent, buttonDown); + if (haveEvent) + PSP_DEBUG_PRINT("have event. key[%d] flag[%x] %s\n", event.kbd.ascii, event.kbd.flags, buttonDown ? "down" : "up"); + return haveEvent; } - - haveEvent = true; - } - - return haveEvent; + } + + return false; } - -bool InputHandler::getNubEvent(Common::Event &event, SceCtrlData &pad) { + +void ButtonPad::modifyButtonsForCombos(SceCtrlData &pad) { + if (DOWN(PSP_CTRL_RTRIGGER | PSP_CTRL_LTRIGGER)) { + if (!_comboMode) { // we're entering combo mode + PSP_DEBUG_PRINT("entering combo mode\n"); + _button[BTN_SQUARE][UNSHIFTED].clear(); + _button[BTN_SQUARE][SHIFTED].clear(); + _button[BTN_DOWN][SHIFTED].clear(); + _button[BTN_DOWN][UNSHIFTED].clear(); + _button[BTN_UP][SHIFTED].clear(); + _button[BTN_UP][UNSHIFTED].clear(); + _button[BTN_SQUARE][UNSHIFTED].setPspEvent(PSP_EVENT_MODE_SWITCH, true, PSP_EVENT_NONE, true); + _button[BTN_SQUARE][SHIFTED].setPspEvent(PSP_EVENT_MODE_SWITCH, true, PSP_EVENT_NONE, true); + _button[BTN_DOWN][UNSHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, false, PSP_EVENT_NONE, true); + _button[BTN_DOWN][SHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, false, PSP_EVENT_NONE, true); + _button[BTN_UP][UNSHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, true, PSP_EVENT_NONE, true); + _button[BTN_UP][SHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, true, PSP_EVENT_NONE, true); + _comboMode = true; + } + } else { // no combo buttons are pressed now + if (_comboMode) { // we have been running in combo mode + initButtons(); // reset the button configuration + _comboMode = false; + } + } +} + +bool Nub::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { DEBUG_ENTER_FUNC(); - - bool haveEvent = false; + + if (_dpadMode) { // Convert the nub to a D-Pad + uint32 buttonState; + translateToDpadState(pad.Lx, pad.Ly, buttonState); + return _buttonPad.getEventFromButtonState(event, pspEvent, buttonState); + } + int32 analogStepX = pad.Lx; // Goes up to 255. int32 analogStepY = pad.Ly; - int32 oldX = _cursor->getX(); - int32 oldY = _cursor->getY(); - analogStepX = modifyNubAxisMotion(analogStepX); analogStepY = modifyNubAxisMotion(analogStepY); + + int32 oldX = _cursor->getX(); + int32 oldY = _cursor->getY(); if (analogStepX != 0 || analogStepY != 0) { PSP_DEBUG_PRINT("raw x[%d], y[%d]\n", analogStepX, analogStepY); // If no movement then this has no effect - if (DOWN(PSP_CTRL_RTRIGGER)) { + if (_shifted) { // Fine control mode for analog if (analogStepX != 0) { if (analogStepX > 0) @@ -281,15 +315,29 @@ bool InputHandler::getNubEvent(Common::Event &event, SceCtrlData &pad) { event.type = Common::EVENT_MOUSEMOVE; event.mouse.x = newX; event.mouse.y = newY; - haveEvent = true; - PSP_DEBUG_PRINT("Nub event. X[%d], Y[%d]\n", newX, newY); + return true; } } - return haveEvent; + return false; +} + +void Nub::translateToDpadState(int dpadX, int dpadY, uint32 &buttonState) { + #define MIN_NUB_POSITION 70 + buttonState = 0; + + if (dpadX > 127 + MIN_NUB_POSITION) + buttonState |= PSP_CTRL_RIGHT; + else if (dpadX < 127 - MIN_NUB_POSITION) + buttonState |= PSP_CTRL_LEFT; + + if (dpadY > 127 + MIN_NUB_POSITION) + buttonState |= PSP_CTRL_DOWN; + else if (dpadY < 127 - MIN_NUB_POSITION) + buttonState |= PSP_CTRL_UP; } -inline int32 InputHandler::modifyNubAxisMotion(int32 input) { +inline int32 Nub::modifyNubAxisMotion(int32 input) { DEBUG_ENTER_FUNC(); const int MIN_NUB_MOTION = 30; @@ -304,3 +352,160 @@ inline int32 InputHandler::modifyNubAxisMotion(int32 input) { return input; } + +inline bool Nub::isButtonDown() { + if (_dpadMode) // only relevant in dpad mode + return _buttonPad.isButtonDown(); + return false; +} + +const char *InputHandler::_padModeText[] = { + "Normal Button Mode", + "1st Person RPG Button Mode" +}; + +void InputHandler::init() { + sceCtrlSetSamplingCycle(0); // set sampling to vsync. n = n usecs + sceCtrlSetSamplingMode(1); // analog + + _buttonPad.initButtons(); +} + +bool InputHandler::getAllInputs(Common::Event &event) { + DEBUG_ENTER_FUNC(); + + uint32 time = g_system->getMillis(); // may not be necessary with read + if (time - _lastPadCheckTime < PAD_CHECK_TIME) { + return false; + } + + _lastPadCheckTime = time; + SceCtrlData pad; + + sceCtrlPeekBufferPositive(&pad, 1); // Peek doesn't sleep. Read sleeps the thread + + bool haveEvent; + //memset(&event, 0, sizeof(event)); + + haveEvent = getEvent(event, pad); + + if (haveEvent) { + PSP_DEBUG_PRINT("Have event[%s]. Type[%d]\n", haveEvent ? "true" : "false", event.type); + } + + return haveEvent; +} + +bool InputHandler::getEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + PspEvent pspEvent; + bool haveEvent = false; + + if (_keyboard->isVisible()) { + haveEvent = _keyboard->processInput(event, pspEvent, pad); + } else { // only process buttonpad if keyboard invisible + haveEvent = _buttonPad.getEvent(event, pspEvent, pad); + } + + if (!haveEvent && pspEvent.isEmpty()) + haveEvent = _nub.getEvent(event, pspEvent, pad); + + // handle any pending PSP events + if (!haveEvent && pspEvent.isEmpty()) { + if (!_pendingPspEvent.isEmpty()) { + pspEvent = _pendingPspEvent; + _pendingPspEvent.clear(); + } + } + + // handle any PSP events we might have + if (!pspEvent.isEmpty()) + haveEvent |= handlePspEvent(event, pspEvent); // overrides any event we might have + + return haveEvent; +} + +bool InputHandler::handlePspEvent(Common::Event &event, PspEvent &pspEvent) { + bool haveEvent = false; + + PSP_DEBUG_PRINT("have pspEvent[%d] data[%d]\n", pspEvent.type, pspEvent.data); + + switch (pspEvent.type) { + case PSP_EVENT_SHIFT: + handleShiftEvent((ShiftMode)pspEvent.data); + break; + case PSP_EVENT_SHOW_VIRTUAL_KB: + _keyboard->setVisible((bool)pspEvent.data); + if ((pspEvent.data && _keyboard->isVisible()) || !pspEvent.data) // don't change mode if keyboard didn't load + _nub.setDpadMode((bool)pspEvent.data); // set nub to keypad/regular mode + break; + case PSP_EVENT_LBUTTON: + haveEvent = true; + if (pspEvent.data) // down + handleMouseEvent(event, Common::EVENT_LBUTTONDOWN, "LButtonDown"); + else + handleMouseEvent(event, Common::EVENT_LBUTTONUP, "LButtonUp"); + break; + case PSP_EVENT_RBUTTON: + haveEvent = true; + if (pspEvent.data) // down + handleMouseEvent(event, Common::EVENT_RBUTTONDOWN, "RButtonDown"); + else + handleMouseEvent(event, Common::EVENT_RBUTTONUP, "RButtonUp"); + break; + case PSP_EVENT_MODE_SWITCH: + handleModeSwitchEvent(); + break; + /*case PSP_EVENT_CHANGE_SPEED: + handleSpeedChange(pspEvent.data); + break;*/ + default: + PSP_ERROR("Unhandled PSP Event[%d]\n", pspEvent.type); + break; + } + + return haveEvent; +} + +void InputHandler::handleMouseEvent(Common::Event &event, Common::EventType type, const char *string) { + event.type = type; + event.mouse.x = _cursor->getX(); + event.mouse.y = _cursor->getY(); + PSP_DEBUG_PRINT("%s event, x[%d], y[%d]\n", string, event.mouse.x, event.mouse.y); +} + +void InputHandler::handleShiftEvent(ShiftMode shifted) { + _buttonPad.setShifted(shifted); + _nub.setShifted(shifted); +} + +void InputHandler::handleModeSwitchEvent() { + // check if we can't switch modes right now + if (_buttonPad.isButtonDown() || _nub.isButtonDown()) { // can't switch yet + PSP_DEBUG_PRINT("postponing mode switch event\n"); + _pendingPspEvent.type = PSP_EVENT_MODE_SWITCH; // queue it to be done later + } else { // we can switch + PSP_DEBUG_PRINT("mode switch event\n"); + _padMode = (PspPadMode)(_padMode + 1); + if (_padMode >= PAD_MODE_LAST) + _padMode = PAD_MODE_NORMAL; + + GUI::TimedMessageDialog dialog(_padModeText[_padMode], 1500); + dialog.runModal(); + + _buttonPad.setPadMode(_padMode); + _buttonPad.initButtons(); + } +} + +/* +void InputHandler::handleSpeedChange(bool up) { + char *dialogMsg; + + if (up) { + dialogMsg = " + + GUI::TimedMessageDialog dialog(_padModeText[_padMode], 1500); + dialog.runModal(); +}*/ diff --git a/backends/platform/psp/input.h b/backends/platform/psp/input.h index cd686d9e02..6991c50533 100644 --- a/backends/platform/psp/input.h +++ b/backends/platform/psp/input.h @@ -28,36 +28,154 @@ #include "common/scummsys.h" #include "common/events.h" -#include "backends/platform/psp/display_client.h" -#include "backends/platform/psp/default_display_client.h" #include "backends/platform/psp/pspkeyboard.h" #include "backends/platform/psp/cursor.h" #include <pspctrl.h> -class InputHandler { +enum PspEventType { + PSP_EVENT_NONE = 0, + PSP_EVENT_SHIFT, + PSP_EVENT_SHOW_VIRTUAL_KB, + PSP_EVENT_LBUTTON, + PSP_EVENT_RBUTTON, + PSP_EVENT_MODE_SWITCH, + PSP_EVENT_CHANGE_SPEED, + PSP_EVENT_LAST +}; + + +struct PspEvent { + PspEventType type; + uint32 data; + PspEvent() { clear(); } + void clear() { + type = PSP_EVENT_NONE; + data = 0; + } + bool isEmpty() { return type == PSP_EVENT_NONE; } +}; + +enum PspPadMode { + PAD_MODE_NORMAL, + PAD_MODE_LOL, + PAD_MODE_LAST +}; + +enum ShiftMode { + UNSHIFTED = 0, + SHIFTED = 1, + SHIFTED_MODE_LAST +}; + + +class Button { +private: + Common::KeyCode _key; + uint32 _ascii; + uint32 _flag; + PspEvent _pspEventDown; // event when we press + PspEvent _pspEventUp; // event when we release +public: + Button(); + void clear(); + bool getEvent(Common::Event &event, PspEvent &pspEvent, bool buttonDown); + void setKey(Common::KeyCode key, uint32 ascii = 0, uint32 flag = 0) { _key = key; _ascii = ascii; _flag = flag; } + void setPspEvent(PspEventType typeDown, uint32 dataDown, PspEventType typeUp, uint32 dataUp); +}; + +class ButtonPad { public: - InputHandler() : _cursor(0), _keyboard(0), _prevButtons(0), _lastPadCheckTime(0), _buttonsChanged(0), _dpadX(0), _dpadY(0) {} + enum ButtonType { // must match the buttonMap + BTN_UP_LEFT, + BTN_UP_RIGHT, + BTN_DOWN_RIGHT, + BTN_DOWN_LEFT, + BTN_RIGHT, + BTN_DOWN, + BTN_LEFT, + BTN_UP, + BTN_CROSS, + BTN_CIRCLE, + BTN_TRIANGLE, + BTN_SQUARE, + BTN_LTRIGGER, + BTN_RTRIGGER, + BTN_START, + BTN_SELECT, + BTN_LAST + }; - void init(); - bool getAllInputs(Common::Event &event); - void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } - void setCursor(Cursor *cursor) { _cursor = cursor; } +private: + Button _button[BTN_LAST][SHIFTED_MODE_LAST]; + uint32 _buttonsChanged[SHIFTED_MODE_LAST]; // normal and shifted + uint32 _prevButtonState; + ShiftMode _shifted; + PspPadMode _padMode; + bool _comboMode; // are we in the middle of combos + static const uint32 _buttonMap[]; // maps the buttons to their values + void initButtonsNormalMode(); + void initButtonsLolMode(); + void modifyButtonsForCombos(SceCtrlData &pad); + void clearButtons(); + +public: + ButtonPad(); + bool getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); + bool getEventFromButtonState(Common::Event &event, PspEvent &pspEvent, uint32 buttonState); + void setShifted(ShiftMode shifted) { _shifted = shifted; } + void setPadMode(PspPadMode mode) { _padMode = mode; } + bool isButtonDown() { return _prevButtonState; } + void initButtons(); +}; + +class Nub { +private: + Cursor *_cursor; // to enable changing/getting cursor position + + ButtonPad _buttonPad; // private buttonpad for dpad mode + ShiftMode _shifted; + bool _dpadMode; + +public: + Nub() : _shifted(UNSHIFTED), _dpadMode(false) { _buttonPad.initButtons(); } + + void setCursor(Cursor *cursor) { _cursor = cursor; } + void setDpadMode(bool active) { _dpadMode = active; } + void setShifted(ShiftMode shifted) { _shifted = shifted; } + bool isButtonDown(); + + bool getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); + int32 modifyNubAxisMotion(int32 input); + void translateToDpadState(int dpadX, int dpadY, uint32 &buttonState); // convert nub data to dpad data +}; + +class InputHandler { +public: + InputHandler() : _keyboard(0), _cursor(0), _padMode(PAD_MODE_NORMAL), _lastPadCheckTime(0) {} + void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } + void setCursor(Cursor *cursor) { _cursor = cursor; _nub.setCursor(cursor); } + + void init(); + bool getAllInputs(Common::Event &event); + private: - Cursor *_cursor; PSPKeyboard *_keyboard; - uint32 _prevButtons; + Cursor *_cursor; + + Nub _nub; + ButtonPad _buttonPad; + + PspPadMode _padMode; // whice mode we're in + PspEvent _pendingPspEvent; // an event that can't be handled yet uint32 _lastPadCheckTime; - uint32 _buttonsChanged; - int32 _dpadX, _dpadY; - int32 _accelX, _accelY; + static const char *_padModeText[]; bool getEvent(Common::Event &event, SceCtrlData &pad); - bool getDpadEvent(Common::Event &event, SceCtrlData &pad); - bool getButtonEvent(Common::Event &event, SceCtrlData &pad); - bool getNubEvent(Common::Event &event, SceCtrlData &pad); - int32 modifyNubAxisMotion(int32 input); - Common::KeyCode translateDpad(int x, int y); + bool handlePspEvent(Common::Event &event, PspEvent &pspEvent); + void handleMouseEvent(Common::Event &event, Common::EventType type, const char *string); + void handleShiftEvent(ShiftMode shifted); + void handleModeSwitchEvent(); }; #endif /* PSP_INPUT_H */ diff --git a/backends/platform/psp/pspkeyboard.cpp b/backends/platform/psp/pspkeyboard.cpp index eb081fc5f4..b83b1c873a 100644 --- a/backends/platform/psp/pspkeyboard.cpp +++ b/backends/platform/psp/pspkeyboard.cpp @@ -26,7 +26,7 @@ //#define PSP_KB_SHELL /* Need a hack to properly load the keyboard from the PSP shell */ #ifdef PSP_KB_SHELL -#define PSP_KB_SHELL_PATH "ms0:/psp/game4xx/scummvm-solid/" /* path to kbd.zip */ +#define PSP_KB_SHELL_PATH "ms0:/psp/game5xx/scummvm-solid/" /* path to kbd.zip */ #endif @@ -36,6 +36,7 @@ #include "backends/platform/psp/psppixelformat.h" #include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/input.h" #include "common/keyboard.h" #include "common/fs.h" #include "common/unzip.h" @@ -508,10 +509,11 @@ int PSPKeyboard::loadPngImage(Common::SeekableReadStream *file, Buffer &buffer, * Uses the state machine. * returns whether we have an event */ -bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad) { +bool PSPKeyboard::processInput(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { DEBUG_ENTER_FUNC(); bool haveEvent = false; // Whether we have an event for the event manager to process + bool havePspEvent = false; event.kbd.flags = 0; _buttonsChanged = _prevButtons ^ pad.Buttons; @@ -529,12 +531,12 @@ bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad) { event.type = DOWN(PSP_CTRL_START) ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; haveEvent = true; _dirty = true; - if (UP(PSP_CTRL_START)) - _state = kInvisible; // Make us invisible if unpressed + if (UP(PSP_CTRL_START)) + havePspEvent = true; } // Check for being in state of moving the keyboard onscreen or pressing select else if (_state == kMove) - handleMoveState(pad); + havePspEvent = handleMoveState(pad); else if (_state == kDefault) haveEvent = handleDefaultState(event, pad); else if (_state == kCornersSelected) @@ -544,12 +546,16 @@ bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad) { else if (_state == kLTriggerDown) handleLTriggerDownState(pad); // Deal with trigger states + if (havePspEvent) { + pspEvent.type = PSP_EVENT_SHOW_VIRTUAL_KB; // tell the input handler we're off + pspEvent.data = false; + } _prevButtons = pad.Buttons; return haveEvent; } -void PSPKeyboard::handleMoveState(SceCtrlData &pad) { +bool PSPKeyboard::handleMoveState(SceCtrlData &pad) { DEBUG_ENTER_FUNC(); if (UP(PSP_CTRL_SELECT)) { // Toggle between visible and invisible @@ -560,6 +566,9 @@ void PSPKeyboard::handleMoveState(SceCtrlData &pad) { _state = kDefault; _moved = false; // reset moved flag } + if (_state == kInvisible) { + return true; // we become invisible + } } else if (DOWN(PSP_DPAD)) { // How we move the KB onscreen _moved = true; _dirty = true; @@ -573,6 +582,7 @@ void PSPKeyboard::handleMoveState(SceCtrlData &pad) { else /* DOWN(PSP_CTRL_RIGHT) */ increaseKeyboardLocationX(5); } + return false; } bool PSPKeyboard::handleDefaultState(Common::Event &event, SceCtrlData &pad) { diff --git a/backends/platform/psp/pspkeyboard.h b/backends/platform/psp/pspkeyboard.h index a30e7d0f32..1bd394c15a 100644 --- a/backends/platform/psp/pspkeyboard.h +++ b/backends/platform/psp/pspkeyboard.h @@ -29,12 +29,15 @@ #include "common/events.h" #include "common/stream.h" #include "backends/platform/psp/display_client.h" +//#include "backends/platform/psp/input.h" #include <pspctrl.h> //number of modes #define MODE_COUNT 4 #define guiStringsSize 8 /* size of guistrings array */ +class PspEvent; + class PSPKeyboard : public DisplayClient { private: @@ -58,10 +61,9 @@ public: void setClean() { _dirty = false; } bool isVisible() const { return _state != kInvisible; } // Check if visible void setVisible(bool val); - bool processInput(Common::Event &event, SceCtrlData &pad); // Process input + bool processInput(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); // Process input void moveTo(const int newX, const int newY); // Move keyboard void render(); // Draw the keyboard onscreen - private: enum CursorDirections { kUp = 0, @@ -82,7 +84,7 @@ private: void increaseKeyboardLocationY(int amount); void convertCursorToXY(CursorDirections cur, int &x, int &y); - void handleMoveState(SceCtrlData &pad); + bool handleMoveState(SceCtrlData &pad); bool handleDefaultState(Common::Event &event, SceCtrlData &pad); bool handleCornersSelectedState(Common::Event &event, SceCtrlData &pad); bool getInputChoice(Common::Event &event, SceCtrlData &pad); |