Compare commits

...

20 Commits
5.40 ... 5.42

Author SHA1 Message Date
icex2
119272b5d2 Update changelog for 5.42 release 2022-06-16 00:19:59 +02:00
icex2
0cd85083f6 Fix compiler warning about conversion type in snprintf 2022-06-16 00:10:50 +02:00
icex2
485c4d0ad7 Documentation clarification 2022-06-16 00:02:49 +02:00
2d9f8a0741a7573b189035dcb819847ecb5d981d
4bd0ee5ef6 iidxhook: Fix diagonal tearing on textures on iidx18 and 19
Affects all games based on version 18 and 19 which includes
the chinese versions

This code is based on the toastertools implementation.
Credits to the original authors.
2022-06-16 00:02:47 +02:00
2d9f8a0741a7573b189035dcb819847ecb5d981d
8081793a5f iidxhook4-cn: Add support for IIDX Resort Anthem CN
* Exe based game
* No network functionality
* No card readers checked/used
2022-06-15 23:34:50 +02:00
2d9f8a0741a7573b189035dcb819847ecb5d981d
badd616add iidxhook 4, 5, 5-cn: enable nvidia fix
Was absent but actually fixes crashing on nvidia cards
on these versions as well.
2022-06-15 21:30:43 +00:00
2d9f8a0741a7573b189035dcb819847ecb5d981d
926e976c36 iidxhook5-cn: Fix log messages, Delete unnecessary code
The game doesn't have network nor uses card readers
2022-06-15 21:29:15 +00:00
95c6cd771e00602e3ec82fccba1b3741fdb7f7ca
5d2b46376d popn: add config.bat 2022-06-13 04:28:33 +09:00
icex2
8d5ef0bfb3 Bump version to 5.42 for next development cycle 2022-06-12 20:09:10 +02:00
icex2
db12f21fd2 Update changelog for 5.41 release 2022-06-12 19:47:44 +02:00
icex2
d009502c9f Add basic documentation for tricoro CN 2022-06-12 19:47:27 +02:00
2d9f8a0741a7573b189035dcb819847ecb5d981d
aa147022c6 Add iidxhook5-cn, support IIDX tricoro CN
alternative name: (狂热节拍 IIDX 2)
2022-06-10 22:54:13 +00:00
icex2
8bcadcfa8f doc/game-errorcodes: Add the well known IIDX network error on boot 2022-06-11 00:45:54 +02:00
icex2
993e6718b3 doc/game-error-codes: Extend USB IO errors 2022-06-11 00:45:54 +02:00
icex2
2939106841 doc: Add links to game error code documentation 2022-06-11 00:45:52 +02:00
icex2
91bb3b4278 doc/game-error-codes: Add information about backup data error 2022-06-11 00:45:07 +02:00
icex2
9c49839e57 Add document with game error codes
Reasoning given in document why this should be part of btools
2022-06-11 00:45:07 +02:00
icex2
52d907e0c6 doc/iidxhook: Improve faq item video codec background video
Add some more information making it easier to identify the entry
2022-06-11 00:45:07 +02:00
QCDLZCLW3K
f8a09580ea Support pop'n music 15-18
* popnhook1 for pop'n 15 - 18 has been added
* popnio has been added
* inject.exe has new syntax for loading hook DLLs, `real.dll=hook.dll`. This will trigger an early IAT hook where it will load the EXE suspended without resolving imports, replace the reference to real.dll in the import table with hook.dll, and then resolve everything before launching. This allows for ezusb.dll to be hooked properly.
* launcher.exe also has a new early IAT hook feature now. Use `-I real.dll=hook.dll`. The idea is the same as described above for inject.exe.
* Updated ezusb constant namings based on what is visible in ezusb.dll's debug statements.

The launcher.exe implementation of early IAT hooking means that someone can implement popnhook2.dll for 19 and above. I have tried pop'n music Sunny Park using a modified version of popnhook1 and it seems to work to some degree: the I/O check and security check returns OK which means the ezusb hooking used in popnhook1 is also working for the later games using `launcher.exe -I ezusb.dll=ezusb2-popn-shim.dll ...`. The process is rather invasive (manually resolving all imports means more chances to fail) so it has been implemented in such a way that the launcher will work the same as it has before as long as `-I` isn't specified.

One questionable thing I am not confident about is the `texture_usage_fix` hack flag I added in the conf. As the comment says, pop'n music 16 will work in Windows XP without the flag being set, but the game will immediately crash on later OSes without the flag being set in my experience. No other games had this issue in my experience. Enabling it in other games doesn't seem to have any negative effects.
2022-06-10 22:46:59 +00:00
icex2
6e06685551 Bump version to 5.41 for next development cycle 2022-06-07 20:20:30 +02:00
114 changed files with 6131 additions and 163 deletions

View File

@@ -2,6 +2,18 @@
Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions
given in tags. The pipeline will pick this up and cuts out the relevant section for release notes. given in tags. The pipeline will pick this up and cuts out the relevant section for release notes.
## 5.42
* Bugfix: Fix diagonal texture tearing on IIDX 18 and 19 based games
* Feature: Add support for IIDX Resort Anthem CN using iidxhook4-cn
* Feature/bugfix: Enable "nvidia fix" for iidxhook4, 5 and 5-cn. Should fix crashing on some/all
nvidia cards
* Various minor fixes
## 5.41
* Feature: Support pop'n music 15-18 using popnhook1
* Feature: Support IIDX tricoro CN using iidxhook5-cn
* Various documentation improvements
## 5.40 ## 5.40
* Feature: Support DDR X and X2 US/EU using ddrhook1 including memory card emulation * Feature: Support DDR X and X2 US/EU using ddrhook1 including memory card emulation
* Fix: sdvxhook2 crashing on some OS versions * Fix: sdvxhook2 crashing on some OS versions

View File

@@ -29,4 +29,4 @@ COPY src src
COPY .git .git COPY .git .git
# Building # Building
RUN make RUN make

View File

