1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2025-02-20 20:41:10 +01:00

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

View File

@ -136,6 +136,7 @@ include src/main/p4ioemu/Module.mk
include src/main/pcbidgen/Module.mk
include src/main/sdvxhook/Module.mk
include src/main/sdvxhook2/Module.mk
include src/main/sdvxhook2-cn/Module.mk
include src/main/sdvxio/Module.mk
include src/main/sdvxio-kfca/Module.mk
include src/main/security/Module.mk
@ -436,6 +437,20 @@ $(zipdir)/sdvx-05.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx-05-cn.zip: \
build/bin/avs2_1700-64/launcher.exe \
build/bin/avs2_1700-64/sdvxhook2-cn.dll \
build/bin/indep-64/config.exe \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
build/bin/indep-64/sdvxio.dll \
dist/sdvx5/config.bat \
dist/sdvx5/gamestart-cn.bat \
dist/sdvx5/sdvxhook2-cn.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-12-to-16.zip: \
build/bin/avs2_1508-32/launcher.exe \
build/bin/avs2_1508-32/ddrhook.dll \
@ -523,6 +538,7 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/src.zip \
$(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-cn.zip \
$(zipdir)/tools.zip \
$(zipdir)/tools-x64.zip \
CHANGELOG.md \

17
dist/sdvx5/gamestart-cn.bat vendored Normal file
View File

@ -0,0 +1,17 @@
@echo off
cd /d %~dp0
if not exist dev mkdir dev
if not exist dev\e mkdir dev\e
if not exist dev\g mkdir dev\g
if not exist dev\nvram mkdir dev\nvram
if not exist dev\raw mkdir dev\raw
if not exist dev\raw\c.dest echo $null >> dev\raw\c.dest
if not exist dev\raw\log mkdir dev\raw\log
if not exist dev\raw\fscache mkdir dev\raw\fscache
for /R prop\defaults %%D in (*.*) do (
if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
)
launcher -H 268435456 -K sdvxhook2-cn.dll soundvoltex.dll --config sdvxhook2-cn.conf %*

24
dist/sdvx5/sdvxhook2-cn.conf vendored Normal file
View File

@ -0,0 +1,24 @@
# Disable IO emulation and enable usage of real KFCA hardware
io.disable_io_emu=false
# Path to unis version file under the prop.s folder
cn.unis_path=prop/unis.xml
# Run the game in a framed window (requires windowed option)
gfx.framed=true
# Run the game windowed
gfx.windowed=false
# Windowed width, -1 for default size
gfx.window_width=720
# Windowed height, -1 for default size
gfx.window_height=1280
# Disables the camera emulation
cam.disable_emu=false
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id1=

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 \

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);
}
}

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

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);
}
}

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

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;
}

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));
}

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

View File

@ -0,0 +1,4 @@
LIBRARY sdvxhook2-cn
EXPORTS
DllMain@12 @1 NONAME

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");
}

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