Bemanitools v5.26 release

This commit is contained in:
icex2
2019-09-27 22:36:50 +02:00
commit cbd7720349
718 changed files with 62731 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
avsdlls += ddrhook
deplibs_ddrhook := \
avs \
libs_ddrhook := \
acioemu \
p3ioemu \
p3io \
hook \
hooklib \
security \
util \
eamio \
ddrio \
src_ddrhook := \
extio.c \
dllmain.c \
_com4.c \
dinput.c \
gfx.c \
guid.c \
master.c \
misc.c \
monitor.c \
p3io.c \
usbmem.c \
spike.c
+106
View File
@@ -0,0 +1,106 @@
#include <windows.h>
#include <ntdef.h>
#include <devioctl.h>
#include <ntddser.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "acioemu/addr.h"
#include "acioemu/hdxs.h"
#include "acioemu/icca.h"
#include "ddrhook/_com4.h"
#include "hook/iohook.h"
#include "p3ioemu/uart.h"
#include "util/defs.h"
#include "util/iobuf.h"
#include "util/log.h"
static struct ac_io_emu com4_ac_io_emu;
static struct ac_io_emu_hdxs com4_hdxs;
static struct ac_io_emu_icca com4_icca[2];
void com4_init(void)
{
uint8_t i;
/* This isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we intercept them. */
p3io_uart_set_path(0, L"COM4");
ac_io_emu_init(&com4_ac_io_emu, L"COM4");
ac_io_emu_hdxs_init(&com4_hdxs, &com4_ac_io_emu);
for (i = 0 ; i < lengthof(com4_icca) ; i++) {
ac_io_emu_icca_init(&com4_icca[i], &com4_ac_io_emu, i);
}
}
void com4_fini(void)
{
ac_io_emu_fini(&com4_ac_io_emu);
}
HRESULT com4_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&com4_ac_io_emu, irp)) {
return irp_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&com4_ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&com4_ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&com4_ac_io_emu, msg, 3);
break;
case 1:
ac_io_emu_icca_dispatch_request(&com4_icca[0], msg);
break;
case 2:
ac_io_emu_icca_dispatch_request(&com4_icca[1], msg);
break;
case 3:
ac_io_emu_hdxs_dispatch_request(&com4_hdxs, msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast(?) message on p3io ACIO bus?");
break;
default:
log_warning("p3io ACIO message on unhandled bus address: %d",
msg->addr);
break;
}
ac_io_emu_request_pop(&com4_ac_io_emu);
}
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef IIDXHOOK_COM4_H
#define IIDXHOOK_COM4_H
#include "hook/iohook.h"
void com4_init(void);
void com4_fini(void);
HRESULT com4_dispatch_irp(struct irp *irp);
#endif
+4
View File
@@ -0,0 +1,4 @@
LIBRARY ddrhook
EXPORTS
DllMain@12 @1 NONAME
+85
View File
@@ -0,0 +1,85 @@
#include <windows.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include <stdbool.h>
#include "hook/com-proxy.h"
#include "hook/pe.h"
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
static HRESULT STDCALL my_DirectInput8Create( HINSTANCE hinst, DWORD dwVersion,
REFIID riidltf, LPVOID * ppvOut, LPVOID punkOuter);
static HRESULT (STDCALL *real_DirectInput8Create)( HINSTANCE hinst, DWORD dwVersion,
REFIID riidltf, LPVOID * ppvOut, LPVOID punkOuter);
static const struct hook_symbol dinput_syms[] = {
{
.name = "DirectInput8Create",
.patch = my_DirectInput8Create,
.link = (void **) &real_DirectInput8Create,
},
};
static HRESULT STDCALL my_CreateDevice(
IDirectInput8W *self,
REFGUID rguid,
LPDIRECTINPUTDEVICE8W * lplpDirectInputDevice,
LPUNKNOWN pUnkOuter
) {
log_misc("IDirectInput8::CreateDevice hook hit");
return DIERR_NOINTERFACE;
}
static HRESULT STDCALL my_EnumDevices(
IDirectInput8W *self,
DWORD dwDevType,
LPDIENUMDEVICESCALLBACKW lpCallback,
LPVOID pvRef,
DWORD dwFlags
) {
log_misc("IDirectInput8::EnumDevices hook hit");
return DI_OK;
}
static HRESULT STDCALL my_DirectInput8Create( HINSTANCE hinst, DWORD dwVersion,
REFIID riidltf, LPVOID * ppvOut, LPVOID punkOuter)
{
IDirectInput8W *api;
IDirectInput8WVtbl *api_vtbl;
struct com_proxy *api_proxy;
HRESULT res;
log_info("DirectInput8Create hook hit");
res = real_DirectInput8Create(hinst, dwVersion, riidltf, (LPVOID *)&api, punkOuter);
if(res != DI_OK) {
return res;
}
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
api_vtbl = api_proxy->vptr;
api_vtbl->EnumDevices = my_EnumDevices;
api_vtbl->CreateDevice = my_CreateDevice;
*(IDirectInput8W**)ppvOut = (IDirectInput8W *)api_proxy;
return res;
}
void dinput_init(HMODULE target)
{
hook_table_apply(
target,
"dinput8.dll",
dinput_syms,
lengthof(dinput_syms));
log_info("Inserted dinput hooks into %p", target);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef HOOK_DINPUT_H
#define HOOK_DINPUT_H
#include <windows.h>
void dinput_init(HMODULE target);
#endif
+154
View File
@@ -0,0 +1,154 @@
#include <windows.h>
#include <stdbool.h>
#include "bemanitools/ddrio.h"
#include "bemanitools/eamio.h"
#include "ddrhook/_com4.h"
#include "ddrhook/extio.h"
#include "ddrhook/gfx.h"
#include "ddrhook/master.h"
#include "ddrhook/p3io.h"
#include "ddrhook/spike.h"
#include "ddrhook/usbmem.h"
#include "hook/iohook.h"
#include "hooklib/app.h"
#include "hooklib/rs232.h"
#include "imports/avs.h"
#include "p3ioemu/emu.h"
#include "util/cmdline.h"
#include "util/defs.h"
#include "util/log.h"
static bool my_dll_entry_init(char *sidcode, struct property_node *param);
static bool my_dll_entry_main(void);
bool standard_def;
bool _15khz;
static const irp_handler_t ddrhook_handlers[] = {
p3io_emu_dispatch_irp,
extio_dispatch_irp,
spike_dispatch_irp,
usbmem_dispatch_irp,
com4_dispatch_irp,
};
static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{
int argc;
char **argv;
bool ok;
int i;
log_info("--- Begin ddrhook dll_entry_init ---");
args_recover(&argc, &argv);
for (i = 1 ; i < argc ; i++) {
if (argv[i][0] != '-') {
continue;
}
switch (argv[i][1]) {
case 'o':
standard_def = true;
break;
case 'w':
gfx_set_windowed();
break;
}
}
args_free(argc, argv);
iohook_init(ddrhook_handlers, lengthof(ddrhook_handlers));
rs232_hook_init();
master_insert_hooks(NULL);
p3io_ddr_init();
extio_init();
usbmem_init();
spike_init();
com4_init();
log_info("Initializing DDR IO backend");
ddr_io_set_loggers(
log_body_misc,
log_body_info,
log_body_warning,
log_body_fatal);
ok = ddr_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy);
if (!ok) {
return false;
}
log_info("Initializing card reader backend");
eam_io_set_loggers(
log_body_misc,
log_body_info,
log_body_warning,
log_body_fatal);
ok = eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy);
if (!ok) {
return false;
}
log_info("--- End ddrhook dll_entry_init ---");
return app_hook_invoke_init(sidcode, param);
}
static bool my_dll_entry_main(void)
{
bool result;
result = app_hook_invoke_main();
log_misc("Shutting down card reader backend");
eam_io_fini();
log_misc("Shutting down DDR IO backend");
ddr_io_fini();
com4_fini();
spike_fini();
usbmem_fini();
extio_fini();
p3io_emu_fini();
return result;
}
BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx)
{
if (reason != DLL_PROCESS_ATTACH) {
goto end;
}
log_to_external(
log_body_misc,
log_body_info,
log_body_warning,
log_body_fatal);
app_hook_init(my_dll_entry_init, my_dll_entry_main);
end:
return TRUE;
}
+156
View File
@@ -0,0 +1,156 @@
#include <windows.h>
#include <ntdef.h>
#include <devioctl.h>
#include <ntddser.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "bemanitools/ddrio.h"
#include "hook/iohook.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
static HRESULT extio_open(struct irp *irp);
static HRESULT extio_close(struct irp *irp);
static HRESULT extio_write(struct irp *irp);
static HRESULT extio_read(struct irp *irp);
static HRESULT extio_ioctl(struct irp *irp);
static HANDLE extio_fd;
static bool extio_pending;
void extio_init(void)
{
log_assert(extio_fd == NULL);
extio_fd = iohook_open_dummy_fd();
}
void extio_fini(void)
{
if (extio_fd != NULL) {
CloseHandle(extio_fd);
}
extio_fd = NULL;
}
HRESULT extio_dispatch_irp(struct irp *irp)
{
log_assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != extio_fd) {
return irp_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN: return extio_open(irp);
case IRP_OP_CLOSE: return extio_close(irp);
case IRP_OP_READ: return extio_read(irp);
case IRP_OP_WRITE: return extio_write(irp);
case IRP_OP_IOCTL: return extio_ioctl(irp);
default: return E_NOTIMPL;
}
}
static HRESULT extio_open(struct irp *irp)
{
log_assert(irp != NULL);
if (!wstr_eq(irp->open_filename, L"COM1")) {
return irp_invoke_next(irp);
}
log_info("EXTIO RS232 port opened");
irp->fd = extio_fd;
return S_OK;
}
static HRESULT extio_close(struct irp *irp)
{
log_info("EXTIO RS232 port closed");
return S_OK;
}
static HRESULT extio_write(struct irp *irp)
{
const uint32_t *lights_be;
uint32_t lights;
log_assert(irp != NULL);
log_assert(irp->write.bytes != NULL);
if (irp->write.nbytes >= sizeof(lights)) {
lights_be = (const uint32_t *) irp->write.bytes;
lights = _byteswap_ulong(*lights_be);
ddr_io_set_lights_extio(lights);
extio_pending = true;
} else {
log_warning("Short EXTIO write");
}
irp->write.pos = irp->write.nbytes;
return S_OK;
}
static HRESULT extio_read(struct irp *irp)
{
log_assert(irp != NULL);
log_assert(irp->read.bytes != NULL);
if (extio_pending && irp->read.nbytes > 0) {
irp->read.bytes[0] = 0x11;
irp->read.pos = 1;
extio_pending = false;
}
return S_OK;
}
static HRESULT extio_ioctl(struct irp *irp)
{
SERIAL_STATUS *status;
log_assert(irp != NULL);
switch (irp->ioctl) {
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
return E_INVALIDARG;
}
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = extio_pending ? 1 : 0;
irp->read.pos = sizeof(*status);
break;
default:
break;
}
return S_OK;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef DDRHOOK_EXTIO_H
#define DDRHOOK_EXTIO_H
#include <windows.h>
#include "hook/iohook.h"
void extio_init(void);
void extio_fini(void);
HRESULT extio_dispatch_irp(struct irp *irp);
#endif
+89
View File
@@ -0,0 +1,89 @@
#include <windows.h>
#include <d3d9.h>
#include <stdbool.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
static HRESULT STDCALL my_CreateDevice(
IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, HWND hwnd,
DWORD flags, D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev);
static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver);
static IDirect3D9 * (STDCALL *real_Direct3DCreate9)(
UINT sdk_ver);
static bool gfx_windowed;
static const struct hook_symbol gfx_d3d9_hook_syms[] = {
{
.name = "Direct3DCreate9",
.patch = my_Direct3DCreate9,
.link = (void **) &real_Direct3DCreate9,
},
};
static HRESULT STDCALL my_CreateDevice(
IDirect3D9 *self,
UINT adapter,
D3DDEVTYPE type,
HWND hwnd,
DWORD flags,
D3DPRESENT_PARAMETERS *pp,
IDirect3DDevice9 **pdev)
{
IDirect3D9 *real;
real = COM_PROXY_UNWRAP(self);
if (gfx_windowed) {
pp->Windowed = TRUE;
pp->FullScreen_RefreshRateInHz = 0;
}
return IDirect3D9_CreateDevice(real, adapter, type, hwnd, flags, pp, pdev);
}
static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver)
{
IDirect3D9 *api;
IDirect3D9Vtbl *api_vtbl;
struct com_proxy *api_proxy;
log_info("Direct3DCreate9 hook hit");
api = real_Direct3DCreate9(sdk_ver);
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
api_vtbl = api_proxy->vptr;
api_vtbl->CreateDevice = my_CreateDevice;
return (IDirect3D9 *) api_proxy;
}
void gfx_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"d3d9.dll",
gfx_d3d9_hook_syms,
lengthof(gfx_d3d9_hook_syms));
log_info("Inserted graphics hooks");
}
bool gfx_get_windowed(void)
{
return gfx_windowed;
}
void gfx_set_windowed(void)
{
gfx_windowed = true;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef DDRHOOK_GFX_H
#define DDRHOOK_GFX_H
#include <windows.h>
#include <stdbool.h>
void gfx_insert_hooks(HMODULE target);
bool gfx_get_windowed(void);
void gfx_set_windowed(void);
#endif
+4
View File
@@ -0,0 +1,4 @@
#include <windows.h>
#include <initguid.h>
#include "ddrhook/monitor.h"
+69
View File
@@ -0,0 +1,69 @@
#include "ddrhook/dinput.h"
#include "ddrhook/gfx.h"
#include "ddrhook/master.h"
#include "ddrhook/misc.h"
#include "ddrhook/monitor.h"
#include "hook/table.h"
#include "p3ioemu/devmgr.h"
#include "util/defs.h"
#include "util/log.h"
static HMODULE (STDCALL *real_LoadLibraryA)(const char *name);
static HMODULE STDCALL my_LoadLibraryA(const char *name);
static const struct hook_symbol master_kernel32_syms[] = {
{
.name = "LoadLibraryA",
.patch = my_LoadLibraryA,
.link = (void **) &real_LoadLibraryA,
},
};
static HMODULE STDCALL my_LoadLibraryA(const char *name)
{
HMODULE result;
result = GetModuleHandleA(name);
if (result != NULL) {
log_misc("LoadLibraryA(%s) -> %p [already loaded]", name, result);
return result;
}
result = real_LoadLibraryA(name);
log_misc("LoadLibraryA(%s) -> %p [newly loaded]", name, result);
if (result == NULL) {
return result;
}
master_insert_hooks(result);
return result;
}
void master_insert_hooks(HMODULE target)
{
/* Insert all other hooks here */
p3io_setupapi_insert_hooks(target);
monitor_setupapi_insert_hooks(target);
misc_insert_hooks(target);
dinput_init(target);
gfx_insert_hooks(target);
/* Insert dynamic loader hooks so that we can hook late-loaded modules */
hook_table_apply(
target,
"kernel32.dll",
master_kernel32_syms,
lengthof(master_kernel32_syms));
log_info("Inserted dynamic loader hooks into %p", target);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef DDRHOOK_MASTER_H
#define DDRHOOK_MASTER_H
#include <windows.h>
void master_insert_hooks(HMODULE target);
#endif
+232
View File
@@ -0,0 +1,232 @@
#include <windows.h>
#include <stdint.h>
#include "ddrhook/gfx.h"
#include "hook/pe.h"
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
static LONG (STDCALL *real_ChangeDisplaySettingsExA)(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
static LRESULT (STDCALL *real_SendMessageW)(
HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static HWND (STDCALL *real_CreateWindowExW)(DWORD dwExStyle, LPCWSTR lpClassName,
LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth,
int nHeight, HWND hWndParent, HMENU hMenu,
HINSTANCE hInstance, LPVOID lpParam);
static LONG (STDCALL *real_SetWindowLongW)(HWND hWnd, int nIndex, LONG dwNewLong);
static BOOL (STDCALL *real_SetWindowPos)(HWND hWnd, HWND hWndInsertAfter,
int X, int Y, int cx, int cy, UINT uFlags);
static LONG STDCALL my_ChangeDisplaySettingsExA(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
static SHORT STDCALL my_GetKeyState(int vk);
static LRESULT STDCALL my_SendMessageW(
HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static HWND STDCALL my_CreateWindowExA(
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
HINSTANCE hInstance, LPVOID lpParam);
static HWND STDCALL my_CreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassName,
LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth,
int nHeight, HWND hWndParent, HMENU hMenu,
HINSTANCE hInstance, LPVOID lpParam);
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong);
static BOOL STDCALL my_SetWindowPos(HWND hWnd, HWND hWndInsertAfter,
int X, int Y, int cx, int cy, UINT uFlags);
static const struct hook_symbol misc_user32_syms[] = {
{
.name = "ChangeDisplaySettingsExA",
.patch = my_ChangeDisplaySettingsExA,
.link = (void **) &real_ChangeDisplaySettingsExA,
},
{
.name = "SendMessageW",
.patch = my_SendMessageW,
.link = (void **) &real_SendMessageW,
},
{
.name = "GetKeyState",
.patch = my_GetKeyState,
},
{
.name = "CreateWindowExA",
.patch = my_CreateWindowExA,
},
{
.name = "CreateWindowExW",
.patch = my_CreateWindowExW,
.link = (void **) &real_CreateWindowExW,
},
{
.name = "SetWindowLongW",
.patch = my_SetWindowLongW,
.link = (void **) &real_SetWindowLongW,
},
{
.name = "SetWindowPos",
.patch = my_SetWindowPos,
.link = (void **) &real_SetWindowPos,
},
};
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong) {
if(nIndex == GWL_STYLE)
dwNewLong |= WS_OVERLAPPEDWINDOW;
return real_SetWindowLongW(hWnd, nIndex, dwNewLong);
}
static BOOL STDCALL my_SetWindowPos(HWND hWnd, HWND hWndInsertAfter,
int X, int Y, int cx, int cy, UINT uFlags) {
return true;
}
static LONG STDCALL my_ChangeDisplaySettingsExA(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param)
{
if (gfx_get_windowed()) {
return DISP_CHANGE_SUCCESSFUL;
} else {
return real_ChangeDisplaySettingsExA(dev_name, dev_mode, hwnd, flags,
param);
}
}
static void calc_win_size_with_framed(HWND hwnd, DWORD x, DWORD y, DWORD width,
DWORD height, LPWINDOWPOS wp)
{
/* taken from dxwnd */
RECT rect;
DWORD style;
int max_x, max_y;
HMENU menu;
rect.left = x;
rect.top = y;
max_x = width;
max_y = height;
rect.right = x + max_x;
rect.bottom = y + max_y;
style = GetWindowLong(hwnd, GWL_STYLE);
menu = GetMenu(hwnd);
AdjustWindowRect(&rect, style, (menu != NULL));
/* shift down-right so that the border is visible
and also update the iPosX,iPosY upper-left coordinates
of the client area */
if (rect.left < 0) {
rect.right -= rect.left;
rect.left = 0;
}
if (rect.top < 0) {
rect.bottom -= rect.top;
rect.top = 0;
}
wp->x = rect.left;
wp->y = rect.top;
wp->cx = rect.right - rect.left;
wp->cy = rect.bottom - rect.top;
}
static HWND STDCALL my_CreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassName,
LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth,
int nHeight, HWND hWndParent, HMENU hMenu,
HINSTANCE hInstance, LPVOID lpParam)
{
if (gfx_get_windowed()) {
/* use a different style */
dwStyle |= WS_OVERLAPPEDWINDOW;
/* also show mouse cursor */
ShowCursor(TRUE);
}
if(!lpWindowName)
lpWindowName = L"Dance Dance Revolution";
HWND hwnd = real_CreateWindowExW(dwExStyle, lpClassName, lpWindowName,
dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance,
lpParam);
if (hwnd == INVALID_HANDLE_VALUE) {
return hwnd;
}
if (gfx_get_windowed()) {
/* we have to adjust the window size, because the window needs to be a
slightly bigger than the rendering resolution (window caption and
stuff is included in the window size) */
WINDOWPOS wp;
calc_win_size_with_framed(hwnd, X, Y, nWidth, nHeight, &wp);
SetWindowPos(hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, 0);
X = wp.x;
Y = wp.y;
nWidth = wp.cx;
nHeight = wp.cy;
}
return hwnd;
}
static HWND STDCALL my_CreateWindowExA(
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
HINSTANCE hInstance, LPVOID lpParam)
{
LPWSTR longWindowName = NULL;
LPWSTR longClassName = NULL;
if(lpWindowName)
longWindowName = str_widen(lpWindowName);
if(lpClassName)
longClassName = str_widen(lpClassName);
HWND ret = my_CreateWindowExW(dwExStyle, longClassName, longWindowName,
dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
if(longWindowName)
free(longWindowName);
if(longClassName)
free(longClassName);
return ret;
}
static SHORT STDCALL my_GetKeyState(int vk)
{
/* yeah we kinda have our own keyboard input thing */
return 0;
}
static LRESULT STDCALL my_SendMessageW(
HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (hwnd == HWND_BROADCAST) {
/* OK COOL STORY BRO */
log_misc("Dropping message sent to HWND_BROADCAST");
return TRUE;
} else {
return real_SendMessageW(hwnd, msg, wparam, lparam);
}
}
void misc_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"user32.dll",
misc_user32_syms,
lengthof(misc_user32_syms));
log_info("Inserted miscellaneous hooks into %p", target);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef HOOK_MISC_H
#define HOOK_MISC_H
#include <windows.h>
void misc_insert_hooks(HMODULE target);
#endif
+208
View File
@@ -0,0 +1,208 @@
#include <windows.h>
#include <setupapi.h>
#include <stdbool.h>
#include <wchar.h>
#include "ddrhook/monitor.h"
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
/* Link pointers */
static HDEVINFO (WINAPI *next_SetupDiGetClassDevsW)(
const GUID *class_guid,
const wchar_t *enumerator,
HWND hwnd,
DWORD flags);
static BOOL (WINAPI *next_SetupDiEnumDeviceInfo)(
HDEVINFO dev_info,
DWORD index,
SP_DEVINFO_DATA *info_data);
static BOOL (WINAPI *next_SetupDiGetDeviceRegistryPropertyA)(
HDEVINFO dev_info,
SP_DEVINFO_DATA *info_data,
DWORD prop,
DWORD *reg_type,
BYTE *bytes,
DWORD nbytes,
DWORD *need_nbytes);
static BOOL (WINAPI *next_SetupDiDestroyDeviceInfoList)(HDEVINFO dev_info);
/* API hooks */
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
const GUID *class_guid,
const wchar_t *enumerator,
HWND hwnd,
DWORD flags);
static BOOL WINAPI my_SetupDiEnumDeviceInfo(
HDEVINFO dev_info,
DWORD index,
SP_DEVINFO_DATA *info_data);
static BOOL WINAPI my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO dev_info,
SP_DEVINFO_DATA *info_data,
DWORD prop,
DWORD *reg_type,
BYTE *bytes,
DWORD nbytes,
DWORD *need_nbytes);
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO dev_info);
static const struct hook_symbol monitor_setupapi_syms[] = {
{
.name = "SetupDiGetClassDevsW",
.patch = my_SetupDiGetClassDevsW,
.link = (void **) &next_SetupDiGetClassDevsW,
}, {
.name = "SetupDiEnumDeviceInfo",
.patch = my_SetupDiEnumDeviceInfo,
.link = (void **) &next_SetupDiEnumDeviceInfo,
}, {
.name = "SetupDiGetDeviceRegistryPropertyA",
.patch = my_SetupDiGetDeviceRegistryPropertyA,
.link = (void **) &next_SetupDiGetDeviceRegistryPropertyA,
}, {
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
.link = (void **) &next_SetupDiDestroyDeviceInfoList,
},
};
extern bool standard_def;
static HDEVINFO monitor_hdevinfo;
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
const GUID *class_guid,
const wchar_t *enumerator,
HWND hwnd,
DWORD flags)
{
HDEVINFO result;
result = next_SetupDiGetClassDevsW(class_guid, enumerator, hwnd, flags);
if ( result != INVALID_HANDLE_VALUE &&
IsEqualGUID(class_guid, &monitor_guid)) {
monitor_hdevinfo = result;
}
return result;
}
static BOOL WINAPI my_SetupDiEnumDeviceInfo(
HDEVINFO dev_info,
DWORD index,
SP_DEVINFO_DATA *info_data)
{
if (dev_info != monitor_hdevinfo) {
return next_SetupDiEnumDeviceInfo(dev_info, index, info_data);
}
if (info_data == NULL || info_data->cbSize != sizeof(*info_data)) {
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
if (index > 0) {
SetLastError(ERROR_NO_MORE_ITEMS);
return FALSE;
}
SetLastError(ERROR_SUCCESS);
return TRUE;
}
static BOOL WINAPI my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO dev_info,
SP_DEVINFO_DATA *info_data,
DWORD prop,
DWORD *reg_type,
BYTE *bytes,
DWORD nbytes,
DWORD *nbytes_out)
{
const char *txt;
size_t txt_nbytes;
if (dev_info != monitor_hdevinfo) {
return next_SetupDiGetDeviceRegistryPropertyA(
dev_info,
info_data,
prop,
reg_type,
bytes,
nbytes,
nbytes_out);
}
/* The only implemented property */
log_assert(prop == SPDRP_DEVICEDESC);
if (standard_def) {
txt = "Generic Television";
} else {
txt = "Generic Monitor";
}
txt_nbytes = strlen(txt) + 1;
if (reg_type != NULL) {
*reg_type = REG_SZ;
}
if (nbytes_out != NULL) {
*nbytes_out = txt_nbytes;
}
if (nbytes < txt_nbytes) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
if (bytes == NULL) {
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
str_cpy((char *) bytes, nbytes, txt);
SetLastError(ERROR_SUCCESS);
return TRUE;
}
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO dev_info)
{
if (dev_info == monitor_hdevinfo) {
monitor_hdevinfo = NULL;
}
return next_SetupDiDestroyDeviceInfoList(dev_info);
}
void monitor_setupapi_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"setupapi.dll",
monitor_setupapi_syms,
lengthof(monitor_setupapi_syms));
log_info("Inserted monitor setupapi hooks into %p", target);
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef DDRHOOK_MONITOR_H
#define DDRHOOK_MONITOR_H
#include <windows.h>
DEFINE_GUID(
monitor_guid,
0x4D36E96E,
0xE325,
0x11CE,
0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
void monitor_setupapi_insert_hooks(HMODULE target);
#endif
+79
View File
@@ -0,0 +1,79 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "bemanitools/ddrio.h"
#include "ddrhook/p3io.h"
#include "p3ioemu/emu.h"
#include "p3ioemu/uart.h"
#include "util/log.h"
extern bool _15khz;
extern bool standard_def;
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state);
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs);
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type);
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq);
static const struct p3io_ops p3io_ddr_ops = {
.read_jamma = p3io_ddr_read_jamma,
.set_outputs = p3io_ddr_set_outputs,
.get_cab_type = p3io_ddr_get_cab_type,
.get_video_freq = p3io_ddr_get_video_freq,
};
void p3io_ddr_init(void)
{
p3io_emu_init(&p3io_ddr_ops, NULL);
}
void p3io_ddr_fini(void)
{
p3io_emu_fini();
}
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state)
{
log_assert(state != NULL);
*state = ddr_io_read_pad();
return S_OK;
}
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs)
{
ddr_io_set_lights_p3io(outputs);
return S_OK;
}
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type)
{
if (standard_def) {
*type = P3IO_CAB_TYPE_SD;
} else {
*type = P3IO_CAB_TYPE_HD;
}
return S_OK;
}
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq)
{
if (_15khz) {
*freq = P3IO_VIDEO_FREQ_15KHZ;
} else {
*freq = P3IO_VIDEO_FREQ_31KHZ;
}
return S_OK;
}
// TODO coinstock
// TODO round plug
+14
View File
@@ -0,0 +1,14 @@
#ifndef DDRHOOK_P3IO_H
#define DDRHOOK_P3IO_H
#include <windows.h>
#include "hook/iohook.h"
extern const wchar_t p3io_dev_node_prefix[];
extern const wchar_t p3io_dev_node[];
void p3io_ddr_init(void);
void p3io_ddr_fini(void);
#endif
+172
View File
@@ -0,0 +1,172 @@
#define LOG_MODULE "spike"
#include <windows.h>
#include <ntdef.h>
#include <devioctl.h>
#include <ntddser.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "acioemu/addr.h"
#include "acioemu/emu.h"
#include "hook/iohook.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu spike_ac_io_emu;
static void spike_handle_broadcast(const struct ac_io_message *bcast);
static void spike_handle_get_version(const struct ac_io_message *req);
static void spike_handle_status(const struct ac_io_message *req);
static void spike_send_empty(const struct ac_io_message *req);
void spike_init(void)
{
ac_io_emu_init(&spike_ac_io_emu, L"COM2");
}
void spike_fini(void)
{
ac_io_emu_fini(&spike_ac_io_emu);
}
HRESULT spike_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&spike_ac_io_emu, irp)) {
return irp_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&spike_ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&spike_ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&spike_ac_io_emu, msg, 7);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
switch (ac_io_u16(msg->cmd.code)) {
case AC_IO_CMD_GET_VERSION:
spike_handle_get_version(msg);
break;
case AC_IO_CMD_START_UP:
spike_handle_status(msg);
break;
case AC_IO_CMD_KEEPALIVE:
spike_send_empty(msg);
break;
case 0x100:
case 0x110:
case 0x112:
case 0x128:
spike_handle_status(msg);
break;
default:
log_warning("Spike ACIO unhandled cmd: %04X",
ac_io_u16(msg->cmd.code));
}
break;
case AC_IO_BROADCAST:
spike_handle_broadcast(msg);
break;
default:
log_warning(
"Spike ACIO message on unhandled bus address: %d",
msg->addr);
break;
}
ac_io_emu_request_pop(&spike_ac_io_emu);
}
}
static void spike_handle_broadcast(const struct ac_io_message *bcast)
{
/* The payload consists of 7x10 byte chunks. Chunk 0 seems to correspond
to the front LED strip, and chunks 1-6 are the 2x3 spike bundles on the
side of a dedicab. No idea about the format of this data other than
that, try figuring it out if you're bored. */
}
static void spike_handle_get_version(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_LED_SPIKE);
resp.cmd.version.flag = 0x00;
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x01;
resp.cmd.version.revision = 0x00;
memcpy(resp.cmd.version.product_code, "DDRS",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
static void spike_handle_status(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.status);
resp.cmd.status = 0x00;
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
static void spike_send_empty(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = 0;
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef DDRHOOK_SPIKE_H
#define DDRHOOK_SPIKE_H
#include <windows.h>
#include "hook/iohook.h"
void spike_init(void);
void spike_fini(void);
HRESULT spike_dispatch_irp(struct irp *irp);
#endif
+190
View File
@@ -0,0 +1,190 @@
#define LOG_MODULE "usbmem"
#include <windows.h>
#include <ntdef.h>
#include <devioctl.h>
#include <ntddser.h>
#include <stdbool.h>
#include <string.h>
#include <wchar.h>
#include "hook/iohook.h"
#include "util/log.h"
#include "util/iobuf.h"
#include "util/str.h"
#define USBMEM_BUF_SIZE 128
static HANDLE usbmem_fd;
static char usbmem_response[USBMEM_BUF_SIZE];
static bool usbmem_pending;
static HRESULT usbmem_open(struct irp *irp);
static HRESULT usbmem_close(struct irp *irp);
static HRESULT usbmem_write(struct irp *irp);
static HRESULT usbmem_read(struct irp *irp);
static HRESULT usbmem_ioctl(struct irp *irp);
void usbmem_init(void)
{
log_assert(usbmem_fd == NULL);
usbmem_fd = iohook_open_dummy_fd();
}
void usbmem_fini(void)
{
if (usbmem_fd != NULL) {
CloseHandle(usbmem_fd);
}
usbmem_fd = NULL;
}
HRESULT usbmem_dispatch_irp(struct irp *irp)
{
log_assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != usbmem_fd) {
return irp_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN: return usbmem_open(irp);
case IRP_OP_CLOSE: return usbmem_close(irp);
case IRP_OP_READ: return usbmem_read(irp);
case IRP_OP_WRITE: return usbmem_write(irp);
case IRP_OP_IOCTL: return usbmem_ioctl(irp);
default: return E_NOTIMPL;
}
}
static HRESULT usbmem_open(struct irp *irp)
{
log_assert(irp != NULL);
if (!wstr_eq(irp->open_filename, L"COM3")) {
return irp_invoke_next(irp);
}
irp->fd = usbmem_fd;
log_info("USB edit data PCB opened");
return S_OK;
}
static HRESULT usbmem_close(struct irp *irp)
{
log_info("USB edit data PCB closed");
return S_OK;
}
static HRESULT usbmem_write(struct irp *irp)
{
struct const_iobuf *src;
char request[USBMEM_BUF_SIZE];
uint32_t nbytes;
log_assert(irp != NULL);
log_assert(irp->write.bytes != NULL);
src = &irp->write;
nbytes = src->nbytes > USBMEM_BUF_SIZE ? USBMEM_BUF_SIZE : src->nbytes;
memcpy(request, src->bytes, nbytes);
request[nbytes - 1] = '\0'; /* This is always a CR. */
log_misc(">%s", request);
if (strlen(request) > 0) {
if (str_eq(request, "sver")) {
str_cpy(usbmem_response,
sizeof(usbmem_response),
"done GQHDXJAA DJHACKRS");
} else if (
str_eq(request, "on_a") ||
str_eq(request, "on_b") ||
str_eq(request, "offa") ||
str_eq(request, "offb") ) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else if (
strncmp(request, "lma ", 4) == 0 ||
strncmp(request, "lmb ", 4) == 0) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else {
str_cpy(usbmem_response, sizeof(usbmem_response), "not connected");
}
}
usbmem_pending = true;
src->pos = nbytes;
return S_OK;
}
static HRESULT usbmem_read(struct irp *irp)
{
struct iobuf *dest;
uint32_t rlength;
log_assert(irp != NULL);
log_assert(irp->read.bytes != NULL);
dest = &irp->read;
if (usbmem_pending) {
if (strlen(usbmem_response) > 0) {
log_misc("%s", usbmem_response);
}
str_cat(usbmem_response, sizeof(usbmem_response), "\r>");
usbmem_pending = false;
}
rlength = strlen(usbmem_response);
memcpy(dest->bytes, usbmem_response, rlength);
memset(usbmem_response, 0, USBMEM_BUF_SIZE);
dest->pos = rlength;
return S_OK;
}
static HRESULT usbmem_ioctl(struct irp *irp)
{
SERIAL_STATUS *status;
log_assert(irp != NULL);
switch (irp->ioctl) {
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
return E_INVALIDARG;
}
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = usbmem_pending ? 1 : 0;
irp->read.pos = sizeof(*status);
break;
default:
break;
}
return S_OK;
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef HOOK_USBMEM_H
#define HOOK_USBMEM_H
void usbmem_init(void);
void usbmem_fini(void);
HRESULT usbmem_dispatch_irp(struct irp *irp);
#endif