@@ -21,12 +21,19 @@
# #
# 4: Patch 2: beatmania IIDX 14 GOLD # 4: Patch 2: beatmania IIDX 14 GOLD
# #
# 4: Patch 3: pop'n music 15 ADVENTURE
#
# 6: Patch 5: beatmania IIDX 15 DJ Troopers # 6: Patch 5: beatmania IIDX 15 DJ Troopers
# #
# 7: Patch 1: pop'n music 16 PARTY
#
# 8: Patch 3: beatmania IIDX 16 Empress # 8: Patch 3: beatmania IIDX 16 Empress
# jubeat # jubeat
# #
# 10: Patch 2: jubeat Knit # 9: Patch 0: pop'n music 17 THE MOVIE
#
# 10: Patch 1: pop'n music 18 Sengoku Retsuden
# Patch 2: jubeat Knit
# Patch 4: DanceDanceRevolution X2 # Patch 4: DanceDanceRevolution X2
# #
# 11: Patch 1: beatmania IIDX 18 Resort Anthem # 11: Patch 1: beatmania IIDX 18 Resort Anthem
@@ -113,6 +120,8 @@ include src/main/ezusb2-dbg-hook/Module.mk
include src/main/ezusb2-emu/Module.mk include src/main/ezusb2-emu/Module.mk
include src/main/ezusb2-iidx-emu/Module.mk include src/main/ezusb2-iidx-emu/Module.mk
include src/main/ezusb2-iidx/Module.mk include src/main/ezusb2-iidx/Module.mk
include src/main/ezusb2-popn-emu/Module.mk
include src/main/ezusb2-popn-shim/Module.mk
include src/main/ezusb2-tool/Module.mk include src/main/ezusb2-tool/Module.mk
include src/main/ezusb2/Module.mk include src/main/ezusb2/Module.mk
include src/main/geninput/Module.mk include src/main/geninput/Module.mk
@@ -127,7 +136,9 @@ include src/main/iidxhook1/Module.mk
include src/main/iidxhook2/Module.mk include src/main/iidxhook2/Module.mk
include src/main/iidxhook3/Module.mk include src/main/iidxhook3/Module.mk
include src/main/iidxhook4/Module.mk include src/main/iidxhook4/Module.mk
include src/main/iidxhook4-cn/Module.mk
include src/main/iidxhook5/Module.mk include src/main/iidxhook5/Module.mk
include src/main/iidxhook5-cn/Module.mk
include src/main/iidxhook6/Module.mk include src/main/iidxhook6/Module.mk
include src/main/iidxhook7/Module.mk include src/main/iidxhook7/Module.mk
include src/main/iidxhook8/Module.mk include src/main/iidxhook8/Module.mk
@@ -154,6 +165,9 @@ include src/main/p3io/Module.mk
include src/main/p3ioemu/Module.mk include src/main/p3ioemu/Module.mk
include src/main/p4iodrv/Module.mk include src/main/p4iodrv/Module.mk
include src/main/p4ioemu/Module.mk include src/main/p4ioemu/Module.mk
include src/main/popnhook-util/Module.mk
include src/main/popnhook1/Module.mk
include src/main/popnio/Module.mk
include src/main/pcbidgen/Module.mk include src/main/pcbidgen/Module.mk
include src/main/sdvxhook/Module.mk include src/main/sdvxhook/Module.mk
include src/main/sdvxhook2-cn/Module.mk include src/main/sdvxhook2-cn/Module.mk
@@ -299,6 +313,21 @@ $(zipdir)/iidx-18.zip: \
$(V)echo ... $@ $(V)echo ... $@
$(V)zip -j $@ $^ $(V)zip -j $@ $^
$(zipdir)/iidx-18-cn.zip: \
build/bin/avs2_1101-32/iidxhook4-cn.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
dist/iidx/config.bat \
dist/iidx/gamestart-18-cn.bat \
dist/iidx/iidxhook-18-cn.conf \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/iidx-19.zip: \ $(zipdir)/iidx-19.zip: \
build/bin/avs2_1304-32/iidxhook5.dll \ build/bin/avs2_1304-32/iidxhook5.dll \
build/bin/avs2_1304-32/launcher.exe \ build/bin/avs2_1304-32/launcher.exe \
@@ -331,6 +360,21 @@ $(zipdir)/iidx-20.zip: \
$(V)echo ... $@ $(V)echo ... $@
$(V)zip -j $@ $^ $(V)zip -j $@ $^
$(zipdir)/iidx-20-cn.zip: \
build/bin/avs2_1304-32/iidxhook5-cn.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
dist/iidx/config.bat \
dist/iidx/gamestart-20-cn.bat \
dist/iidx/iidxhook-20-cn.conf \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/iidx-21-to-24.zip: \ $(zipdir)/iidx-21-to-24.zip: \
build/bin/avs2_1601-32/iidxhook7.dll \ build/bin/avs2_1601-32/iidxhook7.dll \
build/bin/avs2_1601-32/launcher.exe \ build/bin/avs2_1601-32/launcher.exe \
@@ -685,6 +729,27 @@ $(zipdir)/bst.zip: \
$(V)echo ... $@ $(V)echo ... $@
$(V)zip -j $@ $^ $(V)zip -j $@ $^
$(zipdir)/popn-15-to-18.zip: \
build/bin/avs2_803-32/popnhook1.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/inject.exe \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/popnio.dll \
build/bin/indep-32/ezusb2-popn-shim.dll \
dist/popn/config.bat \
dist/popn/gamestart-15.bat \
dist/popn/gamestart-16.bat \
dist/popn/gamestart-17.bat \
dist/popn/gamestart-18.bat \
dist/popn/popnhook-15.conf \
dist/popn/popnhook-16.conf \
dist/popn/popnhook-17.conf \
dist/popn/popnhook-18.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/doc.zip: \ $(zipdir)/doc.zip: \
doc/ \ doc/ \
| $(zipdir)/ | $(zipdir)/
@@ -730,8 +795,10 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/iidx-13.zip \ $(zipdir)/iidx-13.zip \
$(zipdir)/iidx-14-to-17.zip \ $(zipdir)/iidx-14-to-17.zip \
$(zipdir)/iidx-18.zip \ $(zipdir)/iidx-18.zip \
$(zipdir)/iidx-18-cn.zip \
$(zipdir)/iidx-19.zip \ $(zipdir)/iidx-19.zip \
$(zipdir)/iidx-20.zip \ $(zipdir)/iidx-20.zip \
$(zipdir)/iidx-20-cn.zip \
$(zipdir)/iidx-21-to-24.zip \ $(zipdir)/iidx-21-to-24.zip \
$(zipdir)/iidx-25-to-26.zip \ $(zipdir)/iidx-25-to-26.zip \
$(zipdir)/iidx-27-to-28.zip \ $(zipdir)/iidx-27-to-28.zip \
@@ -744,6 +811,7 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/jb-05-to-07.zip \ $(zipdir)/jb-05-to-07.zip \
$(zipdir)/jb-08.zip \ $(zipdir)/jb-08.zip \
$(zipdir)/jb-hwio.zip \ $(zipdir)/jb-hwio.zip \
$(zipdir)/popn-15-to-18.zip \
$(zipdir)/sdvx-01-to-04.zip \ $(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05-to-06.zip \ $(zipdir)/sdvx-05-to-06.zip \
$(zipdir)/sdvx-05-cn.zip \ $(zipdir)/sdvx-05-cn.zip \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5 # Bemanitools 5
[![pipeline status](https://dev.s-ul.net/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.net/djhackers/bemanitools/commits/master) [![pipeline status](https://dev.s-ul.net/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.net/djhackers/bemanitools/commits/master)
Version: 5.40 Version: 5.42
[Release history](CHANGELOG.md) [Release history](CHANGELOG.md)
@@ -51,6 +51,7 @@ The following games are supported with their corresponding hook-libraries.
* Beatmania IIDX 17 SIRIUS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md) * Beatmania IIDX 17 SIRIUS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 18 Resort Anthem (`iidx-18.zip`): [iidxhook4](doc/iidxhook/iidxhook4.md) * Beatmania IIDX 18 Resort Anthem (`iidx-18.zip`): [iidxhook4](doc/iidxhook/iidxhook4.md)
* Beatmania IIDX 19 Lincle (`iidx-19.zip`): [iidxhook5](doc/iidxhook/iidxhook5.md) * Beatmania IIDX 19 Lincle (`iidx-19.zip`): [iidxhook5](doc/iidxhook/iidxhook5.md)
* Beatmania IIDX tricoro CN (狂热节拍 IIDX 2) (`iidx-20-cn.zip`): [iidxhook5-cn](doc/iidxhook/iidxhook5-cn.md)
* Beatmania IIDX 20 Tricoro (`iidx-20.zip`): [iidxhook6](doc/iidxhook/iidxhook6.md) * Beatmania IIDX 20 Tricoro (`iidx-20.zip`): [iidxhook6](doc/iidxhook/iidxhook6.md)
* Beatmania IIDX 21 SPADA (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md) * Beatmania IIDX 21 SPADA (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 22 PENDUAL (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md) * Beatmania IIDX 22 PENDUAL (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
@@ -70,6 +71,11 @@ The following games are supported with their corresponding hook-libraries.
* jubeat qubell (`jb-05-to-07.zip`): [jbhook3](doc/jbhook/jbhook3.md) * jubeat qubell (`jb-05-to-07.zip`): [jbhook3](doc/jbhook/jbhook3.md)
* jubeat clan (`jb-08.zip`): [jbhook3](doc/jbhook/jbhook3.md) * jubeat clan (`jb-08.zip`): [jbhook3](doc/jbhook/jbhook3.md)
* jubeat festo (`jb-08.zip`): [jbhook3](doc/jbhook/jbhook3.md) * jubeat festo (`jb-08.zip`): [jbhook3](doc/jbhook/jbhook3.md)
* [pop'n music](doc/popnhook/README.md)
* pop'n music 15 ADVENTURE (`popn-15-to-18.zip`) using [popnhook1](doc/popnhook/popnhook1.md)
* pop'n music 16 PARTY♪ (`popn-15-to-18.zip`) using [popnhook1](doc/popnhook/popnhook1.md)
* pop'n music 17 THE MOVIE (`popn-15-to-18.zip`) using [popnhook1](doc/popnhook/popnhook1.md)
* pop'n music 18 せんごく列伝 (`popn-15-to-18.zip`) using [popnhook1](doc/popnhook/popnhook1.md)
* SOUND VOLTEX * SOUND VOLTEX
* SOUND VOLTEX BOOTH (`sdvx-01-to-04.zip`): sdvxhook * SOUND VOLTEX BOOTH (`sdvx-01-to-04.zip`): sdvxhook
* SOUND VOLTEX II -infinite infection- (`sdvx-01-to-04.zip`): sdvxhook * SOUND VOLTEX II -infinite infection- (`sdvx-01-to-04.zip`): sdvxhook
@@ -91,7 +97,7 @@ change in the future. Many games also run on very recent Windows 10 builds but b
with Windows updates breaking legacy software. with Windows updates breaking legacy software.
## Distribution contents ## Distribution contents
Check the [list of supported games](#list-of-supported-games) to grab the right files for your game. BT5 also includes Check the [list of supported games](#supported-games) to grab the right files for your game. BT5 also includes
a *tools* subpackage (tools.zip) as well as the full source code (src.zip). a *tools* subpackage (tools.zip) as well as the full source code (src.zip).
You will find *.md files in various sub-packages that give you further instructions for setup, usage, error information You will find *.md files in various sub-packages that give you further instructions for setup, usage, error information

14
dist/iidx/gamestart-18-cn.bat vendored Normal file
View File

@@ -0,0 +1,14 @@
@echo off
cd /d %~dp0
if not exist d mkdir d
if not exist e mkdir e
if not exist f mkdir f
if not exist e\avs_conf mkdir e\avs_conf
if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF
if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM
if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW
inject iidxhook4-cn.dll bm2dx.exe -D --config iidxhook-18-cn.conf %*

14
dist/iidx/gamestart-20-cn.bat vendored Normal file
View File

@@ -0,0 +1,14 @@
@echo off
cd /d %~dp0
if not exist d mkdir d
if not exist e mkdir e
if not exist f mkdir f
if not exist e\avs_conf mkdir e\avs_conf
if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF
if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM
if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW
inject iidxhook5-cn.dll bm2dx.exe -D --config iidxhook-20-cn.conf %*

50
dist/iidx/iidxhook-18-cn.conf vendored Normal file
View File

@@ -0,0 +1,50 @@
# PCBID
eamuse.pcbid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit)
gfx.frame_rate_limit=0.0
# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!!
gfx.monitor_check=-1.000000
# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450)
gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter.
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 diagonal tearing with video cards other than Radeon X1300 and HD3450
gfx.diagonal_tearing_fix=false
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
io.disable_io_emu=false
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GKJDZCAA

View File

@@ -37,6 +37,9 @@ gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter # D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1 gfx.device_adapter=-1
# Fix diagonal tearing with video cards other than Radeon X1300 and HD3450
gfx.diagonal_tearing_fix=false
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) # Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
io.disable_card_reader_emu=false io.disable_card_reader_emu=false

View File

@@ -34,6 +34,9 @@ gfx.forced_refresh_rate=-1
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter # D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
gfx.device_adapter=-1 gfx.device_adapter=-1
# Fix diagonal tearing with video cards other than Radeon X1300 and HD3450
gfx.diagonal_tearing_fix=false
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) # Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
io.disable_card_reader_emu=false io.disable_card_reader_emu=false

47
dist/iidx/iidxhook-20-cn.conf vendored Normal file
View File

@@ -0,0 +1,47 @@
# PCBID
eamuse.pcbid=0101020304050607086F
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
gfx.bgvideo_uv_fix=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit)
gfx.frame_rate_limit=0.0
# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450)
gfx.pci_id=1002:7146
# Run the game windowed
gfx.windowed=false
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, 0 for default size
gfx.window_height=0
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
gfx.scale_back_buffer_width=0
# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter.
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 diagonal tearing with video cards other than Radeon X1300 and HD3450
gfx.diagonal_tearing_fix=false
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
io.disable_io_emu=false
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GKJDZCAA

1
dist/popn/config.bat vendored Normal file
View File

@@ -0,0 +1 @@
@start config.exe pnm

16
dist/popn/gamestart-15.bat vendored Normal file
View File

@@ -0,0 +1,16 @@
@echo off
cd /d %~dp0
if not exist e\bookkeeping mkdir e\bookkeeping
if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM
if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0
if not exist e\CONF\NVRAM\1 mkdir e\CONF\NVRAM\1
if not exist e\CONF\NVRAM\2 mkdir e\CONF\NVRAM\2
if not exist e\CONF\NVRAM\3 mkdir e\CONF\NVRAM\3
if not exist e\CONF\RAW mkdir e\CONF\RAW
if not exist e\settings mkdir e\settings
if not exist e\UP mkdir e\UP
inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn15.exe --config popnhook-15.conf %*

16
dist/popn/gamestart-16.bat vendored Normal file
View File

@@ -0,0 +1,16 @@
@echo off
cd /d %~dp0
if not exist e\bookkeeping mkdir e\bookkeeping
if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM
if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0
if not exist e\CONF\NVRAM\1 mkdir e\CONF\NVRAM\1
if not exist e\CONF\NVRAM\2 mkdir e\CONF\NVRAM\2
if not exist e\CONF\NVRAM\3 mkdir e\CONF\NVRAM\3
if not exist e\CONF\RAW mkdir e\CONF\RAW
if not exist e\settings mkdir e\settings
if not exist e\UP mkdir e\UP
inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn16.exe --config popnhook-16.conf %*

16
dist/popn/gamestart-17.bat vendored Normal file
View File

@@ -0,0 +1,16 @@
@echo off
cd /d %~dp0
if not exist e\bookkeeping mkdir e\bookkeeping
if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM
if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0
if not exist e\CONF\NVRAM\1 mkdir e\CONF\NVRAM\1
if not exist e\CONF\NVRAM\2 mkdir e\CONF\NVRAM\2
if not exist e\CONF\NVRAM\3 mkdir e\CONF\NVRAM\3
if not exist e\CONF\RAW mkdir e\CONF\RAW
if not exist e\settings mkdir e\settings
if not exist e\UP mkdir e\UP
inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn17.exe --config popnhook-17.conf %*

16
dist/popn/gamestart-18.bat vendored Normal file
View File

@@ -0,0 +1,16 @@
@echo off
cd /d %~dp0
if not exist e\bookkeeping mkdir e\bookkeeping
if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM
if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0
if not exist e\CONF\NVRAM\1 mkdir e\CONF\NVRAM\1
if not exist e\CONF\NVRAM\2 mkdir e\CONF\NVRAM\2
if not exist e\CONF\NVRAM\3 mkdir e\CONF\NVRAM\3
if not exist e\CONF\RAW mkdir e\CONF\RAW
if not exist e\settings mkdir e\settings
if not exist e\UP mkdir e\UP
inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn18.exe --config popnhook-18.conf %*

23
dist/popn/popnhook-15.conf vendored Normal file
View File

@@ -0,0 +1,23 @@
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80
# PCBID
eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Run the game windowed
gfx.windowed=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, 0 for default size
gfx.window_height=0
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQG15JAA

23
dist/popn/popnhook-16.conf vendored Normal file
View File

@@ -0,0 +1,23 @@
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80
# PCBID
eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Run the game windowed
gfx.windowed=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, 0 for default size
gfx.window_height=0
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQH16JAA

23
dist/popn/popnhook-17.conf vendored Normal file
View File

@@ -0,0 +1,23 @@
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80
# PCBID
eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Run the game windowed
gfx.windowed=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, 0 for default size
gfx.window_height=0
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQI17JAA

23
dist/popn/popnhook-18.conf vendored Normal file
View File

@@ -0,0 +1,23 @@
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80
# PCBID
eamuse.pcbid=0101020304050607086F
# EAMID
eamuse.eamid=0101020304050607086F
# Run the game windowed
gfx.windowed=false
# Run the game in a framed window (requires windowed option)
gfx.framed=false
# Windowed width, 0 for default size
gfx.window_width=0
# Windowed height, 0 for default size
gfx.window_height=0
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GCJ39JAA

View File

@@ -4,6 +4,9 @@ This folder contains various types of documentation.
Table of contents: Table of contents:
* Game
* [Error codes](game-error-codes.md): List of bemani game specific error codes that you might
encounter during boot or gameplay with troubleshooting information
* Key tools * Key tools
* [Inject](inject.md): Readme for one of BT5's key applications, `inject.exe` * [Inject](inject.md): Readme for one of BT5's key applications, `inject.exe`
* [Launcher](launcher.md): Readme for another one of BT5's key applications, `launcher.exe` * [Launcher](launcher.md): Readme for another one of BT5's key applications, `launcher.exe`
@@ -12,6 +15,7 @@ Table of contents:
* [ddrhook](ddrhook/README.md): Documentation relevant to `ddrhook` implementations * [ddrhook](ddrhook/README.md): Documentation relevant to `ddrhook` implementations
* [iidxhook](iidxhook/README.md): Documentation relevant to `iidxhook` implementations * [iidxhook](iidxhook/README.md): Documentation relevant to `iidxhook` implementations
* [jbhook](jbhook/README.md): Documentation relevant to `jbhook` implementations * [jbhook](jbhook/README.md): Documentation relevant to `jbhook` implementations
* [popnhook](popnhook/README.md): Documentation relevant to `popnhook` implementations
* [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations * [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations
* Development * Development
* [API](api.md): Available APIs for BT5 and instructions how to use them * [API](api.md): Available APIs for BT5 and instructions how to use them

View File

@@ -12,7 +12,7 @@ If you want to write an implementation for your own custom piece of hardware, ch
sub-folder) in the source code (src.zip). sub-folder) in the source code (src.zip).
## Implementations ## Implementations
The following implementations are already shipped with BT5. The following implementations are already shipped with BT5.
* BeatStream * BeatStream
* bstio.dll (default): Keyboard, joystick and mouse input * bstio.dll (default): Keyboard, joystick and mouse input
@@ -27,13 +27,15 @@ The following implementations are already shipped with BT5.
* [iidxio-ezusb2.dll](iidxhook/iidxio-ezusb2.md): Ezusb FX2 (IO2) driver * [iidxio-ezusb2.dll](iidxhook/iidxio-ezusb2.md): Ezusb FX2 (IO2) driver
* jubeat * jubeat
* jbio.dll (default): Keyboard, joystick and mouse input * jbio.dll (default): Keyboard, joystick and mouse input
* pop'n music
* popnio.dll (default): Keyboard, joystick and mouse input
* SOUND VOLTEX * SOUND VOLTEX
* sdvxio.dll (default): Keyboard, joystick and mouse input * sdvxio.dll (default): Keyboard, joystick and mouse input
* [sdvxio-bio2.dll](sdvxhook/sdvxio-bio2.md): BIO2 driver * [sdvxio-bio2.dll](sdvxhook/sdvxio-bio2.md): BIO2 driver
* [sdvxio-kfca.dll](sdvxhook/sdvxio-kfca.md): KFCA IO board driver * [sdvxio-kfca.dll](sdvxhook/sdvxio-kfca.md): KFCA IO board driver
Eamuse hardware support is implemented separately: Eamuse hardware support is implemented separately:
* eamio.dll (default): Keyboard and joystick input * eamio.dll (default): Keyboard and joystick input
## Development notes ## Development notes
A DEF file for geninput.dll is included. To convert the DEF into an import library suitable for use with Visual C++, run A DEF file for geninput.dll is included. To convert the DEF into an import library suitable for use with Visual C++, run

View File

@@ -51,7 +51,7 @@ Modules that make use of this:
* ezusb2-emu/device * ezusb2-emu/device
* acioemu/emu * acioemu/emu
## Bemanitools's hook libraries, let's glue everything together ## Bemanitools's hook libraries, let's glue everything together
Bemanitools dlls to be injected into target game processes are refered to as "hook dlls" and come in different flavours Bemanitools dlls to be injected into target game processes are refered to as "hook dlls" and come in different flavours
targetting different games and often different versions of the same game (series), for example: targetting different games and often different versions of the same game (series), for example:
* ddrhook: Hook dll for Dance Dance Revolution games * ddrhook: Hook dll for Dance Dance Revolution games
@@ -69,13 +69,13 @@ TODO
### iidxhook ### iidxhook
IIDX went through so many hard- and software iterations, it's actually amazing that the development team(s) refactored IIDX went through so many hard- and software iterations, it's actually amazing that the development team(s) refactored
and improved parts of the game and hardware with each iteration. However, when facing emulation and supporting and improved parts of the game and hardware with each iteration. However, when facing emulation and supporting
compatibility to legacy OS platforms, it can't get any worse. On the bright side, IIDX helped shaping Bemanitools a lot compatibility to legacy OS platforms, it can't get any worse. On the bright side, IIDX helped shaping Bemanitools a lot
and created a solid foundation other games can build on. and created a solid foundation other games can build on.
Because of that, we have 8 iidxhook implementations supporting sometimes different software features/fixes and Because of that, we have 8 iidxhook implementations supporting sometimes different software features/fixes and
hardware. The following sub-sub-sections list the most relevant aspects and modules to point out common and different hardware. The following sub-sub-sections list the most relevant aspects and modules to point out common and different
higher level features. higher level features.
Essentially, the main module file of each iidxhook implementation just glues the APIs of the modules it requires Essentially, the main module file of each iidxhook implementation just glues the APIs of the modules it requires
together. An additional configuration layer allows users to tweak some of the features. together. An additional configuration layer allows users to tweak some of the features.
@@ -88,7 +88,7 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
* Setupapi emulation * Setupapi emulation
* Full security emulation with SRAM and round plugs * Full security emulation with SRAM and round plugs
* Full serial emulation for magstripe card readers * Full serial emulation for magstripe card readers
* Full game essential I/O emulation * Full game essential I/O emulation
* d3d8 patching and extended features (superseded by d3d9 hook module + d3d8to9 wrapper) * d3d8 patching and extended features (superseded by d3d9 hook module + d3d8to9 wrapper)
* clock patching * clock patching
* Font patching for Japanese chars * Font patching for Japanese chars
@@ -99,7 +99,7 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
* Ezusb C02 I/O emulation * Ezusb C02 I/O emulation
* Setupapi emulation * Setupapi emulation
* Full security emulation with SRAM and round plugs * Full security emulation with SRAM and round plugs
* Full game essential I/O emulation * Full game essential I/O emulation
* ACIO ICCA card reader emulation, slotted readers * ACIO ICCA card reader emulation, slotted readers
* d3d8 patching and extended features (superseded by d3d9 hook module + d3d8to9 wrapper) * d3d8 patching and extended features (superseded by d3d9 hook module + d3d8to9 wrapper)
* clock patching * clock patching
@@ -111,7 +111,7 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
* Ezusb IO2 I/O emulation * Ezusb IO2 I/O emulation
* Setupapi emulation * Setupapi emulation
* Full security emulation with SRAM and round plugs * Full security emulation with SRAM and round plugs
* Full game essential I/O emulation * Full game essential I/O emulation
* ACIO ICCA card reader emulation, slotted readers * ACIO ICCA card reader emulation, slotted readers
* d3d9 patching and extended features * d3d9 patching and extended features
* Font patching for Japanese chars * Font patching for Japanese chars
@@ -121,25 +121,43 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
#### iidxhook4 (18) #### iidxhook4 (18)
* Ezusb IO2 I/O emulation * Ezusb IO2 I/O emulation
* Setupapi emulation * Setupapi emulation
* Full game essential I/O emulation * Full game essential I/O emulation
* ACIO ICCA card reader emulation, slotted readers * ACIO ICCA card reader emulation, slotted readers
* d3d9 patching and extended features * d3d9 patching and extended features
* Font patching for Japanese chars * Font patching for Japanese chars
* Filesystem patches to detour E and F backup drives for settings * Filesystem patches to detour E and F backup drives for settings
#### iidxhook4-cn (18 CN)
* Ezusb IO2 I/O emulation
* Setupapi emulation
* Full security emulation with SRAM and round plugs
* Full game essential I/O emulation
* d3d9 patching and extended features
* Font patching for Japanese chars
* Filesystem patches to detour E and F backup drives for settings
#### iidxhook5 (19) #### iidxhook5 (19)
* Ezusb IO2 I/O emulation * Ezusb IO2 I/O emulation
* Setupapi emulation * Setupapi emulation
* Full game essential I/O emulation * Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers * ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features * d3d9 patching and extended features
* Font patching for Japanese chars * Font patching for Japanese chars
* Filesystem patches to detour E and F backup drives for settings * Filesystem patches to detour E and F backup drives for settings
#### iidxhook5-cn (20 CN)
* Ezusb IO2 I/O emulation
* Setupapi emulation
* Full security emulation with SRAM and round plugs
* Full game essential I/O emulation
* d3d9 patching and extended features
* Font patching for Japanese chars
* Filesystem patches to detour E and F backup drives for settings
#### iidxhook6 (20) #### iidxhook6 (20)
* Ezusb IO2 I/O emulation * Ezusb IO2 I/O emulation
* Setupapi emulation * Setupapi emulation
* Full game essential I/O emulation * Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers * ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features * d3d9 patching and extended features
* Font patching for Japanese chars * Font patching for Japanese chars
@@ -147,7 +165,7 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
#### iidxhook7 (21-24) #### iidxhook7 (21-24)
* Ezusb IO2 I/O emulation * Ezusb IO2 I/O emulation
* Setupapi emulation * Setupapi emulation
* Full game essential I/O emulation * Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers * ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features * d3d9 patching and extended features
* Font patching for Japanese chars * Font patching for Japanese chars
@@ -155,7 +173,7 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
#### iidxhook8 (25-26) #### iidxhook8 (25-26)
* ACIO BIO2 I/O emulation * ACIO BIO2 I/O emulation
* Setupapi emulation * Setupapi emulation
* Full game essential I/O emulation * Full game essential I/O emulation
* ACIO ICCA card reader emulation, wave pass readers * ACIO ICCA card reader emulation, wave pass readers
* d3d9 patching and extended features * d3d9 patching and extended features
* Font patching for Japanese chars * Font patching for Japanese chars
@@ -163,6 +181,9 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
### jbhook ### jbhook
TODO TODO
### popnhook
TODO
### sdvxhook ### sdvxhook
TODO TODO

781
doc/game-error-codes.md Normal file
View File

@@ -0,0 +1,781 @@
# Bemani Game Error Codes
This document collects the various error codes that are know across the many games including some
information what can be done.
This information is not part of bemanitools but useful to many users using it to run the games. We
saw users encountering these errors not knowing what they mean. Therefore, we include these errors
in the repository to provide an accessible source of information regarding them.
Important: The error codes are not consistent throughout the many years of game series and versions.
It is adviced to read the error information carefully (use Google Translate App with your phone's
camera) and check the following sections. It would be great to get feedback if you see information
missing or specific games and versions not matching to increase the value of the list.
## 5-0000 series errors
### 5-0000-0000
#### Description
A generic critical error.
#### Known occurances
N/A
#### How to fix
* Make sure your data is not set to read only, especially the dev folder.
* Disable all network adapters other than the one used to connect to the Internet.
* Check for hidden network adapters in Device Manager.
## 5-1500 series errors
### 5-1500-0000
#### Description
IO ERROR
#### Known occurances
* Pop'n Music 15
#### How to fix
No information available.
### 5-1500-0002
#### Description
SOUND DATA CREATE ERROR
#### Known occurances
N/A
#### How to fix
* Check the integrity of the data you have, i.e. some files might be corrupted
* Check your physical drive. Is it failing?
## 5-1501 series errors
### 5-1501-0000
#### Description
IO BOARD ERROR
#### Known occurances
N/A
#### How to fix
* Recopy Bemanitools.
* For Reflec Beat, make sure you are not missing device.dll. (This seems to apply to some older
version of bemanitools)
## 5-1502 series errors
### 5-1502-0000
#### Description
BACKUP CHECK ERROR
#### Known occurances
* Pop'n'Music 21 Sunny Park
#### How to fix
* Give access to gamestart.bat and launcher.exe from Windows Firewall if enabled.
* Make sure no antivirus software firewall is blocking access to those files.
* Start gamestart.bat as Administrator.
### 5-1502-0000
#### Description
HDD READ ERROR
#### Known occurances
N/A
#### How to fix
* Make sure `/dev/` isn't read-only.
### 5-1502-0002
#### Description
HDD READ ERROR
#### Known occurances
* GFDM V4
#### How to fix
Unknown
## 5-1503 series errors
### 5-1503-0000
#### Description
USB I/O ERROR
##### FPGA WRITE ERROR
Writing the FPGA firmware fails. Can have various causes depending on your setup.
##### FW TRNS-OUT
This typically happens if it takes too long to upload the base firmware to the USB IO. A potential
root-cause can be bad timing since the game uses a bad combination of software sleeps and fixed
timeouts making this code prone to fail.
#### Known occurances
* IIDX
#### How to fix
#### FPGA WRITE ERROR
* Restart the game
* Re-copy bemanitools
#### FW TRNS-OUT
* Restart the game
* Re-copy bemanitools
* Running the process on high priority and with admin rights
* If you attached a debugger, that might have messed with the timing and caused this. Try a
different debugger or attach it later in the boot process
### 5-1503-0001
#### Description
DATA ERROR
"Could not read the file normally. There is a likelihood the file is damaged."
This error occurs when a file is either missing or corrupt.
#### Known occurances
N/A
#### How to fix
* Check the integrity of the data you have, i.e. some files might be corrupted
* If the data came in an archive format, try extracting it again with another application.
* Make sure your game is up to date with the current data available.
* Check your physical drive. Is it failing?
### 5-1503-0004
#### Description
USBIO ERROR (NO ANSWER...)
This error occurs when the game does not receive a heartbeat from the IO board. On legitimate
hardware, this error is usually caused by the IO board resetting during play. The issue is rarely
fixed by simply restarting the game and will require a full power cycle.
#### Known occurances
N/A
#### How do I fix it?
Real hardware:
* Check the USB cable between the PC and the IO board is okay.
* Make sure the IO board is getting enough of a clean supply of power.
Bemanitools:
* Don't attempt to put your computer to sleep while playing rhythm games.
* Change launcher.exe process priority to High when starting the game.
### 5-1503-0006
#### Description
CARD DEVICE ERROR
#### Known occurances
N/A
#### How do I fix it?
* Recopy Bemanitools.
### 5-1503-0007
#### Description
USBIO ERROR (FM DL-ERR)
#### Known occurances
N/A
#### How do I fix it?
* Run the game using gamestart.bat, don't just drag and drop the game dll onto launcher.exe
### 5-1503-0008
#### Description
FPGA Write error
#### Known occurances
* IIDX Tricoro
Seen in Tricoro Omnimix RC1.
#### How do I fix it?
Unknown
### 5-1503-9000
### Description
PCB ERROR (PCB is unusual.)
#### Known occurances
N/A
#### How do I fix it?
* Make sure your AC(real)IO board is on the correct COM port.
## 5-1504 series errors
### 5-1504-0000
#### Description
IC CARD READER ERROR
Something is wrong with your e-amusement card readers (usually a timeout due to them not existing).
#### Known occurances
N/A
#### How do I fix it?
Real hardware:
* Make sure your readers are connected and powered on.
* Check your serial cables are good.
### 5-1504-0003
### Description
N/A
#### Known occurances
N/A
#### How do I fix it?
N/A
### 5-1504-0004
### Description
SDLOAD TIMEOUT or SOUND LOAD TIMEOUT
#### Known occurances
N/A
#### How do I fix it?
N/A
## 5-1505 series errors
### 5-1505-0000
#### Description
HDD Data Error(BPM Notes)
For Jubeat Ripples, getting this error the first time you boot is normal. After getting this error,
the game may take 1-3 minutes longer to boot as it regenerates backup data.
#### Known occurances
* Jubeat Ripples
#### How do I fix it?
* Check the integrity of the data you have, i.e. some files might be corrupted
* If the data came in an archive format, try extracting it again with another application.
* Check your physical drive. Is it failing?
### 5-1505-0001
#### Description
HDD Data Error(Music Data)
#### Known occurances
N/A
#### How do I fix it?
* Check the integrity of the data you have, i.e. some files might be corrupted
* If the data came in an archive format, try extracting it again with another application.
* Check your physical drive. Is it failing?
### 5-1505-0002
#### Description
Coin Error
This error occurs when the coin line (the input triggered when a coin is inserted) is held closed
for too long.
#### Known occurances
N/A
#### How do I fix it?
##### Real hardware
* There may be a coin stuck, check.
* The coin mechanism may be stuck, check.
* Don't hold down the coin line so long.
### 5-1505-0006
#### Description
HDD DATA ERROR(MOUNT IMAGEFS)
#### Known occurances
N/A
#### How do I fix it?
* Check the integrity of the data you have, i.e. some files might be corrupted
* If the data came in an archive format, try extracting it again with another application.
* Check your physical drive. Is it failing?
### 5-1505-0025
#### Description
N/A
#### Known occurances
* Jubeat Saucer Fullfill
#### How do I fix it?
* Disable excess network adapters
## 5-1506 series errors
### 5-1506-0000
#### Description
##### ACIO ERROR (ERR_INIT_LINE)
##### BACKUP DATA ERROR
The backup data is corrupted. Press the test button to re-initialize it.
#### Known occurances
* IIDX 15 (BACKUP DATA ERROR)
#### How do I fix it?
##### ACIO ERROR
If you're using ACrealIO, cut the reset trace on your Arduino.
##### BACKUP DATA ERROR
Follow the instructions of the error message. You will have to re-set certain settings like clock
settings in the operator menu to complete initialization.
### 5-1506-0001
#### Description
SHOP NAME ERROR
This error may happen before the monitor check on IIDX.
#### Known occurances
* IIDX (version?)
#### How do I fix it?
Press the service button and set the shop name in "NETWORK OPTIONS".
### 5-1506-1001
#### Description
CLOCK ERROR
#### Known occurances
N/A
#### How do I fix it?
* "Set" and save the clock date and time in the test menu
* Recopy Bemanitools
## 5-1507 series errors
### 5-1507-0000
#### Description
SECURITY ERROR
#### Known occurances
N/A
#### How do I fix it?
Make sure your ea3-config.xml file contains valid values on the following lines:
```xml
<dest __type="str">...</dest>
```
Should almost always be `J`. Certain games will support `K` (Korea) or `A` (Asia) but there is
rarely a reason to use it. DDR 2014 and forward will support `U`. DanEvo will support (I believe)
`C`.
```xml
<spec __type="str">...</spec>
```
Should almost always be `A`. DDR will support `B` for non-HD monitors.
```xml
<rev __type="str">...</rev>
```
Should always be `A`.
## 5-1508 series errors
### 5-1508-0000
#### Description
LAMP CHECK ERROR
#### Known occurances
* Pop'n Music 20 Fantasia
#### How do I fix it?
N/A
## 5-1509 series errors
### 5-1509-0000
#### Description
REBOOT THE MACHINE
The original message in Japanese: 電源を再投入して下さい
#### Known occurances
* Pop'n Music 22 Lapistoria
#### How do I fix it?
Restart entire machine if on cabinet, or close the game (ALT+F4/ALT+TAB and then close through
taskbar) and re-run the launcher/gamestart file
## 5-2000 series errors (Network errors)
### 5-2000-0000
#### Description
Router error.
Something's not okay with the connection between the game and your router. This can either be a
(W)LAN error, or something within your computer settings (firewall, network adapter, etc.)
#### Known occurances
N/A
#### How do I fix it?
* Restart your game.
* Check if your computer is connected to the Internet at all.
* Make sure the services URL is correct.
* Disable all network adapters other than the one used to connect to the Internet. Alternatively,
setting that adapter to have the highest affinity also works.
* If none of the above work, reinstall a newer or older version of your network drivers.
### 5-2002-0000
#### Description
speculation: general malformed ea3-config.xml file or server communication error
#### Known occurances
N/A
#### How do I fix it?
* Make sure you're editing the right file for network configuration settings.
### 5-2002-0916
#### Description
Cannot communicate with the server.
#### Known occurances
N/A
#### How do I fix it?
N/A
### 5-2002-1013
#### Description
NETWORK ERROR
Cannot communicate with server.
Ensure that your internet connection is working and that your router is turned on.
Ensure that your machine is connected to your router.
Press the service button to start the game.
#### Known occurances
* IIDX, probably all known versions
#### How do I fix it?
The original message is already telling you what is going on:
* Check if your machine/pc has an internet connection
* Check your firewall settings
* Check that the server address is configured and correct in `iidxhook.conf` (old games) or
`ea3-config.xml`
* You can disable the network in the operator menu to just boot the game first. Note that this is
not possible on any versions starting IIDX 20 (tricoro).
### 5-2002-2301
#### Description
Cannot communicate with the server.
#### Known occurances
N/A
#### How do I fix it?
Your ea3 services URL is probably incorrect.
### 5-2000-2402
#### Description
No PCBID. You have no PCBID.
#### Known occurances
N/A
#### How do I fix it?
Add a valid PCBID to `ea3-config.xml`.
### 5-2002-0910
#### Description
Server Error. The game cannot communicate with the server.
#### Known occurances
N/A
#### How do I fix it?
Make sure the services URL is correct.
### 5-2002-2403
#### Description
Unauthorized. The server is rejecting your PCBID.
#### Known occurances
N/A
#### How do I fix it?
* Check that there is a valid PCBID in ea3-config.xml.
### 5-2002-2400
#### Description
Bad Request. Syntax was entered improperly and the server does not understand it.
#### Known occurances
N/A
#### How do I fix it?
Check your services URL and make sure it is entered correctly (e.g. "http:" instead of "https:")
### 5-2002-2404
#### Description
Not found. The server can't find the URL that the game has requested, this is usually because the
game is attempting to connect to an incorrect endpoint.
#### Known occurances
N/A
#### How do I fix it?
* Check your services URL in `ea3-config.xml`. Make sure to remove any slash at the end of the URL
and check for https/http.
* If you are running Spada, ensure to use a service URL that supports that older game (check with
your private server provider)
* If you are running Tune Street, ensure to use a service URL that supports that older game (check
with your private server provider)
### 5-2003-2404
#### Description
Malformed `<network>` section. The `<network>` section in your `ea3-config.xml` file is malformed
in some way.
#### Known occurances
N/A
#### How do I fix it?
Ensure your `<network>` section follows the following format:
```xml
<network>
<timeout __type="u32">10000</timeout>
<sz_xrpc_buf __type="u32">102400</sz_xrpc_buf>
<ssl __type="bool">0</ssl>
<services></services>
<url_slash __type="bool">1</url_slash>
</network>
```
Note: Delete the line `<url_slash __type="bool">1</url_slash>` if you're connecting to Arcana
### 5-2002-2500
#### Description
??? (Logs say http status 500)
#### Known occurances
N/A
#### How do I fix it?
If you are playing Lincle, use the `/core/services` URL from Tricoro, not xrpc.
### 5-2003-2502
#### Description
Server Error. The game cannot communicate with the server.
#### Known occurances
N/A
#### How do I fix it?
Check if your `hosts` file has any DNS redirects to other private servers that might interfere
with this
### 5-2016-0000
#### Description
"apsmanager" is a special eAM Participation system for Korean machines(XXX:K). This system
is maybe not supported by private servers.
#### Known occurances
N/A
#### How do I fix it?
Make sure your `ea3-config.xml` has this line set to 0:
```xml
<apsmanager __type="u8">0</apsmanager>
```

View File

@@ -17,7 +17,9 @@ games:
* [iidxhook2](iidxhook2.md): DistorteD * [iidxhook2](iidxhook2.md): DistorteD
* [iidxhook3](iidxhook3.md): GOLD, DJ TROOPERS, EMPRESS, SIRIUS * [iidxhook3](iidxhook3.md): GOLD, DJ TROOPERS, EMPRESS, SIRIUS
* [iidxhook4](iidxhook4.md): Resort Anthem * [iidxhook4](iidxhook4.md): Resort Anthem
* [iidxhook4-cn](iidxhook4-cn.md): Resort Anthem CN (狂热节拍 IIDX)
* [iidxhook5](iidxhook5.md): Lincle * [iidxhook5](iidxhook5.md): Lincle
* [iidxhook5-cn](iidxhook5-cn.md): tricoro CN (狂热节拍 IIDX 2)
* [iidxhook6](iidxhook6.md): Tricoro * [iidxhook6](iidxhook6.md): Tricoro
* [iidxhook7](iidxhook7.md): SPADA, PENDUAL, copula, SINOBUZ * [iidxhook7](iidxhook7.md): SPADA, PENDUAL, copula, SINOBUZ
* [iidxhook8](iidxhook8.md): CANNON BALLERS, Rootage * [iidxhook8](iidxhook8.md): CANNON BALLERS, Rootage

View File

@@ -198,6 +198,13 @@ can't be refreshed very often to make it feel unresponsive. Solution:
hit your 10key/numpad slower than normal hit your 10key/numpad slower than normal
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears (RED, HAPPY SKY) ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears (RED, HAPPY SKY)
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax
@@ -234,4 +241,4 @@ If one or multiple of these issues apply, use the built in scaling options by se
*gfx.scale_back_buffer_width* and *gfx.scale_back_buffer_height* to a target resolution *gfx.scale_back_buffer_width* and *gfx.scale_back_buffer_height* to a target resolution
to scale to. Usually, you want to set this to the monitor's native resolution, e.g. to scale to. Usually, you want to set this to the monitor's native resolution, e.g.
1920x1080 for full HD. You can play around with a few different filters using 1920x1080 for full HD. You can play around with a few different filters using
*gfx.scale_back_buffer_filter* which impacts image quality/blurriness on upscaling. *gfx.scale_back_buffer_filter* which impacts image quality/blurriness on upscaling.

View File

@@ -154,6 +154,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

View File

@@ -165,6 +165,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

View File

@@ -0,0 +1,13 @@
# Game list
The following games are compatible with this version of iidxhook:
* Resort Anthem CN (狂热节拍 IIDX)
The games must be bootstrapped using [inject.exe](../inject.md).
# Remarks
Resort Anthem CN (狂热节拍 IIDX):
* Does not have NETWORK function
* Game doesn't used card readers

View File

@@ -175,6 +175,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

View File

@@ -0,0 +1,15 @@
# Game list
The following games are compatible with this version of iidxhook:
* tricoro CN (狂热节拍 IIDX 2)
The games must be bootstrapped using [inject.exe](../inject.md).
# Remarks
tricoro CN (狂热节拍 IIDX 2):
* Game uses Lincle engine
* Identifier being JDZ
* Does not have NETWORK function
* Game doesn't used card readers

View File

@@ -171,6 +171,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

View File

@@ -177,6 +177,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

View File

@@ -182,6 +182,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

View File

@@ -185,6 +185,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

View File

@@ -221,6 +221,13 @@ iidxhook can limit the frame rate for you (refer to help/config file)
Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only" Use dxwnd and set settings like "Acquire admin caps" and "Fullscreen only"
## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears ## Background videos aren't working. When starting a song, windows is playing the error sound and a message box appears
If you are running in window mode, you can see an error pop-up window with the title
`DirectShow Texture3D Sample` and error message
`Could not create source filter to graph! hr=<some number>`.
When running fullscreen, you only hear a windows error sound and the game appears to be frozen
when trying to play a background video.
You are missing a codec to decode and play the videos. There are different You are missing a codec to decode and play the videos. There are different
methods available to get background videos working. Probably, the easiest methods available to get background videos working. Probably, the easiest
solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax solution: grab the CLVSD.ax file and go to Start -> Run -> regsvr32 clvsd.ax

48
doc/popnhook/README.md Normal file
View File

@@ -0,0 +1,48 @@
# popnhook
popnhook is a collection of hook libraries for jubeat providing
emulation and various patches to run these games on non BemaniPC hardware and
newer Windows versions.
The hook libraries must be bootstrapped either using [inject](../inject.md) or
[launcher](../launcher.md) depending on the version you want to run. Further
instructions are given in dedicated readme files for each popnhook version
(see below).
# Versions
popnhook comes in a few different flavors. The game and its engine changed over
the years. Some game versions might require patches/parameters enabled which
others don't need or have different AVS versions. Here is the list of supported
games:
* [popnhook1](popnhook1.md): 15 ADVENTURE, 16 PARTY♪, 17 THE MOVIE, 18 せんごく列伝
When building bemanitools, independent packages are created for each set of games
which are ready to be dropped on top of vanilla AC data dumps. We recommend
using pristine dumps to avoid any conflicts with other hardcoded hacks or
binary patches.
# How to run
To run your game with popnhook, you have to use the inject tool to inject the
DLL to the game process. `dist/popn` contains bat scripts with all the
important parameters configured. Further parameters can be added but might not
be required to run the game with default settings.
Further information on how to setup the data for each specific version are
elaborated in their dedicated readme files.
# Eamuse network setup
Running pop'n music 15 through 18? Modify the appropriate popnhook-15.conf, popnhook-16.conf,
popnhook-17.conf, or popnhook-18.conf.
Running anything newer?
* Open the `prop/ea3-config.xml`
* Replace the `ea3/network/services` URL with network service URL of your
choice (for example http://my.eamuse.com)
* Edit the `ea3/id/pcbid`
# Command line options
Add the argument *-h* when running inject with popnhook to print help/usage
information with a list of parameters you can apply to tweak various things.

45
doc/popnhook/popnhook1.md Normal file
View File

@@ -0,0 +1,45 @@
# Game list
The following games are compatible with this version of popnhook:
* pop'n music 15 ADVENTURE
* pop'n music 16 PARTY♪
* pop'n music 17 THE MOVIE
* pop'n music 18 せんごく列伝
The games must be bootstrapped using [inject](../inject.md).
# Data setup and running the game
Unpack the package containing popnhook1 into the revision folder of your choice.
Most likely, you want to target the latest revision you have to run the latest
binary of the game with any bugfixes by developers.
The DLLs in this package should be in the same location as the game DLLs and
executable - i.e. all these files should be in the same folder:
- `inject.exe`
- `popn15.exe` or `popn16.exe` or `popn17.exe` or `popn18.exe`
- `popnhook-15.conf` or `popnhook-16.conf` or `popnhook-17.conf` or `popnhook-18.conf`
- `eamio.dll`
- `popnio.dll`
- `libavs-win32.dll`
- etc
Run the `gamestart-15.bat` or `gamestart-16.bat` or `gamestart-17.bat` or `gamestart-18.bat` file as admin.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID in the
configuration file. You also have to set the url of the eamuse server you want
to connect to.
# Eamuse network setup
If you want to run the games online, you have to set a valid PCBID and EAMID
(use the PCBID as the EAMID) in the configuration file or as a command line
argument. You also have to set the url of the eamuse server you want to
connect to.
Additional note regarding EAMID: This is provided as the identifier of the
"eamuse license" to the server. Depending on the implementation of the server,
this can lead to authentication failure resulting in a network error on boot or
warning during gameplay.

View File

@@ -18,6 +18,7 @@ EXPORTS
property_destroy @247 NONAME property_destroy @247 NONAME
property_insert_read @255 NONAME property_insert_read @255 NONAME
property_node_create @266 NONAME property_node_create @266 NONAME
property_node_datasize @267 NONAME
property_node_refer @278 NONAME property_node_refer @278 NONAME
property_node_remove @279 NONAME property_node_remove @279 NONAME
property_psmap_import @288 NONAME property_psmap_import @288 NONAME

View File

@@ -17,6 +17,7 @@ EXPORTS
property_destroy @264 NONAME property_destroy @264 NONAME
property_insert_read @23 NONAME property_insert_read @23 NONAME
property_node_create @316 NONAME property_node_create @316 NONAME
property_node_datasize @249 NONAME
property_node_refer @268 NONAME property_node_refer @268 NONAME
property_node_remove @129 NONAME property_node_remove @129 NONAME
property_psmap_import @102 NONAME property_psmap_import @102 NONAME

View File

@@ -0,0 +1,108 @@
#ifndef BEMANITOOLS_POPNIO_H
#define BEMANITOOLS_POPNIO_H
/* IO emulation provider for pop'n music. */
#include <stdbool.h>
#include <stdint.h>
#include "bemanitools/glue.h"
/* Bit mapping for the "buttons" word */
enum popn_io_sys_bit {
POPN_IO_SYS_SERVICE = 0x06,
POPN_IO_SYS_TEST = 0x07,
};
enum popn_io_button_bit {
POPN_IO_BUTTON_1 = 0x08,
POPN_IO_BUTTON_2 = 0x09,
POPN_IO_BUTTON_3 = 0x0a,
POPN_IO_BUTTON_4 = 0x0b,
POPN_IO_BUTTON_5 = 0x0c,
POPN_IO_BUTTON_6 = 0x0d,
POPN_IO_BUTTON_7 = 0x0e,
POPN_IO_BUTTON_8 = 0x0f,
POPN_IO_BUTTON_9 = 0x10,
};
enum popn_io_light_top_lamp_bit {
POPN_LIGHT_HI_LAMP1 = 0x00,
POPN_LIGHT_HI_LAMP2 = 0x01,
POPN_LIGHT_HI_LAMP3 = 0x02,
POPN_LIGHT_HI_LAMP4 = 0x03,
POPN_LIGHT_HI_LAMP5 = 0x04,
};
enum popn_io_light_side_lamp_bit {
POPN_LIGHT_LEFT_LAMP1 = 0x00,
POPN_LIGHT_LEFT_LAMP2 = 0x01,
POPN_LIGHT_RIGHT_LAMP1 = 0x02,
POPN_LIGHT_RIGHT_LAMP2 = 0x03,
};
enum popn_io_light_switch_lamp_bit {
POPN_LIGHT_SW_LAMP1 = 0x00, // Is actually 4 bits wide
POPN_LIGHT_SW_LAMP2 = 0x04,
POPN_LIGHT_SW_LAMP3 = 0x05,
POPN_LIGHT_SW_LAMP4 = 0x06,
POPN_LIGHT_SW_LAMP5 = 0x07,
POPN_LIGHT_SW_LAMP6 = 0x08,
POPN_LIGHT_SW_LAMP7 = 0x09,
POPN_LIGHT_SW_LAMP8 = 0x0a,
POPN_LIGHT_SW_LAMP9 = 0x0b,
};
/* The first function that will be called on your DLL. You will be supplied
with four function pointers that may be used to log messages to the game's
log file. See comments in glue.h for further information. */
void popn_io_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal);
/* Initialize your pop'n music IO emulation DLL. Thread management functions are
provided to you; you must use these functions to create your own threads if
you want to make use of the logging functions that are provided to
eam_io_set_loggers(). You will also need to pass these thread management
functions on to geninput if you intend to make use of that library.
See glue.h and geninput.h for further details. */
bool popn_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy);
/* Shut down your pop'n music IO emulation DLL */
void popn_io_fini(void);
/* Get the state of the buttons. See enums above. */
uint32_t popn_io_get_buttons(void);
/* Set the top light state. See enum popn_io_light_top_lamp_bit above. */
void popn_io_set_top_lights(uint32_t lights);
/* Set the side light state. See enum popn_io_light_side_lamp_bit above. */
void popn_io_set_side_lights(uint32_t lights);
/* Set the button light state. See enum popn_io_light_switch_lamp_bit above. */
void popn_io_set_button_lights(uint32_t lights);
/* Set the coin blocker light state. */
void popn_io_set_coin_blocker_light(bool enabled);
/* Set the coin counter light state. */
void popn_io_set_coin_counter_light(bool enabled);
#endif

View File

@@ -193,7 +193,7 @@ static HRESULT usbmem_write(struct irp *irp)
usbmem_response[2] = ~usbmem_response[1]; usbmem_response[2] = ~usbmem_response[1];
if (usbmem_state[target_device_id].buffer_frame == 0) { if (usbmem_state[target_device_id].buffer_frame == 0) {
snprintf(usbmem_response + 4, sizeof(usbmem_response) - 5, "%d ", usbmem_state[target_device_id].buffer_len); snprintf(usbmem_response + 4, sizeof(usbmem_response) - 5, "%Iu ", usbmem_state[target_device_id].buffer_len);
} else { } else {
size_t len = sizeof(usbmem_response) - 5; size_t len = sizeof(usbmem_response) - 5;

View File

@@ -54,9 +54,9 @@ uint8_t ezusb_iidx_emu_node_security_mem_v1_process_cmd(
uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2) uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2)
{ {
switch (cmd_id) { switch (cmd_id) {
case EZUSB_IIDX_SECMEM_CMD_WRITE: case EZUSB_IIDX_SECMEM_CMD_INIT:
log_misc("EZUSB_SECURITY_MEM_V1_CMD_WRITE"); log_misc("EZUSB_SECURITY_MEM_V1_CMD_INIT");
return EZUSB_IIDX_SECMEM_CMD_STATUS_V1_WRITE_OK; return EZUSB_IIDX_SECMEM_CMD_STATUS_V1_INIT_OK;
default: default:
log_warning( log_warning(
@@ -69,9 +69,9 @@ uint8_t ezusb_iidx_emu_node_security_mem_v2_process_cmd(
uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2) uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2)
{ {
switch (cmd_id) { switch (cmd_id) {
case EZUSB_IIDX_SECMEM_CMD_WRITE: case EZUSB_IIDX_SECMEM_CMD_INIT:
log_misc("EZUSB_SECURITY_MEM_V2_CMD_WRITE"); log_misc("EZUSB_SECURITY_MEM_V2_CMD_INIT");
return EZUSB_IIDX_SECMEM_CMD_STATUS_V2_WRITE_OK; return EZUSB_IIDX_SECMEM_CMD_STATUS_V2_INIT_OK;
default: default:
log_warning( log_warning(

View File

@@ -174,8 +174,8 @@ uint8_t ezusb_iidx_emu_node_security_plug_process_cmd_v1(
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA; EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK;
case EZUSB_IIDX_SECPLUG_CMD_V1_SECURITY_CONVERSION: case EZUSB_IIDX_SECPLUG_CMD_V1_WRITE_DATA:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V1_SECURITY_CONVERSION"); log_misc("EZUSB_IIDX_SECPLUG_CMD_V1_WRITE_DATA");
/* TODO ? */ /* TODO ? */
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK;
@@ -201,40 +201,57 @@ uint8_t ezusb_iidx_emu_node_security_plug_process_cmd_v2(
uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2) uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2)
{ {
switch (cmd_id) { switch (cmd_id) {
case EZUSB_IIDX_SECPLUG_CMD_V2_INIT: case EZUSB_IIDX_SECPLUG_CMD_V2_SEARCH:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_INIT"); log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SEARCH");
ezusb_iidx_emu_node_security_plug_active_dongle_mem = ezusb_iidx_emu_node_security_plug_active_dongle_mem =
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM; EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM;
ezusb_iidx_emu_node_security_plug_enc_rom_data_seed = cmd_data; ezusb_iidx_emu_node_security_plug_enc_rom_data_seed = cmd_data;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SEARCH_OK;
case EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA: case EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA"); log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA");
ezusb_iidx_emu_node_security_plug_active_dongle_mem = ezusb_iidx_emu_node_security_plug_active_dongle_mem =
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA; EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_DATA_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_READ_DATA_OK;
case EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM: case EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM"); log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM");
ezusb_iidx_emu_node_security_plug_active_dongle_mem = ezusb_iidx_emu_node_security_plug_active_dongle_mem =
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM; EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM;
ezusb_iidx_emu_node_security_plug_enc_rom_data_seed = cmd_data; ezusb_iidx_emu_node_security_plug_enc_rom_data_seed = cmd_data;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_ROM_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_READ_ROM_OK;
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE_2: // pop'n music only ever uses slot 2 (white) and slot 4 (black).
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE_2"); // If the configuration does not match then it will error out.
// IIDX uses slots 2 and 3 and detects what is plugged into each slot so ordering isn't important.
// IIDX also reads slot 1's data section but doesn't care what dongle it is?
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_1:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_1");
ezusb_iidx_emu_node_security_plug_active_dongle_slot = ezusb_iidx_emu_node_security_plug_active_dongle_slot =
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE; EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_BLACK_DONGLE: case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_2:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_BLACK_DONGLE"); log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_2");
ezusb_iidx_emu_node_security_plug_active_dongle_slot =
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_3:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_3");
ezusb_iidx_emu_node_security_plug_active_dongle_slot = ezusb_iidx_emu_node_security_plug_active_dongle_slot =
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK; EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE: case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_4:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE"); log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_4");
ezusb_iidx_emu_node_security_plug_active_dongle_slot =
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_5:
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_5");
// Unknown, not encountered during testing
ezusb_iidx_emu_node_security_plug_active_dongle_slot = ezusb_iidx_emu_node_security_plug_active_dongle_slot =
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE; EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE;
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK; return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;

View File

@@ -2,16 +2,16 @@
#define EZUSB_IIDX_SECMEM_CMD_H #define EZUSB_IIDX_SECMEM_CMD_H
enum ezusb_iidx_secmem_command { enum ezusb_iidx_secmem_command {
EZUSB_IIDX_SECMEM_CMD_WRITE = 0x00, EZUSB_IIDX_SECMEM_CMD_INIT = 0x00,
}; };
enum ezusb_iidx_secmem_command_status_v1 { enum ezusb_iidx_secmem_command_status_v1 {
EZUSB_IIDX_SECMEM_CMD_STATUS_V1_WRITE_OK = 0x60, EZUSB_IIDX_SECMEM_CMD_STATUS_V1_INIT_OK = 0x60,
EZUSB_IIDX_SECMEM_CMD_STATUS_V1_FAULT = 0xFE, EZUSB_IIDX_SECMEM_CMD_STATUS_V1_FAULT = 0xFE,
}; };
enum ezusb_iidx_secmem_command_status_v2 { enum ezusb_iidx_secmem_command_status_v2 {
EZUSB_IIDX_SECMEM_CMD_STATUS_V2_WRITE_OK = 0x11, EZUSB_IIDX_SECMEM_CMD_STATUS_V2_INIT_OK = 0x11,
EZUSB_IIDX_SECMEM_CMD_STATUS_V2_FAULT = 0xFE, EZUSB_IIDX_SECMEM_CMD_STATUS_V2_FAULT = 0xFE,
}; };

View File

@@ -14,7 +14,7 @@ enum ezusb_iidx_secplug_dongle_memory {
enum ezusb_iidx_secplug_command_v1 { enum ezusb_iidx_secplug_command_v1 {
EZUSB_IIDX_SECPLUG_CMD_V1_READ_ROM = 0x01, EZUSB_IIDX_SECPLUG_CMD_V1_READ_ROM = 0x01,
EZUSB_IIDX_SECPLUG_CMD_V1_READ_DATA = 0x02, EZUSB_IIDX_SECPLUG_CMD_V1_READ_DATA = 0x02,
EZUSB_IIDX_SECPLUG_CMD_V1_SECURITY_CONVERSION = 0x03, EZUSB_IIDX_SECPLUG_CMD_V1_WRITE_DATA = 0x03,
EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_BLACK_DONGLE = 0x04, EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_BLACK_DONGLE = 0x04,
EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_WHITE_DONGLE = 0x05 EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_WHITE_DONGLE = 0x05
}; };
@@ -25,18 +25,22 @@ enum ezusb_iidx_secplug_command_status_v1 {
}; };
enum ezusb_iidx_secplug_command_v2 { enum ezusb_iidx_secplug_command_v2 {
EZUSB_IIDX_SECPLUG_CMD_V2_INIT = 0x01, EZUSB_IIDX_SECPLUG_CMD_V2_SEARCH = 0x01,
EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA = 0x02, EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA = 0x02,
EZUSB_IIDX_SECPLUG_CMD_V2_WRITE_DATA = 0x03,
EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM = 0x06, EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM = 0x06,
EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE_2 = 0x07, EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_1 = 0x07,
EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_BLACK_DONGLE = 0x08, EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_2 = 0x08,
EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE = 0x09 EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_3 = 0x09,
EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_4 = 0x0a,
EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_DONGLE_5 = 0x0b,
}; };
enum ezusb_iidx_secplug_command_status_v2 { enum ezusb_iidx_secplug_command_status_v2 {
EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_OK = 0x12, EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SEARCH_OK = 0x12,
EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_DATA_OK = 0x13, EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_READ_DATA_OK = 0x13,
EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_ROM_OK = 0x15, EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_WRITE_DATA_OK = 0x14,
EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_READ_ROM_OK = 0x15,
EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK = 0x16, EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK = 0x16,
EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_FAIL = 0xFE EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_FAIL = 0xFE
}; };

View File

@@ -2,8 +2,8 @@
#define EZUSB_IIDX_SRAM_CMD_H #define EZUSB_IIDX_SRAM_CMD_H
enum ezusb_iidx_sram_command { enum ezusb_iidx_sram_command {
EZUSB_IIDX_SRAM_CMD_WRITE = 0x03,
EZUSB_IIDX_SRAM_CMD_READ = 0x02, EZUSB_IIDX_SRAM_CMD_READ = 0x02,
EZUSB_IIDX_SRAM_CMD_WRITE = 0x03,
EZUSB_IIDX_SRAM_CMD_DONE = 0x04 EZUSB_IIDX_SRAM_CMD_DONE = 0x04
}; };

View File

@@ -0,0 +1,10 @@
libs += ezusb2-popn-emu
libs_ezusb2-popn-emu := \
ezusb-emu \
ezusb-iidx-emu \
ezusb-iidx \
ezusb2-iidx-emu \
src_ezusb2-popn-emu := \
msg.c \

View File

@@ -0,0 +1,194 @@
#define LOG_MODULE "ezusb2-popn-emu-msg"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "bemanitools/popnio.h"
#include "hook/iohook.h"
#include "ezusb-emu/msg.h"
#include "ezusb-iidx-emu/msg.h"
#include "ezusb-iidx-emu/nodes.h"
#include "ezusb-iidx-emu/node-none.h"
#include "ezusb-iidx-emu/node-coin.h"
#include "ezusb-iidx-emu/node-security-mem.h"
#include "ezusb-iidx-emu/node-security-plug.h"
#include "ezusb2-popn/msg.h"
#include "util/hex.h"
#include "util/log.h"
/* ------------------------------------------------------------------------ */
static HRESULT ezusb2_popn_emu_msg_interrupt_read(struct iobuf *read);
static HRESULT ezusb2_popn_emu_msg_interrupt_write(struct const_iobuf *write);
static HRESULT ezusb2_popn_emu_msg_bulk_read(struct iobuf *read);
static HRESULT ezusb2_popn_emu_msg_bulk_write(struct const_iobuf *write);
/* ------------------------------------------------------------------------ */
static struct ezusb_emu_msg_hook ezusb2_popn_emu_msg_hook = {
.interrupt_read = ezusb2_popn_emu_msg_interrupt_read,
.interrupt_write = ezusb2_popn_emu_msg_interrupt_write,
.bulk_read = ezusb2_popn_emu_msg_bulk_read,
.bulk_write = ezusb2_popn_emu_msg_bulk_write};
/* ------------------------------------------------------------------------ */
static const struct ezusb_iidx_emu_node *ezusb2_popn_emu_msg_nodes[256] = {
[EZUSB_IIDX_MSG_NODE_COIN] = &ezusb_iidx_emu_node_coin,
[EZUSB_IIDX_MSG_NODE_NONE] = &ezusb_iidx_emu_node_none,
[EZUSB_IIDX_MSG_NODE_EEPROM] = &ezusb_iidx_emu_node_eeprom_v2,
[EZUSB_IIDX_MSG_NODE_SECURITY_MEM] = &ezusb_iidx_emu_node_security_mem_v2,
[EZUSB_IIDX_MSG_NODE_SECURITY_PLUG] = &ezusb_iidx_emu_node_security_plug_v2,
[EZUSB_IIDX_MSG_NODE_SRAM] = &ezusb_iidx_emu_node_sram,
[EZUSB_IIDX_MSG_NODE_WDT] = &ezusb_iidx_emu_node_wdt,
};
static uint8_t ezusb2_popn_emu_msg_status = 0;
static uint8_t ezusb2_popn_emu_msg_seq_no = 0;
static uint8_t ezusb2_popn_emu_msg_read_cur_node = 0;
static uint16_t ezusb2_popn_emu_msg_history[10];
/* ------------------------------------------------------------------------ */
struct ezusb_emu_msg_hook *ezusb2_popn_emu_msg_init(void)
{
/* Init all nodes */
for (uint32_t i = 0; i < 256; i++) {
/* "Constructor" optional */
if (ezusb2_popn_emu_msg_nodes[i] &&
ezusb2_popn_emu_msg_nodes[i]->init_node) {
ezusb2_popn_emu_msg_nodes[i]->init_node();
}
}
memset(&ezusb2_popn_emu_msg_history[0], 0xff, sizeof(ezusb2_popn_emu_msg_history));
return &ezusb2_popn_emu_msg_hook;
}
static HRESULT ezusb2_popn_emu_msg_interrupt_read(struct iobuf *read)
{
struct ezusb2_popn_msg_interrupt_read_packet *msg_resp =
(struct ezusb2_popn_msg_interrupt_read_packet *) read->bytes;
memset(msg_resp, 0, sizeof(*msg_resp));
msg_resp->unk0 = 0x03;
msg_resp->unk1 = 0x1d;
msg_resp->unk2 = 0x85;
msg_resp->seq_no = ezusb2_popn_emu_msg_seq_no++;
msg_resp->status = ezusb2_popn_emu_msg_status;
msg_resp->unk3 = 0x00;
msg_resp->coin_count = 0;
msg_resp->unk4 = 0xfd;
msg_resp->io.inverted_pad = ~popn_io_get_buttons();
msg_resp->unk5 = 0x00;
msg_resp->unk6 = 0x7d;
msg_resp->unk7 = 0xdf;
msg_resp->unk8 = ezusb2_popn_emu_msg_seq_no;
memcpy(&msg_resp->button_history[0], &ezusb2_popn_emu_msg_history[0], sizeof(uint16_t) * 10);
read->pos = sizeof(*msg_resp);
memmove(&ezusb2_popn_emu_msg_history[1], &ezusb2_popn_emu_msg_history[0], sizeof(uint16_t) * 9);
ezusb2_popn_emu_msg_history[0] = msg_resp->io.button;
return S_OK;
}
static HRESULT ezusb2_popn_emu_msg_interrupt_write(struct const_iobuf *write)
{
const struct ezusb2_popn_msg_interrupt_write_packet *msg_req =
(const struct ezusb2_popn_msg_interrupt_write_packet *) write->bytes;
if (write->nbytes < sizeof(*msg_req)) {
log_warning("Interrupt write message too small");
return E_INVALIDARG;
}
if (!ezusb2_popn_emu_msg_nodes[msg_req->node]) {
ezusb2_popn_emu_msg_read_cur_node = 0;
log_warning(
"Unrecognised node in interrupt message: %02x", msg_req->node);
return E_INVALIDARG;
}
popn_io_set_top_lights(msg_req->lamp & 0x1f);
popn_io_set_side_lights((msg_req->lamp >> 8) & 0xf);
popn_io_set_button_lights((msg_req->lamp >> 20) & 0xfff);
popn_io_set_coin_counter_light(((msg_req->lamp >> 12) & 0xf) == 0); // Active low
popn_io_set_coin_blocker_light(((msg_req->lamp >> 16) & 0xf) == 0xf);
/* Remember node for next bulk read */
ezusb2_popn_emu_msg_read_cur_node = msg_req->node;
ezusb2_popn_emu_msg_status =
ezusb2_popn_emu_msg_nodes[msg_req->node]->process_cmd(
msg_req->cmd, msg_req->cmd_detail[0], msg_req->cmd_detail[1]);
return S_OK;
}
static HRESULT ezusb2_popn_emu_msg_bulk_read(struct iobuf *read)
{
struct ezusb_iidx_msg_bulk_packet *pkt =
(struct ezusb_iidx_msg_bulk_packet *) read->bytes;
if (read->nbytes < sizeof(*pkt)) {
log_warning("Bulk read buffer too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
if (!ezusb2_popn_emu_msg_nodes[ezusb2_popn_emu_msg_read_cur_node]) {
log_warning(
"Bulk read unsupported on cur_node = %d",
ezusb2_popn_emu_msg_read_cur_node);
return E_NOTIMPL;
}
if (!ezusb2_popn_emu_msg_nodes[ezusb2_popn_emu_msg_read_cur_node]
->read_packet(pkt)) {
return E_FAIL;
}
read->pos = sizeof(*pkt);
return S_OK;
}
static HRESULT ezusb2_popn_emu_msg_bulk_write(struct const_iobuf *write)
{
const struct ezusb_iidx_msg_bulk_packet *pkt =
(const struct ezusb_iidx_msg_bulk_packet *) write->bytes;
if (write->nbytes < sizeof(*pkt)) {
log_warning("Bulk write packet too small");
return E_INVALIDARG;
}
if (!ezusb2_popn_emu_msg_nodes[pkt->node]) {
log_warning("Bulk write not supported on pkt->node = %02x", pkt->node);
return E_NOTIMPL;
}
if (!ezusb2_popn_emu_msg_nodes[pkt->node]->write_packet(pkt)) {
return E_FAIL;
}
return S_OK;
}

View File

@@ -0,0 +1,19 @@
#ifndef EZUSB2_POPN_EMU_MSG_H
#define EZUSB2_POPN_EMU_MSG_H
#include <stddef.h>
#include <stdint.h>
#include "hook/iohook.h"
#include "ezusb-emu/msg.h"
/**
* Init the fully emulated pop'n msg backend for a EZUSB FX2 (IO2) board
*
* @return ezusb_emu_msg_hook structure with hook calls for ezusb msg
* dispatching
*/
struct ezusb_emu_msg_hook *ezusb2_popn_emu_msg_init(void);
#endif

View File

@@ -0,0 +1,14 @@
dlls += ezusb2-popn-shim
ldflags_ezusb2-popn-shim := \
-lsetupapi \
libs_ezusb2-popn-shim := \
ezusb2-emu \
hook \
hooklib \
util \
src_ezusb2-popn-shim := \
dllmain.c \
proxy.c \

View File

@@ -0,0 +1,40 @@
#include <windows.h>
#include <stdint.h>
#include <stdbool.h>
#include <setupapi.h>
#include "ezusb2-emu/desc.h"
#include "ezusb2-emu/device.h"
#include "hook/pe.h"
#include "hooklib/setupapi.h"
#include "ezusb2-popn-shim/proxy.h"
#include "util/log.h"
#define EZUSB_REAL_DLL_FILENAME "ezusb.dll"
static DWORD(STDCALL *real_entrypoint)(HMODULE self, DWORD reason, void *ctx);
static HMODULE real_pe = NULL;
BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx)
{
if (reason == DLL_PROCESS_ATTACH && real_pe == NULL)
{
pe_hijack_entrypoint(EZUSB_REAL_DLL_FILENAME, &real_entrypoint);
real_pe = GetModuleHandleA(EZUSB_REAL_DLL_FILENAME);
ezusb2_proxy_initialize(real_pe);
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
}
if (real_pe != NULL)
return real_entrypoint(real_pe, reason, ctx);
return true;
}

View File

@@ -0,0 +1,63 @@
LIBRARY ezusb2-popn-shim
EXPORTS
DllMain@12 @1 NONAME
?usbBootSecurity@@YAHPAEHHH@Z=proxy_usb_boot_security
?usbBootSecurityAll@@YAHPAEHHH@Z=proxy_usb_boot_security_all
?usbBootSecurityAllR@@YAHPAEHHH@Z=proxy_usb_boot_security_all_r
?usbCheckAlive@@YAHXZ=proxy_usb_check_alive
?usbCheckSecurity@@YAHPAEHHH@Z=proxy_usb_check_security
?usbCheckSecurityEep@@YAHH@Z=proxy_usb_check_security_eep
?usbCheckSecurityNew@@YAHH@Z=proxy_usb_check_security_new
?usbCoinBlocker@@YAHH@Z=proxy_usb_coin_blocker
?usbCoinGet2@@YAHPAUCoinParam@@@Z=proxy_usb_coin_get2
?usbCoinGet@@YAHH@Z=proxy_usb_coin_get
?usbCoinMeterDown@@YAHH@Z=proxy_usb_coin_meter_down
?usbCoinMeterUp@@YAHH@Z=proxy_usb_coin_meter_up
?usbCoinMode@@YAHH@Z=proxy_usb_coin_mode
?usbCoinUp@@YAHH@Z=proxy_usb_coin_up
?usbEepRead@@YAHXZ=proxy_usb_eep_read
?usbEepReadDone@@YAHPAE@Z=proxy_usb_eep_read_done
?usbEepTest@@YAHXZ=proxy_usb_eep_test
?usbEepWrite@@YAHPAE@Z=proxy_usb_eep_write
?usbEepWriteDone@@YAHXZ=proxy_usb_eep_write_done
?usbEnd@@YAHXZ=proxy_usb_end
?usbFactoryModeInit@@YAHPAE@Z=proxy_usb_factory_mode_init
?usbFirmResult@@YAHXZ=proxy_usb_firm_result
?usbGetError@@YAHPAD@Z=proxy_usb_get_error
?usbGetKEYID@@YAHPAEH@Z=proxy_usb_get_keyid
?usbGetMute@@YAHXZ=proxy_usb_get_mute
?usbGetPCBID@@YAHPAE@Z=proxy_usb_get_pcbid
?usbGetSecurity@@YAHHPAE@Z=proxy_usb_get_security
?usbIsHiSpeed@@YAHXZ=proxy_usb_is_hi_speed
?usbLamp@@YAHH@Z=proxy_usb_lamp
?usbMute@@YAHH@Z=proxy_usb_mute
?usbPadRead@@YAHPAK@Z=proxy_usb_pad_read
?usbPadReadLast@@YAHPAE@Z=proxy_usb_pad_read_last
?usbReadEepHistory@@YAHPAUEEP_HISTORY@@@Z=proxy_usb_read_eep_history
?usbSecurityGetId@@YAHXZ=proxy_usb_security_get_id
?usbSecurityGetIdDone@@YAHPAE@Z=proxy_usb_security_get_id_done
?usbSecurityInit@@YAHXZ=proxy_usb_security_init
?usbSecurityInitDone@@YAHXZ=proxy_usb_security_init_done
?usbSecurityRead@@YAHXZ=proxy_usb_security_read
?usbSecurityReadDone@@YAHPAE@Z=proxy_usb_security_read_done
?usbSecuritySearch@@YAHXZ=proxy_usb_security_search
?usbSecuritySearchDone@@YAHXZ=proxy_usb_security_search_done
?usbSecuritySelect@@YAHH@Z=proxy_usb_security_select
?usbSecuritySelectDone@@YAHXZ=proxy_usb_security_select_done
?usbSecurityTest@@YAHH@Z=proxy_usb_security_test
?usbSecurityWrite@@YAHPAE@Z=proxy_usb_security_write
?usbSecurityWriteDone@@YAHXZ=proxy_usb_security_write_done
?usbSetExtIo@@YAHH@Z=proxy_usb_set_ext_io
?usbSetupEeprom@@YAHPAEHHH@Z=proxy_usb_setup_eeprom
?usbSetupEepromNew@@YAHHPAEHHH@Z=proxy_usb_setup_eeprom_new
?usbSetupSecurity@@YAHPAEHHH@Z=proxy_usb_setup_security
?usbSetupSecurityComplete@@YAHPAEHHH@Z=proxy_usb_setup_security_complete
?usbSetupSecurityCompleteNew@@YAHHPAEHHH@Z=proxy_usb_setup_security_complete_new
?usbSetupSecurityNew@@YAHHPAEHHH@Z=proxy_usb_setup_security_new
?usbStart@@YAHH@Z=proxy_usb_start
?usbStartWithFile@@YAHPAD@Z=proxy_usb_start_with_file
?usbWdtReset@@YAHXZ=proxy_usb_wdt_reset
?usbWdtStart@@YAHH@Z=proxy_usb_wdt_start
?usbWdtStartDone@@YAHXZ=proxy_usb_wdt_start_done
?usbWdtStop@@YAHXZ=proxy_usb_wdt_stop

View File

@@ -0,0 +1,612 @@
#include <windows.h>
#include <stdint.h>
#include <stdbool.h>
#include "util/log.h"
struct CoinParam;
struct EEP_HISTORY;
typedef int32_t (*usb_boot_security_t)(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4);
typedef int32_t (*usb_boot_security_all_t)(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4);
typedef int32_t (*usb_boot_security_all_r_t)(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4);
typedef int32_t (*usb_check_alive_t)();
typedef int32_t (*usb_check_security_t)(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4);
typedef int32_t (*usb_check_security_eep_t)(int32_t param1);
typedef int32_t (*usb_check_security_new_t)(int32_t param1);
typedef int32_t (*usb_coin_blocker_t)(int32_t param1);
typedef int32_t (*usb_coin_get2_t)(struct CoinParam *param1);
typedef int32_t (*usb_coin_get_t)(int32_t param1);
typedef int32_t (*usb_coin_meter_down_t)(int32_t param1);
typedef int32_t (*usb_coin_meter_up_t)(int32_t param1);
typedef int32_t (*usb_coin_mode_t)(int32_t param1);
typedef int32_t (*usb_coin_up_t)(int32_t param1);
typedef int32_t (*usb_eep_read_t)();
typedef int32_t (*usb_eep_read_done_t)(uint8_t *param1);
typedef int32_t (*usb_eep_test_t)();
typedef int32_t (*usb_eep_write_t)(uint8_t *param1);
typedef int32_t (*usb_eep_write_done_t)();
typedef int32_t (*usb_end_t)();
typedef int32_t (*usb_factory_mode_init_t)(uint8_t *param1);
typedef int32_t (*usb_firm_result_t)();
typedef int32_t (*usb_get_error_t)(char *param1);
typedef int32_t (*usb_get_keyid_t)(uint8_t *param1, int32_t param2);
typedef int32_t (*usb_get_mute_t)();
typedef int32_t (*usb_get_pcbid_t)(uint8_t *param1);
typedef int32_t (*usb_get_security_t)(int32_t param1, uint8_t *param2);
typedef int32_t (*usb_is_hi_speed_t)();
typedef int32_t (*usb_lamp_t)(int32_t param1);
typedef int32_t (*usb_mute_t)(int32_t param1);
typedef int32_t (*usb_pad_read_t)(uint32_t *param1);
typedef int32_t (*usb_pad_read_last_t)(uint8_t *param1);
typedef int32_t (*usb_read_eep_history_t)(struct EEP_HISTORY *param1);
typedef int32_t (*usb_security_get_id_t)();
typedef int32_t (*usb_security_get_id_done_t)(uint8_t *param1);
typedef int32_t (*usb_security_init_t)();
typedef int32_t (*usb_security_init_done_t)();
typedef int32_t (*usb_security_read_t)();
typedef int32_t (*usb_security_read_done_t)(uint8_t *param1);
typedef int32_t (*usb_security_search_t)();
typedef int32_t (*usb_security_search_done_t)();
typedef int32_t (*usb_security_select_t)(int32_t param1);
typedef int32_t (*usb_security_select_done_t)();
typedef int32_t (*usb_security_test_t)(int32_t param1);
typedef int32_t (*usb_security_write_t)(uint8_t *param1);
typedef int32_t (*usb_security_write_done_t)();
typedef int32_t (*usb_set_ext_io_t)(int32_t param1);
typedef int32_t (*usb_setup_eeprom_t)(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4);
typedef int32_t (*usb_setup_eeprom_new_t)(int32_t param1, uint8_t *param2, int32_t param3, int32_t param4, int32_t param5);
typedef int32_t (*usb_setup_security_t)(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4);
typedef int32_t (*usb_setup_security_complete_t)(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4);
typedef int32_t (*usb_setup_security_complete_new_t)(int32_t param1, uint8_t *param2, int32_t param3, int32_t param4, int32_t param5);
typedef int32_t (*usb_setup_security_new_t)(int32_t param1, uint8_t *param2, int32_t param3, int32_t param4, int32_t param5);
typedef int32_t (*usb_start_t)(int32_t param1);
typedef int32_t (*usb_start_with_file_t)(char *param1);
typedef int32_t (*usb_wdt_reset_t)();
typedef int32_t (*usb_wdt_start_t)(int32_t param1);
typedef int32_t (*usb_wdt_start_done_t)();
typedef int32_t (*usb_wdt_stop_t)();
static usb_boot_security_t real_usb_boot_security;
static usb_boot_security_all_t real_usb_boot_security_all;
static usb_boot_security_all_r_t real_usb_boot_security_all_r;
static usb_check_alive_t real_usb_check_alive;
static usb_check_security_t real_usb_check_security;
static usb_check_security_eep_t real_usb_check_security_eep;
static usb_check_security_new_t real_usb_check_security_new;
static usb_coin_blocker_t real_usb_coin_blocker;
static usb_coin_get2_t real_usb_coin_get2;
static usb_coin_get_t real_usb_coin_get;
static usb_coin_meter_down_t real_usb_coin_meter_down;
static usb_coin_meter_up_t real_usb_coin_meter_up;
static usb_coin_mode_t real_usb_coin_mode;
static usb_coin_up_t real_usb_coin_up;
static usb_eep_read_t real_usb_eep_read;
static usb_eep_read_done_t real_usb_eep_read_done;
static usb_eep_test_t real_usb_eep_test;
static usb_eep_write_t real_usb_eep_write;
static usb_eep_write_done_t real_usb_eep_write_done;
static usb_end_t real_usb_end;
static usb_factory_mode_init_t real_usb_factory_mode_init;
static usb_firm_result_t real_usb_firm_result;
static usb_get_error_t real_usb_get_error;
static usb_get_keyid_t real_usb_get_keyid;
static usb_get_mute_t real_usb_get_mute;
static usb_get_pcbid_t real_usb_get_pcbid;
static usb_get_security_t real_usb_get_security;
static usb_is_hi_speed_t real_usb_is_hi_speed;
static usb_lamp_t real_usb_lamp;
static usb_mute_t real_usb_mute;
static usb_pad_read_t real_usb_pad_read;
static usb_pad_read_last_t real_usb_pad_read_last;
static usb_read_eep_history_t real_usb_read_eep_history;
static usb_security_get_id_t real_usb_security_get_id;
static usb_security_get_id_done_t real_usb_security_get_id_done;
static usb_security_init_t real_usb_security_init;
static usb_security_init_done_t real_usb_security_init_done;
static usb_security_read_t real_usb_security_read;
static usb_security_read_done_t real_usb_security_read_done;
static usb_security_search_t real_usb_security_search;
static usb_security_search_done_t real_usb_security_search_done;
static usb_security_select_t real_usb_security_select;
static usb_security_select_done_t real_usb_security_select_done;
static usb_security_test_t real_usb_security_test;
static usb_security_write_t real_usb_security_write;
static usb_security_write_done_t real_usb_security_write_done;
static usb_set_ext_io_t real_usb_set_ext_io;
static usb_setup_eeprom_t real_usb_setup_eeprom;
static usb_setup_eeprom_new_t real_usb_setup_eeprom_new;
static usb_setup_security_t real_usb_setup_security;
static usb_setup_security_complete_t real_usb_setup_security_complete;
static usb_setup_security_complete_new_t real_usb_setup_security_complete_new;
static usb_setup_security_new_t real_usb_setup_security_new;
static usb_start_t real_usb_start;
static usb_start_with_file_t real_usb_start_with_file;
static usb_wdt_reset_t real_usb_wdt_reset;
static usb_wdt_start_t real_usb_wdt_start;
static usb_wdt_start_done_t real_usb_wdt_start_done;
static usb_wdt_stop_t real_usb_wdt_stop;
static bool proxy_is_initialized = false;
void ezusb2_proxy_initialize(HMODULE pe)
{
if (proxy_is_initialized)
return;
log_assert(pe != NULL);
proxy_is_initialized = true;
real_usb_boot_security = (usb_boot_security_t)GetProcAddress(pe, "?usbBootSecurity@@YAHPAEHHH@Z");
log_assert(real_usb_boot_security);
real_usb_boot_security_all = (usb_boot_security_all_t)GetProcAddress(pe, "?usbBootSecurityAll@@YAHPAEHHH@Z");
log_assert(real_usb_boot_security_all);
real_usb_boot_security_all_r = (usb_boot_security_all_r_t)GetProcAddress(pe, "?usbBootSecurityAllR@@YAHPAEHHH@Z");
log_assert(real_usb_boot_security_all_r);
real_usb_check_alive = (usb_check_alive_t)GetProcAddress(pe, "?usbCheckAlive@@YAHXZ");
log_assert(real_usb_check_alive);
real_usb_check_security = (usb_check_security_t)GetProcAddress(pe, "?usbCheckSecurity@@YAHPAEHHH@Z");
log_assert(real_usb_check_security);
real_usb_check_security_eep = (usb_check_security_eep_t)GetProcAddress(pe, "?usbCheckSecurityEep@@YAHH@Z");
log_assert(real_usb_check_security_eep);
real_usb_check_security_new = (usb_check_security_new_t)GetProcAddress(pe, "?usbCheckSecurityNew@@YAHH@Z");
log_assert(real_usb_check_security_new);
real_usb_coin_blocker = (usb_coin_blocker_t)GetProcAddress(pe, "?usbCoinBlocker@@YAHH@Z");
log_assert(real_usb_coin_blocker);
real_usb_coin_get2 = (usb_coin_get2_t)GetProcAddress(pe, "?usbCoinGet2@@YAHPAUCoinParam@@@Z");
log_assert(real_usb_coin_get2);
real_usb_coin_get = (usb_coin_get_t)GetProcAddress(pe, "?usbCoinGet@@YAHH@Z");
log_assert(real_usb_coin_get);
real_usb_coin_meter_down = (usb_coin_meter_down_t)GetProcAddress(pe, "?usbCoinMeterDown@@YAHH@Z");
log_assert(real_usb_coin_meter_down);
real_usb_coin_meter_up = (usb_coin_meter_up_t)GetProcAddress(pe, "?usbCoinMeterUp@@YAHH@Z");
log_assert(real_usb_coin_meter_up);
real_usb_coin_mode = (usb_coin_mode_t)GetProcAddress(pe, "?usbCoinMode@@YAHH@Z");
log_assert(real_usb_coin_mode);
real_usb_coin_up = (usb_coin_up_t)GetProcAddress(pe, "?usbCoinUp@@YAHH@Z");
log_assert(real_usb_coin_up);
real_usb_eep_read = (usb_eep_read_t)GetProcAddress(pe, "?usbEepRead@@YAHXZ");
log_assert(real_usb_eep_read);
real_usb_eep_read_done = (usb_eep_read_done_t)GetProcAddress(pe, "?usbEepReadDone@@YAHPAE@Z");
log_assert(real_usb_eep_read_done);
real_usb_eep_test = (usb_eep_test_t)GetProcAddress(pe, "?usbEepTest@@YAHXZ");
log_assert(real_usb_eep_test);
real_usb_eep_write = (usb_eep_write_t)GetProcAddress(pe, "?usbEepWrite@@YAHPAE@Z");
log_assert(real_usb_eep_write);
real_usb_eep_write_done = (usb_eep_write_done_t)GetProcAddress(pe, "?usbEepWriteDone@@YAHXZ");
log_assert(real_usb_eep_write_done);
real_usb_end = (usb_end_t)GetProcAddress(pe, "?usbEnd@@YAHXZ");
log_assert(real_usb_end);
real_usb_factory_mode_init = (usb_factory_mode_init_t)GetProcAddress(pe, "?usbFactoryModeInit@@YAHPAE@Z");
log_assert(real_usb_factory_mode_init);
real_usb_firm_result = (usb_firm_result_t)GetProcAddress(pe, "?usbFirmResult@@YAHXZ");
log_assert(real_usb_firm_result);
real_usb_get_error = (usb_get_error_t)GetProcAddress(pe, "?usbGetError@@YAHPAD@Z");
log_assert(real_usb_get_error);
real_usb_get_keyid = (usb_get_keyid_t)GetProcAddress(pe, "?usbGetKEYID@@YAHPAEH@Z");
log_assert(real_usb_get_keyid);
real_usb_get_mute = (usb_get_mute_t)GetProcAddress(pe, "?usbGetMute@@YAHXZ");
log_assert(real_usb_get_mute);
real_usb_get_pcbid = (usb_get_pcbid_t)GetProcAddress(pe, "?usbGetPCBID@@YAHPAE@Z");
log_assert(real_usb_get_pcbid);
real_usb_get_security = (usb_get_security_t)GetProcAddress(pe, "?usbGetSecurity@@YAHHPAE@Z");
log_assert(real_usb_get_security);
real_usb_is_hi_speed = (usb_is_hi_speed_t)GetProcAddress(pe, "?usbIsHiSpeed@@YAHXZ");
log_assert(real_usb_is_hi_speed);
real_usb_lamp = (usb_lamp_t)GetProcAddress(pe, "?usbLamp@@YAHH@Z");
log_assert(real_usb_lamp);
real_usb_mute = (usb_mute_t)GetProcAddress(pe, "?usbMute@@YAHH@Z");
log_assert(real_usb_mute);
real_usb_pad_read = (usb_pad_read_t)GetProcAddress(pe, "?usbPadRead@@YAHPAK@Z");
log_assert(real_usb_pad_read);
real_usb_pad_read_last = (usb_pad_read_last_t)GetProcAddress(pe, "?usbPadReadLast@@YAHPAE@Z");
log_assert(real_usb_pad_read_last);
real_usb_read_eep_history = (usb_read_eep_history_t)GetProcAddress(pe, "?usbReadEepHistory@@YAHPAUEEP_HISTORY@@@Z");
log_assert(real_usb_read_eep_history);
real_usb_security_get_id = (usb_security_get_id_t)GetProcAddress(pe, "?usbSecurityGetId@@YAHXZ");
log_assert(real_usb_security_get_id);
real_usb_security_get_id_done = (usb_security_get_id_done_t)GetProcAddress(pe, "?usbSecurityGetIdDone@@YAHPAE@Z");
log_assert(real_usb_security_get_id_done);
real_usb_security_init = (usb_security_init_t)GetProcAddress(pe, "?usbSecurityInit@@YAHXZ");
log_assert(real_usb_security_init);
real_usb_security_init_done = (usb_security_init_done_t)GetProcAddress(pe, "?usbSecurityInitDone@@YAHXZ");
log_assert(real_usb_security_init_done);
real_usb_security_read = (usb_security_read_t)GetProcAddress(pe, "?usbSecurityRead@@YAHXZ");
log_assert(real_usb_security_read);
real_usb_security_read_done = (usb_security_read_done_t)GetProcAddress(pe, "?usbSecurityReadDone@@YAHPAE@Z");
log_assert(real_usb_security_read_done);
real_usb_security_search = (usb_security_search_t)GetProcAddress(pe, "?usbSecuritySearch@@YAHXZ");
log_assert(real_usb_security_search);
real_usb_security_search_done = (usb_security_search_done_t)GetProcAddress(pe, "?usbSecuritySearchDone@@YAHXZ");
log_assert(real_usb_security_search_done);
real_usb_security_select = (usb_security_select_t)GetProcAddress(pe, "?usbSecuritySelect@@YAHH@Z");
log_assert(real_usb_security_select);
real_usb_security_select_done = (usb_security_select_done_t)GetProcAddress(pe, "?usbSecuritySelectDone@@YAHXZ");
log_assert(real_usb_security_select_done);
real_usb_security_test = (usb_security_test_t)GetProcAddress(pe, "?usbSecurityTest@@YAHH@Z");
log_assert(real_usb_security_test);
real_usb_security_write = (usb_security_write_t)GetProcAddress(pe, "?usbSecurityWrite@@YAHPAE@Z");
log_assert(real_usb_security_write);
real_usb_security_write_done = (usb_security_write_done_t)GetProcAddress(pe, "?usbSecurityWriteDone@@YAHXZ");
log_assert(real_usb_security_write_done);
real_usb_set_ext_io = (usb_set_ext_io_t)GetProcAddress(pe, "?usbSetExtIo@@YAHH@Z");
log_assert(real_usb_set_ext_io);
real_usb_setup_eeprom = (usb_setup_eeprom_t)GetProcAddress(pe, "?usbSetupEeprom@@YAHPAEHHH@Z");
log_assert(real_usb_setup_eeprom);
real_usb_setup_eeprom_new = (usb_setup_eeprom_new_t)GetProcAddress(pe, "?usbSetupEepromNew@@YAHHPAEHHH@Z");
log_assert(real_usb_setup_eeprom_new);
real_usb_setup_security = (usb_setup_security_t)GetProcAddress(pe, "?usbSetupSecurity@@YAHPAEHHH@Z");
log_assert(real_usb_setup_security);
real_usb_setup_security_complete = (usb_setup_security_complete_t)GetProcAddress(pe, "?usbSetupSecurityComplete@@YAHPAEHHH@Z");
log_assert(real_usb_setup_security_complete);
real_usb_setup_security_complete_new = (usb_setup_security_complete_new_t)GetProcAddress(pe, "?usbSetupSecurityCompleteNew@@YAHHPAEHHH@Z");
log_assert(real_usb_setup_security_complete_new);
real_usb_setup_security_new = (usb_setup_security_new_t)GetProcAddress(pe, "?usbSetupSecurityNew@@YAHHPAEHHH@Z");
log_assert(real_usb_setup_security_new);
real_usb_start = (usb_start_t)GetProcAddress(pe, "?usbStart@@YAHH@Z");
log_assert(real_usb_start);
real_usb_start_with_file = (usb_start_with_file_t)GetProcAddress(pe, "?usbStartWithFile@@YAHPAD@Z");
log_assert(real_usb_start_with_file);
real_usb_wdt_reset = (usb_wdt_reset_t)GetProcAddress(pe, "?usbWdtReset@@YAHXZ");
log_assert(real_usb_wdt_reset);
real_usb_wdt_start = (usb_wdt_start_t)GetProcAddress(pe, "?usbWdtStart@@YAHH@Z");
log_assert(real_usb_wdt_start);
real_usb_wdt_start_done = (usb_wdt_start_done_t)GetProcAddress(pe, "?usbWdtStartDone@@YAHXZ");
log_assert(real_usb_wdt_start_done);
real_usb_wdt_stop = (usb_wdt_stop_t)GetProcAddress(pe, "?usbWdtStop@@YAHXZ");
log_assert(real_usb_wdt_stop);
}
int32_t proxy_usb_boot_security(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4)
{
return real_usb_boot_security(param1, param2, param3, param4);
}
int32_t proxy_usb_boot_security_all(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4)
{
return real_usb_boot_security_all(param1, param2, param3, param4);
}
int32_t proxy_usb_boot_security_all_r(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4)
{
return real_usb_boot_security_all_r(param1, param2, param3, param4);
}
int32_t proxy_usb_check_alive()
{
return real_usb_check_alive();
}
int32_t proxy_usb_check_security(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4)
{
return real_usb_check_security(param1, param2, param3, param4);
}
int32_t proxy_usb_check_security_eep(int32_t param1)
{
return real_usb_check_security_eep(param1);
}
int32_t proxy_usb_check_security_new(int32_t param1)
{
return real_usb_check_security_new(param1);
}
int32_t proxy_usb_coin_blocker(int32_t param1)
{
return real_usb_coin_blocker(param1);
}
int32_t proxy_usb_coin_get2(struct CoinParam *param1)
{
return real_usb_coin_get2(param1);
}
int32_t proxy_usb_coin_get(int32_t param1)
{
return real_usb_coin_get(param1);
}
int32_t proxy_usb_coin_meter_down(int32_t param1)
{
return real_usb_coin_meter_down(param1);
}
int32_t proxy_usb_coin_meter_up(int32_t param1)
{
return real_usb_coin_meter_up(param1);
}
int32_t proxy_usb_coin_mode(int32_t param1)
{
return real_usb_coin_mode(param1);
}
int32_t proxy_usb_coin_up(int32_t param1)
{
return real_usb_coin_up(param1);
}
int32_t proxy_usb_eep_read()
{
return real_usb_eep_read();
}
int32_t proxy_usb_eep_read_done(uint8_t *param1)
{
return real_usb_eep_read_done(param1);
}
int32_t proxy_usb_eep_test()
{
return real_usb_eep_test();
}
int32_t proxy_usb_eep_write(uint8_t *param1)
{
return real_usb_eep_write(param1);
}
int32_t proxy_usb_eep_write_done()
{
return real_usb_eep_write_done();
}
int32_t proxy_usb_end()
{
return real_usb_end();
}
int32_t proxy_usb_factory_mode_init(uint8_t *param1)
{
return real_usb_factory_mode_init(param1);
}
int32_t proxy_usb_firm_result()
{
return real_usb_firm_result();
}
int32_t proxy_usb_get_error(char *param1)
{
return real_usb_get_error(param1);
}
int32_t proxy_usb_get_keyid(uint8_t *param1, int32_t param2)
{
return real_usb_get_keyid(param1, param2);
}
int32_t proxy_usb_get_mute()
{
return real_usb_get_mute();
}
int32_t proxy_usb_get_pcbid(uint8_t *param1)
{
return real_usb_get_pcbid(param1);
}
int32_t proxy_usb_get_security(int32_t param1, uint8_t *param2)
{
return real_usb_get_security(param1, param2);
}
int32_t proxy_usb_is_hi_speed()
{
return real_usb_is_hi_speed();
}
int32_t proxy_usb_lamp(int32_t param1)
{
return real_usb_lamp(param1);
}
int32_t proxy_usb_mute(int32_t param1)
{
return real_usb_mute(param1);
}
int32_t proxy_usb_pad_read(uint32_t *param1)
{
return real_usb_pad_read(param1);
}
int32_t proxy_usb_pad_read_last(uint8_t *param1)
{
return real_usb_pad_read_last(param1);
}
int32_t proxy_usb_read_eep_history(struct EEP_HISTORY *param1)
{
return real_usb_read_eep_history(param1);
}
int32_t proxy_usb_security_get_id()
{
return real_usb_security_get_id();
}
int32_t proxy_usb_security_get_id_done(uint8_t *param1)
{
return real_usb_security_get_id_done(param1);
}
int32_t proxy_usb_security_init()
{
return real_usb_security_init();
}
int32_t proxy_usb_security_init_done()
{
return real_usb_security_init_done();
}
int32_t proxy_usb_security_read()
{
return real_usb_security_read();
}
int32_t proxy_usb_security_read_done(uint8_t *param1)
{
return real_usb_security_read_done(param1);
}
int32_t proxy_usb_security_search()
{
return real_usb_security_search();
}
int32_t proxy_usb_security_search_done()
{
return real_usb_security_search_done();
}
int32_t proxy_usb_security_select(int32_t param1)
{
return real_usb_security_select(param1);
}
int32_t proxy_usb_security_select_done()
{
return real_usb_security_select_done();
}
int32_t proxy_usb_security_test(int32_t param1)
{
return real_usb_security_test(param1);
}
int32_t proxy_usb_security_write(uint8_t *param1)
{
return real_usb_security_write(param1);
}
int32_t proxy_usb_security_write_done()
{
return real_usb_security_write_done();
}
int32_t proxy_usb_set_ext_io(int32_t param1)
{
return real_usb_set_ext_io(param1);
}
int32_t proxy_usb_setup_eeprom(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4)
{
return real_usb_setup_eeprom(param1, param2, param3, param4);
}
int32_t proxy_usb_setup_eeprom_new(int32_t param1, uint8_t *param2, int32_t param3, int32_t param4, int32_t param5)
{
return real_usb_setup_eeprom_new(param1, param2, param3, param4, param5);
}
int32_t proxy_usb_setup_security(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4)
{
return real_usb_setup_security(param1, param2, param3, param4);
}
int32_t proxy_usb_setup_security_complete(uint8_t *param1, int32_t param2, int32_t param3, int32_t param4)
{
return real_usb_setup_security_complete(param1, param2, param3, param4);
}
int32_t proxy_usb_setup_security_complete_new(int32_t param1, uint8_t *param2, int32_t param3, int32_t param4, int32_t param5)
{
return real_usb_setup_security_complete_new(param1, param2, param3, param4, param5);
}
int32_t proxy_usb_setup_security_new(int32_t param1, uint8_t *param2, int32_t param3, int32_t param4, int32_t param5)
{
return real_usb_setup_security_new(param1, param2, param3, param4, param5);
}
int32_t proxy_usb_start(int32_t param1)
{
return real_usb_start(param1);
}
int32_t proxy_usb_start_with_file(char *param1)
{
return real_usb_start_with_file(param1);
}
int32_t proxy_usb_wdt_reset()
{
return real_usb_wdt_reset();
}
int32_t proxy_usb_wdt_start(int32_t param1)
{
return real_usb_wdt_start(param1);
}
int32_t proxy_usb_wdt_start_done()
{
return real_usb_wdt_start_done();
}
int32_t proxy_usb_wdt_stop()
{
return real_usb_wdt_stop();
}

View File

@@ -0,0 +1,6 @@
#ifndef EZUSB2_POPN_SHIM_PROXY_H
#define EZUSB2_POPN_SHIM_PROXY_H
void ezusb2_proxy_initialize(HMODULE pe);
#endif

View File

@@ -0,0 +1,87 @@
#ifndef EZUSB2_POPN_MSG_H
#define EZUSB2_POPN_MSG_H
#include <stddef.h>
#include <stdint.h>
#pragma pack(push, 1)
struct ezusb2_popn_msg_interrupt_write_packet {
uint8_t unk0;
uint8_t unk1;
uint8_t node;
uint8_t cmd;
uint8_t cmd_detail[2];
uint8_t unknown[2];
uint32_t lamp;
/* Pad to 64 byte total size because the endpoint expects this buffer size.
Requests are hanging on ioctl calls otherwise. */
uint8_t unknown2[52];
};
#pragma pack(pop)
#pragma pack(push, 1)
struct ezusb2_popn_msg_interrupt_read_packet {
/*
Pad mappings:
0: unknown/not used
1: unknown/not used
2: unknown/not used
3: unknown/not used
4: unknown/not used
5: unknown/not used
6: service
7: test
8: button 1
9: button 2
10: button 3
11: button 4
12: button 5
13: button 6
14: button 7
15: button 8
16: button 9
17: unknown/not used
18: unknown/not used
19: unknown/not used
20: unknown/not used
21: unknown/not used
22: coin
23: unknown/not used
24: dipsw 1
25: dipsw 2
26: dipsw 3
27: dipsw 4
28: unknown/not used
29: unknown/not used
30: unknown/not used
31: unknown/not used
*/
uint8_t unk0; /* 0x03 */
uint8_t unk1; /* 0x1d */
uint8_t unk2; /* 0x85 */
uint8_t seq_no;
uint8_t status;
uint8_t unk3; /* 0x00 */
uint8_t coin_count;
uint8_t unk4; /* 0xfd */
union {
uint32_t inverted_pad;
struct {
uint8_t sys; /* test/service bitfield */
uint16_t button; /* button bitfield */
uint8_t dipsw; /* dip switches */
};
} io;
uint8_t unk5; /* 0x00 */
uint8_t unk6; /* 0x7d */
uint8_t unk7; /* 0xdf */
uint8_t unk8; /* seq no 2? */
uint16_t button_history[10];
uint8_t padding[28];
};
#pragma pack(pop)
#endif

View File

@@ -75,6 +75,12 @@ static HRESULT(STDCALL *real_Reset)(
IDirect3DDevice9 *self, IDirect3DDevice9 *self,
D3DPRESENT_PARAMETERS *pp); D3DPRESENT_PARAMETERS *pp);
static HRESULT (STDCALL *real_SetViewport)(
IDirect3DDevice9 *self, const D3DVIEWPORT9 *pViewport);
static HRESULT (STDCALL *real_SetVertexShader)(
IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader);
/* ------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------
*/ */
@@ -144,6 +150,12 @@ static HRESULT STDCALL my_Reset(
IDirect3DDevice9 *self, IDirect3DDevice9 *self,
D3DPRESENT_PARAMETERS *pp); D3DPRESENT_PARAMETERS *pp);
static HRESULT STDCALL my_SetViewport(
IDirect3DDevice9 *self, const D3DVIEWPORT9 *pViewport);
static HRESULT STDCALL my_SetVertexShader(
IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader);
/* ------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------
*/ */
@@ -205,6 +217,12 @@ hook_d3d9_irp_handler_real_dev_draw_primitive_up(struct hook_d3d9_irp *irp);
static HRESULT static HRESULT
hook_d3d9_irp_handler_real_dev_reset(struct hook_d3d9_irp *irp); hook_d3d9_irp_handler_real_dev_reset(struct hook_d3d9_irp *irp);
static HRESULT
hook_d3d9_irp_handler_real_dev_set_viewport(struct hook_d3d9_irp *irp);
static HRESULT
hook_d3d9_irp_handler_real_dev_set_vertex_shader(struct hook_d3d9_irp *irp);
/* ------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------
*/ */
@@ -231,6 +249,10 @@ static const hook_d3d9_irp_handler_t hook_d3d9_irp_real_handlers[] = {
hook_d3d9_irp_handler_real_dev_draw_primitive_up, hook_d3d9_irp_handler_real_dev_draw_primitive_up,
[HOOK_D3D9_IRP_OP_DEV_RESET] = [HOOK_D3D9_IRP_OP_DEV_RESET] =
hook_d3d9_irp_handler_real_dev_reset, hook_d3d9_irp_handler_real_dev_reset,
[HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT] =
hook_d3d9_irp_handler_real_dev_set_viewport,
[HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER] =
hook_d3d9_irp_handler_real_dev_set_vertex_shader,
}; };
static const hook_d3d9_irp_handler_t *hook_d3d9_handlers; static const hook_d3d9_irp_handler_t *hook_d3d9_handlers;
@@ -501,6 +523,40 @@ static HRESULT STDCALL my_DrawPrimitiveUP(
return hr; return hr;
} }
static HRESULT STDCALL my_SetViewport(
IDirect3DDevice9 *self, const D3DVIEWPORT9 *pViewport)
{
struct hook_d3d9_irp irp;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT;
irp.args.dev_set_viewport.self = self;
irp.args.dev_set_viewport.pViewport = pViewport;
hr = hook_d3d9_irp_invoke_next(&irp);
return hr;
}
static HRESULT STDCALL my_SetVertexShader(
IDirect3DDevice9 *self, IDirect3DVertexShader9 *pShader)
{
struct hook_d3d9_irp irp;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER;
irp.args.dev_set_vertex_shader.self = self;
irp.args.dev_set_vertex_shader.pShader = pShader;
hr = hook_d3d9_irp_invoke_next(&irp);
return hr;
}
static HRESULT STDCALL my_Reset( static HRESULT STDCALL my_Reset(
IDirect3DDevice9 *self, IDirect3DDevice9 *self,
D3DPRESENT_PARAMETERS *pp) D3DPRESENT_PARAMETERS *pp)
@@ -691,6 +747,12 @@ hook_d3d9_irp_handler_real_dev_create_device(struct hook_d3d9_irp *irp)
real_Reset = api_vtbl->Reset; real_Reset = api_vtbl->Reset;
api_vtbl->Reset = my_Reset; api_vtbl->Reset = my_Reset;
real_SetViewport = api_vtbl->SetViewport;
api_vtbl->SetViewport = my_SetViewport;
real_SetVertexShader = api_vtbl->SetVertexShader;
api_vtbl->SetVertexShader = my_SetVertexShader;
*irp->args.ctx_create_device.pdev = (IDirect3DDevice9 *) api_proxy; *irp->args.ctx_create_device.pdev = (IDirect3DDevice9 *) api_proxy;
return hr; return hr;
@@ -775,6 +837,26 @@ hook_d3d9_irp_handler_real_dev_reset(struct hook_d3d9_irp *irp)
irp->args.dev_reset.pp); irp->args.dev_reset.pp);
} }
static HRESULT
hook_d3d9_irp_handler_real_dev_set_viewport(struct hook_d3d9_irp *irp)
{
log_assert(irp);
return real_SetViewport(
irp->args.dev_set_viewport.self,
irp->args.dev_set_viewport.pViewport);
}
static HRESULT
hook_d3d9_irp_handler_real_dev_set_vertex_shader(struct hook_d3d9_irp *irp)
{
log_assert(irp);
return real_SetVertexShader(
irp->args.dev_set_vertex_shader.self,
irp->args.dev_set_vertex_shader.pShader);
}
/* ------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------
*/ */

View File

@@ -34,6 +34,8 @@ enum hook_d3d9_irp_op {
HOOK_D3D9_IRP_OP_DEV_SET_RENDER_STATE = 10, HOOK_D3D9_IRP_OP_DEV_SET_RENDER_STATE = 10,
HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP = 11, HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP = 11,
HOOK_D3D9_IRP_OP_DEV_RESET = 12, HOOK_D3D9_IRP_OP_DEV_RESET = 12,
HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT = 13,
HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER = 14,
}; };
/** /**
@@ -170,6 +172,22 @@ struct hook_d3d9_irp {
IDirect3DDevice9 *self; IDirect3DDevice9 *self;
D3DPRESENT_PARAMETERS *pp; D3DPRESENT_PARAMETERS *pp;
} dev_reset; } dev_reset;
/**
* Params of IDIrect3DDevice9_SetViewport
*/
struct {
IDirect3DDevice9 *self;
const D3DVIEWPORT9 *pViewport;
} dev_set_viewport;
/**
* Params of IDIrect3DDevice9_SetVertexShader
*/
struct {
IDirect3DDevice9 *self;
IDirect3DVertexShader9 *pShader;
} dev_set_vertex_shader;
} args; } args;
size_t next_handler; size_t next_handler;

View File

@@ -220,3 +220,96 @@ HRESULT pe_patch(void *dest, const void *src, size_t nbytes)
return S_OK; return S_OK;
} }
const pe_thunk_t *pe_thunk_get_first(HMODULE pe, const pe_iid_t *iid)
{
pe_thunk_t *thunk;
assert(pe != NULL);
assert(iid != NULL);
thunk = pe_offset(pe, iid->FirstThunk);
if (thunk == NULL || thunk->u1.AddressOfData == 0) {
return NULL;
}
return thunk;
}
const pe_thunk_t *pe_thunk_get_next(const pe_thunk_t *thunk)
{
const IMAGE_THUNK_DATA *thunk_next;
assert(thunk != NULL);
thunk_next = thunk + 1;
if (thunk_next == NULL || thunk_next->u1.AddressOfData == 0) {
return NULL;
}
return thunk_next;
}
void *pe_thunk_get_resolved_function(HMODULE target_pe, HMODULE import_pe, const pe_thunk_t *thunk)
{
void *addr;
assert(target_pe != NULL);
assert(import_pe != NULL);
assert(thunk != NULL);
if (thunk->u1.AddressOfData != 0) {
if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal)) {
LPCSTR functionOrdinal = (LPCSTR)IMAGE_ORDINAL(thunk->u1.Ordinal);
addr = (void *)GetProcAddress(import_pe, functionOrdinal);
} else {
PIMAGE_IMPORT_BY_NAME functionName = pe_offset(target_pe, thunk->u1.AddressOfData);
addr = (void *)GetProcAddress(import_pe, functionName->Name);
}
} else {
addr = NULL;
}
return addr;
}
void pe_resolve_imports(HMODULE target_pe)
{
for (const pe_iid_t *iid = pe_iid_get_first(target_pe); iid != NULL; iid = pe_iid_get_next(target_pe, iid)) {
const char *iid_name;
HMODULE imported_pe;
iid_name = pe_iid_get_name(target_pe, iid);
imported_pe = LoadLibraryA(iid_name);
assert(imported_pe != NULL);
for (const pe_thunk_t *thunk = pe_thunk_get_first(target_pe, iid); thunk != NULL; thunk = pe_thunk_get_next(thunk)) {
void *addr;
addr = pe_thunk_get_resolved_function(target_pe, imported_pe, thunk);
if (addr != NULL) {
pe_patch((void*)&thunk->u1.Function, &addr, sizeof(PDWORD));
}
}
}
}
HRESULT pe_hijack_entrypoint(const char *filename, dll_entry_t *orig_entry)
{
HMODULE pe;
pe = LoadLibraryExA(filename, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (!pe) {
return HRESULT_FROM_WIN32(GetLastError());
}
pe_resolve_imports(pe);
*orig_entry = pe_get_entry_point(pe);
return S_OK;
}

View File

@@ -7,6 +7,9 @@
#include <stdint.h> #include <stdint.h>
typedef IMAGE_IMPORT_DESCRIPTOR pe_iid_t; typedef IMAGE_IMPORT_DESCRIPTOR pe_iid_t;
typedef IMAGE_THUNK_DATA pe_thunk_t;
typedef DWORD (CALLBACK *dll_entry_t)(HMODULE self, DWORD reason, void *ctx);
struct pe_iat_entry { struct pe_iat_entry {
const char *name; const char *name;
@@ -25,3 +28,6 @@ HRESULT pe_iid_get_iat_entry(
void *pe_get_export(HMODULE pe, const char *name, uint16_t ord); void *pe_get_export(HMODULE pe, const char *name, uint16_t ord);
void *pe_get_entry_point(HMODULE pe); void *pe_get_entry_point(HMODULE pe);
HRESULT pe_patch(void *dest, const void *src, size_t nbytes); HRESULT pe_patch(void *dest, const void *src, size_t nbytes);
HRESULT pe_hijack_entrypoint(const char *filename, dll_entry_t *orig_entry);
void pe_resolve_imports(HMODULE target_pe);

View File

@@ -22,6 +22,7 @@
"gfx.scale_back_buffer_filter" "gfx.scale_back_buffer_filter"
#define IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate" #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_DEVICE_ADAPTER_KEY "gfx.device_adapter"
#define IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY "gfx.diagonal_tearing_fix"
#define IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE false #define IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE false
#define IIDXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false #define IIDXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false
@@ -36,6 +37,7 @@
#define IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE "none" #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_FORCED_RR_VALUE -1
#define IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE -1 #define IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE -1
#define IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE false
void iidxhook_config_gfx_init(struct cconfig *config) void iidxhook_config_gfx_init(struct cconfig *config)
{ {
@@ -159,6 +161,13 @@ void iidxhook_config_gfx_init(struct cconfig *config)
IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE, IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE,
"D3D9 device adapter (monitor), -1 to use default, " "D3D9 device adapter (monitor), -1 to use default, "
"0, 1, 2 etc. to use specified adapter"); "0, 1, 2 etc. to use specified adapter");
cconfig_util_set_bool(
config,
IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE,
"Fix diagonal tearing with video cards "
"other than Radeon X1300 and HD3450");
} }
void iidxhook_config_gfx_get( void iidxhook_config_gfx_get(
@@ -367,4 +376,16 @@ void iidxhook_config_gfx_get(
IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY, IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE); IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE);
} }
if (!cconfig_util_get_bool(
config,
IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY,
&config_gfx->diagonal_tearing_fix,
IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY,
IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE);
}
} }

