1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2024-11-28 00:10:51 +01:00

bio2emu: Refactor out the BIO2 emulation code so that it can be reused

Also make it support multiple BIO2 devices if needed (DRS)
This commit is contained in:
Will Xyen 2019-10-12 04:17:06 -04:00
parent 073392407a
commit e495bfb8f1
14 changed files with 530 additions and 427 deletions

View File

@ -74,6 +74,7 @@ imps += avs avs-ea3
include src/main/aciodrv/Module.mk include src/main/aciodrv/Module.mk
include src/main/acioemu/Module.mk include src/main/acioemu/Module.mk
include src/main/aciotest/Module.mk include src/main/aciotest/Module.mk
include src/main/bio2emu/Module.mk
include src/main/bsthook/Module.mk include src/main/bsthook/Module.mk
include src/main/bstio/Module.mk include src/main/bstio/Module.mk
include src/main/cconfig/Module.mk include src/main/cconfig/Module.mk

View File

@ -0,0 +1,8 @@
libs += bio2emu
libs_bio2emu := \
acioemu \
src_bio2emu := \
emu.c \
setupapi.c \

107
src/main/bio2emu/emu.c Normal file
View File

@ -0,0 +1,107 @@
#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/emu.h"
#include "hook/iohook.h"
#include "hooklib/rs232.h"
#include "bio2emu/emu.h"
#include "bio2emu/setupapi.h"
#include "imports/avs.h"
#include "util/defs.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
#include "util/array.h"
static struct array bio2_active_ports;
void bio2emu_init_start()
{
array_init(&bio2_active_ports);
}
void bio2emu_init_end()
{
bio2emu_setupapi_hook_init(&bio2_active_ports);
}
void bio2emu_port_init(struct bio2emu_port* bio2_emu)
{
// BIO2 seems like ACIO with just 1 device
ac_io_emu_init(&bio2_emu->acio, bio2_emu->wport);
rs232_hook_add_fd(bio2_emu->acio.fd);
*array_append(struct bio2emu_port*, &bio2_active_ports) = bio2_emu;
}
void bio2emu_port_fini(struct bio2emu_port* bio2_emu)
{
ac_io_emu_fini(&bio2_emu->acio);
}
HRESULT bio2emu_port_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
struct bio2emu_port* check = NULL;
struct bio2emu_port* selected_emu = NULL;
for (size_t i = 0 ; i < bio2_active_ports.nitems ; i++) {
check = *array_item(struct bio2emu_port*, &bio2_active_ports, i);
if (ac_io_emu_match_irp(&check->acio, irp)) {
selected_emu = check;
}
}
if (!selected_emu) {
return irp_invoke_next(irp);
}
struct ac_io_emu* emu = &selected_emu->acio;
for (;;) {
hr = ac_io_emu_dispatch_irp(emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(emu, msg, 1);
break;
case 1:
selected_emu->dispatcher(selected_emu, msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast(?) message on BIO2 bus?");
break;
default:
log_warning("BIO2 message on unhandled bus address: %d", msg->addr);
break;
}
ac_io_emu_request_pop(emu);
}
}

28
src/main/bio2emu/emu.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef BIO2EMU_H
#define BIO2EMU_BIO2EMU_H
#include "hook/iohook.h"
#include "acioemu/emu.h"
struct bio2emu_port;
struct ac_io_message;
typedef void (*bio2_bi2a_dispatcher)(struct bio2emu_port *emu, const struct ac_io_message *req);
struct bio2emu_port {
struct ac_io_emu acio;
const char* port;
const wchar_t* wport;
bio2_bi2a_dispatcher dispatcher;
};
void bio2emu_init_start();
void bio2emu_init_end();
void bio2emu_port_init(struct bio2emu_port* bio2emu_emu);
void bio2emu_port_fini(struct bio2emu_port* bio2emu_emu);
HRESULT bio2emu_port_dispatch_irp(struct irp *irp);
#endif

327
src/main/bio2emu/setupapi.c Normal file
View File

