Compare commits

...

55 Commits
5.38 ... 5.41

Author SHA1 Message Date
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
icex2
efca967553 Update changelog for 5.40 release 2022-06-07 20:19:04 +02:00
QCDLZCLW3K
6c1bb3db82 Documentation fixes, MR feedback 2022-06-07 18:17:54 +00:00
icex2
bec809fbaa doc: Add further references from root readme to docs 2022-06-07 18:17:54 +00:00
icex2
9775f2c853 doc: Add root ddrhook readme 2022-06-07 18:17:54 +00:00
icex2
26c9d7fe0a doc: Add documentation for ddrhook1 and 2 2022-06-07 18:17:54 +00:00
icex2
6b81cd7535 docs: Formatting, highlighting and minor re-phrasing 2022-06-07 18:17:54 +00:00
Will Xyen
b3b6c3f499 ddrhook1: fix build (missing flag) 2022-06-06 21:51:09 -07:00
QCDLZCLW3K
0586ea50aa Add ddr-12 EU support 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
cafa60d0f6 Clean up old variables 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
76c2c49c13 Add ddr-12-us.zip to bemanitools.zip 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
6d38aa5f4a Add support for DDR X2 US 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
c1c5685e3a Force game to always think a debugger isn't present 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
050e52b21e revert: Use process_hijack_startup instead of hooking an early function 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
ab50c70f71 Fix conf description string 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
2223947dd8 Split USB memory path configurations 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
0294eed22b Add in check for updates folder too 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
d7235c3c2c Add in more filesystem hooks 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
402d0d4ca4 Fix bemanitools.zip build 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
89fe822919 Fix window mode for X2 and X3 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
75583897c1 Be more careful about USB memory errors 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
58d297458c ddr: Disable cursor during fullscreen 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
ba528488f0 Fix typo in README 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
7692e14b0b Fix ddr-16-x64.zip build 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
4cc81f48f3 ddr: Fix windowed mode regressions 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
da736d2968 Refactor d3d9 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
c3f9ce7e91 Fixes based on PR feedback 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
41de45d459 Update README 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
bda239a2ba Use process_hijack_startup instead of hooking an early function 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
1e32d1a9a8 Fix DDR X2 and X3 not booting 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
852d770629 Nearly complete USB memory support 2022-05-30 02:00:49 +00:00
QCDLZCLW3K
4be866e69e Add support for DDR X 2022-05-30 02:00:49 +00:00
Will Xyen
537b1fa384 sdvxhook2: fix crash when using sdvxhook2 on certain OS versions 2022-05-27 23:26:17 +00:00
Will Xyen
bd2d722031 sdvxio-bio2: set title pop lights to 50% by default 2022-05-27 23:26:17 +00:00
95c6cd771e00602e3ec82fccba1b3741fdb7f7ca
4f8f6c0f7a jb ripples: Create dev/nvram if not exists in gamestart.bat 2022-05-23 19:10:44 +00:00
96021c6f149619c2abfb151ec48670b44f896293
51a018b0cf Add sdvx generator lights to sdvxio-bio2. 2022-05-20 03:49:29 +00:00
icex2
04442a6dbc Bump version to 5.40 for next development cycle 2022-05-19 01:02:01 +02:00
icex2
85a080e6b3 Update changelog for 5.39 release 2022-05-19 00:02:20 +02:00
95c6cd771e00602e3ec82fccba1b3741fdb7f7ca
28633ded37 jbhook2 and jbhook3 gfx updates
- Fix jbhook3 window mode
- Remove -f option for framed window, no value
- Add -s option to show mouse cursor on window
2022-05-13 19:26:00 +00:00
QCDLZCLW3K
721897d7b0 Separate key algorithm and core code for rp2 and rp3 2022-05-12 10:25:53 +09:00
QCDLZCLW3K
926bbf2e10 Small refactor for rp2 and rp3 + add new sign keys 2022-05-12 05:18:07 +09:00
Will Toohey
ce75e149f7 Sane default for vertical window (true) 2022-04-03 21:40:18 +10:00
Will Toohey
57d9d976ff jbhook2: get p3io sidcode from ea3-config, don't hardcode 2022-04-03 21:32:33 +10:00
Will Toohey
7e731916e2 Move p3io-specific jbhook-util funcs to their own static lib 2022-04-03 21:02:38 +10:00
icex2
dd9b8faafe Bump version to 5.39 for next development cycle 2022-04-02 11:16:58 +02:00
199 changed files with 8592 additions and 1092 deletions

View File

@@ -2,6 +2,21 @@
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.41
* Feature: Support pop'n music 15-18 using popnhook1
* Feature: Support IIDX tricoro CN using iidxhook5-cn
* Various documentation improvements
## 5.40
* Feature: Support DDR X and X2 US/EU using ddrhook1 including memory card emulation
* Fix: sdvxhook2 crashing on some OS versions
* Feature: Support sdvx generator lights in sdvxio
## 5.39
* jbhook3: Fix window mode, remove window frame option, add show cursor on window option
* Code simplification and cleanup round plug modules
* Code structure improvements p3io jubeat
## 5.38 ## 5.38
* sdvxhook2: Support sound voltex exceed gear * sdvxhook2: Support sound voltex exceed gear

View File

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

