Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

input.cpp

/* 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/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 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) {
            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);
      }

      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;

      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;
      }

      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;
      }

      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;
      }

      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);
            }
      }
      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;

      return input;
}

Generated by  Doxygen 1.6.0   Back to index