@ -0,0 +1,327 @@
#define LOG_MODULE "setupapi-hook"
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include "hook/table.h"
#include "bio2emu/setupapi.h"
#include "bio2emu/emu.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
#define MAX_INSTANCES_HOOKED 8
static struct array* bio2_assigned_ports = NULL;
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
);
static BOOL (*real_SetupDiDestroyDeviceInfoList)(
HDEVINFO DeviceInfoSet
);
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static BOOL (*real_SetupDiEnumDeviceInfo)(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static HKEY my_SetupDiOpenDevRegKey(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
);
static HKEY (*real_SetupDiOpenDevRegKey)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
);
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static BOOL (*real_SetupDiGetDeviceRegistryPropertyA)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static BOOL my_SetupDiGetDeviceInfoListDetailA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
);
static BOOL (*real_SetupDiGetDeviceInfoListDetailA)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
);
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static HDEVINFO(*real_SetupDiGetClassDevsA)(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static const struct hook_symbol bio2emu_setupapi_syms[] = {
{
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
.link = (void **) &real_SetupDiDestroyDeviceInfoList
},
{
.name = "SetupDiEnumDeviceInfo",
.patch = my_SetupDiEnumDeviceInfo,
.link = (void **) &real_SetupDiEnumDeviceInfo
},
{
.name = "SetupDiOpenDevRegKey",
.patch = my_SetupDiOpenDevRegKey,
.link = (void **) &real_SetupDiOpenDevRegKey
},
{
.name = "SetupDiGetDeviceRegistryPropertyA",
.patch = my_SetupDiGetDeviceRegistryPropertyA,
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA
},
{
.name = "SetupDiGetDeviceInfoListDetailA",
.patch = my_SetupDiGetDeviceInfoListDetailA,
.link = (void **) &real_SetupDiGetDeviceInfoListDetailA
},
{
.name = "SetupDiGetClassDevsA",
.patch = my_SetupDiGetClassDevsA,
.link = (void **) &real_SetupDiGetClassDevsA
},
};
static LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
static LSTATUS (*real_RegQueryValueExA)(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
static const struct hook_symbol bio2emu_Advapi32_syms[] = {
{
.name = "RegQueryValueExA",
.patch = my_RegQueryValueExA,
.link = (void **) &real_RegQueryValueExA
},
};
static void* CUSTOM_DEVICE_HANDLE;
static struct HKEY__ CUSTOM_REGISTRY_HANDLE[MAX_INSTANCES_HOOKED];
static BOOL check_if_match(HKEY ptr, HKEY base) {
return (ptr >= &base[0]) && (ptr <= &base[MAX_INSTANCES_HOOKED - 1]);
}
static size_t get_match_index(HKEY ptr, HKEY base) {
for (size_t i = 0; i < MAX_INSTANCES_HOOKED; ++i) {
if (ptr == &base[i]) {
return i;
}
}
return -1;
}
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
){
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
){
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
log_info("%s: Loaded idx %ld", __FUNCTION__, MemberIndex);
if (MemberIndex < MAX_INSTANCES_HOOKED) {
DeviceInfoData->DevInst = MemberIndex;
return true;
}
return false;
}
return real_SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, DeviceInfoData);
}
static HKEY my_SetupDiOpenDevRegKey(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
){
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
if (DeviceInfoData->DevInst < MAX_INSTANCES_HOOKED){
log_info("%s: matched instance", __FUNCTION__);
return &CUSTOM_REGISTRY_HANDLE[DeviceInfoData->DevInst];
}
}
return real_SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired);
}
static const char DEVICE_PROPERTY_VALUE[] = "BIO2(VIDEO)(";
static const size_t DEVICE_PROPERTY_LENGTH = 12;
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
){
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
if (DeviceInfoData->DevInst< MAX_INSTANCES_HOOKED){
struct bio2emu_port* selected_port = *array_item(struct bio2emu_port*, bio2_assigned_ports, DeviceInfoData->DevInst);
size_t portname_len = strlen(selected_port->port);
size_t required_size = (DEVICE_PROPERTY_LENGTH + portname_len + 1 + 1); // + 1 for ')', + 1 for NULL
if (PropertyBuffer && (PropertyBufferSize >= required_size)){
char* PropBuffStr = (char*)PropertyBuffer;
strcpy(PropBuffStr, DEVICE_PROPERTY_VALUE);
strcpy(PropBuffStr + DEVICE_PROPERTY_LENGTH, selected_port->port);
strcpy(PropBuffStr + DEVICE_PROPERTY_LENGTH + portname_len, ")");
log_info("%s: Done copying property name [%s]", __FUNCTION__, PropBuffStr);
} else {
log_info("%s: Returning size", __FUNCTION__);
*RequiredSize = required_size;
}
}
log_info("%s: STUB RETURN", __FUNCTION__);
return true;
}
return real_SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize);
}
static BOOL my_SetupDiGetDeviceInfoListDetailA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
){
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiGetDeviceInfoListDetailA(DeviceInfoSet, DeviceInfoSetDetailData);
}
DEFINE_GUID(GUID_COM_BUS_ENUMERATOR,
0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
){
if (ClassGuid) {
if (IsEqualGUID(ClassGuid, &GUID_COM_BUS_ENUMERATOR)){
log_info("Inside: %s", __FUNCTION__);
return &CUSTOM_DEVICE_HANDLE;
}
}
return real_SetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
}
static LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
){
if (check_if_match(hKey, CUSTOM_REGISTRY_HANDLE)){
if (strcmp(lpValueName, "PortName") == 0) {
if (lpData){
size_t portidx = get_match_index(hKey, CUSTOM_REGISTRY_HANDLE);
struct bio2emu_port* selected_port = *array_item(struct bio2emu_port*, bio2_assigned_ports, portidx);
strncpy((char*)lpData, selected_port->port, *lpcbData);
log_info("%s: Queried %s", __FUNCTION__, selected_port->port);
return ERROR_SUCCESS;
}
return ERROR_MORE_DATA;
}
}
return real_RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
}
void bio2emu_setupapi_hook_init(struct array* bio2_ports)
{
bio2_assigned_ports = bio2_ports;
hook_table_apply(
NULL,
"setupapi.dll",
bio2emu_setupapi_syms,
lengthof(bio2emu_setupapi_syms));
hook_table_apply(
NULL,
"Advapi32.dll",
bio2emu_Advapi32_syms,
lengthof(bio2emu_Advapi32_syms));
log_info("Inserted setupapi hooks");
}

