Compare commits

...

33 Commits
v5.28 ... 5.30

Author SHA1 Message Date
icex2
ff2a4b9a2c Changelog 5.30 update 2020-04-27 21:59:33 +02:00
Will Xyen
10bddd4905 d3d9ex: add cursor confining (ported from sdvxhook1) 2020-04-27 12:52:07 -07:00
Will Xyen
ad5fbc1f5b sdvxhook2: Add option to force headphone detection on 2020-04-27 10:19:29 -07:00
Will Xyen
25413bcba8 dinput/asio: drop hook suffix 2020-04-05 02:18:24 -07:00
Will Xyen
937290f93d asiohook: add config 2020-04-05 01:44:42 -07:00
Will Xyen
d04598a570 dinputhook: Adds dinput stub hook for later use
Thanks to felix for the original di8_stub_device.
2020-04-05 01:44:42 -07:00
Will Xyen
bd382e5509 asiohook: Adds asio reghook for later use 2020-04-05 01:44:41 -07:00
Will Xyen
0d3fa54316 launcher: Add before-hook support
Required to hook certain things that happen on module load / avs boot:
 - network adapter hooking for avs
 - envvar setting

Note: the logging facilities are NOT setup yet at this point
so these hooks cannot use avs for logging
2020-04-05 01:42:08 -07:00
6d16ce71d2cb7fb29ef6c9b6fd0f0943018cd3d0
e8943edff6 Add light support for SMX gen 4 pads
The old set lights API doesn't support gen 4 pads. Replace the call to SMX_SetLights with SMX_SetLights2 which adds support for gen 4 pads while maintaining backwards compatibility.
2020-03-22 21:18:38 +01:00
Will Xyen
61f3eb44d2 hooklib: fix warning in adapter.c 2020-02-05 01:26:41 -05:00
icex2
5aa1e27a31 Bump version to 5.30 2020-02-01 11:15:51 +01:00
icex2
596b962cfe Update changelog for 5.29 release 2020-02-01 11:07:18 +01:00
Will Xyen
5969573dc9 d3d9exhook: actually rotate the right monitor 2020-01-29 00:29:46 -05:00
Will Xyen
5da6997805 address MR comments. 2020-01-29 00:09:26 -05:00
Will Xyen
dc98103419 formatting update 2020-01-28 04:25:25 -05:00
Will Xyen
2d07bd6f5a d3d9exhook/sdvxhook2: add option to force monitor orientation
also adds adapter hook into sdvxhook2
2020-01-28 04:23:19 -05:00
Will Xyen
a21e37c894 hooklib: add adapter_hook_override to allow specifying network adapter id 2020-01-28 04:15:47 -05:00
Will Xyen
fbb7731681 dist: Update sdvxhook2.conf provided to have new d3d9exhook options 2020-01-21 06:13:36 -05:00
Will Xyen
3659494c18 misc: touchup some comments 2020-01-13 21:21:43 -05:00
Will Xyen
6d638ff1ae sdvxhook2-cn: sdvx5 cn support 2020-01-13 16:16:12 -05:00
Will Xyen
214a31b24d iidxhook/d3d9exhook: Use -1 to specify default adapter instead of 0 because the indexing starts at 0
Originally thought the default monitor showed up again later, it does not
2020-01-10 17:36:34 -05:00
Will Xyen
66d1131664 clang-format pass 2020-01-10 17:24:47 -05:00
Will Xyen
3450686cf5 iidxhook: allow forcing adapter and refresh rate in d3d9 based IIDX games 2020-01-10 10:44:21 -05:00
Will Xyen
3b8f6ac1d9 launcher: make app_config.xml optional 2019-12-23 20:40:51 -05:00
Will Xyen
8ae06f6f4b d3d9exhook: Add option to specify the display adapter to open 2019-12-23 20:14:26 -05:00
Will Xyen
b1fd175318 dist/docs: --config not --options 2019-12-18 21:48:47 -05:00
Will Xyen
b1329d10bf camhook: Fix cameras not being auto-detected sometimes on older machines
MFStartup needs to be called before any MF functions are used (such as for auto detect)
2019-12-10 15:24:46 -05:00
icex2
bf3d543893 Add some general notes about data setup for OS to README 2019-12-09 15:17:09 +01:00
icex2
f1f26dece3 Update development doc with some useful dev tools 2019-12-09 15:08:14 +01:00
icex2
fe0996ec3b Update MR templates, add checklist for guidance 2019-12-09 15:01:16 +01:00
icex2
d551930ea0 Version bump to 5.29 2019-12-06 23:25:21 +01:00
icex2
daad6a09c5 Fix versioning for sdvx distribution packages
sdvx.zip -> sdvx-01-to-04.zip
sdvx5.zip -> sdvx-05.zip
2019-12-06 23:23:12 +01:00
icex2
27fdabe17a Add instructions how to create releases 2019-12-06 23:19:27 +01:00
90 changed files with 2353 additions and 97 deletions

View File

@@ -13,4 +13,15 @@
## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
<!--- see how your change affects other areas of the code, etc. -->
## Checklist
<!-- Make sure you covered all items, which apply, of the checklist below. -->
<!-- Strikethrough items that do not apply and provide a brief description why. -->
* [ ] Implemented (unit) test(s) which prove that the introduced changes are working as expected.
* Tested with the following games:
* [ ] ... <!-- insert game name 1-->
* [ ] ... <!-- insert game name 2--->
* [ ] Followed the developer (style) guidelines.
* [ ] Updated existing doc of or add new doc to README file(s).
* [ ] Updated development documentation.

View File

@@ -13,4 +13,15 @@
## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
<!--- see how your change affects other areas of the code, etc. -->
## Checklist
<!-- Make sure you covered all items, which apply, of the checklist below. -->
<!-- Strikethrough items that do not apply and provide a brief description why. -->
* [ ] Implemented (unit) test(s) which prove that the introduced changes are working as expected.
* Tested with the following games:
* [ ] ... <!-- insert game name 1-->
* [ ] ... <!-- insert game name 2--->
* [ ] Followed the developer (style) guidelines.
* [ ] Updated existing doc of or add new doc to README file(s).
* [ ] Updated development documentation.

View File

@@ -1,4 +1,15 @@
# Release history
## 5.30
* SDVX: sdvxhook2 headphone force and cursor confining config options
* DDR: Add light support for SMX gen 4 pads
## 5.29
* SDVX: Add option for monitor rotation
* SDVX: Add option to allow overriding network adapter IP
* IIDX: Add force display adapter and refresh rate configuration
* SDVX: Allow specifying display adapter to open for d3d9ex hook
* IIDX/SDVX camerahooks bugfix: Camera sometimes not detected on some older machines
## 5.28
* Improve documentation in various places
* Automatic code formatting in build pipeline

View File

