mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2024-11-12 01:10:49 +01:00
sdvxhook2: Add sdvxhook2
This commit is contained in:
parent
2011bfafd6
commit
1d247d44d5
17
Module.mk
17
Module.mk
@ -134,6 +134,7 @@ include src/main/p3ioemu/Module.mk
|
||||
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/sdvxio/Module.mk
|
||||
include src/main/sdvxio-kfca/Module.mk
|
||||
include src/main/security/Module.mk
|
||||
@ -419,6 +420,21 @@ $(zipdir)/sdvx.zip: \
|
||||
$(V)echo ... $@
|
||||
$(V)zip -j $@ $^
|
||||
|
||||
$(zipdir)/sdvx5.zip: \
|
||||
build/bin/avs2_1700-64/launcher.exe \
|
||||
build/bin/avs2_1700-64/sdvxhook2.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 \
|
||||
build/bin/indep-64/sdvxio-kfca.dll \
|
||||
dist/sdvx5/config.bat \
|
||||
dist/sdvx5/gamestart.bat \
|
||||
dist/sdvx5/sdvxhook.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 \
|
||||
@ -504,6 +520,7 @@ $(BUILDDIR)/bemanitools.zip: \
|
||||
$(zipdir)/jb-08.zip \
|
||||
$(zipdir)/src.zip \
|
||||
$(zipdir)/sdvx.zip \
|
||||
$(zipdir)/sdvx5.zip \
|
||||
$(zipdir)/tools.zip \
|
||||
$(zipdir)/tools-x64.zip \
|
||||
CHANGELOG.md \
|
||||
|
1
dist/sdvx5/config.bat
vendored
Normal file
1
dist/sdvx5/config.bat
vendored
Normal file
@ -0,0 +1 @@
|
||||
@start config.exe sdvx
|
16
dist/sdvx5/gamestart.bat
vendored
Normal file
16
dist/sdvx5/gamestart.bat
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
@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\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 sdvxhook5.dll soundvoltex.dll --options sdvxhook.conf %*
|
21
dist/sdvx5/sdvxhook.conf
vendored
Normal file
21
dist/sdvx5/sdvxhook.conf
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# [bool (0/1)]: Run the game in a framed window (requires windowed option)
|
||||
gfx.framed=1
|
||||
|
||||
# [bool (0/1)]: Run the game windowed
|
||||
gfx.windowed=0
|
||||
|
||||
# [bool (0/1)]: Disable card reader emulation and enable usage of real card reader hardware on COM0 (for games supporting slotted readers)
|
||||
io.disable_card_reader_emulation=0
|
||||
|
||||
# [bool (0/1)]: Disable BIO2 emulation and enable usage of real BIO2 hardware
|
||||
io.disable_bio2_emu=0
|
||||
|
||||
# [bool (0/1)]: Disables the poll limiter, warning very high CPU usage may arise
|
||||
io.disable_poll_limiter=0
|
||||
|
||||
# [bool (0/1)]: Disables the camera emulation
|
||||
cam.disable_emu=0
|
||||
|
||||
# [str]: Override camera device ID detection (copy from device manager, do not escape)
|
||||
cam.device_id=
|
||||
|
31
src/main/sdvxhook2/Module.mk
Normal file
31
src/main/sdvxhook2/Module.mk
Normal file
@ -0,0 +1,31 @@
|
||||
avsdlls += sdvxhook2
|
||||
|
||||
ldflags_sdvxhook2 := \
|
||||
-liphlpapi \
|
||||
-lsetupapi \
|
||||
-lcfgmgr32 \
|
||||
-lmf \
|
||||
-lmfplat \
|
||||
-lole32 \
|
||||
|
||||
deplibs_sdvxhook2 := \
|
||||
avs \
|
||||
|
||||
libs_sdvxhook2 := \
|
||||
acioemu \
|
||||
bio2emu \
|
||||
camhook \
|
||||
sdvxio \
|
||||
hook \
|
||||
hooklib \
|
||||
cconfig \
|
||||
util \
|
||||
eamio \
|
||||
|
||||
src_sdvxhook2 := \
|
||||
acio.c \
|
||||
bi2a.c \
|
||||
dllmain.c \
|
||||
d3d9.c \
|
||||
config-gfx.c \
|
||||
config-io.c \
|
93
src/main/sdvxhook2/acio.c
Normal file
93
src/main/sdvxhook2/acio.c
Normal file
@ -0,0 +1,93 @@
|
||||
// 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 "acioemu/icca.h"
|
||||
|
||||
#include "hook/iohook.h"
|
||||
#include "hooklib/rs232.h"
|
||||
|
||||
#include "sdvxhook2/acio.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;
|
||||
static struct ac_io_emu_icca ac_io_emu_icca;
|
||||
|
||||
void ac_io_port_init(void)
|
||||
{
|
||||
ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2");
|
||||
|
||||
ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0);
|
||||
|
||||
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:
|
||||
ac_io_emu_icca_dispatch_request(&ac_io_emu_icca, msg);
|
||||
|
||||
break;
|
||||
|
||||
case AC_IO_BROADCAST:
|
||||
log_warning("Broadcast(?) message on IIDX 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
src/main/sdvxhook2/acio.h
Normal file
14
src/main/sdvxhook2/acio.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef SDVXHOOK2_AC_IO_H
|
||||
#define SDVXHOOK2_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
|
251
src/main/sdvxhook2/bi2a.c
Normal file
251
src/main/sdvxhook2/bi2a.c
Normal file
@ -0,0 +1,251 @@
|
||||
#define LOG_MODULE "sdvxhook2-bi2a"
|
||||
|
||||
#include "sdvxhook2/bi2a.h"
|
||||
#include "bio2emu/emu.h"
|
||||
|
||||
#include <windows.h> /* for _BitScanForward */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "acioemu/emu.h"
|
||||
|
||||
#include "bemanitools/sdvxio.h"
|
||||
|
||||
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 void
|
||||
kfca_amp_control(struct ac_io_emu *emu, const struct ac_io_message *req);
|
||||
|
||||
static bool poll_delay;
|
||||
|
||||
void bio2_emu_bi2a_init(
|
||||
struct bio2emu_port *bio2_emu, bool disable_poll_limiter)
|
||||
{
|
||||
bio2emu_port_init(bio2_emu);
|
||||
|
||||
poll_delay = !disable_poll_limiter;
|
||||
if (!poll_delay) {
|
||||
log_warning("bio2_emu_bi2a_init: poll_delay has been disabled");
|
||||
}
|
||||
}
|
||||
|
||||
void bio2_emu_bi2a_dispatch_request(
|
||||
struct bio2emu_port *bio2port, 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_KFCA_WATCHDOG:
|
||||
log_misc("BIO2_BI2A_CMD_WATCHDOG(%d)", req->addr);
|
||||
bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_KFCA_POLL:
|
||||
// log_misc("BIO2_BI2A_CMD_POLL");
|
||||
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(&bio2port->acio, req);
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_CLEAR:
|
||||
log_misc("BIO2_BI2A_CMD_CLEAR(%d)", req->addr);
|
||||
bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_START_UP:
|
||||
log_misc("BIO2_BI2A_CMD_START_UP(%d)", req->addr);
|
||||
bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_KEEPALIVE:
|
||||
log_misc("BIO2_BI2A_CMD_KEEPALIVE(%d)", req->addr);
|
||||
bio2_emu_bi2a_send_empty(&bio2port->acio, req);
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_KFCA_AMP_CONTROL:
|
||||
log_misc("BIO2_BI2A_CMD_AMP_CONTROL(%d)", req->addr);
|
||||
kfca_amp_control(&bio2port->acio, req);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning(
|
||||
"Unknown BIO2 message %04x on BI2A node, addr=%d",
|
||||
cmd_code,
|
||||
req->addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kfca_amp_control(struct ac_io_emu *emu, 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);
|
||||
|
||||
// log_misc("sz %d: %d, %d, %d, %d", req->cmd.nbytes, req->cmd.raw[0],
|
||||
// req->cmd.raw[1], req->cmd.raw[2], req->cmd.raw[3]);
|
||||
|
||||
ac_io_emu_response_push(emu, &resp, 0);
|
||||
}
|
||||
|
||||
static void bio2_emu_bi2a_cmd_send_version(
|
||||
struct ac_io_emu *emu, 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_BI2A);
|
||||
resp.cmd.version.flag = 0x00;
|
||||
resp.cmd.version.major = 0x01;
|
||||
resp.cmd.version.minor = 0x02;
|
||||
resp.cmd.version.revision = 0x09;
|
||||
memcpy(
|
||||
resp.cmd.version.product_code,
|
||||
"BI2A",
|
||||
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(emu, &resp, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
bio2_emu_bi2a_send_empty(struct ac_io_emu *emu, 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(emu, &resp, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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(emu, &resp, 0);
|
||||
}
|
||||
|
||||
static uint8_t check_pin(uint16_t value, uint8_t pin)
|
||||
{
|
||||
return (value >> pin) & 1;
|
||||
}
|
||||
|
||||
static uint32_t _assign_light(uint32_t shift, uint32_t value)
|
||||
{
|
||||
if (!value) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1 << shift;
|
||||
}
|
||||
}
|
||||
|
||||
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 *pin;
|
||||
struct bio2_bi2a_state_out *pout;
|
||||
|
||||
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(*pin);
|
||||
|
||||
pout = (struct bio2_bi2a_state_out *) &req->cmd.raw;
|
||||
pin = (struct bio2_bi2a_state *) &resp.cmd.raw;
|
||||
memset(pin, 0, sizeof(*pin));
|
||||
|
||||
uint32_t gpio = 0;
|
||||
gpio |= _assign_light(0x0C, pout->gpio[0]);
|
||||
gpio |= _assign_light(0x0D, pout->gpio[1]);
|
||||
gpio |= _assign_light(0x0E, pout->gpio[2]);
|
||||
gpio |= _assign_light(0x0F, pout->gpio[3]);
|
||||
gpio |= _assign_light(0x00, pout->gpio[4]);
|
||||
gpio |= _assign_light(0x01, pout->gpio[5]);
|
||||
gpio |= _assign_light(0x02, pout->gpio[6]);
|
||||
|
||||
sdvx_io_set_gpio_lights(gpio);
|
||||
|
||||
sdvx_io_set_pwm_light(0x0, pout->wingUpper[0]);
|
||||
sdvx_io_set_pwm_light(0x1, pout->wingUpper[1]);
|
||||
sdvx_io_set_pwm_light(0x2, pout->wingUpper[2]);
|
||||
sdvx_io_set_pwm_light(0x3, pout->wingUpper[0]);
|
||||
sdvx_io_set_pwm_light(0x4, pout->wingUpper[1]);
|
||||
sdvx_io_set_pwm_light(0x5, pout->wingUpper[2]);
|
||||
|
||||
sdvx_io_set_pwm_light(0x6, pout->wingLower[0]);
|
||||
sdvx_io_set_pwm_light(0x7, pout->wingLower[1]);
|
||||
sdvx_io_set_pwm_light(0x8, pout->wingLower[2]);
|
||||
sdvx_io_set_pwm_light(0x9, pout->wingLower[0]);
|
||||
sdvx_io_set_pwm_light(0xA, pout->wingLower[1]);
|
||||
sdvx_io_set_pwm_light(0xB, pout->wingLower[2]);
|
||||
|
||||
sdvx_io_set_pwm_light(0xC, pout->woof_r);
|
||||
sdvx_io_set_pwm_light(0xD, pout->woof_g);
|
||||
sdvx_io_set_pwm_light(0xE, pout->woof_b);
|
||||
|
||||
sdvx_io_set_pwm_light(0xF, pout->controller[0]);
|
||||
sdvx_io_set_pwm_light(0x10, pout->controller[1]);
|
||||
sdvx_io_set_pwm_light(0x11, pout->controller[2]);
|
||||
|
||||
sdvx_io_write_output();
|
||||
|
||||
sdvx_io_read_input();
|
||||
uint8_t sys = sdvx_io_get_input_gpio_sys();
|
||||
uint16_t gpio0 = sdvx_io_get_input_gpio(0);
|
||||
uint16_t gpio1 = sdvx_io_get_input_gpio(1);
|
||||
|
||||
// TODO: Make a counter or smth to counteract the accuracy lost in *4
|
||||
pin->ANALOGS[0].a_val = sdvx_io_get_spinner_pos(0);
|
||||
pin->ANALOGS[1].a_val = sdvx_io_get_spinner_pos(1);
|
||||
|
||||
pin->ANALOGS[0].a_coin = check_pin(sys, SDVX_IO_IN_GPIO_SYS_COIN);
|
||||
pin->ANALOGS[0].a_test = check_pin(sys, SDVX_IO_IN_GPIO_SYS_TEST);
|
||||
pin->ANALOGS[0].a_service = check_pin(sys, SDVX_IO_IN_GPIO_SYS_SERVICE) ||
|
||||
check_pin(sys, SDVX_IO_IN_GPIO_SYS_COIN);
|
||||
pin->raw[0] = ac_io_u16(pin->raw[0]);
|
||||
pin->raw[1] = ac_io_u16(pin->raw[1]);
|
||||
|
||||
pin->BUTTONS1.b_start = check_pin(gpio0, SDVX_IO_IN_GPIO_0_START);
|
||||
pin->BUTTONS1.b_headphone = check_pin(gpio0, SDVX_IO_IN_GPIO_0_HEADPHONE);
|
||||
pin->BUTTONS1.b_a = check_pin(gpio0, SDVX_IO_IN_GPIO_0_A);
|
||||
pin->BUTTONS1.b_b = check_pin(gpio0, SDVX_IO_IN_GPIO_0_B);
|
||||
pin->BUTTONS1.b_c = check_pin(gpio0, SDVX_IO_IN_GPIO_0_C);
|
||||
pin->BUTTONS1.b_d = check_pin(gpio1, SDVX_IO_IN_GPIO_1_D);
|
||||
pin->BUTTONS1.b_fxl = check_pin(gpio1, SDVX_IO_IN_GPIO_1_FX_L);
|
||||
pin->BUTTONS2.b_fxr = check_pin(gpio1, SDVX_IO_IN_GPIO_1_FX_R);
|
||||
|
||||
ac_io_emu_response_push(emu, &resp, 0);
|
||||
}
|
90
src/main/sdvxhook2/bi2a.h
Normal file
90
src/main/sdvxhook2/bi2a.h
Normal file
@ -0,0 +1,90 @@
|
||||
#ifndef SDVXHOOK2_BI2A_H
|
||||
#define SDVXHOOK2_BI2A_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bio2emu/emu.h"
|
||||
|
||||
enum bio2_bi2a_cmd {
|
||||
// Custom Stuff
|
||||
BIO2_BI2A_CMD_UNK_0100 = 0x0100,
|
||||
BIO2_BI2A_CMD_UNK_0120 = 0x0120,
|
||||
BIO2_BI2A_CMD_POLL = 0x0152,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct bi2a_sdvx_analog {
|
||||
uint16_t unk1 : 1;
|
||||
uint16_t a_coin : 1;
|
||||
uint16_t a_service : 1;
|
||||
uint16_t a_test : 1;
|
||||
uint16_t unk2 : 2;
|
||||
uint16_t a_val : 10;
|
||||
};
|
||||
|
||||
struct bi2a_sdvx_buttons1 {
|
||||
uint8_t b_fxl : 1;
|
||||
uint8_t b_d : 1;
|
||||
uint8_t b_c : 1;
|
||||
uint8_t b_b : 1;
|
||||
uint8_t b_a : 1;
|
||||
uint8_t b_start : 1;
|
||||
uint8_t b_recorder : 1;
|
||||
uint8_t b_headphone : 1;
|
||||
};
|
||||
|
||||
struct bi2a_sdvx_buttons2 {
|
||||
uint8_t unk : 5;
|
||||
uint8_t b_ex2 : 1;
|
||||
uint8_t b_ex1 : 1;
|
||||
uint8_t b_fxr : 1;
|
||||
};
|
||||
|
||||
struct bio2_bi2a_state {
|
||||
union {
|
||||
uint16_t raw[8];
|
||||
struct {
|
||||
struct bi2a_sdvx_analog ANALOGS[4];
|
||||
uint8_t UNK; // coin mech?
|
||||
struct bi2a_sdvx_buttons1 BUTTONS1;
|
||||
struct bi2a_sdvx_buttons2 BUTTONS2;
|
||||
uint8_t UNK2[5];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct bio2_bi2a_state_out {
|
||||
uint8_t unk1[2];
|
||||
uint8_t c_block;
|
||||
uint8_t woof_r;
|
||||
uint8_t woof_g;
|
||||
uint8_t unk2;
|
||||
uint8_t woof_b;
|
||||
uint8_t controller[3];
|
||||
uint8_t unk3;
|
||||
uint8_t gpio[7]; // START, ABCD, FXL, FXR
|
||||
uint8_t unk4[3];
|
||||
uint8_t generator[3];
|
||||
uint8_t unk5[3];
|
||||
uint8_t gpio2[3]; // pop, titleL, titleR
|
||||
uint8_t unk6;
|
||||
uint8_t wingUpper[3];
|
||||
uint8_t wingLower[3];
|
||||
uint8_t unk7[3];
|
||||
};
|
||||
|
||||
_Static_assert(
|
||||
sizeof(struct bio2_bi2a_state) == 16,
|
||||
"bio2_bi2a_state_in is the wrong size");
|
||||
_Static_assert(
|
||||
sizeof(struct bio2_bi2a_state_out) == 40,
|
||||
"bio2_bi2a_state_out is the wrong size");
|
||||
#pragma pack(pop)
|
||||
|
||||
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
|
139
src/main/sdvxhook2/config-gfx.c
Normal file
139
src/main/sdvxhook2/config-gfx.c
Normal file
@ -0,0 +1,139 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "sdvxhook2/config-gfx.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define SDVXHOOK2_CONFIG_GFX_FRAMED_KEY "gfx.framed"
|
||||
#define SDVXHOOK2_CONFIG_GFX_PCI_ID_KEY "gfx.pci_id"
|
||||
#define SDVXHOOK2_CONFIG_GFX_WINDOWED_KEY "gfx.windowed"
|
||||
#define SDVXHOOK2_CONFIG_GFX_WINDOW_WIDTH_KEY "gfx.window_width"
|
||||
#define SDVXHOOK2_CONFIG_GFX_WINDOW_HEIGHT_KEY "gfx.window_height"
|
||||
|
||||
#define SDVXHOOK2_CONFIG_GFX_DEFAULT_FRAMED_VALUE false
|
||||
#define SDVXHOOK2_CONFIG_GFX_DEFAULT_PCI_ID_VALUE "1002:7146"
|
||||
#define SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false
|
||||
#define SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE -1
|
||||
#define SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE -1
|
||||
|
||||
void sdvxhook2_config_gfx_init(struct cconfig *config)
|
||||
{
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_FRAMED_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_FRAMED_VALUE,
|
||||
"Run the game in a framed window (requires windowed option)");
|
||||
|
||||
cconfig_util_set_str(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_PCI_ID_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_PCI_ID_VALUE,
|
||||
"Patch the GPU device ID detection (leave empty to"
|
||||
" disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid)."
|
||||
" Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE,"
|
||||
" Radeon HD3450)");
|
||||
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOWED_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOWED_VALUE,
|
||||
"Run the game windowed");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOW_WIDTH_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE,
|
||||
"Windowed width, -1 for default size");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOW_HEIGHT_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE,
|
||||
"Windowed height, -1 for default size");
|
||||
}
|
||||
|
||||
void sdvxhook2_config_gfx_get(
|
||||
struct sdvxhook2_config_gfx *config_gfx, struct cconfig *config)
|
||||
{
|
||||
char tmp[10];
|
||||
char *vid;
|
||||
char *pid;
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_FRAMED_KEY,
|
||||
&config_gfx->framed,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_FRAMED_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
SDVXHOOK2_CONFIG_GFX_FRAMED_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_FRAMED_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_str(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_PCI_ID_KEY,
|
||||
tmp,
|
||||
sizeof(tmp) - 1,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_PCI_ID_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%s'",
|
||||
SDVXHOOK2_CONFIG_GFX_PCI_ID_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_PCI_ID_VALUE);
|
||||
}
|
||||
|
||||
if (tmp[4] != ':') {
|
||||
log_warning(
|
||||
"Invalid format for value for key '%s' specified, fallback "
|
||||
"to default '%s'",
|
||||
SDVXHOOK2_CONFIG_GFX_PCI_ID_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_PCI_ID_VALUE);
|
||||
strcpy(tmp, SDVXHOOK2_CONFIG_GFX_DEFAULT_PCI_ID_VALUE);
|
||||
}
|
||||
|
||||
tmp[4] = '\0';
|
||||
vid = tmp;
|
||||
pid = &tmp[5];
|
||||
config_gfx->pci_id_vid = strtol(vid, NULL, 16);
|
||||
config_gfx->pci_id_pid = strtol(pid, NULL, 16);
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOWED_KEY,
|
||||
&config_gfx->windowed,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOWED_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOWED_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOW_WIDTH_KEY,
|
||||
&config_gfx->window_width,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOW_WIDTH_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOW_HEIGHT_KEY,
|
||||
&config_gfx->window_height,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
SDVXHOOK2_CONFIG_GFX_WINDOW_HEIGHT_KEY,
|
||||
SDVXHOOK2_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE);
|
||||
}
|
||||
}
|
20
src/main/sdvxhook2/config-gfx.h
Normal file
20
src/main/sdvxhook2/config-gfx.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef SDVXHOOK2_CONFIG_GFX_H
|
||||
#define SDVXHOOK2_CONFIG_GFX_H
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
struct sdvxhook2_config_gfx {
|
||||
bool framed;
|
||||
uint16_t pci_id_vid;
|
||||
uint16_t pci_id_pid;
|
||||
bool windowed;
|
||||
int32_t window_width;
|
||||
int32_t window_height;
|
||||
};
|
||||
|
||||
void sdvxhook2_config_gfx_init(struct cconfig *config);
|
||||
|
||||
void sdvxhook2_config_gfx_get(
|
||||
struct sdvxhook2_config_gfx *config_gfx, struct cconfig *config);
|
||||
|
||||
#endif
|
76
src/main/sdvxhook2/config-io.c
Normal file
76
src/main/sdvxhook2/config-io.c
Normal file
@ -0,0 +1,76 @@
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "sdvxhook2/config-io.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY \
|
||||
"io.disable_card_reader_emu"
|
||||
#define SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY "io.disable_bio2_emu"
|
||||
#define SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter"
|
||||
|
||||
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false
|
||||
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false
|
||||
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false
|
||||
|
||||
void sdvxhook2_config_io_init(struct cconfig *config)
|
||||
{
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE,
|
||||
"Disable card reader emulation and enable usage of real card reader "
|
||||
"hardware on COM0 (for games supporting slotted readers)");
|
||||
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE,
|
||||
"Disable BIO2 emulation and enable usage of real BIO2 hardware");
|
||||
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE,
|
||||
"Disables the poll limiter, warning very high CPU usage may arise");
|
||||
}
|
||||
|
||||
void sdvxhook2_config_io_get(
|
||||
struct sdvxhook2_config_io *config_io, struct cconfig *config)
|
||||
{
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
|
||||
&config_io->disable_card_reader_emu,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY,
|
||||
&config_io->disable_bio2_emu,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
|
||||
&config_io->disable_poll_limiter,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
|
||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE);
|
||||
}
|
||||
}
|
19
src/main/sdvxhook2/config-io.h
Normal file
19
src/main/sdvxhook2/config-io.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef SDVXHOOK2_CONFIG_IO_H
|
||||
#define SDVXHOOK2_CONFIG_IO_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
struct sdvxhook2_config_io {
|
||||
bool disable_card_reader_emu;
|
||||
bool disable_bio2_emu;
|
||||
bool disable_poll_limiter;
|
||||
};
|
||||
|
||||
void sdvxhook2_config_io_init(struct cconfig *config);
|
||||
|
||||
void sdvxhook2_config_io_get(
|
||||
struct sdvxhook2_config_io *config_io, struct cconfig *config);
|
||||
|
||||
#endif
|
319
src/main/sdvxhook2/d3d9.c
Normal file
319
src/main/sdvxhook2/d3d9.c
Normal file
@ -0,0 +1,319 @@
|
||||
#define LOG_MODULE "d3d9-hook"
|
||||
|
||||
#include <d3d9.h>
|
||||
#include <d3dx9core.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hook/com-proxy.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "sdvxhook2/d3d9.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/time.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
// thanks to Felix for reminding Xyen to hook 9Ex instead of 9
|
||||
|
||||
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 HRESULT STDCALL my_CreateDeviceEx(
|
||||
IDirect3D9Ex *self,
|
||||
UINT adapter,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
D3DDISPLAYMODEEX *fdm,
|
||||
IDirect3DDevice9Ex **pdev);
|
||||
|
||||
static HRESULT STDCALL my_Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **api);
|
||||
|
||||
static BOOL STDCALL my_EnumDisplayDevicesA(
|
||||
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags);
|
||||
|
||||
static BOOL STDCALL
|
||||
my_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
|
||||
|
||||
static void calc_win_size_with_framed(
|
||||
HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp);
|
||||
|
||||
static HWND(STDCALL *real_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 HRESULT(STDCALL *real_Direct3DCreate9Ex)(
|
||||
UINT sdk_ver, IDirect3D9Ex **api);
|
||||
|
||||
static BOOL(STDCALL *real_EnumDisplayDevicesA)(
|
||||
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags);
|
||||
|
||||
static BOOL(STDCALL *real_MoveWindow)(
|
||||
HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static char d3d9_pci_id[32];
|
||||
static bool d3d9_windowed;
|
||||
static int32_t d3d9_window_width = -1;
|
||||
static int32_t d3d9_window_height = -1;
|
||||
static bool d3d9_window_framed;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static const struct hook_symbol d3d9_hook_syms[] = {
|
||||
{.name = "Direct3DCreate9Ex",
|
||||
.patch = my_Direct3DCreate9Ex,
|
||||
.link = (void **) &real_Direct3DCreate9Ex},
|
||||
};
|
||||
|
||||
static const struct hook_symbol d3d9_hook_user32_syms[] = {
|
||||
{.name = "EnumDisplayDevicesA",
|
||||
.patch = my_EnumDisplayDevicesA,
|
||||
.link = (void **) &real_EnumDisplayDevicesA},
|
||||
{.name = "CreateWindowExA",
|
||||
.patch = my_CreateWindowExA,
|
||||
.link = (void **) &real_CreateWindowExA},
|
||||
{.name = "MoveWindow",
|
||||
.patch = my_MoveWindow,
|
||||
.link = (void **) &real_MoveWindow},
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
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)
|
||||
{
|
||||
if (d3d9_windowed && d3d9_window_framed) {
|
||||
/* use a different style */
|
||||
dwStyle |= WS_OVERLAPPEDWINDOW;
|
||||
/* also show mouse cursor */
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
HWND hwnd = real_CreateWindowExA(
|
||||
dwExStyle,
|
||||
lpClassName,
|
||||
lpWindowName,
|
||||
dwStyle,
|
||||
X,
|
||||
Y,
|
||||
nWidth,
|
||||
nHeight,
|
||||
hWndParent,
|
||||
hMenu,
|
||||
hInstance,
|
||||
lpParam);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
static BOOL STDCALL
|
||||
my_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
|
||||
{
|
||||
if (d3d9_windowed && d3d9_window_framed) {
|
||||
/* 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) */
|
||||
|
||||
if (d3d9_window_width != -1 && d3d9_window_height != -1) {
|
||||
log_misc(
|
||||
"Overriding window size from %dx%d with %dx%d",
|
||||
nWidth,
|
||||
nHeight,
|
||||
d3d9_window_width,
|
||||
d3d9_window_height);
|
||||
|
||||
nWidth = d3d9_window_width;
|
||||
nHeight = d3d9_window_height;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
BOOL result = real_MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_CreateDeviceEx(
|
||||
IDirect3D9Ex *self,
|
||||
UINT adapter,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
D3DDISPLAYMODEEX *fdm,
|
||||
IDirect3DDevice9Ex **pdev)
|
||||
{
|
||||
IDirect3D9Ex *real = COM_PROXY_UNWRAP(self);
|
||||
HRESULT hr;
|
||||
|
||||
if (d3d9_windowed) {
|
||||
fdm = NULL;
|
||||
pp->Windowed = TRUE;
|
||||
pp->FullScreen_RefreshRateInHz = 0;
|
||||
}
|
||||
|
||||
hr = IDirect3D9Ex_CreateDeviceEx(
|
||||
real, adapter, type, hwnd, flags, pp, fdm, pdev);
|
||||
|
||||
// TODO stuff
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **api)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDirect3D9ExVtbl *api_vtbl;
|
||||
struct com_proxy *api_proxy;
|
||||
IDirect3D9Ex *api_;
|
||||
|
||||
log_info("Direct3DCreate9Ex hook hit");
|
||||
|
||||
hr = real_Direct3DCreate9Ex(sdk_ver, api);
|
||||
api_ = *api;
|
||||
api_proxy = com_proxy_wrap(api_, sizeof(*api_->lpVtbl));
|
||||
api_vtbl = api_proxy->vptr;
|
||||
|
||||
api_vtbl->CreateDeviceEx = my_CreateDeviceEx;
|
||||
|
||||
*api = (IDirect3D9Ex *) api_proxy;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static BOOL STDCALL my_EnumDisplayDevicesA(
|
||||
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags)
|
||||
{
|
||||
BOOL ok;
|
||||
|
||||
ok = real_EnumDisplayDevicesA(dev_name, dev_num, info, flags);
|
||||
|
||||
if (ok && d3d9_pci_id[0] != '\0') {
|
||||
/* Apparently Konami didn't read the "Not Used" message in the MSDN
|
||||
docs for DISPLAY_DEVICE */
|
||||
log_misc("Replacing device ID %s with %s", info->DeviceID, d3d9_pci_id);
|
||||
|
||||
str_cpy(info->DeviceID, sizeof(info->DeviceID), d3d9_pci_id);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void d3d9_hook_init(void)
|
||||
{
|
||||
hook_table_apply(
|
||||
NULL, "d3d9.dll", d3d9_hook_syms, lengthof(d3d9_hook_syms));
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"user32.dll",
|
||||
d3d9_hook_user32_syms,
|
||||
lengthof(d3d9_hook_user32_syms));
|
||||
|
||||
log_info("Inserted graphics hooks");
|
||||
}
|
||||
|
||||
void d3d9_set_windowed(bool framed, int32_t width, int32_t height)
|
||||
{
|
||||
d3d9_windowed = true;
|
||||
d3d9_window_framed = framed;
|
||||
d3d9_window_width = width;
|
||||
d3d9_window_height = height;
|
||||
}
|
||||
|
||||
void d3d9_set_pci_id(uint16_t vid, uint16_t pid)
|
||||
{
|
||||
str_format(
|
||||
d3d9_pci_id, sizeof(d3d9_pci_id), "PCI\\VEN_%04X&DEV_%04X", vid, pid);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
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;
|
||||
}
|
38
src/main/sdvxhook2/d3d9.h
Normal file
38
src/main/sdvxhook2/d3d9.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef SDVXHOOK2_D3D9_H
|
||||
#define SDVXHOOK2_D3D9_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Hook some d3d9 functions to patch gfx related stuff
|
||||
* like enabling window mode.
|
||||
*/
|
||||
void d3d9_hook_init(void);
|
||||
|
||||
/**
|
||||
* Set the game to window mode.
|
||||
*
|
||||
* @param framed True to add a window frame and make the window
|
||||
* movable, resizable, minizable. False for no frame.
|
||||
*/
|
||||
void d3d9_set_windowed(bool framed, int32_t width, int32_t height);
|
||||
|
||||
/**
|
||||
* Patch the GPU device ID detection to allow running the game with
|
||||
* other GPUs than the ones it is locked to.
|
||||
*
|
||||
* @param vid Vendor ID to patch.
|
||||
* @param pid Product ID to patch.
|
||||
*/
|
||||
void d3d9_set_pci_id(uint16_t vid, uint16_t pid);
|
||||
|
||||
/**
|
||||
* Set a framerate limit for the rendering loop.
|
||||
*
|
||||
* Use this if the game won't sync up properly with vsync enabled.
|
||||
*
|
||||
* @limit Number of frames to limit the rendering loop to
|
||||
*/
|
||||
void d3d9_set_frame_rate_limit(int limit);
|
||||
|
||||
#endif
|
184
src/main/sdvxhook2/dllmain.c
Normal file
184
src/main/sdvxhook2/dllmain.c
Normal file
@ -0,0 +1,184 @@
|
||||
#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 "bio2emu/emu.h"
|
||||
#include "sdvxhook2/bi2a.h"
|
||||
|
||||
#include "sdvxhook2/acio.h"
|
||||
#include "sdvxhook2/d3d9.h"
|
||||
#include "sdvxhook2/config-gfx.h"
|
||||
#include "sdvxhook2/config-io.h"
|
||||
|
||||
#include "camhook/cam.h"
|
||||
#include "camhook/config-cam.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/thread.h"
|
||||
|
||||
#define SDVXHOOK2_INFO_HEADER \
|
||||
"sdvxhook for VW" \
|
||||
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n"
|
||||
#define SDVXHOOK2_CMD_USAGE \
|
||||
"Usage: launcher.exe -K sdvxhook2.dll <soundvoltex.dll> [options...]"
|
||||
|
||||
static const irp_handler_t sdvxhook_handlers[] = {
|
||||
ac_io_port_dispatch_irp,
|
||||
bio2emu_port_dispatch_irp,
|
||||
};
|
||||
|
||||
struct sdvxhook2_config_io config_io;
|
||||
struct camhook_config_cam config_cam;
|
||||
struct sdvxhook2_config_gfx config_gfx;
|
||||
|
||||
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;
|
||||
|
||||
log_info("--- Begin sdvxhook dll_entry_init ---");
|
||||
|
||||
config = cconfig_init();
|
||||
|
||||
sdvxhook2_config_io_init(config);
|
||||
sdvxhook2_config_gfx_init(config);
|
||||
camhook_config_cam_init(config, 1);
|
||||
|
||||
if (!cconfig_hook_config_init(
|
||||
config,
|
||||
SDVXHOOK2_INFO_HEADER "\n" SDVXHOOK2_CMD_USAGE,
|
||||
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
|
||||
cconfig_finit(config);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sdvxhook2_config_io_get(&config_io, config);
|
||||
sdvxhook2_config_gfx_get(&config_gfx, config);
|
||||
camhook_config_cam_get(&config_cam, config, 1);
|
||||
|
||||
cconfig_finit(config);
|
||||
|
||||
log_info(SDVXHOOK2_INFO_HEADER);
|
||||
log_info("Initializing sdvxhook2...");
|
||||
|
||||
if (config_gfx.windowed) {
|
||||
d3d9_set_windowed(
|
||||
config_gfx.framed,
|
||||
config_gfx.window_width,
|
||||
config_gfx.window_height);
|
||||
}
|
||||
|
||||
if (config_gfx.pci_id_pid != 0 && config_gfx.pci_id_vid != 0) {
|
||||
d3d9_set_pci_id(config_gfx.pci_id_pid, config_gfx.pci_id_vid);
|
||||
}
|
||||
|
||||
/* Start up sdvxio.DLL */
|
||||
if (!config_io.disable_bio2_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");
|
||||
}
|
||||
}
|
||||
|
||||
/* Start up EAMIO.DLL */
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Initializing card reader backend");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!eam_io_init(
|
||||
avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader 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_io.disable_bio2_emu) {
|
||||
bio2emu_init();
|
||||
bio2_emu_bi2a_init(&bio2_emu, config_io.disable_poll_limiter);
|
||||
}
|
||||
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
ac_io_port_init();
|
||||
}
|
||||
|
||||
// camera hooks
|
||||
if (!config_cam.disable_emu) {
|
||||
camhook_init(&config_cam);
|
||||
}
|
||||
|
||||
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_io.disable_card_reader_emu) {
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
}
|
||||
|
||||
if (!config_io.disable_bio2_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();
|
||||
d3d9_hook_init();
|
||||
|
||||
end:
|
||||
return TRUE;
|
||||
}
|
4
src/main/sdvxhook2/sdvxhook2.def
Normal file
4
src/main/sdvxhook2/sdvxhook2.def
Normal file
@ -0,0 +1,4 @@
|
||||
LIBRARY sdvxhook2
|
||||
|
||||
EXPORTS
|
||||
DllMain@12 @1 NONAME
|
Loading…
Reference in New Issue
Block a user