View File

@ -0,0 +1,8 @@
#ifndef BIO2EMU_SETUPAPI_H
#define BIO2EMU_SETUPAPI_H
#include "util/array.h"
void bio2emu_setupapi_hook_init(struct array* bio2_ports);
#endif

View File

@ -14,6 +14,7 @@ deplibs_iidxhook8 := \
libs_iidxhook8 := \ libs_iidxhook8 := \
iidxhook-util \ iidxhook-util \
acioemu \ acioemu \
bio2emu \
iidxio \ iidxio \
hook \ hook \
hooklib \ hooklib \
@ -23,9 +24,7 @@ libs_iidxhook8 := \
src_iidxhook8 := \ src_iidxhook8 := \
bi2a.c \ bi2a.c \
bio2.c \
cam.c \ cam.c \
config-cam.c \ config-cam.c \
config-io.c \ config-io.c \
dllmain.c \ dllmain.c \
setupapi.c \

View File

@ -1,6 +1,7 @@
#define LOG_MODULE "bio2emu-bi2a" #define LOG_MODULE "bio2emu-bi2a"
#include "iidxhook8/bi2a.h" #include "iidxhook8/bi2a.h"
#include "bio2emu/emu.h"
#include <windows.h> /* for _BitScanForward */ #include <windows.h> /* for _BitScanForward */
@ -13,12 +14,11 @@
#include "bemanitools/iidxio.h" #include "bemanitools/iidxio.h"
static int get_default_slider_valid(size_t idx); static int get_default_slider_valid(size_t idx);
static void bio2_emu_bi2a_cmd_send_version(const struct ac_io_message *req); static void bio2_emu_bi2a_cmd_send_version(struct ac_io_emu *emu, const struct ac_io_message *req);
static void bio2_emu_bi2a_send_state(const struct ac_io_message *req); static void bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req);
static void bio2_emu_bi2a_send_empty(const struct ac_io_message *req); static void bio2_emu_bi2a_send_empty(struct ac_io_emu *emu, const struct ac_io_message *req);
static void bio2_emu_bi2a_send_status(const struct ac_io_message *req, uint8_t status); static void bio2_emu_bi2a_send_status(struct ac_io_emu *emu, const struct ac_io_message *req, uint8_t status);
static struct ac_io_emu *bi2a_bio2;
static int default_sliders[5]; static int default_sliders[5];
static bool poll_delay; static bool poll_delay;
@ -30,10 +30,10 @@ int get_default_slider_valid(size_t idx) {
} }
} }
void bio2_emu_bi2a_init(struct ac_io_emu *bio2_emu, bool disable_poll_limiter) void bio2_emu_bi2a_init(struct bio2emu_port *bio2_emu, bool disable_poll_limiter)
{ {
FILE* f; bio2emu_port_init(bio2_emu);
bi2a_bio2 = bio2_emu;
poll_delay = !disable_poll_limiter; poll_delay = !disable_poll_limiter;
if (!poll_delay) { if (!poll_delay) {
log_warning("bio2_emu_bi2a_init: poll_delay has been disabled"); log_warning("bio2_emu_bi2a_init: poll_delay has been disabled");
@ -43,7 +43,7 @@ void bio2_emu_bi2a_init(struct ac_io_emu *bio2_emu, bool disable_poll_limiter)
default_sliders[i] = -1; default_sliders[i] = -1;
} }
f = fopen("vefx.txt", "r"); FILE* f = fopen("vefx.txt", "r");
if (f) { if (f) {
fscanf(f, "%d %d %d %d %d", &default_sliders[0], &default_sliders[1], &default_sliders[2], &default_sliders[3], &default_sliders[4]); fscanf(f, "%d %d %d %d %d", &default_sliders[0], &default_sliders[1], &default_sliders[2], &default_sliders[3], &default_sliders[4]);
fclose(f); fclose(f);
@ -51,7 +51,7 @@ void bio2_emu_bi2a_init(struct ac_io_emu *bio2_emu, bool disable_poll_limiter)
} }
void bio2_emu_bi2a_dispatch_request(const struct ac_io_message *req) void bio2_emu_bi2a_dispatch_request(struct bio2emu_port *bio2port, const struct ac_io_message *req)
{ {
uint16_t cmd_code; uint16_t cmd_code;
@ -61,27 +61,27 @@ void bio2_emu_bi2a_dispatch_request(const struct ac_io_message *req)
case BIO2_BI2A_CMD_UNK_0100: case BIO2_BI2A_CMD_UNK_0100:
case BIO2_BI2A_CMD_UNK_0120: case BIO2_BI2A_CMD_UNK_0120:
log_misc("BIO2_BI2A_CMD_UNK_%04X(%d)", cmd_code, req->addr); log_misc("BIO2_BI2A_CMD_UNK_%04X(%d)", cmd_code, req->addr);
bio2_emu_bi2a_send_status(req, 0x00); bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
break; break;
case BIO2_BI2A_CMD_POLL: case BIO2_BI2A_CMD_POLL:
// log_misc("BIO2_BI2A_CMD_POLL"); // log_misc("BIO2_BI2A_CMD_POLL");
bio2_emu_bi2a_send_state(req); bio2_emu_bi2a_send_state(&bio2port->acio, req);
break; break;
case AC_IO_CMD_GET_VERSION: case AC_IO_CMD_GET_VERSION:
log_misc("BIO2_CMD_GET_VERSION(%d)", req->addr); log_misc("BIO2_CMD_GET_VERSION(%d)", req->addr);
bio2_emu_bi2a_cmd_send_version(req); bio2_emu_bi2a_cmd_send_version(&bio2port->acio, req);
break; break;
case AC_IO_CMD_START_UP: case AC_IO_CMD_START_UP:
log_misc("BIO2_CMD_START_UP(%d)", req->addr); log_misc("BIO2_CMD_START_UP(%d)", req->addr);
bio2_emu_bi2a_send_status(req, 0x00); bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
break; break;
case AC_IO_CMD_KEEPALIVE: case AC_IO_CMD_KEEPALIVE:
log_misc("BIO2_CMD_KEEPALIVE(%d)", req->addr); log_misc("BIO2_CMD_KEEPALIVE(%d)", req->addr);
bio2_emu_bi2a_send_empty(req); bio2_emu_bi2a_send_empty(&bio2port->acio, req);
break; break;
default: default:
@ -90,7 +90,7 @@ void bio2_emu_bi2a_dispatch_request(const struct ac_io_message *req)
} }
} }
static void bio2_emu_bi2a_cmd_send_version(const struct ac_io_message *req) static void bio2_emu_bi2a_cmd_send_version(struct ac_io_emu *emu, const struct ac_io_message *req)
{ {
struct ac_io_message resp; struct ac_io_message resp;
@ -108,10 +108,10 @@ static void bio2_emu_bi2a_cmd_send_version(const struct ac_io_message *req)
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date)); strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time)); strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
ac_io_emu_response_push(bi2a_bio2, &resp, 0); ac_io_emu_response_push(emu, &resp, 0);
} }
static void bio2_emu_bi2a_send_empty(const struct ac_io_message *req) static void bio2_emu_bi2a_send_empty(struct ac_io_emu *emu, const struct ac_io_message *req)
{ {
struct ac_io_message resp; struct ac_io_message resp;
@ -120,10 +120,10 @@ static void bio2_emu_bi2a_send_empty(const struct ac_io_message *req)
resp.cmd.seq_no = req->cmd.seq_no; resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = 0; resp.cmd.nbytes = 0;
ac_io_emu_response_push(bi2a_bio2, &resp, 0); ac_io_emu_response_push(emu, &resp, 0);
} }
static void bio2_emu_bi2a_send_status(const struct ac_io_message *req, uint8_t status) static void bio2_emu_bi2a_send_status(struct ac_io_emu *emu, const struct ac_io_message *req, uint8_t status)
{ {
struct ac_io_message resp; struct ac_io_message resp;
@ -133,11 +133,11 @@ static void bio2_emu_bi2a_send_status(const struct ac_io_message *req, uint8_t s
resp.cmd.nbytes = sizeof(resp.cmd.status); resp.cmd.nbytes = sizeof(resp.cmd.status);
resp.cmd.status = status; resp.cmd.status = status;
ac_io_emu_response_push(bi2a_bio2, &resp, 0); ac_io_emu_response_push(emu, &resp, 0);
} }
static void bio2_emu_bi2a_send_state(const struct ac_io_message *req) static void bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
{ {
struct ac_io_message resp; struct ac_io_message resp;
struct bio2_bi2a_state *body; struct bio2_bi2a_state *body;
@ -190,12 +190,12 @@ static void bio2_emu_bi2a_send_state(const struct ac_io_message *req)
if (!iidx_io_ep1_send()) { if (!iidx_io_ep1_send()) {
log_warning("BIO2: iidx_io_ep1_send error"); log_warning("BIO2: iidx_io_ep1_send error");
return bio2_emu_bi2a_send_status(req, 0); return bio2_emu_bi2a_send_status(emu, req, 0);
} }
if (!iidx_io_ep3_write_16seg((const char*) req_bi2a->SEG16)) { if (!iidx_io_ep3_write_16seg((const char*) req_bi2a->SEG16)) {
log_warning("BIO2: iidx_io_ep3_write_16seg error"); log_warning("BIO2: iidx_io_ep3_write_16seg error");
return bio2_emu_bi2a_send_status(req, 0); return bio2_emu_bi2a_send_status(emu, req, 0);
} }
body = (struct bio2_bi2a_state *)&resp.cmd.raw; body = (struct bio2_bi2a_state *)&resp.cmd.raw;
@ -208,7 +208,7 @@ static void bio2_emu_bi2a_send_state(const struct ac_io_message *req)
if (!iidx_io_ep2_recv()) { if (!iidx_io_ep2_recv()) {
log_warning("BIO2: iidx_io_ep2_recv error"); log_warning("BIO2: iidx_io_ep2_recv error");
return bio2_emu_bi2a_send_status(req, 0); return bio2_emu_bi2a_send_status(emu, req, 0);
} }
body->TURNTABLE1 = iidx_io_ep2_get_turntable(0); body->TURNTABLE1 = iidx_io_ep2_get_turntable(0);
@ -247,5 +247,5 @@ static void bio2_emu_bi2a_send_state(const struct ac_io_message *req)
body->SYSTEM.v_service = (input_sys >> IIDX_IO_SYS_SERVICE) & 1; body->SYSTEM.v_service = (input_sys >> IIDX_IO_SYS_SERVICE) & 1;
body->SYSTEM.v_coin = (input_sys >> IIDX_IO_SYS_COIN) & 1; body->SYSTEM.v_coin = (input_sys >> IIDX_IO_SYS_COIN) & 1;
ac_io_emu_response_push(bi2a_bio2, &resp, 0); ac_io_emu_response_push(emu, &resp, 0);
} }

View File

@ -107,9 +107,12 @@ struct bio2_bi2a_state_in {
uint8_t UNK3[7]; uint8_t UNK3[7];
}; };
_Static_assert(sizeof(struct bio2_bi2a_state_in) == 48, "bio2_bi2a_state_in is the wrong size"); _Static_assert(sizeof(struct bio2_bi2a_state_in) == 48, "bio2_bi2a_state_in is the wrong size");
_Static_assert(sizeof(struct bio2_bi2a_state) == 46, "bio2_bi2a_state_out is the wrong size");
#pragma pack(pop) #pragma pack(pop)
void bio2_emu_bi2a_init(struct ac_io_emu *in, bool disable_poll_limiter); struct bio2emu_port;
void bio2_emu_bi2a_dispatch_request(const struct ac_io_message *req);
void bio2_emu_bi2a_init(struct bio2emu_port *in, bool disable_poll_limiter);
void bio2_emu_bi2a_dispatch_request(struct bio2emu_port *bio2port, const struct ac_io_message *req);
#endif #endif