@@ -77,6 +77,7 @@ imps += avs avs-ea3
include src/main/aciodrv/Module.mk
include src/main/acioemu/Module.mk
include src/main/aciotest/Module.mk
include src/main/asio/Module.mk
include src/main/bio2emu/Module.mk
include src/main/bsthook/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-smx/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-icca/Module.mk
include src/main/eamiotest/Module.mk
@@ -136,6 +138,7 @@ include src/main/p4ioemu/Module.mk
include src/main/pcbidgen/Module.mk
include src/main/sdvxhook/Module.mk
include src/main/sdvxhook2/Module.mk
include src/main/sdvxhook2-cn/Module.mk
include src/main/sdvxio/Module.mk
include src/main/sdvxio-kfca/Module.mk
include src/main/security/Module.mk
@@ -407,7 +410,7 @@ $(zipdir)/jb-08.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx.zip: \
$(zipdir)/sdvx-01-to-04.zip: \
build/bin/avs2_1508-32/launcher.exe \
build/bin/avs2_1508-32/sdvxhook.dll \
build/bin/indep-32/config.exe \
@@ -421,7 +424,7 @@ $(zipdir)/sdvx.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx5.zip: \
$(zipdir)/sdvx-05.zip: \
build/bin/avs2_1700-64/launcher.exe \
build/bin/avs2_1700-64/sdvxhook2.dll \
build/bin/indep-64/config.exe \
@@ -436,6 +439,20 @@ $(zipdir)/sdvx5.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx-05-cn.zip: \
build/bin/avs2_1700-64/launcher.exe \
build/bin/avs2_1700-64/sdvxhook2-cn.dll \
build/bin/indep-64/config.exe \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
build/bin/indep-64/sdvxio.dll \
dist/sdvx5/config.bat \
dist/sdvx5/gamestart-cn.bat \
dist/sdvx5/sdvxhook2-cn.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-12-to-16.zip: \
build/bin/avs2_1508-32/launcher.exe \
build/bin/avs2_1508-32/ddrhook.dll \
@@ -521,8 +538,9 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/jb-05-to-07.zip \
$(zipdir)/jb-08.zip \
$(zipdir)/src.zip \
$(zipdir)/sdvx.zip \
$(zipdir)/sdvx5.zip \
$(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-cn.zip \
$(zipdir)/tools.zip \
$(zipdir)/tools-x64.zip \
CHANGELOG.md \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5
[![pipeline status](https://dev.s-ul.eu/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
Version: 5.28</br>
Version: 5.30</br>
[Release history](CHANGELOG.md)
A collection of tools to run [various Bemani arcade games](#list-of-supported-games).
@@ -47,11 +47,11 @@ authentic gameplay experience, and easier support for a broader range of release
* jubeat Qubell (jb-05-to-07.zip) using jbhook
* jubeat clan (jb-08.zip) using jbhook
* SOUND VOLTEX
* SOUND VOLTEX BOOTH (sdvx.zip) using sdvxhook
* SOUND VOLTEX II -infinite infection- (sdvx.zip) using sdvxhook
* SOUND VOLTEX III GRAVITY WARS (sdvx.zip) using sdvxhook
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx.zip) using sdvxhook
* SOUND VOLTEX Vivid Wave (sdvx2.zip) using sdvxhook2
* SOUND VOLTEX BOOTH (sdvx-01-to-04.zip) using sdvxhook
* 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
# Supported platforms
Our main platforms are currently Windows XP and Windows 7 which are also the target platforms on the original hardware
@@ -67,6 +67,16 @@ You will find *.md files in various sub-packages that give you further instructi
or FAQ. We advice you to read them as your questions and concerns might already be answered by them. If not, let us
know if there is any information that you consider helpful or important to know and should be added.
# Setup and dependencies
Most (older generation) games were developed for Windows XP Embedded but should run fine on any
consumer version of Windows XP. Newer versions of Windows, e.g. Windows 7, 8 and 10, should be fine
as well. Some hooks also include fixes required to run the games on a more recent version.
Depending on the game, you also need the following dependencies installed:
* DirectX 9 runtime
* Microsoft Visual C++ Redistributables 2010 **and** 2013: Depends on the game and age but both
should cover most if not all of the games so far
# Contributions
Please refer to the [dedicated documentation](CONTRIBUTING.md).

View File

@@ -40,6 +40,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -40,6 +40,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -40,6 +40,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -40,6 +40,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Fix broken 3D background on Happy Sky's music select (if appearing completely white)
misc.happy_sky_ms_bg_fix=false

View File

@@ -40,6 +40,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Fix broken 3D background on DistorteD's music select (if appearing completely black)
misc.distorted_ms_bg_fix=false

View File

@@ -37,6 +37,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -37,6 +37,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -40,6 +40,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -40,6 +40,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false

View File

@@ -30,3 +30,9 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1

View File

@@ -27,3 +27,9 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1

View File

@@ -27,3 +27,9 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1

View File

@@ -27,3 +27,9 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1

View File

@@ -27,3 +27,9 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1

View File

@@ -27,3 +27,9 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1

View File

@@ -27,3 +27,9 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1

View File

@@ -28,6 +28,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disables the camera emulation
cam.disable_emu=false

View File

@@ -28,6 +28,12 @@ gfx.scale_back_buffer_height=0
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
gfx.scale_back_buffer_filter=none
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1
# Disables the camera emulation
cam.disable_emu=false

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

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

View File

@@ -13,4 +13,4 @@ for /R prop\defaults %%D in (*.*) do (
if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
)
launcher -H 268435456 -K sdvxhook2.dll soundvoltex.dll --options sdvxhook2.conf %*
launcher -H 268435456 -K sdvxhook2.dll soundvoltex.dll --config sdvxhook2.conf %*

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

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

View File

@@ -7,17 +7,32 @@ io.disable_bio2_emu=false
# Disables the poll limiter, warning very high CPU usage may arise
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)
gfx.framed=true
# Run the game windowed
gfx.windowed=false
# Confine mouse coursor to window
gfx.confined=false
# Windowed width, -1 for default size
gfx.window_width=720
gfx.window_width=1080
# Windowed height, -1 for default size
gfx.window_height=1280
gfx.window_height=1920
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
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
# Disables the camera emulation
cam.disable_emu=false
@@ -25,3 +40,6 @@ cam.disable_emu=false
# Override camera device ID detection (copy from device manager, do not escape)
cam.device_id1=
# IP of adapter to force override with
adapter.override_ip=

View File

@@ -36,6 +36,13 @@ development environment which we run on a Linux distribution of our choice:
* C++ Intellisense
* Clang-Format
### Further tools for testing and debugging
* Debugger: Can be part of your reverse engineering IDE of your choice or stand-along like
[OllyDbg](http://www.ollydbg.de/).
* [apitrace](https://apitrace.github.io/): Trace render calls to graphics APIs like D3D and OpenGL.
This tool allows you to record and re-play render calls of an application with frame-by-frame
debugging. Very useful to analyze the render pipeline or debug graphicial glitches.
## Building
Simply run make in the root folder:
```
@@ -51,6 +58,39 @@ command:
make release
```
## Creating releases
For developers to create official releases with major and minor versioning:
1. Ensure that all everything you want to have for this release is merged into master.
1. Create a [changelog](CHANGELOG.md) based on aggregating and summerizing commit messages of
whatever got added starting from the tag of the current version to the current head of master.
Commit that changelog and push to master.
1. Create a tag with the next version number, e.g. for 5.28:
```bash
git tag v5.28
```
1. Push the tag upstream:
```bash
git push origin v5.28
```
1. Wait for the CI pipeline to finish building the release and check if everything's ok.
1. On GitLab, go to "Tags" in the repository, click on the commit ID below the tag in the list you
just created.
1. Click on the "Pipelines" tab and click on the download button on the right and on "Download
release artifacts".
1. Rename the downloaded zip to "bemanitools-v5.28.zip" and the replace v5.28 with the version
you want to release.
1. Upload the release.
1. For publishing the release, create a post with the following contents:
```
v5.28
<insert link to uploaded zip here>
<additional comments or things to point out for this release>
Changelog copy-paste:
<insert copy-pasted changelog you created previously here>
```
## Code formatting
To apply our code style using clang-format, simply run the following command:
```

View File

@@ -14,12 +14,12 @@ it to the list of libraries to inject:
Example when using *inject.exe*:
```
inject iidxhook3.dll mempatch-hook.dll bm2dx.exe --options iidxhook-16.conf --mempatch myPatch.mph %*
inject iidxhook3.dll mempatch-hook.dll bm2dx.exe --config iidxhook-16.conf --mempatch myPatch.mph %*
```
When using *launcher.exe*:
```
launcher -K iidxhook4.dll -K mempatch-hook.dll bm2dx.dll --options iidxhook.conf --mempatch myPatch.mph %*
launcher -K iidxhook4.dll -K mempatch-hook.dll bm2dx.dll --config iidxhook.conf --mempatch myPatch.mph %*
```
To load a patch script, add the *--mempatch <path to patch script>* argument (as

View File

@@ -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.
SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
// Update the lights. Both pads are always updated together. lightsData is a
// list of 8-bit RGB colors, one for each LED. Each panel has lights in the
// following order:
// (deprecated) Equivalent to SMX_SetLights2(lightsData, 864).
SMX_API void SMX_SetLights(const char lightData[864]);
// Update the lights. Both pads are always updated together. lightData is a list of 8-bit RGB
// colors, one for each LED.
//
// 0123
// 4567
// 89AB
// CDEF
// lightDataSize is the number of bytes in lightsData. This should be 1350 (2 pads * 9 panels *
// 25 lights * 3 RGB colors). For backwards-compatibility, this can also be 864.
//
// 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:
//
@@ -76,17 +86,17 @@ SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
// 345 CDE
// 678 F01
//
// With 18 panels, 16 LEDs per panel and 3 bytes per LED, each light update has
// 864 bytes of data.
// With 18 panels, 25 LEDs per panel and 3 bytes per LED, each light update has 1350 bytes of data.
//
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a
// best effort will be made to send the most recent lights data available, but
// the panels won't update more quickly.
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a best effort will be
// made to send the most recent lights data available, but the panels won't update more quickly.
//
// The panels will return to automatic lighting if no lights are received for a
// while, so applications controlling lights should send light updates
// continually, even if the lights aren't changing.
SMX_EXTERN_C SMX_API void SMX_SetLights(const char lightsData[864]);
// The panels will return to automatic lighting if no lights are received for a while, so applications
// controlling lights should send light updates continually, even if the lights aren't changing.
//
// 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
// command is sent by the application, this stops happening to allow the

View File

@@ -7,6 +7,7 @@ EXPORTS
SMX_GetInfo
SMX_GetInputState
SMX_SetLights
SMX_SetLights2
SMX_ReenableAutoLights
SMX_GetConfig
SMX_SetConfig

10
src/main/asio/Module.mk Normal file
View File

@@ -0,0 +1,10 @@
libs += asio
libs_asio := \
hook \
hooklib \
util \
src_asio := \
asio-reghook.c \
config-asio.c \

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

View 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

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

View 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

View File

@@ -206,6 +206,7 @@ my_CM_Locate_DevNodeA(PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags)
char builtString[CAMERA_DATA_STRING_SIZE] = {0};
if (pdnDevInst) {
log_info("seeking: %s", pDeviceID);
for (size_t i = 0; i < CAMHOOK_CONFIG_CAM_MAX; ++i) {
if (camData[i].setup) {
snprintf(
@@ -213,6 +214,7 @@ my_CM_Locate_DevNodeA(PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags)
CAMERA_DATA_STRING_SIZE,
"USB\\VID_288C&PID_0002&MI_00\\%s",
camData[i].extra_upper);
log_info("built: %s", builtString);
if (strcmp(pDeviceID, builtString) == 0) {
if (!camData[i].fake_located) {
camData[i].fake_located_node = num_located_cams;
@@ -280,7 +282,9 @@ HRESULT my_GetAllocatedString(
// should probably check GUID, oh well
ret = real_GetAllocatedString(self, guidKey, ppwszValue, pcchLength);
log_info("Obtained: %ls", *ppwszValue);
char *pMBBuffer = (char *) malloc(0x100);
wcstombs(pMBBuffer, *ppwszValue, 0x100);
log_info("Obtained: %s", pMBBuffer);
wchar_t *pwc = NULL;
@@ -308,8 +312,11 @@ HRESULT my_GetAllocatedString(
pwc[29] = L'0';
pwc[30] = L'0';
log_info("Replaced: %ls", *ppwszValue);
wcstombs(pMBBuffer, *ppwszValue, 0x100);
log_info("Replaced: %s", pMBBuffer);
}
free(pMBBuffer);
return ret;
}
@@ -787,6 +794,8 @@ void fill_cam_struct(struct CameraData *data, const char *devid)
void camhook_init(struct camhook_config_cam *config_cam)
{
MFStartup(0x20070u, 0);
// fill before applying hooks
for (size_t i = 0; i < config_cam->num_devices; ++i) {
fill_cam_struct(&camData[i], config_cam->device_id[i]);
@@ -814,3 +823,8 @@ void camhook_init(struct camhook_config_cam *config_cam)
log_info("No cams detected, not hooking");
}
}
void camhook_fini(void)
{
MFShutdown();
}

View File

@@ -5,4 +5,6 @@
void camhook_init(struct camhook_config_cam *config_cam);
void camhook_fini(void);
#endif

View File

@@ -9,5 +9,6 @@ bool cconfig_hook_config_init(
const char *usage_header,
enum cconfig_cmd_usage_out cmd_usage_out)
{
return cconfig_main_config_init(config, "--config", NULL, "--help", "-h", usage_header, cmd_usage_out);
return cconfig_main_config_init(
config, "--config", NULL, "--help", "-h", usage_header, cmd_usage_out);
}

View File

@@ -6,7 +6,7 @@
/**
* Init function for cconfig for hooks
*
*
* calls cconfig_main_config_init with some defaults for hook dlls
* see: cconfig_main_config_init for more details
*/

View File

@@ -29,7 +29,8 @@ bool cconfig_main_config_init(
args_recover(&argc, &argv);
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], help_parameter_short_name) || !strcmp(argv[i], help_parameter_name)) {
if (!strcmp(argv[i], help_parameter_short_name) ||
!strcmp(argv[i], help_parameter_name)) {
goto failure_usage;
}
}

View File

@@ -6,7 +6,7 @@
/**
* Init function for cconfig after all cconfig_util_set's have been called
*
*
* will parse a config file first (if specified)
* then uses override config parameters from cmd
*/

View File

@@ -1,3 +1,5 @@
#include <d3d9.h>
#include <string.h>
#include "cconfig/cconfig-util.h"
@@ -8,15 +10,21 @@
#define D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY "gfx.framed"
#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_HEIGHT_KEY "gfx.window_height"
#define D3D9EXHOOK_CONFIG_GFX_FORCED_RR_KEY "gfx.forced_refresh_rate"
#define D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate"
#define D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY "gfx.device_adapter"
#define D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY "gfx.force_orientation"
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_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_HEIGHT_VALUE -1
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE -1
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE -1
void d3d9exhook_config_gfx_init(struct cconfig *config)
{
@@ -32,6 +40,12 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE,
"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(
config,
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,
@@ -46,9 +60,24 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
cconfig_util_set_int(
config,
D3D9EXHOOK_CONFIG_GFX_FORCED_RR_KEY,
D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE,
"Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)");
"Forced refresh rate, -1 to not force any (try 59 or 60 if monitor "
"check fails to lock on high refresh rate monitors)");
cconfig_util_set_int(
config,
D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE,
"D3D9ex device adapter (monitor), -1 to use default, "
"0, 1, 2 etc. to use specified adapter");
cconfig_util_set_int(
config,
D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE,
"Orientation to force monitor into, -1 to use default, "
"0, 1, 2, 3 to do 0, 90, 180, 270 degrees");
}
void d3d9exhook_config_gfx_get(
@@ -78,6 +107,18 @@ void d3d9exhook_config_gfx_get(
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(
config,
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,
@@ -104,13 +145,37 @@ void d3d9exhook_config_gfx_get(
if (!cconfig_util_get_int(
config,
D3D9EXHOOK_CONFIG_GFX_FORCED_RR_KEY,
D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY,
&config_gfx->forced_refresh_rate,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
D3D9EXHOOK_CONFIG_GFX_FORCED_RR_KEY,
D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE);
}
if (!cconfig_util_get_int(
config,
D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY,
&config_gfx->device_adapter,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE);
}
if (!cconfig_util_get_int(
config,
D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY,
&config_gfx->force_orientation,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE);
}
}

View File

@@ -5,16 +5,19 @@
/**
* Config struct for d3d9exhook
*
*
* Note: forced_refresh_rate sets the monitor's refresh rate
* (it does not limit FPS or anything)
*/
struct d3d9exhook_config_gfx {
bool framed;
bool windowed;
bool confined;
int32_t window_width;
int32_t window_height;
int32_t forced_refresh_rate;
int32_t device_adapter;
int32_t force_orientation;
};
/**

View File

@@ -47,6 +47,8 @@ static HRESULT STDCALL my_CreateDeviceEx(
static HRESULT STDCALL my_Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **api);
static WNDPROC real_WndProc;
static BOOL STDCALL my_EnumDisplayDevicesA(
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags);
@@ -82,10 +84,13 @@ static BOOL(STDCALL *real_MoveWindow)(
/* ------------------------------------------------------------------------- */
static bool d3d9ex_windowed;
static bool d3d9ex_confined;
static int32_t d3d9ex_force_refresh_rate = -1;
static int32_t d3d9ex_window_width = -1;
static int32_t d3d9ex_window_height = -1;
static bool d3d9ex_window_framed;
static int32_t d3d9ex_device_adapter = -1;
static int32_t d3d9ex_force_orientation = -1;
/* ------------------------------------------------------------------------- */
@@ -181,6 +186,52 @@ my_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
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(
IDirect3D9Ex *self,
UINT adapter,
@@ -194,24 +245,83 @@ static HRESULT STDCALL my_CreateDeviceEx(
IDirect3D9Ex *real = COM_PROXY_UNWRAP(self);
HRESULT hr;
if (d3d9ex_device_adapter >= 0) {
log_info("Forcing adapter %d -> %d", adapter, d3d9ex_device_adapter);
adapter = d3d9ex_device_adapter;
}
if (d3d9ex_windowed) {
fdm = NULL;
pp->Windowed = TRUE;
pp->FullScreen_RefreshRateInHz = 0;
} else {
if (d3d9ex_force_refresh_rate != -1) {
log_info("Forcing refresh rate %d -> %d", pp->FullScreen_RefreshRateInHz, d3d9ex_force_refresh_rate);
if (d3d9ex_force_refresh_rate > 0) {
log_info(
"Forcing refresh rate %d -> %d",
pp->FullScreen_RefreshRateInHz,
d3d9ex_force_refresh_rate);
pp->FullScreen_RefreshRateInHz = d3d9ex_force_refresh_rate;
if (fdm) {
fdm->RefreshRate = pp->FullScreen_RefreshRateInHz;
}
}
if (d3d9ex_force_orientation >= DMDO_DEFAULT &&
d3d9ex_force_orientation <= DMDO_270) {
D3DADAPTER_IDENTIFIER9 adapter_ident;
if (IDirect3D9Ex_GetAdapterIdentifier(
real, adapter, 0, &adapter_ident) == D3D_OK) {
// straight outta MSDN
DEVMODE dm;
// initialize the DEVMODE structure
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
if (EnumDisplaySettings(
adapter_ident.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) {
int32_t delta =
d3d9ex_force_orientation - dm.dmDisplayOrientation;
if (delta % 2 != 0) {
// swap height and width
DWORD dwTemp = dm.dmPelsHeight;
dm.dmPelsHeight = dm.dmPelsWidth;
dm.dmPelsWidth = dwTemp;
}
dm.dmDisplayOrientation = d3d9ex_force_orientation;
long cd_ret = ChangeDisplaySettingsEx(
adapter_ident.DeviceName,
&dm,
NULL,
CDS_FULLSCREEN,
NULL);
if (cd_ret == DISP_CHANGE_SUCCESSFUL) {
log_info(
"Overriding rotation suceeded: %s",
adapter_ident.DeviceName);
} else {
log_info(
"Overriding rotation failed %s %ld",
adapter_ident.DeviceName,
cd_ret);
}
}
}
}
}
hr = IDirect3D9Ex_CreateDeviceEx(
real, adapter, type, hwnd, flags, pp, fdm, pdev);
// TODO stuff
if (SUCCEEDED(hr) && d3d9ex_confined) {
real_WndProc = (void *) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (uintptr_t) my_WndProc);
}
return hr;
}
@@ -261,14 +371,17 @@ void d3d9ex_hook_init(void)
log_info("Inserted graphics hooks");
}
void d3d9ex_configure(struct d3d9exhook_config_gfx* gfx_config)
void d3d9ex_configure(struct d3d9exhook_config_gfx *gfx_config)
{
d3d9ex_windowed = gfx_config->windowed;
d3d9ex_confined = gfx_config->confined;
d3d9ex_window_framed = gfx_config->framed;
d3d9ex_window_width = gfx_config->window_width;
d3d9ex_window_height = gfx_config->window_height;
d3d9ex_force_refresh_rate = gfx_config->forced_refresh_rate;
d3d9ex_device_adapter = gfx_config->device_adapter;
d3d9ex_force_orientation = gfx_config->force_orientation;
}
/* ------------------------------------------------------------------------- */

View File

@@ -16,6 +16,6 @@ void d3d9ex_hook_init(void);
*
* @param gfx_config Config to apply.
*/
void d3d9ex_configure(struct d3d9exhook_config_gfx* gfx_config);
void d3d9ex_configure(struct d3d9exhook_config_gfx *gfx_config);
#endif

View File

@@ -41,24 +41,28 @@ static const struct ddr_io_smx_pad_map ddr_io_smx_pad_map[] = {
{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[] = {
/* 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_LEFT, 48 * 3, 0x00, 0x00, 0xFF},
{1 << LIGHT_P1_RIGHT, 48 * 5, 0x00, 0x00, 0xFF},
{1 << LIGHT_P1_DOWN, 48 * 7, 0xFF, 0x00, 0x00},
{1 << LIGHT_P1_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 1, 0xFF, 0x00, 0x00},
{1 << LIGHT_P1_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 3, 0x00, 0x00, 0xFF},
{1 << LIGHT_P1_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 5, 0x00, 0x00, 0xFF},
{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_LEFT, 48 * 12, 0x00, 0x00, 0xFF},
{1 << LIGHT_P2_RIGHT, 48 * 14, 0x00, 0x00, 0xFF},
{1 << LIGHT_P2_DOWN, 48 * 16, 0xFF, 0x00, 0x00},
{1 << LIGHT_P2_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 10, 0xFF, 0x00, 0x00},
{1 << LIGHT_P2_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 12, 0x00, 0x00, 0xFF},
{1 << LIGHT_P2_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 14, 0x00, 0x00, 0xFF},
{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 CRITICAL_SECTION ddr_io_smx_lights_lock;
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(
log_formatter_t misc,
@@ -109,7 +113,7 @@ uint32_t ddr_io_read_pad(void)
EnterCriticalSection(&ddr_io_smx_lights_lock);
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++;
@@ -149,7 +153,7 @@ void ddr_io_set_lights_extio(uint32_t lights)
if (lights & map->extio_bit) {
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 + 1] = map->g;
ddr_io_smx_lights[offset + j + 2] = map->b;

10
src/main/dinput/Module.mk Normal file
View File

@@ -0,0 +1,10 @@
libs += dinput
libs_dinput := \
hook \
hooklib \
util \
src_dinput := \
dinput.c \
device_dinput8.c \

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

View 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
View 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
View 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

View File

@@ -4,6 +4,7 @@ src_hooklib := \
acp.c \
app.c \
adapter.c \
config-adapter.c \
rs232.c \
setupapi.c \

View File

@@ -3,12 +3,16 @@
#include <windows.h>
#include <winsock2.h>
#include <stdbool.h>
#include <string.h>
#include "hook/table.h"
#include "hooklib/adapter.h"
#include "util/codepage.h"
#include "util/defs.h"
#include "util/log.h"
static DWORD WINAPI
my_GetAdaptersInfo(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len);
@@ -16,6 +20,9 @@ my_GetAdaptersInfo(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len);
static DWORD(WINAPI *real_GetAdaptersInfo)(
PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len);
static IP_ADDRESS_STRING override_address;
static bool use_address_override;
static const struct hook_symbol adapter_hook_syms[] = {
{.name = "GetAdaptersInfo",
.patch = my_GetAdaptersInfo,
@@ -37,6 +44,34 @@ my_GetAdaptersInfo(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len)
return ret;
}
info = adapter_info;
if (use_address_override) {
while (info) {
// this is well defined to be at most sizeof(IP_ADDRESS_STRING)
// and NULL filled if shorter (hence the memset in
// adapter_hook_override)
if (!memcmp(
info->IpAddressList.IpAddress.String,
override_address.String,
sizeof(IP_ADDRESS_STRING))) {
log_info(
"%s: using [override] adapter: %s, %s, %s, %s",
__FUNCTION__,
info->AdapterName,
info->Description,
info->IpAddressList.IpAddress.String,
info->IpAddressList.IpMask.String);
// copy only this adapter over
memcpy(adapter_info, info, sizeof(*info));
adapter_info->Next = 0;
return ret;
}
info = info->Next;
}
}
ip_fwd_table = (MIB_IPFORWARDTABLE *) malloc(sizeof(MIB_IPFORWARDTABLE));
table_size = 0;
@@ -58,6 +93,15 @@ my_GetAdaptersInfo(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len)
while (info) {
if (info->Index == best_adapter) {
log_info(
"%s: using [best] adapter: %s, %s, %s, %s",
__FUNCTION__,
info->AdapterName,
info->Description,
info->IpAddressList.IpAddress.String,
info->IpAddressList.IpMask.String);
// copy only this adapter over
memcpy(adapter_info, info, sizeof(*info));
adapter_info->Next = 0;
return ret;
@@ -73,3 +117,26 @@ void adapter_hook_init(void)
hook_table_apply(
NULL, "iphlpapi.dll", adapter_hook_syms, lengthof(adapter_hook_syms));
}
void adapter_hook_override(const char *adapter_address)
{
// starts off false anyways due to static
// but in case it gets called multiple times, set it anyways
use_address_override = false;
if (adapter_address == NULL || *adapter_address == '\0') {
// empty, do nothing
return;
}
if (strlen(adapter_address) > sizeof(IP_ADDRESS_STRING)) {
log_warning(
"%s: %s is not an ipv4 address", __FUNCTION__, adapter_address);
return;
}
memset(override_address.String, 0, sizeof(IP_ADDRESS_STRING));
memcpy(override_address.String, adapter_address, sizeof(IP_ADDRESS_STRING));
use_address_override = true;
}

View File

@@ -1,6 +1,18 @@
#ifndef HOOKLIB_ADAPTER_H
#define HOOKLIB_ADAPTER_H
/**
* Hooks GetAdaptersInfo to attempt only returning 1 adapter.
*
*/
void adapter_hook_init(void);
/**
* Uses the provided address to try and match a network adapter.
* This adapter is then returned as the only adapter.
*
* @param network ip to match
*/
void adapter_hook_override(const char *adapter_address);
#endif

View File

@@ -0,0 +1,35 @@
#include "cconfig/cconfig-util.h"
#include "hooklib/config-adapter.h"
#include "util/log.h"
#define HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY "adapter.override_ip"
#define HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE ""
void hooklib_config_adapter_init(struct cconfig *config)
{
cconfig_util_set_str(
config,
HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY,
HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE,
"IP of adapter to force override with");
}
void hooklib_config_adapter_get(
struct hooklib_config_adapter *config_adapter, struct cconfig *config)
{
if (!cconfig_util_get_str(
config,
HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY,
config_adapter->override_ip,
sizeof(config_adapter->override_ip),
HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY,
HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE);
}
}

View File

@@ -0,0 +1,18 @@
#ifndef HOOKLIB_CONFIG_ADAPTER_H
#define HOOKLIB_CONFIG_ADAPTER_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct hooklib_config_adapter {
// this is larger on purpose, in case ppl enter the wrong stuff here
char override_ip[32];
};
void hooklib_config_adapter_init(struct cconfig *config);
void hooklib_config_adapter_get(
struct hooklib_config_adapter *config_adapter, struct cconfig *config);
#endif

View File

@@ -20,6 +20,8 @@
"gfx.scale_back_buffer_height"
#define IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_FILTER_KEY \
"gfx.scale_back_buffer_filter"
#define IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate"
#define IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY "gfx.device_adapter"
#define IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE false
#define IIDXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false
@@ -32,6 +34,8 @@
#define IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_WIDTH_VALUE 0
#define IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_HEIGHT_VALUE 0
#define IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE "none"
#define IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1
#define IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE -1
void iidxhook_config_gfx_init(struct cconfig *config)
{
@@ -141,6 +145,20 @@ void iidxhook_config_gfx_init(struct cconfig *config)
"linear, point (refer to "
"D3DTEXTUREFILTERTYPE "
" for explanation).");
cconfig_util_set_int(
config,
IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE,
"Forced refresh rate, -1 to not force any (try 59 or 60 if monitor "
"check fails to lock on high refresh rate monitors)");
cconfig_util_set_int(
config,
IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE,
"D3D9 device adapter (monitor), -1 to use default, "
"0, 1, 2 etc. to use specified adapter");
}
void iidxhook_config_gfx_get(
@@ -325,4 +343,28 @@ void iidxhook_config_gfx_get(
IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_FILTER_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE);
}
if (!cconfig_util_get_int(
config,
IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY,
&config_gfx->forced_refresh_rate,
IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE);
}
if (!cconfig_util_get_int(
config,
IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY,
&config_gfx->device_adapter,
IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE);
}
}

View File

@@ -5,6 +5,7 @@
#include "iidxhook-util/d3d9.h"
// see struct iidxhook_util_d3d9_config for more info
struct iidxhook_config_gfx {
bool bgvideo_uv_fix;
bool framed;
@@ -18,6 +19,8 @@ struct iidxhook_config_gfx {
uint16_t scale_back_buffer_width;
uint16_t scale_back_buffer_height;
enum iidxhook_util_d3d9_back_buffer_scale_filter scale_back_buffer_filter;
int32_t forced_refresh_rate;
int32_t device_adapter;
};
void iidxhook_config_gfx_init(struct cconfig *config);

View File

@@ -262,10 +262,29 @@ static void iidxhook_util_d3d9_fix_create_device_apply_window_mode(
{
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE);
D3DPRESENT_PARAMETERS *pp = irp->args.ctx_create_device.pp;
if (iidxhook_util_d3d9_config.windowed) {
irp->args.ctx_create_device.pp->Windowed = TRUE;
irp->args.ctx_create_device.pp->FullScreen_RefreshRateInHz = 0;
pp->Windowed = TRUE;
pp->FullScreen_RefreshRateInHz = 0;
} else {
if (iidxhook_util_d3d9_config.forced_refresh_rate > 0) {
log_info(
"Forcing refresh rate %d -> %d",
pp->FullScreen_RefreshRateInHz,
iidxhook_util_d3d9_config.forced_refresh_rate);
pp->FullScreen_RefreshRateInHz =
iidxhook_util_d3d9_config.forced_refresh_rate;
}
}
if (iidxhook_util_d3d9_config.device_adapter >= 0) {
log_info(
"Forcing adapter %d -> %d",
irp->args.ctx_create_device.adapter,
iidxhook_util_d3d9_config.device_adapter);
irp->args.ctx_create_device.adapter =
iidxhook_util_d3d9_config.device_adapter;
}
}
@@ -904,7 +923,9 @@ iidxhook_util_d3d9_log_config(const struct iidxhook_util_d3d9_config *config)
"iidx14_to_19_nvidia_fix: %d\n"
"scale_back_buffer_width: %d\n"
"scale_back_buffer_height: %d\n"
"scale_back_buffer_filter: %d",
"scale_back_buffer_filter: %d\n"
"forced_refresh_rate: %d\n"
"device_adapter: %d",
config->windowed,
config->framed,
config->override_window_width,
@@ -919,7 +940,9 @@ iidxhook_util_d3d9_log_config(const struct iidxhook_util_d3d9_config *config)
config->iidx14_to_19_nvidia_fix,
config->scale_back_buffer_width,
config->scale_back_buffer_height,
config->scale_back_buffer_filter);
config->scale_back_buffer_filter,
config->forced_refresh_rate,
config->device_adapter);
}
static void iidxhook_util_d3d9_validate_config(
@@ -983,6 +1006,8 @@ void iidxhook_util_d3d9_init_config(struct iidxhook_util_d3d9_config *config)
config->scale_back_buffer_height = 0;
config->scale_back_buffer_filter =
IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_NONE;
config->forced_refresh_rate = -1;
config->device_adapter = -1;
}
void iidxhook_util_d3d9_configure(
@@ -1046,9 +1071,10 @@ iidxhook_util_d3d9_irp_handler(struct hook_d3d9_irp *irp)
hr = hook_d3d9_irp_invoke_next(irp);
if (hr == S_OK) {
iidxhook_util_d3d9_log_result_create_device(hr);
iidxhook_util_d3d9_setup_back_buffer_scaling_post(irp);
iidxhook_util_d3d9_execute_monitor_check(irp);
} else {
iidxhook_util_d3d9_log_result_create_device(hr);
}
return hr;

View File

@@ -159,6 +159,20 @@ struct iidxhook_util_d3d9_config {
* for full doc.
*/
enum iidxhook_util_d3d9_back_buffer_scale_filter scale_back_buffer_filter;
/**
* Forced refresh rate
* -1 to not force any (try 59 or 60 if monitor check fails to lock on high
* refresh rate monitors)
*/
int32_t forced_refresh_rate;
/**
* override device adapter (monitor)
* -1 to use default (whatever the game sends)
* 0, 1, 2 etc. to use specified adapter
*/
int32_t device_adapter;
};
/**

View File

@@ -95,6 +95,8 @@ static void iidxhook1_setup_d3d9_hooks(
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
if (config_gfx->monitor_check == 0) {
log_info("Auto monitor check enabled");

View File

@@ -94,6 +94,8 @@ static void iidxhook2_setup_d3d9_hooks(
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
if (config_gfx->monitor_check == 0) {
log_info("Auto monitor check enabled");

View File

@@ -91,6 +91,8 @@ iidxhook3_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
if (config_gfx->monitor_check == 0) {
log_info("Auto monitor check enabled");

View File

@@ -72,6 +72,8 @@ iidxhook4_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
if (config_gfx->monitor_check == 0) {
log_info("Auto monitor check enabled");

View File

@@ -70,6 +70,8 @@ iidxhook5_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
iidxhook_util_d3d9_configure(&d3d9_config);

View File

@@ -68,6 +68,8 @@ iidxhook6_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
iidxhook_util_d3d9_configure(&d3d9_config);

View File

@@ -68,6 +68,8 @@ iidxhook7_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
iidxhook_util_d3d9_configure(&d3d9_config);

View File

@@ -37,7 +37,7 @@
#include "util/thread.h"
#define IIDXHOOK8_INFO_HEADER \
"iidxhook for Cannon Ballers" \
"iidxhook for Cannon Ballers/Rootage" \
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n"
#define IIDXHOOK8_CMD_USAGE \
"Usage: launcher.exe -K iidxhook8.dll <bm2dx.dll> [options...]"
@@ -68,6 +68,8 @@ iidxhook8_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width;
d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height;
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter;
iidxhook_util_d3d9_configure(&d3d9_config);
@@ -75,6 +77,7 @@ iidxhook8_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
}
struct iidxhook8_config_io iidxhook8_config_io;
struct camhook_config_cam config_cam;
static struct bio2emu_port bio2_emu = {
.port = "COM4",
@@ -87,7 +90,6 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
struct cconfig *config;
struct iidxhook_config_gfx config_gfx;
struct camhook_config_cam config_cam;
// log_server_init is required due to IO occuring in a non avs_thread
log_server_init();
@@ -181,6 +183,10 @@ static bool my_dll_entry_main(void)
result = app_hook_invoke_main();
if (!config_cam.disable_emu) {
camhook_fini();
}
if (!iidxhook8_config_io.disable_card_reader_emu) {
log_misc("Shutting down card reader backend");
eam_io_fini();
@@ -197,7 +203,7 @@ static bool my_dll_entry_main(void)
}
/**
* Hook library Resort Anthem onwards
* Hook library CB/Rootage
*/
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{

View File

@@ -17,6 +17,7 @@
#include "util/codepage.h"
#include "util/defs.h"
#include "util/fs.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/str.h"
@@ -92,10 +93,34 @@ static AVS_LOG_WRITER(log_callback, chars, nchars, ctx)
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 i;
const char *hook_dll;
bool ok;
HANDLE logfile;
@@ -169,6 +194,8 @@ int main(int argc, const char **argv)
log_fatal("%s: /config missing", options.avs_config_path);
}
load_hook_dlls(&options.before_hook_dlls);
avs_context_init(
avs_config_root,
options.avs_heap_size,
@@ -187,27 +214,7 @@ int main(int argc, const char **argv)
/* Load hook DLLs */
for (i = 0; i < options.hook_dlls.nitems; i++) {
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);
}
}
load_hook_dlls(&options.hook_dlls);
/* Inject GetModuleHandle hooks */
@@ -243,7 +250,15 @@ int main(int argc, const char **argv)
/* Invoke dll_entry_init */
app_config = boot_property_load(options.app_config_path);
if (path_exists(options.app_config_path)) {
app_config = boot_property_load(options.app_config_path);
} else {
log_warning(
"%s: app config file missing, using empty",
options.app_config_path);
app_config = boot_property_load_cstring("<param>dummy</param>");
}
app_config_root = property_search(app_config, 0, "/param");
if (app_config_root == NULL) {

View File

@@ -23,6 +23,7 @@ void options_init(struct options *options)
options->logfile = NULL;
options->remote_debugger = false;
array_init(&options->hook_dlls);
array_init(&options->before_hook_dlls);
}
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;
case 'B':
if (i + 1 >= argc) {
return false;
}
*array_append(const char *, &options->before_hook_dlls) =
argv[++i];
break;
case 'Y':
if (i + 1 >= argc) {
return false;
@@ -170,6 +181,8 @@ void options_print_usage(void)
" -R [pcbid] Specify Soft ID (default: use ea3 config)\n"
" -K [filename] Load hook DLL (can be specified multiple "
"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"
" -D Halt the launcher before bootstrapping AVS "
"until a"
@@ -179,4 +192,5 @@ void options_print_usage(void)
void options_fini(struct options *options)
{
array_fini(&options->hook_dlls);
array_fini(&options->before_hook_dlls);
}

View File

@@ -17,6 +17,7 @@ struct options {
const char *module;
const char *logfile;
struct array hook_dlls;
struct array before_hook_dlls;
bool remote_debugger;
};

View File

@@ -20,6 +20,26 @@ static int boot_property_fread(uint32_t context, void *bytes, size_t nbytes)
return fread(bytes, 1, nbytes, f);
}
struct cstring_read_handle {
const char *buffer;
size_t buffer_len;
size_t offset;
};
static int
boot_property_cstring_read(uint32_t context, void *bytes, size_t nbytes)
{
int result = 0;
struct cstring_read_handle *h = TlsGetValue(context);
if (h->offset < h->buffer_len) {
result = min(nbytes, h->buffer_len - h->offset);
memcpy(bytes, (const void *) (h->buffer + h->offset), result);
h->offset += result;
}
return result;
}
struct property *boot_property_load(const char *filename)
{
struct property *prop;
@@ -65,6 +85,45 @@ struct property *boot_property_load(const char *filename)
return prop;
}
struct property *boot_property_load_cstring(const char *cstring)
{
struct property *prop;
void *buffer;
int nbytes;
uint32_t s_keyhole;
// see above
struct cstring_read_handle read_handle;
read_handle.buffer = cstring;
read_handle.buffer_len = strlen(cstring);
read_handle.offset = 0;
s_keyhole = TlsAlloc();
TlsSetValue(s_keyhole, &read_handle);
nbytes = property_read_query_memsize(
boot_property_cstring_read, s_keyhole, 0, 0);
if (nbytes < 0) {
log_fatal("Error querying configuration string");
}
buffer = xmalloc(nbytes);
prop = property_create(
PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE |
PROPERTY_FLAG_APPEND,
buffer,
nbytes);
read_handle.offset = 0;
if (!property_insert_read(prop, 0, boot_property_cstring_read, s_keyhole)) {
log_fatal("Error inserting configuration string");
}
TlsFree(s_keyhole);
return prop;
}
void boot_property_free(struct property *prop)
{

View File

@@ -4,6 +4,7 @@
#include "imports/avs.h"
struct property *boot_property_load(const char *filename);
struct property *boot_property_load_cstring(const char *cstring);
void boot_property_free(struct property *prop);
#endif

View File

@@ -0,0 +1,29 @@
avsdlls += sdvxhook2-cn
ldflags_sdvxhook2-cn := \
-liphlpapi \
-lsetupapi \
-lcfgmgr32 \
-lmf \
-lmfplat \
-lole32 \
deplibs_sdvxhook2-cn := \
avs \
libs_sdvxhook2-cn := \
acioemu \
camhook \
d3d9exhook \
sdvxio \
hook \
hooklib \
cconfig \
util \
src_sdvxhook2-cn := \
acio.c \
kfca.c \
dllmain.c \
config-cn.c \
unis-version.c \

View File

@@ -0,0 +1,92 @@
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "acioemu/addr.h"
#include "acioemu/emu.h"
#include "hook/iohook.h"
#include "hooklib/rs232.h"
#include "sdvxhook2-cn/acio.h"
#include "sdvxhook2-cn/kfca.h"
#include "imports/avs.h"
#include "util/defs.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu ac_io_emu;
void ac_io_port_init(void)
{
ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2");
kfca_init(&ac_io_emu);
rs232_hook_add_fd(ac_io_emu.fd);
}
void ac_io_port_fini(void)
{
ac_io_emu_fini(&ac_io_emu);
}
HRESULT ac_io_port_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&ac_io_emu, irp)) {
return irp_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&ac_io_emu, msg, 1);
log_warning("ac_io_emu_cmd_assign_addrs");
break;
case 1:
kfca_dispatch_request(msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast? (0x70) message on ACIO bus");
break;
default:
log_warning(
"ACIO message on unhandled bus address: %d", msg->addr);
break;
}
ac_io_emu_request_pop(&ac_io_emu);
}
}

View File

@@ -0,0 +1,14 @@
#ifndef SDVXHOOK2_5_AC_IO_H
#define SDVXHOOK2_5_AC_IO_H
#include <windows.h>
#include <stdbool.h>
#include "hook/iohook.h"
void ac_io_port_init(void);
void ac_io_port_fini(void);
HRESULT ac_io_port_dispatch_irp(struct irp *irp);
#endif

View File

@@ -0,0 +1,55 @@
#include "cconfig/cconfig-util.h"
#include "sdvxhook2-cn/config-cn.h"
#include "util/log.h"
#define SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY "io.disable_io_emu"
#define SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY "cn.unis_path"
#define SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE false
#define SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE "prop/unis.xml"
void sdvxhook2_cn_config_init(struct cconfig *config)
{
cconfig_util_set_bool(
config,
SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE,
"Disable IO emulation and enable usage of real KFCA hardware");
cconfig_util_set_str(
config,
SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE,
"Path to unis version file under the prop.s folder");
}
void sdvxhook2_cn_config_get(
struct sdvxhook2_cn_config *cn_config, struct cconfig *config)
{
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY,
&cn_config->disable_io_emu,
SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE);
}
if (!cconfig_util_get_str(
config,
SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY,
cn_config->unis_path,
sizeof(cn_config->unis_path),
SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY,
SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE);
}
}

View File

@@ -0,0 +1,18 @@
#ifndef SDVXHOOK2_CN_CONFIG_H
#define SDVXHOOK2_CN_CONFIG_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct sdvxhook2_cn_config {
bool disable_io_emu;
char unis_path[256];
};
void sdvxhook2_cn_config_init(struct cconfig *config);
void sdvxhook2_cn_config_get(
struct sdvxhook2_cn_config *cn_config, struct cconfig *config);
#endif

View File

@@ -0,0 +1,151 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "bemanitools/eamio.h"
#include "bemanitools/sdvxio.h"
#include "cconfig/cconfig-hook.h"
#include "hooklib/acp.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h"
#include "hooklib/rs232.h"
#include "sdvxhook2-cn/acio.h"
#include "sdvxhook2-cn/config-cn.h"
#include "sdvxhook2-cn/unis-version.h"
#include "camhook/cam.h"
#include "camhook/config-cam.h"
#include "d3d9exhook/config-gfx.h"
#include "d3d9exhook/d3d9ex.h"
#include "imports/avs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/thread.h"
#define SDVXHOOK2_CN_INFO_HEADER \
"sdvxhook for VW CN" \
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n"
#define SDVXHOOK2_CN_CMD_USAGE \
"Usage: launcher.exe -K sdvxhook2.dll <soundvoltex.dll> [options...]"
static const irp_handler_t sdvxhook_handlers[] = {
ac_io_port_dispatch_irp,
};
struct sdvxhook2_cn_config config_cn;
struct camhook_config_cam config_cam;
struct d3d9exhook_config_gfx config_gfx;
static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{
struct cconfig *config;
log_info("--- Begin sdvxhook dll_entry_init ---");
config = cconfig_init();
sdvxhook2_cn_config_init(config);
d3d9exhook_config_gfx_init(config);
camhook_config_cam_init(config, 1);
if (!cconfig_hook_config_init(
config,
SDVXHOOK2_CN_INFO_HEADER "\n" SDVXHOOK2_CN_CMD_USAGE,
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
cconfig_finit(config);
exit(EXIT_FAILURE);
}
sdvxhook2_cn_config_get(&config_cn, config);
camhook_config_cam_get(&config_cam, config, 1);
d3d9exhook_config_gfx_get(&config_gfx, config);
cconfig_finit(config);
log_info(SDVXHOOK2_CN_INFO_HEADER);
log_info("Initializing sdvxhook2-cn...");
d3d9ex_configure(&config_gfx);
/* Start up sdvxio.DLL */
if (!config_cn.disable_io_emu) {
log_info("Starting sdvx IO backend");
sdvx_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
if (!sdvx_io_init(
avs_thread_create, avs_thread_join, avs_thread_destroy)) {
log_fatal("Initializing sdvx IO backend failed");
}
}
/* iohooks are okay, even if emu is diabled since the fake handlers won't be
* used */
iohook_init(sdvxhook_handlers, lengthof(sdvxhook_handlers));
rs232_hook_init();
rs232_hook_limit_hooks();
if (!config_cn.disable_io_emu) {
ac_io_port_init();
}
// camera hooks
if (!config_cam.disable_emu) {
camhook_init(&config_cam);
}
unis_version_hook_init(config_cn.unis_path);
log_info("--- End sdvxhook dll_entry_init ---");
return app_hook_invoke_init(sidcode, param);
}
static bool my_dll_entry_main(void)
{
bool result;
result = app_hook_invoke_main();
if (!config_cam.disable_emu) {
camhook_fini();
}
if (!config_cn.disable_io_emu) {
log_misc("Shutting down sdvx IO backend");
sdvx_io_fini();
}
return result;
}
/**
* Hook library SDVX5 CN
*/
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{
if (reason != DLL_PROCESS_ATTACH) {
goto end;
}
log_to_external(
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
app_hook_init(my_dll_entry_init, my_dll_entry_main);
acp_hook_init();
adapter_hook_init();
d3d9ex_hook_init();
end:
return TRUE;
}

View File

@@ -0,0 +1,196 @@
#include <windows.h>
#include <stdint.h>
#include <string.h>
#include "acio/acio.h"
#include "acioemu/emu.h"
#include "bemanitools/sdvxio.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/time.h"
static void kfca_send_version(const struct ac_io_message *req);
static void kfca_report_status(const struct ac_io_message *req, uint8_t status);
static void kfca_report_0128(const struct ac_io_message *req);
static void kfca_poll(const struct ac_io_message *req);
static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp);
static struct ac_io_emu *kfca_ac_io_emu;
void kfca_init(struct ac_io_emu *emu)
{
log_assert(emu != NULL);
kfca_ac_io_emu = emu;
}
void kfca_dispatch_request(const struct ac_io_message *req)
{
uint16_t cmd_code;
cmd_code = ac_io_u16(req->cmd.code);
switch (cmd_code) {
case AC_IO_CMD_GET_VERSION:
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
kfca_send_version(req);
break;
case AC_IO_CMD_START_UP:
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
kfca_report_status(req, 0x00);
break;
case AC_IO_CMD_KFCA_POLL:
kfca_poll(req);
break;
case AC_IO_CMD_KFCA_WATCHDOG:
log_misc("AC_IO_CMD_KFCA_WATCHDOG(%d)", req->addr);
kfca_report_status(req, 0x00);
break;
case AC_IO_CMD_KFCA_AMP_CONTROL:
log_misc("AC_IO_CMD_KFCA_AMP_CONTROL(%d)", req->addr);
kfca_report_0128(req);
break;
default:
log_warning(
"Unknown ACIO message %04x on KFCA mode, addr=%d",
cmd_code,
req->addr);
break;
}
}
static void kfca_send_version(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_KFCA);
resp.cmd.version.flag = 0x00;
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x01;
resp.cmd.version.revision = 0x00;
memcpy(
resp.cmd.version.product_code,
"KFCA",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0);
}
static void kfca_report_status(const struct ac_io_message *req, uint8_t status)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.status);
resp.cmd.status = status;
ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0);
}
static void kfca_report_0128(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = req->cmd.nbytes;
memcpy(resp.cmd.raw, req->cmd.raw, req->cmd.nbytes);
ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0);
}
static void kfca_poll(const struct ac_io_message *req)
{
static uint32_t last_poll = 0;
uint64_t delay;
const struct ac_io_kfca_poll_out *pout;
uintptr_t ctx;
size_t i;
/* Handle lighting output immediately */
pout = &req->cmd.kfca_poll_out;
sdvx_io_set_gpio_lights(ac_io_u32(pout->gpio));
for (i = 0; i < lengthof(pout->pwm); i++) {
sdvx_io_set_pwm_light(i, pout->pwm[i]);
}
sdvx_io_write_output();
/* SDVX expects only one poll response per frame.
We use a thunk here to defer polling until right before the response
is due. */
delay = time_get_elapsed_ms(last_poll) < 16 ? 16000 : 0;
last_poll = time_get_counter();
ctx = req->addr | (req->cmd.code << 8) | (req->cmd.seq_no << 24);
ac_io_emu_response_push_thunk(
kfca_ac_io_emu, kfca_poll_thunk, (void *) ctx, delay);
}
static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp)
{
struct ac_io_kfca_poll_in *pin;
uintptr_t ctx;
uint8_t req_addr;
uint16_t req_code;
uint8_t req_seq_no;
/* Unpack context "pointer" for relevant response information */
ctx = (uintptr_t) ctx_ptr;
req_addr = ctx;
req_code = ctx >> 8;
req_seq_no = ctx >> 24;
/* Poll input now and construct an immediate response */
pin = &resp->cmd.kfca_poll_in;
resp->addr = req_addr | AC_IO_RESPONSE_FLAG;
resp->cmd.code = req_code;
resp->cmd.seq_no = req_seq_no;
resp->cmd.nbytes = sizeof(*pin);
sdvx_io_read_input();
memset(pin, 0, sizeof(*pin));
pin->adc[0] = sdvx_io_get_spinner_pos(0) << 6;
pin->adc[1] = sdvx_io_get_spinner_pos(1) << 6;
pin->gpio_sys |= sdvx_io_get_input_gpio_sys() & 0x3F;
pin->adc[0] = ac_io_u16(pin->adc[0]);
pin->adc[1] = ac_io_u16(pin->adc[1]);
pin->gpio[0] = ac_io_u16(sdvx_io_get_input_gpio(0));
pin->gpio[1] = ac_io_u16(sdvx_io_get_input_gpio(1));
}

View File

@@ -0,0 +1,11 @@
#ifndef SDVXHOOK_KFCA_H
#define SDVXHOOK_KFCA_H
#include "acio/acio.h"
#include "acioemu/emu.h"
void kfca_init(struct ac_io_emu *emu);
void kfca_dispatch_request(const struct ac_io_message *req);
#endif

View File

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

View File

@@ -0,0 +1,84 @@
#define LOG_MODULE "unis-version"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <shellapi.h>
// clang-format on
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
LPWSTR *(*real_CommandLineToArgvW)(LPCWSTR lpCmdLine, int *pNumArgs);
LPWSTR *my_CommandLineToArgvW(LPCWSTR lpCmdLine, int *pNumArgs);
static const struct hook_symbol unis_shell32_syms[] = {
{.name = "CommandLineToArgvW",
.patch = my_CommandLineToArgvW,
.link = (void **) &real_CommandLineToArgvW},
};
bool (*real_IsInComm)(void);
bool my_IsInComm(void);
bool (*real_IsConnectServer)(void);
bool my_IsConnectServer(void);
bool (*real_IsPlayerForbidState)(int pnum);
bool my_IsPlayerForbidState(int pnum);
static wchar_t unis_cmd_path[256 + 16];
static const struct hook_symbol unis_unisintr_syms[] = {
{.name = "IsInComm",
.patch = my_IsInComm,
.link = (void **) &real_IsInComm},
{.name = "IsConnectServer",
.patch = my_IsConnectServer,
.link = (void **) &real_IsConnectServer},
{.name = "IsPlayerForbidState",
.patch = my_IsPlayerForbidState,
.link = (void **) &real_IsPlayerForbidState},
};
LPWSTR *my_CommandLineToArgvW(LPCWSTR lpCmdLine, int *pNumArgs)
{
return real_CommandLineToArgvW(unis_cmd_path, pNumArgs);
}
bool my_IsInComm(void)
{
return true;
}
bool my_IsConnectServer(void)
{
return true;
}
bool my_IsPlayerForbidState(int pnum)
{
return false;
}
void unis_version_hook_init(const char* unis_path)
{
hook_table_apply(
NULL, "Shell32.dll", unis_shell32_syms, lengthof(unis_shell32_syms));
hook_table_apply(
NULL, "unisintr.dll", unis_unisintr_syms, lengthof(unis_unisintr_syms));
wcscpy(unis_cmd_path, L"launcher.exe ");
wchar_t *end = wcsrchr(unis_cmd_path, L'\0');
mbstowcs(end, unis_path, 256);
log_info("Inserted hooks for unis version detection");
}

View File

@@ -0,0 +1,14 @@
#ifndef SDVXHOOK2_5_UNIS_VERSION_H
#define SDVXHOOK2_5_UNIS_VERSION_H
/**
* Hooks UNIS support functions
*
* patches:
* - unis config path
* - unis network functions
*
*/
void unis_version_hook_init(const char* unis_path);
#endif

View File

@@ -25,8 +25,10 @@ kfca_amp_control(struct ac_io_emu *emu, const struct ac_io_message *req);
static bool poll_delay;
static bool force_headphones_on;
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);
@@ -35,6 +37,8 @@ void bio2_emu_bi2a_init(
if (!poll_delay) {
log_warning("bio2_emu_bi2a_init: poll_delay has been disabled");
}
force_headphones_on = force_headphones;
}
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_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_b = check_pin(gpio0, SDVX_IO_IN_GPIO_0_B);
pin->buttons_1.b_c = check_pin(gpio0, SDVX_IO_IN_GPIO_0_C);

View File

@@ -83,7 +83,7 @@ _Static_assert(
"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_init(struct bio2emu_port *in, bool disable_poll_limiter, bool force_headphones);
void bio2_emu_bi2a_dispatch_request(
struct bio2emu_port *bio2port, const struct ac_io_message *req);

View File

@@ -8,10 +8,12 @@
"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_FORCE_HEADPHONES_KEY "io.force_headphones"
#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
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_DEFAULT_DISABLE_POLL_LIMITER_VALUE,
"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(
@@ -73,4 +81,16 @@ void sdvxhook2_config_io_get(
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
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);
}
}

View File

@@ -9,6 +9,7 @@ struct sdvxhook2_config_io {
bool disable_card_reader_emu;
bool disable_bio2_emu;
bool disable_poll_limiter;
bool force_headphones;
};
void sdvxhook2_config_io_init(struct cconfig *config);

View File

@@ -13,6 +13,7 @@
#include "hooklib/acp.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h"
#include "hooklib/config-adapter.h"
#include "hooklib/rs232.h"
#include "bio2emu/emu.h"
@@ -47,6 +48,7 @@ static const irp_handler_t sdvxhook_handlers[] = {
struct sdvxhook2_config_io config_io;
struct camhook_config_cam config_cam;
struct d3d9exhook_config_gfx config_gfx;
struct hooklib_config_adapter config_adapter;
static struct bio2emu_port bio2_emu = {
.port = "COM4",
@@ -65,6 +67,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
sdvxhook2_config_io_init(config);
d3d9exhook_config_gfx_init(config);
camhook_config_cam_init(config, 1);
hooklib_config_adapter_init(config);
if (!cconfig_hook_config_init(
config,
@@ -77,6 +80,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
sdvxhook2_config_io_get(&config_io, config);
camhook_config_cam_get(&config_cam, config, 1);
d3d9exhook_config_gfx_get(&config_gfx, config);
hooklib_config_adapter_get(&config_adapter, config);
cconfig_finit(config);
@@ -117,7 +121,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
if (!config_io.disable_bio2_emu) {
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) {
@@ -129,6 +133,8 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
camhook_init(&config_cam);
}
adapter_hook_override(config_adapter.override_ip);
log_info("--- End sdvxhook dll_entry_init ---");
return app_hook_invoke_init(sidcode, param);
@@ -140,6 +146,10 @@ static bool my_dll_entry_main(void)
result = app_hook_invoke_main();
if (!config_cam.disable_emu) {
camhook_fini();
}
if (!config_io.disable_card_reader_emu) {
log_misc("Shutting down card reader backend");
eam_io_fini();
@@ -154,7 +164,7 @@ static bool my_dll_entry_main(void)
}
/**
* Hook library Resort Anthem onwards
* Hook library SDVX5+
*/
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{