2022-07-30 12:24:03 -04:00
|
|
|
#include <Windows.h>
|
2023-08-04 13:29:28 -04:00
|
|
|
#include <Xinput.h>
|
2024-01-11 10:55:54 -05:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <inttypes.h>
|
2022-07-30 12:24:03 -04:00
|
|
|
|
2023-08-04 13:29:28 -04:00
|
|
|
#ifndef MAX_PATH
|
|
|
|
#define MAX_PATH 260
|
|
|
|
#endif
|
|
|
|
|
|
|
|
HMODULE xinput = NULL;
|
|
|
|
DWORD(WINAPI* getState)(DWORD, XINPUT_STATE*) = NULL;
|
|
|
|
DWORD(WINAPI* setState)(DWORD, XINPUT_VIBRATION*) = NULL;
|
|
|
|
DWORD(WINAPI* getCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*) = NULL;
|
|
|
|
DWORD(WINAPI* getDSoundAudioDeviceGuids)(DWORD, GUID*, GUID*) = NULL;
|
|
|
|
void lazyLoadXInput() {
|
|
|
|
if (xinput)
|
|
|
|
return;
|
|
|
|
char path[MAX_PATH];
|
|
|
|
GetSystemDirectoryA(path, MAX_PATH);
|
|
|
|
strcat_s(path, MAX_PATH, "\\XInput9_1_0.dll");
|
|
|
|
xinput = LoadLibraryA(path);
|
|
|
|
getState = (DWORD(WINAPI*)(DWORD, XINPUT_STATE*))GetProcAddress(xinput, "XInputGetState");
|
|
|
|
setState = (DWORD(WINAPI*)(DWORD, XINPUT_VIBRATION*))GetProcAddress(xinput, "XInputSetState");
|
|
|
|
getCapabilities = (DWORD(WINAPI*)(DWORD, DWORD, XINPUT_CAPABILITIES*))GetProcAddress(xinput, "XInputGetCapabilities");
|
|
|
|
getDSoundAudioDeviceGuids = (DWORD(WINAPI*)(DWORD, GUID*, GUID*))GetProcAddress(xinput, "XInputGetDSoundAudioDeviceGuids");
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD WINAPI xinputGetState(DWORD dwUserIndex, XINPUT_STATE* pState) {
|
|
|
|
lazyLoadXInput();
|
|
|
|
return getState(dwUserIndex, pState);
|
|
|
|
}
|
|
|
|
DWORD WINAPI xinputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration) {
|
|
|
|
lazyLoadXInput();
|
|
|
|
return setState(dwUserIndex, pVibration);
|
|
|
|
}
|
|
|
|
DWORD WINAPI xinputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities) {
|
|
|
|
lazyLoadXInput();
|
|
|
|
return getCapabilities(dwUserIndex, dwFlags, pCapabilities);
|
|
|
|
}
|
|
|
|
DWORD WINAPI xinputGetDSoundAudioDeviceGuids(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid) {
|
|
|
|
lazyLoadXInput();
|
|
|
|
return getDSoundAudioDeviceGuids(dwUserIndex, pDSoundRenderGuid, pDSoundCaptureGuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma comment(linker, "/export:XInputGetState=_xinputGetState@8")
|
|
|
|
#pragma comment(linker, "/export:XInputSetState=_xinputSetState@8")
|
|
|
|
#pragma comment(linker, "/export:XInputGetCapabilities=_xinputGetCapabilities@12")
|
|
|
|
#pragma comment(linker, "/export:XInputGetDSoundAudioDeviceGuids=_xinputGetDSoundAudioDeviceGuids@12")
|
2022-07-30 12:24:03 -04:00
|
|
|
|
2024-01-10 16:23:56 -05:00
|
|
|
unsigned int getExeTimestamp() {
|
|
|
|
HANDLE hMod = GetModuleHandleA(NULL);
|
|
|
|
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hMod;
|
|
|
|
|
|
|
|
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
|
|
|
|
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((uintptr_t)(hMod) + dosHeader->e_lfanew);
|
|
|
|
|
|
|
|
if (ntHeader->Signature == IMAGE_NT_SIGNATURE) {
|
|
|
|
return ntHeader->FileHeader.TimeDateStamp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL fileExists(char const* path) {
|
|
|
|
DWORD attrib = GetFileAttributesA(path);
|
|
|
|
|
|
|
|
return (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Table originally from this gist by absolute:
|
|
|
|
// https://gist.github.com/absoIute/ebe5da42d118109a03632c9751d86e19
|
|
|
|
|
|
|
|
#define TIMESTAMP_FOR_1_900 1419173053
|
|
|
|
#define TIMESTAMP_FOR_1_910 1419880840
|
|
|
|
#define TIMESTAMP_FOR_1_920 1421745341
|
|
|
|
#define TIMESTAMP_FOR_2_000 1440638199
|
|
|
|
#define TIMESTAMP_FOR_2_001 1440643927
|
|
|
|
#define TIMESTAMP_FOR_2_010 1443053232
|
|
|
|
#define TIMESTAMP_FOR_2_011 1443077847
|
|
|
|
#define TIMESTAMP_FOR_2_020 1443077847
|
|
|
|
#define TIMESTAMP_FOR_2_100 1484612867
|
|
|
|
#define TIMESTAMP_FOR_2_101 1484626658
|
|
|
|
#define TIMESTAMP_FOR_2_102 1484737207
|
|
|
|
#define TIMESTAMP_FOR_2_110 1510526914
|
|
|
|
#define TIMESTAMP_FOR_2_111 1510538091
|
|
|
|
#define TIMESTAMP_FOR_2_112 1510619253
|
|
|
|
#define TIMESTAMP_FOR_2_113 1511220108
|
|
|
|
#define TIMESTAMP_FOR_2_200 1702921605
|
|
|
|
#define TIMESTAMP_FOR_2_201 1704582672
|
|
|
|
#define TIMESTAMP_FOR_2_202 1704601266
|
2024-01-11 10:55:54 -05:00
|
|
|
#define TIMESTAMP_FOR_2_203 1704948277
|
2024-01-10 16:23:56 -05:00
|
|
|
|
|
|
|
#define GEODE_WRAPPER_CONCAT(x, y) x##y
|
|
|
|
#define GEODE_CONCAT(x, y) GEODE_WRAPPER_CONCAT(x, y)
|
|
|
|
|
|
|
|
// Hello future person. if this is erroring then you need to add
|
|
|
|
// the exe timestamp for whatever you set GEODE_GD_VERSION to. hope that helps!
|
|
|
|
#define TIMESTAMP GEODE_CONCAT(TIMESTAMP_FOR, GEODE_GD_VERSION_IDENTIFIER)
|
|
|
|
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE module, DWORD reason, LPVOID _) {
|
|
|
|
if (reason != DLL_PROCESS_ATTACH)
|
|
|
|
return TRUE;
|
|
|
|
DisableThreadLibraryCalls(module);
|
|
|
|
|
|
|
|
if (fileExists("Geode.dll")) {
|
2024-01-11 10:55:54 -05:00
|
|
|
unsigned int timestamp = getExeTimestamp();
|
|
|
|
if (timestamp == TIMESTAMP) {
|
2024-01-10 16:23:56 -05:00
|
|
|
// somehow, this works fine inside of dllmain :-)
|
|
|
|
// yes, even on wine.
|
|
|
|
LoadLibraryA("Geode.dll");
|
|
|
|
} else {
|
2024-01-11 10:55:54 -05:00
|
|
|
char buffer[128];
|
|
|
|
sprintf_s(buffer, sizeof(buffer), "GD version mismatch, not loading Geode. (%" PRIu32 ")", timestamp);
|
|
|
|
MessageBoxA(NULL, buffer, "Unable to load Geode!", MB_OK | MB_ICONWARNING);
|
2024-01-10 16:23:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|