View File

@@ -21,6 +21,7 @@ struct iidxhook_config_gfx {
enum iidxhook_util_d3d9_back_buffer_scale_filter scale_back_buffer_filter; enum iidxhook_util_d3d9_back_buffer_scale_filter scale_back_buffer_filter;
int32_t forced_refresh_rate; int32_t forced_refresh_rate;
int32_t device_adapter; int32_t device_adapter;
bool diagonal_tearing_fix;
}; };
void iidxhook_config_gfx_init(struct cconfig *config); void iidxhook_config_gfx_init(struct cconfig *config);

View File

@@ -13,6 +13,7 @@
#include "hook/table.h" #include "hook/table.h"
#include "iidxhook-util/d3d9.h" #include "iidxhook-util/d3d9.h"
#include "iidxhook-util/vertex-shader.h"
#include "util/defs.h" #include "util/defs.h"
#include "util/log.h" #include "util/log.h"
@@ -64,6 +65,8 @@ static struct {
D3DTEXTUREFILTERTYPE filter; D3DTEXTUREFILTERTYPE filter;
} iidxhook_util_d3d9_back_buffer_scaling; } iidxhook_util_d3d9_back_buffer_scaling;
static IDirect3DVertexShader9* vertex_shader;
/* ------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------
*/ */
@@ -901,6 +904,45 @@ iidxhook_util_d3d9_scale_render_target_to_back_buffer(struct hook_d3d9_irp *irp)
} }
} }
static void
iidxhook_util_d3d9_iidx18_and_19_fix_diagonal_tearing(struct hook_d3d9_irp *irp)
{
HRESULT hr;
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT || irp->op == HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER);
if (!iidxhook_util_d3d9_config.iidx18_and_19_diagonal_tearing_fix)
{
return;
}
if (irp->op == HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT)
{
const D3DVIEWPORT9 *pViewport = irp->args.dev_set_viewport.pViewport;
const float fix_offset[2] = {-1.0F / (float)pViewport->Width, -1.0F / (float)pViewport->Height};
hr = IDirect3DDevice9_SetVertexShaderConstantF(irp->args.dev_set_viewport.self, 63, fix_offset, lengthof(fix_offset));
if (hr != S_OK) {
log_warning("SetVertexShaderConstantF failed: %lX", hr);
}
}
if (irp->op == HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER)
{
if (!vertex_shader) {
hr = IDirect3DDevice9_CreateVertexShader(irp->args.dev_set_vertex_shader.self, (const DWORD*) g_vs11_vs_main, &vertex_shader);
if (hr != S_OK) {
log_fatal("CreateVertexShader failed: %lX", hr);
}
}
if (irp->args.dev_set_vertex_shader.pShader != NULL) {
irp->args.dev_set_vertex_shader.pShader = vertex_shader;
}
}
}
/* ------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------
*/ */
@@ -921,6 +963,7 @@ iidxhook_util_d3d9_log_config(const struct iidxhook_util_d3d9_config *config)
"iidx12_fix_song_select_bg: %d\n" "iidx12_fix_song_select_bg: %d\n"
"iidx13_fix_song_select_bg: %d\n" "iidx13_fix_song_select_bg: %d\n"
"iidx14_to_19_nvidia_fix: %d\n" "iidx14_to_19_nvidia_fix: %d\n"
"iidx18_and_19_diagonal_tearing_fix: %d\n"
"scale_back_buffer_width: %d\n" "scale_back_buffer_width: %d\n"
"scale_back_buffer_height: %d\n" "scale_back_buffer_height: %d\n"
"scale_back_buffer_filter: %d\n" "scale_back_buffer_filter: %d\n"
@@ -938,6 +981,7 @@ iidxhook_util_d3d9_log_config(const struct iidxhook_util_d3d9_config *config)
config->iidx12_fix_song_select_bg, config->iidx12_fix_song_select_bg,
config->iidx13_fix_song_select_bg, config->iidx13_fix_song_select_bg,
config->iidx14_to_19_nvidia_fix, config->iidx14_to_19_nvidia_fix,
config->iidx18_and_19_diagonal_tearing_fix,
config->scale_back_buffer_width, config->scale_back_buffer_width,
config->scale_back_buffer_height, config->scale_back_buffer_height,
config->scale_back_buffer_filter, config->scale_back_buffer_filter,
@@ -1002,6 +1046,7 @@ void iidxhook_util_d3d9_init_config(struct iidxhook_util_d3d9_config *config)
config->iidx12_fix_song_select_bg = false; config->iidx12_fix_song_select_bg = false;
config->iidx13_fix_song_select_bg = false; config->iidx13_fix_song_select_bg = false;
config->iidx14_to_19_nvidia_fix = false; config->iidx14_to_19_nvidia_fix = false;
config->iidx18_and_19_diagonal_tearing_fix = false;
config->scale_back_buffer_width = 0; config->scale_back_buffer_width = 0;
config->scale_back_buffer_height = 0; config->scale_back_buffer_height = 0;
config->scale_back_buffer_filter = config->scale_back_buffer_filter =
@@ -1112,6 +1157,12 @@ iidxhook_util_d3d9_irp_handler(struct hook_d3d9_irp *irp)
return hook_d3d9_irp_invoke_next(irp); return hook_d3d9_irp_invoke_next(irp);
case HOOK_D3D9_IRP_OP_DEV_SET_VIEWPORT:
case HOOK_D3D9_IRP_OP_DEV_SET_VERTEX_SHADER:
iidxhook_util_d3d9_iidx18_and_19_fix_diagonal_tearing(irp);
return hook_d3d9_irp_invoke_next(irp);
default: default:
return hook_d3d9_irp_invoke_next(irp); return hook_d3d9_irp_invoke_next(irp);
} }

