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:33:50 -04:00
parent 073392407a
commit e495bfb8f1
14 changed files with 530 additions and 427 deletions
+1 -2
View File
@@ -14,6 +14,7 @@ deplibs_iidxhook8 := \
libs_iidxhook8 := \
iidxhook-util \
acioemu \
bio2emu \
iidxio \
hook \
hooklib \
@@ -23,9 +24,7 @@ libs_iidxhook8 := \
src_iidxhook8 := \
bi2a.c \
bio2.c \
cam.c \
config-cam.c \
config-io.c \
dllmain.c \
setupapi.c \
+26 -26
View File
@@ -1,6 +1,7 @@
#define LOG_MODULE "bio2emu-bi2a"
#include "iidxhook8/bi2a.h"
#include "bio2emu/emu.h"
#include <windows.h> /* for _BitScanForward */
@@ -13,12 +14,11 @@
#include "bemanitools/iidxio.h"
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_send_state(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_status(const struct ac_io_message *req, uint8_t status);
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(struct ac_io_emu *emu, 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(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 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;
bi2a_bio2 = bio2_emu;
bio2emu_port_init(bio2_emu);
poll_delay = !disable_poll_limiter;
if (!poll_delay) {
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;
}
f = fopen("vefx.txt", "r");
FILE* f = fopen("vefx.txt", "r");
if (f) {
fscanf(f, "%d %d %d %d %d", &default_sliders[0], &default_sliders[1], &default_sliders[2], &default_sliders[3], &default_sliders[4]);
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;
@@ -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_0120:
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;
case 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;
case AC_IO_CMD_GET_VERSION:
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;
case AC_IO_CMD_START_UP:
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;
case AC_IO_CMD_KEEPALIVE:
log_misc("BIO2_CMD_KEEPALIVE(%d)", req->addr);
bio2_emu_bi2a_send_empty(req);
bio2_emu_bi2a_send_empty(&bio2port->acio, req);
break;
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;
@@ -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.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;
@@ -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.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;
@@ -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.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 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()) {
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)) {
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;
@@ -208,7 +208,7 @@ static void bio2_emu_bi2a_send_state(const struct ac_io_message *req)
if (!iidx_io_ep2_recv()) {
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);
@@ -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_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);
}
+5 -2
View File
@@ -107,9 +107,12 @@ struct bio2_bi2a_state_in {
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) == 46, "bio2_bi2a_state_out is the wrong size");
#pragma pack(pop)
void bio2_emu_bi2a_init(struct ac_io_emu *in, bool disable_poll_limiter);
void bio2_emu_bi2a_dispatch_request(const struct ac_io_message *req);
struct bio2emu_port;
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
-84
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);
}
}
-14
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
+19 -6
View File
@@ -23,11 +23,12 @@
#include "iidxhook-util/d3d9.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/config-cam.h"
#include "iidxhook8/config-io.h"
#include "iidxhook8/setupapi.h"
#include "iidxhook8/cam.h"
#include "imports/avs.h"
@@ -44,7 +45,7 @@
static const irp_handler_t iidxhook_handlers[] = {
iidxhook_util_acio_dispatch_irp,
bio2_port_dispatch_irp,
bio2emu_port_dispatch_irp,
};
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;
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)
{
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 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("--------------- 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();
if (!iidxhook8_config_io.disable_bio2_emu) {
bio2_port_init(iidxhook8_config_io.disable_poll_limiter);
setupapi_hook_init();
bio2emu_init_start();
bio2_emu_bi2a_init(&bio2_emu, iidxhook8_config_io.disable_poll_limiter);
bio2emu_init_end();
}
if (!iidxhook8_config_io.disable_card_reader_emu) {
@@ -177,6 +188,8 @@ static bool my_dll_entry_main(void)
iidx_io_fini();
}
log_server_fini();
return result;
}
-287
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");
}
-6
View File
@@ -1,6 +0,0 @@
#ifndef IIDXHOOK_SETUPAPI_H
#define IIDXHOOK_SETUPAPI_H
void setupapi_hook_init(void);
#endif