mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-09-15 03:45:09 -05:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efca967553 | ||
|
|
6c1bb3db82 | ||
|
|
bec809fbaa | ||
|
|
9775f2c853 | ||
|
|
26c9d7fe0a | ||
|
|
6b81cd7535 | ||
|
|
b3b6c3f499 | ||
|
|
0586ea50aa | ||
|
|
cafa60d0f6 | ||
|
|
76c2c49c13 | ||
|
|
6d38aa5f4a | ||
|
|
c1c5685e3a | ||
|
|
050e52b21e | ||
|
|
ab50c70f71 | ||
|
|
2223947dd8 | ||
|
|
0294eed22b | ||
|
|
d7235c3c2c | ||
|
|
402d0d4ca4 | ||
|
|
89fe822919 | ||
|
|
75583897c1 | ||
|
|
58d297458c | ||
|
|
ba528488f0 | ||
|
|
7692e14b0b | ||
|
|
4cc81f48f3 | ||
|
|
da736d2968 | ||
|
|
c3f9ce7e91 | ||
|
|
41de45d459 | ||
|
|
bda239a2ba | ||
|
|
1e32d1a9a8 | ||
|
|
852d770629 | ||
|
|
4be866e69e | ||
|
|
537b1fa384 | ||
|
|
bd2d722031 | ||
|
|
4f8f6c0f7a | ||
|
|
51a018b0cf | ||
|
|
04442a6dbc | ||
|
|
85a080e6b3 | ||
|
|
28633ded37 | ||
|
|
721897d7b0 | ||
|
|
926bbf2e10 | ||
|
|
ce75e149f7 | ||
|
|
57d9d976ff | ||
|
|
7e731916e2 | ||
|
|
dd9b8faafe |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -2,6 +2,16 @@
|
||||
Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions
|
||||
given in tags. The pipeline will pick this up and cuts out the relevant section for release notes.
|
||||
|
||||
## 5.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
|
||||
* sdvxhook2: Support sound voltex exceed gear
|
||||
|
||||
|
||||
88
Module.mk
88
Module.mk
@@ -93,7 +93,8 @@ include src/main/cconfig/Module.mk
|
||||
include src/main/config/Module.mk
|
||||
include src/main/d3d9exhook/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-smx/Module.mk
|
||||
include src/main/ddrio/Module.mk
|
||||
@@ -142,6 +143,7 @@ include src/main/jbio-p4io/Module.mk
|
||||
include src/main/jbio/Module.mk
|
||||
include src/main/jbiotest/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/jbhook2/Module.mk
|
||||
include src/main/jbhook3/Module.mk
|
||||
@@ -565,10 +567,48 @@ $(zipdir)/sdvx-hwio-x64.zip: \
|
||||
$(V)echo ... $@
|
||||
$(V)zip -j $@ $^
|
||||
|
||||
$(zipdir)/ddr-12-to-16.zip: \
|
||||
build/bin/avs2_1508-32/launcher.exe \
|
||||
build/bin/avs2_1508-32/ddrhook.dll \
|
||||
build/bin/avs2_1508-32/unicorntail.dll \
|
||||
$(zipdir)/ddr-11.zip: \
|
||||
build/bin/indep-32/inject.exe \
|
||||
build/bin/avs2_803-32/ddrhook1.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/ddrio.dll \
|
||||
build/bin/indep-32/ddrio-mm.dll \
|
||||
@@ -577,7 +617,37 @@ $(zipdir)/ddr-12-to-16.zip: \
|
||||
build/bin/indep-32/geninput.dll \
|
||||
dist/ddr/config.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 \
|
||||
| $(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-15.bat \
|
||||
dist/ddr/gamestart-16.bat \
|
||||
@@ -587,7 +657,7 @@ $(zipdir)/ddr-12-to-16.zip: \
|
||||
|
||||
$(zipdir)/ddr-16-x64.zip: \
|
||||
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/indep-64/config.exe \
|
||||
build/bin/indep-64/ddrio.dll \
|
||||
@@ -649,7 +719,11 @@ $(BUILDDIR)/tests.zip: \
|
||||
|
||||
$(BUILDDIR)/bemanitools.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)/doc.zip \
|
||||
$(zipdir)/iidx-09-to-12.zip \
|
||||
|
||||
97
README.md
97
README.md
@@ -1,7 +1,7 @@
|
||||
# Bemanitools 5
|
||||
[](https://dev.s-ul.net/djhackers/bemanitools/commits/master)
|
||||
|
||||
Version: 5.38
|
||||
Version: 5.40
|
||||
|
||||
[Release history](CHANGELOG.md)
|
||||
|
||||
@@ -26,54 +26,57 @@ 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)
|
||||
* [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 (bst.zip) using bsthook
|
||||
* BeatStream アニムトライヴ (bst.zip) using bsthook
|
||||
* Dance Dance Revolution
|
||||
* Dance Dance Revolution X2 (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution X3 vs. 2ndMIX (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution 2013 (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution 2014 (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution A (ddr-12-to-16.zip) using ddrhook
|
||||
* Beatmania IIDX
|
||||
* Beatmania IIDX 9th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 10th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 11 IIDX RED (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 12 HAPPY SKY (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 13 DistorteD (iidx-13.zip) using [iidxhook2](doc/iidxhook/iidxhook2.md)
|
||||
* Beatmania IIDX 14 GOLD (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 15 DJ TROOPERS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 16 EMPRESS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 17 SIRIUS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 18 Resort Anthem (iidx-18.zip) using [iidxhook4](doc/iidxhook/iidxhook4.md)
|
||||
* Beatmania IIDX 19 Lincle (iidx-19.zip) using [iidxhook5](doc/iidxhook/iidxhook5.md)
|
||||
* Beatmania IIDX 20 Tricoro (iidx-20.zip) using [iidxhook6](doc/iidxhook/iidxhook6.md)
|
||||
* Beatmania IIDX 21 SPADA (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 22 PENDUAL (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 23 copula (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 24 SINOBUZ (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 25 CANNON BALLERS (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md)
|
||||
* Beatmania IIDX 26 Rootage (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md)
|
||||
* Beatmania IIDX 27 Heroic Verse (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
|
||||
* Beatmania IIDX 28 BISTROVER (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
|
||||
* jubeat
|
||||
* jubeat (jb-01.zip) using [jbhook1](doc/jbhook/jbhook1.md)
|
||||
* jubeat ripples (jb-02.zip) using [jbhook1](doc/jbhook/jbhook1.md)
|
||||
* jubeat knit (jb-03.zip) using [jbhook2](doc/jbhook/jbhook2.md)
|
||||
* jubeat copious (jb-04.zip) using [jbhook2](doc/jbhook/jbhook2.md)
|
||||
* jubeat saucer (fulfill) (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat prop (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat qubell (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat clan (jb-08.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat festo (jb-08.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* BeatStream (`bst.zip`): bsthook
|
||||
* BeatStream アニムトライヴ (`bst.zip`): bsthook
|
||||
* [Dance Dance Revolution](doc/ddrhook/README.md)
|
||||
* Dance Dance Revolution X (`ddr-11.zip`): [ddrhook1](doc/ddrhook/ddrhook1.md)
|
||||
* Dance Dance Revolution X2 (US/EU regions) (`ddr-12-us.zip`): [ddrhook1](doc/ddrhook/ddrhook1.md)
|
||||
* Dance Dance Revolution X2 (JP region) (`ddr-12.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
|
||||
* Dance Dance Revolution 2013 (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
|
||||
* Dance Dance Revolution 2014 (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
|
||||
* Dance Dance Revolution A (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
|
||||
* [Beatmania IIDX](doc/iidxhook/README.md)
|
||||
* Beatmania IIDX 9th Style (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 10th Style (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 11 IIDX RED (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 12 HAPPY SKY (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 13 DistorteD (`iidx-13.zip`): [iidxhook2](doc/iidxhook/iidxhook2.md)
|
||||
* Beatmania IIDX 14 GOLD (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 15 DJ TROOPERS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 16 EMPRESS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 17 SIRIUS (`iidx-14-to-17.zip`): [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 18 Resort Anthem (`iidx-18.zip`): [iidxhook4](doc/iidxhook/iidxhook4.md)
|
||||
* Beatmania IIDX 19 Lincle (`iidx-19.zip`): [iidxhook5](doc/iidxhook/iidxhook5.md)
|
||||
* Beatmania IIDX 20 Tricoro (`iidx-20.zip`): [iidxhook6](doc/iidxhook/iidxhook6.md)
|
||||
* Beatmania IIDX 21 SPADA (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 22 PENDUAL (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 23 copula (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 24 SINOBUZ (`iidx-21-to-24.zip`): [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 25 CANNON BALLERS (`iidx-25-to-26.zip`): [iidxhook8](doc/iidxhook/iidxhook8.md)
|
||||
* Beatmania IIDX 26 Rootage (`iidx-25-to-26.zip`): [iidxhook8](doc/iidxhook/iidxhook8.md)
|
||||
* Beatmania IIDX 27 Heroic Verse (`iidx-27-to-28.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
|
||||
* Beatmania IIDX 28 BISTROVER (`iidx-27-to-28.zip`): [iidxhook9](doc/iidxhook/iidxhook9.md)
|
||||
* [jubeat](doc/jbhook/README.md)
|
||||
* jubeat (`jb-01.zip`): [jbhook1](doc/jbhook/jbhook1.md)
|
||||
* jubeat ripples (`jb-02.zip`): [jbhook1](doc/jbhook/jbhook1.md)
|
||||
* jubeat knit (`jb-03.zip`): [jbhook2](doc/jbhook/jbhook2.md)
|
||||
* jubeat copious (`jb-04.zip`): [jbhook2](doc/jbhook/jbhook2.md)
|
||||
* jubeat saucer (fulfill) (`jb-05-to-07.zip`): [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat prop (`jb-05-to-07.zip`): [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat qubell (`jb-05-to-07.zip`): [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat clan (`jb-08.zip`): [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* jubeat festo (`jb-08.zip`): [jbhook3](doc/jbhook/jbhook3.md)
|
||||
* SOUND VOLTEX
|
||||
* SOUND VOLTEX BOOTH (sdvx-01-to-04.zip) using sdvxhook
|
||||
* SOUND VOLTEX II -infinite infection- (sdvx-01-to-04.zip) using sdvxhook
|
||||
* SOUND VOLTEX III GRAVITY WARS (sdvx-01-to-04.zip) using sdvxhook
|
||||
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx-01-to-04.zip) using sdvxhook
|
||||
* SOUND VOLTEX Vivid Wave (sdvx-05-to-06) using sdvxhook2
|
||||
* SOUND VOLTEX EXCEED GEAR (sdvx-05-to-06) using sdvxhook2
|
||||
* SOUND VOLTEX BOOTH (`sdvx-01-to-04.zip`): sdvxhook
|
||||
* SOUND VOLTEX II -infinite infection- (`sdvx-01-to-04.zip`): sdvxhook
|
||||
* SOUND VOLTEX III GRAVITY WARS (`sdvx-01-to-04.zip`): sdvxhook
|
||||
* SOUND VOLTEX IV HEAVENLY HAVEN (`sdvx-01-to-04.zip`): sdvxhook
|
||||
* SOUND VOLTEX Vivid Wave (`sdvx-05-to-06`): sdvxhook2
|
||||
* SOUND VOLTEX EXCEED GEAR (`sdvx-05-to-06`): sdvxhook2
|
||||
|
||||
## ViGEm clients: Expose BT5 APIs as XBOX game controllers
|
||||
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that
|
||||
|
||||
32
dist/ddr/ddr-11-us.conf
vendored
Normal file
32
dist/ddr/ddr-11-us.conf
vendored
Normal 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
32
dist/ddr/ddr-11.conf
vendored
Normal 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
32
dist/ddr/ddr-12-eu.conf
vendored
Normal 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
32
dist/ddr/ddr-12-us.conf
vendored
Normal 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
11
dist/ddr/gamestart-11-us.bat
vendored
Normal 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
11
dist/ddr/gamestart-11.bat
vendored
Normal 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
11
dist/ddr/gamestart-12-eu.bat
vendored
Normal 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
11
dist/ddr/gamestart-12-us.bat
vendored
Normal 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 %*
|
||||
2
dist/ddr/gamestart-12.bat
vendored
2
dist/ddr/gamestart-12.bat
vendored
@@ -8,4 +8,4 @@ if not exist conf\raw mkdir conf\raw
|
||||
regsvr32 /s k-clvsd.dll
|
||||
regsvr32 /s xactengine2_10.dll
|
||||
|
||||
.\launcher.exe -K .\ddrhook.dll .\ddr.dll %*
|
||||
.\launcher.exe -K .\ddrhook2.dll .\ddr.dll %*
|
||||
|
||||
2
dist/ddr/gamestart-13.bat
vendored
2
dist/ddr/gamestart-13.bat
vendored
@@ -8,4 +8,4 @@ if not exist conf\raw mkdir conf\raw
|
||||
regsvr32 /s k-clvsd.dll
|
||||
regsvr32 /s xactengine2_10.dll
|
||||
|
||||
.\launcher.exe -K .\ddrhook.dll .\ddr.dll %*
|
||||
.\launcher.exe -K .\ddrhook2.dll .\ddr.dll %*
|
||||
|
||||
2
dist/ddr/gamestart-14.bat
vendored
2
dist/ddr/gamestart-14.bat
vendored
@@ -11,4 +11,4 @@ if not exist conf\raw mkdir conf\raw
|
||||
regsvr32 /s k-clvsd.dll
|
||||
regsvr32 /s xactengine2_10.dll
|
||||
|
||||
.\launcher.exe -K .\ddrhook.dll .\mdxja_945.dll %*
|
||||
.\launcher.exe -K .\ddrhook2.dll .\mdxja_945.dll %*
|
||||
|
||||
2
dist/ddr/gamestart-15.bat
vendored
2
dist/ddr/gamestart-15.bat
vendored
@@ -11,4 +11,4 @@ if not exist conf\raw mkdir conf\raw
|
||||
regsvr32 /s k-clvsd.dll
|
||||
regsvr32 /s xactengine2_10.dll
|
||||
|
||||
.\launcher.exe -K .\ddrhook.dll .\mdxja_945.dll %*
|
||||
.\launcher.exe -K .\ddrhook2.dll .\mdxja_945.dll %*
|
||||
|
||||
2
dist/ddr/gamestart-16.bat
vendored
2
dist/ddr/gamestart-16.bat
vendored
@@ -12,4 +12,4 @@ if not exist conf\raw mkdir conf\raw
|
||||
regsvr32 /s com\k-clvsd.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 %*
|
||||
|
||||
5
dist/iidx/iidxhook-14.conf
vendored
5
dist/iidx/iidxhook-14.conf
vendored
@@ -46,8 +46,5 @@ gfx.device_adapter=-1
|
||||
# Disable operator clock setting system clock time
|
||||
misc.disable_clock_set=false
|
||||
|
||||
# Security boot version (e.g. GEC02).
|
||||
sec.boot_version=GQGLDJAA
|
||||
|
||||
# Security black plug mcode id string (e.g. GQC02JAA).
|
||||
sec.black_plug_mcode=GQGLDJA
|
||||
sec.black_plug_mcode=GQGLDJAA
|
||||
5
dist/iidx/iidxhook-15.conf
vendored
5
dist/iidx/iidxhook-15.conf
vendored
@@ -46,8 +46,5 @@ gfx.device_adapter=-1
|
||||
# Disable operator clock setting system clock time
|
||||
misc.disable_clock_set=false
|
||||
|
||||
# Security boot version (e.g. GEC02).
|
||||
sec.boot_version=GQHDDJAA
|
||||
|
||||
# Security black plug mcode id string (e.g. GQC02JAA).
|
||||
sec.black_plug_mcode=GQHDDJA
|
||||
sec.black_plug_mcode=GQHDDJAA
|
||||
5
dist/iidx/iidxhook-16.conf
vendored
5
dist/iidx/iidxhook-16.conf
vendored
@@ -49,8 +49,5 @@ gfx.device_adapter=-1
|
||||
# Disable operator clock setting system clock time
|
||||
misc.disable_clock_set=false
|
||||
|
||||
# Security boot version (e.g. GEC02).
|
||||
sec.boot_version=GQI00JAA
|
||||
|
||||
# Security black plug mcode id string (e.g. GQC02JAA).
|
||||
sec.black_plug_mcode=GQI00JA
|
||||
sec.black_plug_mcode=GQI00JAA
|
||||
5
dist/iidx/iidxhook-17.conf
vendored
5
dist/iidx/iidxhook-17.conf
vendored
@@ -49,8 +49,5 @@ gfx.device_adapter=-1
|
||||
# Disable operator clock setting system clock time
|
||||
misc.disable_clock_set=false
|
||||
|
||||
# Security boot version (e.g. GEC02).
|
||||
sec.boot_version=GCJDJJAA
|
||||
|
||||
# Security black plug mcode id string (e.g. GQC02JAA).
|
||||
sec.black_plug_mcode=GCJDJJA
|
||||
sec.black_plug_mcode=GCJDJJAA
|
||||
2
dist/jb/gamestart-02.bat
vendored
2
dist/jb/gamestart-02.bat
vendored
@@ -2,4 +2,6 @@
|
||||
|
||||
cd /d %~dp0
|
||||
|
||||
if not exist dev\nvram mkdir dev\nvram
|
||||
|
||||
inject jbhook1.dll jubeat.exe --config jbhook-02.conf %*
|
||||
|
||||
2
dist/jb/gamestart-03.bat
vendored
2
dist/jb/gamestart-03.bat
vendored
@@ -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\raw mkdir dev\raw
|
||||
|
||||
launcher -H 33554432 -K jbhook2.dll jubeat.dll
|
||||
launcher -H 33554432 -K jbhook2.dll jubeat.dll -v
|
||||
|
||||
2
dist/jb/jbhook-01.conf
vendored
2
dist/jb/jbhook-01.conf
vendored
@@ -2,7 +2,7 @@
|
||||
gfx.windowed=false
|
||||
|
||||
# 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.
|
||||
eamuse.server=localhost:80
|
||||
|
||||
2
dist/jb/jbhook-02.conf
vendored
2
dist/jb/jbhook-02.conf
vendored
@@ -2,7 +2,7 @@
|
||||
gfx.windowed=false
|
||||
|
||||
# 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.
|
||||
eamuse.server=localhost:80
|
||||
|
||||
49
doc/ddrhook/README.md
Normal file
49
doc/ddrhook/README.md
Normal 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
139
doc/ddrhook/ddrhook1.md
Normal 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
80
doc/ddrhook/ddrhook2.md
Normal 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..
|
||||
@@ -32,6 +32,8 @@ EXPORTS
|
||||
property_node_type
|
||||
property_node_traversal
|
||||
property_node_refdata
|
||||
property_psmap_export
|
||||
property_psmap_import
|
||||
std_getenv
|
||||
std_setenv
|
||||
std_setenv
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@ struct ac_io_kfca_poll_in {
|
||||
|
||||
struct ac_io_kfca_poll_out {
|
||||
uint32_t gpio;
|
||||
uint8_t pwm[18];
|
||||
uint8_t unk[2];
|
||||
uint8_t pwm[20];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -33,6 +33,7 @@ enum sdvx_io_out_gpio_bit {
|
||||
SDVX_IO_OUT_GPIO_D = 0,
|
||||
SDVX_IO_OUT_GPIO_FX_L = 1,
|
||||
SDVX_IO_OUT_GPIO_FX_R = 2,
|
||||
SDVX_IO_OUT_GPIO_GENERATOR_B = 3,
|
||||
SDVX_IO_OUT_GPIO_START = 12,
|
||||
SDVX_IO_OUT_GPIO_A = 13,
|
||||
SDVX_IO_OUT_GPIO_B = 14,
|
||||
|
||||
@@ -11,3 +11,8 @@ src_ddrhook-util := \
|
||||
guid.c \
|
||||
misc.c \
|
||||
monitor.c \
|
||||
extio.c \
|
||||
_com4.c \
|
||||
usbmem.c \
|
||||
spike.c \
|
||||
p3io.c \
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "bemanitools/ddrio.h"
|
||||
|
||||
#include "ddrhook/_com4.h"
|
||||
#include "ddrhook-util/_com4.h"
|
||||
|
||||
#include "hook/iohook.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef IIDXHOOK_COM4_H
|
||||
#define IIDXHOOK_COM4_H
|
||||
#ifndef DDRHOOK_UTIL_COM4_H
|
||||
#define DDRHOOK_UTIL_COM4_H
|
||||
|
||||
#include "hook/iohook.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef HOOK_DINPUT_H
|
||||
#define HOOK_DINPUT_H
|
||||
#ifndef DDRHOOK_UTIL_DINPUT_H
|
||||
#define DDRHOOK_UTIL_DINPUT_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef DDRHOOK_EXTIO_H
|
||||
#define DDRHOOK_EXTIO_H
|
||||
#ifndef DDRHOOK_UTIL_EXTIO_H
|
||||
#define DDRHOOK_UTIL_EXTIO_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@@ -1,88 +1,152 @@
|
||||
// TODO: Fix gray arrows on NVIDIA cards (also applies to X3)
|
||||
|
||||
#define LOG_MODULE "gfx-hook"
|
||||
|
||||
#include <d3d9.h>
|
||||
#include <d3dx9core.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hook/com-proxy.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "ddrhook-util/gfx.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static HRESULT STDCALL my_CreateDevice(
|
||||
IDirect3D9 *self,
|
||||
UINT adapter,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
IDirect3DDevice9 **pdev);
|
||||
static LONG(STDCALL *real_ChangeDisplaySettingsExA)(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
|
||||
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 IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver);
|
||||
|
||||
static IDirect3D9 *(STDCALL *real_Direct3DCreate9)(UINT sdk_ver);
|
||||
static LONG STDCALL my_ChangeDisplaySettingsExA(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
|
||||
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_is_modern;
|
||||
|
||||
static const struct hook_symbol gfx_d3d9_hook_syms[] = {
|
||||
static const struct hook_symbol gfx_user32_syms[] = {
|
||||
{
|
||||
.name = "Direct3DCreate9",
|
||||
.patch = my_Direct3DCreate9,
|
||||
.link = (void **) &real_Direct3DCreate9,
|
||||
.name = "ChangeDisplaySettingsExA",
|
||||
.patch = my_ChangeDisplaySettingsExA,
|
||||
.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,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
IDirect3DDevice9 **pdev)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void gfx_d3d9_calc_win_size_with_framed(
|
||||
HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp)
|
||||
{
|
||||
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) {
|
||||
pp->Windowed = TRUE;
|
||||
pp->FullScreen_RefreshRateInHz = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
return IDirect3D9_CreateDevice(real, adapter, type, hwnd, flags, pp, pdev);
|
||||
}
|
||||
|
||||
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);
|
||||
if (rect.top < 0) {
|
||||
rect.bottom -= rect.top;
|
||||
rect.top = 0;
|
||||
}
|
||||
|
||||
api_vtbl = api_proxy->vptr;
|
||||
|
||||
api_vtbl->CreateDevice = my_CreateDevice;
|
||||
|
||||
return (IDirect3D9 *) api_proxy;
|
||||
wp->x = rect.left;
|
||||
wp->y = rect.top;
|
||||
wp->cx = rect.right - rect.left;
|
||||
wp->cy = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
@@ -94,3 +158,124 @@ void gfx_set_windowed(void)
|
||||
{
|
||||
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");
|
||||
}
|
||||
@@ -1,12 +1,25 @@
|
||||
#ifndef DDRHOOK_GFX_H
|
||||
#define DDRHOOK_GFX_H
|
||||
|
||||
#include <windows.h>
|
||||
#ifndef DDRHOOK1_D3D9_H
|
||||
#define DDRHOOK1_D3D9_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);
|
||||
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
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
#include "util/log.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)(
|
||||
HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
static HWND(STDCALL *real_CreateWindowExW)(
|
||||
DWORD dwExStyle,
|
||||
LPCWSTR lpClassName,
|
||||
@@ -28,16 +27,11 @@ static HWND(STDCALL *real_CreateWindowExW)(
|
||||
HMENU hMenu,
|
||||
HINSTANCE hInstance,
|
||||
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 LRESULT STDCALL
|
||||
my_SendMessageW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
static HWND STDCALL my_CreateWindowExA(
|
||||
DWORD dwExStyle,
|
||||
LPCSTR lpClassName,
|
||||
@@ -64,16 +58,8 @@ static HWND STDCALL my_CreateWindowExW(
|
||||
HMENU hMenu,
|
||||
HINSTANCE hInstance,
|
||||
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[] = {
|
||||
{
|
||||
.name = "ChangeDisplaySettingsExA",
|
||||
.patch = my_ChangeDisplaySettingsExA,
|
||||
.link = (void **) &real_ChangeDisplaySettingsExA,
|
||||
},
|
||||
{
|
||||
.name = "SendMessageW",
|
||||
.patch = my_SendMessageW,
|
||||
@@ -92,82 +78,8 @@ static const struct hook_symbol misc_user32_syms[] = {
|
||||
.patch = my_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(
|
||||
DWORD dwExStyle,
|
||||
LPCWSTR lpClassName,
|
||||
@@ -182,6 +94,23 @@ static HWND STDCALL my_CreateWindowExW(
|
||||
HINSTANCE hInstance,
|
||||
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()) {
|
||||
/* use a different style */
|
||||
dwStyle |= WS_OVERLAPPEDWINDOW;
|
||||
@@ -215,7 +144,7 @@ static HWND STDCALL my_CreateWindowExW(
|
||||
slightly bigger than the rendering resolution (window caption and
|
||||
stuff is included in the window size) */
|
||||
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);
|
||||
X = wp.x;
|
||||
Y = wp.y;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef HOOK_MISC_H
|
||||
#define HOOK_MISC_H
|
||||
#ifndef DDRHOOK_UTIL_MISC_H
|
||||
#define DDRHOOK_UTIL_MISC_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef DDRHOOK_MONITOR_H
|
||||
#define DDRHOOK_MONITOR_H
|
||||
#ifndef DDRHOOK_UTIL_MONITOR_H
|
||||
#define DDRHOOK_UTIL_MONITOR_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
152
src/main/ddrhook-util/p3io.c
Normal file
152
src/main/ddrhook-util/p3io.c
Normal 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
|
||||
23
src/main/ddrhook-util/p3io.h
Normal file
23
src/main/ddrhook-util/p3io.h
Normal 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
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef DDRHOOK_SPIKE_H
|
||||
#define DDRHOOK_SPIKE_H
|
||||
#ifndef DDRHOOK_UTIL_SPIKE_H
|
||||
#define DDRHOOK_UTIL_SPIKE_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
439
src/main/ddrhook-util/usbmem.c
Normal file
439
src/main/ddrhook-util/usbmem.c
Normal 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;
|
||||
}
|
||||
8
src/main/ddrhook-util/usbmem.h
Normal file
8
src/main/ddrhook-util/usbmem.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef DDRHOOK_MASTER_H
|
||||
#define DDRHOOK_MASTER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void master_insert_hooks(HMODULE target);
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
30
src/main/ddrhook1/Module.mk
Normal file
30
src/main/ddrhook1/Module.mk
Normal 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 \
|
||||
173
src/main/ddrhook1/avs-boot.c
Normal file
173
src/main/ddrhook1/avs-boot.c
Normal 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));
|
||||
}
|
||||
19
src/main/ddrhook1/avs-boot.h
Normal file
19
src/main/ddrhook1/avs-boot.h
Normal 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
|
||||
128
src/main/ddrhook1/config-ddrhook1.c
Normal file
128
src/main/ddrhook1/config-ddrhook1.c
Normal 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);
|
||||
}
|
||||
}
|
||||
37
src/main/ddrhook1/config-ddrhook1.h
Normal file
37
src/main/ddrhook1/config-ddrhook1.h
Normal 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
|
||||
144
src/main/ddrhook1/config-eamuse.c
Normal file
144
src/main/ddrhook1/config-eamuse.c
Normal 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);
|
||||
}
|
||||
}
|
||||
36
src/main/ddrhook1/config-eamuse.h
Normal file
36
src/main/ddrhook1/config-eamuse.h
Normal 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
|
||||
36
src/main/ddrhook1/config-gfx.c
Normal file
36
src/main/ddrhook1/config-gfx.c
Normal 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);
|
||||
}
|
||||
}
|
||||
30
src/main/ddrhook1/config-gfx.h
Normal file
30
src/main/ddrhook1/config-gfx.h
Normal 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
|
||||
75
src/main/ddrhook1/config-security.c
Normal file
75
src/main/ddrhook1/config-security.c
Normal 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);
|
||||
}
|
||||
34
src/main/ddrhook1/config-security.h
Normal file
34
src/main/ddrhook1/config-security.h
Normal 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
|
||||
@@ -1,4 +1,4 @@
|
||||
LIBRARY ddrhook
|
||||
LIBRARY ddrhook1
|
||||
|
||||
EXPORTS
|
||||
DllMain@12 @1 NONAME
|
||||
196
src/main/ddrhook1/dllmain.c
Normal file
196
src/main/ddrhook1/dllmain.c
Normal 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;
|
||||
}
|
||||
327
src/main/ddrhook1/filesystem.c
Normal file
327
src/main/ddrhook1/filesystem.c
Normal 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");
|
||||
}
|
||||
16
src/main/ddrhook1/filesystem.h
Normal file
16
src/main/ddrhook1/filesystem.h
Normal 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
|
||||
85
src/main/ddrhook1/master.c
Normal file
85
src/main/ddrhook1/master.c
Normal 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);
|
||||
}
|
||||
8
src/main/ddrhook1/master.h
Normal file
8
src/main/ddrhook1/master.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef DDRHOOK1_MASTER_H
|
||||
#define DDRHOOK1_MASTER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void ddrhook1_master_insert_hooks(HMODULE target);
|
||||
|
||||
#endif
|
||||
21
src/main/ddrhook2/Module.mk
Normal file
21
src/main/ddrhook2/Module.mk
Normal file
@@ -0,0 +1,21 @@
|
||||
avsdlls += ddrhook2
|
||||
|
||||
deplibs_ddrhook2 := \
|
||||
avs \
|
||||
|
||||
libs_ddrhook2 := \
|
||||
acioemu \
|
||||
ddrhook-util \
|
||||
p3ioemu \
|
||||
p3io \
|
||||
hook \
|
||||
hooklib \
|
||||
util \
|
||||
eamio \
|
||||
ddrio \
|
||||
security \
|
||||
|
||||
src_ddrhook2 := \
|
||||
dllmain.c \
|
||||
master.c \
|
||||
|
||||
4
src/main/ddrhook2/ddrhook2.def
Normal file
4
src/main/ddrhook2/ddrhook2.def
Normal file
@@ -0,0 +1,4 @@
|
||||
LIBRARY ddrhook2
|
||||
|
||||
EXPORTS
|
||||
DllMain@12 @1 NONAME
|
||||
@@ -5,14 +5,14 @@
|
||||
#include "bemanitools/ddrio.h"
|
||||
#include "bemanitools/eamio.h"
|
||||
|
||||
#include "ddrhook-util/_com4.h"
|
||||
#include "ddrhook-util/extio.h"
|
||||
#include "ddrhook-util/gfx.h"
|
||||
#include "ddrhook-util/p3io.h"
|
||||
#include "ddrhook-util/spike.h"
|
||||
#include "ddrhook-util/usbmem.h"
|
||||
|
||||
#include "ddrhook/_com4.h"
|
||||
#include "ddrhook/extio.h"
|
||||
#include "ddrhook/master.h"
|
||||
#include "ddrhook/p3io.h"
|
||||
#include "ddrhook/spike.h"
|
||||
#include "ddrhook/usbmem.h"
|
||||
#include "ddrhook2/master.h"
|
||||
|
||||
#include "hook/iohook.h"
|
||||
|
||||
@@ -40,6 +40,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
bool com4;
|
||||
bool ok;
|
||||
int i;
|
||||
char usbmem_data_path_p1[MAX_PATH] = "";
|
||||
char usbmem_data_path_p2[MAX_PATH] = "";
|
||||
bool usbmem_enabled = false;
|
||||
|
||||
log_info("--- Begin ddrhook dll_entry_init ---");
|
||||
|
||||
@@ -67,28 +70,50 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
Windows COM4 port instead. */
|
||||
com4 = false;
|
||||
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
/* Specify a USB memory path for P1 */
|
||||
if (i + 1 < argc) {
|
||||
strcpy(usbmem_data_path_p1, argv[i+1]);
|
||||
usbmem_enabled = true;
|
||||
i++; // Move forward one to skip the path parameter
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
/* Specify a USB memory path for P2 */
|
||||
if (i + 1 < argc) {
|
||||
strcpy(usbmem_data_path_p2, argv[i+1]);
|
||||
usbmem_enabled = true;
|
||||
i++; // Move forward one to skip the path parameter
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
args_free(argc, argv);
|
||||
|
||||
gfx_set_is_modern();
|
||||
|
||||
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 (com4) {
|
||||
/* See ddrhook/p3io.c for details. */
|
||||
/* See ddrhook2/p3io.c for details. */
|
||||
iohook_push_handler(com4_dispatch_irp);
|
||||
}
|
||||
|
||||
rs232_hook_init();
|
||||
|
||||
master_insert_hooks(NULL);
|
||||
ddrhook2_master_insert_hooks(NULL);
|
||||
p3io_ddr_init();
|
||||
extio_init();
|
||||
usbmem_init();
|
||||
usbmem_init(usbmem_data_path_p1, usbmem_data_path_p2, usbmem_enabled);
|
||||
spike_init();
|
||||
com4_init();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "ddrhook/master.h"
|
||||
#include "ddrhook2/master.h"
|
||||
|
||||
#include "ddrhook-util/dinput.h"
|
||||
#include "ddrhook-util/gfx.h"
|
||||
@@ -16,6 +16,11 @@ static HMODULE(STDCALL *real_LoadLibraryA)(const char *name);
|
||||
|
||||
static HMODULE STDCALL my_LoadLibraryA(const char *name);
|
||||
|
||||
|
||||
static const hook_d3d9_irp_handler_t ddrhook2_d3d9_handlers[] = {
|
||||
gfx_d3d9_irp_handler,
|
||||
};
|
||||
|
||||
static const struct hook_symbol master_kernel32_syms[] = {
|
||||
{
|
||||
.name = "LoadLibraryA",
|
||||
@@ -43,12 +48,12 @@ static HMODULE STDCALL my_LoadLibraryA(const char *name)
|
||||
return result;
|
||||
}
|
||||
|
||||
master_insert_hooks(result);
|
||||
ddrhook2_master_insert_hooks(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void master_insert_hooks(HMODULE target)
|
||||
void ddrhook2_master_insert_hooks(HMODULE target)
|
||||
{
|
||||
/* Insert all other hooks here */
|
||||
|
||||
@@ -58,6 +63,8 @@ void master_insert_hooks(HMODULE target)
|
||||
dinput_init(target);
|
||||
gfx_insert_hooks(target);
|
||||
|
||||
hook_d3d9_init(ddrhook2_d3d9_handlers, lengthof(ddrhook2_d3d9_handlers));
|
||||
|
||||
/* Insert dynamic loader hooks so that we can hook late-loaded modules */
|
||||
|
||||
hook_table_apply(
|
||||
8
src/main/ddrhook2/master.h
Normal file
8
src/main/ddrhook2/master.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef DDRHOOK2_MASTER_H
|
||||
#define DDRHOOK2_MASTER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void ddrhook2_master_insert_hooks(HMODULE target);
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,9 @@
|
||||
static struct security_mcode ezusb_iidx_emu_node_security_plug_boot_version;
|
||||
static uint32_t ezusb_iidx_emu_node_security_plug_boot_seeds[3];
|
||||
|
||||
static struct security_rp_sign_key ezusb_iidx_emu_node_security_plug_black_sign_key;
|
||||
static struct security_rp_sign_key ezusb_iidx_emu_node_security_plug_white_sign_key;
|
||||
|
||||
static struct security_mcode ezusb_iidx_emu_node_security_plug_black_mcode;
|
||||
static struct security_mcode ezusb_iidx_emu_node_security_plug_white_mcode;
|
||||
|
||||
@@ -62,6 +65,28 @@ void ezusb_iidx_emu_node_security_plug_set_boot_seeds(const uint32_t *seeds)
|
||||
sizeof(ezusb_iidx_emu_node_security_plug_boot_seeds));
|
||||
}
|
||||
|
||||
void ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key(
|
||||
const struct security_rp_sign_key *sign_key)
|
||||
{
|
||||
log_misc("black sign key: %s", sign_key->data);
|
||||
|
||||
memcpy(
|
||||
&ezusb_iidx_emu_node_security_plug_black_sign_key,
|
||||
sign_key,
|
||||
sizeof(struct security_rp_sign_key));
|
||||
}
|
||||
|
||||
void ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key(
|
||||
const struct security_rp_sign_key *sign_key)
|
||||
{
|
||||
log_misc("white sign key: %s", sign_key->data);
|
||||
|
||||
memcpy(
|
||||
&ezusb_iidx_emu_node_security_plug_white_sign_key,
|
||||
sign_key,
|
||||
sizeof(struct security_rp_sign_key));
|
||||
}
|
||||
|
||||
void ezusb_iidx_emu_node_security_plug_set_plug_black_mcode(
|
||||
const struct security_mcode *mcode)
|
||||
{
|
||||
@@ -373,7 +398,7 @@ bool ezusb_iidx_emu_node_security_plug_read_packet_v2(
|
||||
|
||||
security_rp2_generate_signed_eeprom_data(
|
||||
SECURITY_RP_UTIL_RP_TYPE_BLACK,
|
||||
&ezusb_iidx_emu_node_security_plug_boot_version,
|
||||
&ezusb_iidx_emu_node_security_plug_black_sign_key,
|
||||
&ezusb_iidx_emu_node_security_plug_black_mcode,
|
||||
&ezusb_iidx_emu_node_security_plug_pcbid,
|
||||
(struct security_rp2_eeprom *) pkg->payload);
|
||||
@@ -415,7 +440,7 @@ bool ezusb_iidx_emu_node_security_plug_read_packet_v2(
|
||||
|
||||
security_rp2_generate_signed_eeprom_data(
|
||||
SECURITY_RP_UTIL_RP_TYPE_WHITE,
|
||||
&ezusb_iidx_emu_node_security_plug_boot_version,
|
||||
&ezusb_iidx_emu_node_security_plug_white_sign_key,
|
||||
&ezusb_iidx_emu_node_security_plug_white_mcode,
|
||||
&ezusb_iidx_emu_node_security_plug_eamid,
|
||||
(struct security_rp2_eeprom *) pkg->payload);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "security/id.h"
|
||||
#include "security/mcode.h"
|
||||
#include "security/rp-sign-key.h"
|
||||
|
||||
/**
|
||||
* Set the boot version of the game. The boot version mcode is used for
|
||||
@@ -23,6 +24,22 @@ void ezusb_iidx_emu_node_security_plug_set_boot_version(
|
||||
*/
|
||||
void ezusb_iidx_emu_node_security_plug_set_boot_seeds(const uint32_t *seeds);
|
||||
|
||||
/**
|
||||
* Set the signing key for the black dongle.
|
||||
*
|
||||
* @param sign_key Pointer to the black dongle sign key.
|
||||
*/
|
||||
void ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key(
|
||||
const struct security_rp_sign_key *sign_key);
|
||||
|
||||
/**
|
||||
* Set the signing key for the white dongle.
|
||||
*
|
||||
* @param sign_key Pointer to the white dongle sign key.
|
||||
*/
|
||||
void ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key(
|
||||
const struct security_rp_sign_key *sign_key);
|
||||
|
||||
/**
|
||||
* The mcode of the target game to boot. This mcode is typically printed onto
|
||||
* the black plug corresponding to the game to boot.
|
||||
|
||||
@@ -71,6 +71,10 @@ static HRESULT(STDCALL *real_DrawPrimitiveUP)(
|
||||
const void *data,
|
||||
UINT stride);
|
||||
|
||||
static HRESULT(STDCALL *real_Reset)(
|
||||
IDirect3DDevice9 *self,
|
||||
D3DPRESENT_PARAMETERS *pp);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -136,6 +140,10 @@ static HRESULT STDCALL my_DrawPrimitiveUP(
|
||||
const void *data,
|
||||
UINT stride);
|
||||
|
||||
static HRESULT STDCALL my_Reset(
|
||||
IDirect3DDevice9 *self,
|
||||
D3DPRESENT_PARAMETERS *pp);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -194,6 +202,9 @@ hook_d3d9_irp_handler_real_dev_set_render_state(struct hook_d3d9_irp *irp);
|
||||
static HRESULT
|
||||
hook_d3d9_irp_handler_real_dev_draw_primitive_up(struct hook_d3d9_irp *irp);
|
||||
|
||||
static HRESULT
|
||||
hook_d3d9_irp_handler_real_dev_reset(struct hook_d3d9_irp *irp);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -218,6 +229,8 @@ static const hook_d3d9_irp_handler_t hook_d3d9_irp_real_handlers[] = {
|
||||
hook_d3d9_irp_handler_real_dev_set_render_state,
|
||||
[HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP] =
|
||||
hook_d3d9_irp_handler_real_dev_draw_primitive_up,
|
||||
[HOOK_D3D9_IRP_OP_DEV_RESET] =
|
||||
hook_d3d9_irp_handler_real_dev_reset,
|
||||
};
|
||||
|
||||
static const hook_d3d9_irp_handler_t *hook_d3d9_handlers;
|
||||
@@ -488,6 +501,24 @@ static HRESULT STDCALL my_DrawPrimitiveUP(
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDCALL my_Reset(
|
||||
IDirect3DDevice9 *self,
|
||||
D3DPRESENT_PARAMETERS *pp)
|
||||
{
|
||||
struct hook_d3d9_irp irp;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&irp, 0, sizeof(irp));
|
||||
|
||||
irp.op = HOOK_D3D9_IRP_OP_DEV_RESET;
|
||||
irp.args.dev_reset.self = self;
|
||||
irp.args.dev_reset.pp = pp;
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(&irp);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -528,7 +559,7 @@ static HRESULT hook_d3d9_irp_handler_real_ctx_create(struct hook_d3d9_irp *irp)
|
||||
}
|
||||
|
||||
res = com_proxy_wrap(&api_proxy, api, sizeof(*api->lpVtbl));
|
||||
|
||||
|
||||
if (res != S_OK) {
|
||||
log_fatal("Wrapping com proxy failed: %08lx", res);
|
||||
}
|
||||
@@ -657,6 +688,9 @@ hook_d3d9_irp_handler_real_dev_create_device(struct hook_d3d9_irp *irp)
|
||||
real_DrawPrimitiveUP = api_vtbl->DrawPrimitiveUP;
|
||||
api_vtbl->DrawPrimitiveUP = my_DrawPrimitiveUP;
|
||||
|
||||
real_Reset = api_vtbl->Reset;
|
||||
api_vtbl->Reset = my_Reset;
|
||||
|
||||
*irp->args.ctx_create_device.pdev = (IDirect3DDevice9 *) api_proxy;
|
||||
|
||||
return hr;
|
||||
@@ -731,6 +765,16 @@ hook_d3d9_irp_handler_real_dev_draw_primitive_up(struct hook_d3d9_irp *irp)
|
||||
irp->args.dev_draw_primitive_up.stride);
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
hook_d3d9_irp_handler_real_dev_reset(struct hook_d3d9_irp *irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
|
||||
return real_Reset(
|
||||
irp->args.dev_reset.self,
|
||||
irp->args.dev_reset.pp);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ enum hook_d3d9_irp_op {
|
||||
HOOK_D3D9_IRP_OP_DEV_PRESENT = 9,
|
||||
HOOK_D3D9_IRP_OP_DEV_SET_RENDER_STATE = 10,
|
||||
HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP = 11,
|
||||
HOOK_D3D9_IRP_OP_DEV_RESET = 12,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -161,6 +162,14 @@ struct hook_d3d9_irp {
|
||||
const void *data;
|
||||
UINT stride;
|
||||
} dev_draw_primitive_up;
|
||||
|
||||
/**
|
||||
* Params of IDirect3DDevice9_Reset.
|
||||
*/
|
||||
struct {
|
||||
IDirect3DDevice9 *self;
|
||||
D3DPRESENT_PARAMETERS *pp;
|
||||
} dev_reset;
|
||||
} args;
|
||||
|
||||
size_t next_handler;
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "iidxhook-util/eamuse.h"
|
||||
#include "iidxhook-util/settings.h"
|
||||
|
||||
#include "security/rp-sign-key.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/thread.h"
|
||||
@@ -163,6 +165,10 @@ my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
|
||||
ezusb_iidx_emu_node_security_plug_set_boot_version(
|
||||
&config_sec.boot_version);
|
||||
ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds);
|
||||
ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key(
|
||||
&security_rp_sign_key_black_iidx);
|
||||
ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key(
|
||||
&security_rp_sign_key_white_eamuse);
|
||||
ezusb_iidx_emu_node_security_plug_set_plug_black_mcode(
|
||||
&config_sec.black_plug_mcode);
|
||||
ezusb_iidx_emu_node_security_plug_set_plug_white_mcode(
|
||||
@@ -235,7 +241,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH) {
|
||||
log_to_writer(log_writer_debug, NULL);
|
||||
|
||||
|
||||
/* Bootstrap hook for further init tasks (see above) */
|
||||
|
||||
hook_table_apply(
|
||||
|
||||
6
src/main/jbhook-util-p3io/Module.mk
Normal file
6
src/main/jbhook-util-p3io/Module.mk
Normal file
@@ -0,0 +1,6 @@
|
||||
libs += jbhook-util-p3io
|
||||
|
||||
src_jbhook-util-p3io := \
|
||||
gfx.c \
|
||||
mixer.c \
|
||||
p3io.c \
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "imports/glhelper.h"
|
||||
|
||||
#include "jbhook-util/gfx.h"
|
||||
#include "jbhook-util-p3io/gfx.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
@@ -47,71 +47,6 @@ static const struct hook_symbol jbhook_infodisp_hook_syms[] = {
|
||||
.patch = hook_infodispcore_set_angle},
|
||||
};
|
||||
|
||||
static DWORD STDCALL my_GetGlyphOutline(
|
||||
HDC hdc,
|
||||
UINT uChar,
|
||||
UINT uFormat,
|
||||
LPGLYPHMETRICS lpgm,
|
||||
DWORD cbBuffer,
|
||||
LPVOID lpvBuffer,
|
||||
const MAT2 *lpmat2);
|
||||
|
||||
static DWORD(STDCALL *real_GetGlyphOutline)(
|
||||
HDC hdc,
|
||||
UINT uChar,
|
||||
UINT uFormat,
|
||||
LPGLYPHMETRICS lpgm,
|
||||
DWORD cbBuffer,
|
||||
LPVOID lpvBuffer,
|
||||
const MAT2 *lpmat2);
|
||||
|
||||
static const struct hook_symbol gfx_hook_syms[] = {
|
||||
{.name = "GetGlyphOutlineA",
|
||||
.patch = my_GetGlyphOutline,
|
||||
.link = (void **) &real_GetGlyphOutline},
|
||||
{
|
||||
.name = "IsDBCSLeadByteEx",
|
||||
.patch = my_GetGlyphOutline, // !??
|
||||
.link = (void **) &real_GetGlyphOutline // !??
|
||||
},
|
||||
};
|
||||
|
||||
static DWORD STDCALL my_GetGlyphOutline(
|
||||
HDC hdc,
|
||||
UINT uChar,
|
||||
UINT uFormat,
|
||||
LPGLYPHMETRICS lpgm,
|
||||
DWORD cbBuffer,
|
||||
LPVOID lpvBuffer,
|
||||
const MAT2 *lpmat2)
|
||||
{
|
||||
if (IsDBCSLeadByteEx(CP_ACP, uChar & 0xFF)) {
|
||||
log_warning("!!!!!!!!");
|
||||
|
||||
char tmp[2];
|
||||
|
||||
tmp[0] = uChar & 0xFF;
|
||||
tmp[1] = (uChar >> 8) & 0xFF;
|
||||
|
||||
MultiByteToWideChar(
|
||||
CP_ACP, MB_USEGLYPHCHARS, tmp, 2, lpvBuffer, cbBuffer);
|
||||
}
|
||||
|
||||
return real_GetGlyphOutline(
|
||||
hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, lpmat2);
|
||||
}
|
||||
|
||||
void jbhook_util_gfx_hook_init(void)
|
||||
{
|
||||
hook_table_apply(NULL, "gdi32.dll", gfx_hook_syms, lengthof(gfx_hook_syms));
|
||||
|
||||
log_info("Inserted gfx hooks");
|
||||
}
|
||||
|
||||
void jbhook_util_gfx_set_windowed(bool framed)
|
||||
{
|
||||
}
|
||||
|
||||
void jbhook_util_gfx_install_vertical_hooks(void) {
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
4
src/main/jbhook-util-p3io/gfx.h
Normal file
4
src/main/jbhook-util-p3io/gfx.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Rotate a horizontal-by-default jubeat window to vertical
|
||||
*/
|
||||
void jbhook_util_gfx_install_vertical_hooks(void);
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "bemanitools/jbio.h"
|
||||
|
||||
#include "jbhook-util/p3io.h"
|
||||
#include "jbhook-util-p3io/p3io.h"
|
||||
|
||||
#include "p3ioemu/emu.h"
|
||||
#include "p3ioemu/uart.h"
|
||||
@@ -6,8 +6,5 @@ libs_jbhook-util := \
|
||||
src_jbhook-util := \
|
||||
acio.c \
|
||||
eamuse.c \
|
||||
gfx.c \
|
||||
mixer.c \
|
||||
locale.c \
|
||||
p3io.c \
|
||||
p4io.c \
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef JBHOOK_D3D8_H
|
||||
#define JBHOOK_D3D8_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* Hook some gfx related functions to patch gfx related stuff
|
||||
* like enabling window mode.
|
||||
*/
|
||||
void jbhook_util_gfx_hook_init(void);
|
||||
|
||||
/**
|
||||
* Set the game to window mode.
|
||||
*
|
||||
* @param framed True to add a window frame and make the window
|
||||
* movable, resizable, minizable. False for no frame.
|
||||
*/
|
||||
void jbhook_util_gfx_set_windowed(bool framed);
|
||||
|
||||
/**
|
||||
* Rotate a horizontal-by-default jubeat window to vertical
|
||||
*/
|
||||
void jbhook_util_gfx_install_vertical_hooks(void);
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@ avsdlls += jbhook1
|
||||
imps += glhelper
|
||||
|
||||
deplibs_jbhook1 := \
|
||||
avs \
|
||||
avs \
|
||||
glhelper \
|
||||
|
||||
ldflags_jbhook1 := \
|
||||
@@ -15,7 +15,8 @@ libs_jbhook1 := \
|
||||
cconfig \
|
||||
eamio \
|
||||
jbio \
|
||||
jbhook-util \
|
||||
jbhook-util \
|
||||
jbhook-util-p3io \
|
||||
p3ioemu \
|
||||
p3io \
|
||||
hook \
|
||||
|
||||
@@ -24,9 +24,10 @@
|
||||
|
||||
#include "jbhook-util/acio.h"
|
||||
#include "jbhook-util/eamuse.h"
|
||||
#include "jbhook-util/gfx.h"
|
||||
#include "jbhook-util/mixer.h"
|
||||
#include "jbhook-util/p3io.h"
|
||||
|
||||
#include "jbhook-util-p3io/gfx.h"
|
||||
#include "jbhook-util-p3io/mixer.h"
|
||||
#include "jbhook-util-p3io/p3io.h"
|
||||
|
||||
#include "p3ioemu/devmgr.h"
|
||||
#include "p3ioemu/emu.h"
|
||||
|
||||
@@ -14,6 +14,7 @@ libs_jbhook2 := \
|
||||
eamio \
|
||||
jbio \
|
||||
jbhook-util \
|
||||
jbhook-util-p3io \
|
||||
p3ioemu \
|
||||
p3io \
|
||||
p4ioemu \
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
|
||||
#include "jbhook-util/acio.h"
|
||||
#include "jbhook-util/eamuse.h"
|
||||
#include "jbhook-util/gfx.h"
|
||||
#include "jbhook-util/p3io.h"
|
||||
|
||||
#include "jbhook-util-p3io/gfx.h"
|
||||
#include "jbhook-util-p3io/p3io.h"
|
||||
|
||||
#include "p3ioemu/devmgr.h"
|
||||
#include "p3ioemu/emu.h"
|
||||
@@ -40,15 +41,6 @@
|
||||
|
||||
static struct options options;
|
||||
|
||||
static const struct security_mcode security_mcode_j44 = {
|
||||
.header = SECURITY_MCODE_HEADER,
|
||||
.unkn = SECURITY_MCODE_UNKN_C,
|
||||
.game = SECURITY_MCODE_GAME_JB_3,
|
||||
.region = SECURITY_MCODE_REGION_JAPAN,
|
||||
.cabinet = SECURITY_MCODE_CABINET_C,
|
||||
.revision = SECURITY_MCODE_REVISION_A,
|
||||
};
|
||||
|
||||
static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
{
|
||||
bool eam_io_ok;
|
||||
@@ -59,6 +51,8 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
|
||||
log_info("--- Begin jbhook dll_entry_init ---");
|
||||
|
||||
log_assert(sidcode != NULL);
|
||||
|
||||
if(options.vertical) {
|
||||
jbhook_util_gfx_install_vertical_hooks();
|
||||
}
|
||||
@@ -67,12 +61,20 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
iohook_push_handler(p3io_emu_dispatch_irp);
|
||||
p3io_setupapi_insert_hooks(NULL);
|
||||
|
||||
log_assert(sidcode != NULL);
|
||||
|
||||
// pcbid and eamid are only used here for sec check, the ones used for
|
||||
// network access are taken from ea3-config.xml.
|
||||
// When booting knit append (and on no other version), the code must
|
||||
// actually match, so the ID used is for append (JCA)
|
||||
// actually match, so we use the one from ea3-config as well.
|
||||
// Example sidcode format: `K44JBA2012072301`
|
||||
struct security_mcode security_mcode_j44 = {
|
||||
.header = SECURITY_MCODE_HEADER,
|
||||
.unkn = SECURITY_MCODE_UNKN_C,
|
||||
.game = {sidcode[0], sidcode[1], sidcode[2]},
|
||||
.region = sidcode[3],
|
||||
.cabinet = sidcode[4],
|
||||
.revision = sidcode[5],
|
||||
};
|
||||
|
||||
jbhook_util_p3io_init(
|
||||
&security_mcode_j44,
|
||||
&security_id_default, &security_id_default);
|
||||
@@ -111,8 +113,22 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
|
||||
log_info("--- End jbhook dll_entry_init ---");
|
||||
|
||||
char *sidcode_in_ea3_config = strdup(sidcode);
|
||||
|
||||
bool ret = app_hook_invoke_init(sidcode, param);
|
||||
|
||||
// If the game is append, the mcode `cabinet` is forced to C. This is bad if
|
||||
// p3io was configured to respond as A! Help the user help themsevles...
|
||||
if(strcmp(sidcode_in_ea3_config, sidcode) != 0) {
|
||||
log_warning("sidcode changed after running game DLL init (%s -> %s)", sidcode_in_ea3_config, sidcode);
|
||||
log_warning("This will trigger a security error. Modify ea3-config.xml <soft> section to match the second value!");
|
||||
|
||||
// abort the boot
|
||||
return false;
|
||||
}
|
||||
|
||||
free(sidcode_in_ea3_config);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
@@ -183,6 +199,10 @@ static HWND CDECL my_mwindow_create(
|
||||
window_height = tmp;
|
||||
}
|
||||
|
||||
if(options.show_cursor) {
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
fullscreen = !options.windowed;
|
||||
|
||||
return real_mwindow_create(
|
||||
@@ -214,7 +234,6 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
|
||||
adapter_hook_init();
|
||||
}
|
||||
|
||||
jbhook_util_gfx_hook_init();
|
||||
jbhook_util_eamuse_hook_init();
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -34,10 +34,10 @@ void options_init_from_cmdline(struct options *options)
|
||||
void options_init(struct options *options)
|
||||
{
|
||||
options->windowed = false;
|
||||
options->window_framed = false;
|
||||
options->disable_p3ioemu = false;
|
||||
options->disable_cardemu = false;
|
||||
options->disable_adapteremu = false;
|
||||
options->show_cursor = false;
|
||||
}
|
||||
|
||||
bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
@@ -60,11 +60,6 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f': {
|
||||
options->window_framed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v': {
|
||||
options->vertical = true;
|
||||
break;
|
||||
@@ -84,6 +79,11 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
options->disable_p3ioemu = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
options->show_cursor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,8 @@ void options_print_usage(void)
|
||||
" -c Disable card emulation (e.g. when running on a "
|
||||
"real cab)\n"
|
||||
" -p Disable p3io emulation (e.g. when running on a "
|
||||
"real cab)\n");
|
||||
"real cab)\n"
|
||||
" -s Show mouse cursor on game window\n");
|
||||
}
|
||||
|
||||
void options_fini(struct options *options)
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
struct options {
|
||||
bool windowed;
|
||||
bool window_framed;
|
||||
bool vertical;
|
||||
bool disable_p3ioemu;
|
||||
bool disable_cardemu;
|
||||
bool disable_adapteremu;
|
||||
bool show_cursor;
|
||||
};
|
||||
|
||||
void options_init_from_cmdline(struct options *options);
|
||||
|
||||
@@ -22,4 +22,5 @@ libs_jbhook3 := \
|
||||
|
||||
src_jbhook3 := \
|
||||
dllmain.c \
|
||||
gfx.c \
|
||||
options.c
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "bemanitools/jbio.h"
|
||||
|
||||
#include "hook/iohook.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/adapter.h"
|
||||
#include "hooklib/app.h"
|
||||
@@ -17,11 +18,11 @@
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "jbhook3/gfx.h"
|
||||
#include "jbhook3/options.h"
|
||||
|
||||
#include "jbhook-util/acio.h"
|
||||
#include "jbhook-util/eamuse.h"
|
||||
#include "jbhook-util/gfx.h"
|
||||
#include "jbhook-util/p4io.h"
|
||||
|
||||
#include "p4ioemu/device.h"
|
||||
@@ -48,6 +49,16 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
iohook_push_handler(p4ioemu_dispatch_irp);
|
||||
iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp);
|
||||
|
||||
jbhook3_gfx_init();
|
||||
|
||||
if(options.windowed) {
|
||||
jbhook3_gfx_set_windowed();
|
||||
}
|
||||
|
||||
if(options.show_cursor) {
|
||||
jbhook3_gfx_set_show_cursor();
|
||||
}
|
||||
|
||||
if (!options.disable_p4ioemu) {
|
||||
log_info("Starting up jubeat IO backend");
|
||||
|
||||
@@ -120,7 +131,7 @@ static bool my_dll_entry_main(void)
|
||||
if (!options.disable_p4ioemu) {
|
||||
p4ioemu_fini();
|
||||
}
|
||||
|
||||
|
||||
options_fini(&options);
|
||||
|
||||
return result;
|
||||
@@ -142,8 +153,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
|
||||
if (!options.disable_adapteremu) {
|
||||
adapter_hook_init();
|
||||
}
|
||||
|
||||
jbhook_util_gfx_hook_init();
|
||||
|
||||
jbhook_util_eamuse_hook_init();
|
||||
|
||||
return TRUE;
|
||||
|
||||
73
src/main/jbhook3/gfx.c
Normal file
73
src/main/jbhook3/gfx.c
Normal file
@@ -0,0 +1,73 @@
|
||||
#define LOG_MODULE "jbhook-gfx"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "jbhook3/options.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
static bool jbhook3_gfx_windowed;
|
||||
static bool jbhook3_gfx_show_cursor;
|
||||
|
||||
void jbhook3_gfx_set_windowed(void)
|
||||
{
|
||||
jbhook3_gfx_windowed = true;
|
||||
}
|
||||
|
||||
void jbhook3_gfx_set_show_cursor(void)
|
||||
{
|
||||
jbhook3_gfx_show_cursor = true;
|
||||
}
|
||||
|
||||
static HWND CDECL my_GFWin32MainWindowRun(
|
||||
HINSTANCE,
|
||||
const char *,
|
||||
long,
|
||||
long,
|
||||
DWORD);
|
||||
|
||||
static HWND(CDECL *real_GFWin32MainWindowRun)(
|
||||
HINSTANCE,
|
||||
const char *,
|
||||
long,
|
||||
long,
|
||||
DWORD);
|
||||
|
||||
static const struct hook_symbol init_hook_syms[] = {
|
||||
{.name = "GFWin32MainWindowRun",
|
||||
.patch = my_GFWin32MainWindowRun,
|
||||
.link = (void **) &real_GFWin32MainWindowRun,},
|
||||
};
|
||||
|
||||
static HWND CDECL my_GFWin32MainWindowRun(
|
||||
HINSTANCE hInstance,
|
||||
const char *lpWindowName,
|
||||
long X,
|
||||
long Y,
|
||||
DWORD dwStyle
|
||||
)
|
||||
{
|
||||
if(jbhook3_gfx_windowed) {
|
||||
log_info("--- Begin jbhook GFWin32MainWindowRun ---");
|
||||
dwStyle |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE;
|
||||
}
|
||||
|
||||
if(jbhook3_gfx_show_cursor) {
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
return real_GFWin32MainWindowRun(hInstance, lpWindowName, X, Y, dwStyle);
|
||||
}
|
||||
|
||||
void jbhook3_gfx_init(void)
|
||||
{
|
||||
hook_table_apply(
|
||||
NULL, "gftools.dll", init_hook_syms, lengthof(init_hook_syms));
|
||||
|
||||
log_info("Inserted gfx hooks");
|
||||
}
|
||||
3
src/main/jbhook3/gfx.h
Normal file
3
src/main/jbhook3/gfx.h
Normal file
@@ -0,0 +1,3 @@
|
||||
void jbhook3_gfx_init(void);
|
||||
void jbhook3_gfx_set_windowed(void);
|
||||
void jbhook3_gfx_set_show_cursor(void);
|
||||
@@ -34,10 +34,10 @@ void options_init_from_cmdline(struct options *options)
|
||||
void options_init(struct options *options)
|
||||
{
|
||||
options->windowed = false;
|
||||
options->window_framed = false;
|
||||
options->disable_p4ioemu = false;
|
||||
options->disable_cardemu = false;
|
||||
options->disable_adapteremu = false;
|
||||
options->show_cursor = false;
|
||||
}
|
||||
|
||||
bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
@@ -60,11 +60,6 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f': {
|
||||
options->window_framed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
options->disable_adapteremu = true;
|
||||
break;
|
||||
@@ -79,6 +74,11 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
options->disable_p4ioemu = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
options->show_cursor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,13 +95,13 @@ void options_print_usage(void)
|
||||
"\n"
|
||||
" -h Print this usage message\n"
|
||||
" -w Run the game windowed\n"
|
||||
" -f Run the game in a framed window (needs -w option)\n"
|
||||
" -a Disable adapter hook\n"
|
||||
" -c Disable card emulation (e.g. when running on a "
|
||||
"real cab)\n"
|
||||
" -p Disable p4io emulation (e.g. when running on a "
|
||||
"real cab or on a bare "
|
||||
"p4io)\n");
|
||||
"p4io)\n"
|
||||
" -s Show mouse cursor on game window\n");
|
||||
}
|
||||
|
||||
void options_fini(struct options *options)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user