View File

@@ -127,10 +127,15 @@ struct iidxhook_util_d3d9_config {
/** /**
* Fixes a parameter on CreateTexture calls causing the game to crash with * Fixes a parameter on CreateTexture calls causing the game to crash with
* NVIDIA cards (on GOLD and possible newer) * NVIDIA cards on all games from GOLD to Lincle including.
*/ */
bool iidx14_to_19_nvidia_fix; bool iidx14_to_19_nvidia_fix;
/**
* Fix diagonal tearing with video cards other than Radeon X1300 and HD3450
*/
bool iidx18_and_19_diagonal_tearing_fix;
/** /**
* Scale the back buffer after a frame got rendered. This allows you to * Scale the back buffer after a frame got rendered. This allows you to
* up-/downscale the final frame to display arbitrary resolutions, e.g. * up-/downscale the final frame to display arbitrary resolutions, e.g.

View File

@@ -0,0 +1,107 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
// Parameters:
//
// float4 ColorMultiply;
// float2 FixOffset;
// float4x4 WorldViewProjection;
//
//
// Registers:
//
// Name Reg Size
// ------------------- ----- ----
// WorldViewProjection c0 4
// ColorMultiply c4 1
// FixOffset c63 1
//
vs_1_1
dcl_position v0
dcl_color v1
dcl_texcoord v2
dp4 oPos.z, v0, c2
mul oD0, v1, c4
dp4 r0.x, v0, c0
dp4 r0.y, v0, c1
dp4 r0.z, v0, c3
mad oPos.xy, c63, r0.z, r0
mov oPos.w, r0.z
mov oT0.xy, v2
// approximately 8 instruction slots used
#endif
const BYTE g_vs11_vs_main[] =
{
1, 1, 254, 255, 254, 255,
59, 0, 67, 84, 65, 66,
28, 0, 0, 0, 191, 0,
0, 0, 1, 1, 254, 255,
3, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
184, 0, 0, 0, 88, 0,
0, 0, 2, 0, 4, 0,
1, 0, 18, 0, 104, 0,
0, 0, 0, 0, 0, 0,
120, 0, 0, 0, 2, 0,
63, 0, 1, 0, 254, 0,
132, 0, 0, 0, 0, 0,
0, 0, 148, 0, 0, 0,
2, 0, 0, 0, 4, 0,
2, 0, 168, 0, 0, 0,
0, 0, 0, 0, 67, 111,
108, 111, 114, 77, 117, 108,
116, 105, 112, 108, 121, 0,
171, 171, 1, 0, 3, 0,
1, 0, 4, 0, 1, 0,
0, 0, 0, 0, 0, 0,
70, 105, 120, 79, 102, 102,
115, 101, 116, 0, 171, 171,
1, 0, 3, 0, 1, 0,
2, 0, 1, 0, 0, 0,
0, 0, 0, 0, 87, 111,
114, 108, 100, 86, 105, 101,
119, 80, 114, 111, 106, 101,
99, 116, 105, 111, 110, 0,
3, 0, 3, 0, 4, 0,
4, 0, 1, 0, 0, 0,
0, 0, 0, 0, 118, 115,
95, 49, 95, 49, 0, 77,
105, 99, 114, 111, 115, 111,
102, 116, 32, 40, 82, 41,
32, 72, 76, 83, 76, 32,
83, 104, 97, 100, 101, 114,
32, 67, 111, 109, 112, 105,
108, 101, 114, 32, 49, 48,
46, 49, 0, 171, 31, 0,
0, 0, 0, 0, 0, 128,
0, 0, 15, 144, 31, 0,
0, 0, 10, 0, 0, 128,
1, 0, 15, 144, 31, 0,
0, 0, 5, 0, 0, 128,
2, 0, 15, 144, 9, 0,
0, 0, 0, 0, 4, 192,
0, 0, 228, 144, 2, 0,
228, 160, 5, 0, 0, 0,
0, 0, 15, 208, 1, 0,
228, 144, 4, 0, 228, 160,
9, 0, 0, 0, 0, 0,
1, 128, 0, 0, 228, 144,
0, 0, 228, 160, 9, 0,
0, 0, 0, 0, 2, 128,
0, 0, 228, 144, 1, 0,
228, 160, 9, 0, 0, 0,
0, 0, 4, 128, 0, 0,
228, 144, 3, 0, 228, 160,
4, 0, 0, 0, 0, 0,
3, 192, 63, 0, 228, 160,
0, 0, 170, 128, 0, 0,
228, 128, 1, 0, 0, 0,
0, 0, 8, 192, 0, 0,
170, 128, 1, 0, 0, 0,
0, 0, 3, 224, 2, 0,
228, 144, 255, 255, 0, 0
};

View File

@@ -0,0 +1,40 @@
/*
* original shader
* vs.1.1 //Shader version 1.1
* dcl_position v0;
* dcl_color v1;
* dcl_texcoord0 v2;
* m4x4 oPos, v0, c0
* mul oD0, v1, c4
* mov oT0.xy, v2
*
* build command
* fxc.exe /Vi vertex-shader.hlsl /Fh vertex-shader.h /T vs_1_1 /E vs_main
*/
float4x4 WorldViewProjection : register(c0);
float4 ColorMultiply : register(c4);
float2 FixOffset : register(c63);
struct VS {
float4 Position : POSITION; // dcl_position v0;
float4 Color : COLOR; // dcl_color v1;
float2 TexCoord : TEXCOORD0; // dcl_texcoord0 v2;
};
VS vs_main(VS input)
{
VS output;
output.Position = mul(input.Position, WorldViewProjection); // m4x4 oPos, v0, c0
output.Color.x = mul(input.Color.x, ColorMultiply.x); // mul oD0, v1, c4
output.Color.y = mul(input.Color.y, ColorMultiply.y);
output.Color.z = mul(input.Color.z, ColorMultiply.z);
output.Color.w = mul(input.Color.w, ColorMultiply.w);
output.TexCoord = input.TexCoord; // mov oT0.xy, v2
// fix diagonal tearing
output.Position.xy += FixOffset.xy * output.Position.w;
return output;
}

View File

@@ -0,0 +1,26 @@
avsdlls += iidxhook4-cn
ldflags_iidxhook4-cn := \
-liphlpapi \
deplibs_iidxhook4-cn := \
avs \
libs_iidxhook4-cn := \
iidxhook-util \
ezusb-emu \
ezusb2-emu \
ezusb2-iidx-emu \
ezusb-iidx-emu \
security \
hook \
hooklib \
iidxio \
cconfig \
util \
ezusb \
src_iidxhook4-cn := \
avs-boot.c \
path.c \
dllmain.c \

View File

@@ -0,0 +1,103 @@
#define LOG_MODULE "avs-boot"
#include <stdint.h>
#include <string.h>
#include "hook/table.h"
#include "imports/avs.h"
#include "iidxhook4-cn/avs-boot.h"
#include "util/log.h"
static void (*real_avs_boot)(
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context);
static void my_avs_boot(
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context);
static const struct hook_symbol iidxhook4_cn_log_hook_syms[] = {
{.name = "avs_boot",
.patch = my_avs_boot,
.link = (void **) &real_avs_boot},
};
static void avs_boot_replace_property_uint32(
struct property_node *node, const char *name, uint32_t val)
{
struct property_node *tmp;
tmp = property_search(NULL, node, name);
if (tmp) {
property_node_remove(tmp);
}
property_node_create(NULL, node, PSMAP_TYPE_U32, name, val);
}
static void avs_boot_replace_property_str(
struct property_node *node, const char *name, const char *val)
{
struct property_node *tmp;
tmp = property_search(NULL, node, name);
if (tmp) {
property_node_remove(tmp);
}
tmp = property_node_create(NULL, node, PROPERTY_TYPE_STR, name, val);
if (tmp) {
property_node_datasize(tmp);
}
}
static void my_avs_boot(
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context)
{
log_info("Called my_avs_boot");
avs_boot_replace_property_uint32(config, "log/level", 4);
avs_boot_replace_property_str(config, "fs/root/device", ".");
real_avs_boot(
config,
std_heap,
sz_std_heap,
avs_heap,
sz_avs_heap,
log_writer_debug,
NULL);
}
void iidxhook4_cn_avs_boot_init()
{
hook_table_apply(
NULL,
"libavs-win32.dll",
iidxhook4_cn_log_hook_syms,
lengthof(iidxhook4_cn_log_hook_syms));
log_info("Inserted avs log hooks");
}

View File

@@ -0,0 +1,10 @@
#ifndef IIDXHOOK4_CN_AVS_BOOT_H
#define IIDXHOOK4_CN_AVS_BOOT_H
/**
* Initialize hooking of avs_boot. This re-enables avs logging
* and injects a few important settings.
*/
void iidxhook4_cn_avs_boot_init();
#endif

View File

@@ -0,0 +1,224 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bemanitools/iidxio.h"
#include "cconfig/cconfig-hook.h"
#include "ezusb-iidx-emu/node-security-plug.h"
#include "ezusb2-emu/desc.h"
#include "ezusb2-emu/device.h"
#include "ezusb2-iidx-emu/msg.h"
#include "hook/table.h"
#include "hooklib/acp.h"
#include "hooklib/setupapi.h"
#include "iidxhook4-cn/avs-boot.h"
#include "iidxhook4-cn/path.h"
#include "iidxhook-util/chart-patch.h"
#include "iidxhook-util/config-eamuse.h"
#include "iidxhook-util/config-gfx.h"
#include "iidxhook-util/config-io.h"
#include "iidxhook-util/config-sec.h"
#include "iidxhook-util/d3d9.h"
#include "iidxhook-util/settings.h"
#include "security/rp-sign-key.h"
#include "imports/avs.h"
#include "util/log.h"
#define IIDXHOOK4_CN_INFO_HEADER \
"iidxhook for Resort Anthem CN" \
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)
#define IIDXHOOK4_CN_CMD_USAGE \
"Usage: inject.exe iidxhook4-cn.dll <bm2dx.exe> [options...]"
static HANDLE STDCALL my_OpenProcess(DWORD, BOOL, DWORD);
static HANDLE(STDCALL *real_OpenProcess)(DWORD, BOOL, DWORD);
static bool iidxhook_init_check;
static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = {
iidxhook_util_d3d9_irp_handler,
};
static const struct hook_symbol init_hook_syms[] = {
{.name = "OpenProcess",
.patch = my_OpenProcess,
.link = (void **) &real_OpenProcess},
};
static struct iidxhook_config_io config_io;
static void
iidxhook4_cn_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
{
struct iidxhook_util_d3d9_config d3d9_config;
iidxhook_util_d3d9_init_config(&d3d9_config);
d3d9_config.windowed = config_gfx->windowed;
d3d9_config.framed = config_gfx->framed;
d3d9_config.override_window_width = config_gfx->window_width;
d3d9_config.override_window_height = config_gfx->window_height;
d3d9_config.framerate_limit = config_gfx->frame_rate_limit;
d3d9_config.pci_vid = config_gfx->pci_id_vid;
d3d9_config.pci_pid = config_gfx->pci_id_pid;
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;
d3d9_config.iidx18_and_19_diagonal_tearing_fix = config_gfx->diagonal_tearing_fix;
d3d9_config.iidx14_to_19_nvidia_fix = true;
d3d9_config.iidx18_and_19_diagonal_tearing_fix = config_gfx->diagonal_tearing_fix;
if (config_gfx->monitor_check == 0) {
log_info("Auto monitor check enabled");
d3d9_config.iidx09_to_19_monitor_check_cb =
iidxhook_util_chart_patch_set_refresh_rate;
iidxhook_util_chart_patch_init(
IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_18_VGA);
} else if (config_gfx->monitor_check > 0) {
log_info(
"Manual monitor check, resulting refresh rate: %f",
config_gfx->monitor_check);
iidxhook_util_chart_patch_init(
IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_18_VGA);
iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check);
}
iidxhook_util_d3d9_configure(&d3d9_config);
hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers));
}
/**
* This seems to be a good entry point to intercept
* before the game calls anything important
*/
static HANDLE STDCALL
my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
struct cconfig *config;
struct iidxhook_util_config_eamuse config_eamuse;
struct iidxhook_config_gfx config_gfx;
struct iidxhook_config_sec config_sec;
if (iidxhook_init_check) {
return real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
}
iidxhook_init_check = true;
log_info("-------------------------------------------------------------");
log_info("--------------- Begin iidxhook my_OpenProcess ---------------");
log_info("-------------------------------------------------------------");
config = cconfig_init();
iidxhook_util_config_eamuse_init(config);
iidxhook_config_gfx_init(config);
iidxhook_config_io_init(config);
iidxhook_config_sec_init(config);
if (!cconfig_hook_config_init(
config,
IIDXHOOK4_CN_INFO_HEADER "\n" IIDXHOOK4_CN_CMD_USAGE,
CCONFIG_CMD_USAGE_OUT_DBG)) {
cconfig_finit(config);
exit(EXIT_FAILURE);
}
iidxhook_util_config_eamuse_get(&config_eamuse, config);
iidxhook_config_gfx_get(&config_gfx, config);
iidxhook_config_io_get(&config_io, config);
iidxhook_config_sec_get(&config_sec, config);
cconfig_finit(config);
log_info(IIDXHOOK4_CN_INFO_HEADER);
log_info("Initializing iidxhook...");
/**
* This game is using a black round plug for game license management instead of a black usb dongle.
* No white dongle hooks applies since the game does not have network functionality.
* Also, card readers are not used/checked; no card reader hooks required.
*/
ezusb_iidx_emu_node_security_plug_set_boot_version(
&config_sec.boot_version);
ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds);
ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key(
&security_rp_sign_key_black_iidx);
ezusb_iidx_emu_node_security_plug_set_plug_black_mcode(
&config_sec.black_plug_mcode);
ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid);
iidxhook4_cn_setup_d3d9_hooks(&config_gfx);
if (!config_io.disable_io_emu) {
log_info("Starting IIDX IO backend");
iidx_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
if (!iidx_io_init(
avs_thread_create, avs_thread_join, avs_thread_destroy)) {
log_fatal("Initializing IIDX IO backend failed");
}
} else {
log_info("IIDX IO emulation backend disabled");
}
/* Set up IO emulation hooks _after_ IO API setup to allow
API implementations with real IO devices */
iohook_push_handler(ezusb2_emu_device_dispatch_irp);
iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp);
iohook_push_handler(settings_hook_dispatch_irp);
if (!config_io.disable_io_emu) {
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
}
log_info("-------------------------------------------------------------");
log_info("---------------- End iidxhook my_OpenProcess ----------------");
log_info("-------------------------------------------------------------");
return real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
}
/**
* Hook library for Resort Anthem CN
*/
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{
if (reason != DLL_PROCESS_ATTACH) {
return TRUE;
}
log_to_writer(log_writer_debug, NULL);
hook_table_apply(
NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms));
iidxhook4_cn_path_init();
iidxhook4_cn_avs_boot_init();
acp_hook_init();
settings_hook_init();
return TRUE;
}

