shithub: cstory

Download patch

ref: d5ee5f6979097458b43a14a0f2fec9139b8cce8e
parent: 0af39741d48fe802906a308b60f96f0f14dbc206
author: Clownacy <Clownacy@users.noreply.github.com>
date: Thu Aug 29 15:27:56 EDT 2019

Made Input.cpp ASM-accurate

See #74

--- a/msvc2003/CSE2.vcproj
+++ b/msvc2003/CSE2.vcproj
@@ -34,7 +34,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib dsound.lib WinMM.lib dxguid.lib dinput.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="2"
 				AdditionalLibraryDirectories=""
@@ -85,7 +85,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib dsound.lib WinMM.lib dxguid.lib dinput.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="1"
 				IgnoreAllDefaultLibraries="FALSE"
@@ -135,7 +135,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib dsound.lib WinMM.lib dxguid.lib dinput.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="1"
 				IgnoreAllDefaultLibraries="FALSE"
@@ -186,7 +186,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib dsound.lib WinMM.lib dxguid.lib dinput.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="2"
 				AdditionalLibraryDirectories=""
--- a/msvc2003/devilution/comparer-config.toml
+++ b/msvc2003/devilution/comparer-config.toml
@@ -640,6 +640,35 @@
 addr = 0x411390
 
 [[func]]
+name = "ReleaseDirectInput"
+addr = 0x411E10
+
+[[func]]
+name = "SetDeviceAquire"
+addr = 0x411E60
+size = 0x46
+
+[[func]]
+name = "InitDirectInput"
+addr = 0x411EB0
+
+[[func]]
+name = "HookAllDirectInputDevices"
+addr = 0x411EF0
+
+[[func]]
+name = "EnumDevices_Callback"
+addr = 0x411FC0
+
+[[func]]
+name = "GetJoystickStatus"
+addr = 0x4120F0
+
+[[func]]
+name = "ResetJoystickStatus"
+addr = 0x412250
+
+[[func]]
 name = "GetTrg"
 addr = 0x4122E0
 
--- a/src/Input.cpp
+++ b/src/Input.cpp
@@ -1,72 +1,220 @@
 #include "Input.h"
 
 #include <stddef.h>
+#include <stdio.h>
 #include <string.h>
 
+#define DIRECTINPUT_VERSION 0x500
+#include <dinput.h>
+
 #include "SDL.h"
 
 #include "WindowsWrapper.h"
 
-#define JOYSTICK_DEADZONE 10000
+typedef struct DirectInputPair
+{
+	LPDIRECTINPUTA lpDI;
+	LPDIRECTINPUTDEVICE2A device;
+} DirectInputPair;
 
-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.
+static LPDIRECTINPUTDEVICE2A joystick;
+static LPDIRECTINPUTA lpDI;
 
-void ReleaseDirectInput()
+static int joystick_neutral_x;
+static int joystick_neutral_y;
+
+void ReleaseDirectInput(void)
 {
-	// Close opened joystick (if exists)
-	if (joystick)
+	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;
 }
--- a/src/Input.h
+++ b/src/Input.h
@@ -14,7 +14,7 @@
 	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);
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -354,6 +354,7 @@
 			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 @@
 				InitDirectSound(ghWnd);
 
 				// Initialize joystick
-				if (config.bJoystick && InitDirectInput())
+				if (config.bJoystick && InitDirectInput(hinstance, ghWnd))
 				{
 					ResetJoystickStatus();
 					gbUseJoystick = TRUE;
@@ -421,7 +422,7 @@
 
 void JoystickProc()
 {
-	JOYSTICK_STATUS status;
+/*	JOYSTICK_STATUS status;
 
 	if (GetJoystickStatus(&status))
 	{
@@ -444,7 +445,7 @@
 			if (status.bButton[i])
 				gKey |= gJoystickButtonTable[i];
 		}
-	}
+	}*/
 }
 
 #define DO_KEY_PRESS(key) \