Compare commits

..

4 Commits
5.37 ... 5.38

Author SHA1 Message Date
icex2
50ff026b85 Update changelog and docs for 5.38 release 2022-04-02 10:51:43 +02:00
Will Xyen
0ff6134b79 sdvxhook: address comments 2022-03-15 16:50:03 -07:00
Will Xyen
ae35b859d9 sdvxio-kfca: add volume overrides 2022-03-15 00:39:10 -07:00
Will Xyen
3cf3d44945 sdvxhook2: add nvapi and power hooks 2022-03-15 00:38:46 -07:00
19 changed files with 366 additions and 16 deletions

View File

@@ -2,6 +2,9 @@
Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions
given in tags. The pipeline will pick this up and cuts out the relevant section for release notes.
## 5.38
* sdvxhook2: Support sound voltex exceed gear
## 5.37
* jbhook1: Support jubeat (1) and ripples
* jbhook2: Support jubeat knit and copious

View File

@@ -517,7 +517,7 @@ $(zipdir)/sdvx-01-to-04.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx-05.zip: \
$(zipdir)/sdvx-05-to-06.zip: \
build/bin/avs2_1700-64/launcher.exe \
build/bin/avs2_1700-64/sdvxhook2.dll \
build/bin/indep-64/config.exe \
@@ -671,7 +671,7 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/jb-08.zip \
$(zipdir)/jb-hwio.zip \
$(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-to-06.zip \
$(zipdir)/sdvx-05-cn.zip \
$(zipdir)/sdvx-hwio-x86.zip \
$(zipdir)/sdvx-hwio-x64.zip \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5
[![pipeline status](https://dev.s-ul.net/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.net/djhackers/bemanitools/commits/master)
Version: 5.37
Version: 5.38
[Release history](CHANGELOG.md)
@@ -72,7 +72,8 @@ The tl;dr version and golden rules of the sections in the document:
* SOUND VOLTEX II -infinite infection- (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX III GRAVITY WARS (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX Vivid Wave (sdvx-05.zip) using sdvxhook2
* SOUND VOLTEX Vivid Wave (sdvx-05-to-06) using sdvxhook2
* SOUND VOLTEX EXCEED GEAR (sdvx-05-to-06) using sdvxhook2
## ViGEm clients: Expose BT5 APIs as XBOX game controllers
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that

View File

@@ -13,6 +13,15 @@ io.force_headphones=false
# Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest)
io.disable_file_hooks=false
# Disables the built in power control hooks, allowing game to modify system power settings
io.disable_power_hooks=false
# Disables the built in NVAPI control hooks, allowing game to modify system monitor settings
io.disable_nvapi_hooks=false
# Emulates the card reader on COM1 instead of COM2
io.com1_card_reader=false
# Run the game in a framed window (requires windowed option)
gfx.framed=true
@@ -43,6 +52,12 @@ gfx.device_adapter=-1
# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees
gfx.force_orientation=-1
# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.width=-1
# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.height=-1
# Disables the camera emulation
cam.disable_emu=false

View File

@@ -52,7 +52,7 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
config,
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE,
"Confine mouse coursor to window");
"Confine mouse cursor to window");
cconfig_util_set_int(
config,

View File

@@ -28,3 +28,5 @@ src_sdvxhook2 := \
bi2a.c \
dllmain.c \
config-io.c \
nvapi.c \
power.c \

View File

@@ -30,11 +30,16 @@
static struct ac_io_emu ac_io_emu;
static struct ac_io_emu_icca ac_io_emu_icca;
void ac_io_port_init(void)
void ac_io_port_init(bool use_new_reader)
{
ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2");
ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0);
if (use_new_reader) {
ac_io_emu_init(&ac_io_emu, L"COM1");
ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0);
ac_io_emu_icca_set_version(&ac_io_emu_icca, v170);
} else {
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);
}

View File

@@ -7,7 +7,7 @@
#include "hook/iohook.h"
void ac_io_port_init(void);
void ac_io_port_init(bool use_new_reader);
void ac_io_port_fini(void);
HRESULT ac_io_port_dispatch_irp(struct irp *irp);

View File

@@ -10,12 +10,19 @@
#define SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter"
#define SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY "io.force_headphones"
#define SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY "io.disable_file_hooks"
#define SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY "io.disable_power_hooks"
#define SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY "io.disable_nvapi_hooks"
#define SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY "io.com1_card_reader"
#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
#define SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE false
void sdvxhook2_config_io_init(struct cconfig *config)
{
@@ -49,6 +56,24 @@ void sdvxhook2_config_io_init(struct cconfig *config)
SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE,
"Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest)");
cconfig_util_set_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE,
"Disables the built in power control hooks, allowing game to modify system power settings");
cconfig_util_set_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE,
"Disables the built in NVAPI control hooks, allowing game to modify system monitor settings");
cconfig_util_set_bool(
config,
SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE,
"Emulates the card reader on COM1 instead of COM2");
}
void sdvxhook2_config_io_get(
@@ -113,4 +138,40 @@ void sdvxhook2_config_io_get(
SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE);
}
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY,
&config_io->disable_power_hooks,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE);
}
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY,
&config_io->disable_nvapi_hooks,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE);
}
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY,
&config_io->com1_card_reader,
SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE);
}
}

