mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-09-26 16:56:23 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff2a4b9a2c | ||
|
|
10bddd4905 | ||
|
|
ad5fbc1f5b | ||
|
|
25413bcba8 | ||
|
|
937290f93d | ||
|
|
d04598a570 | ||
|
|
bd382e5509 | ||
|
|
0d3fa54316 | ||
|
|
e8943edff6 | ||
|
|
61f3eb44d2 | ||
|
|
5aa1e27a31 |
@@ -1,4 +1,8 @@
|
|||||||
# Release history
|
# Release history
|
||||||
|
## 5.30
|
||||||
|
* SDVX: sdvxhook2 headphone force and cursor confining config options
|
||||||
|
* DDR: Add light support for SMX gen 4 pads
|
||||||
|
|
||||||
## 5.29
|
## 5.29
|
||||||
* SDVX: Add option for monitor rotation
|
* SDVX: Add option for monitor rotation
|
||||||
* SDVX: Add option to allow overriding network adapter IP
|
* SDVX: Add option to allow overriding network adapter IP
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ imps += avs avs-ea3
|
|||||||
include src/main/aciodrv/Module.mk
|
include src/main/aciodrv/Module.mk
|
||||||
include src/main/acioemu/Module.mk
|
include src/main/acioemu/Module.mk
|
||||||
include src/main/aciotest/Module.mk
|
include src/main/aciotest/Module.mk
|
||||||
|
include src/main/asio/Module.mk
|
||||||
include src/main/bio2emu/Module.mk
|
include src/main/bio2emu/Module.mk
|
||||||
include src/main/bsthook/Module.mk
|
include src/main/bsthook/Module.mk
|
||||||
include src/main/bstio/Module.mk
|
include src/main/bstio/Module.mk
|
||||||
@@ -88,6 +89,7 @@ include src/main/ddrhook/Module.mk
|
|||||||
include src/main/ddrio/Module.mk
|
include src/main/ddrio/Module.mk
|
||||||
include src/main/ddrio-smx/Module.mk
|
include src/main/ddrio-smx/Module.mk
|
||||||
include src/main/ddrio-mm/Module.mk
|
include src/main/ddrio-mm/Module.mk
|
||||||
|
include src/main/dinput/Module.mk
|
||||||
include src/main/eamio/Module.mk
|
include src/main/eamio/Module.mk
|
||||||
include src/main/eamio-icca/Module.mk
|
include src/main/eamio-icca/Module.mk
|
||||||
include src/main/eamiotest/Module.mk
|
include src/main/eamiotest/Module.mk
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Bemanitools 5
|
# Bemanitools 5
|
||||||
[](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
|
[](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
|
||||||
|
|
||||||
Version: 5.29</br>
|
Version: 5.30</br>
|
||||||
[Release history](CHANGELOG.md)
|
[Release history](CHANGELOG.md)
|
||||||
|
|
||||||
A collection of tools to run [various Bemani arcade games](#list-of-supported-games).
|
A collection of tools to run [various Bemani arcade games](#list-of-supported-games).
|
||||||
|
|||||||
6
dist/sdvx5/sdvxhook2.conf
vendored
6
dist/sdvx5/sdvxhook2.conf
vendored
@@ -7,12 +7,18 @@ io.disable_bio2_emu=false
|
|||||||
# Disables the poll limiter, warning very high CPU usage may arise
|
# Disables the poll limiter, warning very high CPU usage may arise
|
||||||
io.disable_poll_limiter=false
|
io.disable_poll_limiter=false
|
||||||
|
|
||||||
|
# Forces game to think headphones are attached
|
||||||
|
io.force_headphones=false
|
||||||
|
|
||||||
# Run the game in a framed window (requires windowed option)
|
# Run the game in a framed window (requires windowed option)
|
||||||
gfx.framed=true
|
gfx.framed=true
|
||||||
|
|
||||||
# Run the game windowed
|
# Run the game windowed
|
||||||
gfx.windowed=false
|
gfx.windowed=false
|
||||||
|
|
||||||
|
# Confine mouse coursor to window
|
||||||
|
gfx.confined=false
|
||||||
|
|
||||||
# Windowed width, -1 for default size
|
# Windowed width, -1 for default size
|
||||||
gfx.window_width=1080
|
gfx.window_width=1080
|
||||||
|
|
||||||
|
|||||||
@@ -61,14 +61,24 @@ SMX_EXTERN_C SMX_API void SMX_GetInfo(int pad, struct SMXInfo *info);
|
|||||||
// Get a mask of the currently pressed panels.
|
// Get a mask of the currently pressed panels.
|
||||||
SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
|
SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
|
||||||
|
|
||||||
// Update the lights. Both pads are always updated together. lightsData is a
|
// (deprecated) Equivalent to SMX_SetLights2(lightsData, 864).
|
||||||
// list of 8-bit RGB colors, one for each LED. Each panel has lights in the
|
SMX_API void SMX_SetLights(const char lightData[864]);
|
||||||
// following order:
|
|
||||||
|
// Update the lights. Both pads are always updated together. lightData is a list of 8-bit RGB
|
||||||
|
// colors, one for each LED.
|
||||||
//
|
//
|
||||||
// 0123
|
// lightDataSize is the number of bytes in lightsData. This should be 1350 (2 pads * 9 panels *
|
||||||
// 4567
|
// 25 lights * 3 RGB colors). For backwards-compatibility, this can also be 864.
|
||||||
// 89AB
|
//
|
||||||
// CDEF
|
// Each panel has lights in the following order:
|
||||||
|
//
|
||||||
|
// 00 01 02 03
|
||||||
|
// 16 17 18
|
||||||
|
// 04 05 06 07
|
||||||
|
// 19 20 21
|
||||||
|
// 08 09 10 11
|
||||||
|
// 22 23 24
|
||||||
|
// 12 13 14 15
|
||||||
//
|
//
|
||||||
// Panels are in the following order:
|
// Panels are in the following order:
|
||||||
//
|
//
|
||||||
@@ -76,17 +86,17 @@ SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
|
|||||||
// 345 CDE
|
// 345 CDE
|
||||||
// 678 F01
|
// 678 F01
|
||||||
//
|
//
|
||||||
// With 18 panels, 16 LEDs per panel and 3 bytes per LED, each light update has
|
// With 18 panels, 25 LEDs per panel and 3 bytes per LED, each light update has 1350 bytes of data.
|
||||||
// 864 bytes of data.
|
|
||||||
//
|
//
|
||||||
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a
|
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a best effort will be
|
||||||
// best effort will be made to send the most recent lights data available, but
|
// made to send the most recent lights data available, but the panels won't update more quickly.
|
||||||
// the panels won't update more quickly.
|
|
||||||
//
|
//
|
||||||
// The panels will return to automatic lighting if no lights are received for a
|
// The panels will return to automatic lighting if no lights are received for a while, so applications
|
||||||
// while, so applications controlling lights should send light updates
|
// controlling lights should send light updates continually, even if the lights aren't changing.
|
||||||
// continually, even if the lights aren't changing.
|
//
|
||||||
SMX_EXTERN_C SMX_API void SMX_SetLights(const char lightsData[864]);
|
// For backwards compatibility, if lightDataSize is 864, the old 4x4-only order is used,
|
||||||
|
// which simply omits lights 16-24.
|
||||||
|
SMX_API void SMX_SetLights2(const char *lightData, int lightDataSize);
|
||||||
|
|
||||||
// By default, the panels light automatically when stepped on. If a lights
|
// By default, the panels light automatically when stepped on. If a lights
|
||||||
// command is sent by the application, this stops happening to allow the
|
// command is sent by the application, this stops happening to allow the
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ EXPORTS
|
|||||||
SMX_GetInfo
|
SMX_GetInfo
|
||||||
SMX_GetInputState
|
SMX_GetInputState
|
||||||
SMX_SetLights
|
SMX_SetLights
|
||||||
|
SMX_SetLights2
|
||||||
SMX_ReenableAutoLights
|
SMX_ReenableAutoLights
|
||||||
SMX_GetConfig
|
SMX_GetConfig
|
||||||
SMX_SetConfig
|
SMX_SetConfig
|
||||||
|
|||||||
10
src/main/asio/Module.mk
Normal file
10
src/main/asio/Module.mk
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
libs += asio
|
||||||
|
|
||||||
|
libs_asio := \
|
||||||
|
hook \
|
||||||
|
hooklib \
|
||||||
|
util \
|
||||||
|
|
||||||
|
src_asio := \
|
||||||
|
asio-reghook.c \
|
||||||
|
config-asio.c \
|
||||||
199
src/main/asio/asio-reghook.c
Normal file
199
src/main/asio/asio-reghook.c
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#define LOG_MODULE "asio-reghook"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
// Don't format because the order is important here
|
||||||
|
#include <windows.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#include <winreg.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "hook/com-proxy.h"
|
||||||
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
#include "asio/asio-reghook.h"
|
||||||
|
|
||||||
|
#include "util/defs.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
#include "util/str.h"
|
||||||
|
#include "util/time.h"
|
||||||
|
|
||||||
|
// MAXDRVNAMELEN
|
||||||
|
#define ASIO_NAME_STRING_SIZE 128
|
||||||
|
|
||||||
|
static char asio_expected_name[ASIO_NAME_STRING_SIZE] = "XONAR SOUND CARD(64)";
|
||||||
|
static char asio_target_name[ASIO_NAME_STRING_SIZE] = "XONAR SOUND CARD(64)";
|
||||||
|
static HKEY asio_root_key;
|
||||||
|
static HKEY asio_sub_key;
|
||||||
|
|
||||||
|
LSTATUS my_RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);
|
||||||
|
|
||||||
|
LSTATUS my_RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cchName);
|
||||||
|
|
||||||
|
LSTATUS my_RegOpenKeyExA(
|
||||||
|
HKEY hKey,
|
||||||
|
LPCSTR lpSubKey,
|
||||||
|
DWORD ulOptions,
|
||||||
|
REGSAM samDesired,
|
||||||
|
PHKEY phkResult);
|
||||||
|
|
||||||
|
LSTATUS my_RegQueryValueExA(
|
||||||
|
HKEY hKey,
|
||||||
|
LPCSTR lpValueName,
|
||||||
|
LPDWORD lpReserved,
|
||||||
|
LPDWORD lpType,
|
||||||
|
LPBYTE lpData,
|
||||||
|
LPDWORD lpcbData);
|
||||||
|
|
||||||
|
LSTATUS my_RegCloseKey(HKEY hKey);
|
||||||
|
|
||||||
|
LSTATUS (*real_RegOpenKeyA)(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);
|
||||||
|
|
||||||
|
LSTATUS (*real_RegEnumKeyA)
|
||||||
|
(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cchName);
|
||||||
|
|
||||||
|
LSTATUS (*real_RegOpenKeyExA)
|
||||||
|
(HKEY hKey,
|
||||||
|
LPCSTR lpSubKey,
|
||||||
|
DWORD ulOptions,
|
||||||
|
REGSAM samDesired,
|
||||||
|
PHKEY phkResult);
|
||||||
|
|
||||||
|
LSTATUS (*real_RegQueryValueExA)
|
||||||
|
(HKEY hKey,
|
||||||
|
LPCSTR lpValueName,
|
||||||
|
LPDWORD lpReserved,
|
||||||
|
LPDWORD lpType,
|
||||||
|
LPBYTE lpData,
|
||||||
|
LPDWORD lpcbData);
|
||||||
|
|
||||||
|
LSTATUS (*real_RegCloseKey)(HKEY hKey);
|
||||||
|
|
||||||
|
static const struct hook_symbol asio_reghook_advapi32_syms[] = {
|
||||||
|
{.name = "RegOpenKeyA",
|
||||||
|
.patch = my_RegOpenKeyA,
|
||||||
|
.link = (void **) &real_RegOpenKeyA},
|
||||||
|
{.name = "RegEnumKeyA",
|
||||||
|
.patch = my_RegEnumKeyA,
|
||||||
|
.link = (void **) &real_RegEnumKeyA},
|
||||||
|
{.name = "RegOpenKeyExA",
|
||||||
|
.patch = my_RegOpenKeyExA,
|
||||||
|
.link = (void **) &real_RegOpenKeyExA},
|
||||||
|
{.name = "RegQueryValueExA",
|
||||||
|
.patch = my_RegQueryValueExA,
|
||||||
|
.link = (void **) &real_RegQueryValueExA},
|
||||||
|
{.name = "RegCloseKey",
|
||||||
|
.patch = my_RegCloseKey,
|
||||||
|
.link = (void **) &real_RegCloseKey},
|
||||||
|
};
|
||||||
|
|
||||||
|
LSTATUS my_RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
|
||||||
|
{
|
||||||
|
LSTATUS result = real_RegOpenKeyA(hKey, lpSubKey, phkResult);
|
||||||
|
|
||||||
|
if (!strcmp("software\\asio", lpSubKey)) {
|
||||||
|
log_info("ASIO root key found");
|
||||||
|
asio_root_key = *phkResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LSTATUS my_RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cchName)
|
||||||
|
{
|
||||||
|
LSTATUS result = real_RegEnumKeyA(hKey, dwIndex, lpName, cchName);
|
||||||
|
|
||||||
|
if (hKey == asio_root_key) {
|
||||||
|
if (!strcmp(asio_target_name, lpName)) {
|
||||||
|
log_info(
|
||||||
|
"Replacing key [%s] with [%s]",
|
||||||
|
asio_target_name,
|
||||||
|
asio_expected_name);
|
||||||
|
strncpy(lpName, asio_expected_name, cchName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LSTATUS my_RegOpenKeyExA(
|
||||||
|
HKEY hKey,
|
||||||
|
LPCSTR lpSubKey,
|
||||||
|
DWORD ulOptions,
|
||||||
|
REGSAM samDesired,
|
||||||
|
PHKEY phkResult)
|
||||||
|
{
|
||||||
|
if (hKey == asio_root_key) {
|
||||||
|
if (!strcmp(asio_expected_name, lpSubKey)) {
|
||||||
|
// swap to the real one so the call succeeds
|
||||||
|
LSTATUS result = real_RegOpenKeyExA(
|
||||||
|
hKey, asio_target_name, ulOptions, samDesired, phkResult);
|
||||||
|
|
||||||
|
asio_sub_key = *phkResult;
|
||||||
|
log_info("ASIO device key found");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
LSTATUS my_RegQueryValueExA(
|
||||||
|
HKEY hKey,
|
||||||
|
LPCSTR lpValueName,
|
||||||
|
LPDWORD lpReserved,
|
||||||
|
LPDWORD lpType,
|
||||||
|
LPBYTE lpData,
|
||||||
|
LPDWORD lpcbData)
|
||||||
|
{
|
||||||
|
DWORD lpcbData_orig = *lpcbData;
|
||||||
|
LSTATUS result = real_RegQueryValueExA(
|
||||||
|
hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||||
|
|
||||||
|
if (result == ERROR_SUCCESS) {
|
||||||
|
if (hKey == asio_sub_key) {
|
||||||
|
if (!strcmp("description", lpValueName)) {
|
||||||
|
log_info(
|
||||||
|
"Replacing description [%s] with [%s]",
|
||||||
|
lpData,
|
||||||
|
asio_expected_name);
|
||||||
|
strncpy((char *) lpData, asio_expected_name, lpcbData_orig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LSTATUS my_RegCloseKey(HKEY hKey)
|
||||||
|
{
|
||||||
|
if (hKey == asio_root_key) {
|
||||||
|
asio_root_key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hKey == asio_sub_key) {
|
||||||
|
asio_sub_key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_RegCloseKey(hKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void asio_reghook_init(const char *expected_name, const char *target_name)
|
||||||
|
{
|
||||||
|
strncpy(asio_expected_name, expected_name, ASIO_NAME_STRING_SIZE - 1);
|
||||||
|
strncpy(asio_target_name, target_name, ASIO_NAME_STRING_SIZE - 1);
|
||||||
|
|
||||||
|
asio_expected_name[ASIO_NAME_STRING_SIZE - 1] = '\0';
|
||||||
|
asio_target_name[ASIO_NAME_STRING_SIZE - 1] = '\0';
|
||||||
|
|
||||||
|
hook_table_apply(
|
||||||
|
NULL,
|
||||||
|
"Advapi32.dll",
|
||||||
|
asio_reghook_advapi32_syms,
|
||||||
|
lengthof(asio_reghook_advapi32_syms));
|
||||||
|
|
||||||
|
log_info("Inserted reg hooks for ASIO override");
|
||||||
|
}
|
||||||
6
src/main/asio/asio-reghook.h
Normal file
6
src/main/asio/asio-reghook.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef IASIO_REG_HOOK_H
|
||||||
|
#define IASIO_REG_HOOK_H
|
||||||
|
|
||||||
|
void asio_reghook_init(const char *expected_name, const char *target_name);
|
||||||
|
|
||||||
|
#endif
|
||||||
56
src/main/asio/config-asio.c
Normal file
56
src/main/asio/config-asio.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "cconfig/cconfig-util.h"
|
||||||
|
|
||||||
|
#include "asio/config-asio.h"
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
#define ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY "asio.force_asio"
|
||||||
|
#define ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY "asio.device_name"
|
||||||
|
|
||||||
|
#define ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE false
|
||||||
|
#define ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE \
|
||||||
|
"XONAR SOUND CARD(64)"
|
||||||
|
|
||||||
|
void asiohook_config_init(struct cconfig *config)
|
||||||
|
{
|
||||||
|
cconfig_util_set_bool(
|
||||||
|
config,
|
||||||
|
ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY,
|
||||||
|
ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE,
|
||||||
|
"Force ASIO audio mode/device");
|
||||||
|
|
||||||
|
cconfig_util_set_str(
|
||||||
|
config,
|
||||||
|
ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY,
|
||||||
|
ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE,
|
||||||
|
"The ASIO device name to use");
|
||||||
|
}
|
||||||
|
|
||||||
|
void asiohook_config_asio_get(
|
||||||
|
struct asiohook_config_asio *config_asio, struct cconfig *config)
|
||||||
|
{
|
||||||
|
if (!cconfig_util_get_bool(
|
||||||
|
config,
|
||||||
|
ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY,
|
||||||
|
&config_asio->force_asio,
|
||||||
|
ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE)) {
|
||||||
|
log_warning(
|
||||||
|
"Invalid value for key '%s' specified, fallback "
|
||||||
|
"to default '%d'",
|
||||||
|
ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY,
|
||||||
|
ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cconfig_util_get_str(
|
||||||
|
config,
|
||||||
|
ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY,
|
||||||
|
config_asio->replacement_name,
|
||||||
|
sizeof(config_asio->replacement_name) - 1,
|
||||||
|
ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE)) {
|
||||||
|
log_warning(
|
||||||
|
"Invalid value for key '%s' specified, fallback "
|
||||||
|
"to default '%s'",
|
||||||
|
ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY,
|
||||||
|
ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/main/asio/config-asio.h
Normal file
18
src/main/asio/config-asio.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef ASIOHOOK_CONFIG_IO_H
|
||||||
|
#define ASIOHOOK_CONFIG_IO_H
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "cconfig/cconfig.h"
|
||||||
|
|
||||||
|
struct asiohook_config_asio {
|
||||||
|
bool force_asio;
|
||||||
|
char replacement_name[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
void asiohook_config_init(struct cconfig *config);
|
||||||
|
|
||||||
|
void asiohook_config_asio_get(
|
||||||
|
struct asiohook_config_asio *config_asio, struct cconfig *config);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY "gfx.framed"
|
#define D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY "gfx.framed"
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_WINDOWED_KEY "gfx.windowed"
|
#define D3D9EXHOOK_CONFIG_GFX_WINDOWED_KEY "gfx.windowed"
|
||||||
|
#define D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY "gfx.confined"
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY "gfx.window_width"
|
#define D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY "gfx.window_width"
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY "gfx.window_height"
|
#define D3D9EXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY "gfx.window_height"
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate"
|
#define D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate"
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
|
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false
|
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false
|
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false
|
||||||
|
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE false
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE -1
|
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE -1
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE -1
|
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE -1
|
||||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1
|
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1
|
||||||
@@ -38,6 +40,12 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
|
|||||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE,
|
D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE,
|
||||||
"Run the game windowed");
|
"Run the game windowed");
|
||||||
|
|
||||||
|
cconfig_util_set_bool(
|
||||||
|
config,
|
||||||
|
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
|
||||||
|
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE,
|
||||||
|
"Confine mouse coursor to window");
|
||||||
|
|
||||||
cconfig_util_set_int(
|
cconfig_util_set_int(
|
||||||
config,
|
config,
|
||||||
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,
|
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,
|
||||||
@@ -99,6 +107,18 @@ void d3d9exhook_config_gfx_get(
|
|||||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE);
|
D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cconfig_util_get_bool(
|
||||||
|
config,
|
||||||
|
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
|
||||||
|
&config_gfx->confined,
|
||||||
|
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE)) {
|
||||||
|
log_warning(
|
||||||
|
"Invalid value for key '%s' specified, fallback "
|
||||||
|
"to default '%d'",
|
||||||
|
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
|
||||||
|
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
if (!cconfig_util_get_int(
|
if (!cconfig_util_get_int(
|
||||||
config,
|
config,
|
||||||
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,
|
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
struct d3d9exhook_config_gfx {
|
struct d3d9exhook_config_gfx {
|
||||||
bool framed;
|
bool framed;
|
||||||
bool windowed;
|
bool windowed;
|
||||||
|
bool confined;
|
||||||
int32_t window_width;
|
int32_t window_width;
|
||||||
int32_t window_height;
|
int32_t window_height;
|
||||||
int32_t forced_refresh_rate;
|
int32_t forced_refresh_rate;
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ static HRESULT STDCALL my_CreateDeviceEx(
|
|||||||
|
|
||||||
static HRESULT STDCALL my_Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **api);
|
static HRESULT STDCALL my_Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **api);
|
||||||
|
|
||||||
|
static WNDPROC real_WndProc;
|
||||||
|
|
||||||
static BOOL STDCALL my_EnumDisplayDevicesA(
|
static BOOL STDCALL my_EnumDisplayDevicesA(
|
||||||
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags);
|
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags);
|
||||||
|
|
||||||
@@ -82,6 +84,7 @@ static BOOL(STDCALL *real_MoveWindow)(
|
|||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static bool d3d9ex_windowed;
|
static bool d3d9ex_windowed;
|
||||||
|
static bool d3d9ex_confined;
|
||||||
static int32_t d3d9ex_force_refresh_rate = -1;
|
static int32_t d3d9ex_force_refresh_rate = -1;
|
||||||
static int32_t d3d9ex_window_width = -1;
|
static int32_t d3d9ex_window_width = -1;
|
||||||
static int32_t d3d9ex_window_height = -1;
|
static int32_t d3d9ex_window_height = -1;
|
||||||
@@ -183,6 +186,52 @@ my_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LRESULT gfx_confine(HWND hwnd)
|
||||||
|
{
|
||||||
|
POINT p;
|
||||||
|
RECT r;
|
||||||
|
|
||||||
|
log_misc("Confining mouse (ALT-TAB to release)");
|
||||||
|
|
||||||
|
p.x = 0;
|
||||||
|
p.y = 0;
|
||||||
|
|
||||||
|
ClientToScreen(hwnd, &p);
|
||||||
|
|
||||||
|
r.left = p.x;
|
||||||
|
r.top = p.y;
|
||||||
|
r.right = p.x + 100;
|
||||||
|
r.bottom = p.y + 100;
|
||||||
|
|
||||||
|
ClipCursor(&r);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT gfx_unconfine(HWND hwnd)
|
||||||
|
{
|
||||||
|
log_misc("Un-confining mouse");
|
||||||
|
|
||||||
|
ClipCursor(NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK
|
||||||
|
my_WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
switch (msg) {
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
return gfx_confine(hwnd);
|
||||||
|
|
||||||
|
case WM_KILLFOCUS:
|
||||||
|
return gfx_unconfine(hwnd);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return CallWindowProc(real_WndProc, hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT STDCALL my_CreateDeviceEx(
|
static HRESULT STDCALL my_CreateDeviceEx(
|
||||||
IDirect3D9Ex *self,
|
IDirect3D9Ex *self,
|
||||||
UINT adapter,
|
UINT adapter,
|
||||||
@@ -268,6 +317,12 @@ static HRESULT STDCALL my_CreateDeviceEx(
|
|||||||
hr = IDirect3D9Ex_CreateDeviceEx(
|
hr = IDirect3D9Ex_CreateDeviceEx(
|
||||||
real, adapter, type, hwnd, flags, pp, fdm, pdev);
|
real, adapter, type, hwnd, flags, pp, fdm, pdev);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && d3d9ex_confined) {
|
||||||
|
real_WndProc = (void *) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
|
||||||
|
|
||||||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (uintptr_t) my_WndProc);
|
||||||
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,6 +374,7 @@ void d3d9ex_hook_init(void)
|
|||||||
void d3d9ex_configure(struct d3d9exhook_config_gfx *gfx_config)
|
void d3d9ex_configure(struct d3d9exhook_config_gfx *gfx_config)
|
||||||
{
|
{
|
||||||
d3d9ex_windowed = gfx_config->windowed;
|
d3d9ex_windowed = gfx_config->windowed;
|
||||||
|
d3d9ex_confined = gfx_config->confined;
|
||||||
d3d9ex_window_framed = gfx_config->framed;
|
d3d9ex_window_framed = gfx_config->framed;
|
||||||
d3d9ex_window_width = gfx_config->window_width;
|
d3d9ex_window_width = gfx_config->window_width;
|
||||||
d3d9ex_window_height = gfx_config->window_height;
|
d3d9ex_window_height = gfx_config->window_height;
|
||||||
|
|||||||
@@ -41,24 +41,28 @@ static const struct ddr_io_smx_pad_map ddr_io_smx_pad_map[] = {
|
|||||||
{1, 1 << 7, 1 << DDR_P2_DOWN},
|
{1, 1 << 7, 1 << DDR_P2_DOWN},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DDR_IO_SMX_LIGHT_VALUES_PER_PANEL 75
|
||||||
|
#define DDR_IO_SMX_NUMBER_OF_PANELS 18
|
||||||
|
#define DDR_IO_SMX_TOTAL_LIGHT_VALUES DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * DDR_IO_SMX_NUMBER_OF_PANELS
|
||||||
|
|
||||||
static const struct ddr_io_smx_light_map ddr_io_smx_light_map[] = {
|
static const struct ddr_io_smx_light_map ddr_io_smx_light_map[] = {
|
||||||
/* Light L/R blue and U/D red to match DDR pad color scheme */
|
/* Light L/R blue and U/D red to match DDR pad color scheme */
|
||||||
|
|
||||||
{1 << LIGHT_P1_UP, 48 * 1, 0xFF, 0x00, 0x00},
|
{1 << LIGHT_P1_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 1, 0xFF, 0x00, 0x00},
|
||||||
{1 << LIGHT_P1_LEFT, 48 * 3, 0x00, 0x00, 0xFF},
|
{1 << LIGHT_P1_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 3, 0x00, 0x00, 0xFF},
|
||||||
{1 << LIGHT_P1_RIGHT, 48 * 5, 0x00, 0x00, 0xFF},
|
{1 << LIGHT_P1_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 5, 0x00, 0x00, 0xFF},
|
||||||
{1 << LIGHT_P1_DOWN, 48 * 7, 0xFF, 0x00, 0x00},
|
{1 << LIGHT_P1_DOWN, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 7, 0xFF, 0x00, 0x00},
|
||||||
|
|
||||||
{1 << LIGHT_P2_UP, 48 * 10, 0xFF, 0x00, 0x00},
|
{1 << LIGHT_P2_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 10, 0xFF, 0x00, 0x00},
|
||||||
{1 << LIGHT_P2_LEFT, 48 * 12, 0x00, 0x00, 0xFF},
|
{1 << LIGHT_P2_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 12, 0x00, 0x00, 0xFF},
|
||||||
{1 << LIGHT_P2_RIGHT, 48 * 14, 0x00, 0x00, 0xFF},
|
{1 << LIGHT_P2_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 14, 0x00, 0x00, 0xFF},
|
||||||
{1 << LIGHT_P2_DOWN, 48 * 16, 0xFF, 0x00, 0x00},
|
{1 << LIGHT_P2_DOWN, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 16, 0xFF, 0x00, 0x00},
|
||||||
};
|
};
|
||||||
|
|
||||||
static _Atomic uint32_t ddr_io_smx_pad_state[2];
|
static _Atomic uint32_t ddr_io_smx_pad_state[2];
|
||||||
static CRITICAL_SECTION ddr_io_smx_lights_lock;
|
static CRITICAL_SECTION ddr_io_smx_lights_lock;
|
||||||
static uint8_t ddr_io_smx_lights_counter;
|
static uint8_t ddr_io_smx_lights_counter;
|
||||||
static char ddr_io_smx_lights[864];
|
static char ddr_io_smx_lights[DDR_IO_SMX_TOTAL_LIGHT_VALUES];
|
||||||
|
|
||||||
void ddr_io_set_loggers(
|
void ddr_io_set_loggers(
|
||||||
log_formatter_t misc,
|
log_formatter_t misc,
|
||||||
@@ -109,7 +113,7 @@ uint32_t ddr_io_read_pad(void)
|
|||||||
EnterCriticalSection(&ddr_io_smx_lights_lock);
|
EnterCriticalSection(&ddr_io_smx_lights_lock);
|
||||||
|
|
||||||
if (ddr_io_smx_lights_counter == 0) {
|
if (ddr_io_smx_lights_counter == 0) {
|
||||||
SMX_SetLights(ddr_io_smx_lights);
|
SMX_SetLights2(ddr_io_smx_lights, lengthof(ddr_io_smx_lights));
|
||||||
}
|
}
|
||||||
|
|
||||||
ddr_io_smx_lights_counter++;
|
ddr_io_smx_lights_counter++;
|
||||||
@@ -149,7 +153,7 @@ void ddr_io_set_lights_extio(uint32_t lights)
|
|||||||
if (lights & map->extio_bit) {
|
if (lights & map->extio_bit) {
|
||||||
offset = map->smx_light_offset;
|
offset = map->smx_light_offset;
|
||||||
|
|
||||||
for (j = 0; j < 48; j += 3) {
|
for (j = 0; j < DDR_IO_SMX_LIGHT_VALUES_PER_PANEL; j += 3) {
|
||||||
ddr_io_smx_lights[offset + j] = map->r;
|
ddr_io_smx_lights[offset + j] = map->r;
|
||||||
ddr_io_smx_lights[offset + j + 1] = map->g;
|
ddr_io_smx_lights[offset + j + 1] = map->g;
|
||||||
ddr_io_smx_lights[offset + j + 2] = map->b;
|
ddr_io_smx_lights[offset + j + 2] = map->b;
|
||||||
|
|||||||
10
src/main/dinput/Module.mk
Normal file
10
src/main/dinput/Module.mk
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
libs += dinput
|
||||||
|
|
||||||
|
libs_dinput := \
|
||||||
|
hook \
|
||||||
|
hooklib \
|
||||||
|
util \
|
||||||
|
|
||||||
|
src_dinput := \
|
||||||
|
dinput.c \
|
||||||
|
device_dinput8.c \
|
||||||
307
src/main/dinput/device_dinput8.c
Normal file
307
src/main/dinput/device_dinput8.c
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
#include "dinput/device_dinput8.h"
|
||||||
|
|
||||||
|
static ULONG REF_COUNT = 0;
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_QueryInterface(
|
||||||
|
IDirectInputDevice8W FAR *This, REFIID riid, void **ppvObj)
|
||||||
|
{
|
||||||
|
if (ppvObj == NULL) {
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDeviceA) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDeviceW) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDevice2A) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDevice2W) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDevice7A) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDevice7W) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDevice8A) ||
|
||||||
|
IsEqualGUID(riid, &IID_IDirectInputDevice8W)) {
|
||||||
|
This->lpVtbl->AddRef(This);
|
||||||
|
*ppvObj = This;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG STDMETHODCALLTYPE
|
||||||
|
IDirectInputDevice8W_AddRef(IDirectInputDevice8W FAR *This)
|
||||||
|
{
|
||||||
|
return ++REF_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG STDMETHODCALLTYPE
|
||||||
|
IDirectInputDevice8W_Release(IDirectInputDevice8W FAR *This)
|
||||||
|
{
|
||||||
|
return --REF_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetCapabilities(
|
||||||
|
IDirectInputDevice8W FAR *This, LPDIDEVCAPS lpDIDevCaps)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumObjects(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
|
||||||
|
LPVOID pvRef,
|
||||||
|
DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetProperty(
|
||||||
|
IDirectInputDevice8W FAR *This, REFGUID rguidProp, LPDIPROPHEADER pdiph)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetProperty(
|
||||||
|
IDirectInputDevice8W FAR *This, REFGUID rguidProp, LPCDIPROPHEADER pdiph)
|
||||||
|
{
|
||||||
|
return DI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE
|
||||||
|
IDirectInputDevice8W_Acquire(IDirectInputDevice8W FAR *This)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE
|
||||||
|
IDirectInputDevice8W_Unacquire(IDirectInputDevice8W FAR *This)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetDeviceState(
|
||||||
|
IDirectInputDevice8W FAR *This, DWORD cbData, LPVOID lpvData)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetDeviceData(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
DWORD cbObjectData,
|
||||||
|
LPDIDEVICEOBJECTDATA rgdod,
|
||||||
|
LPDWORD pdwInOut,
|
||||||
|
DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetDataFormat(
|
||||||
|
IDirectInputDevice8W FAR *This, LPCDIDATAFORMAT lpdf)
|
||||||
|
{
|
||||||
|
return DI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetEventNotification(
|
||||||
|
IDirectInputDevice8W FAR *This, HANDLE hEvent)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetCooperativeLevel(
|
||||||
|
IDirectInputDevice8W FAR *This, HWND hWnd, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetObjectInfo(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPDIDEVICEOBJECTINSTANCEW pdidoi,
|
||||||
|
DWORD dwObj,
|
||||||
|
DWORD dwHow)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetDeviceInfo(
|
||||||
|
IDirectInputDevice8W FAR *This, LPDIDEVICEINSTANCEW pdidi)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_RunControlPanel(
|
||||||
|
IDirectInputDevice8W FAR *This, HWND hwndOwner, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_Initialize(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
HINSTANCE hinst,
|
||||||
|
DWORD dwVersion,
|
||||||
|
REFGUID rguid)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_CreateEffect(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
REFGUID rguid,
|
||||||
|
LPCDIEFFECT lpeff,
|
||||||
|
LPDIRECTINPUTEFFECT *ppdeff,
|
||||||
|
LPUNKNOWN punkOuter)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumEffects(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPDIENUMEFFECTSCALLBACKW lpCallback,
|
||||||
|
LPVOID pvRef,
|
||||||
|
DWORD dwEffType)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetEffectInfo(
|
||||||
|
IDirectInputDevice8W FAR *This, LPDIEFFECTINFOW pdei, REFGUID rguid)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetForceFeedbackState(
|
||||||
|
IDirectInputDevice8W FAR *This, LPDWORD pdwOut)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SendForceFeedbackCommand(
|
||||||
|
IDirectInputDevice8W FAR *This, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumCreatedEffectObjects(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
|
||||||
|
LPVOID pvRef,
|
||||||
|
DWORD fl)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE
|
||||||
|
IDirectInputDevice8W_Escape(IDirectInputDevice8W FAR *This, LPDIEFFESCAPE pesc)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE
|
||||||
|
IDirectInputDevice8W_Poll(IDirectInputDevice8W FAR *This)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SendDeviceData(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
DWORD cbObjectData,
|
||||||
|
LPCDIDEVICEOBJECTDATA rgdod,
|
||||||
|
LPDWORD pdwInOut,
|
||||||
|
DWORD fl)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumEffectsInFile(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPCWSTR lpszFileName,
|
||||||
|
LPDIENUMEFFECTSINFILECALLBACK pec,
|
||||||
|
LPVOID pvRef,
|
||||||
|
DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_WriteEffectToFile(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPCWSTR lpszFileName,
|
||||||
|
DWORD dwEntries,
|
||||||
|
LPDIFILEEFFECT rgDiFileEft,
|
||||||
|
DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_BuildActionMap(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPDIACTIONFORMATW lpdiaf,
|
||||||
|
LPCWSTR lpszUserName,
|
||||||
|
DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetActionMap(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPDIACTIONFORMATW lpdiaf,
|
||||||
|
LPCWSTR lpszUserName,
|
||||||
|
DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetImageInfo(
|
||||||
|
IDirectInputDevice8W FAR *This,
|
||||||
|
LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
|
||||||
|
{
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IDirectInputDevice8WVtbl stub_device_vtbl = {
|
||||||
|
|
||||||
|
// IUnknown
|
||||||
|
.QueryInterface = IDirectInputDevice8W_QueryInterface,
|
||||||
|
.AddRef = IDirectInputDevice8W_AddRef,
|
||||||
|
.Release = IDirectInputDevice8W_Release,
|
||||||
|
|
||||||
|
// IDirectInputDeviceW
|
||||||
|
.GetCapabilities = IDirectInputDevice8W_GetCapabilities,
|
||||||
|
.EnumObjects = IDirectInputDevice8W_EnumObjects,
|
||||||
|
.GetProperty = IDirectInputDevice8W_GetProperty,
|
||||||
|
.SetProperty = IDirectInputDevice8W_SetProperty,
|
||||||
|
.Acquire = IDirectInputDevice8W_Acquire,
|
||||||
|
.Unacquire = IDirectInputDevice8W_Unacquire,
|
||||||
|
.GetDeviceState = IDirectInputDevice8W_GetDeviceState,
|
||||||
|
.GetDeviceData = IDirectInputDevice8W_GetDeviceData,
|
||||||
|
.SetDataFormat = IDirectInputDevice8W_SetDataFormat,
|
||||||
|
.SetEventNotification = IDirectInputDevice8W_SetEventNotification,
|
||||||
|
.SetCooperativeLevel = IDirectInputDevice8W_SetCooperativeLevel,
|
||||||
|
.GetObjectInfo = IDirectInputDevice8W_GetObjectInfo,
|
||||||
|
.GetDeviceInfo = IDirectInputDevice8W_GetDeviceInfo,
|
||||||
|
.RunControlPanel = IDirectInputDevice8W_RunControlPanel,
|
||||||
|
.Initialize = IDirectInputDevice8W_Initialize,
|
||||||
|
|
||||||
|
// IDirectInputDevice2W
|
||||||
|
.CreateEffect = IDirectInputDevice8W_CreateEffect,
|
||||||
|
.EnumEffects = IDirectInputDevice8W_EnumEffects,
|
||||||
|
.GetEffectInfo = IDirectInputDevice8W_GetEffectInfo,
|
||||||
|
.GetForceFeedbackState = IDirectInputDevice8W_GetForceFeedbackState,
|
||||||
|
.SendForceFeedbackCommand = IDirectInputDevice8W_SendForceFeedbackCommand,
|
||||||
|
.EnumCreatedEffectObjects = IDirectInputDevice8W_EnumCreatedEffectObjects,
|
||||||
|
.Escape = IDirectInputDevice8W_Escape,
|
||||||
|
.Poll = IDirectInputDevice8W_Poll,
|
||||||
|
.SendDeviceData = IDirectInputDevice8W_SendDeviceData,
|
||||||
|
|
||||||
|
// IDirectInputDevice7W
|
||||||
|
.EnumEffectsInFile = IDirectInputDevice8W_EnumEffectsInFile,
|
||||||
|
.WriteEffectToFile = IDirectInputDevice8W_WriteEffectToFile,
|
||||||
|
|
||||||
|
// IDirectInputDevice8W
|
||||||
|
.BuildActionMap = IDirectInputDevice8W_BuildActionMap,
|
||||||
|
.SetActionMap = IDirectInputDevice8W_SetActionMap,
|
||||||
|
.GetImageInfo = IDirectInputDevice8W_GetImageInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
static IDirectInputDevice8W stub_device_object = {
|
||||||
|
.lpVtbl = &stub_device_vtbl,
|
||||||
|
};
|
||||||
|
|
||||||
|
IDirectInputDevice8W *di8_stub_device = &stub_device_object;
|
||||||
10
src/main/dinput/device_dinput8.h
Normal file
10
src/main/dinput/device_dinput8.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef DINPUTHOOK_DEVICES_DINPUT8_H
|
||||||
|
#define DINPUTHOOK_DEVICES_DINPUT8_H
|
||||||
|
|
||||||
|
#include <initguid.h>
|
||||||
|
|
||||||
|
#include <dinput.h>
|
||||||
|
|
||||||
|
extern IDirectInputDevice8W *di8_stub_device;
|
||||||
|
|
||||||
|
#endif
|
||||||
114
src/main/dinput/dinput.c
Normal file
114
src/main/dinput/dinput.c
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define DIRECTINPUT_VERSION 0x0800
|
||||||
|
#include <dinput.h>
|
||||||
|
|
||||||
|
#include "dinput/device_dinput8.h"
|
||||||
|
#include "dinput/dinput.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "hook/com-proxy.h"
|
||||||
|
#include "hook/pe.h"
|
||||||
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
#include "util/defs.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
static HRESULT STDCALL my_DirectInput8Create(
|
||||||
|
HINSTANCE hinst,
|
||||||
|
DWORD dwVersion,
|
||||||
|
REFIID riidltf,
|
||||||
|
LPVOID *ppvOut,
|
||||||
|
LPVOID punkOuter);
|
||||||
|
|
||||||
|
static HRESULT(STDCALL *real_DirectInput8Create)(
|
||||||
|
HINSTANCE hinst,
|
||||||
|
DWORD dwVersion,
|
||||||
|
REFIID riidltf,
|
||||||
|
LPVOID *ppvOut,
|
||||||
|
LPVOID punkOuter);
|
||||||
|
|
||||||
|
static const struct hook_symbol dinput_syms[] = {
|
||||||
|
{
|
||||||
|
.name = "DirectInput8Create",
|
||||||
|
.patch = my_DirectInput8Create,
|
||||||
|
.link = (void **) &real_DirectInput8Create,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static HRESULT STDCALL my_CreateDevice(
|
||||||
|
IDirectInput8W *self,
|
||||||
|
REFGUID rguid,
|
||||||
|
LPDIRECTINPUTDEVICE8W *lplpDirectInputDevice,
|
||||||
|
LPUNKNOWN pUnkOuter)
|
||||||
|
{
|
||||||
|
log_misc("IDirectInput8::CreateDevice hook hit");
|
||||||
|
|
||||||
|
if (lplpDirectInputDevice == NULL) {
|
||||||
|
return DIERR_INVALIDPARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsEqualGUID(rguid, &GUID_SysKeyboard) ||
|
||||||
|
IsEqualGUID(rguid, &GUID_SysMouse)) {
|
||||||
|
log_misc("Returning stub device");
|
||||||
|
|
||||||
|
*lplpDirectInputDevice = di8_stub_device;
|
||||||
|
di8_stub_device->lpVtbl->AddRef(di8_stub_device);
|
||||||
|
|
||||||
|
return DI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DIERR_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDCALL my_EnumDevices(
|
||||||
|
IDirectInput8W *self,
|
||||||
|
DWORD dwDevType,
|
||||||
|
LPDIENUMDEVICESCALLBACKW lpCallback,
|
||||||
|
LPVOID pvRef,
|
||||||
|
DWORD dwFlags)
|
||||||
|
{
|
||||||
|
log_misc("IDirectInput8::EnumDevices hook hit");
|
||||||
|
|
||||||
|
return DI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDCALL my_DirectInput8Create(
|
||||||
|
HINSTANCE hinst,
|
||||||
|
DWORD dwVersion,
|
||||||
|
REFIID riidltf,
|
||||||
|
LPVOID *ppvOut,
|
||||||
|
LPVOID punkOuter)
|
||||||
|
{
|
||||||
|
IDirectInput8W *api;
|
||||||
|
IDirectInput8WVtbl *api_vtbl;
|
||||||
|
struct com_proxy *api_proxy;
|
||||||
|
HRESULT res;
|
||||||
|
|
||||||
|
log_info("DirectInput8Create hook hit");
|
||||||
|
|
||||||
|
res = real_DirectInput8Create(
|
||||||
|
hinst, dwVersion, riidltf, (LPVOID *) &api, punkOuter);
|
||||||
|
|
||||||
|
if (res != DI_OK) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
|
||||||
|
api_vtbl = api_proxy->vptr;
|
||||||
|
|
||||||
|
api_vtbl->EnumDevices = my_EnumDevices;
|
||||||
|
api_vtbl->CreateDevice = my_CreateDevice;
|
||||||
|
|
||||||
|
*(IDirectInput8W **) ppvOut = (IDirectInput8W *) api_proxy;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dinput_init(void)
|
||||||
|
{
|
||||||
|
hook_table_apply(NULL, "dinput8.dll", dinput_syms, lengthof(dinput_syms));
|
||||||
|
|
||||||
|
log_info("Inserted dinput hooks");
|
||||||
|
}
|
||||||
10
src/main/dinput/dinput.h
Normal file
10
src/main/dinput/dinput.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef DINPUTHOOK_DINPUT_H
|
||||||
|
#define DINPUTHOOK_DINPUT_H
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
// This is to stub out the dinput device
|
||||||
|
// Such that rawinput can still poll keyboards
|
||||||
|
void dinput_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -124,7 +124,7 @@ void adapter_hook_override(const char *adapter_address)
|
|||||||
// but in case it gets called multiple times, set it anyways
|
// but in case it gets called multiple times, set it anyways
|
||||||
use_address_override = false;
|
use_address_override = false;
|
||||||
|
|
||||||
if (adapter_address == NULL || *adapter_address == NULL) {
|
if (adapter_address == NULL || *adapter_address == '\0') {
|
||||||
// empty, do nothing
|
// empty, do nothing
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,10 +93,34 @@ static AVS_LOG_WRITER(log_callback, chars, nchars, ctx)
|
|||||||
free(utf16);
|
free(utf16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_hook_dlls(struct array* hook_dlls) {
|
||||||
|
const char *hook_dll;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < hook_dlls->nitems; i++) {
|
||||||
|
hook_dll = *array_item(char *, hook_dlls, i);
|
||||||
|
|
||||||
|
if (LoadLibraryA(hook_dll) == NULL) {
|
||||||
|
LPSTR buffer;
|
||||||
|
|
||||||
|
FormatMessageA(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
GetLastError(),
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPSTR) &buffer,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
log_fatal("%s: Failed to load hook DLL: %s", hook_dll, buffer);
|
||||||
|
|
||||||
|
LocalFree(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
const char *hook_dll;
|
|
||||||
bool ok;
|
bool ok;
|
||||||
HANDLE logfile;
|
HANDLE logfile;
|
||||||
|
|
||||||
@@ -170,6 +194,8 @@ int main(int argc, const char **argv)
|
|||||||
log_fatal("%s: /config missing", options.avs_config_path);
|
log_fatal("%s: /config missing", options.avs_config_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_hook_dlls(&options.before_hook_dlls);
|
||||||
|
|
||||||
avs_context_init(
|
avs_context_init(
|
||||||
avs_config_root,
|
avs_config_root,
|
||||||
options.avs_heap_size,
|
options.avs_heap_size,
|
||||||
@@ -188,27 +214,7 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
/* Load hook DLLs */
|
/* Load hook DLLs */
|
||||||
|
|
||||||
for (i = 0; i < options.hook_dlls.nitems; i++) {
|
load_hook_dlls(&options.hook_dlls);
|
||||||
hook_dll = *array_item(char *, &options.hook_dlls, i);
|
|
||||||
|
|
||||||
if (LoadLibraryA(hook_dll) == NULL) {
|
|
||||||
LPSTR buffer;
|
|
||||||
|
|
||||||
FormatMessageA(
|
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPSTR) &buffer,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
log_fatal("%s: Failed to load hook DLL: %s", hook_dll, buffer);
|
|
||||||
|
|
||||||
LocalFree(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Inject GetModuleHandle hooks */
|
/* Inject GetModuleHandle hooks */
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ void options_init(struct options *options)
|
|||||||
options->logfile = NULL;
|
options->logfile = NULL;
|
||||||
options->remote_debugger = false;
|
options->remote_debugger = false;
|
||||||
array_init(&options->hook_dlls);
|
array_init(&options->hook_dlls);
|
||||||
|
array_init(&options->before_hook_dlls);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||||
@@ -115,6 +116,16 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*array_append(const char *, &options->before_hook_dlls) =
|
||||||
|
argv[++i];
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case 'Y':
|
case 'Y':
|
||||||
if (i + 1 >= argc) {
|
if (i + 1 >= argc) {
|
||||||
return false;
|
return false;
|
||||||
@@ -170,6 +181,8 @@ void options_print_usage(void)
|
|||||||
" -R [pcbid] Specify Soft ID (default: use ea3 config)\n"
|
" -R [pcbid] Specify Soft ID (default: use ea3 config)\n"
|
||||||
" -K [filename] Load hook DLL (can be specified multiple "
|
" -K [filename] Load hook DLL (can be specified multiple "
|
||||||
"times)\n"
|
"times)\n"
|
||||||
|
" -B [filename] Load pre-hook DLL loaded before avs boot "
|
||||||
|
"(can be specified multiple times)\n"
|
||||||
" -Y [filename] Log to a file in addition to the console\n"
|
" -Y [filename] Log to a file in addition to the console\n"
|
||||||
" -D Halt the launcher before bootstrapping AVS "
|
" -D Halt the launcher before bootstrapping AVS "
|
||||||
"until a"
|
"until a"
|
||||||
@@ -179,4 +192,5 @@ void options_print_usage(void)
|
|||||||
void options_fini(struct options *options)
|
void options_fini(struct options *options)
|
||||||
{
|
{
|
||||||
array_fini(&options->hook_dlls);
|
array_fini(&options->hook_dlls);
|
||||||
|
array_fini(&options->before_hook_dlls);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ struct options {
|
|||||||
const char *module;
|
const char *module;
|
||||||
const char *logfile;
|
const char *logfile;
|
||||||
struct array hook_dlls;
|
struct array hook_dlls;
|
||||||
|
struct array before_hook_dlls;
|
||||||
bool remote_debugger;
|
bool remote_debugger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ kfca_amp_control(struct ac_io_emu *emu, const struct ac_io_message *req);
|
|||||||
|
|
||||||
static bool poll_delay;
|
static bool poll_delay;
|
||||||
|
|
||||||
|
static bool force_headphones_on;
|
||||||
|
|
||||||
void bio2_emu_bi2a_init(
|
void bio2_emu_bi2a_init(
|
||||||
struct bio2emu_port *bio2_emu, bool disable_poll_limiter)
|
struct bio2emu_port *bio2_emu, bool disable_poll_limiter, bool force_headphones)
|
||||||
{
|
{
|
||||||
bio2emu_port_init(bio2_emu);
|
bio2emu_port_init(bio2_emu);
|
||||||
|
|
||||||
@@ -35,6 +37,8 @@ void bio2_emu_bi2a_init(
|
|||||||
if (!poll_delay) {
|
if (!poll_delay) {
|
||||||
log_warning("bio2_emu_bi2a_init: poll_delay has been disabled");
|
log_warning("bio2_emu_bi2a_init: poll_delay has been disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
force_headphones_on = force_headphones;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bio2_emu_bi2a_dispatch_request(
|
void bio2_emu_bi2a_dispatch_request(
|
||||||
@@ -240,6 +244,9 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
|
|||||||
|
|
||||||
pin->buttons_1.b_start = check_pin(gpio0, SDVX_IO_IN_GPIO_0_START);
|
pin->buttons_1.b_start = check_pin(gpio0, SDVX_IO_IN_GPIO_0_START);
|
||||||
pin->buttons_1.b_headphone = check_pin(gpio0, SDVX_IO_IN_GPIO_0_HEADPHONE);
|
pin->buttons_1.b_headphone = check_pin(gpio0, SDVX_IO_IN_GPIO_0_HEADPHONE);
|
||||||
|
if (force_headphones_on) {
|
||||||
|
pin->buttons_1.b_headphone = 1;
|
||||||
|
}
|
||||||
pin->buttons_1.b_a = check_pin(gpio0, SDVX_IO_IN_GPIO_0_A);
|
pin->buttons_1.b_a = check_pin(gpio0, SDVX_IO_IN_GPIO_0_A);
|
||||||
pin->buttons_1.b_b = check_pin(gpio0, SDVX_IO_IN_GPIO_0_B);
|
pin->buttons_1.b_b = check_pin(gpio0, SDVX_IO_IN_GPIO_0_B);
|
||||||
pin->buttons_1.b_c = check_pin(gpio0, SDVX_IO_IN_GPIO_0_C);
|
pin->buttons_1.b_c = check_pin(gpio0, SDVX_IO_IN_GPIO_0_C);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ _Static_assert(
|
|||||||
"bio2_bi2a_state_out is the wrong size");
|
"bio2_bi2a_state_out is the wrong size");
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
void bio2_emu_bi2a_init(struct bio2emu_port *in, bool disable_poll_limiter);
|
void bio2_emu_bi2a_init(struct bio2emu_port *in, bool disable_poll_limiter, bool force_headphones);
|
||||||
void bio2_emu_bi2a_dispatch_request(
|
void bio2_emu_bi2a_dispatch_request(
|
||||||
struct bio2emu_port *bio2port, const struct ac_io_message *req);
|
struct bio2emu_port *bio2port, const struct ac_io_message *req);
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,12 @@
|
|||||||
"io.disable_card_reader_emu"
|
"io.disable_card_reader_emu"
|
||||||
#define SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY "io.disable_bio2_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_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter"
|
||||||
|
#define SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY "io.force_headphones"
|
||||||
|
|
||||||
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false
|
#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_BIO2_EMU_VALUE false
|
||||||
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false
|
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false
|
||||||
|
#define SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE false
|
||||||
|
|
||||||
void sdvxhook2_config_io_init(struct cconfig *config)
|
void sdvxhook2_config_io_init(struct cconfig *config)
|
||||||
{
|
{
|
||||||
@@ -33,6 +35,12 @@ void sdvxhook2_config_io_init(struct cconfig *config)
|
|||||||
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
|
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
|
||||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE,
|
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE,
|
||||||
"Disables the poll limiter, warning very high CPU usage may arise");
|
"Disables the poll limiter, warning very high CPU usage may arise");
|
||||||
|
|
||||||
|
cconfig_util_set_bool(
|
||||||
|
config,
|
||||||
|
SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY,
|
||||||
|
SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE,
|
||||||
|
"Forces game to think headphones are attached");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdvxhook2_config_io_get(
|
void sdvxhook2_config_io_get(
|
||||||
@@ -73,4 +81,16 @@ void sdvxhook2_config_io_get(
|
|||||||
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
|
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
|
||||||
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE);
|
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cconfig_util_get_bool(
|
||||||
|
config,
|
||||||
|
SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY,
|
||||||
|
&config_io->force_headphones,
|
||||||
|
SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE)) {
|
||||||
|
log_warning(
|
||||||
|
"Invalid value for key '%s' specified, fallback "
|
||||||
|
"to default '%d'",
|
||||||
|
SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY,
|
||||||
|
SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ struct sdvxhook2_config_io {
|
|||||||
bool disable_card_reader_emu;
|
bool disable_card_reader_emu;
|
||||||
bool disable_bio2_emu;
|
bool disable_bio2_emu;
|
||||||
bool disable_poll_limiter;
|
bool disable_poll_limiter;
|
||||||
|
bool force_headphones;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sdvxhook2_config_io_init(struct cconfig *config);
|
void sdvxhook2_config_io_init(struct cconfig *config);
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
|||||||
|
|
||||||
if (!config_io.disable_bio2_emu) {
|
if (!config_io.disable_bio2_emu) {
|
||||||
bio2emu_init();
|
bio2emu_init();
|
||||||
bio2_emu_bi2a_init(&bio2_emu, config_io.disable_poll_limiter);
|
bio2_emu_bi2a_init(&bio2_emu, config_io.disable_poll_limiter, config_io.force_headphones);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config_io.disable_card_reader_emu) {
|
if (!config_io.disable_card_reader_emu) {
|
||||||
|
|||||||
Reference in New Issue
Block a user