Bemanitools v5.26 release
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
LIBRARY ddrhook
|
||||
|
||||
EXPORTS
|
||||
DllMain@12 @1 NONAME
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef HOOK_DINPUT_H
|
||||
#define HOOK_DINPUT_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void dinput_init(HMODULE target);
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
#include <windows.h>
|
||||
#include <initguid.h>
|
||||
|
||||
#include "ddrhook/monitor.h"
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef DDRHOOK_MASTER_H
|
||||
#define DDRHOOK_MASTER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void master_insert_hooks(HMODULE target);
|
||||
|
||||
#endif
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef HOOK_MISC_H
|
||||
#define HOOK_MISC_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void misc_insert_hooks(HMODULE target);
|
||||
|
||||
#endif
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user