diff options
Diffstat (limited to 'backends/ps2/ps2pad.cpp')
-rw-r--r-- | backends/ps2/ps2pad.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/backends/ps2/ps2pad.cpp b/backends/ps2/ps2pad.cpp new file mode 100644 index 0000000000..0f0457668c --- /dev/null +++ b/backends/ps2/ps2pad.cpp @@ -0,0 +1,155 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 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 "backends/ps2/systemps2.h" +#include "backends/ps2/ps2pad.h" + +Ps2Pad::Ps2Pad(OSystem_PS2 *system) { + _system = system; + _padBuf = (uint8*)memalign(64, 256); + _padStatus = STAT_NONE; + + padInit(0); // initialize library + _port = _slot = 0; // first controller, no multitap + initPad(); +} + +void Ps2Pad::initPad(void) { + int modes = 0; + if (_padStatus == STAT_NONE) { + if (padPortOpen(_port, _slot, _padBuf) == 1) { + _padStatus = STAT_OPEN; + _padInitTime = _system->getMillis(); + } else { + padPortClose(_port, _slot); + printf("Unable to open port (%d/%d)!\n", _port, _slot); + } + } else { + if (checkPadReady(_port, _slot)) { + switch (_padStatus) { + case STAT_OPEN: + _padStatus = STAT_DETECT; + break; + case STAT_DETECT: + _isDualShock = false; + modes = padInfoMode(_port, _slot, PAD_MODETABLE, -1); + + // Verify that the controller has a DUAL SHOCK mode + for (int cnt = 0; cnt < modes; cnt++) + if (padInfoMode(_port, _slot, PAD_MODETABLE, cnt) == PAD_TYPE_DUALSHOCK) + _isDualShock = true; + + // If ExId != 0x0 => This controller has actuator engines + // This check should always pass if the Dual Shock test above passed + if (_isDualShock) + if (padInfoMode(_port, _slot, PAD_MODECUREXID, 0) == 0) + _isDualShock = false; + + if (_isDualShock) { + // When using MMODE_LOCK, user cant change mode with Select button + padSetMainMode(_port, _slot, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK); + _padStatus = STAT_INIT_DSHOCK; + } else + _padStatus = STAT_WAIT_READY; + break; + case STAT_INIT_DSHOCK: + padEnterPressMode(_port, _slot); + _padStatus = STAT_CHECK_ACT; + break; + case STAT_CHECK_ACT: + _actuators = padInfoAct(_port, _slot, -1, 0); + if (_actuators != 0) + _padStatus = STAT_INIT_ACT; + else { + _isDualShock = false; + _padStatus = STAT_WAIT_READY; + } + break; + case STAT_INIT_ACT: + char actAlign[6]; + actAlign[0] = 0; + actAlign[1] = 1; + actAlign[2] = actAlign[3] = actAlign[4] = actAlign[5] = 0xff; + padSetActAlign(_port, _slot, actAlign); + _padStatus = STAT_WAIT_READY; + break; + case STAT_WAIT_READY: + _padStatus = STAT_OKAY; + break; + } + } else { + // check for timeout... + if (_system->getMillis() - _padInitTime > 5000) { + // still no pad, give up. + if (padPortClose(_port, _slot) != 1) + printf("WARNING: can't close port: %d/%d\n"); + printf("looking for pad, gave up and closed port\n"); + _padStatus = STAT_NONE; + } + } + } +} + +bool Ps2Pad::checkPadReady(int port, int slot, uint32 wait, uint32 *waitRes) { + int state; + for (uint32 cnt = 0; cnt < wait; cnt++) { + state = padGetState(port, slot); + if ((state == PAD_STATE_STABLE) || (state == PAD_STATE_FINDCTP1)) { + if (waitRes) + *waitRes = cnt; + return true; + } + } + return false; +} + +bool Ps2Pad::padAlive(void) { + if ((_padStatus == STAT_OKAY) && checkPadReady(_port, _slot)) + return true; + initPad(); + return false; +} + +bool Ps2Pad::isDualShock(void) { + return _isDualShock; +} + +void Ps2Pad::readPad(uint16 *pbuttons, int16 *joyh, int16 *joyv) { + if (padAlive()) { + struct padButtonStatus buttons; + padRead(_port, _slot, &buttons); + *pbuttons = ~buttons.btns; + if (_isDualShock) { + *joyh = (int16)buttons.ljoy_h - 128; + *joyv = (int16)buttons.ljoy_v - 128; + } else + *joyh = *joyv = 0; + } else { + *joyh = *joyv = 0; + *pbuttons = 0; + } +} + + + |