View File

@@ -11,6 +11,9 @@ struct sdvxhook2_config_io {
bool disable_poll_limiter;
bool force_headphones;
bool disable_file_hooks;
bool disable_power_hooks;
bool disable_nvapi_hooks;
bool com1_card_reader;
};
void sdvxhook2_config_io_init(struct cconfig *config);

View File

@@ -22,6 +22,8 @@
#include "sdvxhook2/acio.h"
#include "sdvxhook2/bi2a.h"
#include "sdvxhook2/config-io.h"
#include "sdvxhook2/nvapi.h"
#include "sdvxhook2/power.h"
#include "camhook/cam.h"
#include "camhook/config-cam.h"
@@ -147,14 +149,21 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
}
if (!config_io.disable_card_reader_emu) {
ac_io_port_init();
ac_io_port_init(config_io.com1_card_reader);
}
// camera hooks
if (!config_cam.disable_emu) {
camhook_init(&config_cam);
}
if (!config_io.disable_power_hooks) {
powerhook_init();
}
if (!config_io.disable_nvapi_hooks) {
nvapihook_init();
}
adapter_hook_override(config_adapter.override_ip);
log_info("--- End sdvxhook dll_entry_init ---");

View File

@@ -0,0 +1,71 @@
#define LOG_MODULE "power-hook"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <initguid.h>
// clang-format on
#include <powrprof.h>
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "sdvxhook2/nvapi.h"
#include "util/log.h"
static void *my_GetProcAddress(HMODULE dll, const char *name);
static void *(*real_GetProcAddress)(HMODULE dll, const char *name);
// nvapi64.dll
static void *my_nvapi_QueryInterface(uint32_t FunctionOffset);
static void *(*real_nvapi_QueryInterface)(uint32_t FunctionOffset);
static struct hook_symbol nvapihook_kernel_syms[] = {
{.name = "GetProcAddress",
.patch = my_GetProcAddress,
.link = (void *) &real_GetProcAddress},
};
static void *my_GetProcAddress(HMODULE dll, const char *name)
{
if (strcmp("nvapi_QueryInterface", name) == 0) {
log_info("Request for stub %s", name);
real_nvapi_QueryInterface = real_GetProcAddress(dll, name);
return &my_nvapi_QueryInterface;
}
// log_warning("Request for unknown stub %s", name);
return real_GetProcAddress(dll, name);
}
#define OFFSET_NvAPI_DISP_SetDisplayConfig 0x5D8CF8DE
static void *my_nvapi_QueryInterface(uint32_t FunctionOffset) {
if (FunctionOffset == OFFSET_NvAPI_DISP_SetDisplayConfig) {
log_info("Request for interface %x intercepted", FunctionOffset);
// no point stubbing this, the error checking for now doesn't check the response anyways
return NULL;
}
log_info("Request for interface %x passed", FunctionOffset);
return real_nvapi_QueryInterface(FunctionOffset);
}
void nvapihook_init()
{
hook_table_apply(
NULL,
"kernel32.dll",
nvapihook_kernel_syms,
lengthof(nvapihook_kernel_syms));
}
void nvapihook_fini(void)
{
return;
}

View File

@@ -0,0 +1,8 @@
#ifndef NVAPIHOOK_H
#define NVAPIHOOK_H
void nvapihook_init();
void nvapihook_fini(void);
#endif

View File

@@ -0,0 +1,86 @@
#define LOG_MODULE "power-hook"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <initguid.h>
// clang-format on
#include <powrprof.h>
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "sdvxhook2/power.h"
#include "util/log.h"
static DWORD
my_PowerSetActiveScheme(HKEY UserRootPowerKey, const GUID *SchemeGuid);
static DWORD my_PowerWriteACValueIndex(
HKEY RootPowerKey,
const GUID *SchemeGuid,
const GUID *SubGroupOfPowerSettingsGuid,
const GUID *PowerSettingGuid,
DWORD AcValueIndex);
static DWORD
my_PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **ActivePolicyGuid);
static DWORD (*real_PowerSetActiveScheme)(
HKEY UserRootPowerKey, const GUID *SchemeGuid);
static DWORD (*real_PowerWriteACValueIndex)(
HKEY RootPowerKey,
const GUID *SchemeGuid,
const GUID *SubGroupOfPowerSettingsGuid,
const GUID *PowerSettingGuid,
DWORD AcValueIndex);
static DWORD (*real_PowerGetActiveScheme)(
HKEY UserRootPowerKey, GUID **ActivePolicyGuid);
static const struct hook_symbol powerhook_pp_syms[] = {
{.name = "PowerGetActiveScheme",
.patch = my_PowerGetActiveScheme,
.link = (void **) &real_PowerGetActiveScheme},
{.name = "PowerWriteACValueIndex",
.patch = my_PowerWriteACValueIndex,
.link = (void **) &real_PowerWriteACValueIndex},
{.name = "PowerSetActiveScheme",
.patch = my_PowerSetActiveScheme,
.link = (void **) &real_PowerSetActiveScheme},
};
static DWORD
my_PowerSetActiveScheme(HKEY UserRootPowerKey, const GUID *SchemeGuid)
{
// stubbed
return 0;
}
static DWORD my_PowerWriteACValueIndex(
HKEY RootPowerKey,
const GUID *SchemeGuid,
const GUID *SubGroupOfPowerSettingsGuid,
const GUID *PowerSettingGuid,
DWORD AcValueIndex)
{
// stubbed
return 0;
}
static DWORD
my_PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **ActivePolicyGuid)
{
// stubbed
return 0;
}
void powerhook_init()
{
hook_table_apply(
NULL, "PowrProf.dll", powerhook_pp_syms, lengthof(powerhook_pp_syms));
}
void powerhook_fini(void)
{
return;
}