View File

@ -1,84 +0,0 @@
#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/emu.h"
#include "hook/iohook.h"
#include "hooklib/rs232.h"
#include "iidxhook8/bi2a.h"
#include "imports/avs.h"
#include "util/defs.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu bio2_emu;
void bio2_port_init(bool disable_poll_limiter)
{
// yes I'm using acio
// they use the same framing
ac_io_emu_init(&bio2_emu, L"COM4");
bio2_emu_bi2a_init(&bio2_emu, disable_poll_limiter);
rs232_hook_add_fd(bio2_emu.fd);
}
void bio2_port_fini(void)
{
ac_io_emu_fini(&bio2_emu);
}
HRESULT bio2_port_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&bio2_emu, irp)) {
return irp_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&bio2_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&bio2_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&bio2_emu, msg, 1);
break;
case 1:
bio2_emu_bi2a_dispatch_request(msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast(?) message on IIDX BIO2 bus?");
break;
default:
log_warning("BIO2 message on unhandled bus address: %d", msg->addr);
break;
}
ac_io_emu_request_pop(&bio2_emu);
}
}

View File

@ -1,14 +0,0 @@
#ifndef IIDXHOOK_BIO2_H
#define IIDXHOOK_BIO2_H
#include <windows.h>
#include <stdbool.h>
#include "hook/iohook.h"
void bio2_port_init(bool disable_poll_limiter);
void bio2_port_fini(void);
HRESULT bio2_port_dispatch_irp(struct irp *irp);
#endif

