
There was one ASM-inaccuracy I missed last time, but now I've also made the file's memory layout accurate (it appears that global variable initialisation actually affects the order they reside in memory).
228 lines
5.1 KiB
C++
228 lines
5.1 KiB
C++
#include "Input.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#if defined(_MSC_VER) && _MSC_VER >= 1500 // Newer versions of Visual Studio don't support anything earlier than DirectInput8
|
|
#define DIRECTINPUT_VERSION 0x800
|
|
#else
|
|
#define DIRECTINPUT_VERSION 0x500
|
|
#endif
|
|
#include <dinput.h>
|
|
|
|
#include "WindowsWrapper.h"
|
|
|
|
typedef struct DirectInputPair
|
|
{
|
|
LPDIRECTINPUTA lpDI;
|
|
LPDIRECTINPUTDEVICE2A device;
|
|
} DirectInputPair;
|
|
|
|
// The original names for these variables are unknown
|
|
static LPDIRECTINPUTA lpDI = NULL;
|
|
static LPDIRECTINPUTDEVICE2A joystick = NULL;
|
|
static int joystick_neutral_x = 0;
|
|
static int joystick_neutral_y = 0;
|
|
|
|
void ReleaseDirectInput(void)
|
|
{
|
|
if (joystick != NULL)
|
|
{
|
|
joystick->Release();
|
|
joystick = NULL;
|
|
}
|
|
|
|
if (lpDI != NULL)
|
|
{
|
|
lpDI->Release();
|
|
lpDI = NULL;
|
|
}
|
|
}
|
|
|
|
// The original name for this function and its variables are unknown
|
|
BOOL SetDeviceAquire(BOOL aquire)
|
|
{
|
|
if (aquire == TRUE)
|
|
{
|
|
if (joystick != NULL)
|
|
joystick->Acquire();
|
|
}
|
|
else
|
|
{
|
|
if (joystick != NULL)
|
|
joystick->Unacquire();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// It looks like Pixel declared his functions early, so he could forward-reference
|
|
BOOL HookAllDirectInputDevices(HWND hWnd);
|
|
BOOL __stdcall EnumDevices_Callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
|
|
|
|
BOOL InitDirectInput(HINSTANCE hinst, HWND hWnd)
|
|
{
|
|
#if defined(_MSC_VER) && _MSC_VER >= 1500
|
|
if (DirectInput8Create(hinst, DIRECTINPUT_VERSION, IID_IDirectInput8A, (LPVOID*)&lpDI, NULL) != DI_OK)
|
|
#else
|
|
if (DirectInputCreateA(hinst, DIRECTINPUT_VERSION, &lpDI, NULL) != DI_OK)
|
|
#endif
|
|
return FALSE;
|
|
|
|
if (!HookAllDirectInputDevices(hWnd))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// The original name for this function and its variables are unknown
|
|
BOOL HookAllDirectInputDevices(HWND hWnd)
|
|
{
|
|
DirectInputPair directinput_objects;
|
|
|
|
directinput_objects.device = NULL;
|
|
directinput_objects.lpDI = lpDI;
|
|
|
|
directinput_objects.lpDI->AddRef();
|
|
|
|
lpDI->EnumDevices(DIDEVTYPE_JOYSTICK, EnumDevices_Callback, &directinput_objects, DIEDFL_ATTACHEDONLY);
|
|
|
|
if (directinput_objects.lpDI != NULL)
|
|
{
|
|
directinput_objects.lpDI->Release();
|
|
directinput_objects.lpDI = NULL;
|
|
}
|
|
|
|
if (directinput_objects.device == NULL)
|
|
return FALSE;
|
|
|
|
joystick = directinput_objects.device;
|
|
|
|
if (joystick->SetDataFormat(&c_dfDIJoystick) != DI_OK) // c_dfDIJoystick might be incorrect
|
|
return FALSE;
|
|
|
|
if (joystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND) != DI_OK)
|
|
return FALSE;
|
|
|
|
joystick->Acquire();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// The original name for this function and its variables are unknown
|
|
BOOL __stdcall EnumDevices_Callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
|
|
{
|
|
static int already_ran;
|
|
static DirectInputPair *directinput_objects;
|
|
|
|
if (!(already_ran & 1))
|
|
{
|
|
already_ran |= 1;
|
|
directinput_objects = (DirectInputPair*)pvRef;
|
|
}
|
|
|
|
static LPDIRECTINPUTDEVICEA device;
|
|
if (directinput_objects->lpDI->CreateDevice(lpddi->guidInstance, &device, NULL) != DI_OK)
|
|
{
|
|
directinput_objects->device = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
static LPDIRECTINPUTDEVICE2A _joystick;
|
|
HRESULT res = device->QueryInterface(IID_IDirectInputDevice2A, (LPVOID*)&_joystick);
|
|
|
|
if (FAILED(res))
|
|
{
|
|
joystick = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
if (device != NULL)
|
|
{
|
|
device->Release();
|
|
device = NULL;
|
|
}
|
|
|
|
directinput_objects->device = _joystick;
|
|
|
|
char string[0x100];
|
|
#ifdef FIX_BUGS
|
|
sprintf(string, "DeviceGUID = %08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", lpddi->guidInstance.Data1, lpddi->guidInstance.Data2, lpddi->guidInstance.Data3, lpddi->guidInstance.Data4[0], lpddi->guidInstance.Data4[1], lpddi->guidInstance.Data4[2], lpddi->guidInstance.Data4[3], lpddi->guidInstance.Data4[4], lpddi->guidInstance.Data4[5], lpddi->guidInstance.Data4[6], lpddi->guidInstance.Data4[7]);
|
|
#else
|
|
sprintf(string, "DeviceGUID = %x\n", lpddi->guidInstance); // Tries to print a struct as an int
|
|
#endif
|
|
OutputDebugStringA(string);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL GetJoystickStatus(JOYSTICK_STATUS *status)
|
|
{
|
|
DIJOYSTATE joystate;
|
|
|
|
if (joystick == NULL)
|
|
return FALSE;
|
|
|
|
if (joystick->Poll() != DI_OK)
|
|
return FALSE;
|
|
|
|
HRESULT res = joystick->GetDeviceState(sizeof(DIJOYSTATE), &joystate);
|
|
if (res != DI_OK)
|
|
{
|
|
if (res == DIERR_INPUTLOST)
|
|
SetDeviceAquire(FALSE);
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
for (int i = 0; i < 32; ++i)
|
|
{
|
|
if (joystate.rgbButtons[i] & 0x80)
|
|
status->bButton[i] = TRUE;
|
|
else
|
|
status->bButton[i] = FALSE;
|
|
}
|
|
|
|
status->bDown = FALSE;
|
|
status->bRight = FALSE;
|
|
status->bUp = FALSE;
|
|
status->bLeft = FALSE;
|
|
|
|
if (joystate.lX < joystick_neutral_x - 10000)
|
|
status->bLeft = TRUE;
|
|
else if (joystate.lX > joystick_neutral_x + 10000)
|
|
status->bRight = TRUE;
|
|
|
|
if (joystate.lY < joystick_neutral_y - 10000)
|
|
status->bUp = TRUE;
|
|
else if (joystate.lY > joystick_neutral_y + 10000)
|
|
status->bDown = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL ResetJoystickStatus(void)
|
|
{
|
|
DIJOYSTATE joystate;
|
|
|
|
if (joystick == NULL)
|
|
return FALSE;
|
|
|
|
if (joystick->Poll() != DI_OK)
|
|
return FALSE;
|
|
|
|
HRESULT res = joystick->GetDeviceState(sizeof(DIJOYSTATE), &joystate);
|
|
if (res != DI_OK)
|
|
{
|
|
if (res == DIERR_INPUTLOST)
|
|
SetDeviceAquire(FALSE);
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
joystick_neutral_x = joystate.lX;
|
|
joystick_neutral_y = joystate.lY;
|
|
|
|
return TRUE;
|
|
}
|