scummvm/backends/ps2/ps2input.cpp
Robert Göffringmann 4120ae9921 various PS2 system changes
svn-id: r17912
2005-05-05 03:06:32 +00:00

546 lines
12 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2005 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*
*/
#include <kernel.h>
#include <malloc.h>
#include <assert.h>
#include <libmouse.h>
#include "backends/ps2/rpckbd.h"
#include "backends/ps2/ps2input.h"
#include "backends/ps2/ps2pad.h"
#include "backends/ps2/systemps2.h"
#include "backends/ps2/sdlkeys.h"
#include "common/system.h"
Ps2Input::Ps2Input(OSystem_PS2 *system, bool mouseLoaded, bool kbdLoaded) {
_system = system;
_mouseLoaded = mouseLoaded;
_kbdLoaded = kbdLoaded;
_pad = new Ps2Pad(system);
_lastPadCheck = 0;
_posX = _posY = _mButtons = _padLastButtons = 0;
_padAccel = 0;
_minx = _miny = 0;
_maxy = 239;
_maxx = 319;
_keyFlags = 0;
if (_mouseLoaded) {
if (PS2MouseInit() >= 0) {
PS2MouseSetReadMode(PS2MOUSE_READMODE_ABS);
printf("PS2Mouse initialized\n");
} else { // shouldn't happen if the drivers were correctly loaded
printf("unable to initialize PS2Mouse!\n");
_mouseLoaded = false;
}
}
if (_kbdLoaded) {
if (PS2KbdInit() >= 0) {
PS2KbdSetReadmode(PS2KBD_READMODE_RAW);
printf("PS2Kbd initialized\n");
} else {
printf("unable to initialize PS2Kbd!\n");
_kbdLoaded = false;
}
}
}
Ps2Input::~Ps2Input(void) {
}
void Ps2Input::newRange(uint16 minx, uint16 miny, uint16 maxx, uint16 maxy) {
_minx = minx;
_miny = miny;
_maxx = maxx;
_maxy = maxy;
if (_mouseLoaded)
PS2MouseSetBoundary(minx, maxx, miny, maxy);
warpTo(_posX, _posY);
}
void Ps2Input::warpTo(uint16 x, uint16 y) {
if ((x >= _minx) && (x <= _maxx) && (y >= _miny) && (y <= _maxy)) {
_posX = x;
_posY = y;
} else {
_posX = (x < _minx) ? (_minx) : ((x > _maxx) ? (_maxx) : (x));
_posY = (y < _miny) ? (_miny) : ((y > _maxy) ? (_maxy) : (y));
}
if (_mouseLoaded)
PS2MouseSetPosition(_posX, _posY);
}
#define JOY_THRESHOLD 30
#define PAD_CHECK_TIME 20
int Ps2Input::mapKey(int key, int mod) { // copied from sdl backend
if (key >= SDLK_F1 && key <= SDLK_F9) {
return key - SDLK_F1 + 315;
} else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
return key - SDLK_KP0 + '0';
} else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
return key;
} else if (key >= 'a' && key <= 'z' && mod & OSystem::KBD_SHIFT) {
return key & ~0x20;
} else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
return 0;
}
return key;
}
bool Ps2Input::pollEvent(OSystem::Event *event) {
bool checkPadMouse, checkPadKbd;
checkPadMouse = checkPadKbd = _pad->padAlive();
if (_mouseLoaded && (PS2MouseEnum() > 0)) { // usb mouse connected
mouse_data mData;
PS2MouseRead(&mData);
if ((_posX != mData.x) || (_posY != mData.y)) {
event->mouse.x = _posX = mData.x;
event->mouse.y = _posY = mData.y;
event->type = OSystem::EVENT_MOUSEMOVE;
return true;
}
if (mData.buttons != _mButtons) {
uint16 change = _mButtons ^ mData.buttons;
_mButtons = mData.buttons;
if (change & (PS2MOUSE_BTN1 | PS2MOUSE_BTN2)) {
if (change & PS2MOUSE_BTN1)
event->type = (_mButtons & PS2MOUSE_BTN1) ? OSystem::EVENT_LBUTTONDOWN : OSystem::EVENT_LBUTTONUP;
else
event->type = (_mButtons & PS2MOUSE_BTN2) ? OSystem::EVENT_RBUTTONDOWN : OSystem::EVENT_RBUTTONUP;
event->mouse.x = _posX;
event->mouse.y = _posY;
return true;
}
}
checkPadMouse = false;
}
if (_kbdLoaded) { // there's no way to tell if there's actually a keyboard connected
PS2KbdRawKey key;
if (PS2KbdReadRaw(&key) == 1) {
if (_usbToSdlk[key.key]) {
if ((_usbToSdlk[key.key] == SDLK_LSHIFT) || (_usbToSdlk[key.key] == SDLK_RSHIFT)) {
if (key.state & 1)
_keyFlags |= OSystem::KBD_SHIFT;
else
_keyFlags &= ~OSystem::KBD_SHIFT;
} else if ((_usbToSdlk[key.key] == SDLK_LCTRL) || (_usbToSdlk[key.key] == SDLK_RCTRL)) {
if (key.state & 1)
_keyFlags |= OSystem::KBD_CTRL;
else
_keyFlags &= ~OSystem::KBD_CTRL;
} else if ((_usbToSdlk[key.key] == SDLK_LALT) || (_usbToSdlk[key.key] == SDLK_RALT)) {
if (key.state & 1)
_keyFlags |= OSystem::KBD_ALT;
else
_keyFlags &= ~OSystem::KBD_ALT;
}
if (key.state & 1) // down
event->type = OSystem::EVENT_KEYDOWN;
else
event->type = OSystem::EVENT_KEYUP;
event->kbd.flags = 0;
event->kbd.keycode = _usbToSdlk[key.key];
event->kbd.ascii = mapKey(_usbToSdlk[key.key], _keyFlags);
return true;
} else
printf("unknown keycode %02X - %02X\n", key.state, key.key);
}
}
if (checkPadMouse || checkPadKbd) {
// no usb mouse, simulate it using the pad
uint16 buttons;
int16 joyh, joyv;
_pad->readPad(&buttons, &joyh, &joyv);
uint16 btnChange = buttons ^ _padLastButtons;
if (checkPadMouse) {
if (btnChange & (PAD_CROSS | PAD_CIRCLE)) {
if (btnChange & PAD_CROSS)
event->type = (buttons & PAD_CROSS) ? OSystem::EVENT_LBUTTONDOWN : OSystem::EVENT_LBUTTONUP;
else
event->type = (buttons & PAD_CIRCLE) ? OSystem::EVENT_RBUTTONDOWN : OSystem::EVENT_RBUTTONUP;
event->mouse.x = _posX;
event->mouse.y = _posY;
_padLastButtons = buttons;
return true;
}
uint32 time = _system->getMillis();
if (time - _lastPadCheck > PAD_CHECK_TIME) {
_lastPadCheck = time;
int16 newX = _posX;
int16 newY = _posY;
if ((ABS(joyh) > JOY_THRESHOLD) || (ABS(joyv) > JOY_THRESHOLD)) {
newX += joyh / 20;
newY += joyv / 20;
} else if (buttons & PAD_DIR_MASK) {
if (_padLastButtons & PAD_DIR_MASK) {
if (_padAccel < 16)
_padAccel++;
} else
_padAccel = 0;
_padLastButtons = buttons;
if (buttons & PAD_LEFT)
newX -= _padAccel >> 2;
if (buttons & PAD_RIGHT)
newX += _padAccel >> 2;
if (buttons & PAD_UP)
newY -= _padAccel >> 2;
if (buttons & PAD_DOWN)
newY += _padAccel >> 2;
}
newX = ((newX < (int16)_minx) ? (_minx) : ((newX > (int16)_maxx) ? (_maxx) : ((int16)newX)));
newY = ((newY < (int16)_miny) ? (_miny) : ((newY > (int16)_maxy) ? (_maxy) : ((int16)newY)));
if ((_posX != newX) || (_posY != newY)) {
event->type = OSystem::EVENT_MOUSEMOVE;
event->mouse.x = _posX = newX;
event->mouse.y = _posY = newY;
return true;
}
}
}
if (checkPadKbd) {
if (getKeyEvent(event, btnChange, (btnChange & buttons) != 0)) {
_padLastButtons = buttons;
return true;
}
}
}
return false;
}
bool Ps2Input::getKeyEvent(OSystem::Event *event, uint16 buttonCode, bool down) {
// for simulating key presses with the pad
if (buttonCode) {
uint8 entry = 0;
while (!(buttonCode & 1)) {
entry++;
buttonCode >>= 1;
}
if (_asciiCodes[entry] || _keyCodes[entry]) {
event->type = (down) ? OSystem::EVENT_KEYDOWN : OSystem::EVENT_KEYUP;
event->kbd.ascii = _asciiCodes[entry];
event->kbd.keycode = _keyCodes[entry];
event->kbd.flags = 0;
return true;
}
}
return false;
}
const int Ps2Input::_usbToSdlk[0x100] = {
/* 00 */ 0,
/* 01 */ 0,
/* 02 */ 0,
/* 03 */ 0,
/* 04 */ SDLK_a,
/* 05 */ SDLK_b,
/* 06 */ SDLK_c,
/* 07 */ SDLK_d,
/* 08 */ SDLK_e,
/* 09 */ SDLK_f,
/* 0A */ SDLK_g,
/* 0B */ SDLK_h,
/* 0C */ SDLK_i,
/* 0D */ SDLK_j,
/* 0E */ SDLK_k,
/* 0F */ SDLK_l,
/* 10 */ SDLK_m,
/* 11 */ SDLK_n,
/* 12 */ SDLK_o,
/* 13 */ SDLK_p,
/* 14 */ SDLK_q,
/* 15 */ SDLK_r,
/* 16 */ SDLK_s,
/* 17 */ SDLK_t,
/* 18 */ SDLK_u,
/* 19 */ SDLK_v,
/* 1A */ SDLK_w,
/* 1B */ SDLK_x,
/* 1C */ SDLK_y,
/* 1D */ SDLK_z,
/* 1E */ SDLK_1,
/* 1F */ SDLK_2,
/* 20 */ SDLK_3,
/* 21 */ SDLK_4,
/* 22 */ SDLK_5,
/* 23 */ SDLK_6,
/* 24 */ SDLK_7,
/* 25 */ SDLK_8,
/* 26 */ SDLK_9,
/* 27 */ SDLK_0,
/* 28 */ SDLK_RETURN,
/* 29 */ SDLK_ESCAPE,
/* 2A */ SDLK_BACKSPACE,
/* 2B */ SDLK_TAB,
/* 2C */ SDLK_SPACE,
/* 2D */ SDLK_MINUS,
/* 2E */ SDLK_EQUALS,
/* 2F */ SDLK_LEFTBRACKET,
/* 30 */ SDLK_RIGHTBRACKET,
/* 31 */ SDLK_BACKSLASH,
/* 32 */ SDLK_HASH,
/* 33 */ SDLK_SEMICOLON,
/* 34 */ SDLK_QUOTE,
/* 35 */ SDLK_BACKQUOTE,
/* 36 */ SDLK_COMMA,
/* 37 */ SDLK_PERIOD,
/* 38 */ SDLK_SLASH,
/* 39 */ SDLK_CAPSLOCK,
/* 3A */ SDLK_F1,
/* 3B */ SDLK_F2,
/* 3C */ SDLK_F3,
/* 3D */ SDLK_F4,
/* 3E */ SDLK_F5,
/* 3F */ SDLK_F6,
/* 40 */ SDLK_F7,
/* 41 */ SDLK_F8,
/* 42 */ SDLK_F9,
/* 43 */ SDLK_F10,
/* 44 */ SDLK_F11,
/* 45 */ SDLK_F12,
/* 46 */ SDLK_PRINT,
/* 47 */ SDLK_SCROLLOCK,
/* 48 */ SDLK_PAUSE,
/* 49 */ SDLK_INSERT,
/* 4A */ SDLK_HOME,
/* 4B */ SDLK_PAGEUP,
/* 4C */ SDLK_DELETE,
/* 4D */ SDLK_END,
/* 4E */ SDLK_PAGEDOWN,
/* 4F */ SDLK_RIGHT,
/* 50 */ SDLK_LEFT,
/* 51 */ SDLK_DOWN,
/* 52 */ SDLK_UP,
/* 53 */ SDLK_NUMLOCK,
/* 54 */ SDLK_KP_DIVIDE,
/* 55 */ SDLK_KP_MULTIPLY,
/* 56 */ SDLK_KP_MINUS,
/* 57 */ SDLK_KP_PLUS,
/* 58 */ SDLK_KP_ENTER,
/* 59 */ SDLK_KP1,
/* 5A */ SDLK_KP2,
/* 5B */ SDLK_KP3,
/* 5C */ SDLK_KP4,
/* 5D */ SDLK_KP5,
/* 5E */ SDLK_KP6,
/* 5F */ SDLK_KP7,
/* 60 */ SDLK_KP8,
/* 61 */ SDLK_KP9,
/* 62 */ SDLK_KP0,
/* 63 */ SDLK_KP_PERIOD,
/* 64 */ 0,
/* 65 */ 0,
/* 66 */ 0,
/* 67 */ SDLK_KP_EQUALS,
/* 68 */ 0,
/* 69 */ 0,
/* 6A */ 0,
/* 6B */ 0,
/* 6C */ 0,
/* 6D */ 0,
/* 6E */ 0,
/* 6F */ 0,
/* 70 */ 0,
/* 71 */ 0,
/* 72 */ 0,
/* 73 */ 0,
/* 74 */ 0,
/* 75 */ 0,
/* 76 */ 0,
/* 77 */ 0,
/* 78 */ 0,
/* 79 */ 0,
/* 7A */ 0,
/* 7B */ 0,
/* 7C */ 0,
/* 7D */ 0,
/* 7E */ 0,
/* 7F */ 0,
/* 80 */ 0,
/* 81 */ 0,
/* 82 */ 0,
/* 83 */ 0,
/* 84 */ 0,
/* 85 */ 0,
/* 86 */ 0,
/* 87 */ 0,
/* 88 */ 0,
/* 89 */ 0,
/* 8A */ 0,
/* 8B */ 0,
/* 8C */ 0,
/* 8D */ 0,
/* 8E */ 0,
/* 8F */ 0,
/* 90 */ 0,
/* 91 */ 0,
/* 92 */ 0,
/* 93 */ 0,
/* 94 */ 0,
/* 95 */ 0,
/* 96 */ 0,
/* 97 */ 0,
/* 98 */ 0,
/* 99 */ 0,
/* 9A */ 0,
/* 9B */ 0,
/* 9C */ 0,
/* 9D */ 0,
/* 9E */ 0,
/* 9F */ 0,
/* A0 */ 0,
/* A1 */ 0,
/* A2 */ 0,
/* A3 */ 0,
/* A4 */ 0,
/* A5 */ 0,
/* A6 */ 0,
/* A7 */ 0,
/* A8 */ 0,
/* A9 */ 0,
/* AA */ 0,
/* AB */ 0,
/* AC */ 0,
/* AD */ 0,
/* AE */ 0,
/* AF */ 0,
/* B0 */ 0,
/* B1 */ 0,
/* B2 */ 0,
/* B3 */ 0,
/* B4 */ 0,
/* B5 */ 0,
/* B6 */ 0,
/* B7 */ 0,
/* B8 */ 0,
/* B9 */ 0,
/* BA */ 0,
/* BB */ 0,
/* BC */ 0,
/* BD */ 0,
/* BE */ 0,
/* BF */ 0,
/* C0 */ 0,
/* C1 */ 0,
/* C2 */ 0,
/* C3 */ 0,
/* C4 */ 0,
/* C5 */ 0,
/* C6 */ 0,
/* C7 */ 0,
/* C8 */ 0,
/* C9 */ 0,
/* CA */ 0,
/* CB */ 0,
/* CC */ 0,
/* CD */ 0,
/* CE */ 0,
/* CF */ 0,
/* D0 */ 0,
/* D1 */ 0,
/* D2 */ 0,
/* D3 */ 0,
/* D4 */ 0,
/* D5 */ 0,
/* D6 */ 0,
/* D7 */ 0,
/* D8 */ 0,
/* D9 */ 0,
/* DA */ 0,
/* DB */ 0,
/* DC */ 0,
/* DD */ 0,
/* DE */ 0,
/* DF */ 0,
/* E0 */ SDLK_LCTRL,
/* E1 */ SDLK_LSHIFT,
/* E2 */ SDLK_LALT,
/* E3 */ 0,
/* E4 */ SDLK_RCTRL,
/* E5 */ SDLK_RSHIFT,
/* E6 */ SDLK_RALT,
/* E7 */ 0,
/* E8 */ 0,
/* E9 */ 0,
/* EA */ 0,
/* EB */ 0,
/* EC */ 0,
/* ED */ 0,
/* EE */ 0,
/* EF */ 0,
/* F0 */ 0,
/* F1 */ 0,
/* F2 */ 0,
/* F3 */ 0,
/* F4 */ 0,
/* F5 */ 0,
/* F6 */ 0,
/* F7 */ 0,
/* F8 */ 0,
/* F9 */ 0,
/* FA */ 0,
/* FB */ 0,
/* FC */ 0,
/* FD */ 0,
/* FE */ 0,
/* FF */ 0
};
const int Ps2Input::_keyCodes[16] = {
49, // '1' - Select
0, // - L3
0, // - R3
286, // F5 - Start
0, // - Up
0, // - Right
0, // - Down
0, // - Left
0, // - L2
0, // - R2
0, // - L1
0, // - R1
27, // Esc - Triangle
0, // - Circle
0, // - Cross
0, // - Square
};
const uint16 Ps2Input::_asciiCodes[16] = {
49, // '1' - Select
0, // - L3
0, // - R3
319, // F5 - Start
0, // - Up
0, // - Right
0, // - Down
0, // - Left
0, // - L2
0, // - R2
0, // - L1
0, // - R1
27, // Esc - Triangle
0, // - Circle
0, // - Cross
0, // - Square
};