From 9a2eac7eee8fbe6a903e842cb257d96bd57f8702 Mon Sep 17 00:00:00 2001 From: Yotam Barnoy Date: Mon, 12 Apr 2010 06:49:05 +0000 Subject: PSP: refactoring/redesign of the backend svn-id: r48632 --- backends/platform/psp/input.cpp | 317 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 backends/platform/psp/input.cpp (limited to 'backends/platform/psp/input.cpp') diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp new file mode 100644 index 0000000000..bd33175f03 --- /dev/null +++ b/backends/platform/psp/input.cpp @@ -0,0 +1,317 @@ +/* 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. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 43618 2009-08-21 22:44:49Z joostp $ + * + */ + +// 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. + +//#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/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 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 PAD_CHECK_TIME 53 + +void InputHandler::init() { + sceCtrlSetSamplingCycle(0); // set sampling to vsync. n = n usecs + sceCtrlSetSamplingMode(1); // analog +} + +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) { + DEBUG_EXIT_FUNC(); + 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); + + if (haveEvent) + { + PSP_DEBUG_PRINT("Have event[%s]\n", haveEvent ? "true" : "false"); + PSP_DEBUG_PRINT("event.type[%d]\n", event.type); + } + + DEBUG_EXIT_FUNC(); + + return haveEvent; +} + +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; + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +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--; + } + 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; + } + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +inline Common::KeyCode InputHandler::translateDpad(int x, int y) { + 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; + } + + DEBUG_EXIT_FUNC(); + return key; +} + + +bool InputHandler::getButtonEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + bool haveEvent = false; + + 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 + } + } 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" ); + } + + haveEvent = true; + } + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +bool InputHandler::getNubEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + bool haveEvent = false; + 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); + + 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)) { + // Fine control mode for analog + if (analogStepX != 0) { + if (analogStepX > 0) + _cursor->increaseXY(2, 0); + else + _cursor->increaseXY(-2, 0); + } + + if (analogStepY != 0) { + if (analogStepY > 0) + _cursor->increaseXY(0, 2); + else + _cursor->increaseXY(0, -2); + } + } else { // Regular speed movement + _cursor->increaseXY(analogStepX, 0); + _cursor->increaseXY(0, analogStepY); + } + + int32 newX = _cursor->getX(); + int32 newY = _cursor->getY(); + + if ((oldX != newX) || (oldY != newY)) { + 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); + } + } + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +inline int32 InputHandler::modifyNubAxisMotion(int32 input) { + DEBUG_ENTER_FUNC(); + const int MIN_NUB_MOTION = 30; + + input -= 128; // Center on 0. + + if (input < -MIN_NUB_MOTION - 1) + input += MIN_NUB_MOTION + 1; // reduce the velocity + else if (input > MIN_NUB_MOTION) + input -= MIN_NUB_MOTION; // same + else // between these points, dampen the response to 0 + input = 0; + + + DEBUG_EXIT_FUNC(); + return input; +} -- cgit v1.2.3