141
Module.mk
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
@@ -93,7 +100,8 @@ include src/main/cconfig/Module.mk
include src/main/config/Module.mk include src/main/config/Module.mk
include src/main/d3d9exhook/Module.mk include src/main/d3d9exhook/Module.mk
include src/main/ddrhook-util/Module.mk include src/main/ddrhook-util/Module.mk
include src/main/ddrhook/Module.mk include src/main/ddrhook1/Module.mk
include src/main/ddrhook2/Module.mk
include src/main/ddrio-mm/Module.mk include src/main/ddrio-mm/Module.mk
include src/main/ddrio-smx/Module.mk include src/main/ddrio-smx/Module.mk
include src/main/ddrio/Module.mk include src/main/ddrio/Module.mk
@@ -112,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,6 +137,7 @@ 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/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
@@ -142,6 +153,7 @@ include src/main/jbio-p4io/Module.mk
include src/main/jbio/Module.mk include src/main/jbio/Module.mk
include src/main/jbiotest/Module.mk include src/main/jbiotest/Module.mk
include src/main/jbhook-util/Module.mk include src/main/jbhook-util/Module.mk
include src/main/jbhook-util-p3io/Module.mk
include src/main/jbhook1/Module.mk include src/main/jbhook1/Module.mk
include src/main/jbhook2/Module.mk include src/main/jbhook2/Module.mk
include src/main/jbhook3/Module.mk include src/main/jbhook3/Module.mk
@@ -152,6 +164,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
@@ -329,6 +344,22 @@ $(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/eamio.dll \
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 \
@@ -565,10 +596,48 @@ $(zipdir)/sdvx-hwio-x64.zip: \
$(V)echo ... $@ $(V)echo ... $@
$(V)zip -j $@ $^ $(V)zip -j $@ $^
$(zipdir)/ddr-12-to-16.zip: \ $(zipdir)/ddr-11.zip: \
build/bin/avs2_1508-32/launcher.exe \ build/bin/indep-32/inject.exe \
build/bin/avs2_1508-32/ddrhook.dll \ build/bin/avs2_803-32/ddrhook1.dll \
build/bin/avs2_1508-32/unicorntail.dll \ build/bin/avs2_803-32/unicorntail.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/ddrio.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-11.bat \
dist/ddr/gamestart-11-us.bat \
dist/ddr/ddr-11.conf \
dist/ddr/ddr-11-us.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-12-us.zip: \
build/bin/indep-32/inject.exe \
build/bin/avs2_1002-32/ddrhook1.dll \
build/bin/avs2_1002-32/unicorntail.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/ddrio.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-12-us.bat \
dist/ddr/gamestart-12-eu.bat \
dist/ddr/ddr-12-us.conf \
dist/ddr/ddr-12-eu.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-12.zip: \
build/bin/avs2_1002-32/launcher.exe \
build/bin/avs2_1002-32/ddrhook2.dll \
build/bin/avs2_1002-32/unicorntail.dll \
build/bin/indep-32/config.exe \ build/bin/indep-32/config.exe \
build/bin/indep-32/ddrio.dll \ build/bin/indep-32/ddrio.dll \
build/bin/indep-32/ddrio-mm.dll \ build/bin/indep-32/ddrio-mm.dll \
@@ -577,7 +646,37 @@ $(zipdir)/ddr-12-to-16.zip: \
build/bin/indep-32/geninput.dll \ build/bin/indep-32/geninput.dll \
dist/ddr/config.bat \ dist/ddr/config.bat \
dist/ddr/gamestart-12.bat \ dist/ddr/gamestart-12.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-13.zip: \
build/bin/avs2_1304-32/launcher.exe \
build/bin/avs2_1304-32/ddrhook2.dll \
build/bin/avs2_1304-32/unicorntail.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/ddrio.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-13.bat \ dist/ddr/gamestart-13.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-14-to-16.zip: \
build/bin/avs2_1508-32/launcher.exe \
build/bin/avs2_1508-32/ddrhook2.dll \
build/bin/avs2_1508-32/unicorntail.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/ddrio.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-14.bat \ dist/ddr/gamestart-14.bat \
dist/ddr/gamestart-15.bat \ dist/ddr/gamestart-15.bat \
dist/ddr/gamestart-16.bat \ dist/ddr/gamestart-16.bat \
@@ -587,7 +686,7 @@ $(zipdir)/ddr-12-to-16.zip: \
$(zipdir)/ddr-16-x64.zip: \ $(zipdir)/ddr-16-x64.zip: \
build/bin/avs2_1603-64/launcher.exe \ build/bin/avs2_1603-64/launcher.exe \
build/bin/avs2_1603-64/ddrhook.dll \ build/bin/avs2_1603-64/ddrhook2.dll \
build/bin/avs2_1603-64/unicorntail.dll \ build/bin/avs2_1603-64/unicorntail.dll \
build/bin/indep-64/config.exe \ build/bin/indep-64/config.exe \
build/bin/indep-64/ddrio.dll \ build/bin/indep-64/ddrio.dll \
@@ -615,6 +714,26 @@ $(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/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)/
@@ -649,7 +768,11 @@ $(BUILDDIR)/tests.zip: \
$(BUILDDIR)/bemanitools.zip: \ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/bst.zip \ $(zipdir)/bst.zip \
$(zipdir)/ddr-12-to-16.zip \ $(zipdir)/ddr-11.zip \
$(zipdir)/ddr-12.zip \
$(zipdir)/ddr-12-us.zip \
$(zipdir)/ddr-13.zip \
$(zipdir)/ddr-14-to-16.zip \
$(zipdir)/ddr-16-x64.zip \ $(zipdir)/ddr-16-x64.zip \
$(zipdir)/doc.zip \ $(zipdir)/doc.zip \
$(zipdir)/iidx-09-to-12.zip \ $(zipdir)/iidx-09-to-12.zip \
@@ -658,6 +781,7 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/iidx-18.zip \ $(zipdir)/iidx-18.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 \
@@ -670,6 +794,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 \

105
README.md
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.38 Version: 5.41
[Release history](CHANGELOG.md) [Release history](CHANGELOG.md)
@@ -26,54 +26,63 @@ The tl;dr version and golden rules of the sections in the document:
* [Everyone is allowed to submit changes which are not just limited to code by opening merge requests](CONTRIBUTING.md#pull-requests-bugfixes-new-features-or-other-code-contributions) * [Everyone is allowed to submit changes which are not just limited to code by opening merge requests](CONTRIBUTING.md#pull-requests-bugfixes-new-features-or-other-code-contributions)
* [Documentation improvements can and even should be contributed by non developers](CONTRIBUTING.md#pull-requests-bugfixes-new-features-or-other-code-contributions) * [Documentation improvements can and even should be contributed by non developers](CONTRIBUTING.md#pull-requests-bugfixes-new-features-or-other-code-contributions)
## List of supported games (hook libraries) ## Supported games
The following games are supported with their corresponding hook-libraries.
* BeatStream * BeatStream
* BeatStream (bst.zip) using bsthook * BeatStream (`bst.zip`): bsthook
* BeatStream アニムトライヴ (bst.zip) using bsthook * BeatStream アニムトライヴ (`bst.zip`): bsthook
* Dance Dance Revolution * [Dance Dance Revolution](doc/ddrhook/README.md)
* Dance Dance Revolution X2 (ddr-12-to-16.zip) using ddrhook * Dance Dance Revolution X (`ddr-11.zip`): [ddrhook1](doc/ddrhook/ddrhook1.md)
* Dance Dance Revolution X3 vs. 2ndMIX (ddr-12-to-16.zip) using ddrhook * Dance Dance Revolution X2 (US/EU regions) (`ddr-12-us.zip`): [ddrhook1](doc/ddrhook/ddrhook1.md)
* Dance Dance Revolution 2013 (ddr-12-to-16.zip) using ddrhook * Dance Dance Revolution X2 (JP region) (`ddr-12.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
* Dance Dance Revolution 2014 (ddr-12-to-16.zip) using ddrhook * Dance Dance Revolution 2013 (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
* Dance Dance Revolution A (ddr-12-to-16.zip) using ddrhook * Dance Dance Revolution 2014 (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
* Beatmania IIDX * Dance Dance Revolution A (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
* Beatmania IIDX 9th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md) * [Beatmania IIDX](doc/iidxhook/README.md)
* Beatmania IIDX 10th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md) * Beatmania IIDX 9th Style (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 11 IIDX RED (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md) * Beatmania IIDX 10th Style (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 12 HAPPY SKY (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md) * Beatmania IIDX 11 IIDX RED (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 13 DistorteD (iidx-13.zip) using [iidxhook2](doc/iidxhook/iidxhook2.md) * Beatmania IIDX 12 HAPPY SKY (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 14 GOLD (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md) * Beatmania IIDX 13 DistorteD (`iidx-13.zip`): [iidxhook2](doc/iidxhook/iidxhook2.md)
* Beatmania IIDX 15 DJ TROOPERS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md) * Beatmania IIDX 14 GOLD (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 16 EMPRESS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md) * Beatmania IIDX 15 DJ TROOPERS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 17 SIRIUS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md) * Beatmania IIDX 16 EMPRESS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 18 Resort Anthem (iidx-18.zip) using [iidxhook4](doc/iidxhook/iidxhook4.md) * Beatmania IIDX 17 SIRIUS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
* Beatmania IIDX 19 Lincle (iidx-19.zip) using [iidxhook5](doc/iidxhook/iidxhook5.md) * Beatmania IIDX 18 Resort Anthem (`iidx-18.zip`): [iidxhook4](doc/iidxhook/iidxhook4.md)
* Beatmania IIDX 20 Tricoro (iidx-20.zip) using [iidxhook6](doc/iidxhook/iidxhook6.md) * Beatmania IIDX 19 Lincle (`iidx-19.zip`): [iidxhook5](doc/iidxhook/iidxhook5.md)
* Beatmania IIDX 21 SPADA (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md) * Beatmania IIDX tricoro CN (狂热节拍 IIDX 2) (`iidx-20-cn.zip`): [iidxhook5-cn](doc/iidxhook/iidxhook5-cn.md)
* Beatmania IIDX 22 PENDUAL (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md) * Beatmania IIDX 20 Tricoro (`iidx-20.zip`): [iidxhook6](doc/iidxhook/iidxhook6.md)
* Beatmania IIDX 23 copula (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md) * Beatmania IIDX 21 SPADA (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 24 SINOBUZ (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md) * Beatmania IIDX 22 PENDUAL (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 25 CANNON BALLERS (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md) * Beatmania IIDX 23 copula (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 26 Rootage (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md) * Beatmania IIDX 24 SINOBUZ (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
* Beatmania IIDX 27 Heroic Verse (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md) * Beatmania IIDX 25 CANNON BALLERS (`iidx-25-to-26.zip`): [iidxhook8](doc/iidxhook/iidxhook8.md)
* Beatmania IIDX 28 BISTROVER (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md) * Beatmania IIDX 26 Rootage (`iidx-25-to-26.zip`): [iidxhook8](doc/iidxhook/iidxhook8.md)
* jubeat * Beatmania IIDX 27 Heroic Verse (`iidx-27-to-28.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* jubeat (jb-01.zip) using [jbhook1](doc/jbhook/jbhook1.md) * Beatmania IIDX 28 BISTROVER (`iidx-27-to-28.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
* jubeat ripples (jb-02.zip) using [jbhook1](doc/jbhook/jbhook1.md) * [jubeat](doc/jbhook/README.md)
* jubeat knit (jb-03.zip) using [jbhook2](doc/jbhook/jbhook2.md) * jubeat (`jb-01.zip`): [jbhook1](doc/jbhook/jbhook1.md)
* jubeat copious (jb-04.zip) using [jbhook2](doc/jbhook/jbhook2.md) * jubeat ripples (`jb-02.zip`): [jbhook1](doc/jbhook/jbhook1.md)
* jubeat saucer (fulfill) (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md) * jubeat knit (`jb-03.zip`): [jbhook2](doc/jbhook/jbhook2.md)
* jubeat prop (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md) * jubeat copious (`jb-04.zip`): [jbhook2](doc/jbhook/jbhook2.md)
* jubeat qubell (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md) * jubeat saucer (fulfill) (`jb-05-to-07.zip`): [jbhook3](doc/jbhook/jbhook3.md)
* jubeat clan (jb-08.zip) using [jbhook3](doc/jbhook/jbhook3.md) * jubeat prop (`jb-05-to-07.zip`): [jbhook3](doc/jbhook/jbhook3.md)
* jubeat festo (jb-08.zip) using [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 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) using sdvxhook * SOUND VOLTEX BOOTH (`sdvx-01-to-04.zip`): sdvxhook
* SOUND VOLTEX II -infinite infection- (sdvx-01-to-04.zip) using sdvxhook * SOUND VOLTEX II -infinite infection- (`sdvx-01-to-04.zip`): sdvxhook
* SOUND VOLTEX III GRAVITY WARS (sdvx-01-to-04.zip) using sdvxhook * SOUND VOLTEX III GRAVITY WARS (`sdvx-01-to-04.zip`): sdvxhook
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx-01-to-04.zip) using sdvxhook * SOUND VOLTEX IV HEAVENLY HAVEN (`sdvx-01-to-04.zip`): sdvxhook
* SOUND VOLTEX Vivid Wave (sdvx-05-to-06) using sdvxhook2 * SOUND VOLTEX Vivid Wave (`sdvx-05-to-06`): sdvxhook2
* SOUND VOLTEX EXCEED GEAR (sdvx-05-to-06) using sdvxhook2 * SOUND VOLTEX EXCEED GEAR (`sdvx-05-to-06`): sdvxhook2
## ViGEm clients: Expose BT5 APIs as XBOX game controllers ## ViGEm clients: Expose BT5 APIs as XBOX game controllers
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that
@@ -88,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

32
dist/ddr/ddr-11-us.conf vendored Normal file
View File

@@ -0,0 +1,32 @@
# 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
# Mcode of the game to run.
security.mcode=GQHDXUAA
# Emulate P3IO COM4 and its downstream devices. Uses the Windows COM4 port when disabled.
ddrhook1.use_com4_emu=true
# SD cabinet mode
ddrhook1.standard_def=false
# Use 15 kHz monitor mode
ddrhook1.use_15khz=false
# Enable USB memory data emulation
ddrhook1.usbmem_enabled=false
# Specify path for P1 USB memory data
ddrhook1.usbmem_path_p1=usbmem_p1
# Specify path for P2 USB memory data
ddrhook1.usbmem_path_p2=usbmem_p2
# Run the game windowed
gfx.windowed=false

32
dist/ddr/ddr-11.conf vendored Normal file
View File

@@ -0,0 +1,32 @@
# 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
# Mcode of the game to run.
security.mcode=GQHDXJAA
# Emulate P3IO COM4 and its downstream devices. Uses the Windows COM4 port when disabled.
ddrhook1.use_com4_emu=true
# SD cabinet mode
ddrhook1.standard_def=false
# Use 15 kHz monitor mode
ddrhook1.use_15khz=false
# Enable USB memory data emulation
ddrhook1.usbmem_enabled=false
# Specify path for P1 USB memory data
ddrhook1.usbmem_path_p1=usbmem_p1
# Specify path for P2 USB memory data
ddrhook1.usbmem_path_p2=usbmem_p2
# Run the game windowed
gfx.windowed=false

32
dist/ddr/ddr-12-eu.conf vendored Normal file
View File

@@ -0,0 +1,32 @@
# 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
# Mcode of the game to run.
security.mcode=GQJDXEAA
# Emulate P3IO COM4 and its downstream devices. Uses the Windows COM4 port when disabled.
ddrhook1.use_com4_emu=true
# SD cabinet mode
ddrhook1.standard_def=false
# Use 15 kHz monitor mode
ddrhook1.use_15khz=false
# Enable USB memory data emulation
ddrhook1.usbmem_enabled=false
# Specify path for P1 USB memory data
ddrhook1.usbmem_path_p1=usbmem_p1
# Specify path for P2 USB memory data
ddrhook1.usbmem_path_p2=usbmem_p2
# Run the game windowed
gfx.windowed=false

32
dist/ddr/ddr-12-us.conf vendored Normal file
View File

@@ -0,0 +1,32 @@
# 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
# Mcode of the game to run.
security.mcode=GQJDXUAA
# Emulate P3IO COM4 and its downstream devices. Uses the Windows COM4 port when disabled.
ddrhook1.use_com4_emu=true
# SD cabinet mode
ddrhook1.standard_def=false
# Use 15 kHz monitor mode
ddrhook1.use_15khz=false
# Enable USB memory data emulation
ddrhook1.usbmem_enabled=false
# Specify path for P1 USB memory data
ddrhook1.usbmem_path_p1=usbmem_p1
# Specify path for P2 USB memory data
ddrhook1.usbmem_path_p2=usbmem_p2
# Run the game windowed
gfx.windowed=false

11
dist/ddr/gamestart-11-us.bat vendored Normal file
View File

@@ -0,0 +1,11 @@
@echo off
cd /d %~dp0
if not exist conf\nvram mkdir conf\nvram
if not exist conf\raw mkdir conf\raw
regsvr32 /s com\CLVsd.ax
regsvr32 /s com\xactengine2_10.dll
inject ddrhook1.dll DDR.exe --config ddr-11-us.conf %*

11
dist/ddr/gamestart-11.bat vendored Normal file
View File

@@ -0,0 +1,11 @@
@echo off
cd /d %~dp0
if not exist conf\nvram mkdir conf\nvram
if not exist conf\raw mkdir conf\raw
regsvr32 /s com\CLVsd.ax
regsvr32 /s com\xactengine2_10.dll
inject ddrhook1.dll DDR.exe --config ddr-11.conf %*

11
dist/ddr/gamestart-12-eu.bat vendored Normal file
View File

@@ -0,0 +1,11 @@
@echo off
cd /d %~dp0
if not exist conf\nvram mkdir conf\nvram
if not exist conf\raw mkdir conf\raw
regsvr32 /s com\CLVsd.ax
regsvr32 /s com\xactengine2_10.dll
inject ddrhook1.dll DDR.exe --config ddr-12-eu.conf %*

11
dist/ddr/gamestart-12-us.bat vendored Normal file
View File

@@ -0,0 +1,11 @@
@echo off
cd /d %~dp0
if not exist conf\nvram mkdir conf\nvram
if not exist conf\raw mkdir conf\raw
regsvr32 /s com\CLVsd.ax
regsvr32 /s com\xactengine2_10.dll
inject ddrhook1.dll DDR.exe --config ddr-12-us.conf %*

View File

@@ -8,4 +8,4 @@ if not exist conf\raw mkdir conf\raw
regsvr32 /s k-clvsd.dll regsvr32 /s k-clvsd.dll
regsvr32 /s xactengine2_10.dll regsvr32 /s xactengine2_10.dll
.\launcher.exe -K .\ddrhook.dll .\ddr.dll %* .\launcher.exe -K .\ddrhook2.dll .\ddr.dll %*

View File

@@ -8,4 +8,4 @@ if not exist conf\raw mkdir conf\raw
regsvr32 /s k-clvsd.dll regsvr32 /s k-clvsd.dll
regsvr32 /s xactengine2_10.dll regsvr32 /s xactengine2_10.dll
.\launcher.exe -K .\ddrhook.dll .\ddr.dll %* .\launcher.exe -K .\ddrhook2.dll .\ddr.dll %*

View File

@@ -11,4 +11,4 @@ if not exist conf\raw mkdir conf\raw
regsvr32 /s k-clvsd.dll regsvr32 /s k-clvsd.dll
regsvr32 /s xactengine2_10.dll regsvr32 /s xactengine2_10.dll
.\launcher.exe -K .\ddrhook.dll .\mdxja_945.dll %* .\launcher.exe -K .\ddrhook2.dll .\mdxja_945.dll %*

View File

@@ -11,4 +11,4 @@ if not exist conf\raw mkdir conf\raw
regsvr32 /s k-clvsd.dll regsvr32 /s k-clvsd.dll
regsvr32 /s xactengine2_10.dll regsvr32 /s xactengine2_10.dll
.\launcher.exe -K .\ddrhook.dll .\mdxja_945.dll %* .\launcher.exe -K .\ddrhook2.dll .\mdxja_945.dll %*

View File

@@ -12,4 +12,4 @@ if not exist conf\raw mkdir conf\raw
regsvr32 /s com\k-clvsd.dll regsvr32 /s com\k-clvsd.dll
regsvr32 /s com\xactengine2_10.dll regsvr32 /s com\xactengine2_10.dll
.\launcher.exe -H 33554432 -K .\ddrhook.dll .\arkmdxp3.dll %* .\launcher.exe -H 33554432 -K .\ddrhook2.dll .\arkmdxp3.dll %*

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 %*

View File

@@ -46,8 +46,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time # Disable operator clock setting system clock time
misc.disable_clock_set=false misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GQGLDJAA
# Security black plug mcode id string (e.g. GQC02JAA). # Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQGLDJA sec.black_plug_mcode=GQGLDJAA

View File

@@ -46,8 +46,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time # Disable operator clock setting system clock time
misc.disable_clock_set=false misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GQHDDJAA
# Security black plug mcode id string (e.g. GQC02JAA). # Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQHDDJA sec.black_plug_mcode=GQHDDJAA

View File

@@ -49,8 +49,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time # Disable operator clock setting system clock time
misc.disable_clock_set=false misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GQI00JAA
# Security black plug mcode id string (e.g. GQC02JAA). # Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQI00JA sec.black_plug_mcode=GQI00JAA

View File

@@ -49,8 +49,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time # Disable operator clock setting system clock time
misc.disable_clock_set=false misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GCJDJJAA
# Security black plug mcode id string (e.g. GQC02JAA). # Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GCJDJJA sec.black_plug_mcode=GCJDJJAA

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

@@ -0,0 +1,44 @@
# 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
# 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

@@ -2,4 +2,6 @@
cd /d %~dp0 cd /d %~dp0
if not exist dev\nvram mkdir dev\nvram
inject jbhook1.dll jubeat.exe --config jbhook-02.conf %* inject jbhook1.dll jubeat.exe --config jbhook-02.conf %*

View File

@@ -7,4 +7,4 @@ if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
if not exist dev\raw mkdir dev\raw if not exist dev\raw mkdir dev\raw
launcher -H 33554432 -K jbhook2.dll jubeat.dll launcher -H 33554432 -K jbhook2.dll jubeat.dll -v

View File

@@ -2,7 +2,7 @@
gfx.windowed=false gfx.windowed=false
# rotate the normally-horizontal game window to be vertical # rotate the normally-horizontal game window to be vertical
gfx.vertical=false gfx.vertical=true
# 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. # 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 eamuse.server=localhost:80

View File

@@ -2,7 +2,7 @@
gfx.windowed=false gfx.windowed=false
# rotate the normally-horizontal game window to be vertical # rotate the normally-horizontal game window to be vertical
gfx.vertical=false gfx.vertical=true
# 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. # 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 eamuse.server=localhost:80

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,7 +121,7 @@ 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
@@ -130,7 +130,7 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
#### 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
@@ -139,7 +139,7 @@ TODO go into some more detail about some differences in the hook modules, e.g. 1
#### 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 +147,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 +155,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 +163,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

49
doc/ddrhook/README.md Normal file
View File

@@ -0,0 +1,49 @@
# ddrhook
ddrhook is a collection of hook libraries for "Dance Dance Revoluion" 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 ddrhook version
(see below).
## Versions
ddrhook 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:
* [ddrhook1](ddrhook1.md): X, X2 (US/EU regions)
* [ddrhook2](ddrhook2.md): X2 (JP region), X3 vs. 2ndMIX, 2013, 2014, A
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 ddrhook, you have to use the inject tool to inject the
DLL to the game process. `dist/ddr` 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.
## Command line options
Add the argument *-h* when running inject with ddrhook to print help/usage
information with a list of parameters you can apply to tweak various things.
## ddrio API
Available implementations that can be swapped out depending on which kind of
IO hardware you want to use:
* `ddrio`: Default implementation supporting keyboard, mouse and USB
game controllers
* ddrio-mm: Support Minimaid custom interface
* [ddrio-smx](ddrhook/ddrio-smx.md): Support for StepManiaX dance platforms

139
doc/ddrhook/ddrhook1.md Normal file
View File

@@ -0,0 +1,139 @@
# ddrhook1
## Supported games
The following games are supported with this hook library:
* Dance Dance Revolution X
* Dance Dance Revolution X2 (US/EU regions)
The games must be bootstrapped using [inject](../inject.md).
## Data setup
Ensure your folder with your unpacked data looks like this:
* `conf`
* `data`
* `ddr`
* `ddr_YYYYMMDDRR` where `YYYYMMDDRR` corresponds to different datecodes of
different versions. Multiple folders of these possible
`DDR.exe` files should be in `ddr` and `ddr_YYYYMMDDRR` folders.
Unpack the distribution package `ddr-11.zip` into one of the folders containing
a `DDR.exe` file. We recommend using the one with the latest datecode which
denotes the latest version of the game including bugfixes etc.
`gamestart-11.bat` as well as `ddrhook1.dll` are now expected to be located
in the same folder as (one) `DDR.exe` file.
## Running
Run `gamestart-11.bat` as administrator. For the US version of the game, run
`gamestart-11-us.bat` instead. This can be done by either by double
clicking or running it from `cmd.exe`. The latter is recommended to have
any debug output kept on screen after closing the game.
This will run [inject](../inject.md) with the `ddrhook1.dll`. On first run,
if you don't have a conguration file, e.g. `ddr-11.conf`, available in the
same folder, a default one will be created and the game exits. Simply re-run
`gamestart-11.bat` again.
## Configuration ddrhook
The hook library can be configured via cmd arguments or a configuration file.
The latter is generated (*ddr-11.conf* in the same directory) on the first
start of the game using the gamestart-XX.bat file. It contains default values
for all available parameters and comments explaining each parameter. Please
follow the comments when configuring your setup.
Add the argument *-h* when running gamestart-XX.bat
(e.g. *gamestart-XX.bat -h*) to print help/usage information with a list of
all available parameters. Every parameter can be either set as command line
argument or using a configuration file.
To set a parameter from the command line, just add it as an argument after
the bat file like this
```
gamestart-11.bat -p gfx.windowed=true
```
The syntax for the "key=value" is the same as in the config file. Make sure
to have a pre-ceeding "-p" for every parameter added.
However, if a parameter is specifed in the configuration file and as a command
line argument, the command line argument overrides the config file's value.
## Configure USB memory cards and edit data
You can setup actual USB thumb drives mapped to a drive letter, e.g. `E:\` for
player 1 and `F:\` for player 2, or just have them point to any local directory,
e.g. `usbmem_p1` and `usbmem_p2`.
Set-up your folder mappings in the
[conf file or via command line args](#configuration-ddrhook) like follows:
* Enable USB memory data emulation: `ddrhook1.usbmem_enabled=true`
* Set P1 USB memory data path pointing to local folder `usbmem_p1` next to `DDR.EXE`:
`ddrhook1.usbmem_path_p1=usbmem_p1`
* Set P1 USB memory data path pointing to local folder `usbmem_p2` next to `DDR.EXE`:
`ddrhook1.usbmem_path_p1=usbmem_p2`
* Have/create a subfolder called `DDR_EDIT` on any location/USB drive you want to use
* Name your edit data file either `DDR_EDIT_J.DAT` (for JP version) or `DDR_EDIT_U.DAT`
(for US version) and place it in the `DDR_EDIT` directory.
For the example setup above, the full relative path of the edit file should be
`usbmem_p1\DDR_EDIT\DDR_EDIT_J.DAT` for player 1.
Note that USB memory cards are not detected by the game and the game stays
silent about that if they do not contain edit data, your path mapping does not resolve
or you misplaced or named your edit data file incorrectly.
## Grey and glitchy arrows
This is a known issue with many GPUs, typically non-Radeon GPUs.
There is currently not patch available in Bemanitools for that. We assume this is an
issue with incompatible shader code.
There are solutions to hard-patch the code available elsewhere.
## Troubleshooting and FAQ
### Issues with background videos (not) playing
The game expects you have the `CLVSD.ax` file registered for decoding videos.
Grab the `CLVSD.ax` file and go to *Start* > *Run* > enter `regsvr32 clvsd.ax` and
execute. Make sure to run as Administrator, otherwise you will get errors due to
invalid permissions.
### Game crashes during boot
If you have played a newer version of DDR, e.g. DDR 2014+, you might have the
`k-clvsd.dll` codec registered which crashes DDR X and likely X2 (EU/US) as well.
Unregister `k-clvsd.dll`, e.g. `regsvr32 /u k-clvsd.dll`, and
[registering `CLVSD.ax`](#issues-with-background-videos-not-working).
Note that `CLVSD.ax` will likely hang any newer/more recent DDR versions on startup
and require you to use the `k-clvsd.dll` that came with the respective version
instead. See [this section](ddrhook2.md#video-codecs-for-background-videos) for
further details.
### Black screen/render window without a response
This symptom might have many causes, here is a list of known issues and what can be done:
* If not done already, try installing
[DirectX Redist (June 2010)](https://www.microsoft.com/en-us/download/details.aspx?id=8109)
* If you have an integrated/second GPU, ensure it is disabled
* External (USB) audio devices could cause issues. Ensure you are running on on-board/integrated
sound cards and unplug any external audio devices.
* [Disable fullscreen optimizations](https://devblogs.microsoft.com/directx/demystifying-full-screen-optimizations/):
Right click on `DDR.exe`, *Properties* > *Compatibility* > *Disable fullscreen optimizations*
* Check if you can run `DDR.exe` without Bemanitools by simply launching it. It should at least
boot into a startup screen. If that isn't even possible, then it's likely not an issue with
Bemanitools. Note that your data path needs to be `D:\HDX` for that to work though.

80
doc/ddrhook/ddrhook2.md Normal file
View File

@@ -0,0 +1,80 @@
# ddrhook2
## Supported games
The following games are supported by this hook library:
* Dance Dance Revolution X2 (JP region)
* Dance Dance Revolution X3 vs. 2ndMIX
* Dance Dance Revolution 2013
* Dance Dance Revolution 2014
* Dance Dance Revolution A
Note that different builds of the same hook library are required to run the
different versions. See different distribution packages, e.g. `ddr-12.zip`,
`ddr-13.zip` etc.
Depending on the game version, earlier versions are bootstrapped using
[inject](../inject.md) while later versions require [launcher](../launcher.md).
## Running
Run `gamestart-XX.bat`, where `XX` corresponds to the version of the game you
want to run, as administrator. For the US version of X2, run
`gamestart-12-us.bat` instead. This can be done by either by double
clicking or running it from `cmd.exe`. The latter is recommended to have
any debug output kept on screen after closing the game.
This will run [inject](../inject.md) or [launcher](../launcher.md), depending
on the version of the game, with the `ddrhook2.dll`. On first run, if you don't
have a conguration file, e.g. `ddr-12.conf`, available in the same folder, a
default one will be created and the game exits. Simply re-run `gamestart-XX.bat`
again.
## Configure USB memory cards and edit data (DDR X2)
You can setup actual USB thumb drives mapped to a drive letter, e.g. `E:\` for
player 1 and `F:\` for player 2, or just have them point to any local directory,
e.g. `usbmem_p1` and `usbmem_p2`.
Set-up your folder mappings in the
[conf file or via command line args](#configuration-ddrhook) like follows:
* Enable USB memory data emulation: `ddrhook1.usbmem_enabled=true`
* Set P1 USB memory data path pointing to local folder `usbmem_p1` next to `DDR.EXE`:
`ddrhook1.usbmem_path_p1=usbmem_p1`
* Set P1 USB memory data path pointing to local folder `usbmem_p2` next to `DDR.EXE`:
`ddrhook1.usbmem_path_p1=usbmem_p2`
* Have/create a subfolder called `DDR_EDIT` on any location/USB drive you want to use
* Name your edit data file either `DDR_EDIT_J.DAT` (for JP version) or `DDR_EDIT_US.DAT`
(for US version) and place it in the `DDR_EDIT` directory.
For the example setup above, the full relative path of the edit file should be
`usbmem_p1\DDR_EDIT\DDR_EDIT_J.DAT` for player 1.
Note that USB memory cards are not detected by the game and the game stays
silent about that if they do not contain edit data, your path mapping does not resolve
or you misplaced or named your edit data file incorrectly.
## Troubleshooting and FAQ
### Video codecs for background videos
For DDR 2014 and newer (maybe also earlier?), you need to register `k-clvsd.dll` and
`xactengine2_10.dll` to make background videos work. These files are included with
respective versions of the games.
Run the following commands either from a command line (`cmd.exe`) or from
*Start* > *Run*. Adjust the path to files accordingly pointing to the correct files.
* Register `regsvr32 D:\MDX\contents\k-clvsd.dll`
* Register `regsvr32 D:\MDX\contents\xactengine2_10.dll`
Note: The one that comes with IIDX will hang DDR at startup. The opposite is not true:
IIDX works just fine with this CLVSD.
### Laggy audio
If you're running on Windows XP, go to the sound devices control panel, select your
sound card, click Advanced Options and turn Hardware Acceleration down to basic. This
will make the audio much less laggy..

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

@@ -18,6 +18,7 @@ games:
* [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
* [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

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

@@ -32,6 +32,8 @@ EXPORTS
property_node_type property_node_type
property_node_traversal property_node_traversal
property_node_refdata property_node_refdata
property_psmap_export
property_psmap_import
std_getenv std_getenv
std_setenv std_setenv

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

@@ -41,8 +41,7 @@ struct ac_io_kfca_poll_in {
struct ac_io_kfca_poll_out { struct ac_io_kfca_poll_out {
uint32_t gpio; uint32_t gpio;
uint8_t pwm[18]; uint8_t pwm[20];
uint8_t unk[2];
}; };
#pragma pack(pop) #pragma pack(pop)

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

@@ -33,6 +33,7 @@ enum sdvx_io_out_gpio_bit {
SDVX_IO_OUT_GPIO_D = 0, SDVX_IO_OUT_GPIO_D = 0,
SDVX_IO_OUT_GPIO_FX_L = 1, SDVX_IO_OUT_GPIO_FX_L = 1,
SDVX_IO_OUT_GPIO_FX_R = 2, SDVX_IO_OUT_GPIO_FX_R = 2,
SDVX_IO_OUT_GPIO_GENERATOR_B = 3,
SDVX_IO_OUT_GPIO_START = 12, SDVX_IO_OUT_GPIO_START = 12,
SDVX_IO_OUT_GPIO_A = 13, SDVX_IO_OUT_GPIO_A = 13,
SDVX_IO_OUT_GPIO_B = 14, SDVX_IO_OUT_GPIO_B = 14,

View File

@@ -11,3 +11,8 @@ src_ddrhook-util := \
guid.c \ guid.c \
misc.c \ misc.c \
monitor.c \ monitor.c \
extio.c \
_com4.c \
usbmem.c \
spike.c \
p3io.c \

View File

@@ -19,7 +19,7 @@
#include "bemanitools/ddrio.h" #include "bemanitools/ddrio.h"
#include "ddrhook/_com4.h" #include "ddrhook-util/_com4.h"
#include "hook/iohook.h" #include "hook/iohook.h"

View File

@@ -1,5 +1,5 @@
#ifndef IIDXHOOK_COM4_H #ifndef DDRHOOK_UTIL_COM4_H
#define IIDXHOOK_COM4_H #define DDRHOOK_UTIL_COM4_H
#include "hook/iohook.h" #include "hook/iohook.h"

View File

@@ -1,5 +1,5 @@
#ifndef HOOK_DINPUT_H #ifndef DDRHOOK_UTIL_DINPUT_H
#define HOOK_DINPUT_H #define DDRHOOK_UTIL_DINPUT_H
#include <windows.h> #include <windows.h>

View File

@@ -1,5 +1,5 @@
#ifndef DDRHOOK_EXTIO_H #ifndef DDRHOOK_UTIL_EXTIO_H
#define DDRHOOK_EXTIO_H #define DDRHOOK_UTIL_EXTIO_H
#include <windows.h> #include <windows.h>

View File

@@ -1,88 +1,152 @@
// TODO: Fix gray arrows on NVIDIA cards (also applies to X3)
#define LOG_MODULE "gfx-hook"
#include <d3d9.h> #include <d3d9.h>
#include <d3dx9core.h>
#include <windows.h> #include <windows.h>
#include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "hook/com-proxy.h" #include "hook/com-proxy.h"
#include "hook/table.h" #include "hook/table.h"
#include "ddrhook-util/gfx.h"
#include "util/defs.h" #include "util/defs.h"
#include "util/log.h" #include "util/log.h"
#include "util/str.h"
#include "util/time.h"
static HRESULT STDCALL my_CreateDevice( static LONG(STDCALL *real_ChangeDisplaySettingsExA)(
IDirect3D9 *self, char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
UINT adapter, static LONG(STDCALL *real_SetWindowLongW)(
D3DDEVTYPE type, HWND hWnd, int nIndex, LONG dwNewLong);
HWND hwnd, static BOOL(STDCALL *real_SetWindowPos)(
DWORD flags, HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
D3DPRESENT_PARAMETERS *pp,
IDirect3DDevice9 **pdev);
static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver); static LONG STDCALL my_ChangeDisplaySettingsExA(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
static IDirect3D9 *(STDCALL *real_Direct3DCreate9)(UINT sdk_ver); static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong);
static BOOL STDCALL my_SetWindowPos(
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
static bool gfx_windowed; static bool gfx_windowed;
static bool gfx_is_modern;
static const struct hook_symbol gfx_d3d9_hook_syms[] = { static const struct hook_symbol gfx_user32_syms[] = {
{ {
.name = "Direct3DCreate9", .name = "ChangeDisplaySettingsExA",
.patch = my_Direct3DCreate9, .patch = my_ChangeDisplaySettingsExA,
.link = (void **) &real_Direct3DCreate9, .link = (void **) &real_ChangeDisplaySettingsExA,
},
{
.name = "SetWindowLongW",
.patch = my_SetWindowLongW,
.link = (void **) &real_SetWindowLongW,
},
{
.name = "SetWindowPos",
.patch = my_SetWindowPos,
.link = (void **) &real_SetWindowPos,
}, },
}; };
static HRESULT STDCALL my_CreateDevice( /* ------------------------------------------------------------------------- */
IDirect3D9 *self,
UINT adapter, void gfx_d3d9_calc_win_size_with_framed(
D3DDEVTYPE type, HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp)
HWND hwnd,
DWORD flags,
D3DPRESENT_PARAMETERS *pp,
IDirect3DDevice9 **pdev)
{ {
IDirect3D9 *real; /* taken from dxwnd */
RECT rect;
DWORD style;
int max_x, max_y;
HMENU menu;
real = com_proxy_downcast(self)->real; rect.left = x;
rect.top = y;
max_x = width;
max_y = height;
rect.right = x + max_x;
rect.bottom = y + max_y;
if (gfx_windowed) { style = GetWindowLong(hwnd, GWL_STYLE);
pp->Windowed = TRUE; menu = GetMenu(hwnd);
pp->FullScreen_RefreshRateInHz = 0; AdjustWindowRect(&rect, style, (menu != NULL));
/* shift down-right so that the border is visible
and also update the iPosX,iPosY upper-left coordinates
of the client area */
if (rect.left < 0) {
rect.right -= rect.left;
rect.left = 0;
} }
return IDirect3D9_CreateDevice(real, adapter, type, hwnd, flags, pp, pdev); if (rect.top < 0) {
} rect.bottom -= rect.top;
rect.top = 0;
static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver)
{
IDirect3D9 *api;
IDirect3D9Vtbl *api_vtbl;
struct com_proxy *api_proxy;
HRESULT hr;
log_info("Direct3DCreate9 hook hit");
api = real_Direct3DCreate9(sdk_ver);
hr = com_proxy_wrap(&api_proxy, api, sizeof(*api->lpVtbl));
if (hr != S_OK) {
log_fatal("Wrapping com proxy failed: %08lx", hr);
} }
api_vtbl = api_proxy->vptr; wp->x = rect.left;
wp->y = rect.top;
api_vtbl->CreateDevice = my_CreateDevice; wp->cx = rect.right - rect.left;
wp->cy = rect.bottom - rect.top;
return (IDirect3D9 *) api_proxy;
} }
/* ------------------------------------------------------------------------- */
static LONG STDCALL my_ChangeDisplaySettingsExA(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param)
{
if (gfx_get_windowed()) {
return DISP_CHANGE_SUCCESSFUL;
}
return real_ChangeDisplaySettingsExA(
dev_name, dev_mode, hwnd, flags, param);
}
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong)
{
if (gfx_get_windowed() && nIndex == GWL_STYLE) {
dwNewLong |= WS_OVERLAPPEDWINDOW;
}
return real_SetWindowLongW(hWnd, nIndex, dwNewLong);
}
static BOOL STDCALL my_SetWindowPos(
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
{
// Causes DDR A to have a really wide window
if (gfx_get_is_modern()) {
return true;
}
if (gfx_get_windowed()) {
WINDOWPOS wp;
gfx_d3d9_calc_win_size_with_framed(hWnd, X, Y, cx, cy, &wp);
return real_SetWindowPos(
hWnd, hWndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, uFlags);
}
return real_SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
}
/* ------------------------------------------------------------------------- */
void gfx_insert_hooks(HMODULE target) void gfx_insert_hooks(HMODULE target)
{ {
hook_table_apply( hook_table_apply(
target, "d3d9.dll", gfx_d3d9_hook_syms, lengthof(gfx_d3d9_hook_syms)); target, "user32.dll", gfx_user32_syms, lengthof(gfx_user32_syms));
log_info("Inserted graphics hooks"); log_info("Initialized d3d9 hooks");
} }
bool gfx_get_windowed(void) bool gfx_get_windowed(void)
@@ -94,3 +158,124 @@ void gfx_set_windowed(void)
{ {
gfx_windowed = true; gfx_windowed = true;
} }
bool gfx_get_is_modern(void)
{
return gfx_is_modern;
}
void gfx_set_is_modern(void)
{
gfx_is_modern = true;
}
/* ------------------------------------------------------------------------- */
static void gfx_d3d9_patch_window(struct hook_d3d9_irp *irp)
{
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX);
if (gfx_get_windowed()) {
/* use a different style */
irp->args.create_window_ex.style |= WS_OVERLAPPEDWINDOW;
/* also show mouse cursor */
ShowCursor(TRUE);
}
}
static void
gfx_d3d9_fix_window_size_and_pos(struct hook_d3d9_irp *irp)
{
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX);
if (gfx_get_windowed()) {
/* we have to adjust the window size, because the window needs to be a
slightly bigger than the rendering resolution (window caption and
stuff is included in the window size) */
WINDOWPOS wp;
gfx_d3d9_calc_win_size_with_framed(
irp->args.create_window_ex.result,
irp->args.create_window_ex.x,
irp->args.create_window_ex.y,
irp->args.create_window_ex.width,
irp->args.create_window_ex.height,
&wp);
SetWindowPos(
irp->args.create_window_ex.result, 0, wp.x, wp.y, wp.cx, wp.cy, 0);
irp->args.create_window_ex.x = wp.x;
irp->args.create_window_ex.y = wp.y;
irp->args.create_window_ex.width = wp.cx;
irp->args.create_window_ex.height = wp.cy;
}
}
static void gfx_d3d9_create_device_apply_window_mode(
struct hook_d3d9_irp *irp)
{
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE);
D3DPRESENT_PARAMETERS *pp = irp->args.ctx_create_device.pp;
if (gfx_get_windowed()) {
pp->Windowed = TRUE;
pp->FullScreen_RefreshRateInHz = 0;
} else if (pp->Windowed == FALSE) {
/* 64bit builds show the cursor even during fullscreen */
ShowCursor(FALSE);
}
}
static void gfx_d3d9_reset_apply_window_mode(
struct hook_d3d9_irp *irp)
{
log_assert(irp);
log_assert(irp->op == HOOK_D3D9_IRP_OP_DEV_RESET);
D3DPRESENT_PARAMETERS *pp = irp->args.dev_reset.pp;
if (gfx_get_windowed()) {
pp->Windowed = TRUE;
pp->FullScreen_RefreshRateInHz = 0;
}
}
HRESULT
gfx_d3d9_irp_handler(struct hook_d3d9_irp *irp)
{
HRESULT hr;
log_assert(irp);
switch (irp->op) {
case HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX:
gfx_d3d9_patch_window(irp);
hr = hook_d3d9_irp_invoke_next(irp);
if (hr == S_OK) {
gfx_d3d9_fix_window_size_and_pos(irp);
}
return hr;
case HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE:
gfx_d3d9_create_device_apply_window_mode(irp);
hr = hook_d3d9_irp_invoke_next(irp);
return hr;
case HOOK_D3D9_IRP_OP_DEV_RESET:
gfx_d3d9_reset_apply_window_mode(irp);
hr = hook_d3d9_irp_invoke_next(irp);
return hr;
default:
return hook_d3d9_irp_invoke_next(irp);
}
log_fatal("Illegal state");
}

View File

@@ -1,12 +1,25 @@
#ifndef DDRHOOK_GFX_H #ifndef DDRHOOK1_D3D9_H
#define DDRHOOK_GFX_H #define DDRHOOK1_D3D9_H
#include <windows.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include "hook/d3d9.h"
struct ddrhook1_d3d9_config {
bool windowed;
};
void gfx_insert_hooks(HMODULE target);
bool gfx_get_windowed(void); bool gfx_get_windowed(void);
void gfx_set_windowed(void); void gfx_set_windowed(void);
bool gfx_get_is_modern(void);
void gfx_set_is_modern(void);
void gfx_d3d9_calc_win_size_with_framed(
HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp);
void gfx_insert_hooks(HMODULE target);
HRESULT gfx_d3d9_irp_handler(struct hook_d3d9_irp *irp);
#endif #endif

View File

@@ -11,10 +11,9 @@
#include "util/log.h" #include "util/log.h"
#include "util/str.h" #include "util/str.h"
static LONG(STDCALL *real_ChangeDisplaySettingsExA)(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
static LRESULT(STDCALL *real_SendMessageW)( static LRESULT(STDCALL *real_SendMessageW)(
HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static HWND(STDCALL *real_CreateWindowExW)( static HWND(STDCALL *real_CreateWindowExW)(
DWORD dwExStyle, DWORD dwExStyle,
LPCWSTR lpClassName, LPCWSTR lpClassName,
@@ -28,16 +27,11 @@ static HWND(STDCALL *real_CreateWindowExW)(
HMENU hMenu, HMENU hMenu,
HINSTANCE hInstance, HINSTANCE hInstance,
LPVOID lpParam); LPVOID lpParam);
static LONG(STDCALL *real_SetWindowLongW)(
HWND hWnd, int nIndex, LONG dwNewLong);
static BOOL(STDCALL *real_SetWindowPos)(
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
static LONG STDCALL my_ChangeDisplaySettingsExA(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
static SHORT STDCALL my_GetKeyState(int vk); static SHORT STDCALL my_GetKeyState(int vk);
static LRESULT STDCALL static LRESULT STDCALL
my_SendMessageW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); my_SendMessageW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static HWND STDCALL my_CreateWindowExA( static HWND STDCALL my_CreateWindowExA(
DWORD dwExStyle, DWORD dwExStyle,
LPCSTR lpClassName, LPCSTR lpClassName,
@@ -64,16 +58,8 @@ static HWND STDCALL my_CreateWindowExW(
HMENU hMenu, HMENU hMenu,
HINSTANCE hInstance, HINSTANCE hInstance,
LPVOID lpParam); LPVOID lpParam);
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong);
static BOOL STDCALL my_SetWindowPos(
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
static const struct hook_symbol misc_user32_syms[] = { static const struct hook_symbol misc_user32_syms[] = {
{
.name = "ChangeDisplaySettingsExA",
.patch = my_ChangeDisplaySettingsExA,
.link = (void **) &real_ChangeDisplaySettingsExA,
},
{ {
.name = "SendMessageW", .name = "SendMessageW",
.patch = my_SendMessageW, .patch = my_SendMessageW,
@@ -92,82 +78,8 @@ static const struct hook_symbol misc_user32_syms[] = {
.patch = my_CreateWindowExW, .patch = my_CreateWindowExW,
.link = (void **) &real_CreateWindowExW, .link = (void **) &real_CreateWindowExW,
}, },
{
.name = "SetWindowLongW",
.patch = my_SetWindowLongW,
.link = (void **) &real_SetWindowLongW,
},
{
.name = "SetWindowPos",
.patch = my_SetWindowPos,
.link = (void **) &real_SetWindowPos,
},
}; };
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong)
{
if (nIndex == GWL_STYLE)
dwNewLong |= WS_OVERLAPPEDWINDOW;
return real_SetWindowLongW(hWnd, nIndex, dwNewLong);
}
static BOOL STDCALL my_SetWindowPos(
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
{
return true;
}
static LONG STDCALL my_ChangeDisplaySettingsExA(
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param)
{
if (gfx_get_windowed()) {
return DISP_CHANGE_SUCCESSFUL;
} else {
return real_ChangeDisplaySettingsExA(
dev_name, dev_mode, hwnd, flags, param);
}
}
static void calc_win_size_with_framed(
HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp)
{
/* taken from dxwnd */
RECT rect;
DWORD style;
int max_x, max_y;
HMENU menu;
rect.left = x;
rect.top = y;
max_x = width;
max_y = height;
rect.right = x + max_x;
rect.bottom = y + max_y;
style = GetWindowLong(hwnd, GWL_STYLE);
menu = GetMenu(hwnd);
AdjustWindowRect(&rect, style, (menu != NULL));
/* shift down-right so that the border is visible
and also update the iPosX,iPosY upper-left coordinates
of the client area */
if (rect.left < 0) {
rect.right -= rect.left;
rect.left = 0;
}
if (rect.top < 0) {
rect.bottom -= rect.top;
rect.top = 0;
}
wp->x = rect.left;
wp->y = rect.top;
wp->cx = rect.right - rect.left;
wp->cy = rect.bottom - rect.top;
}
static HWND STDCALL my_CreateWindowExW( static HWND STDCALL my_CreateWindowExW(
DWORD dwExStyle, DWORD dwExStyle,
LPCWSTR lpClassName, LPCWSTR lpClassName,
@@ -182,6 +94,23 @@ static HWND STDCALL my_CreateWindowExW(
HINSTANCE hInstance, HINSTANCE hInstance,
LPVOID lpParam) LPVOID lpParam)
{ {
// This breaks DDR X, X2 and X3
if (gfx_get_is_modern()) {
return real_CreateWindowExW(
dwExStyle,
lpClassName,
lpWindowName,
dwStyle,
X,
Y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam);
}
if (gfx_get_windowed()) { if (gfx_get_windowed()) {
/* use a different style */ /* use a different style */
dwStyle |= WS_OVERLAPPEDWINDOW; dwStyle |= WS_OVERLAPPEDWINDOW;
@@ -215,7 +144,7 @@ static HWND STDCALL my_CreateWindowExW(
slightly bigger than the rendering resolution (window caption and slightly bigger than the rendering resolution (window caption and
stuff is included in the window size) */ stuff is included in the window size) */
WINDOWPOS wp; WINDOWPOS wp;
calc_win_size_with_framed(hwnd, X, Y, nWidth, nHeight, &wp); gfx_d3d9_calc_win_size_with_framed(hwnd, X, Y, nWidth, nHeight, &wp);
SetWindowPos(hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, 0); SetWindowPos(hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, 0);
X = wp.x; X = wp.x;
Y = wp.y; Y = wp.y;

View File

@@ -1,5 +1,5 @@
#ifndef HOOK_MISC_H #ifndef DDRHOOK_UTIL_MISC_H
#define HOOK_MISC_H #define DDRHOOK_UTIL_MISC_H
#include <windows.h> #include <windows.h>

View File

@@ -1,5 +1,5 @@
#ifndef DDRHOOK_MONITOR_H #ifndef DDRHOOK_UTIL_MONITOR_H
#define DDRHOOK_MONITOR_H #define DDRHOOK_UTIL_MONITOR_H
#include <windows.h> #include <windows.h>

View File

@@ -0,0 +1,152 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "bemanitools/ddrio.h"
#include "ddrhook-util/p3io.h"
#include "p3ioemu/emu.h"
#include "p3ioemu/uart.h"
#include "util/log.h"
extern bool _15khz;
extern bool standard_def;
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state);
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs);
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type);
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq);
static HRESULT p3io_ddr_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom);
static const struct p3io_ops p3io_ddr_ops = {
.read_jamma = p3io_ddr_read_jamma,
.set_outputs = p3io_ddr_set_outputs,
.get_cab_type = p3io_ddr_get_cab_type,
.get_video_freq = p3io_ddr_get_video_freq,
};
static const struct p3io_ops p3io_ddr_ops_with_plugs = {
.read_jamma = p3io_ddr_read_jamma,
.set_outputs = p3io_ddr_set_outputs,
.get_cab_type = p3io_ddr_get_cab_type,
.get_video_freq = p3io_ddr_get_video_freq,
.get_roundplug = p3io_ddr_get_roundplug,
};
static struct security_mcode p3io_ddr_mcode;
static struct security_id p3io_ddr_pcbid;
static struct security_id p3io_ddr_eamid;
static struct security_rp_sign_key p3io_black_sign_key;
static struct security_rp_sign_key p3io_white_sign_key;
void p3io_ddr_init(void)
{
/* COM4 isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we possibly intercept them in
_com4.c (or possibly don't, in which case the communications will be
sent to the real COM4 on your system) */
p3io_uart_set_path(0, L"COM4");
p3io_emu_init(&p3io_ddr_ops, NULL);
}
void p3io_ddr_init_with_plugs(
const struct security_mcode *mcode,
const struct security_id *pcbid,
const struct security_id *eamid,
const struct security_rp_sign_key *black_sign_key,
const struct security_rp_sign_key *white_sign_key)
{
memcpy(&p3io_ddr_mcode, mcode, sizeof(struct security_mcode));
memcpy(&p3io_ddr_pcbid, pcbid, sizeof(struct security_id));
memcpy(&p3io_ddr_eamid, eamid, sizeof(struct security_id));
memcpy(&p3io_black_sign_key, black_sign_key, sizeof(struct security_rp_sign_key));
memcpy(&p3io_white_sign_key, white_sign_key, sizeof(struct security_rp_sign_key));
/* COM4 isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we possibly intercept them in
_com4.c (or possibly don't, in which case the communications will be
sent to the real COM4 on your system) */
p3io_uart_set_path(0, L"COM4");
p3io_emu_init(&p3io_ddr_ops_with_plugs, NULL);
}
void p3io_ddr_fini(void)
{
p3io_emu_fini();
}
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state)
{
log_assert(state != NULL);
*state = ddr_io_read_pad();
return S_OK;
}
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs)
{
ddr_io_set_lights_p3io(outputs);
return S_OK;
}
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type)
{
if (standard_def) {
*type = P3IO_CAB_TYPE_SD;
} else {
*type = P3IO_CAB_TYPE_HD;
}
return S_OK;
}
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq)
{
if (_15khz) {
*freq = P3IO_VIDEO_FREQ_15KHZ;
} else {
*freq = P3IO_VIDEO_FREQ_31KHZ;
}
return S_OK;
}
static HRESULT p3io_ddr_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom)
{
struct security_rp3_eeprom eeprom_out;
if (plug_id == 0) {
/* black */
memcpy(rom, p3io_ddr_pcbid.id, sizeof(p3io_ddr_pcbid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&p3io_black_sign_key,
&p3io_ddr_mcode,
&p3io_ddr_pcbid,
&eeprom_out);
} else {
/* white */
memcpy(rom, p3io_ddr_eamid.id, sizeof(p3io_ddr_eamid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&p3io_white_sign_key,
&security_mcode_eamuse,
&p3io_ddr_eamid,
&eeprom_out);
}
memcpy(eeprom, &eeprom_out, sizeof(struct security_rp3_eeprom));
return S_OK;
}
// TODO coinstock

View File

@@ -0,0 +1,23 @@
#ifndef DDRHOOK_UTIL_P3IO_H
#define DDRHOOK_UTIL_P3IO_H
#include <windows.h>
#include "hook/iohook.h"
#include "security/rp-sign-key.h"
#include "security/rp3.h"
extern const wchar_t p3io_dev_node_prefix[];
extern const wchar_t p3io_dev_node[];
void p3io_ddr_init(void);
void p3io_ddr_init_with_plugs(
const struct security_mcode *mcode,
const struct security_id *pcbid,
const struct security_id *eamid,
const struct security_rp_sign_key *black_sign_key,
const struct security_rp_sign_key *white_sign_key);
void p3io_ddr_fini(void);
#endif

View File

@@ -1,5 +1,5 @@
#ifndef DDRHOOK_SPIKE_H #ifndef DDRHOOK_UTIL_SPIKE_H
#define DDRHOOK_SPIKE_H #define DDRHOOK_UTIL_SPIKE_H
#include <windows.h> #include <windows.h>

View File

@@ -0,0 +1,439 @@
#define LOG_MODULE "usbmem"
// 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 <string.h>
#include <wchar.h>
#include "hook/iohook.h"
#include "util/crc.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/fs.h"
#include "util/str.h"
#define USBMEM_DEVICE_COUNT 2
#define USBMEM_COMMAND_BUF_SIZE 128
#define USBMEM_DATA_BUF_SIZE (1024 + 5)
static HANDLE usbmem_fd;
static char usbmem_response[USBMEM_DATA_BUF_SIZE];
static bool usbmem_pending;
static size_t usbmem_response_length;
static bool usbmem_enabled;
static HRESULT usbmem_open(struct irp *irp);
static HRESULT usbmem_close(struct irp *irp);
static HRESULT usbmem_write(struct irp *irp);
static HRESULT usbmem_read(struct irp *irp);
static HRESULT usbmem_ioctl(struct irp *irp);
typedef enum {
USBMEM_FILE_TYPE_NONE = 0,
USBMEM_FILE_TYPE_READ,
USBMEM_FILE_TYPE_WRITE,
} USBMEM_FILE_TYPE;
struct USBMEM_STATE {
bool connected;
bool opened;
bool errored;
USBMEM_FILE_TYPE file_type;
char basepath[MAX_PATH];
char path[MAX_PATH];
char filename[MAX_PATH];
uint8_t *buffer;
size_t buffer_len;
size_t buffer_index;
int buffer_frame;
};
static int target_device_id;
static struct USBMEM_STATE usbmem_state[USBMEM_DEVICE_COUNT];
static void usbmem_reset_file_state(int port)
{
if (usbmem_state[port].buffer) {
free(usbmem_state[port].buffer);
usbmem_state[port].buffer = NULL;
}
usbmem_state[port].buffer_len = 0;
usbmem_state[port].buffer_index = 0;
usbmem_state[port].buffer_frame = 0;
usbmem_state[port].file_type = USBMEM_FILE_TYPE_NONE;
}
void usbmem_init(const char *path_p1, const char *path_p2, const bool enabled)
{
log_assert(usbmem_fd == NULL);
HRESULT hr;
char usb_data_path[USBMEM_DEVICE_COUNT][MAX_PATH];
hr = iohook_open_nul_fd(&usbmem_fd);
if (hr != S_OK) {
log_fatal("Opening nul fd failed: %08lx", hr);
}
usbmem_enabled = enabled;
GetFullPathNameA(path_p1, sizeof(usb_data_path[0]), usb_data_path[0], NULL);
log_misc("USB memory data path (P1): %s", usb_data_path[0]);
GetFullPathNameA(path_p2, sizeof(usb_data_path[1]), usb_data_path[1], NULL);
log_misc("USB memory data path (P2): %s", usb_data_path[1]);
if (enabled && !path_exists(usb_data_path[0]) && !path_exists(usb_data_path[1])) {
log_warning("USB memory data path does not exist, disabling");
usbmem_enabled = false;
}
target_device_id = -1;
for (int i = 0; i < USBMEM_DEVICE_COUNT; i++) {
usbmem_state[i].connected = false;
usbmem_state[i].opened = false;
usbmem_state[i].errored = false;
strcpy(usbmem_state[i].basepath, usb_data_path[i]);
memset(usbmem_state[i].path, 0, sizeof(usbmem_state[i].path));
memset(usbmem_state[i].filename, 0, sizeof(usbmem_state[i].filename));
usbmem_reset_file_state(i);
}
}
void usbmem_fini(void)
{
if (usbmem_fd != NULL) {
CloseHandle(usbmem_fd);
}
usbmem_fd = NULL;
}
HRESULT
usbmem_dispatch_irp(struct irp *irp)
{
log_assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != usbmem_fd) {
return iohook_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN:
return usbmem_open(irp);
case IRP_OP_CLOSE:
return usbmem_close(irp);
case IRP_OP_READ:
return usbmem_read(irp);
case IRP_OP_WRITE:
return usbmem_write(irp);
case IRP_OP_IOCTL:
return usbmem_ioctl(irp);
default:
return E_NOTIMPL;
}
}
static HRESULT usbmem_open(struct irp *irp)
{
log_assert(irp != NULL);
if (!wstr_eq(irp->open_filename, L"COM3")) {
return iohook_invoke_next(irp);
}
irp->fd = usbmem_fd;
log_info("USB edit data PCB opened");
return S_OK;
}
static HRESULT usbmem_close(struct irp *irp)
{
log_info("USB edit data PCB closed");
return S_OK;
}
static HRESULT usbmem_write(struct irp *irp)
{
struct const_iobuf *src;
char request[USBMEM_COMMAND_BUF_SIZE];
uint32_t nbytes;
log_assert(irp != NULL);
log_assert(irp->write.bytes != NULL);
src = &irp->write;
nbytes = src->nbytes > USBMEM_COMMAND_BUF_SIZE ? USBMEM_COMMAND_BUF_SIZE : src->nbytes;
memcpy(request, src->bytes, nbytes);
request[nbytes - 1] = '\0'; /* This is always a CR. */
if (!usbmem_pending && target_device_id >= 0 && target_device_id < USBMEM_DEVICE_COUNT && usbmem_state[target_device_id].file_type == USBMEM_FILE_TYPE_READ) {
memset(usbmem_response, 0, sizeof(usbmem_response));
// log_misc("Read progress %08x/%08x bytes", usbmem_state[target_device_id].buffer_index, usbmem_state[target_device_id].buffer_len);
if (usbmem_state[target_device_id].buffer_index < usbmem_state[target_device_id].buffer_len) {
usbmem_response_length = sizeof(usbmem_response);
usbmem_response[0] = 0x02; // 1 = 0x80 buffer, 2 = 0x400 buffer
usbmem_response[1] = usbmem_state[target_device_id].buffer_frame;
usbmem_response[2] = ~usbmem_response[1];
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);
} else {
size_t len = sizeof(usbmem_response) - 5;
if (usbmem_state[target_device_id].buffer_index + len > usbmem_state[target_device_id].buffer_len)
len = usbmem_state[target_device_id].buffer_len - usbmem_state[target_device_id].buffer_index;
memcpy(usbmem_response + 3, usbmem_state[target_device_id].buffer + usbmem_state[target_device_id].buffer_index, len);
usbmem_state[target_device_id].buffer_index += len;
}
usbmem_state[target_device_id].buffer_frame++;
uint16_t crc = crc16_msb(usbmem_response + 3, sizeof(usbmem_response) - 5, 0);
usbmem_response[sizeof(usbmem_response) - 2] = crc >> 8;
usbmem_response[sizeof(usbmem_response) - 1] = crc & 0xff;
} else {
usbmem_response_length = 1;
usbmem_response[0] = 0x04; // End
}
} else if (strlen(request) > 0) {
log_misc(">%s", request);
// Try to detect device ID
// The only commands without a device ID are "sver", "start", and "init".
char target_device_val = request[strlen(request) - 1];
char *target_device_id_ptr = strstr(request, " ");
if (target_device_id_ptr != NULL) {
target_device_val = *(target_device_id_ptr - 1);
}
// TODO: Rewrite this code to more cleanly handle hotplugging USB drives
if (str_eq(request, "sver")) {
str_cpy(
usbmem_response,
sizeof(usbmem_response),
"done GQHDXJAA DJHACKRS");
} else if (str_eq(request, "init") || str_eq(request, "start")) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else if (target_device_val == 'a' || target_device_val == 'b') {
// Counterintuitively, b is P1 and a is P2
target_device_id = target_device_val == 'b' ? 0 : 1;
if (!usbmem_enabled) {
// Ignore all other USB device specific commands and pretend a device isn't plugged in
// when USB memory emulation is disabled.
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
} else if (usbmem_state[target_device_id].errored) {
// If the device went through the entire process once and the file didn't exist
// then just force it to be disabled until the game is restarted because otherwise
// it'll get stuck in a loop.
// TODO: This could be better emulated by using a keybind to simulate inserting and
// ejecting the USB drive to additionally clear the error flag.
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
} else if (str_eq(request, "on_a") || str_eq(request, "on_b")) {
usbmem_state[target_device_id].connected = path_exists(usbmem_state[target_device_id].basepath);
usbmem_state[target_device_id].errored = false;
usbmem_reset_file_state(target_device_id);
if (usbmem_state[target_device_id].connected)
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
else
str_cpy(usbmem_response, sizeof(usbmem_response), "not connected");
} else if (str_eq(request, "offa") || str_eq(request, "offb")) {
if (usbmem_state[target_device_id].connected)
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
else
str_cpy(usbmem_response, sizeof(usbmem_response), "not connected");
usbmem_state[target_device_id].connected = false;
usbmem_reset_file_state(target_device_id);
} else if (str_eq(request, "opna") || str_eq(request, "opnb")) {
bool basepath_exists = path_exists(usbmem_state[target_device_id].basepath);
if (!usbmem_state[target_device_id].connected || !basepath_exists) {
usbmem_state[target_device_id].opened = false;
str_cpy(usbmem_response, sizeof(usbmem_response), "not connected");
} else {
usbmem_state[target_device_id].opened = true;
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
}
} else if (str_eq(request, "clsa") || str_eq(request, "clsb")) {
if (usbmem_state[target_device_id].opened)
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
else
str_cpy(usbmem_response, sizeof(usbmem_response), "not connected");
usbmem_state[target_device_id].opened = false;
usbmem_reset_file_state(target_device_id);
} else if (strncmp(request, "cda ", 4) == 0 || strncmp(request, "cdb ", 4) == 0) {
char *path = request + 4;
if (!usbmem_state[target_device_id].connected || !usbmem_state[target_device_id].opened) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else if (path[1] == ':') {
// Absolute path
char temp[MAX_PATH];
snprintf(temp, sizeof(temp), "%s\\%s", usbmem_state[target_device_id].basepath, path + 3);
if (!path_exists(temp)) {
log_warning("Couldn't find path %s", temp);
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else {
log_misc("Changing path to %s", temp);
str_cpy(usbmem_state[target_device_id].path, sizeof(usbmem_state[target_device_id].path), temp);
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
}
} else {
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
}
} else if (strncmp(request, "rda ", 4) == 0 || strncmp(request, "rdb ", 4) == 0) {
usbmem_reset_file_state(target_device_id);
if (!usbmem_state[target_device_id].connected || !usbmem_state[target_device_id].opened) {
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
} else {
char temp[MAX_PATH] = {0};
char *filename = request + 4;
snprintf(temp, sizeof(temp), "%s\\%s", usbmem_state[target_device_id].path, filename);
if (usbmem_state[target_device_id].buffer) {
free(usbmem_state[target_device_id].buffer);
usbmem_state[target_device_id].buffer = NULL;
}
usbmem_state[target_device_id].file_type = USBMEM_FILE_TYPE_NONE;
usbmem_state[target_device_id].buffer_len = 0;
usbmem_state[target_device_id].buffer_index = 0;
usbmem_state[target_device_id].buffer_frame = 0;
memset(usbmem_state[target_device_id].filename, 0, sizeof(usbmem_state[target_device_id].filename));
if (!path_exists(temp)) {
log_warning("Couldn't find file %s", temp);
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
usbmem_state[target_device_id].errored = true;
} else {
bool loaded = file_load(temp, (void**)&usbmem_state[target_device_id].buffer,
&usbmem_state[target_device_id].buffer_len, false);
if (loaded) {
log_misc("Reading file %s", temp);
usbmem_state[target_device_id].file_type = USBMEM_FILE_TYPE_READ;
str_cpy(usbmem_state[target_device_id].filename, sizeof(usbmem_state[target_device_id].filename), filename);
str_cpy(usbmem_response, sizeof(usbmem_response), "start");
} else {
log_warning("Couldn't read file %s", temp);
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
usbmem_state[target_device_id].errored = true;
}
}
}
} else if (strncmp(request, "wra ", 4) == 0 || strncmp(request, "wrb ", 4) == 0) {
// Open file for writing
usbmem_reset_file_state(target_device_id);
str_cpy(usbmem_response, sizeof(usbmem_response), "not supported");
} else if (strncmp(request, "wha ", 4) == 0 || strncmp(request, "whb ", 4) == 0) {
// Something relating to writing?
str_cpy(usbmem_response, sizeof(usbmem_response), "not supported");
} else if (strncmp(request, "lma ", 4) == 0 || strncmp(request, "lmb ", 4) == 0) {
// What is "lm"?
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else {
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
}
} else {
str_cpy(usbmem_response, sizeof(usbmem_response), "fail");
}
str_cat(usbmem_response, sizeof(usbmem_response), "\r>");
usbmem_response_length = strlen(usbmem_response);
}
usbmem_pending = true;
src->pos = nbytes;
return S_OK;
}
static HRESULT usbmem_read(struct irp *irp)
{
struct iobuf *dest;
log_assert(irp != NULL);
log_assert(irp->read.bytes != NULL);
dest = &irp->read;
if (usbmem_pending && usbmem_response_length != USBMEM_DATA_BUF_SIZE) {
log_misc("%s", usbmem_response);
}
if (usbmem_pending && usbmem_response_length == 0) {
str_cpy(usbmem_response, sizeof(usbmem_response), "\r>");
usbmem_response_length = strlen(usbmem_response);
}
dest->pos = usbmem_response_length;
memcpy(dest->bytes, usbmem_response, usbmem_response_length);
usbmem_pending = false;
usbmem_response_length = 0;
memset(usbmem_response, 0, sizeof(usbmem_response));
return S_OK;
}
static HRESULT usbmem_ioctl(struct irp *irp)
{
SERIAL_STATUS *status;
log_assert(irp != NULL);
switch (irp->ioctl) {
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning(
"IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
return E_INVALIDARG;
}
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = usbmem_pending ? 1 : 0;
irp->read.pos = sizeof(*status);
break;
default:
break;
}
return S_OK;
}

View File

@@ -0,0 +1,8 @@
#ifndef DDRHOOK_UTIL_USBMEM_H
#define DDRHOOK_UTIL_USBMEM_H
void usbmem_init(const char *path_p1, const char *path_p2, const bool enabled);
void usbmem_fini(void);
HRESULT usbmem_dispatch_irp(struct irp *irp);
#endif

View File

@@ -1,25 +0,0 @@
avsdlls += ddrhook
deplibs_ddrhook := \
avs \
libs_ddrhook := \
acioemu \
ddrhook-util \
p3ioemu \
p3io \
hook \
hooklib \
util \
eamio \
ddrio \
src_ddrhook := \
extio.c \
dllmain.c \
_com4.c \
master.c \
p3io.c \
usbmem.c \
spike.c

View File

@@ -1,8 +0,0 @@
#ifndef DDRHOOK_MASTER_H
#define DDRHOOK_MASTER_H
#include <windows.h>
void master_insert_hooks(HMODULE target);
#endif

View File

@@ -1,85 +0,0 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "bemanitools/ddrio.h"
#include "ddrhook/p3io.h"
#include "p3ioemu/emu.h"
#include "p3ioemu/uart.h"
#include "util/log.h"
extern bool _15khz;
extern bool standard_def;
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state);
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs);
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type);
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq);
static const struct p3io_ops p3io_ddr_ops = {
.read_jamma = p3io_ddr_read_jamma,
.set_outputs = p3io_ddr_set_outputs,
.get_cab_type = p3io_ddr_get_cab_type,
.get_video_freq = p3io_ddr_get_video_freq,
};
void p3io_ddr_init(void)
{
/* COM4 isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we possibly intercept them in
_com4.c (or possibly don't, in which case the communications will be
sent to the real COM4 on your system) */
p3io_uart_set_path(0, L"COM4");
p3io_emu_init(&p3io_ddr_ops, NULL);
}
void p3io_ddr_fini(void)
{
p3io_emu_fini();
}
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state)
{
log_assert(state != NULL);
*state = ddr_io_read_pad();
return S_OK;
}
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs)
{
ddr_io_set_lights_p3io(outputs);
return S_OK;
}
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type)
{
if (standard_def) {
*type = P3IO_CAB_TYPE_SD;
} else {
*type = P3IO_CAB_TYPE_HD;
}
return S_OK;
}
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq)
{
if (_15khz) {
*freq = P3IO_VIDEO_FREQ_15KHZ;
} else {
*freq = P3IO_VIDEO_FREQ_31KHZ;
}
return S_OK;
}
// TODO coinstock
// TODO round plug

View File

@@ -1,14 +0,0 @@
#ifndef DDRHOOK_P3IO_H
#define DDRHOOK_P3IO_H
#include <windows.h>
#include "hook/iohook.h"
extern const wchar_t p3io_dev_node_prefix[];
extern const wchar_t p3io_dev_node[];
void p3io_ddr_init(void);
void p3io_ddr_fini(void);
#endif

View File

@@ -1,204 +0,0 @@
#define LOG_MODULE "usbmem"
// 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 <string.h>
#include <wchar.h>
#include "hook/iohook.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
#define USBMEM_BUF_SIZE 128
static HANDLE usbmem_fd;
static char usbmem_response[USBMEM_BUF_SIZE];
static bool usbmem_pending;
static HRESULT usbmem_open(struct irp *irp);
static HRESULT usbmem_close(struct irp *irp);
static HRESULT usbmem_write(struct irp *irp);
static HRESULT usbmem_read(struct irp *irp);
static HRESULT usbmem_ioctl(struct irp *irp);
void usbmem_init(void)
{
log_assert(usbmem_fd == NULL);
HRESULT hr;
hr = iohook_open_nul_fd(&usbmem_fd);
if (hr != S_OK) {
log_fatal("Opening nul fd failed: %08lx", hr);
}
}
void usbmem_fini(void)
{
if (usbmem_fd != NULL) {
CloseHandle(usbmem_fd);
}
usbmem_fd = NULL;
}
HRESULT
usbmem_dispatch_irp(struct irp *irp)
{
log_assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != usbmem_fd) {
return iohook_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN:
return usbmem_open(irp);
case IRP_OP_CLOSE:
return usbmem_close(irp);
case IRP_OP_READ:
return usbmem_read(irp);
case IRP_OP_WRITE:
return usbmem_write(irp);
case IRP_OP_IOCTL:
return usbmem_ioctl(irp);
default:
return E_NOTIMPL;
}
}
static HRESULT usbmem_open(struct irp *irp)
{
log_assert(irp != NULL);
if (!wstr_eq(irp->open_filename, L"COM3")) {
return iohook_invoke_next(irp);
}
irp->fd = usbmem_fd;
log_info("USB edit data PCB opened");
return S_OK;
}
static HRESULT usbmem_close(struct irp *irp)
{
log_info("USB edit data PCB closed");
return S_OK;
}
static HRESULT usbmem_write(struct irp *irp)
{
struct const_iobuf *src;
char request[USBMEM_BUF_SIZE];
uint32_t nbytes;
log_assert(irp != NULL);
log_assert(irp->write.bytes != NULL);
src = &irp->write;
nbytes = src->nbytes > USBMEM_BUF_SIZE ? USBMEM_BUF_SIZE : src->nbytes;
memcpy(request, src->bytes, nbytes);
request[nbytes - 1] = '\0'; /* This is always a CR. */
log_misc(">%s", request);
if (strlen(request) > 0) {
if (str_eq(request, "sver")) {
str_cpy(
usbmem_response,
sizeof(usbmem_response),
"done GQHDXJAA DJHACKRS");
} else if (
str_eq(request, "on_a") || str_eq(request, "on_b") ||
str_eq(request, "offa") || str_eq(request, "offb")) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else if (
strncmp(request, "lma ", 4) == 0 ||
strncmp(request, "lmb ", 4) == 0) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else {
str_cpy(usbmem_response, sizeof(usbmem_response), "not connected");
}
}
usbmem_pending = true;
src->pos = nbytes;
return S_OK;
}
static HRESULT usbmem_read(struct irp *irp)
{
struct iobuf *dest;
uint32_t rlength;
log_assert(irp != NULL);
log_assert(irp->read.bytes != NULL);
dest = &irp->read;
if (usbmem_pending) {
if (strlen(usbmem_response) > 0) {
log_misc("%s", usbmem_response);
}
str_cat(usbmem_response, sizeof(usbmem_response), "\r>");
usbmem_pending = false;
}
rlength = strlen(usbmem_response);
memcpy(dest->bytes, usbmem_response, rlength);
memset(usbmem_response, 0, USBMEM_BUF_SIZE);
dest->pos = rlength;
return S_OK;
}
static HRESULT usbmem_ioctl(struct irp *irp)
{
SERIAL_STATUS *status;
log_assert(irp != NULL);
switch (irp->ioctl) {
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning(
"IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
return E_INVALIDARG;
}
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = usbmem_pending ? 1 : 0;
irp->read.pos = sizeof(*status);
break;
default:
break;
}
return S_OK;
}

View File

@@ -1,8 +0,0 @@
#ifndef HOOK_USBMEM_H
#define HOOK_USBMEM_H
void usbmem_init(void);
void usbmem_fini(void);
HRESULT usbmem_dispatch_irp(struct irp *irp);
#endif

View File

@@ -0,0 +1,30 @@
avsdlls += ddrhook1
ldflags_ddrhook1 := \
-lws2_32 \
deplibs_ddrhook1 := \
avs \
libs_ddrhook1 := \
acioemu \
cconfig \
ddrhook-util \
p3ioemu \
p3io \
hook \
hooklib \
util \
eamio \
ddrio \
security \
src_ddrhook1 := \
avs-boot.c \
dllmain.c \
config-ddrhook1.c \
config-eamuse.c \
config-gfx.c \
config-security.c \
master.c \
filesystem.c \

View File

@@ -0,0 +1,173 @@
#define LOG_MODULE "avs-boot"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "hook/iohook.h"
#include "hook/table.h"
#include "imports/avs.h"
#include "ddrhook1/avs-boot.h"
#include "ddrhook1/filesystem.h"
#include "util/log.h"
#include "util/str.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 int (*real_ea3_boot)(struct property_node *config);
static int my_ea3_boot(struct property_node *config);
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 struct net_addr ddrhook1_avs_boot_eamuse_server_addr;
static const struct hook_symbol ddrxhook_avs_hook_syms[] = {
{.name = "avs_boot",
.patch = my_avs_boot,
.link = (void **) &real_avs_boot},
};
static const struct hook_symbol ddrhook1_avs_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 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");
#if AVS_VERSION < 1002
// Only need to add these hooks for DDR X
char nvram_path[MAX_PATH] = {0};
char raw_path[MAX_PATH] = {0};
// Using the full path as part of the AVS paths seems to break on long paths.
// So instead, just take the launcher folder relative to the main game directory.
char *launcher_folder;
ddrhook1_get_launcher_path_parts(NULL, &launcher_folder);
if (launcher_folder) {
strcpy(nvram_path, launcher_folder);
strcat(nvram_path, "\\");
strcpy(raw_path, launcher_folder);
strcat(raw_path, "\\");
free(launcher_folder);
}
strcat(nvram_path, "conf\\nvram");
strcat(raw_path, "conf\\raw");
log_misc("avs paths: %s %s\n", nvram_path, raw_path);
avs_boot_replace_property_str(
config, "/fs/nvram/device", nvram_path);
avs_boot_replace_property_str(
config, "/fs/raw/device", raw_path);
#endif
real_avs_boot(
config,
std_heap,
sz_std_heap,
avs_heap,
sz_avs_heap,
log_writer_debug,
NULL);
}
static int my_ea3_boot(struct property_node *config)
{
char *server_addr;
log_info("Called my_ea3_boot");
if (ddrhook1_avs_boot_eamuse_server_addr.type != NET_ADDR_TYPE_INVALID) {
log_misc("Injecting network server address");
server_addr = net_addr_to_str(&ddrhook1_avs_boot_eamuse_server_addr);
avs_boot_replace_property_str(config, "network/services", server_addr);
free(server_addr);
}
return real_ea3_boot(config);
}
void ddrhook1_avs_boot_init()
{
hook_table_apply(
NULL,
"libavs-win32.dll",
ddrxhook_avs_hook_syms,
lengthof(ddrxhook_avs_hook_syms));
hook_table_apply(
NULL,
"libavs-win32-ea3.dll",
ddrhook1_avs_ea3_hook_syms,
lengthof(ddrhook1_avs_ea3_hook_syms));
memset(&ddrhook1_avs_boot_eamuse_server_addr, 0, sizeof(struct net_addr));
log_info("Inserted avs log hooks");
}
void ddrhook1_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(
&ddrhook1_avs_boot_eamuse_server_addr,
server_addr,
sizeof(struct net_addr));
}

View File

@@ -0,0 +1,19 @@
#ifndef DDRHOOK1_AVS_BOOT_H
#define DDRHOOK1_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 ddrhook1_avs_boot_init();
/**
* Set the target eamuse server address.
*
* @param server_addr Address to target eamuse server.
*/
void ddrhook1_avs_boot_set_eamuse_addr(const struct net_addr *server_addr);
#endif

View File

@@ -0,0 +1,128 @@
#include <string.h>
#include "cconfig/cconfig-util.h"
#include "ddrhook1/config-ddrhook1.h"
#include "util/log.h"
#define DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY "ddrhook1.use_com4_emu"
#define DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY "ddrhook1.standard_def"
#define DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY "ddrhook1.use_15khz"
#define DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED "ddrhook1.usbmem_enabled"
#define DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1 "ddrhook1.usbmem_path_p1"
#define DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2 "ddrhook1.usbmem_path_p2"
#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE true
#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE false
#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE false
#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED false
#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1 "usbmem_p1"
#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2 "usbmem_p2"
void ddrhook1_config_ddrhook1_init(struct cconfig *config)
{
cconfig_util_set_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE,
"Don't emulate P3IO COM4 and its downstream devices, use the Windows COM4 port instead");
cconfig_util_set_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE,
"SD cabinet mode");
cconfig_util_set_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE,
"Use 15 kHz monitor mode");
cconfig_util_set_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED,
"Enable USB memory data emulation");
cconfig_util_set_str(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1,
"Specify path for P1 USB memory data");
cconfig_util_set_str(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2,
"Specify path for P2 USB memory data");
}
void ddrhook1_config_ddrhook1_get(
struct ddrhook1_config_ddrhook1 *config_ddrhook1, struct cconfig *config)
{
if (!cconfig_util_get_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY,
&config_ddrhook1->use_com4_emu,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE);
}
if (!cconfig_util_get_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY,
&config_ddrhook1->standard_def,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE);
}
if (!cconfig_util_get_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY,
&config_ddrhook1->use_15khz,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE);
}
if (!cconfig_util_get_bool(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED,
&config_ddrhook1->usbmem_enabled,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED);
}
if (!cconfig_util_get_str(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1,
config_ddrhook1->usbmem_path_p1,
sizeof(config_ddrhook1->usbmem_path_p1) - 1,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1);
}
if (!cconfig_util_get_str(
config,
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2,
config_ddrhook1->usbmem_path_p2,
sizeof(config_ddrhook1->usbmem_path_p2) - 1,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2,
DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2);
}
}

View File

@@ -0,0 +1,37 @@
#ifndef DDRHOOK1_CONFIG_DDRHOOK1_H
#define DDRHOOK1_CONFIG_DDRHOOK1_H
#include <windows.h>
#include "cconfig/cconfig.h"
/**
* Struct holding configuration values for game-specific items.
*/
struct ddrhook1_config_ddrhook1 {
bool use_com4_emu;
bool standard_def;
bool use_15khz;
bool usbmem_enabled;
char usbmem_path_p1[MAX_PATH];
char usbmem_path_p2[MAX_PATH];
};
/**
* Initialize a cconfig structure with the basic structure and default values
* of this configuration.
*/
void ddrhook1_config_ddrhook1_init(struct cconfig *config);
/**
* Read the module specific config struct values from the provided cconfig
* struct.
*
* @param config_ddrhook1 Target module specific struct to read configuration
* values to.
* @param config cconfig struct holding the intermediate data to read from.
*/
void ddrhook1_config_ddrhook1_get(
struct ddrhook1_config_ddrhook1 *config_ddrhook1, struct cconfig *config);
#endif

View File

@@ -0,0 +1,144 @@
#include <string.h>
#include "cconfig/cconfig-util.h"
#include "ddrhook1/config-eamuse.h"
#include "util/log.h"
#include "util/net.h"
#define DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY "eamuse.server"
#define DDRHOOK1_CONFIG_EAMUSE_PCBID_KEY "eamuse.pcbid"
#define DDRHOOK1_CONFIG_EAMUSE_EAMID_KEY "eamuse.eamid"
#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE "localhost:80"
#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE security_id_default
#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN \
sizeof(security_id_default)
#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE security_id_default
#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN \
sizeof(security_id_default)
const struct net_addr ddrhook1_eamuse_default_server = {
.type = NET_ADDR_TYPE_HOSTNAME,
.hostname.host = "localhost",
.hostname.port = 80,
};
void ddrhook1_config_eamuse_init(struct cconfig *config)
{
cconfig_util_set_str(
config,
DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY,
DDRHOOK1_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,
DDRHOOK1_CONFIG_EAMUSE_PCBID_KEY,
(uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE,
DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN,
"PCBID");
cconfig_util_set_data(
config,
DDRHOOK1_CONFIG_EAMUSE_EAMID_KEY,
(uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE,
DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN,
"EAMID");
}
void ddrhook1_config_eamuse_get(
struct ddrhook1_config_eamuse *config_eamuse, struct cconfig *config)
{
char server_url[1024];
char *tmp;
char *tmp2;
memset(config_eamuse, 0, sizeof(struct ddrhook1_config_eamuse));
if (!cconfig_util_get_str(
config,
DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY,
server_url,
sizeof(server_url),
DDRHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY,
DDRHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE);
}
if (!net_str_parse(server_url, &config_eamuse->server)) {
memcpy(
&config_eamuse->server,
&ddrhook1_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,
DDRHOOK1_CONFIG_EAMUSE_PCBID_KEY,
(uint8_t *) &config_eamuse->pcbid,
DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN,
(uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE)) {
tmp = security_id_to_str(
&DDRHOOK1_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(
&DDRHOOK1_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,
DDRHOOK1_CONFIG_EAMUSE_EAMID_KEY,
(uint8_t *) &config_eamuse->eamid,
DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN,
(uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE)) {
tmp = security_id_to_str(
&DDRHOOK1_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(
&DDRHOOK1_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);
}
}

View File

@@ -0,0 +1,36 @@
#ifndef DDRHOOK1_CONFIG_EAMUSE_H
#define DDRHOOK1_CONFIG_EAMUSE_H
#include "cconfig/cconfig.h"
#include "security/id.h"
#include "util/net.h"
/**
* Struct holding configuration values for eamuse related items.
*/
struct ddrhook1_config_eamuse {
struct net_addr server;
struct security_id pcbid;
struct security_id eamid;
};
/**
* Initialize a cconfig structure with the basic structure and default values
* of this configuration.
*/
void ddrhook1_config_eamuse_init(struct cconfig *config);
/**
* Read the module specific config struct values from the provided cconfig
* struct.
*
* @param config_eamuse Target module specific struct to read configuration
* values to.
* @param config cconfig struct holding the intermediate data to read from.
*/
void ddrhook1_config_eamuse_get(
struct ddrhook1_config_eamuse *config_eamuse, struct cconfig *config);
#endif

View File

@@ -0,0 +1,36 @@
#include <string.h>
#include "cconfig/cconfig-util.h"
#include "ddrhook1/config-gfx.h"
#include "util/log.h"
#define DDRHOOK1_CONFIG_GFX_WINDOWED_KEY "gfx.windowed"
#define DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE true
void ddrhook1_config_gfx_init(struct cconfig *config)
{
cconfig_util_set_bool(
config,
DDRHOOK1_CONFIG_GFX_WINDOWED_KEY,
DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE,
"Run the game windowed");
}
void ddrhook1_config_gfx_get(
struct ddrhook1_config_gfx *config_gfx, struct cconfig *config)
{
if (!cconfig_util_get_bool(
config,
DDRHOOK1_CONFIG_GFX_WINDOWED_KEY,
&config_gfx->windowed,
DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
DDRHOOK1_CONFIG_GFX_WINDOWED_KEY,
DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE);
}
}

View File

@@ -0,0 +1,30 @@
#ifndef DDRHOOK1_CONFIG_GFX_H
#define DDRHOOK1_CONFIG_GFX_H
#include "cconfig/cconfig.h"
/**
* Struct holding configuration values for GFX related items.
*/
struct ddrhook1_config_gfx {
bool windowed;
};
/**
* Initialize a cconfig structure with the basic structure and default values
* of this configuration.
*/
void ddrhook1_config_gfx_init(struct cconfig *config);
/**
* Read the module specific config struct values from the provided cconfig
* struct.
*
* @param config_gfx Target module specific struct to read configuration
* values to.
* @param config cconfig struct holding the intermediate data to read from.
*/
void ddrhook1_config_gfx_get(
struct ddrhook1_config_gfx *config_gfx, struct cconfig *config);
#endif

View File

@@ -0,0 +1,75 @@
#include <string.h>
#include "cconfig/cconfig-util.h"
#include "ddrhook1/config-security.h"
#include "security/mcode.h"
#include "util/log.h"
#include "util/net.h"
#define DDRHOOK1_CONFIG_SECURITY_MCODE_KEY "security.mcode"
static const struct security_mcode security_mcode_ddr_x = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_Q,
.game = SECURITY_MCODE_GAME_DDR_X,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_REVISION_A,
};
void ddrhook1_config_security_init(struct cconfig *config)
{
char *tmp;
tmp = security_mcode_to_str(&security_mcode_ddr_x);
cconfig_util_set_str(
config,
DDRHOOK1_CONFIG_SECURITY_MCODE_KEY,
tmp,
"Mcode of the game to run.");
free(tmp);
}
void ddrhook1_config_security_get(
struct ddrhook1_config_security *config_security, struct cconfig *config)
{
char *tmp_default;
char mcode[9];
tmp_default =
security_mcode_to_str(&security_mcode_ddr_x);
if (!cconfig_util_get_str(
config,
DDRHOOK1_CONFIG_SECURITY_MCODE_KEY,
mcode,
sizeof(mcode) - 1,
tmp_default)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
DDRHOOK1_CONFIG_SECURITY_MCODE_KEY,
tmp_default);
}
mcode[8] = '\0';
if (!security_mcode_parse(mcode, &config_security->mcode)) {
log_warning(
"Invalid mcode '%s' specified, fallback to default '%s'",
mcode,
tmp_default);
memcpy(
&config_security->mcode,
&security_mcode_ddr_x,
sizeof(struct security_mcode));
}
free(tmp_default);
}

View File

@@ -0,0 +1,34 @@
#ifndef DDRHOOK1_CONFIG_SECURITY_H
#define DDRHOOK1_CONFIG_SECURITY_H
#include "cconfig/cconfig.h"
#include "security/mcode.h"
#include "util/net.h"
/**
* Struct holding configuration values for security related items.
*/
struct ddrhook1_config_security {
struct security_mcode mcode;
};
/**
* Initialize a cconfig structure with the basic structure and default values
* of this configuration.
*/
void ddrhook1_config_security_init(struct cconfig *config);
/**
* Read the module specific config struct values from the provided cconfig
* struct.
*
* @param config_security Target module specific struct to read configuration
* values to.
* @param config cconfig struct holding the intermediate data to read from.
*/
void ddrhook1_config_security_get(
struct ddrhook1_config_security *config_security, struct cconfig *config);
#endif

View File

@@ -1,4 +1,4 @@
LIBRARY ddrhook LIBRARY ddrhook1
EXPORTS EXPORTS
DllMain@12 @1 NONAME DllMain@12 @1 NONAME

196
src/main/ddrhook1/dllmain.c Normal file
View File

@@ -0,0 +1,196 @@
#include <windows.h>
#include <stdbool.h>
#include "bemanitools/ddrio.h"
#include "bemanitools/eamio.h"
#include "cconfig/cconfig-hook.h"
#include "ddrhook-util/_com4.h"
#include "ddrhook-util/extio.h"
#include "ddrhook-util/p3io.h"
#include "ddrhook-util/spike.h"
#include "ddrhook-util/usbmem.h"
#include "ddrhook1/avs-boot.h"
#include "ddrhook1/config-ddrhook1.h"
#include "ddrhook1/config-eamuse.h"
#include "ddrhook1/config-gfx.h"
#include "ddrhook1/config-security.h"
#include "ddrhook1/filesystem.h"
#include "ddrhook1/master.h"
#include "ddrhook-util/gfx.h"
#include "hook/iohook.h"
#include "hook/table.h"
#include "hooklib/app.h"
#include "hooklib/rs232.h"
#include "imports/avs.h"
#include "p3ioemu/emu.h"
#include "security/rp-sign-key.h"
#include "util/cmdline.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/thread.h"
#define DDRHOOK1_INFO_HEADER \
"ddrhook1 for DDR X" \
", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)
#define DDRHOOK1_CMD_USAGE \
"Usage: inject.exe ddrhook1.dll <ddr.exe> [options...]"
bool standard_def;
bool _15khz;
static const hook_d3d9_irp_handler_t ddrhook1_d3d9_handlers[] = {
gfx_d3d9_irp_handler,
};
static DWORD STDCALL my_GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
static DWORD(STDCALL *real_GetModuleFileNameA)(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
static bool ddrhook1_init_check = false;
static const struct hook_symbol init_hook_syms[] = {
{
.name = "GetModuleFileNameA",
.patch = my_GetModuleFileNameA,
.link = (void **) &real_GetModuleFileNameA,
},
};
static DWORD STDCALL
my_GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
{
bool ok;
struct cconfig *config;
struct ddrhook1_config_ddrhook1 config_ddrhook1;
struct ddrhook1_config_eamuse config_eamuse;
struct ddrhook1_config_gfx config_gfx;
struct ddrhook1_config_security config_security;
if (ddrhook1_init_check)
goto skip;
log_info("--- Begin ddrhook1 main ---");
ddrhook1_init_check = true;
config = cconfig_init();
ddrhook1_config_ddrhook1_init(config);
ddrhook1_config_eamuse_init(config);
ddrhook1_config_gfx_init(config);
ddrhook1_config_security_init(config);
if (!cconfig_hook_config_init(
config,
DDRHOOK1_INFO_HEADER "\n" DDRHOOK1_CMD_USAGE,
CCONFIG_CMD_USAGE_OUT_DBG)) {
cconfig_finit(config);
exit(EXIT_FAILURE);
}
ddrhook1_config_ddrhook1_get(&config_ddrhook1, config);
ddrhook1_config_eamuse_get(&config_eamuse, config);
ddrhook1_config_gfx_get(&config_gfx, config);
ddrhook1_config_security_get(&config_security, config);
cconfig_finit(config);
standard_def = config_ddrhook1.standard_def;
_15khz = config_ddrhook1.use_15khz;
log_info(DDRHOOK1_INFO_HEADER);
log_info("Initializing ddrhook1...");
ddrhook1_filesystem_hook_init();
ddrhook1_avs_boot_init();
ddrhook1_avs_boot_set_eamuse_addr(&config_eamuse.server);
iohook_push_handler(p3io_emu_dispatch_irp);
iohook_push_handler(extio_dispatch_irp);
iohook_push_handler(spike_dispatch_irp);
iohook_push_handler(usbmem_dispatch_irp);
if (config_ddrhook1.use_com4_emu) {
/* See ddrhook-util/p3io.c for details. */
iohook_push_handler(com4_dispatch_irp);
}
if (config_gfx.windowed) {
gfx_set_windowed();
}
rs232_hook_init();
p3io_ddr_init_with_plugs(
&config_security.mcode,
&config_eamuse.pcbid,
&config_eamuse.eamid,
#if AVS_VERSION >= 1002
&security_rp_sign_key_black_ddrx2,
#else
&security_rp_sign_key_black_ddrx,
#endif
&security_rp_sign_key_white_eamuse);
extio_init();
usbmem_init(config_ddrhook1.usbmem_path_p1, config_ddrhook1.usbmem_path_p2,
config_ddrhook1.usbmem_enabled);
spike_init();
com4_init();
log_info("Initializing DDR IO backend");
ok = ddr_io_init(thread_create, thread_join, thread_destroy);
if (!ok) {
log_fatal("Couldn't initialize DDR IO backend");
return false;
}
if (config_ddrhook1.use_com4_emu) {
log_info("Initializing card reader backend");
eam_io_set_loggers(
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
ok = eam_io_init(thread_create, thread_join, thread_destroy);
if (!ok) {
log_fatal("Couldn't initialize card reader backend");
return false;
}
}
log_info("--- End ddrhook1 main ---");
skip:
return real_GetModuleFileNameA(hModule, lpFilename, nSize);
}
BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx)
{
if (reason == DLL_PROCESS_ATTACH) {
log_to_writer(log_writer_debug, NULL);
hook_table_apply(
NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms));
ddrhook1_master_insert_hooks(NULL);
ddrhook1_filesystem_hook_init();
hook_d3d9_init(ddrhook1_d3d9_handlers, lengthof(ddrhook1_d3d9_handlers));
}
return TRUE;
}

View File

@@ -0,0 +1,327 @@
#include <windows.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/str.h"
static BOOL STDCALL my_SetCurrentDirectoryA(LPCSTR lpPathName);
static HANDLE STDCALL my_FindFirstFileW(
LPCWSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData);
static HANDLE STDCALL my_CreateFileW(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static BOOL WINAPI my_CreateDirectoryW(
LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
static BOOL(STDCALL *real_SetCurrentDirectoryA)(LPCSTR lpPathName);
static HANDLE(STDCALL *real_FindFirstFileW)(
LPCWSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData);
static HANDLE(STDCALL *real_CreateFileW)(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static BOOL(WINAPI *real_CreateDirectoryW)(
LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
static const struct hook_symbol filesystem_hook_syms[] = {
{
.name = "CreateFileW",
.patch = my_CreateFileW,
.link = (void **) &real_CreateFileW
},
{
.name = "SetCurrentDirectoryA",
.patch = my_SetCurrentDirectoryA,
.link = (void **) &real_SetCurrentDirectoryA,
},
{
.name = "FindFirstFileW",
.patch = my_FindFirstFileW,
.link = (void **) &real_FindFirstFileW
},
{
.name = "CreateDirectoryW",
.patch = my_CreateDirectoryW,
.link = (void **) &real_CreateDirectoryW
},
};
void ddrhook1_get_launcher_path_parts(char **output_path, char **output_foldername) {
char module_path[MAX_PATH];
char launcher_path[MAX_PATH];
memset(launcher_path, 0, MAX_PATH);
if (output_path != NULL)
*output_path = NULL;
if (output_foldername != NULL)
*output_foldername = NULL;
if (GetModuleFileNameA(NULL, module_path, sizeof(module_path)) == 0)
return;
char *filename_ptr = NULL;
if (GetFullPathNameA(module_path, sizeof(launcher_path), launcher_path, &filename_ptr) == 0)
return;
if (filename_ptr != NULL)
launcher_path[strlen(launcher_path) - strlen(filename_ptr) - 1] = 0;
// Trim tailing slashes
for (int i = strlen(launcher_path) - 1; i > 0; i--) {
if (launcher_path[i] != '\\' && launcher_path[i] != '/')
break;
launcher_path[i] = 0;
}
int idx_folder = 0;
for (idx_folder = strlen(launcher_path); idx_folder - 1 > 0; idx_folder--) {
if (launcher_path[idx_folder - 1] == '\\' || launcher_path[idx_folder - 1] == '/') {
break;
}
}
if (output_foldername != NULL) {
int len = strlen(launcher_path) - idx_folder;
if (len < 0)
len = 0;
*output_foldername = (char*)xmalloc(len + 2);
memset(*output_foldername, 0, len + 1);
strncpy(*output_foldername, launcher_path + idx_folder, len);
}
if (output_path != NULL) {
size_t len = idx_folder - 1 < 0 ? 0 : idx_folder - 1;
if (len > strlen(launcher_path))
len = strlen(launcher_path);
*output_path = (char*)xmalloc(len + 1);
memset(*output_path, 0, len + 1);
strncpy(*output_path, launcher_path, len);
}
}
static wchar_t *ddrhook1_filesystem_get_path(LPCWSTR path)
{
wchar_t *new_path = NULL;
// char *tmp;
// wstr_narrow(path, &tmp);
// log_misc("path: %s", tmp);
// free(tmp);
// Deal with hardcoded paths: D:/HDX, E:/conf, E:/conf/nvram, E:/conf/raw, F:/update, ...
if (wstr_insensitive_eq(path, L"D:/HDX") || wstr_insensitive_eq(path, L"D:\\HDX")
|| wstr_insensitive_eq(path, L"D:/JDX") || wstr_insensitive_eq(path, L"D:\\JDX")) {
char *_new_path;
ddrhook1_get_launcher_path_parts(&_new_path, NULL);
if (_new_path) {
new_path = str_widen(_new_path);
return new_path;
}
} else if (wcslen(path) >= 7 && (wcsnicmp(path, L"E:/conf", 7) == 0
|| wcsnicmp(path, L"E:\\conf", 7) == 0)) {
char *launcher_folder;
wchar_t *sub_path;
ddrhook1_get_launcher_path_parts(NULL, &launcher_folder);
sub_path = wcsstr(path, L"conf");
if (sub_path && launcher_folder) {
wchar_t *launcher_folder_w = str_widen(launcher_folder);
new_path = (wchar_t*)xmalloc(MAX_PATH * sizeof(wchar_t));
swprintf(new_path, MAX_PATH, L"%s\\%s", launcher_folder_w, sub_path);
free(launcher_folder_w);
return new_path;
}
} else if (wstr_insensitive_eq(path, L"F:/update")
|| wstr_insensitive_eq(path, L"F:\\update")
|| wstr_insensitive_eq(path, L".\\F:/update")
|| wstr_insensitive_eq(path, L".\\F:\\update")) {
char *launcher_folder;
wchar_t *sub_path;
ddrhook1_get_launcher_path_parts(NULL, &launcher_folder);
sub_path = wcsstr(path, L"update");
if (sub_path && launcher_folder) {
wchar_t *launcher_folder_w = str_widen(launcher_folder);
new_path = (wchar_t*)xmalloc(MAX_PATH * sizeof(wchar_t));
swprintf(new_path, MAX_PATH, L"%s\\%s", launcher_folder_w, sub_path);
free(launcher_folder_w);
return new_path;
}
} else if (wcslen(path) >= 24 && (wcsnicmp(path, L"D:/JDX/JDX-001/contents/", 24) == 0
|| wcsnicmp(path, L"D:\\JDX\\JDX-001\\contents\\", 24) == 0)) {
char *content_path;
ddrhook1_get_launcher_path_parts(&content_path, NULL);
if (content_path) {
wchar_t *content_path_w = str_widen(content_path);
new_path = (wchar_t*)xmalloc(MAX_PATH * sizeof(wchar_t));
swprintf(new_path, MAX_PATH, L"%s\\%s", content_path_w, path + 24);
free(content_path_w);
return new_path;
}
} else if (wcslen(path) >= 7 && (wcsnicmp(path, L"D:/HDX/", 7) == 0 || wcsnicmp(path, L"D:\\HDX\\", 7) == 0
|| wcsnicmp(path, L"D:/JDX/", 7) == 0 || wcsnicmp(path, L"D:\\JDX\\", 7) == 0)) {
char *content_path;
ddrhook1_get_launcher_path_parts(&content_path, NULL);
if (content_path) {
wchar_t *content_path_w = str_widen(content_path);
new_path = (wchar_t*)xmalloc(MAX_PATH * sizeof(wchar_t));
swprintf(new_path, MAX_PATH, L"%s\\%s", content_path_w, path + 7);
free(content_path_w);
return new_path;
}
}
return NULL;
}
static BOOL STDCALL my_SetCurrentDirectoryA(LPCSTR lpPathName)
{
wchar_t *_lpPathName = str_widen(lpPathName);
wchar_t *_new_path = ddrhook1_filesystem_get_path(_lpPathName);
char *new_path = NULL;
if (_lpPathName != NULL) {
free(_lpPathName);
}
if (_new_path != NULL) {
wstr_narrow(_new_path, &new_path);
free(_new_path);
}
if (new_path != NULL) {
bool r = real_SetCurrentDirectoryA(new_path);
log_misc("SetCurrentDirectoryA remapped path %s -> %s", lpPathName, new_path);
free(new_path);
return r;
}
return real_SetCurrentDirectoryA(lpPathName);
}
static HANDLE STDCALL my_FindFirstFileW(
LPCWSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData)
{
wchar_t *new_path = ddrhook1_filesystem_get_path(lpFileName);
if (new_path) {
HANDLE r = real_FindFirstFileW(
new_path,
lpFindFileData);
char *tmp;
wstr_narrow(new_path, &tmp);
log_misc("FindFirstFileW remapped path: %s", tmp);
free(tmp);
free(new_path);
return r;
}
return real_FindFirstFileW(
lpFileName,
lpFindFileData);
}
static HANDLE STDCALL my_CreateFileW(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
wchar_t *new_path = ddrhook1_filesystem_get_path(lpFileName);
if (new_path) {
HANDLE r = real_CreateFileW(
new_path,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
// char *tmp;
// wstr_narrow(new_path, &tmp);
// log_misc("CreateFileW remapped path %s", tmp);
// free(tmp);
free(new_path);
return r;
}
return real_CreateFileW(
new_path ? new_path : lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
BOOL WINAPI my_CreateDirectoryW(
LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
wchar_t *new_path = ddrhook1_filesystem_get_path(lpPathName);
if (new_path) {
BOOL r = real_CreateDirectoryW(new_path, lpSecurityAttributes);
char *tmp;
wstr_narrow(new_path, &tmp);
log_misc("CreateDirectoryW remapped path %s", tmp);
free(tmp);
free(new_path);
return r;
}
return real_CreateDirectoryW(lpPathName, lpSecurityAttributes);
}
void ddrhook1_filesystem_hook_init()
{
hook_table_apply(
NULL, "kernel32.dll", filesystem_hook_syms, lengthof(filesystem_hook_syms));
log_info("Inserted filesystem hooks");
}

View File

@@ -0,0 +1,16 @@
#ifndef DDRHOOK1_FILESYSTEM_H
#define DDRHOOK1_FILESYSTEM_H
/**
* DDR sets the current directory on boot to "D:/HDX" and then uses
* relative file paths for everything else.
* This function is a helper function to make it easier to turn a path
* into an absolute path relative to the launcher ("D:/HDX/ddr_datecode")
* and not the current working directory ("D:/HDX") so that settings
* can be saved in the same manner as every other game.
*/
char *ddrhook1_get_launcher_path_parts();
void ddrhook1_filesystem_hook_init();
#endif

View File

@@ -0,0 +1,85 @@
#include "ddrhook1/master.h"
#include "ddrhook-util/dinput.h"
#include "ddrhook-util/gfx.h"
#include "ddrhook-util/monitor.h"
#include "hook/table.h"
#include "p3ioemu/devmgr.h"
#include "util/defs.h"
#include "util/log.h"
static HMODULE(STDCALL *real_LoadLibraryA)(const char *name);
static BOOL(STDCALL *real_IsDebuggerPresent)();
static HMODULE STDCALL my_LoadLibraryA(const char *name);
static BOOL STDCALL my_IsDebuggerPresent();
static const struct hook_symbol master_kernel32_syms[] = {
{
.name = "LoadLibraryA",
.patch = my_LoadLibraryA,
.link = (void **) &real_LoadLibraryA,
},
{
.name = "IsDebuggerPresent",
.patch = my_IsDebuggerPresent,
.link = (void **) &real_IsDebuggerPresent,
},
};
static BOOL STDCALL my_IsDebuggerPresent()
{
// DDR X has different code paths for when a debugger is attached,
// but we want the normal path and not the debugger path.
// The biggest noticeable difference is that when a debugger is attached
// it will show fway.mpg (a car driving) instead of the sky background
// on the menus.
return FALSE;
}
static HMODULE STDCALL my_LoadLibraryA(const char *name)
{
HMODULE result;
result = GetModuleHandleA(name);
if (result != NULL) {
log_misc("LoadLibraryA(%s) -> %p [already loaded]", name, result);
return result;
}
result = real_LoadLibraryA(name);
log_misc("LoadLibraryA(%s) -> %p [newly loaded]", name, result);
if (result == NULL) {
return result;
}
ddrhook1_master_insert_hooks(result);
return result;
}
void ddrhook1_master_insert_hooks(HMODULE target)
{
/* Insert all other hooks here */
p3io_setupapi_insert_hooks(target);
monitor_setupapi_insert_hooks(target);
gfx_insert_hooks(target);
dinput_init(target);
/* Insert dynamic loader hooks so that we can hook late-loaded modules */
hook_table_apply(
target,
"kernel32.dll",
master_kernel32_syms,
lengthof(master_kernel32_syms));
log_info("Inserted dynamic loader hooks into %p", target);
}

View File

@@ -0,0 +1,8 @@
#ifndef DDRHOOK1_MASTER_H
#define DDRHOOK1_MASTER_H
#include <windows.h>
void ddrhook1_master_insert_hooks(HMODULE target);
#endif

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