sdvxhook2-cn: sdvx5 cn support

This commit is contained in:
Will Xyen
2020-01-13 16:16:12 -05:00
parent 214a31b24d
commit 6d638ff1ae
14 changed files with 717 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
avsdlls += sdvxhook2-cn
ldflags_sdvxhook2-cn := \
-liphlpapi \
-lsetupapi \
-lcfgmgr32 \
-lmf \
-lmfplat \
-lole32 \
deplibs_sdvxhook2-cn := \
avs \
libs_sdvxhook2-cn := \
acioemu \
camhook \
d3d9exhook \
sdvxio \
hook \
hooklib \
cconfig \
util \
src_sdvxhook2-cn := \
acio.c \
kfca.c \
dllmain.c \
config-cn.c \
unis-version.c \
+92
View File
@@ -0,0 +1,92 @@
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#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 "sdvxhook2-cn/acio.h"
#include "sdvxhook2-cn/kfca.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 ac_io_emu;
void ac_io_port_init(void)
{
ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2");
kfca_init(&ac_io_emu);
rs232_hook_add_fd(ac_io_emu.fd);
}
void ac_io_port_fini(void)
{
ac_io_emu_fini(&ac_io_emu);
}
HRESULT ac_io_port_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&ac_io_emu, irp)) {
return irp_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&ac_io_emu, msg, 1);
log_warning("ac_io_emu_cmd_assign_addrs");
break;
case 1:
kfca_dispatch_request(msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast? (0x70) message on ACIO bus");
break;
default:
log_warning(
"ACIO message on unhandled bus address: %d", msg->addr);
break;
}
ac_io_emu_request_pop(&ac_io_emu);
}
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef SDVXHOOK2_5_AC_IO_H
#define SDVXHOOK2_5_AC_IO_H
#include <windows.h>
#include <stdbool.h>
#include "hook/iohook.h"
void ac_io_port_init(void);
void ac_io_port_fini(void);
HRESULT ac_io_port_dispatch_irp(struct irp *irp);
#endif
+55
View File
@@ -0,0 +1,55 @@
#include "cconfig/cconfig-util.h"
#include "sdvxhook2-cn/config-cn.h"
#include "util/log.h"
#define SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY "io.disable_io_emu"
#define SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY "cn.unis_path"
#define SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE false
#define SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE "prop/unis.xml"
void sdvxhook2_cn_config_init(struct cconfig *config)
{
cconfig_util_set_bool(
config,
SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE,
"Disable IO emulation and enable usage of real KFCA hardware");
cconfig_util_set_str(
config,
SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE,
"Path to unis version file under the prop.s folder");
}
void sdvxhook2_cn_config_get(
struct sdvxhook2_cn_config *cn_config, struct cconfig *config)
{
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY,
&cn_config->disable_io_emu,
SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE);
}
if (!cconfig_util_get_str(
config,
SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY,
cn_config->unis_path,
sizeof(cn_config->unis_path),
SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE);
}
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef SDVXHOOK2_CN_CONFIG_H
#define SDVXHOOK2_CN_CONFIG_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct sdvxhook2_cn_config {
bool disable_io_emu;
char unis_path[256];
};
void sdvxhook2_cn_config_init(struct cconfig *config);
void sdvxhook2_cn_config_get(
struct sdvxhook2_cn_config *cn_config, struct cconfig *config);
#endif
+151
View File
@@ -0,0 +1,151 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "bemanitools/eamio.h"
#include "bemanitools/sdvxio.h"
#include "cconfig/cconfig-hook.h"
#include "hooklib/acp.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h"
#include "hooklib/rs232.h"
#include "sdvxhook2-cn/acio.h"
#include "sdvxhook2-cn/config-cn.h"
#include "sdvxhook2-cn/unis-version.h"
#include "camhook/cam.h"
#include "camhook/config-cam.h"
#include "d3d9exhook/config-gfx.h"
#include "d3d9exhook/d3d9ex.h"
#include "imports/avs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/thread.h"
#define SDVXHOOK2_CN_INFO_HEADER \
"sdvxhook for VW CN" \
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n"
#define SDVXHOOK2_CN_CMD_USAGE \
"Usage: launcher.exe -K sdvxhook2.dll <soundvoltex.dll> [options...]"
static const irp_handler_t sdvxhook_handlers[] = {
ac_io_port_dispatch_irp,
};
struct sdvxhook2_cn_config config_cn;
struct camhook_config_cam config_cam;
struct d3d9exhook_config_gfx config_gfx;
static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{
struct cconfig *config;
log_info("--- Begin sdvxhook dll_entry_init ---");
config = cconfig_init();
sdvxhook2_cn_config_init(config);
d3d9exhook_config_gfx_init(config);
camhook_config_cam_init(config, 1);
if (!cconfig_hook_config_init(
config,
SDVXHOOK2_CN_INFO_HEADER "\n" SDVXHOOK2_CN_CMD_USAGE,
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
cconfig_finit(config);
exit(EXIT_FAILURE);
}
sdvxhook2_cn_config_get(&config_cn, config);
camhook_config_cam_get(&config_cam, config, 1);
d3d9exhook_config_gfx_get(&config_gfx, config);
cconfig_finit(config);
log_info(SDVXHOOK2_CN_INFO_HEADER);
log_info("Initializing sdvxhook2-cn...");
d3d9ex_configure(&config_gfx);
/* Start up sdvxio.DLL */
if (!config_cn.disable_io_emu) {
log_info("Starting sdvx IO backend");
sdvx_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
if (!sdvx_io_init(
avs_thread_create, avs_thread_join, avs_thread_destroy)) {
log_fatal("Initializing sdvx IO backend failed");
}
}
/* iohooks are okay, even if emu is diabled since the fake handlers won't be
* used */
iohook_init(sdvxhook_handlers, lengthof(sdvxhook_handlers));
rs232_hook_init();
rs232_hook_limit_hooks();
if (!config_cn.disable_io_emu) {
ac_io_port_init();
}
// camera hooks
if (!config_cam.disable_emu) {
camhook_init(&config_cam);
}
unis_version_hook_init(config_cn.unis_path);
log_info("--- End sdvxhook dll_entry_init ---");
return app_hook_invoke_init(sidcode, param);
}
static bool my_dll_entry_main(void)
{
bool result;
result = app_hook_invoke_main();
if (!config_cam.disable_emu) {
camhook_fini();
}
if (!config_cn.disable_io_emu) {
log_misc("Shutting down sdvx IO backend");
sdvx_io_fini();
}
return result;
}
/**
* Hook library Resort Anthem onwards
*/
BOOL WINAPI DllMain(HMODULE mod, 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);
acp_hook_init();
adapter_hook_init();
d3d9ex_hook_init();
end:
return TRUE;
}
+196
View File
@@ -0,0 +1,196 @@
#include <windows.h>
#include <stdint.h>
#include <string.h>
#include "acio/acio.h"
#include "acioemu/emu.h"
#include "bemanitools/sdvxio.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/time.h"
static void kfca_send_version(const struct ac_io_message *req);
static void kfca_report_status(const struct ac_io_message *req, uint8_t status);
static void kfca_report_0128(const struct ac_io_message *req);
static void kfca_poll(const struct ac_io_message *req);
static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp);
static struct ac_io_emu *kfca_ac_io_emu;
void kfca_init(struct ac_io_emu *emu)
{
log_assert(emu != NULL);
kfca_ac_io_emu = emu;
}
void kfca_dispatch_request(const struct ac_io_message *req)
{
uint16_t cmd_code;
cmd_code = ac_io_u16(req->cmd.code);
switch (cmd_code) {
case AC_IO_CMD_GET_VERSION:
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
kfca_send_version(req);
break;
case AC_IO_CMD_START_UP:
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
kfca_report_status(req, 0x00);
break;
case AC_IO_CMD_KFCA_POLL:
kfca_poll(req);
break;
case AC_IO_CMD_KFCA_WATCHDOG:
log_misc("AC_IO_CMD_KFCA_WATCHDOG(%d)", req->addr);
kfca_report_status(req, 0x00);
break;
case AC_IO_CMD_KFCA_AMP_CONTROL:
log_misc("AC_IO_CMD_KFCA_AMP_CONTROL(%d)", req->addr);
kfca_report_0128(req);
break;
default:
log_warning(
"Unknown ACIO message %04x on KFCA mode, addr=%d",
cmd_code,
req->addr);
break;
}
}
static void kfca_send_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_KFCA);
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,
"KFCA",
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(kfca_ac_io_emu, &resp, 0);
}
static void kfca_report_status(const struct ac_io_message *req, uint8_t status)
{
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 = status;
ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0);
}
static void kfca_report_0128(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 = req->cmd.nbytes;
memcpy(resp.cmd.raw, req->cmd.raw, req->cmd.nbytes);
ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0);
}
static void kfca_poll(const struct ac_io_message *req)
{
static uint32_t last_poll = 0;
uint64_t delay;
const struct ac_io_kfca_poll_out *pout;
uintptr_t ctx;
size_t i;
/* Handle lighting output immediately */
pout = &req->cmd.kfca_poll_out;
sdvx_io_set_gpio_lights(ac_io_u32(pout->gpio));
for (i = 0; i < lengthof(pout->pwm); i++) {
sdvx_io_set_pwm_light(i, pout->pwm[i]);
}
sdvx_io_write_output();
/* SDVX expects only one poll response per frame.
We use a thunk here to defer polling until right before the response
is due. */
delay = time_get_elapsed_ms(last_poll) < 16 ? 16000 : 0;
last_poll = time_get_counter();
ctx = req->addr | (req->cmd.code << 8) | (req->cmd.seq_no << 24);
ac_io_emu_response_push_thunk(
kfca_ac_io_emu, kfca_poll_thunk, (void *) ctx, delay);
}
static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp)
{
struct ac_io_kfca_poll_in *pin;
uintptr_t ctx;
uint8_t req_addr;
uint16_t req_code;
uint8_t req_seq_no;
/* Unpack context "pointer" for relevant response information */
ctx = (uintptr_t) ctx_ptr;
req_addr = ctx;
req_code = ctx >> 8;
req_seq_no = ctx >> 24;
/* Poll input now and construct an immediate response */
pin = &resp->cmd.kfca_poll_in;
resp->addr = req_addr | AC_IO_RESPONSE_FLAG;
resp->cmd.code = req_code;
resp->cmd.seq_no = req_seq_no;
resp->cmd.nbytes = sizeof(*pin);
sdvx_io_read_input();
memset(pin, 0, sizeof(*pin));
pin->adc[0] = sdvx_io_get_spinner_pos(0) << 6;
pin->adc[1] = sdvx_io_get_spinner_pos(1) << 6;
pin->gpio_sys |= sdvx_io_get_input_gpio_sys() & 0x3F;
pin->adc[0] = ac_io_u16(pin->adc[0]);
pin->adc[1] = ac_io_u16(pin->adc[1]);
pin->gpio[0] = ac_io_u16(sdvx_io_get_input_gpio(0));
pin->gpio[1] = ac_io_u16(sdvx_io_get_input_gpio(1));
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef SDVXHOOK_KFCA_H
#define SDVXHOOK_KFCA_H
#include "acio/acio.h"
#include "acioemu/emu.h"
void kfca_init(struct ac_io_emu *emu);
void kfca_dispatch_request(const struct ac_io_message *req);
#endif
+4
View File
@@ -0,0 +1,4 @@
LIBRARY sdvxhook2-cn
EXPORTS
DllMain@12 @1 NONAME
+84
View File
@@ -0,0 +1,84 @@
#define LOG_MODULE "unis-version"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <shellapi.h>
// clang-format on
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
LPWSTR *(*real_CommandLineToArgvW)(LPCWSTR lpCmdLine, int *pNumArgs);
LPWSTR *my_CommandLineToArgvW(LPCWSTR lpCmdLine, int *pNumArgs);
static const struct hook_symbol unis_shell32_syms[] = {
{.name = "CommandLineToArgvW",
.patch = my_CommandLineToArgvW,
.link = (void **) &real_CommandLineToArgvW},
};
bool (*real_IsInComm)(void);
bool my_IsInComm(void);
bool (*real_IsConnectServer)(void);
bool my_IsConnectServer(void);
bool (*real_IsPlayerForbidState)(int pnum);
bool my_IsPlayerForbidState(int pnum);
static wchar_t unis_cmd_path[256 + 16];
static const struct hook_symbol unis_unisintr_syms[] = {
{.name = "IsInComm",
.patch = my_IsInComm,
.link = (void **) &real_IsInComm},
{.name = "IsConnectServer",
.patch = my_IsConnectServer,
.link = (void **) &real_IsConnectServer},
{.name = "IsPlayerForbidState",
.patch = my_IsPlayerForbidState,
.link = (void **) &real_IsPlayerForbidState},
};
LPWSTR *my_CommandLineToArgvW(LPCWSTR lpCmdLine, int *pNumArgs)
{
return real_CommandLineToArgvW(unis_cmd_path, pNumArgs);
}
bool my_IsInComm(void)
{
return true;
}
bool my_IsConnectServer(void)
{
return true;
}
bool my_IsPlayerForbidState(int pnum)
{
return false;
}
void unis_version_hook_init(const char* unis_path)
{
hook_table_apply(
NULL, "Shell32.dll", unis_shell32_syms, lengthof(unis_shell32_syms));
hook_table_apply(
NULL, "unisintr.dll", unis_unisintr_syms, lengthof(unis_unisintr_syms));
wcscpy(unis_cmd_path, L"launcher.exe ");
wchar_t *end = wcsrchr(unis_cmd_path, L'\0');
mbstowcs(end, unis_path, 256);
log_info("Inserted hooks for unis version detection");
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef SDVXHOOK2_5_UNIS_VERSION_H
#define SDVXHOOK2_5_UNIS_VERSION_H
void unis_version_hook_init(const char* unis_path);
#endif