View File

@@ -0,0 +1,8 @@
#ifndef POWERHOOK_H
#define POWERHOOK_H
void powerhook_init();
void powerhook_fini(void);
#endif

View File

@@ -6,9 +6,15 @@
#define SDVXIO_KFCA_CONFIG_KFCA_PORT_KEY "kfca.port"
#define SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY "kfca.baud"
#define SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY "kfca.main_override"
#define SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY "kfca.headphone_override"
#define SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY "kfca.subwoofer_override"
#define SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_PORT_VALUE "COM3"
#define SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE 57600
#define SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE -1
#define SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE -1
#define SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE -1
void sdvxio_kfca_config_kfca_init(struct cconfig *config)
{
@@ -23,6 +29,24 @@ void sdvxio_kfca_config_kfca_init(struct cconfig *config)
SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY,
SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE,
"KFCA ACIO bus baudrate (real devices expect 57600)");
cconfig_util_set_int(
config,
SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE,
"SDVXIO digital amp main volume (0-96) 0 is high, 96 is low. -1 is no override.");
cconfig_util_set_int(
config,
SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE,
"SDVXIO digital amp headphone volume (0-96) 0 is high, 96 is low. -1 is no override.");
cconfig_util_set_int(
config,
SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE,
"SDVXIO digital amp subwoofer volume (0-96) 0 is high, 96 is low. -1 is no override.");
}
void sdvxio_kfca_config_kfca_get(
@@ -52,4 +76,40 @@ void sdvxio_kfca_config_kfca_get(
SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY,
SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE);
}
if (!cconfig_util_get_int(
config,
SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY,
&config_kfca->override_main_volume,
SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE);
}
if (!cconfig_util_get_int(
config,
SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY,
&config_kfca->override_headphone_volume,
SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE);
}
if (!cconfig_util_get_int(
config,
SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY,
&config_kfca->override_sub_volume,
SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE);
}
}

View File

@@ -8,6 +8,9 @@
struct sdvxio_kfca_config_kfca {
char port[64];
int32_t baud;
int32_t override_main_volume;
int32_t override_headphone_volume;
int32_t override_sub_volume;
};
void sdvxio_kfca_config_kfca_init(struct cconfig *config);

View File

@@ -120,9 +120,24 @@ bool sdvx_io_init(
if (kfca_node_id != -1) {
log_warning("Using KFCA on node: %d", kfca_node_id);
bool init_result = aciodrv_kfca_init(
uint8_t primary = 0;
uint8_t headphone = 0;
uint8_t subwoofer = 0;
if (config_kfca.override_main_volume >= 0) {
primary = config_kfca.override_main_volume;
}
if (config_kfca.override_headphone_volume >= 0) {
headphone = config_kfca.override_headphone_volume;
}
if (config_kfca.override_sub_volume >= 0) {
subwoofer = config_kfca.override_sub_volume;
}
bool init_result = aciodrv_kfca_amp(
aciomgr_port_checkout(acio_manager_ctx),
kfca_node_id);
kfca_node_id,
primary, headphone, 0, subwoofer);
aciomgr_port_checkin(acio_manager_ctx);
if (!init_result) {
@@ -240,7 +255,7 @@ bool sdvx_io_set_amp_volume(
bool amp_result = aciodrv_kfca_amp(
aciomgr_port_checkout(acio_manager_ctx),
kfca_node_id,
primary, 96, headphone, subwoofer);
primary, headphone, 96, subwoofer);
aciomgr_port_checkin(acio_manager_ctx);
if (!amp_result) {

View File

@@ -67,7 +67,7 @@ bool sdvx_io_read_input(void)
sdvx_io_gpio[0] = (pack >> 8) & 0x00FF;
sdvx_io_gpio[1] = (pack >> 16) & 0x00FF;
return 0;
return true;
}
uint8_t sdvx_io_get_input_gpio_sys(void)