From d5ee5f6979097458b43a14a0f2fec9139b8cce8e Mon Sep 17 00:00:00 2001 From: Clownacy Date: Thu, 29 Aug 2019 19:27:56 +0100 Subject: [PATCH] Made Input.cpp ASM-accurate See #74 --- msvc2003/CSE2.vcproj | 8 +- msvc2003/devilution/comparer-config.toml | 29 +++ src/Input.cpp | 218 +++++++++++++++++++---- src/Input.h | 8 +- src/Main.cpp | 7 +- 5 files changed, 224 insertions(+), 46 deletions(-) diff --git a/msvc2003/CSE2.vcproj b/msvc2003/CSE2.vcproj index 395a721a..0b9ac194 100644 --- a/msvc2003/CSE2.vcproj +++ b/msvc2003/CSE2.vcproj @@ -34,7 +34,7 @@ Name="VCCustomBuildTool"/> +#include #include +#define DIRECTINPUT_VERSION 0x500 +#include + #include "SDL.h" #include "WindowsWrapper.h" -#define JOYSTICK_DEADZONE 10000 - -SDL_Joystick *joystick; // This was probably a name that was given by Simon, but it fits the rest of Pixel's names so it's fine. - -void ReleaseDirectInput() +typedef struct DirectInputPair { - // Close opened joystick (if exists) - if (joystick) + LPDIRECTINPUTA lpDI; + LPDIRECTINPUTDEVICE2A device; +} DirectInputPair; + +static LPDIRECTINPUTDEVICE2A joystick; +static LPDIRECTINPUTA lpDI; + +static int joystick_neutral_x; +static int joystick_neutral_y; + +void ReleaseDirectInput(void) +{ + if (joystick != NULL) { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - SDL_JoystickClose(joystick); + joystick->Release(); joystick = NULL; } + + if (lpDI != NULL) + { + lpDI->Release(); + lpDI = NULL; + } } -BOOL InitDirectInput() +// The original name for this function is unknown +BOOL SetDeviceAquire(BOOL aquire) { - // Open first available joystick - SDL_InitSubSystem(SDL_INIT_JOYSTICK); - - for (int i = 0; i < SDL_NumJoysticks(); i++) + if (aquire == TRUE) { - joystick = SDL_JoystickOpen(i); - - // Break as soon as a joystick is properly opened - if (joystick) - break; + if (joystick != NULL) + joystick->Acquire(); + } + else + { + if (joystick != NULL) + joystick->Unacquire(); } return TRUE; } -BOOL GetJoystickStatus(JOYSTICK_STATUS *pStatus) +BOOL HookAllDirectInputDevices(HWND hWnd); +BOOL __stdcall EnumDevices_Callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); + +BOOL InitDirectInput(HINSTANCE hinst, HWND hWnd) { - // Clear status - memset(pStatus, 0, sizeof(JOYSTICK_STATUS)); + if (DirectInputCreateA(hinst, DIRECTINPUT_VERSION, &lpDI, NULL) != DI_OK) + return FALSE; - if (joystick) + if (!HookAllDirectInputDevices(hWnd)) + return FALSE; + + return TRUE; +} + +// The original name for this function is unknown +BOOL HookAllDirectInputDevices(HWND hWnd) +{ + DirectInputPair directinput_objects; + + directinput_objects.device = NULL; + directinput_objects.lpDI = lpDI; + + lpDI->AddRef(); + lpDI->EnumDevices(4, EnumDevices_Callback, &directinput_objects, 1); + + if (directinput_objects.lpDI != NULL) { - Sint16 x = SDL_JoystickGetAxis(joystick, 0); - Sint16 y = SDL_JoystickGetAxis(joystick, 1); - pStatus->bLeft = x <= -JOYSTICK_DEADZONE; - pStatus->bRight = x >= JOYSTICK_DEADZONE; - pStatus->bUp = y <= -JOYSTICK_DEADZONE; - pStatus->bDown = y >= JOYSTICK_DEADZONE; + directinput_objects.lpDI->Release(); + directinput_objects.lpDI = NULL; + } - int numButtons = SDL_JoystickNumButtons(joystick); - if (numButtons > 32) - numButtons = 32; + if (directinput_objects.device == NULL) + return FALSE; - for (int button = 0; button < numButtons; button++) - pStatus->bButton[button] = SDL_JoystickGetButton(joystick, button) != 0; + joystick = directinput_objects.device; + if (joystick->SetDataFormat(&c_dfDIJoystick) != DI_OK) // c_dfDIJoystick might be incorrect + { + return FALSE; + } + else if (joystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND) != DI_OK) + { + return FALSE; + } + else + { + joystick->Acquire(); return TRUE; } +} + +// The original name for this function is unknown +BOOL __stdcall EnumDevices_Callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) +{ + static int already_ran; + static DirectInputPair *directinput_objects; + + if ((already_ran & 1) == 0) + { + already_ran |= 1; + directinput_objects = (DirectInputPair*)pvRef; + } + + static LPDIRECTINPUTDEVICEA device; + if (directinput_objects->lpDI->CreateDevice(lpddi->guidInstance, &device, NULL)) + { + directinput_objects->device = NULL; + return TRUE; + } + + static LPDIRECTINPUTDEVICE2A _joystick; + HRESULT res = device->QueryInterface(IID_IDirectInputDevice2A, (LPVOID*)&_joystick); + + if (res < 0) + { + joystick = NULL; + return TRUE; + } + + if (device != NULL) + { + device->Release(); + device = NULL; + } + + directinput_objects->device = _joystick; + + char string[0x100]; + sprintf(string, "DeviceGUID = %x\n", lpddi->guidInstance); + OutputDebugStringA(string); return FALSE; } -BOOL ResetJoystickStatus() +BOOL GetJoystickStatus(BOOL *buttons) { + DIJOYSTATE joystate; + + if (joystick == NULL) + return FALSE; + + if (joystick->Poll()) + return FALSE; + + HRESULT res = joystick->GetDeviceState(sizeof(DIJOYSTATE), &joystate); + if (res) + { + if (res == DIERR_INPUTLOST) + SetDeviceAquire(0); + else + return FALSE; + } + + for (int i = 0; i < 32; ++i) + { + if (joystate.rgbButtons[i] & 0x80) + buttons[i + 4] = TRUE; + else + buttons[i + 4] = FALSE; + } + + buttons[3] = FALSE; + buttons[1] = FALSE; + buttons[2] = FALSE; + buttons[0] = FALSE; + + if (joystate.lX < joystick_neutral_x - 10000) + buttons[0] = TRUE; + else if (joystate.lX > joystick_neutral_x + 10000) + buttons[1] = TRUE; + + if (joystate.lY < joystick_neutral_y - 10000) + buttons[2] = TRUE; + else if (joystate.lY > joystick_neutral_y + 10000) + buttons[3] = TRUE; + + return TRUE; +} + +BOOL ResetJoystickStatus(void) +{ + DIJOYSTATE joystate; + + if (joystick == NULL) + return FALSE; + + if (joystick->Poll()) + return FALSE; + + HRESULT res = joystick->GetDeviceState(sizeof(DIJOYSTATE), &joystate); + if (res) + { + if (res == DIERR_INPUTLOST) + SetDeviceAquire(0); + else + return FALSE; + } + + joystick_neutral_x = joystate.lX; + joystick_neutral_y = joystate.lY; + return TRUE; } diff --git a/src/Input.h b/src/Input.h index 973edecf..d6405d78 100644 --- a/src/Input.h +++ b/src/Input.h @@ -14,7 +14,7 @@ struct JOYSTICK_STATUS BOOL bButton[32]; }; -void ReleaseDirectInput(); -BOOL InitDirectInput(); -BOOL GetJoystickStatus(JOYSTICK_STATUS *pStatus); -BOOL ResetJoystickStatus(); +void ReleaseDirectInput(void); +BOOL InitDirectInput(HINSTANCE hinst, HWND hWnd); +BOOL GetJoystickStatus(BOOL *buttons); +BOOL ResetJoystickStatus(void); diff --git a/src/Main.cpp b/src/Main.cpp index 89f4dcc4..fcde7642 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -354,6 +354,7 @@ int main(int argc, char *argv[]) SDL_VERSION(&wmInfo.version); SDL_GetWindowWMInfo(gWindow, &wmInfo); ghWnd = wmInfo.info.win.window; + HINSTANCE hinstance = wmInfo.info.win.hinstance; // Draw to screen if (Flip_SystemTask(ghWnd)) @@ -362,7 +363,7 @@ int main(int argc, char *argv[]) InitDirectSound(ghWnd); // Initialize joystick - if (config.bJoystick && InitDirectInput()) + if (config.bJoystick && InitDirectInput(hinstance, ghWnd)) { ResetJoystickStatus(); gbUseJoystick = TRUE; @@ -421,7 +422,7 @@ void ActiveWindow() void JoystickProc() { - JOYSTICK_STATUS status; +/* JOYSTICK_STATUS status; if (GetJoystickStatus(&status)) { @@ -444,7 +445,7 @@ void JoystickProc() if (status.bButton[i]) gKey |= gJoystickButtonTable[i]; } - } + }*/ } #define DO_KEY_PRESS(key) \