diff --git a/plugins/LilyPad/Linux/LilyPad.cpp b/plugins/LilyPad/Linux/LilyPad.cpp deleted file mode 100644 index c802d7e57f..0000000000 --- a/plugins/LilyPad/Linux/LilyPad.cpp +++ /dev/null @@ -1,1273 +0,0 @@ -/* LilyPad - Pad plugin for PS2 Emulator - * Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver - * - * PCSX2 is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Found- ation, either version 3 of the License, or (at your option) - * any later version. - * - * PCSX2 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 PCSX2. If not, see . - */ - -#include "Global.h" - -// For escape timer, so as not to break GSDX+DX9. -#include -#include "resource.h" -#include "InputManager.h" -#include "Config.h" - -#define PADdefs - -#include "DeviceEnumerator.h" -#include "KeyboardQueue.h" -#include "svnrev.h" -#include "DualShock3.h" -#include "HidDevice.h" - -#define WMA_FORCE_UPDATE (WM_APP + 0x537) -#define FORCE_UPDATE_WPARAM ((WPARAM)0x74328943) -#define FORCE_UPDATE_LPARAM ((LPARAM)0x89437437) - -// LilyPad version. -#define VERSION ((0<<8) | 11 | (0<<24)) - -Display *GSdsp; -Window GSwin; - -// Keeps the various sources for Update polling (PADpoll, PADupdate, etc) from wreaking -// havoc on each other... -static std::mutex updateLock; - -// Used to toggle mouse listening. -u8 miceEnabled; - -// 2 when both pads are initialized, 1 for one pad, etc. -int openCount = 0; - -int activeWindow = 0; -int windowThreadId = 0; -int updateQueued = 0; - -int bufSize = 0; -unsigned char outBuf[50]; -unsigned char inBuf[50]; - -// windowThreadId = GetWindowThreadProcessId(hWnd, 0); - -#define MODE_DIGITAL 0x41 -#define MODE_ANALOG 0x73 -#define MODE_DS2_NATIVE 0x79 - - -void DEBUG_TEXT_OUT(const char *text) { -#ifdef _MSC_VER - if (config.debug) { - HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0); - if (hFile != INVALID_HANDLE_VALUE) { - DWORD junk; - WriteFile(hFile, text, strlen(text), &junk, 0); - CloseHandle(hFile);; - } - } -#endif -} - -void DEBUG_NEW_SET() { -#ifdef _MSC_VER - if (config.debug && bufSize>1) { - HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0); - if (hFile != INVALID_HANDLE_VALUE) { - int i; - char temp[1500]; - char *end = temp; - sprintf(end, "%02X (%02X) ", inBuf[0], inBuf[1]); - end += 8; - for (i=2; i 0). - u8 enabled; -} pads[2][4]; - -// Active slots for each port. -int slots[2]; -// Which ports we're running on. -int portInitialized[2]; - -// Force value to be from 0 to 255. -u8 Cap (int i) { - if (i<0) return 0; - if (i>255) return 255; - return (u8) i; -} - -inline void ReleaseModifierKeys() { - QueueKeyEvent(VK_SHIFT, KEYRELEASE); - QueueKeyEvent(VK_MENU, KEYRELEASE); - QueueKeyEvent(VK_CONTROL, KEYRELEASE); -} - -// RefreshEnabledDevices() enables everything that can potentially -// be bound to, as well as the "Ignore keyboard" device. -// -// This enables everything that input should be read from while the -// emulator is running. Takes into account mouse and focus state -// and which devices have bindings for enabled pads. Releases -// keyboards if window is not focused. Releases game devices if -// background monitoring is not checked. -// And releases games if not focused and config.background is not set. -void UpdateEnabledDevices(int updateList = 0) { - // Enable all devices I might want. Can ignore the rest. - RefreshEnabledDevices(updateList); - // Figure out which pads I'm getting input for. - for (int port = 0; port<2; port++) { - for (int slot = 0; slot<4; slot++) { - if (slot && !config.multitap[port]) { - pads[port][slot].enabled = 0; - } - else { - pads[port][slot].enabled = pads[port][slot].initialized && config.padConfigs[port][slot].type != DisabledPad; - } - } - } - for (int i=0; inumDevices; i++) { - Device *dev = dm->devices[i]; - - if (!dev->enabled) continue; - if (!dev->attached) { - dm->DisableDevice(i); - continue; - } - - // Disable ignore keyboard if don't have focus or there are no keys to ignore. - if (dev->api == IGNORE_KEYBOARD) { - if ((!config.vistaVolume && (config.keyboardApi == NO_API || !dev->pads[0][0].numBindings)) || !activeWindow) { - dm->DisableDevice(i); - } - continue; - } - // Keep for PCSX2 keyboard shotcuts, unless unfocused. - if (dev->type == KEYBOARD) { - if (!activeWindow) dm->DisableDevice(i); - } - // Keep for cursor hiding consistency, unless unfocused. - // miceEnabled tracks state of mouse enable/disable button, not if mouse API is set to disabled. - else if (dev->type == MOUSE) { - if (!miceEnabled || !activeWindow) dm->DisableDevice(i); - } - else if (!activeWindow && !config.background) dm->DisableDevice(i); - else { - int numActiveBindings = 0; - for (int port=0; port<2; port++) { - for (int slot=0; slot<4; slot++) { - if (pads[port][slot].enabled) { - numActiveBindings += dev->pads[port][slot].numBindings + dev->pads[port][slot].numFFBindings; - } - } - } - if (!numActiveBindings) - dm->DisableDevice(i); - } - } -} - -void AddForce(ButtonSum *sum, u8 cmd, int delta = 255) { - if (!delta) return; - if (cmd<0x14) { - sum->buttons[cmd-0x10] += delta; - } - // D-pad. Command numbering is based on ordering of digital values. - else if (cmd < 0x18) { - if (cmd == 0x14) { - sum->sticks[0].vert -= delta; - } - else if (cmd == 0x15) { - sum->sticks[0].horiz += delta; - } - else if (cmd == 0x16) { - sum->sticks[0].vert += delta; - } - else if (cmd == 0x17) { - sum->sticks[0].horiz -= delta; - } - } - else if (cmd < 0x20) { - sum->buttons[cmd-0x10-4] += delta; - } - // Left stick. - else if (cmd < 0x24) { - if (cmd == 32) { - sum->sticks[2].vert -= delta; - } - else if (cmd == 33) { - sum->sticks[2].horiz += delta; - } - else if (cmd == 34) { - sum->sticks[2].vert += delta; - } - else if (cmd == 35) { - sum->sticks[2].horiz -= delta; - } - } - // Right stick. - else if (cmd < 0x28) { - if (cmd == 36) { - sum->sticks[1].vert -= delta; - } - else if (cmd == 37) { - sum->sticks[1].horiz += delta; - } - else if (cmd == 38) { - sum->sticks[1].vert += delta; - } - else if (cmd == 39) { - sum->sticks[1].horiz -= delta; - } - } -} - -void ProcessButtonBinding(Binding *b, ButtonSum *sum, int value) { - if (value < b->deadZone || !value) return; - - if ( config.turboKeyHack == 1 ){ // send a tabulator keypress to emulator - //printf("%x\n", b->command); - if ( b->command == 0x11 ){ // L3 button - static unsigned int LastCheck = 0; - unsigned int t = timeGetTime(); - if (t - LastCheck < 300 ) return; - QueueKeyEvent(VK_TAB, KEYPRESS); - LastCheck = t; - } - } - - int sensitivity = b->sensitivity; - if (sensitivity < 0) { - sensitivity = -sensitivity; - value = (1<<16)-value; - } - if (value < 0) return; - - /* Note: Value ranges of FULLY_DOWN, and sensitivity of - * BASE_SENSITIVITY corresponds to an axis/button being exactly fully down. - * Math in next line takes care of those two conditions, rounding as necessary. - * Done using __int64s because overflows will occur when - * sensitivity > BASE_SENSITIVITY and/or value > FULLY_DOWN. Latter only happens - * for relative axis. - */ - int force = (int)((((sensitivity*(255*(__int64)value)) + BASE_SENSITIVITY/2)/BASE_SENSITIVITY + FULLY_DOWN/2)/FULLY_DOWN); - AddForce(sum, b->command, force); -} - -// Restricts d-pad/analog stick values to be from -255 to 255 and button values to be from 0 to 255. -// With D-pad in DS2 native mode, the negative and positive ranges are both independently from 0 to 255, -// which is why I use 9 bits of all sticks. For left and right sticks, I have to remove a bit before sending. -void CapSum(ButtonSum *sum) { - int i; - for (i=0; i<3; i++) { - int div = std::max(abs(sum->sticks[i].horiz), abs(sum->sticks[i].vert)); - if (div > 255) { - sum->sticks[i].horiz = sum->sticks[i].horiz * 255 / div; - sum->sticks[i].vert = sum->sticks[i].vert * 255 / div; - } - } - for (i=0; i<12; i++) { - sum->buttons[i] = Cap(sum->buttons[i]); - } -} - -// Counter similar to stateUpdated for each pad, except used for PADkeyEvent instead. -// Only matters when GS thread updates is disabled (Just like summed pad values -// for pads beyond the first slot). - -// Values, in order, correspond to PADkeyEvent, PADupdate(0), PADupdate(1), and -// WndProc(WMA_FORCE_UPDATE). Last is always 0. -char padReadKeyUpdated[4] = {0, 0, 0, 0}; - -#define LOCK_DIRECTION 2 -#define LOCK_BUTTONS 4 -#define LOCK_BOTH 1 - -void Update(unsigned int port, unsigned int slot) { - char *stateUpdated; - if (port < 2) { - stateUpdated = &pads[port][slot].stateUpdated; - } - else if (port < 6) { - stateUpdated = padReadKeyUpdated+port-2; - } - else return; - - if (*stateUpdated > 0) { - stateUpdated[0] --; - return; - } - - // Lock prior to timecheck code to avoid pesky race conditions. - std::lock_guard lock(updateLock); - - static unsigned int LastCheck = 0; - unsigned int t = timeGetTime(); - if (t - LastCheck < 15 || !openCount) return; - -#ifdef _MSC_VER - if (windowThreadId != GetCurrentThreadId()) { - if (stateUpdated[0] < 0) { - if (!updateQueued) { - updateQueued = 1; - PostMessage(hWnd, WMA_FORCE_UPDATE, FORCE_UPDATE_WPARAM, FORCE_UPDATE_LPARAM); - } - } else - { - stateUpdated[0] --; - } - return; - } -#endif - - LastCheck = t; - - int i; - ButtonSum s[2][4]; - u8 lockStateChanged[2][4]; - memset(lockStateChanged, 0, sizeof(lockStateChanged)); - - for (i=0; i<8; i++) { - s[i&1][i>>1] = pads[i&1][i>>1].lockedSum; - } -#ifdef _MSC_VER - InitInfo info = { - 0, 0, hWndTop, &hWndGSProc - }; -#else - InitInfo info = { - 0, 0, GSdsp, GSwin - }; -#endif - dm->Update(&info); - - static int turbo = 0; - turbo++; - for (i=0; inumDevices; i++) { - Device *dev = dm->devices[i]; - // Skip both disabled devices and inactive enabled devices. - // Shouldn't be any of the latter, in general, but just in case... - if (!dev->active) continue; - for (int port=0; port<2; port++) { - for (int slot=0; slot<4; slot++) { - if (config.padConfigs[port][slot].type == DisabledPad || !pads[port][slot].initialized) continue; - for (int j=0; jpads[port][slot].numBindings; j++) { - Binding *b = dev->pads[port][slot].bindings+j; - int cmd = b->command; - int state = dev->virtualControlState[b->controlIndex]; - if (!(turbo & b->turbo)) { - if (cmd > 0x0F && cmd != 0x28) { - ProcessButtonBinding(b, &s[port][slot], state); - } - else if ((state>>15) && !(dev->oldVirtualControlState[b->controlIndex]>>15)) { - if (cmd == 0x0F) { - miceEnabled = !miceEnabled; - UpdateEnabledDevices(); - } - else if (cmd == 0x0C) { - lockStateChanged[port][slot] |= LOCK_BUTTONS; - } - else if (cmd == 0x0E) { - lockStateChanged[port][slot] |= LOCK_DIRECTION; - } - else if (cmd == 0x0D) { - lockStateChanged[port][slot] |= LOCK_BOTH; - } - else if (cmd == 0x28) { - if (!pads[port][slot].modeLock) { - if (pads[port][slot].mode != MODE_DIGITAL) - pads[port][slot].mode = MODE_DIGITAL; - else - pads[port][slot].mode = MODE_ANALOG; - } - } - } - } - } - } - } - } - dm->PostRead(); - - { - for (int port=0; port<2; port++) { - for (int slot=0; slot<4; slot++) { - for (int motor=0; motor<2; motor++) { - // TODO: Probably be better to send all of these at once. - if (pads[port][slot].nextVibrate[motor] | pads[port][slot].currentVibrate[motor]) { - pads[port][slot].currentVibrate[motor] = pads[port][slot].nextVibrate[motor]; - dm->SetEffect(port,slot, motor, pads[port][slot].nextVibrate[motor]); - } - } - } - } - - for (int port=0; port<2; port++) { - for (int slot=0; slot<4; slot++) { - pads[port][slot].stateUpdated = 1; - if (config.padConfigs[port][slot].type == DisabledPad || !pads[port][slot].initialized) continue; - if (config.padConfigs[port][slot].type == GuitarPad) { - if (!config.GH2) { - s[port][slot].sticks[1].vert = -s[port][slot].sticks[1].vert; - } - // GH2 hack. - else if (config.GH2) { - const unsigned int oldIdList[5] = {ID_R2, ID_CIRCLE, ID_TRIANGLE, ID_CROSS, ID_SQUARE}; - const unsigned int idList[5] = {ID_L2, ID_L1, ID_R1, ID_R2, ID_CROSS}; - int values[5]; - int i; - for (i=0; i<5; i++) { - int id = oldIdList[i] - 0x1104; - values[i] = s[port][slot].buttons[id]; - s[port][slot].buttons[id] = 0; - } - s[port][slot].buttons[ID_TRIANGLE-0x1104] = values[1]; - for (i=0; i<5; i++) { - int id = idList[i] - 0x1104; - s[port][slot].buttons[id] = values[i]; - } - if (abs(s[port][slot].sticks[0].vert) <= 48) { - for (int i=0; i<5; i++) { - unsigned int id = idList[i] - 0x1104; - if (pads[port][slot].sum.buttons[id] < s[port][slot].buttons[id]) { - s[port][slot].buttons[id] = pads[port][slot].sum.buttons[id]; - } - } - } - else if (abs(pads[port][slot].sum.sticks[0].vert) <= 48) { - for (int i=0; i<5; i++) { - unsigned int id = idList[i] - 0x1104; - if (pads[port][slot].sum.buttons[id]) { - s[port][slot].buttons[id] = 0; - } - } - } - } - } - - if (pads[port][slot].mode == 0x41) { - for (int i=1; i<=2; i++) { - if (abs(s[port][slot].sticks[i].horiz) >= 100) - s[port][slot].sticks[0].horiz += s[port][slot].sticks[i].horiz; - if (abs(s[port][slot].sticks[i].vert) >= 100) - s[port][slot].sticks[0].vert += s[port][slot].sticks[i].vert; - } - } - - CapSum(&s[port][slot]); - if (lockStateChanged[port][slot]) { - if (lockStateChanged[port][slot] & LOCK_BOTH) { - if (pads[port][slot].lockedState != (LOCK_DIRECTION | LOCK_BUTTONS)) { - // Enable the one that's not enabled. - lockStateChanged[port][slot] ^= pads[port][slot].lockedState^(LOCK_DIRECTION | LOCK_BUTTONS); - } - else { - // Disable both - lockStateChanged[port][slot] ^= LOCK_DIRECTION | LOCK_BUTTONS; - } - } - if (lockStateChanged[port][slot] & LOCK_DIRECTION) { - if (pads[port][slot].lockedState & LOCK_DIRECTION) { - memset(pads[port][slot].lockedSum.sticks, 0, sizeof(pads[port][slot].lockedSum.sticks)); - } - else { - memcpy(pads[port][slot].lockedSum.sticks, s[port][slot].sticks, sizeof(pads[port][slot].lockedSum.sticks)); - } - pads[port][slot].lockedState ^= LOCK_DIRECTION; - } - if (lockStateChanged[port][slot] & LOCK_BUTTONS) { - if (pads[port][slot].lockedState & LOCK_BUTTONS) { - memset(pads[port][slot].lockedSum.buttons, 0, sizeof(pads[port][slot].lockedSum.buttons)); - } - else { - memcpy(pads[port][slot].lockedSum.buttons, s[port][slot].buttons, sizeof(pads[port][slot].lockedSum.buttons)); - } - pads[port][slot].lockedState ^= LOCK_BUTTONS; - } - for (i=0; i>1].sum = s[i&1][i>>1]; - } - - padReadKeyUpdated[0] = padReadKeyUpdated[1] = padReadKeyUpdated[2] = 1; - - if( stateUpdated[0] > 0 ) - --stateUpdated[0]; -} - -void CALLBACK PADupdate(int port) { - Update(port+3, 0); -} - -inline void SetVibrate(int port, int slot, int motor, u8 val) { - pads[port][slot].nextVibrate[motor] = val; -} - -u32 CALLBACK PS2EgetLibType(void) { - ps2e = 1; - return PS2E_LT_PAD; -} - -u32 CALLBACK PS2EgetLibVersion2(u32 type) { - ps2e = 1; - if (type == PS2E_LT_PAD) - return (PS2E_PAD_VERSION<<16) | VERSION; - return 0; -} - -char* CALLBACK PSEgetLibName() { -#if defined(PCSX2_DEBUG) - static char version[50]; - sprintf(version, "LilyPad Debug (%lld)", SVN_REV); - return version; -#else - static char version[50]; - sprintf(version, "LilyPad (%lld)", SVN_REV); - return version; -#endif -} - -char* CALLBACK PS2EgetLibName(void) { - ps2e = 1; - return PSEgetLibName(); -} - -//void CALLBACK PADgsDriverInfo(GSdriverInfo *info) { -// info=info; -//} - -void CALLBACK PADshutdown() { - DEBUG_TEXT_OUT("LilyPad shutdown.\n\n"); - for (int i=0; i<8; i++) - pads[i&1][i>>1].initialized = 0; - portInitialized[0] = portInitialized[1] = 0; - UnloadConfigs(); -} - -inline void StopVibrate() { - for (int i=0; i<8; i++) { - SetVibrate(i&1, i>>1, 0, 0); - SetVibrate(i&1, i>>1, 1, 0); - } -} - -inline void ResetVibrate(int port, int slot) { - SetVibrate(port, slot, 0, 0); - SetVibrate(port, slot, 1, 0); - ((int*)(pads[port][slot].vibrate))[0] = 0xFFFFFF5A; - ((int*)(pads[port][slot].vibrate))[1] = 0xFFFFFFFF; -} - -void ResetPad(int port, int slot) { - // Lines before memset currently don't do anything useful, - // but allow this function to be called at any time. - - // Need to backup, so can be called at any point. - u8 enabled = pads[port][slot].enabled; - - // Currently should never do anything. - SetVibrate(port, slot, 0, 0); - SetVibrate(port, slot, 1, 0); - - memset(&pads[port][slot], 0, sizeof(pads[0][0])); - pads[port][slot].mode = MODE_DIGITAL; - pads[port][slot].umask[0] = pads[port][slot].umask[1] = 0xFF; - // Sets up vibrate variable. - ResetVibrate(port, slot); - if (config.padConfigs[port][slot].autoAnalog && !ps2e) { - pads[port][slot].mode = MODE_ANALOG; - } - pads[port][slot].initialized = 1; - - pads[port][slot].enabled = enabled; -} - - -struct QueryInfo { - u8 port; - u8 slot; - u8 lastByte; - u8 currentCommand; - u8 numBytes; - u8 queryDone; - u8 response[42]; -} query = {0,0,0,0, 0,0xFF, 0xF3}; - -s32 CALLBACK PADinit(u32 flags) { - // Note: Won't load settings if already loaded. - if (LoadSettings() < 0) { - return -1; - } - int port = (flags & 3); - if (port == 3) { - if (PADinit(1) == -1) return -1; - return PADinit(2); - } - - #if defined(PCSX2_DEBUG) && defined(_MSC_VER) - int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); - tmpFlag |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF; - _CrtSetDbgFlag( tmpFlag ); - #endif - - port --; - - for (int i=0; i<4; i++) { - ResetPad(port, i); - } - slots[port] = 0; - portInitialized[port] = 1; - - query.lastByte = 1; - query.numBytes = 0; - ClearKeyQueue(); - R_ClearKeyQueue(); - // Just in case, when resuming emulation. - ReleaseModifierKeys(); - - DEBUG_TEXT_OUT("LilyPad initialized\n\n"); - return 0; -} - - - -// Note to self: Has to be a define for the sizeof() to work right. -// Note to self 2: All are the same size, anyways, except for longer full DS2 response -// and shorter digital mode response. -#define SET_RESULT(a) { \ - memcpy(query.response+2, a, sizeof(a)); \ - query.numBytes = 2+sizeof(a); \ -} - -#define SET_FINAL_RESULT(a) { \ - memcpy(query.response+2, a, sizeof(a));\ - query.numBytes = 2+sizeof(a); \ - query.queryDone = 1; \ -} - -static const u8 ConfigExit[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -//static const u8 ConfigExit[7] = {0x5A, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; - -static const u8 noclue[7] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5A}; -static u8 queryMaskMode[7] = {0x5A, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x5A}; -//static const u8 DSNonNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -static const u8 setMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -// DS2 -static const u8 queryModelDS2[7] = {0x5A, 0x03, 0x02, 0x00, 0x02, 0x01, 0x00}; -// DS1 -static const u8 queryModelDS1[7] = {0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00}; - -static const u8 queryAct[2][7] = {{0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, - {0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14}}; - -static const u8 queryComb[7] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}; - -static const u8 queryMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - -static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A}; - -void CALLBACK PADconfigure() { - if (openCount) { - return; - } - Configure(); -} - -s32 CALLBACK PADopen(void *pDsp) { - if (openCount++) return 0; - DEBUG_TEXT_OUT("LilyPad opened\n\n"); - - miceEnabled = !config.mouseUnfocus; - - for (int port=0; port<2; port++) { - for (int slot=0; slot<4; slot++) { - memset(&pads[port][slot].sum, 0, sizeof(pads[port][slot].sum)); - memset(&pads[port][slot].lockedSum, 0, sizeof(pads[port][slot].lockedSum)); - pads[port][slot].lockedState = 0; - } - } - - updateQueued = 0; - - GSdsp = *(Display**)pDsp; - GSwin = (Window)*(((uptr*)pDsp)+1); - - activeWindow = 1; - UpdateEnabledDevices(); - return 0; -} - -void CALLBACK PADclose() { - if (openCount && !--openCount) { - DEBUG_TEXT_OUT("LilyPad closed\n\n"); - updateQueued = 0; - ClearKeyQueue(); - R_ClearKeyQueue(); - } -} - -u8 CALLBACK PADstartPoll(int port) { - DEBUG_NEW_SET(); - port--; - if ((unsigned int)port <= 1 && pads[port][slots[port]].enabled) { - query.queryDone = 0; - query.port = port; - query.slot = slots[port]; - query.numBytes = 2; - query.lastByte = 0; - DEBUG_IN(port); - DEBUG_OUT(0xFF); - DEBUG_IN(slots[port]); - DEBUG_OUT(pads[port][slots[port]].enabled); - return 0xFF; - } - else { - query.queryDone = 1; - query.numBytes = 0; - query.lastByte = 1; - DEBUG_IN(0); - DEBUG_OUT(0); - DEBUG_IN(port); - DEBUG_OUT(0); - return 0; - } -} - -inline int IsDualshock2(u8 port, u8 slot) { - return config.padConfigs[query.port][query.slot].type == Dualshock2Pad || - (config.padConfigs[query.port][query.slot].type == GuitarPad && config.GH2); -} - -u8 CALLBACK PADpoll(u8 value) { - DEBUG_IN(value); - if (query.lastByte+1 >= query.numBytes) { - DEBUG_OUT(0); - return 0; - } - if (query.lastByte && query.queryDone) { - DEBUG_OUT(query.response[1+query.lastByte]); - return query.response[++query.lastByte]; - } - - int i; - Pad *pad = &pads[query.port][query.slot]; - if (query.lastByte == 0) { - query.lastByte++; - query.currentCommand = value; - switch(value) { - // CONFIG_MODE - case 0x43: - if (pad->config) { - // In config mode. Might not actually be leaving it. - SET_RESULT(ConfigExit); - DEBUG_OUT(0xF3); - return 0xF3; - } - // READ_DATA_AND_VIBRATE - case 0x42: - query.response[2] = 0x5A; - { - Update(query.port, query.slot); - ButtonSum *sum = &pad->sum; - - u8 b1 = 0xFF, b2 = 0xFF; - for (i = 0; i<4; i++) { - b1 -= (sum->buttons[i] > 0) << i; - } - for (i = 0; i<8; i++) { - b2 -= (sum->buttons[i+4] > 0) << i; - } - if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) { - sum->sticks[0].horiz = -255; - // Not sure about this. Forces wammy to be from 0 to 0x7F. - // if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0; - } - b1 -= ((sum->sticks[0].vert < 0) << 4); - b1 -= ((sum->sticks[0].horiz > 0) << 5); - b1 -= ((sum->sticks[0].vert > 0) << 6); - b1 -= ((sum->sticks[0].horiz < 0) << 7); - query.response[3] = b1; - query.response[4] = b2; - - query.numBytes = 5; - if (pad->mode != MODE_DIGITAL) { - query.response[5] = Cap((sum->sticks[1].horiz+255)/2); - query.response[6] = Cap((sum->sticks[1].vert+255)/2); - query.response[7] = Cap((sum->sticks[2].horiz+255)/2); - query.response[8] = Cap((sum->sticks[2].vert+255)/2); - - query.numBytes = 9; - if (pad->mode != MODE_ANALOG) { - // Good idea? No clue. - //query.response[3] &= pad->mask[0]; - //query.response[4] &= pad->mask[1]; - - // Each value is from -255 to 255, so have to use cap to convert - // negative values to 0. - query.response[9] = Cap(sum->sticks[0].horiz); - query.response[10] = Cap(-sum->sticks[0].horiz); - query.response[11] = Cap(-sum->sticks[0].vert); - query.response[12] = Cap(sum->sticks[0].vert); - - // No need to cap these, already done int CapSum(). - query.response[13] = (unsigned char) sum->buttons[8]; - query.response[14] = (unsigned char) sum->buttons[9]; - query.response[15] = (unsigned char) sum->buttons[10]; - query.response[16] = (unsigned char) sum->buttons[11]; - query.response[17] = (unsigned char) sum->buttons[6]; - query.response[18] = (unsigned char) sum->buttons[7]; - query.response[19] = (unsigned char) sum->buttons[4]; - query.response[20] = (unsigned char) sum->buttons[5]; - query.numBytes = 21; - } - } - } - - query.lastByte=1; - DEBUG_OUT(pad->mode); - return pad->mode; - // SET_VREF_PARAM - case 0x40: - SET_FINAL_RESULT(noclue); - break; - // QUERY_DS2_ANALOG_MODE - case 0x41: - // Right? Wrong? No clue. - if (pad->mode == MODE_DIGITAL) { - queryMaskMode[1] = queryMaskMode[2] = queryMaskMode[3] = 0; - queryMaskMode[6] = 0x00; - } - else { - queryMaskMode[1] = pad->umask[0]; - queryMaskMode[2] = pad->umask[1]; - queryMaskMode[3] = 0x03; - // Not entirely sure about this. - //queryMaskMode[3] = 0x01 | (pad->mode == MODE_DS2_NATIVE)*2; - queryMaskMode[6] = 0x5A; - } - SET_FINAL_RESULT(queryMaskMode); - break; - // SET_MODE_AND_LOCK - case 0x44: - SET_RESULT(setMode); - ResetVibrate(query.port, query.slot); - break; - // QUERY_MODEL_AND_MODE - case 0x45: - if (IsDualshock2(query.port, query.slot)) { - SET_FINAL_RESULT(queryModelDS2) - } - else { - SET_FINAL_RESULT(queryModelDS1); - } - // Not digital mode. - query.response[5] = (pad->mode & 0xF) != 1; - break; - // QUERY_ACT - case 0x46: - SET_RESULT(queryAct[0]); - break; - // QUERY_COMB - case 0x47: - SET_FINAL_RESULT(queryComb); - break; - // QUERY_MODE - case 0x4C: - SET_RESULT(queryMode); - break; - // VIBRATION_TOGGLE - case 0x4D: - memcpy(query.response+2, pad->vibrate, 7); - query.numBytes = 9; - ResetVibrate(query.port, query.slot); - break; - // SET_DS2_NATIVE_MODE - case 0x4F: - if (IsDualshock2(query.port, query.slot)) { - SET_RESULT(setNativeMode); - } - else { - SET_FINAL_RESULT(setNativeMode); - } - break; - default: - query.numBytes = 0; - query.queryDone = 1; - break; - } - DEBUG_OUT(0xF3); - return 0xF3; - } - else { - query.lastByte++; - switch (query.currentCommand) { - // READ_DATA_AND_VIBRATE - case 0x42: - if (query.lastByte == pad->vibrateI[0]) { - SetVibrate(query.port, query.slot, 1, 255*(0!=value)); - } - else if (query.lastByte == pad->vibrateI[1]) { - SetVibrate(query.port, query.slot, 0, value); - } - break; - // CONFIG_MODE - case 0x43: - if (query.lastByte == 3) { - query.queryDone = 1; - pad->config = value; - } - break; - // SET_MODE_AND_LOCK - case 0x44: - if (query.lastByte == 3 && value < 2) { - static const u8 modes[2] = {MODE_DIGITAL, MODE_ANALOG}; - pad->mode = modes[value]; - } - else if (query.lastByte == 4) { - if (value == 3) { - pad->modeLock = 3; - } - else { - pad->modeLock = 0; - if (pad->mode == MODE_DIGITAL && config.padConfigs[query.port][query.slot].autoAnalog && !ps2e) { - pad->mode = MODE_ANALOG; - } - } - query.queryDone = 1; - } - break; - // QUERY_ACT - case 0x46: - if (query.lastByte == 3) { - if (value<2) SET_RESULT(queryAct[value]) - // bunch of 0's - // else SET_RESULT(setMode); - query.queryDone = 1; - } - break; - // QUERY_MODE - case 0x4C: - if (query.lastByte == 3 && value<2) { - query.response[6] = 4+value*3; - query.queryDone = 1; - } - // bunch of 0's - //else data = setMode; - break; - // VIBRATION_TOGGLE - case 0x4D: - if (query.lastByte>=3) { - if (value == 0) { - pad->vibrateI[0] = (u8)query.lastByte; - } - else if (value == 1) { - pad->vibrateI[1] = (u8)query.lastByte; - } - pad->vibrate[query.lastByte-2] = value; - } - break; - // SET_DS2_NATIVE_MODE - case 0x4F: - if (query.lastByte == 3 || query.lastByte == 4) { - pad->umask[query.lastByte-3] = value; - } - else if (query.lastByte == 5) { - if (!(value & 1)) { - pad->mode = MODE_DIGITAL; - } - else if (!(value & 2)) { - pad->mode = MODE_ANALOG; - } - else { - pad->mode = MODE_DS2_NATIVE; - } - } - break; - default: - DEBUG_OUT(0); - return 0; - } - DEBUG_OUT(query.response[query.lastByte]); - return query.response[query.lastByte]; - } -} - -// returns: 1 if supports pad1 -// 2 if supports pad2 -// 3 if both are supported -u32 CALLBACK PADquery() { - return 3; -} - -void CALLBACK PADabout() { -} - -s32 CALLBACK PADtest() { - return 0; -} - -keyEvent* CALLBACK PADkeyEvent() { - // If running both pads, ignore every other call. So if two keys pressed in same interval... - static char eventCount = 0; - eventCount++; - if (eventCount < openCount) { - return 0; - } - eventCount = 0; - - Update(2, 0); - static keyEvent ev; - if (!GetQueuedKeyEvent(&ev)) return 0; - - return &ev; -} - -struct PadPluginFreezeData { - char format[8]; - // Currently all different versions are incompatible. - // May split into major/minor with some compatibility rules. - u32 version; - // So when loading, know which plugin's settings I'm loading. - // Not a big deal. Use a static variable when saving to figure it out. - u8 port; - // active slot for port - u8 slot[2]; - PadFreezeData padData[2][4]; - QueryInfo query; -}; - -s32 CALLBACK PADfreeze(int mode, freezeData *data) { - if (!data) - { - printf("LilyPad savestate null pointer!\n"); - return -1; - } - - if (mode == FREEZE_SIZE) { - data->size = sizeof(PadPluginFreezeData); - } - else if (mode == FREEZE_LOAD) { - PadPluginFreezeData &pdata = *(PadPluginFreezeData*)(data->data); - StopVibrate(); - if (data->size != sizeof(PadPluginFreezeData) || - pdata.version != PAD_SAVE_STATE_VERSION || - strcmp(pdata.format, "PadMode")) return 0; - - if( pdata.port >= 2 ) return 0; - - query = pdata.query; - if (pdata.query.slot < 4) { - query = pdata.query; - } - - // Tales of the Abyss - pad fix - // - restore data for both ports - for (int port=0; port<2; port++) { - for (int slot=0; slot<4; slot++) { - u8 mode = pdata.padData[port][slot].mode; - - if (mode != MODE_DIGITAL && mode != MODE_ANALOG && mode != MODE_DS2_NATIVE) { - break; - } - - // Not sure if the cast is strictly necessary, but feel safest with it there... - *(PadFreezeData*)&pads[port][slot] = pdata.padData[port][slot]; - } - - if (pdata.slot[port] < 4) - slots[port] = pdata.slot[port]; - } - } - else if (mode == FREEZE_SAVE) { - if (data->size != sizeof(PadPluginFreezeData)) return 0; - PadPluginFreezeData &pdata = *(PadPluginFreezeData*)(data->data); - - - // Tales of the Abyss - pad fix - // - PCSX2 only saves port0 (save #1), then port1 (save #2) - - memset(&pdata, 0, sizeof(pdata)); - strcpy(pdata.format, "PadMode"); - pdata.version = PAD_SAVE_STATE_VERSION; - pdata.port = 0; - pdata.query = query; - - for (int port=0; port<2; port++) { - for (int slot=0; slot<4; slot++) { - pdata.padData[port][slot] = pads[port][slot]; - } - - pdata.slot[port] = slots[port]; - } - } - else return -1; - return 0; -} - -u32 CALLBACK PADreadPort1 (PadDataS* pads) { - PADstartPoll(1); - PADpoll(0x42); - memcpy(pads, query.response+1, 7); - pads->controllerType = pads[0].controllerType>>4; - memset (pads+7, 0, sizeof(PadDataS)-7); - return 0; -} - -u32 CALLBACK PADreadPort2 (PadDataS* pads) { - PADstartPoll(2); - PADpoll(0x42); - memcpy(pads, query.response+1, 7); - pads->controllerType = pads->controllerType>>4; - memset (pads+7, 0, sizeof(PadDataS)-7); - return 0; -} - -u32 CALLBACK PSEgetLibType() { - return 8; -} - -u32 CALLBACK PSEgetLibVersion() { - return (VERSION & 0xFFFFFF); -} - -s32 CALLBACK PADqueryMtap(u8 port) { - port--; - if (port > 1) return 0; - return config.multitap[port]; -} - -s32 CALLBACK PADsetSlot(u8 port, u8 slot) { - port--; - slot--; - if (port > 1 || slot > 3) { - return 0; - } - // Even if no pad there, record the slot, as it is the active slot regardless. - slots[port] = slot; - // First slot always allowed. - // return pads[port][slot].enabled | !slot; - return 1; -} - -// Little funkiness to handle rounding floating points to ints without the C runtime. -// Unfortunately, means I can't use /GL optimization option when NO_CRT is defined. -#ifdef NO_CRT -extern "C" long _cdecl _ftol(); -extern "C" long _cdecl _ftol2_sse() { - return _ftol(); -} -extern "C" long _cdecl _ftol2() { - return _ftol(); -} -#endif -