View File

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

View File

@@ -0,0 +1,156 @@
#define LOG_MODULE "path"
#include <windows.h>
#include <stdint.h>
#include <string.h>
#include "hook/table.h"
#include "iidxhook4-cn/path.h"
#include "util/log.h"
#include "util/str.h"
#define PATH_A "D:/JDZ-001/contents/"
#define PATH_W L"D:/JDZ-001/contents/"
static HANDLE WINAPI my_CreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static HANDLE(WINAPI *real_CreateFileA)(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static HANDLE WINAPI my_CreateFileW(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static HANDLE(WINAPI *real_CreateFileW)(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static HANDLE WINAPI my_FindFirstFileA(
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData);
static HANDLE(WINAPI *real_FindFirstFileA)(
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData);
static const struct hook_symbol iidxhook4_cn_path_hook_syms[] = {
{.name = "CreateFileA",
.patch = my_CreateFileA,
.link = (void **) &real_CreateFileA},
{.name = "CreateFileW",
.patch = my_CreateFileW,
.link = (void **) &real_CreateFileW},
{.name = "FindFirstFileA",
.patch = my_FindFirstFileA,
.link = (void **) &real_FindFirstFileA},
};
static HANDLE WINAPI my_CreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if (lpFileName != NULL && strstr(lpFileName, PATH_A) == lpFileName) {
char relative_path[MAX_PATH] = ".";
str_cat(relative_path, MAX_PATH, lpFileName + strlen(PATH_A) - 1);
return real_CreateFileA(
relative_path,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
return real_CreateFileA(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
static HANDLE WINAPI my_CreateFileW(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if (lpFileName != NULL && wcsstr(lpFileName, PATH_W) == lpFileName) {
wchar_t relative_path[MAX_PATH] = L".";
wstr_cat(relative_path, MAX_PATH, lpFileName + wcslen(PATH_W) - 1);
return real_CreateFileW(
relative_path,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
return real_CreateFileW(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
static HANDLE WINAPI my_FindFirstFileA(
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData)
{
if (lpFileName != NULL && strstr(lpFileName, PATH_A) == lpFileName) {
char relative_path[MAX_PATH] = ".";
str_cat(relative_path, MAX_PATH, lpFileName + strlen(PATH_A) - 1);
return real_FindFirstFileA(relative_path, lpFindFileData);
}
return real_FindFirstFileA(lpFileName, lpFindFileData);
}
void iidxhook4_cn_path_init()
{
hook_table_apply(
NULL,
"kernel32.dll",
iidxhook4_cn_path_hook_syms,
lengthof(iidxhook4_cn_path_hook_syms));
log_info("Inserted path hooks");
}

View File

@@ -0,0 +1,6 @@
#ifndef IIDXHOOK4_CN_PATH_H
#define IIDXHOOK4_CN_PATH_H
void iidxhook4_cn_path_init();
#endif

View File

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

View File

@@ -0,0 +1,26 @@
avsdlls += iidxhook5-cn
ldflags_iidxhook5-cn := \
-liphlpapi \
deplibs_iidxhook5-cn := \
avs \
libs_iidxhook5-cn := \
iidxhook-util \
ezusb-emu \
ezusb2-emu \
ezusb2-iidx-emu \
ezusb-iidx-emu \
security \
hook \
hooklib \
iidxio \
cconfig \
util \
ezusb \
src_iidxhook5-cn := \
avs-boot.c \
path.c \
dllmain.c \

View File

@@ -0,0 +1,103 @@
#define LOG_MODULE "avs-boot"
#include <stdint.h>
#include <string.h>
#include "hook/table.h"
#include "imports/avs.h"
#include "iidxhook5-cn/avs-boot.h"
#include "util/log.h"
static void (*real_avs_boot)(
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context);
static void my_avs_boot(
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context);
static const struct hook_symbol iidxhook5_cn_log_hook_syms[] = {
{.name = "XC058ba50000f4",
.patch = my_avs_boot,
.link = (void **) &real_avs_boot},
};
static void avs_boot_replace_property_uint32(
struct property_node *node, const char *name, uint32_t val)
{
struct property_node *tmp;
tmp = property_search(NULL, node, name);
if (tmp) {
property_node_remove(tmp);
}
property_node_create(NULL, node, PSMAP_TYPE_U32, name, val);
}
static void avs_boot_replace_property_str(
struct property_node *node, const char *name, const char *val)
{
struct property_node *tmp;
tmp = property_search(NULL, node, name);
if (tmp) {
property_node_remove(tmp);
}
tmp = property_node_create(NULL, node, PROPERTY_TYPE_STR, name, val);
if (tmp) {
property_node_datasize(tmp);
}
}
static void my_avs_boot(
struct property_node *config,
void *std_heap,
size_t sz_std_heap,
void *avs_heap,
size_t sz_avs_heap,
avs_log_writer_t log_writer,
void *log_context)
{
log_info("Called my_avs_boot");
avs_boot_replace_property_uint32(config, "log/level", 4);
avs_boot_replace_property_str(config, "fs/root/device", ".");
real_avs_boot(
config,
std_heap,
sz_std_heap,
avs_heap,
sz_avs_heap,
log_writer_debug,
NULL);
}
void iidxhook5_cn_avs_boot_init()
{
hook_table_apply(
NULL,
"libavs-win32.dll",
iidxhook5_cn_log_hook_syms,
lengthof(iidxhook5_cn_log_hook_syms));
log_info("Inserted avs log hooks");
}

View File

@@ -0,0 +1,10 @@
#ifndef IIDXHOOK5_CN_AVS_BOOT_H
#define IIDXHOOK5_CN_AVS_BOOT_H
/**
* Initialize hooking of avs_boot. This re-enables avs logging
* and injects a few important settings.
*/
void iidxhook5_cn_avs_boot_init();
#endif

View File

@@ -0,0 +1,207 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bemanitools/iidxio.h"
#include "cconfig/cconfig-hook.h"
#include "ezusb-iidx-emu/node-security-plug.h"
#include "ezusb2-emu/desc.h"
#include "ezusb2-emu/device.h"
#include "ezusb2-iidx-emu/msg.h"
#include "hook/d3d9.h"
#include "hook/table.h"
#include "hooklib/acp.h"
#include "hooklib/setupapi.h"
#include "iidxhook5-cn/avs-boot.h"
#include "iidxhook5-cn/path.h"
#include "iidxhook-util/config-eamuse.h"
#include "iidxhook-util/config-gfx.h"
#include "iidxhook-util/config-io.h"
#include "iidxhook-util/config-sec.h"
#include "iidxhook-util/d3d9.h"
#include "iidxhook-util/settings.h"
#include "security/rp-sign-key.h"
#include "imports/avs.h"
#include "util/log.h"
#define IIDXHOOK5_CN_INFO_HEADER \
"iidxhook for tricoro CN" \
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)
#define IIDXHOOK5_CN_CMD_USAGE \
"Usage: inject.exe iidxhook5-cn.dll <bm2dx.exe> [options...]"
static ATOM WINAPI my_RegisterClassA(const WNDCLASSA *lpWndClass);
static ATOM(WINAPI *real_RegisterClassA)(const WNDCLASSA *lpWndClass);
static bool iidxhook_init_check;
static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = {
iidxhook_util_d3d9_irp_handler,
};
static const struct hook_symbol init_hook_user32_syms[] = {
{.name = "RegisterClassA",
.patch = my_RegisterClassA,
.link = (void **) &real_RegisterClassA},
};
static struct iidxhook_config_io config_io;
static void
iidxhook5_cn_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
{
struct iidxhook_util_d3d9_config d3d9_config;
iidxhook_util_d3d9_init_config(&d3d9_config);
d3d9_config.windowed = config_gfx->windowed;
d3d9_config.framed = config_gfx->framed;
d3d9_config.override_window_width = config_gfx->window_width;
d3d9_config.override_window_height = config_gfx->window_height;
d3d9_config.framerate_limit = config_gfx->frame_rate_limit;
d3d9_config.pci_vid = config_gfx->pci_id_vid;
d3d9_config.pci_pid = config_gfx->pci_id_pid;
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;
d3d9_config.iidx14_to_19_nvidia_fix = true;
d3d9_config.iidx18_and_19_diagonal_tearing_fix = config_gfx->diagonal_tearing_fix;
iidxhook_util_d3d9_configure(&d3d9_config);
hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers));
}
/**
* OpenProcess is basically used for hooks in exe games,
* but since it does not exist in this game, RegisterClassA is used instead.
*/
static ATOM WINAPI my_RegisterClassA(const WNDCLASSA *lpWndClass)
{
struct cconfig *config;
struct iidxhook_util_config_eamuse config_eamuse;
struct iidxhook_config_gfx config_gfx;
struct iidxhook_config_sec config_sec;
if (iidxhook_init_check) {
return real_RegisterClassA(lpWndClass);
}
iidxhook_init_check = true;
log_info("-------------------------------------------------------------");
log_info("------------- Begin iidxhook my_RegisterClassA --------------");
log_info("-------------------------------------------------------------");
config = cconfig_init();
iidxhook_util_config_eamuse_init(config);
iidxhook_config_gfx_init(config);
iidxhook_config_io_init(config);
iidxhook_config_sec_init(config);
if (!cconfig_hook_config_init(
config,
IIDXHOOK5_CN_INFO_HEADER "\n" IIDXHOOK5_CN_CMD_USAGE,
CCONFIG_CMD_USAGE_OUT_DBG)) {
cconfig_finit(config);
exit(EXIT_FAILURE);
}
iidxhook_util_config_eamuse_get(&config_eamuse, config);
iidxhook_config_gfx_get(&config_gfx, config);
iidxhook_config_io_get(&config_io, config);
iidxhook_config_sec_get(&config_sec, config);
cconfig_finit(config);
log_info(IIDXHOOK5_CN_INFO_HEADER);
log_info("Initializing iidxhook...");
/**
* This game is using a black round plug for game license management instead of a black usb dongle.
* No white dongle hooks applies since the game does not have network functionality.
* Also, card readers are not used/checked; no card reader hooks required.
*/
ezusb_iidx_emu_node_security_plug_set_boot_version(
&config_sec.boot_version);
ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds);
ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key(
&security_rp_sign_key_black_iidx);
ezusb_iidx_emu_node_security_plug_set_plug_black_mcode(
&config_sec.black_plug_mcode);
ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid);
iidxhook5_cn_setup_d3d9_hooks(&config_gfx);
if (!config_io.disable_io_emu) {
log_info("Starting IIDX IO backend");
iidx_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
if (!iidx_io_init(
avs_thread_create, avs_thread_join, avs_thread_destroy)) {
log_fatal("Initializing IIDX IO backend failed");
}
} else {
log_info("IIDX IO emulation backend disabled");
}
/* Set up IO emulation hooks _after_ IO API setup to allow
API implementations with real IO devices */
iohook_push_handler(ezusb2_emu_device_dispatch_irp);
iohook_push_handler(settings_hook_dispatch_irp);
if (!config_io.disable_io_emu) {
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
}
log_info("-------------------------------------------------------------");
log_info("-------------- End iidxhook my_RegisterClassA ---------------");
log_info("-------------------------------------------------------------");
return real_RegisterClassA(lpWndClass);
}
/**
* Hook library for tricoro CN
*/
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{
if (reason != DLL_PROCESS_ATTACH) {
return TRUE;
}
log_to_writer(log_writer_debug, NULL);
hook_table_apply(
NULL,
"user32.dll",
init_hook_user32_syms,
lengthof(init_hook_user32_syms));
iidxhook5_cn_path_init();
iidxhook5_cn_avs_boot_init();
acp_hook_init();
settings_hook_init();
return TRUE;
}

View File

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

View File

@@ -0,0 +1,104 @@
#define LOG_MODULE "path"
#include <windows.h>
#include <stdint.h>
#include <string.h>
#include "hook/table.h"
#include "iidxhook5-cn/path.h"
#include "util/log.h"
#include "util/str.h"
#define PATH_A "D:/JDZ-001/contents/"
#define PATH_W L"D:/JDZ-001/contents/"
static HANDLE WINAPI my_CreateFileW(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static HANDLE(WINAPI *real_CreateFileW)(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static HANDLE WINAPI my_FindFirstFileA(
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData);
static HANDLE(WINAPI *real_FindFirstFileA)(
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData);
static const struct hook_symbol iidxhook5_cn_path_hook_syms[] = {
{.name = "CreateFileW",
.patch = my_CreateFileW,
.link = (void **) &real_CreateFileW},
{.name = "FindFirstFileA",
.patch = my_FindFirstFileA,
.link = (void **) &real_FindFirstFileA},
};
static HANDLE WINAPI my_CreateFileW(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
if (lpFileName != NULL && wcsstr(lpFileName, PATH_W) == lpFileName) {
wchar_t relative[MAX_PATH] = L".";
wstr_cat(relative, MAX_PATH, lpFileName + wcslen(PATH_W) - 1);
return real_CreateFileW(
relative,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
return real_CreateFileW(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
static HANDLE WINAPI my_FindFirstFileA(
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData)
{
if (lpFileName != NULL && strstr(lpFileName, PATH_A) == lpFileName) {
char relative[MAX_PATH] = ".";
str_cat(relative, MAX_PATH, lpFileName + strlen(PATH_A) - 1);
return real_FindFirstFileA(relative, lpFindFileData);
}
return real_FindFirstFileA(lpFileName, lpFindFileData);
}
void iidxhook5_cn_path_init()
{
hook_table_apply(
NULL,
"kernel32.dll",
iidxhook5_cn_path_hook_syms,
lengthof(iidxhook5_cn_path_hook_syms));
log_info("Inserted path hooks");
}

View File

@@ -0,0 +1,6 @@
#ifndef IIDXHOOK5_CN_PATH_H
#define IIDXHOOK5_CN_PATH_H
void iidxhook5_cn_path_init();
#endif

View File

@@ -69,6 +69,8 @@ iidxhook5_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter;
d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate;
d3d9_config.device_adapter = config_gfx->device_adapter; d3d9_config.device_adapter = config_gfx->device_adapter;
d3d9_config.iidx14_to_19_nvidia_fix = true;
d3d9_config.iidx18_and_19_diagonal_tearing_fix = config_gfx->diagonal_tearing_fix;
iidxhook_util_d3d9_configure(&d3d9_config); iidxhook_util_d3d9_configure(&d3d9_config);

View File

@@ -8,8 +8,8 @@ libs_inject := \
util \ util \
src_inject := \ src_inject := \
main.c \
debugger.c \ debugger.c \
logger.c \ logger.c \
main.c \
options.c \ options.c \
version.c \ version.c \

View File

@@ -16,6 +16,8 @@
#include "util/signal.h" #include "util/signal.h"
#include "util/str.h" #include "util/str.h"
#define MM_ALLOCATION_GRANULARITY 0x10000
struct debugger_thread_params { struct debugger_thread_params {
const char *app_name; const char *app_name;
char *cmd_line; char *cmd_line;
@@ -27,6 +29,14 @@ static HANDLE debugger_ready_event;
static PROCESS_INFORMATION pi; static PROCESS_INFORMATION pi;
static PVOID load_nt_header_from_process(HANDLE hProcess,
HMODULE hModule,
PIMAGE_NT_HEADERS32 pNtHeader);
static HMODULE enumerate_modules_in_process(HANDLE hProcess,
HMODULE hModuleLast,
PIMAGE_NT_HEADERS32 pNtHeader);
// Source: // Source:
// https://docs.microsoft.com/en-us/windows/win32/memory/obtaining-a-file-name-from-a-file-handle // https://docs.microsoft.com/en-us/windows/win32/memory/obtaining-a-file-name-from-a-file-handle
static bool static bool
@@ -548,6 +558,156 @@ alloc_fail:
return false; return false;
} }
HRESULT debugger_pe_patch_remote(HANDLE hProcess, void *dest, const void *src, size_t nbytes)
{
DWORD old_protect;
BOOL ok;
log_assert(dest != NULL);
log_assert(src != NULL);
ok = VirtualProtectEx(
hProcess,
dest,
nbytes,
PAGE_EXECUTE_READWRITE,
&old_protect);
if (!ok) {
return HRESULT_FROM_WIN32(GetLastError());
}
ok = WriteProcessMemory(
hProcess, dest, src, nbytes, NULL);
if (!ok) {
return HRESULT_FROM_WIN32(GetLastError());
}
ok = VirtualProtectEx(
hProcess,
dest,
nbytes,
old_protect,
&old_protect);
if (!ok) {
return HRESULT_FROM_WIN32(GetLastError());
}
return S_OK;
}
bool debugger_replace_dll_iat(const char *expected_dll, const char *replacement_path_dll)
{
log_assert(expected_dll);
log_assert(replacement_path_dll);
HMODULE hModule = NULL;
HMODULE hLast = NULL;
void *remote_addr;
// Find EXE base in process memory
IMAGE_NT_HEADERS inh;
for (;;) {
memset(&inh, 0, sizeof(IMAGE_NT_HEADERS));
if ((hLast = enumerate_modules_in_process(pi.hProcess, hLast, &inh)) == NULL) {
break;
}
if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
hModule = hLast;
break;
}
}
if (hModule == NULL) {
log_warning("Couldn't find target EXE for hooking");
goto inject_fail;
}
// Search through import table if it exists and replace the target DLL with our DLL filename
PBYTE pbModule = (PBYTE)hModule;
PIMAGE_SECTION_HEADER pRemoteSectionHeaders
= (PIMAGE_SECTION_HEADER)((PBYTE)pbModule
+ sizeof(inh.Signature)
+ sizeof(inh.FileHeader)
+ inh.FileHeader.SizeOfOptionalHeader);
size_t total_size = inh.OptionalHeader.SizeOfHeaders;
IMAGE_SECTION_HEADER header;
for (DWORD n = 0; n < inh.FileHeader.NumberOfSections; ++n) {
if (!ReadProcessMemory(pi.hProcess, pRemoteSectionHeaders + n, &header, sizeof(header), NULL)) {
log_warning("Couldn't read section header: %lu", GetLastError());
goto inject_fail;
}
size_t new_total_size = header.VirtualAddress + header.Misc.VirtualSize;
if (new_total_size > total_size)
total_size = new_total_size;
}
remote_addr = VirtualAllocEx(
pi.hProcess,
pbModule + total_size + MM_ALLOCATION_GRANULARITY,
strlen(replacement_path_dll) + 1,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
log_assert(remote_addr != NULL);
debugger_pe_patch_remote(
pi.hProcess, remote_addr, replacement_path_dll, strlen(replacement_path_dll));
if (inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress != 0) {
PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule
+ inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
DWORD size = 0;
while (inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0
|| size < inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) {
IMAGE_IMPORT_DESCRIPTOR ImageImport;
if (!ReadProcessMemory(pi.hProcess, pImageImport, &ImageImport, sizeof(ImageImport), NULL)) {
log_warning("Couldn't read import: %lu", GetLastError());
goto inject_fail;
}
if (ImageImport.Name == 0) {
break;
}
char name[MAX_PATH] = {0};
if (ReadProcessMemory(pi.hProcess, pbModule + ImageImport.Name, name, sizeof(name), NULL)) {
// log_misc("\tImport DLL: %ld %s", ImageImport.Name, name);
if (strcmp(name, expected_dll) == 0) {
//log_misc("Replacing %s with %s", name, replacement_path_dll, (void*)pImageImport);
ImageImport.Name = (DWORD)((PBYTE)remote_addr - pbModule);
debugger_pe_patch_remote(
pi.hProcess,
pImageImport,
&ImageImport,
sizeof(ImageImport));
}
}
pImageImport++;
size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
}
} else {
log_warning("Couldn't find import table, can't hook DLL\n");
goto inject_fail;
}
return true;
inject_fail:
return false;
}
bool debugger_resume_process() bool debugger_resume_process()
{ {
log_info("Resuming remote process..."); log_info("Resuming remote process...");
@@ -593,3 +753,90 @@ void debugger_finit(bool failure)
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
} }
// Helper functions based on Microsoft Detours
static PVOID load_nt_header_from_process(HANDLE hProcess,
HMODULE hModule,
PIMAGE_NT_HEADERS32 pNtHeader)
{
PBYTE pbModule = (PBYTE)hModule;
memset(pNtHeader, 0, sizeof(*pNtHeader));
if (pbModule == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) {
return NULL;
}
IMAGE_DOS_HEADER idh;
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
log_warning("Could not read DOS header: %lu", GetLastError());
return NULL;
}
if (idh.e_magic != IMAGE_DOS_SIGNATURE ||
(DWORD)idh.e_lfanew > mbi.RegionSize ||
(DWORD)idh.e_lfanew < sizeof(idh)) {
return NULL;
}
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew,
pNtHeader, sizeof(*pNtHeader), NULL)) {
log_warning("Could not read NT header: %lu", GetLastError());
return NULL;
}
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
return NULL;
}
return pbModule + idh.e_lfanew;
}
static HMODULE enumerate_modules_in_process(HANDLE hProcess,
HMODULE hModuleLast,
PIMAGE_NT_HEADERS32 pNtHeader)
{
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
memset(pNtHeader, 0, sizeof(*pNtHeader));
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
// Find the next memory region that contains a mapped PE image.
for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) == 0) {
break;
}
// Usermode address space has such an unaligned region size always at the
// end and only at the end.
if ((mbi.RegionSize & 0xfff) == 0xfff) {
break;
}
if (((PBYTE)mbi.BaseAddress + mbi.RegionSize) < pbLast) {
break;
}
// Skip uncommitted regions and guard pages.
if ((mbi.State != MEM_COMMIT) ||
((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
(mbi.Protect & PAGE_GUARD)) {
continue;
}
if (load_nt_header_from_process(hProcess, (HMODULE)pbLast, pNtHeader)) {
return (HMODULE)pbLast;
}
}
return NULL;
}

View File

@@ -5,11 +5,11 @@
/** /**
* Initialize inject's logger backend. * Initialize inject's logger backend.
* *
* This takes care of hooking and merging the different log * This takes care of hooking and merging the different log
* streams, e.g. inject's local logging and inject's debugger * streams, e.g. inject's local logging and inject's debugger
* receiving remote logging events. * receiving remote logging events.
* *
* @param log_file_path Path to the file to log to or NULL to * @param log_file_path Path to the file to log to or NULL to
* disable. * disable.
*/ */
@@ -17,21 +17,21 @@
/** /**
* Initialize the debugger. * Initialize the debugger.
* *
* This creates the remote process of the provided application. * This creates the remote process of the provided application.
* *
* The remote process is created suspended. This allows you to * The remote process is created suspended. This allows you to
* to some more process setup tasks like injecting hook DLLs * to some more process setup tasks like injecting hook DLLs
* before you call debugger_resume_process to actually start * before you call debugger_resume_process to actually start
* execution of it. * execution of it.
* *
* The actual debugging runs in a dedicated thread which spawns * The actual debugging runs in a dedicated thread which spawns
* the process, waits for and dispatches debug events. * the process, waits for and dispatches debug events.
* *
* However, if you want to attach a remote debugger, you have to * However, if you want to attach a remote debugger, you have to
* set the parameter local_debugger to false. Then, the debugger * set the parameter local_debugger to false. Then, the debugger
* will only create the remote process and monitor it. * will only create the remote process and monitor it.
* *
* @param local_debugger True to attach inject's local debugger, * @param local_debugger True to attach inject's local debugger,
* false to allow attaching a remote * false to allow attaching a remote
* debugger with enhanced features. * debugger with enhanced features.
@@ -44,18 +44,28 @@ bool debugger_init(bool local_debugger, const char *app_name, char *cmd_line);
/** /**
* Inject a DLL into the remote process. * Inject a DLL into the remote process.
* *
* @param path_dll Path to the dll to inject. * @param path_dll Path to the dll to inject.
* @return true if sucessful, false on error. * @return true if sucessful, false on error.
*/ */
bool debugger_inject_dll(const char *path_dll); bool debugger_inject_dll(const char *path_dll);
/**
* Inject a DLL into the remote process by replacing its reference in
* the import table.
*
* @param expected_dll Name of dll to override.
* @param replacement_path_dll Name of dll to inject.
* @return true if sucessful, false on error.
*/
bool debugger_replace_dll_iat(const char *expected_dll, const char *replacement_path_dll);
/** /**
* Wait/block for a remote debugger to attach to the remote process. * Wait/block for a remote debugger to attach to the remote process.
* *
* You only need to call this if you specified local_debugger = false * You only need to call this if you specified local_debugger = false
* on debugger_init. * on debugger_init.
* *
* @return True if successfull and a remote debugger attached, false * @return True if successfull and a remote debugger attached, false
* on error. * on error.
*/ */
@@ -63,21 +73,21 @@ bool debugger_wait_for_remote_debugger();
/** /**
* Resume the remote process. * Resume the remote process.
* *
* Make sure to call this once you are done with setting it up. * Make sure to call this once you are done with setting it up.
* *
* @return true on success, false on error. * @return true on success, false on error.
*/ */
bool debugger_resume_process(); bool debugger_resume_process();
/** /**
* Wait for the remote process to exit. * Wait for the remote process to exit.
*/ */
void debugger_wait_process_exit(); void debugger_wait_process_exit();
/** /**
* Cleanup the debugger. * Cleanup the debugger.
* *
* @param failure Set this to true if you have to cleanup due to * @param failure Set this to true if you have to cleanup due to
* a failure of another debugger function call. * a failure of another debugger function call.
* Otherwise, set this to false. * Otherwise, set this to false.

View File

@@ -80,8 +80,15 @@ verify_hook_dlls_exist(int argc, char **argv, uint32_t hook_dll_count)
DWORD dll_path_length; DWORD dll_path_length;
for (uint32_t i = 0; i < hook_dll_count; i++) { for (uint32_t i = 0; i < hook_dll_count; i++) {
dll_path_length = char *iat_hook = strstr(argv[i + 1], "=");
SearchPath(NULL, argv[i + 1], NULL, MAX_PATH, dll_path, NULL);
if (iat_hook) {
dll_path_length =
SearchPath(NULL, iat_hook + 1, NULL, MAX_PATH, dll_path, NULL);
} else {
dll_path_length =
SearchPath(NULL, argv[i + 1], NULL, MAX_PATH, dll_path, NULL);
}
if (dll_path_length == 0) { if (dll_path_length == 0) {
log_warning( log_warning(
@@ -94,6 +101,26 @@ verify_hook_dlls_exist(int argc, char **argv, uint32_t hook_dll_count)
return true; return true;
} }
static bool inject_iat_hook_dlls(uint32_t hooks, char **argv)
{
log_assert(argv);
log_info("Injecting IAT hook DLLs...");
for (int i = 0; i < hooks; i++) {
char *iat_hook = strstr(argv[i + 1], "=");
if (!iat_hook)
continue;
*iat_hook = '\0';
debugger_replace_dll_iat(argv[i + 1], iat_hook+1);
*iat_hook = '=';
}
return true;
}
static bool inject_hook_dlls(uint32_t hooks, char **argv) static bool inject_hook_dlls(uint32_t hooks, char **argv)
{ {
log_assert(argv); log_assert(argv);
@@ -101,6 +128,11 @@ static bool inject_hook_dlls(uint32_t hooks, char **argv)
log_info("Injecting hook DLLs..."); log_info("Injecting hook DLLs...");
for (int i = 0; i < hooks; i++) { for (int i = 0; i < hooks; i++) {
char *iat_hook = strstr(argv[i + 1], "=");
if (iat_hook)
continue;
if (!debugger_inject_dll(argv[i + 1])) { if (!debugger_inject_dll(argv[i + 1])) {
return false; return false;
} }
@@ -155,6 +187,10 @@ int main(int argc, char **argv)
goto debugger_init_fail; goto debugger_init_fail;
} }
if (!inject_iat_hook_dlls(hooks, argv)) {
goto inject_hook_dlls_fail;
}
if (!inject_hook_dlls(hooks, argv)) { if (!inject_hook_dlls(hooks, argv)) {
goto inject_hook_dlls_fail; goto inject_hook_dlls_fail;
} }

View File

@@ -54,6 +54,8 @@ void options_print_usage(void)
"You can specify one or multiple hook.dll files, e.g. inject.exe " "You can specify one or multiple hook.dll files, e.g. inject.exe "
"hook1.dll hook2.dll app.exe" "hook1.dll hook2.dll app.exe"
"\n" "\n"
"An IAT replacement early injection can be specified using the syntax orig.dll=hook.dll"
"\n"
" The following options can be specified after the exe path:\n" " The following options can be specified after the exe path:\n"
"\n" "\n"
" -D Enable debugging output\n" " -D Enable debugging output\n"

View File

@@ -214,7 +214,11 @@ int main(int argc, const char **argv)
/* Load game DLL */ /* Load game DLL */
module_context_init(&module, options.module); if (options.iat_hook_dlls.nitems > 0) {
module_context_init_with_iat_hooks(&module, options.module, &options.iat_hook_dlls);
} else {
module_context_init(&module, options.module);
}
/* Load hook DLLs */ /* Load hook DLLs */

View File

@@ -1,94 +1,247 @@
#include <windows.h> #include <windows.h>
#include "imports/avs.h" #include "hook/pe.h"
#include "imports/eapki.h"
#include "imports/avs.h"
#include "launcher/module.h" #include "imports/eapki.h"
#include "util/log.h" #include "launcher/module.h"
#include "util/str.h"
#include "util/log.h"
void module_context_init(struct module_context *module, const char *path) #include "util/str.h"
{
log_assert(module != NULL); #define MM_ALLOCATION_GRANULARITY 0x10000
log_assert(path != NULL);
module->dll = LoadLibrary(path); static bool module_replace_dll_iat(HMODULE hModule, struct array *iat_hook_dlls)
{
if (module->dll == NULL) { log_assert(hModule);
LPSTR buffer; log_assert(iat_hook_dlls);
DWORD err = GetLastError();
if (iat_hook_dlls->nitems == 0)
FormatMessageA( return true;
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, PBYTE pbModule = (PBYTE)hModule;
NULL,
err, // Find EXE base in process memory
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *) pbModule;
(LPSTR) &buffer, IMAGE_NT_HEADERS *inh = (IMAGE_NT_HEADERS *) (pbModule + idh->e_lfanew);
0,
NULL); // Search through import table if it exists and replace the target DLL with our DLL filename
PIMAGE_SECTION_HEADER pRemoteSectionHeaders
if (err == ERROR_MOD_NOT_FOUND) { = (PIMAGE_SECTION_HEADER)((PBYTE)pbModule
log_warning("%s is likely missing dependencies", path); + sizeof(inh->Signature)
log_warning("Do you have vcredist/directx runtimes installed?"); + sizeof(inh->FileHeader)
} + inh->FileHeader.SizeOfOptionalHeader);
size_t total_size = inh->OptionalHeader.SizeOfHeaders;
log_fatal("%s: Failed to load game DLL: %s", path, buffer);
for (DWORD n = 0; n < inh->FileHeader.NumberOfSections; ++n) {
LocalFree(buffer); IMAGE_SECTION_HEADER *header = (IMAGE_SECTION_HEADER *)(pRemoteSectionHeaders + n);
} size_t new_total_size = header->VirtualAddress + header->Misc.VirtualSize;
if (new_total_size > total_size)
module->path = str_dup(path); total_size = new_total_size;
} }
bool module_context_invoke_init( void *remote_addr = NULL;
const struct module_context *module, size_t remote_addr_ptr = 0;
char *sidcode,
struct property_node *app_config) for (size_t i = 0; i < 10000 && remote_addr == NULL; i++) {
{ remote_addr = VirtualAlloc(
dll_entry_init_t init; pbModule + total_size + (MM_ALLOCATION_GRANULARITY * (i + 1)),
(MAX_PATH + 1) * iat_hook_dlls->nitems,
log_assert(module != NULL); MEM_RESERVE | MEM_COMMIT,
log_assert(sidcode != NULL); PAGE_READWRITE);
log_assert(app_config != NULL); }
init = (void *) GetProcAddress(module->dll, "dll_entry_init"); log_assert(remote_addr != NULL);
if (init == NULL) { if (inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress != 0) {
log_fatal( PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule
"%s: dll_entry_init not found. Is this a game DLL?", module->path); + inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
DWORD size = 0;
return init(sidcode, app_config); while (inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0
} || size < inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) {
IMAGE_IMPORT_DESCRIPTOR *ImageImport = (IMAGE_IMPORT_DESCRIPTOR *)pImageImport;
bool module_context_invoke_main(const struct module_context *module)
{ if (ImageImport->Name == 0) {
/* GCC warns if you call a variable "main" */ break;
dll_entry_main_t main_; }
log_assert(module != NULL); const char *name = (const char *)(pbModule + ImageImport->Name);
main_ = (void *) GetProcAddress(module->dll, "dll_entry_main"); for (size_t i = 0; i < iat_hook_dlls->nitems; i++) {
const char *iat_hook_dll =
if (main_ == NULL) { *array_item(char *, iat_hook_dlls, i);
log_fatal(
"%s: dll_entry_main not found. Is this a game DLL?", module->path); char *iat_hook_replacement = strstr(iat_hook_dll, "=");
}
if (!iat_hook_replacement)
return main_(); continue;
}
*iat_hook_replacement = '\0';
void module_context_fini(struct module_context *module)
{ const char *expected_dll = iat_hook_dll;
if (module == NULL) { const char *replacement_path_dll = iat_hook_replacement + 1;
return;
} if (strcmp(name, expected_dll) == 0) {
pe_patch((PBYTE)remote_addr + remote_addr_ptr, replacement_path_dll, strlen(replacement_path_dll));
free(module->path);
log_misc("Replacing %s with %s", name, replacement_path_dll);
if (module->dll != NULL) {
FreeLibrary(module->dll); DWORD val = (DWORD)((PBYTE)remote_addr - pbModule);
} pe_patch(&ImageImport->Name, &val, sizeof(DWORD));
} pe_patch(pImageImport, &ImageImport, sizeof(ImageImport));
remote_addr_ptr += strlen(replacement_path_dll) + 1;
}
*iat_hook_replacement = '=';
}
pImageImport++;
size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
}
} else {
log_misc("Couldn't find import table, can't hook DLL\n");
goto inject_fail;
}
return true;
inject_fail:
return false;
}
void module_context_init(struct module_context *module, const char *path)
{
log_assert(module != NULL);
log_assert(path != NULL);
module->dll = LoadLibrary(path);
if (module->dll == NULL) {
LPSTR buffer;
DWORD err = GetLastError();
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &buffer,
0,
NULL);
if (err == ERROR_MOD_NOT_FOUND) {
log_warning("%s is likely missing dependencies", path);
log_warning("Do you have vcredist/directx runtimes installed?");
}
log_fatal("%s: Failed to load game DLL: %s", path, buffer);
LocalFree(buffer);
}
module->path = str_dup(path);
}
void module_context_init_with_iat_hooks(struct module_context *module, const char *path, struct array *iat_hook_dlls)
{
log_assert(module != NULL);
log_assert(path != NULL);
module->dll = LoadLibraryExA(path, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (module->dll == NULL) {
LPSTR buffer;
DWORD err = GetLastError();
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &buffer,
0,
NULL);
if (err == ERROR_MOD_NOT_FOUND) {
log_warning("%s is likely missing dependencies", path);
log_warning("Do you have vcredist/directx runtimes installed?");
}
log_fatal("%s: Failed to load game DLL: %s", path, buffer);
LocalFree(buffer);
}
// Add IAT hooks
module_replace_dll_iat(module->dll, iat_hook_dlls);
log_misc("Finished processing IAT hooks");
// Resolve all imports like a normally loaded DLL
pe_resolve_imports(module->dll);
dll_entry_t orig_entry = pe_get_entry_point(module->dll);
orig_entry(module->dll, DLL_PROCESS_ATTACH, NULL);
log_misc("Finished resolving imports");
module->path = str_dup(path);
}
bool module_context_invoke_init(
const struct module_context *module,
char *sidcode,
struct property_node *app_config)
{
dll_entry_init_t init;
log_assert(module != NULL);
log_assert(sidcode != NULL);
log_assert(app_config != NULL);
init = (void *) GetProcAddress(module->dll, "dll_entry_init");
if (init == NULL) {
log_fatal(
"%s: dll_entry_init not found. Is this a game DLL?", module->path);
}
return init(sidcode, app_config);
}
bool module_context_invoke_main(const struct module_context *module)
{
/* GCC warns if you call a variable "main" */
dll_entry_main_t main_;
log_assert(module != NULL);
main_ = (void *) GetProcAddress(module->dll, "dll_entry_main");
if (main_ == NULL) {
log_fatal(
"%s: dll_entry_main not found. Is this a game DLL?", module->path);
}
return main_();
}
void module_context_fini(struct module_context *module)
{
if (module == NULL) {
return;
}
free(module->path);
if (module->dll != NULL) {
FreeLibrary(module->dll);
}
}

View File

@@ -5,12 +5,15 @@
#include "imports/avs.h" #include "imports/avs.h"
#include "util/array.h"
struct module_context { struct module_context {
HMODULE dll; HMODULE dll;
char *path; char *path;
}; };
void module_context_init(struct module_context *module, const char *path); void module_context_init(struct module_context *module, const char *path);
void module_context_init_with_iat_hooks(struct module_context *module, const char *path, struct array *iat_hook_dlls);
bool module_context_invoke_init( bool module_context_invoke_init(
const struct module_context *module, const struct module_context *module,
char *sidcode, char *sidcode,

View File

@@ -7,6 +7,7 @@
#include "launcher/options.h" #include "launcher/options.h"
#include "util/array.h" #include "util/array.h"
#include "util/log.h"
#include "util/str.h" #include "util/str.h"
#define DEFAULT_HEAP_SIZE 16777216 #define DEFAULT_HEAP_SIZE 16777216
@@ -25,6 +26,7 @@ void options_init(struct options *options)
options->remote_debugger = false; options->remote_debugger = false;
array_init(&options->hook_dlls); array_init(&options->hook_dlls);
array_init(&options->before_hook_dlls); array_init(&options->before_hook_dlls);
array_init(&options->iat_hook_dlls);
options->override_service = NULL; options->override_service = NULL;
options->override_urlslash_enabled = false; options->override_urlslash_enabled = false;
@@ -131,6 +133,19 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
break; break;
case 'I': {
if (i + 1 >= argc) {
return false;
}
const char *dll = argv[++i];
log_assert(strstr(dll, "=") != NULL);
*array_append(const char *, &options->iat_hook_dlls) = dll;
break;
}
case 'Y': case 'Y':
if (i + 1 >= argc) { if (i + 1 >= argc) {
return false; return false;
@@ -218,6 +233,8 @@ void options_print_usage(void)
"times)\n" "times)\n"
" -B [filename] Load pre-hook DLL loaded before avs boot " " -B [filename] Load pre-hook DLL loaded before avs boot "
"(can be specified multiple times)\n" "(can be specified multiple times)\n"
" -I [filename] Load pre-hook DLL that overrides IAT reference before execution"
"(can be specified multiple times)\n"
" -Y [filename] Log to a file in addition to the console\n" " -Y [filename] Log to a file in addition to the console\n"
" -D Halt the launcher before bootstrapping AVS " " -D Halt the launcher before bootstrapping AVS "
"until a" "until a"
@@ -228,4 +245,5 @@ void options_fini(struct options *options)
{ {
array_fini(&options->hook_dlls); array_fini(&options->hook_dlls);
array_fini(&options->before_hook_dlls); array_fini(&options->before_hook_dlls);
array_fini(&options->iat_hook_dlls);
} }

View File

@@ -18,6 +18,7 @@ struct options {
const char *logfile; const char *logfile;
struct array hook_dlls; struct array hook_dlls;
struct array before_hook_dlls; struct array before_hook_dlls;
struct array iat_hook_dlls;
bool remote_debugger; bool remote_debugger;
const char *override_service; const char *override_service;
bool override_urlslash_enabled; bool override_urlslash_enabled;

View File

@@ -0,0 +1,15 @@
libs += popnhook-util
libs_popnhook-util := \
iidxhook-util \
ezusb-iidx-emu \
ezusb2-popn-emu \
ezusb2-emu \
acioemu \
hook \
hooklib \
util \
src_popnhook-util := \
acio.c \
mixer.c \

View File

@@ -0,0 +1,115 @@
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "acioemu/addr.h"
#include "acioemu/emu.h"
#include "acioemu/icca.h"
#include "hook/iohook.h"
#include "hooklib/rs232.h"
#include "popnhook-util/acio.h"
#include "imports/avs.h"
#include "util/defs.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu popnhook_acio_emu;
static struct ac_io_emu_icca popnhook_acio_emu_icca;
static bool popnhook_icca_override_version;
static enum ac_io_emu_icca_version popnhook_icca_override_version_value;
void popnhook_acio_override_version(enum ac_io_emu_icca_version version)
{
popnhook_icca_override_version = true;
popnhook_icca_override_version_value = version;
}
void popnhook_acio_init(bool legacy_mode)
{
if (legacy_mode) {
ac_io_legacy_mode();
}
ac_io_emu_init(&popnhook_acio_emu, L"COM1");
ac_io_emu_icca_init(
&popnhook_acio_emu_icca, &popnhook_acio_emu, 0);
if (popnhook_icca_override_version) {
ac_io_emu_icca_set_version(
&popnhook_acio_emu_icca,
popnhook_icca_override_version_value
);
}
rs232_hook_add_fd(popnhook_acio_emu.fd);
}
void popnhook_acio_fini(void)
{
ac_io_emu_fini(&popnhook_acio_emu);
}
HRESULT
popnhook_acio_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&popnhook_acio_emu, irp)) {
return iohook_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&popnhook_acio_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&popnhook_acio_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&popnhook_acio_emu, msg, 1);
break;
case 1:
ac_io_emu_icca_dispatch_request(
&popnhook_acio_emu_icca, msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast(?) message on pop'n ACIO bus?");
break;
default:
log_warning(
"ACIO message on unhandled bus address: %d", msg->addr);
break;
}
ac_io_emu_request_pop(&popnhook_acio_emu);
}
}

View File

@@ -0,0 +1,33 @@
#ifndef POPNHOOK_UTIL_ACIO_H
#define POPNHOOK_UTIL_ACIO_H
#include <windows.h>
#include <stdbool.h>
#include "acioemu/icca.h"
#include "hook/iohook.h"
/**
* Initialize an emulated ACIO on COM1 for pop'n music.
*
* @param legacy_mode Set to true if running on slotted readers on pop'n 15-18.
*/
void popnhook_acio_init(bool legacy_mode);
/**
* Use the specified ICCA emulation version
*/
void popnhook_acio_override_version(enum ac_io_emu_icca_version version);
/**
* Cleanup the ACIO emulation layer.
*/
void popnhook_acio_fini(void);
/**
* iohook dispatch function. Needs to be installed.
*/
HRESULT popnhook_acio_dispatch_irp(struct irp *irp);
#endif

View File

@@ -0,0 +1,71 @@
#define LOG_MODULE "jbhook-mixer"
#include <windows.h>
#include <mmsystem.h>
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
MMRESULT STDCALL hook_mixerGetLineControlsA(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls);
MMRESULT STDCALL hook_mixerGetDevCapsA(UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps);
MMRESULT STDCALL hook_mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
MMRESULT STDCALL hook_mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);
MMRESULT STDCALL hook_mixerGetControlDetailsA(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);
MMRESULT STDCALL hook_mixerClose(HMIXER hmx);
MMRESULT STDCALL hook_mixerGetLineInfoA(HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo);
static const struct hook_symbol mixer_hook_syms[] = {
{.name = "mixerGetLineControlsA",
.patch = hook_mixerGetLineControlsA},
{.name = "mixerGetDevCapsA",
.patch = hook_mixerGetDevCapsA},
{.name = "mixerOpen",
.patch = hook_mixerOpen},
{.name = "mixerSetControlDetails",
.patch = hook_mixerSetControlDetails},
{.name = "mixerGetControlDetailsA",
.patch = hook_mixerGetControlDetailsA},
{.name = "mixerClose",
.patch = hook_mixerClose},
{.name = "mixerGetLineInfoA",
.patch = hook_mixerGetLineInfoA},
};
MMRESULT STDCALL hook_mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) {
*(DWORD*)phmx = 1234; // any non-zero value is fine
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerClose(HMIXER hmx) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetLineControlsA(HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetDevCapsA(UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetControlDetailsA(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerGetLineInfoA(HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo) {
return MMSYSERR_NOERROR;
}
MMRESULT STDCALL hook_mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
return MMSYSERR_NOERROR;
}
void popnhook_mixer_hook_init(void)
{
hook_table_apply(NULL, "winmm.dll", mixer_hook_syms, lengthof(mixer_hook_syms));
log_info("Inserted mixer hooks");
}

View File

@@ -0,0 +1,11 @@
#ifndef POPNHOOK_UTIL_MIXER_H
#define POPNHOOK_UTIL_MIXER_H
/**
* Hook some mixer related functions and stub out attempts to change the volume.
* In addition to being annoying, this can fail on Vista+ on some outputs,
* despite not actually preventing sound from playing.
*/
void popnhook_mixer_hook_init(void);
#endif

View File

@@ -0,0 +1,34 @@
avsdlls += popnhook1
deplibs_popnhook1 := \
avs \
ldflags_popnhook1 := \
-lws2_32 \
-liphlpapi \
libs_popnhook1 := \
iidxhook-util \
ezusb-iidx-emu \
ezusb2-popn-emu \
ezusb2-emu \
security \
acioemu \
hook \
hooklib \
eamio \
popnio \
cconfig \
util \
ezusb \
security \
popnhook-util \
src_popnhook1 := \
avs-boot.c \
config-eamuse.c \
config-gfx.c \
config-sec.c \
d3d9.c \
dllmain.c \
filesystem.c \

View File

@@ -0,0 +1,115 @@
#define LOG_MODULE "avs-boot"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "hook/table.h"
#include "imports/avs.h"
#include "popnhook1/avs-boot.h"
#include "util/log.h"
static int (*real_ea3_boot_avs)(struct property_node *config);
static int (*real_ea3_boot)(struct property_node *config);
static int my_ea3_boot_avs(struct property_node *config);
static int my_ea3_boot(struct property_node *config);
static struct net_addr popnhook1_avs_boot_eamuse_server_addr;
static const struct hook_symbol popnhook1_avs_hook_syms[] = {
{.name = "ea3_boot",
.patch = my_ea3_boot_avs,
.link = (void **) &real_ea3_boot_avs},
};
static const struct hook_symbol popnhook1_ea3_hook_syms[] = {
{.name = "ea3_boot",
.patch = my_ea3_boot,
.link = (void **) &real_ea3_boot},
};
static void avs_boot_replace_property_str(
struct property_node *node, const char *name, const char *val)
{
struct property_node *tmp;
tmp = property_search(NULL, node, name);
if (tmp) {
property_node_remove(tmp);
}
tmp = property_node_create(NULL, node, PROPERTY_TYPE_STR, name, val);
if (tmp) {
property_node_datasize(tmp);
}
}
static void insert_eamuse_addr(struct property_node *config)
{
char *server_addr;
if (popnhook1_avs_boot_eamuse_server_addr.type != NET_ADDR_TYPE_INVALID) {
log_misc("Injecting network server address");
server_addr = net_addr_to_str(&popnhook1_avs_boot_eamuse_server_addr);
avs_boot_replace_property_str(config, "network/services", server_addr);
free(server_addr);
}
}
static int my_ea3_boot(struct property_node *config)
{
log_info("Called my_ea3_boot");
insert_eamuse_addr(config);
return real_ea3_boot(config);
}
static int my_ea3_boot_avs(struct property_node *config)
{
log_info("Called my_ea3_boot_avs");
insert_eamuse_addr(config);
return real_ea3_boot_avs(config);
}
void popnhook1_avs_boot_init()
{
// pop'n 15 has the ea3_boot in libavs-win32.dll
hook_table_apply(
NULL,
"libavs-win32.dll",
popnhook1_avs_hook_syms,
lengthof(popnhook1_avs_hook_syms));
hook_table_apply(
NULL,
"libavs-win32-ea3.dll",
popnhook1_ea3_hook_syms,
lengthof(popnhook1_ea3_hook_syms));
memset(&popnhook1_avs_boot_eamuse_server_addr, 0, sizeof(struct net_addr));
log_info("Inserted avs log hooks");
}
void popnhook1_avs_boot_set_eamuse_addr(const struct net_addr *server_addr)
{
char *str;
str = net_addr_to_str(server_addr);
log_info("Setting eamuse server: %s", str);
free(str);
memcpy(
&popnhook1_avs_boot_eamuse_server_addr,
server_addr,
sizeof(struct net_addr));
}

View File

@@ -0,0 +1,19 @@
#ifndef POPNHOOK1_AVS_BOOT_H
#define POPNHOOK1_AVS_BOOT_H
#include "util/net.h"
/**
* Initialize hooking of avs_boot and ea3_boot. This re-enables avs logging
* and injects a few important settings.
*/
void popnhook1_avs_boot_init();
/**
* Set the target eamuse server address.
*
* @param server_addr Address to target eamuse server.
*/
void popnhook1_avs_boot_set_eamuse_addr(const struct net_addr *server_addr);
#endif

View File

@@ -0,0 +1,145 @@
#include <string.h>
#include "cconfig/cconfig-util.h"
#include "popnhook1/config-eamuse.h"
#include "security/mcode.h"
#include "util/log.h"
#define POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY "eamuse.server"
#define POPNHOOK1_CONFIG_EAMUSE_PCBID_KEY "eamuse.pcbid"
#define POPNHOOK1_CONFIG_EAMUSE_EAMID_KEY "eamuse.eamid"
#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE "localhost:80"
#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE security_id_default
#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN \
sizeof(security_id_default)
#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE security_id_default
#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN \
sizeof(security_id_default)
const struct net_addr popnhook1_eamuse_default_server = {
.type = NET_ADDR_TYPE_HOSTNAME,
.hostname.host = "localhost",
.hostname.port = 80,
};
void popnhook1_config_eamuse_init(struct cconfig *config)
{
cconfig_util_set_str(
config,
POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY,
POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE,
"URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 "
"(e.g. 127.0.0.1:80) of the target eamuse server. The port is "
"optional "
"but defaults to 80.");
cconfig_util_set_data(
config,
POPNHOOK1_CONFIG_EAMUSE_PCBID_KEY,
(uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE,
POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN,
"PCBID");
cconfig_util_set_data(
config,
POPNHOOK1_CONFIG_EAMUSE_EAMID_KEY,
(uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE,
POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN,
"EAMID");
}
void popnhook1_config_eamuse_get(
struct popnhook1_config_eamuse *config_eamuse, struct cconfig *config)
{
char server_url[1024];
char *tmp;
char *tmp2;
memset(config_eamuse, 0, sizeof(struct popnhook1_config_eamuse));
if (!cconfig_util_get_str(
config,
POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY,
server_url,
sizeof(server_url),
POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY,
POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE);
}
if (!net_str_parse(server_url, &config_eamuse->server)) {
memcpy(
&config_eamuse->server,
&popnhook1_eamuse_default_server,
sizeof(config_eamuse->server));
tmp = net_addr_to_str(&config_eamuse->server);
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default",
tmp);
free(tmp);
}
if (!cconfig_util_get_data(
config,
POPNHOOK1_CONFIG_EAMUSE_PCBID_KEY,
(uint8_t *) &config_eamuse->pcbid,
POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN,
(uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE)) {
tmp = security_id_to_str(
&POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false);
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default",
tmp);
free(tmp);
}
if (!security_id_verify(&config_eamuse->pcbid)) {
tmp = security_id_to_str(
&POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false);
tmp2 = security_id_to_str(&config_eamuse->pcbid, false);
log_warning(
"PCBID verification of '%s' failed, fallback to default "
"PCBID '%s'",
tmp2,
tmp);
free(tmp);
free(tmp2);
}
if (!cconfig_util_get_data(
config,
POPNHOOK1_CONFIG_EAMUSE_EAMID_KEY,
(uint8_t *) &config_eamuse->eamid,
POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN,
(uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE)) {
tmp = security_id_to_str(
&POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false);
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default",
tmp);
free(tmp);
}
if (!security_id_verify(&config_eamuse->eamid)) {
tmp = security_id_to_str(
&POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false);
tmp2 = security_id_to_str(&config_eamuse->eamid, false);
log_warning(
"EAMID verification of '%s' failed, fallback to default "
"EAMID '%s'",
tmp2,
tmp);
free(tmp);
free(tmp2);
}
}

Some files were not shown because too many files have changed in this diff Show More