/* ScummVM - Scumm Interpreter * Copyright (C) 2005-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ #include #include #include #include #include "backends/platform/ps2/rpckbd.h" #include "backends/platform/ps2/ps2input.h" #include "backends/platform/ps2/ps2pad.h" #include "backends/platform/ps2/systemps2.h" #include "backends/platform/ps2/sdlkeys.h" #include "common/events.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 & Common::KBD_SHIFT) { return key & ~0x20; } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { return 0; } return key; } bool Ps2Input::pollEvent(Common::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 = Common::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) ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP; else event->type = (_mButtons & PS2MOUSE_BTN2) ? Common::EVENT_RBUTTONDOWN : Common::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 |= Common::KBD_SHIFT; else _keyFlags &= ~Common::KBD_SHIFT; } else if ((_usbToSdlk[key.key] == SDLK_LCTRL) || (_usbToSdlk[key.key] == SDLK_RCTRL)) { if (key.state & 1) _keyFlags |= Common::KBD_CTRL; else _keyFlags &= ~Common::KBD_CTRL; } else if ((_usbToSdlk[key.key] == SDLK_LALT) || (_usbToSdlk[key.key] == SDLK_RALT)) { if (key.state & 1) _keyFlags |= Common::KBD_ALT; else _keyFlags &= ~Common::KBD_ALT; } if (key.state & 1) // down event->type = Common::EVENT_KEYDOWN; else event->type = Common::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) ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP; else event->type = (buttons & PAD_CIRCLE) ? Common::EVENT_RBUTTONDOWN : Common::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 = Common::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(Common::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 (_padCodes[entry]) { event->type = (down) ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; event->kbd.keycode = _padCodes[entry]; event->kbd.flags = _padFlags[entry]; event->kbd.ascii = mapKey(_padCodes[entry], _padFlags[entry]); 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::_padCodes[16] = { SDLK_1, // Select 0, // L3 0, // R3 SDLK_F5, // Start 0, // Up 0, // Right 0, // Down 0, // Left SDLK_KP0, // L2 0, // R2 SDLK_n, // L1 SDLK_y, // R1 SDLK_ESCAPE, // Triangle 0, // Circle => Right mouse button 0, // Cross => Left mouse button SDLK_RETURN // Square }; const int Ps2Input::_padFlags[16] = { 0, // Select 0, // L3 0, // R3 0, // Start 0, // Up 0, // Right 0, // Down 0, // Left 0, // L2 0, // R2 0, // L1 0, // R1 0, // Triangle 0, // Circle 0, // Cross 0 // Square };