/* * Copyright (c) 2009, Wei Mingzhi . * All Rights Reserved. * * 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, see . */ #include "pad.h" char *PSEgetLibName(void) { #ifdef EPSXE return _("Gamepad/Keyboard Input (ePSXe)"); #else return _("Gamepad/Keyboard Input"); #endif } uint32_t PSEgetLibType(void) { return PSE_LT_PAD; } uint32_t PSEgetLibVersion(void) { return (1 << 16) | (1 << 8); } long PADinit(long flags) { LoadConfig(); g.PadState[0].PadMode = 0; g.PadState[0].PadID = 0x41; g.PadState[1].PadMode = 0; g.PadState[1].PadID = 0x41; return PSE_PAD_ERR_SUCCESS; } long PADshutdown(void) { PADclose(); return PSE_PAD_ERR_SUCCESS; } static pthread_t ThreadID; static uint8_t TerminateThread = 0; static void *JoyThread(void *param) { while (!TerminateThread) { CheckJoy(); usleep(1000); } pthread_exit(0); return NULL; } long PADopen(unsigned long *Disp) { g.Disp = (Display *)*Disp; if (!g.Opened) { if (SDL_WasInit(SDL_INIT_EVERYTHING)) { if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { return PSE_PAD_ERR_FAILURE; } } else if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == -1) { return PSE_PAD_ERR_FAILURE; } InitSDLJoy(); InitKeyboard(); g.KeyLeftOver = 0; if (g.cfg.Threaded) { TerminateThread = 0; if (pthread_create(&ThreadID, NULL, JoyThread, NULL) != 0) { // thread creation failed, fallback to polling g.cfg.Threaded = 0; } } } g.Opened = 1; return PSE_PAD_ERR_SUCCESS; } long PADclose(void) { if (g.Opened) { if (g.cfg.Threaded) { TerminateThread = 1; pthread_join(ThreadID, NULL); } DestroySDLJoy(); DestroyKeyboard(); if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_JOYSTICK)) { SDL_QuitSubSystem(SDL_INIT_JOYSTICK); } else { SDL_Quit(); } } g.Opened = 0; return PSE_PAD_ERR_SUCCESS; } long PADquery(void) { return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; } static void UpdateInput(void) { if (!g.cfg.Threaded) CheckJoy(); CheckKeyboard(); } #ifndef EPSXE static uint8_t stdpar[2][20] = { {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; static uint8_t unk46[2][8] = { {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A} }; static uint8_t unk47[2][8] = { {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}, {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00} }; static uint8_t unk4c[2][8] = { {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; static uint8_t unk4d[2][8] = { {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} }; static uint8_t stdcfg[2][8] = { {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; static uint8_t stdmode[2][8] = { {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; static uint8_t stdmodel[2][8] = { {0xFF, 0x5A, 0x01, // 03 - dualshock2, 01 - dualshock 0x02, // number of modes 0x01, // current mode: 01 - analog, 00 - digital 0x02, 0x01, 0x00}, {0xFF, 0x5A, 0x01, // 03 - dualshock2, 01 - dualshock 0x02, // number of modes 0x01, // current mode: 01 - analog, 00 - digital 0x02, 0x01, 0x00} }; static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0; unsigned char PADstartPoll(int pad) { CurPad = pad - 1; CurByte = 0; return 0xFF; } unsigned char PADpoll(unsigned char value) { static uint8_t *buf = NULL; uint16_t n; if (CurByte == 0) { CurByte++; // Don't enable Analog/Vibration for a standard pad if (g.cfg.PadDef[CurPad].Type != PSE_PAD_TYPE_ANALOGPAD) { CurCmd = CMD_READ_DATA_AND_VIBRATE; } else { CurCmd = value; } switch (CurCmd) { case CMD_CONFIG_MODE: CmdLen = 8; buf = stdcfg[CurPad]; if (stdcfg[CurPad][3] == 0xFF) return 0xF3; else return g.PadState[CurPad].PadID; case CMD_SET_MODE_AND_LOCK: CmdLen = 8; buf = stdmode[CurPad]; return 0xF3; case CMD_QUERY_MODEL_AND_MODE: CmdLen = 8; buf = stdmodel[CurPad]; buf[4] = g.PadState[CurPad].PadMode; return 0xF3; case CMD_QUERY_ACT: CmdLen = 8; buf = unk46[CurPad]; return 0xF3; case CMD_QUERY_COMB: CmdLen = 8; buf = unk47[CurPad]; return 0xF3; case CMD_QUERY_MODE: CmdLen = 8; buf = unk4c[CurPad]; return 0xF3; case CMD_VIBRATION_TOGGLE: CmdLen = 8; buf = unk4d[CurPad]; return 0xF3; case CMD_READ_DATA_AND_VIBRATE: default: UpdateInput(); n = g.PadState[CurPad].KeyStatus; n &= g.PadState[CurPad].JoyKeyStatus; stdpar[CurPad][2] = n & 0xFF; stdpar[CurPad][3] = n >> 8; if (g.PadState[CurPad].PadMode == 1) { CmdLen = 20; stdpar[CurPad][4] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][ANALOG_X]; stdpar[CurPad][5] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][ANALOG_Y]; stdpar[CurPad][6] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][ANALOG_X]; stdpar[CurPad][7] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][ANALOG_Y]; switch (stdpar[CurPad][3]) { case 0xBF: // X stdpar[CurPad][14] = 0xFF; break; case 0xDF: // Circle stdpar[CurPad][13] = 0xFF; break; case 0xEF: // Triangle stdpar[CurPad][12] = 0xFF; break; case 0x7F: // Square stdpar[CurPad][15] = 0xFF; break; case 0xFB: // L1 stdpar[CurPad][16] = 0xFF; break; case 0xF7: // R1 stdpar[CurPad][17] = 0xFF; break; case 0xFE: // L2 stdpar[CurPad][18] = 0xFF; break; case 0xFD: // R2 stdpar[CurPad][19] = 0xFF; break; default: stdpar[CurPad][14] = 0x00; // Not pressed stdpar[CurPad][13] = 0x00; // Not pressed stdpar[CurPad][12] = 0x00; // Not pressed stdpar[CurPad][15] = 0x00; // Not pressed stdpar[CurPad][16] = 0x00; // Not pressed stdpar[CurPad][17] = 0x00; // Not pressed stdpar[CurPad][18] = 0x00; // Not pressed stdpar[CurPad][19] = 0x00; // Not pressed break; } switch (stdpar[CurPad][2] >> 4) { case 0x0E: // UP stdpar[CurPad][10] = 0xFF; break; case 0x0B: // DOWN stdpar[CurPad][11] = 0xFF; break; case 0x07: // LEFT stdpar[CurPad][9] = 0xFF; break; case 0x0D: // RIGHT stdpar[CurPad][8] = 0xFF; break; default: stdpar[CurPad][8] = 0x00; // Not pressed stdpar[CurPad][9] = 0x00; // Not pressed stdpar[CurPad][10] = 0x00; // Not pressed stdpar[CurPad][11] = 0x00; // Not pressed break; } } else { CmdLen = 4; } buf = stdpar[CurPad]; return g.PadState[CurPad].PadID; } } switch (CurCmd) { case CMD_CONFIG_MODE: if (CurByte == 2) { switch (value) { case 0: buf[2] = 0; buf[3] = 0; break; case 1: buf[2] = 0xFF; buf[3] = 0xFF; break; } } break; case CMD_SET_MODE_AND_LOCK: if (CurByte == 2) { g.PadState[CurPad].PadMode = value; g.PadState[CurPad].PadID = value ? 0x73 : 0x41; } break; case CMD_QUERY_ACT: if (CurByte == 2) { switch (value) { case 0: // default buf[5] = 0x02; buf[6] = 0x00; buf[7] = 0x0A; break; case 1: // Param std conf change buf[5] = 0x01; buf[6] = 0x01; buf[7] = 0x14; break; } } break; case CMD_QUERY_MODE: if (CurByte == 2) { switch (value) { case 0: // mode 0 - digital mode buf[5] = PSE_PAD_TYPE_STANDARD; break; case 1: // mode 1 - analog mode buf[5] = PSE_PAD_TYPE_ANALOGPAD; break; } } break; } if (CurByte >= CmdLen) return 0; return buf[CurByte++]; } #endif static long PADreadPort(int num, PadDataS *pad) { UpdateInput(); pad->buttonStatus = (g.PadState[num].KeyStatus & g.PadState[num].JoyKeyStatus); #ifdef EPSXE // ePSXe different from pcsx, swap bytes pad->buttonStatus = (pad->buttonStatus >> 8) | (pad->buttonStatus << 8); #endif switch (g.cfg.PadDef[num].Type) { case PSE_PAD_TYPE_ANALOGPAD: // Analog Controller SCPH-1150 pad->controllerType = PSE_PAD_TYPE_ANALOGPAD; pad->rightJoyX = g.PadState[num].AnalogStatus[ANALOG_RIGHT][ANALOG_X]; pad->rightJoyY = g.PadState[num].AnalogStatus[ANALOG_RIGHT][ANALOG_Y]; pad->leftJoyX = g.PadState[num].AnalogStatus[ANALOG_LEFT][ANALOG_X]; pad->leftJoyY = g.PadState[num].AnalogStatus[ANALOG_LEFT][ANALOG_Y]; break; case PSE_PAD_TYPE_STANDARD: // Standard Pad SCPH-1080, SCPH-1150 default: pad->controllerType = PSE_PAD_TYPE_STANDARD; break; } return PSE_PAD_ERR_SUCCESS; } long PADreadPort1(PadDataS *pad) { return PADreadPort(0, pad); } long PADreadPort2(PadDataS *pad) { return PADreadPort(1, pad); } long PADkeypressed(void) { long s; CheckKeyboard(); s = g.KeyLeftOver; g.KeyLeftOver = 0; return s; } long PADconfigure(void) { if (fork() == 0) { execl("cfg/cfgDFInput", "cfgDFInput", NULL); exit(0); } return PSE_PAD_ERR_SUCCESS; } void PADabout(void) { if (fork() == 0) { execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL); exit(0); } } long PADtest(void) { return PSE_PAD_ERR_SUCCESS; }