View File

@ -23,11 +23,12 @@
#include "iidxhook-util/d3d9.h" #include "iidxhook-util/d3d9.h"
#include "iidxhook-util/log-server.h" #include "iidxhook-util/log-server.h"
#include "iidxhook8/bio2.h" #include "bio2emu/emu.h"
#include "iidxhook8/bi2a.h"
#include "iidxhook8/cam.h" #include "iidxhook8/cam.h"
#include "iidxhook8/config-cam.h" #include "iidxhook8/config-cam.h"
#include "iidxhook8/config-io.h" #include "iidxhook8/config-io.h"
#include "iidxhook8/setupapi.h"
#include "iidxhook8/cam.h" #include "iidxhook8/cam.h"
#include "imports/avs.h" #include "imports/avs.h"
@ -44,7 +45,7 @@
static const irp_handler_t iidxhook_handlers[] = { static const irp_handler_t iidxhook_handlers[] = {
iidxhook_util_acio_dispatch_irp, iidxhook_util_acio_dispatch_irp,
bio2_port_dispatch_irp, bio2emu_port_dispatch_irp,
}; };
static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = {
@ -75,6 +76,12 @@ static void iidxhook8_setup_d3d9_hooks(const struct iidxhook_config_gfx* config_
struct iidxhook8_config_io iidxhook8_config_io; struct iidxhook8_config_io iidxhook8_config_io;
static struct bio2emu_port bio2_emu = {
.port = "COM4",
.wport = L"COM4",
.dispatcher = bio2_emu_bi2a_dispatch_request,
};
static bool my_dll_entry_init(char *sidcode, struct property_node *param) static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{ {
struct cconfig* config; struct cconfig* config;
@ -82,7 +89,8 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
struct iidxhook_config_gfx config_gfx; struct iidxhook_config_gfx config_gfx;
struct iidxhook8_config_cam config_cam; struct iidxhook8_config_cam config_cam;
// log_server_init is not required anymore // log_server_init is required due to IO occuring in a non avs_thread
log_server_init();
log_info("-------------------------------------------------------------"); log_info("-------------------------------------------------------------");
log_info("--------------- Begin iidxhook dll_entry_init ---------------"); log_info("--------------- Begin iidxhook dll_entry_init ---------------");
@ -141,8 +149,11 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
rs232_hook_limit_hooks(); rs232_hook_limit_hooks();
if (!iidxhook8_config_io.disable_bio2_emu) { if (!iidxhook8_config_io.disable_bio2_emu) {
bio2_port_init(iidxhook8_config_io.disable_poll_limiter); bio2emu_init_start();
setupapi_hook_init();
bio2_emu_bi2a_init(&bio2_emu, iidxhook8_config_io.disable_poll_limiter);
bio2emu_init_end();
} }
if (!iidxhook8_config_io.disable_card_reader_emu) { if (!iidxhook8_config_io.disable_card_reader_emu) {
@ -177,6 +188,8 @@ static bool my_dll_entry_main(void)
iidx_io_fini(); iidx_io_fini();
} }
log_server_fini();
return result; return result;
} }

View File

@ -1,287 +0,0 @@
#define LOG_MODULE "setupapi-hook"
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include "hook/table.h"
#include "iidxhook8/setupapi.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
);
static BOOL (*real_SetupDiDestroyDeviceInfoList)(
HDEVINFO DeviceInfoSet
);
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static BOOL (*real_SetupDiEnumDeviceInfo)(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
);
static HKEY my_SetupDiOpenDevRegKey(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
);
static HKEY (*real_SetupDiOpenDevRegKey)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
);
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static BOOL (*real_SetupDiGetDeviceRegistryPropertyA)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
);
static BOOL my_SetupDiGetDeviceInfoListDetailA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
);
static BOOL (*real_SetupDiGetDeviceInfoListDetailA)(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
);
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static HDEVINFO(*real_SetupDiGetClassDevsA)(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
static const struct hook_symbol iidxhook5_setupapi_syms[] = {
{
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
.link = (void **) &real_SetupDiDestroyDeviceInfoList
},
{
.name = "SetupDiEnumDeviceInfo",
.patch = my_SetupDiEnumDeviceInfo,
.link = (void **) &real_SetupDiEnumDeviceInfo
},
{
.name = "SetupDiOpenDevRegKey",
.patch = my_SetupDiOpenDevRegKey,
.link = (void **) &real_SetupDiOpenDevRegKey
},
{
.name = "SetupDiGetDeviceRegistryPropertyA",
.patch = my_SetupDiGetDeviceRegistryPropertyA,
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA
},
{
.name = "SetupDiGetDeviceInfoListDetailA",
.patch = my_SetupDiGetDeviceInfoListDetailA,
.link = (void **) &real_SetupDiGetDeviceInfoListDetailA
},
{
.name = "SetupDiGetClassDevsA",
.patch = my_SetupDiGetClassDevsA,
.link = (void **) &real_SetupDiGetClassDevsA
},
};
static LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
static LSTATUS (*real_RegQueryValueExA)(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
static const struct hook_symbol iidxhook5_Advapi32_syms[] = {
{
.name = "RegQueryValueExA",
.patch = my_RegQueryValueExA,
.link = (void **) &real_RegQueryValueExA
},
};
#define CUSTOM_DEVICE_HANDLE (void*)0x12341230
#define CUSTOM_REGISTRY_HANDLE (void*)0x4242ccc0
static BOOL my_SetupDiDestroyDeviceInfoList(
HDEVINFO DeviceInfoSet
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
static BOOL my_SetupDiEnumDeviceInfo(
HDEVINFO DeviceInfoSet,
DWORD MemberIndex,
PSP_DEVINFO_DATA DeviceInfoData
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, DeviceInfoData);
}
static HKEY my_SetupDiOpenDevRegKey(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Scope,
DWORD HwProfile,
DWORD KeyType,
REGSAM samDesired
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return CUSTOM_REGISTRY_HANDLE;
}
return real_SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired);
}
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property,
PDWORD PropertyRegDataType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
log_info("%s: Found CUSTOM HANDLE", __FUNCTION__);
if (PropertyBuffer && (PropertyBufferSize >= 12)){
log_info("%s: Copying property name (%ld)", __FUNCTION__, PropertyBufferSize);
strncpy((char*)PropertyBuffer, "BIO2(VIDEO)", PropertyBufferSize);
log_info("%s: Done copying property name", __FUNCTION__);
// Sleep(500);
} else {
log_info("%s: Returning size", __FUNCTION__);
*RequiredSize = 12;
}
log_info("%s: STUB RETURN", __FUNCTION__);
return true;
}
return real_SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize);
}
static BOOL my_SetupDiGetDeviceInfoListDetailA(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
){
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE){
log_info("Inside: %s", __FUNCTION__);
return true;
}
return real_SetupDiGetDeviceInfoListDetailA(DeviceInfoSet, DeviceInfoSetDetailData);
}
DEFINE_GUID(GUID_COM_BUS_ENUMERATOR,
0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
static HDEVINFO my_SetupDiGetClassDevsA(
CONST GUID *ClassGuid,
PCSTR Enumerator,
HWND hwndParent,
DWORD Flags
){
if (ClassGuid) {
if (IsEqualGUID(ClassGuid, &GUID_COM_BUS_ENUMERATOR)){
log_info("Inside: %s", __FUNCTION__);
return CUSTOM_DEVICE_HANDLE;
}
}
return real_SetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
}
static LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
){
if (hKey == CUSTOM_REGISTRY_HANDLE){
if (strcmp(lpValueName, "PortName") == 0) {
log_info("Inside: %s", __FUNCTION__);
if (lpData){
strncpy((char*)lpData, "COM4", *lpcbData);
return ERROR_SUCCESS;
}
return ERROR_MORE_DATA;
}
}
return real_RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
}
void setupapi_hook_init(void)
{
hook_table_apply(
NULL,
"setupapi.dll",
iidxhook5_setupapi_syms,
lengthof(iidxhook5_setupapi_syms));
hook_table_apply(
NULL,
"Advapi32.dll",
iidxhook5_Advapi32_syms,
lengthof(iidxhook5_Advapi32_syms));
log_info("Inserted setupapi hooks");
}

View File

@ -1,6 +0,0 @@
#ifndef IIDXHOOK_SETUPAPI_H
#define IIDXHOOK_SETUPAPI_H
void setupapi_hook_init(void);
#endif