Compare commits
131 Commits
2024-03-13
...
develop
Author | SHA1 | Date |
---|---|---|
![]() |
a6126bf290 | |
![]() |
015097972a | |
![]() |
67eda7458b | |
![]() |
b37e1105d0 | |
![]() |
9a6c4939c2 | |
![]() |
39711a994a | |
![]() |
61f95c3f2e | |
![]() |
70c3e2fe0f | |
![]() |
369fe28687 | |
![]() |
3371f3f437 | |
![]() |
a57542c2d2 | |
![]() |
27116a7a41 | |
![]() |
e850346b79 | |
![]() |
4d0ef54279 | |
![]() |
b8af67377c | |
![]() |
4cb76dd1ee | |
![]() |
efe01d92a6 | |
![]() |
004a2f6dcd | |
![]() |
a1611afffc | |
![]() |
1d63ab24d3 | |
![]() |
2f54183636 | |
![]() |
402bf0f247 | |
![]() |
4c20deb60a | |
![]() |
96ee1afc2f | |
![]() |
0c28765bdd | |
![]() |
96bf8cab81 | |
![]() |
a3120181be | |
![]() |
80d4902cfc | |
![]() |
b4f5cdbe59 | |
![]() |
25431a9db1 | |
![]() |
a705ae8748 | |
![]() |
b52455339f | |
![]() |
ff21223f06 | |
![]() |
047733d122 | |
![]() |
21bb965382 | |
![]() |
11556a1332 | |
![]() |
d8202e1df4 | |
![]() |
2d3d6fc2bb | |
![]() |
6d8ffb46ef | |
![]() |
2069b1ea85 | |
![]() |
c80f903cf8 | |
![]() |
ceb2b63e8b | |
![]() |
83840e0a87 | |
![]() |
e50d6d8ebc | |
![]() |
e1a47cf365 | |
![]() |
8aef1cfa79 | |
![]() |
8fc24503c8 | |
![]() |
ebf0f0b428 | |
![]() |
892eb2b859 | |
![]() |
b80b9fbc19 | |
![]() |
cef3406691 | |
![]() |
97d2d6b9bc | |
![]() |
f39b9ce3a0 | |
![]() |
243bb778d1 | |
![]() |
66317a0054 | |
![]() |
8c24e04900 | |
![]() |
3bb9404a38 | |
![]() |
6819963f06 | |
![]() |
36849bd09a | |
![]() |
5f817c8a36 | |
![]() |
259b763a13 | |
![]() |
2251585ef0 | |
![]() |
c06bb408e7 | |
![]() |
53fb8c28ea | |
![]() |
33452394e6 | |
![]() |
4fa9abffe8 | |
![]() |
88a5bdcd14 | |
![]() |
bb773a63ce | |
![]() |
25e79f87c2 | |
![]() |
79592514ba | |
![]() |
cdfd3bf655 | |
![]() |
f6c12fd230 | |
![]() |
86556ed2c8 | |
![]() |
9de48dd6ce | |
![]() |
d257887f6e | |
![]() |
3eef5dd209 | |
![]() |
599d5e3211 | |
![]() |
f18d074c5f | |
![]() |
6bd1bce419 | |
![]() |
96bdacfa7c | |
![]() |
d4bb7b6e0e | |
![]() |
70ac873d11 | |
![]() |
068651b6fa | |
![]() |
84e9ed3c9a | |
![]() |
c827b4c212 | |
![]() |
26624f25b1 | |
![]() |
824bc9abda | |
![]() |
cc5b87b559 | |
![]() |
e6794807a6 | |
![]() |
54cbbffae9 | |
![]() |
ac0f9f0587 | |
![]() |
0061158188 | |
![]() |
c535f18e40 | |
![]() |
c91c7db3c7 | |
![]() |
6a4cae1165 | |
![]() |
383039e16e | |
![]() |
37c26ecadb | |
![]() |
686d57d3ee | |
![]() |
b9204d4765 | |
![]() |
5abc593b46 | |
![]() |
fe14630b3d | |
![]() |
92fe2751e7 | |
![]() |
8c839b0d4e | |
![]() |
ccb655a12b | |
![]() |
ded89f6343 | |
![]() |
f3e31fc2ae | |
![]() |
965126c68a | |
![]() |
050951e56f | |
![]() |
7e5e0f132e | |
![]() |
4e58d3b9a2 | |
![]() |
7d3cab256b | |
![]() |
b0f307f427 | |
![]() |
7aa996193c | |
![]() |
9353c9872f | |
![]() |
d8b3d41809 | |
![]() |
3bfb046afc | |
![]() |
9fe98b227b | |
![]() |
b77ce7b457 | |
![]() |
517469a60c | |
![]() |
1069cfee26 | |
![]() |
d3a0faa530 | |
![]() |
00b3d5b7bb | |
![]() |
04fcd0d09a | |
![]() |
25e954fb55 | |
![]() |
a8c6ac70e4 | |
![]() |
eb1ec0e261 | |
![]() |
482a6e530a | |
![]() |
65173e1fa6 | |
![]() |
4041844ea9 | |
![]() |
47a65e5e51 | |
![]() |
774a639bb7 |
aimeio
carolio
chunihook
cxbio
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
BasedOnStyle: Google
|
||||||
|
IndentWidth: 4
|
||||||
|
---
|
|
@ -18,3 +18,9 @@ build/
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
subprojects/capnhook
|
subprojects/capnhook
|
||||||
|
|
||||||
|
# For enabling debug logging on local builds
|
||||||
|
MesonLocalOptions.mk
|
||||||
|
|
||||||
|
# Some meson cache thing
|
||||||
|
.meson-subproject-wrap-hash.txt
|
||||||
|
|
9
Makefile
9
Makefile
|
@ -11,6 +11,11 @@ DOC_DIR := doc
|
||||||
|
|
||||||
DIST_DIR := dist
|
DIST_DIR := dist
|
||||||
|
|
||||||
|
# Add "-D[option]=[value]" here as necessary
|
||||||
|
MESON_OPTIONS :=
|
||||||
|
# For options that shouldn't be committed
|
||||||
|
-include MesonLocalOptions.mk
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Targets
|
# Targets
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
@ -19,9 +24,9 @@ include Package.mk
|
||||||
|
|
||||||
.PHONY: build # Build the project
|
.PHONY: build # Build the project
|
||||||
build:
|
build:
|
||||||
$(V)meson --cross cross-mingw-32.txt $(BUILD_DIR_32)
|
$(V)meson setup $(MESON_OPTIONS) --cross cross-mingw-32.txt $(BUILD_DIR_32)
|
||||||
$(V)ninja -C $(BUILD_DIR_32)
|
$(V)ninja -C $(BUILD_DIR_32)
|
||||||
$(V)meson --cross cross-mingw-64.txt $(BUILD_DIR_64)
|
$(V)meson setup $(MESON_OPTIONS) --cross cross-mingw-64.txt $(BUILD_DIR_64)
|
||||||
$(V)ninja -C $(BUILD_DIR_64)
|
$(V)ninja -C $(BUILD_DIR_64)
|
||||||
|
|
||||||
.PHONY: dist # Build and create a zip distribution package
|
.PHONY: dist # Build and create a zip distribution package
|
||||||
|
|
65
Package.mk
65
Package.mk
|
@ -5,7 +5,7 @@ $(BUILD_DIR_ZIP)/chuni.zip:
|
||||||
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_32)/chunihook/chunihook.dll \
|
$(BUILD_DIR_32)/chunihook/chunihook.dll \
|
||||||
$(DIST_DIR)/chuni/segatools.ini \
|
$(DIST_DIR)/chuni/segatools.ini \
|
||||||
$(DIST_DIR)/chuni/start.bat \
|
$(DIST_DIR)/chuni/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/chuni
|
$(BUILD_DIR_ZIP)/chuni
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -20,7 +20,7 @@ $(BUILD_DIR_ZIP)/cxb.zip:
|
||||||
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_32)/cxbhook/cxbhook.dll \
|
$(BUILD_DIR_32)/cxbhook/cxbhook.dll \
|
||||||
$(DIST_DIR)/cxb/segatools.ini \
|
$(DIST_DIR)/cxb/segatools.ini \
|
||||||
$(DIST_DIR)/cxb/start.bat \
|
$(DIST_DIR)/cxb/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/cxb
|
$(BUILD_DIR_ZIP)/cxb
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -35,7 +35,7 @@ $(BUILD_DIR_ZIP)/diva.zip:
|
||||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_64)/divahook/divahook.dll \
|
$(BUILD_DIR_64)/divahook/divahook.dll \
|
||||||
$(DIST_DIR)/diva/segatools.ini \
|
$(DIST_DIR)/diva/segatools.ini \
|
||||||
$(DIST_DIR)/diva/start.bat \
|
$(DIST_DIR)/diva/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/diva
|
$(BUILD_DIR_ZIP)/diva
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -50,7 +50,7 @@ $(BUILD_DIR_ZIP)/carol.zip:
|
||||||
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_32)/carolhook/carolhook.dll \
|
$(BUILD_DIR_32)/carolhook/carolhook.dll \
|
||||||
$(DIST_DIR)/carol/segatools.ini \
|
$(DIST_DIR)/carol/segatools.ini \
|
||||||
$(DIST_DIR)/carol/start.bat \
|
$(DIST_DIR)/carol/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/carol
|
$(BUILD_DIR_ZIP)/carol
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -65,7 +65,7 @@ $(BUILD_DIR_ZIP)/idz.zip:
|
||||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_64)/idzhook/idzhook.dll \
|
$(BUILD_DIR_64)/idzhook/idzhook.dll \
|
||||||
$(DIST_DIR)/idz/segatools.ini \
|
$(DIST_DIR)/idz/segatools.ini \
|
||||||
$(DIST_DIR)/idz/start.bat \
|
$(DIST_DIR)/idz/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/idz
|
$(BUILD_DIR_ZIP)/idz
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -80,7 +80,7 @@ $(BUILD_DIR_ZIP)/fgo.zip:
|
||||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_64)/fgohook/fgohook.dll \
|
$(BUILD_DIR_64)/fgohook/fgohook.dll \
|
||||||
$(DIST_DIR)/fgo/segatools.ini \
|
$(DIST_DIR)/fgo/segatools.ini \
|
||||||
$(DIST_DIR)/fgo/start.bat \
|
$(DIST_DIR)/fgo/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/fgo
|
$(BUILD_DIR_ZIP)/fgo
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -96,7 +96,7 @@ $(BUILD_DIR_ZIP)/idac.zip:
|
||||||
$(BUILD_DIR_64)/idachook/idachook.dll \
|
$(BUILD_DIR_64)/idachook/idachook.dll \
|
||||||
$(DIST_DIR)/idac/segatools.ini \
|
$(DIST_DIR)/idac/segatools.ini \
|
||||||
$(DIST_DIR)/idac/config_hook.json \
|
$(DIST_DIR)/idac/config_hook.json \
|
||||||
$(DIST_DIR)/idac/start.bat \
|
$(DIST_DIR)/idac/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/idac
|
$(BUILD_DIR_ZIP)/idac
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -112,7 +112,7 @@ $(BUILD_DIR_ZIP)/swdc.zip:
|
||||||
$(BUILD_DIR_64)/swdchook/swdchook.dll \
|
$(BUILD_DIR_64)/swdchook/swdchook.dll \
|
||||||
$(DIST_DIR)/swdc/segatools.ini \
|
$(DIST_DIR)/swdc/segatools.ini \
|
||||||
$(DIST_DIR)/swdc/config_hook.json \
|
$(DIST_DIR)/swdc/config_hook.json \
|
||||||
$(DIST_DIR)/swdc/start.bat \
|
$(DIST_DIR)/swdc/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/swdc
|
$(BUILD_DIR_ZIP)/swdc
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -127,7 +127,7 @@ $(BUILD_DIR_ZIP)/mercury.zip:
|
||||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_64)/mercuryhook/mercuryhook.dll \
|
$(BUILD_DIR_64)/mercuryhook/mercuryhook.dll \
|
||||||
$(DIST_DIR)/mercury/segatools.ini \
|
$(DIST_DIR)/mercury/segatools.ini \
|
||||||
$(DIST_DIR)/mercury/start.bat \
|
$(DIST_DIR)/mercury/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/mercury
|
$(BUILD_DIR_ZIP)/mercury
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -141,7 +141,7 @@ $(BUILD_DIR_ZIP)/chusan.zip:
|
||||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/chusan/DEVICE
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/chusan/DEVICE
|
||||||
$(V)cp $(DIST_DIR)/chusan/segatools.ini \
|
$(V)cp $(DIST_DIR)/chusan/segatools.ini \
|
||||||
$(DIST_DIR)/chusan/config_hook.json \
|
$(DIST_DIR)/chusan/config_hook.json \
|
||||||
$(DIST_DIR)/chusan/start.bat \
|
$(DIST_DIR)/chusan/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/chusan
|
$(BUILD_DIR_ZIP)/chusan
|
||||||
$(V)cp $(BUILD_DIR_32)/chusanhook/chusanhook.dll \
|
$(V)cp $(BUILD_DIR_32)/chusanhook/chusanhook.dll \
|
||||||
$(BUILD_DIR_ZIP)/chusan/chusanhook_x86.dll
|
$(BUILD_DIR_ZIP)/chusan/chusanhook_x86.dll
|
||||||
|
@ -164,7 +164,7 @@ $(BUILD_DIR_ZIP)/mu3.zip:
|
||||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_64)/mu3hook/mu3hook.dll \
|
$(BUILD_DIR_64)/mu3hook/mu3hook.dll \
|
||||||
$(DIST_DIR)/mu3/segatools.ini \
|
$(DIST_DIR)/mu3/segatools.ini \
|
||||||
$(DIST_DIR)/mu3/start.bat \
|
$(DIST_DIR)/mu3/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/mu3
|
$(BUILD_DIR_ZIP)/mu3
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -179,7 +179,7 @@ $(BUILD_DIR_ZIP)/mai2.zip:
|
||||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
$(BUILD_DIR_64)/mai2hook/mai2hook.dll \
|
$(BUILD_DIR_64)/mai2hook/mai2hook.dll \
|
||||||
$(DIST_DIR)/mai2/segatools.ini \
|
$(DIST_DIR)/mai2/segatools.ini \
|
||||||
$(DIST_DIR)/mai2/start.bat \
|
$(DIST_DIR)/mai2/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/mai2
|
$(BUILD_DIR_ZIP)/mai2
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -195,7 +195,7 @@ $(BUILD_DIR_ZIP)/cm.zip:
|
||||||
$(BUILD_DIR_64)/cmhook/cmhook.dll \
|
$(BUILD_DIR_64)/cmhook/cmhook.dll \
|
||||||
$(DIST_DIR)/cm/config_hook.json \
|
$(DIST_DIR)/cm/config_hook.json \
|
||||||
$(DIST_DIR)/cm/segatools.ini \
|
$(DIST_DIR)/cm/segatools.ini \
|
||||||
$(DIST_DIR)/cm/start.bat \
|
$(DIST_DIR)/cm/launch.bat \
|
||||||
$(BUILD_DIR_ZIP)/cm
|
$(BUILD_DIR_ZIP)/cm
|
||||||
$(V)cp pki/billing.pub \
|
$(V)cp pki/billing.pub \
|
||||||
pki/ca.crt \
|
pki/ca.crt \
|
||||||
|
@ -203,6 +203,43 @@ $(BUILD_DIR_ZIP)/cm.zip:
|
||||||
$(V)strip $(BUILD_DIR_ZIP)/cm/*.{exe,dll}
|
$(V)strip $(BUILD_DIR_ZIP)/cm/*.{exe,dll}
|
||||||
$(V)cd $(BUILD_DIR_ZIP)/cm ; zip -r ../cm.zip *
|
$(V)cd $(BUILD_DIR_ZIP)/cm ; zip -r ../cm.zip *
|
||||||
|
|
||||||
|
$(BUILD_DIR_ZIP)/tokyo.zip:
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/tokyo
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/tokyo/DEVICE
|
||||||
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
|
$(BUILD_DIR_64)/tokyohook/tokyohook.dll \
|
||||||
|
$(DIST_DIR)/tokyo/config_hook.json \
|
||||||
|
$(DIST_DIR)/tokyo/segatools.ini \
|
||||||
|
$(DIST_DIR)/tokyo/launch.bat \
|
||||||
|
$(BUILD_DIR_ZIP)/tokyo
|
||||||
|
$(V)cp pki/billing.pub \
|
||||||
|
pki/ca.crt \
|
||||||
|
$(BUILD_DIR_ZIP)/tokyo/DEVICE
|
||||||
|
$(V)strip $(BUILD_DIR_ZIP)/tokyo/*.{exe,dll}
|
||||||
|
$(V)cd $(BUILD_DIR_ZIP)/tokyo ; zip -r ../tokyo.zip *
|
||||||
|
|
||||||
|
$(BUILD_DIR_ZIP)/kemono.zip:
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/kemono
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/kemono/DEVICE
|
||||||
|
$(V)cp $(DIST_DIR)/kemono/segatools.ini \
|
||||||
|
$(DIST_DIR)/kemono/launch.bat \
|
||||||
|
$(BUILD_DIR_ZIP)/kemono
|
||||||
|
$(V)cp $(BUILD_DIR_32)/kemonohook/kemonohook.dll \
|
||||||
|
$(BUILD_DIR_ZIP)/kemono/kemonohook_x86.dll
|
||||||
|
$(V)cp $(BUILD_DIR_64)/kemonohook/kemonohook.dll \
|
||||||
|
$(BUILD_DIR_ZIP)/kemono/kemonohook_x64.dll
|
||||||
|
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
|
||||||
|
$(BUILD_DIR_ZIP)/kemono/inject_x86.exe
|
||||||
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
|
$(BUILD_DIR_ZIP)/kemono/inject_x64.exe
|
||||||
|
$(V)cp pki/billing.pub \
|
||||||
|
pki/ca.crt \
|
||||||
|
$(BUILD_DIR_ZIP)/kemono/DEVICE
|
||||||
|
for x in exe dll; do strip $(BUILD_DIR_ZIP)/kemono/*.$$x; done
|
||||||
|
$(V)cd $(BUILD_DIR_ZIP)/kemono ; zip -r ../kemono.zip *
|
||||||
|
|
||||||
$(BUILD_DIR_ZIP)/doc.zip: \
|
$(BUILD_DIR_ZIP)/doc.zip: \
|
||||||
$(DOC_DIR)/config \
|
$(DOC_DIR)/config \
|
||||||
$(DOC_DIR)/chunihook.md \
|
$(DOC_DIR)/chunihook.md \
|
||||||
|
@ -225,7 +262,9 @@ $(BUILD_DIR_ZIP)/segatools.zip: \
|
||||||
$(BUILD_DIR_ZIP)/mu3.zip \
|
$(BUILD_DIR_ZIP)/mu3.zip \
|
||||||
$(BUILD_DIR_ZIP)/mai2.zip \
|
$(BUILD_DIR_ZIP)/mai2.zip \
|
||||||
$(BUILD_DIR_ZIP)/cm.zip \
|
$(BUILD_DIR_ZIP)/cm.zip \
|
||||||
|
$(BUILD_DIR_ZIP)/tokyo.zip \
|
||||||
$(BUILD_DIR_ZIP)/fgo.zip \
|
$(BUILD_DIR_ZIP)/fgo.zip \
|
||||||
|
$(BUILD_DIR_ZIP)/kemono.zip \
|
||||||
CHANGELOG.md \
|
CHANGELOG.md \
|
||||||
README.md \
|
README.md \
|
||||||
|
|
||||||
|
|
26
README.md
26
README.md
|
@ -1,33 +1,37 @@
|
||||||
# Segatools
|
# Segatools
|
||||||
|
|
||||||
Version: `2024-03-13`
|
Version: `2024-09-30`
|
||||||
|
|
||||||
Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms.
|
Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms.
|
||||||
|
|
||||||
## List of supported games
|
## List of supported games
|
||||||
|
|
||||||
|
* Card Maker
|
||||||
|
* starting from Card Maker
|
||||||
* CHUNITHM
|
* CHUNITHM
|
||||||
* up to [CHUNITHM PARADISE LOST](doc/chunihook.md)
|
* up to [CHUNITHM PARADISE LOST](doc/chunihook.md)
|
||||||
* starting from CHUNITHM NEW!!
|
* starting from CHUNITHM NEW!!
|
||||||
* crossbeats REV.
|
* crossbeats REV.
|
||||||
* up to crossbeats REV. SUNRISE
|
* up to crossbeats REV. SUNRISE
|
||||||
|
* Fate/Grand Order
|
||||||
|
* Fate/Grand Order Arcade
|
||||||
|
* Hatsune Miku: Project DIVA Arcade
|
||||||
|
* up to Future Tone
|
||||||
* Initial D
|
* Initial D
|
||||||
* [Initial D Arcade Stage Zero](doc/idzhook.md)
|
* [Initial D Arcade Stage Zero](doc/idzhook.md)
|
||||||
* Initial D THE ARCADE
|
* Initial D THE ARCADE
|
||||||
* Hatsune Miku: Project DIVA Arcade
|
|
||||||
* up to Future Tone
|
|
||||||
* SEGA World Drivers Championship
|
|
||||||
* SEGA World Drivers Championship 2019
|
|
||||||
* Fate/Grand Order
|
|
||||||
* Fate/Grand Order Arcade
|
|
||||||
* O.N.G.E.K.I.
|
|
||||||
* starting from O.N.G.E.K.I.
|
|
||||||
* maimai DX
|
* maimai DX
|
||||||
* starting from maimai DX
|
* starting from maimai DX
|
||||||
* Card Maker
|
* Mario & Sonic
|
||||||
* starting from Card Maker
|
* Mario & Sonic at the Tokyo 2020 Olympics Arcade
|
||||||
|
* O.N.G.E.K.I.
|
||||||
|
* starting from O.N.G.E.K.I.
|
||||||
|
* SEGA World Drivers Championship
|
||||||
|
* SEGA World Drivers Championship 2019
|
||||||
* WACCA
|
* WACCA
|
||||||
* starting from WACCA
|
* starting from WACCA
|
||||||
|
* Kemono Friends
|
||||||
|
* Kemono Friends 3: Planet Tours
|
||||||
|
|
||||||
## End-users
|
## End-users
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "util/crc.h"
|
#include "util/crc.h"
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
struct aime_io_config {
|
struct aime_io_config {
|
||||||
wchar_t aime_path[MAX_PATH];
|
wchar_t aime_path[MAX_PATH];
|
||||||
|
@ -222,7 +223,7 @@ uint16_t aime_io_get_api_version(void)
|
||||||
|
|
||||||
HRESULT aime_io_init(void)
|
HRESULT aime_io_init(void)
|
||||||
{
|
{
|
||||||
aime_io_config_read(&aime_io_cfg, L".\\segatools.ini");
|
aime_io_config_read(&aime_io_cfg, get_config_path());
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ aimeio_lib = static_library(
|
||||||
name_prefix : '',
|
name_prefix : '',
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
link_with : [
|
link_with : [
|
||||||
util_lib,
|
util_lib,
|
||||||
],
|
],
|
||||||
|
|
13
amex/ds.c
13
amex/ds.c
|
@ -1,10 +1,11 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <devioctl.h>
|
#include <devioctl.h>
|
||||||
#include <ntdddisk.h>
|
#include <winioctl.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "amex/ds.h"
|
#include "amex/ds.h"
|
||||||
|
@ -19,13 +20,11 @@
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/str.h"
|
#include "util/str.h"
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#define DS_IOCTL_GET_ABI_VERSION CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
|
#define DS_IOCTL_SETUP CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
|
#define DS_IOCTL_READ_SECTOR CTL_CODE(0x8000, 0x804, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
|
|
||||||
enum {
|
#pragma pack(push, 1)
|
||||||
DS_IOCTL_GET_ABI_VERSION = 0x80006000,
|
|
||||||
DS_IOCTL_SETUP = 0x80006004,
|
|
||||||
DS_IOCTL_READ_SECTOR = 0x80006010,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ds_eeprom {
|
struct ds_eeprom {
|
||||||
uint32_t crc32;
|
uint32_t crc32;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <winnt.h>
|
#include <winnt.h>
|
||||||
#endif
|
#endif
|
||||||
#include <devioctl.h>
|
#include <devioctl.h>
|
||||||
#include <ntdddisk.h>
|
#include <winioctl.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -20,9 +20,7 @@
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/str.h"
|
#include "util/str.h"
|
||||||
|
|
||||||
enum {
|
#define EEPROM_IOCTL_GET_ABI_VERSION CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
EEPROM_IOCTL_GET_ABI_VERSION = 0x80006000,
|
|
||||||
};
|
|
||||||
|
|
||||||
static HRESULT eeprom_handle_irp(struct irp *irp);
|
static HRESULT eeprom_handle_irp(struct irp *irp);
|
||||||
static HRESULT eeprom_handle_open(struct irp *irp);
|
static HRESULT eeprom_handle_open(struct irp *irp);
|
||||||
|
|
12
amex/gpio.c
12
amex/gpio.c
|
@ -1,5 +1,5 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <ntstatus.h>
|
#include <winioctl.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -13,12 +13,10 @@
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/str.h"
|
#include "util/str.h"
|
||||||
|
|
||||||
enum {
|
#define GPIO_IOCTL_SET_LEDS CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||||
GPIO_IOCTL_SET_LEDS = 0x8000A004,
|
#define GPIO_IOCTL_GET_PSW CTL_CODE(0x8000, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
GPIO_IOCTL_GET_PSW = 0x80006008,
|
#define GPIO_IOCTL_GET_DIPSW CTL_CODE(0x8000, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
GPIO_IOCTL_GET_DIPSW = 0x8000600C,
|
#define GPIO_IOCTL_DESCRIBE CTL_CODE(0x8000, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
GPIO_IOCTL_DESCRIBE = 0x80006014,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GPIO_TYPE_NONE = 0,
|
GPIO_TYPE_NONE = 0,
|
||||||
|
|
13
amex/jvs.c
13
amex/jvs.c
|
@ -4,6 +4,7 @@
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
|
|
||||||
#include <ntstatus.h>
|
#include <ntstatus.h>
|
||||||
|
#include <winioctl.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -21,11 +22,9 @@
|
||||||
#include "util/dump.h"
|
#include "util/dump.h"
|
||||||
#include "util/str.h"
|
#include "util/str.h"
|
||||||
|
|
||||||
enum {
|
#define JVS_IOCTL_HELLO CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
JVS_IOCTL_HELLO = 0x80006004,
|
#define JVS_IOCTL_TRANSACT CTL_CODE(0x8000, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||||
JVS_IOCTL_SENSE = 0x8000600C,
|
#define JVS_IOCTL_SENSE CTL_CODE(0x8000, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
JVS_IOCTL_TRANSACT = 0x8000E008,
|
|
||||||
};
|
|
||||||
|
|
||||||
static HRESULT jvs_handle_irp(struct irp *irp);
|
static HRESULT jvs_handle_irp(struct irp *irp);
|
||||||
static HRESULT jvs_handle_open(struct irp *irp);
|
static HRESULT jvs_handle_open(struct irp *irp);
|
||||||
|
@ -185,14 +184,14 @@ static HRESULT jvs_ioctl_sense(struct irp *irp)
|
||||||
|
|
||||||
static HRESULT jvs_ioctl_transact(struct irp *irp)
|
static HRESULT jvs_ioctl_transact(struct irp *irp)
|
||||||
{
|
{
|
||||||
#if 0
|
#if defined(LOG_JVS)
|
||||||
dprintf("\nJVS Port: Outbound frame:\n");
|
dprintf("\nJVS Port: Outbound frame:\n");
|
||||||
dump_const_iobuf(&irp->write);
|
dump_const_iobuf(&irp->write);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &irp->read);
|
jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &irp->read);
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_JVS)
|
||||||
dprintf("JVS Port: Inbound frame:\n");
|
dprintf("JVS Port: Inbound frame:\n");
|
||||||
dump_iobuf(&irp->read);
|
dump_iobuf(&irp->read);
|
||||||
dprintf("\n");
|
dprintf("\n");
|
||||||
|
|
|
@ -2,7 +2,6 @@ amex_lib = static_library(
|
||||||
'amex',
|
'amex',
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
],
|
],
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <winnt.h>
|
#include <winnt.h>
|
||||||
#endif
|
#endif
|
||||||
#include <devioctl.h>
|
#include <devioctl.h>
|
||||||
#include <ntdddisk.h>
|
#include <winioctl.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -20,9 +20,7 @@
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/str.h"
|
#include "util/str.h"
|
||||||
|
|
||||||
enum {
|
#define SRAM_IOCTL_GET_ABI_VERSION CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
SRAM_IOCTL_GET_ABI_VERSION = 0x80006000,
|
|
||||||
};
|
|
||||||
|
|
||||||
static HRESULT sram_handle_irp(struct irp *irp);
|
static HRESULT sram_handle_irp(struct irp *irp);
|
||||||
static HRESULT sram_handle_open(struct irp *irp);
|
static HRESULT sram_handle_open(struct irp *irp);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "aimeio/aimeio.h"
|
#include "aimeio/aimeio.h"
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,18 @@ void aime_config_load(struct aime_config *cfg, const wchar_t *filename)
|
||||||
|
|
||||||
aime_dll_config_load(&cfg->dll, filename);
|
aime_dll_config_load(&cfg->dll, filename);
|
||||||
cfg->enable = GetPrivateProfileIntW(L"aime", L"enable", 1, filename);
|
cfg->enable = GetPrivateProfileIntW(L"aime", L"enable", 1, filename);
|
||||||
|
cfg->port_no = GetPrivateProfileIntW(L"aime", L"portNo", 0, filename);
|
||||||
cfg->high_baudrate = GetPrivateProfileIntW(L"aime", L"highBaud", 1, filename);
|
cfg->high_baudrate = GetPrivateProfileIntW(L"aime", L"highBaud", 1, filename);
|
||||||
cfg->gen = GetPrivateProfileIntW(L"aime", L"gen", 0, filename);
|
cfg->gen = GetPrivateProfileIntW(L"aime", L"gen", 0, filename);
|
||||||
|
cfg->proxy_flag = GetPrivateProfileIntW(L"aime", L"proxyFlag", 2, filename);
|
||||||
|
|
||||||
|
GetPrivateProfileStringW(
|
||||||
|
L"aime",
|
||||||
|
L"authdataPath",
|
||||||
|
L"DEVICE\\authdata.bin",
|
||||||
|
cfg->authdata_path,
|
||||||
|
_countof(cfg->authdata_path),
|
||||||
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void io4_config_load(struct io4_config *cfg, const wchar_t *filename)
|
void io4_config_load(struct io4_config *cfg, const wchar_t *filename)
|
||||||
|
@ -90,4 +100,14 @@ void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename)
|
||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, filename);
|
cfg->enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, filename);
|
||||||
|
cfg->port_no = GetPrivateProfileIntW(L"vfd", L"portNo", 0, filename);
|
||||||
|
cfg->utf_conversion = GetPrivateProfileIntW(L"vfd", L"utfConversion", 0, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffb_config_load(struct ffb_config *cfg, const wchar_t *filename)
|
||||||
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
cfg->enable = GetPrivateProfileIntW(L"ffb", L"enable", 1, filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "board/io4.h"
|
#include "board/io4.h"
|
||||||
#include "board/sg-reader.h"
|
#include "board/sg-reader.h"
|
||||||
#include "board/vfd.h"
|
#include "board/vfd.h"
|
||||||
|
#include "board/ffb.h"
|
||||||
|
|
||||||
void aime_config_load(struct aime_config *cfg, const wchar_t *filename);
|
void aime_config_load(struct aime_config *cfg, const wchar_t *filename);
|
||||||
void io4_config_load(struct io4_config *cfg, const wchar_t *filename);
|
void io4_config_load(struct io4_config *cfg, const wchar_t *filename);
|
||||||
void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename);
|
void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename);
|
||||||
|
void ffb_config_load(struct ffb_config *cfg, const wchar_t *filename);
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
Force Feedback Board (FFB)
|
||||||
|
|
||||||
|
This board is used by many SEGA games to provide force feedback to the player.
|
||||||
|
It is driven by the game software over a serial connection and is used by many
|
||||||
|
games such as SEGA World Drivers Championship, Initial D Arcade, ...
|
||||||
|
|
||||||
|
Part number in schematics is "838-15069 MOTOR DRIVE BD RS232/422 Board".
|
||||||
|
|
||||||
|
Some observations:
|
||||||
|
The maximal strength for any effect is 127, except Damper which maxes out at 40.
|
||||||
|
The period for rumble effects is in the range 0-40.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "board/ffb.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "hook/iohook.h"
|
||||||
|
#include "hooklib/uart.h"
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
#include "util/dump.h"
|
||||||
|
|
||||||
|
|
||||||
|
// request format:
|
||||||
|
// 0x?? - sync + command
|
||||||
|
// 0x?? - direction/additional command
|
||||||
|
// 0x?? - strength
|
||||||
|
// 0x?? - checksum (sum of everything except the sync byte)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FFB_CMD_TOGGLE = 0x80,
|
||||||
|
FFB_CMD_CONSTANT_FORCE = 0x84,
|
||||||
|
FFB_CMD_RUMBLE = 0x85,
|
||||||
|
FFB_CMD_DAMPER = 0x86,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ffb_hdr {
|
||||||
|
uint8_t cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
union ffb_req_any {
|
||||||
|
struct ffb_hdr hdr;
|
||||||
|
uint8_t bytes[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
static HRESULT ffb_handle_irp(struct irp *irp);
|
||||||
|
|
||||||
|
static HRESULT ffb_req_dispatch(const union ffb_req_any *req);
|
||||||
|
static HRESULT ffb_req_toggle(const uint8_t *bytes);
|
||||||
|
static HRESULT ffb_req_constant_force(const uint8_t *bytes);
|
||||||
|
static HRESULT ffb_req_rumble(const uint8_t *bytes);
|
||||||
|
static HRESULT ffb_req_damper(const uint8_t *bytes);
|
||||||
|
|
||||||
|
static const struct ffb_ops *ffb_ops;
|
||||||
|
static struct uart ffb_uart;
|
||||||
|
|
||||||
|
static bool ffb_started;
|
||||||
|
static HRESULT ffb_start_hr;
|
||||||
|
static uint8_t ffb_written[4];
|
||||||
|
static uint8_t ffb_readable[4];
|
||||||
|
|
||||||
|
/* Static variables to store maximum strength values */
|
||||||
|
static uint8_t max_constant_force = 0;
|
||||||
|
static uint8_t max_rumble = 0;
|
||||||
|
static uint8_t max_period = 0;
|
||||||
|
static uint8_t max_damper = 0;
|
||||||
|
|
||||||
|
HRESULT ffb_hook_init(
|
||||||
|
const struct ffb_config *cfg,
|
||||||
|
const struct ffb_ops *ops,
|
||||||
|
unsigned int port_no)
|
||||||
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(ops != NULL);
|
||||||
|
|
||||||
|
if (!cfg->enable) {
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffb_ops = ops;
|
||||||
|
|
||||||
|
uart_init(&ffb_uart, port_no);
|
||||||
|
ffb_uart.written.bytes = ffb_written;
|
||||||
|
ffb_uart.written.nbytes = sizeof(ffb_written);
|
||||||
|
ffb_uart.readable.bytes = ffb_readable;
|
||||||
|
ffb_uart.readable.nbytes = sizeof(ffb_readable);
|
||||||
|
|
||||||
|
dprintf("FFB: hook enabled.\n");
|
||||||
|
|
||||||
|
return iohook_push_handler(ffb_handle_irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ffb_handle_irp(struct irp *irp)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(irp != NULL);
|
||||||
|
|
||||||
|
if (!uart_match_irp(&ffb_uart, irp)) {
|
||||||
|
return iohook_invoke_next(irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = uart_handle_irp(&ffb_uart, irp);
|
||||||
|
|
||||||
|
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(&ffb_uart.written != NULL);
|
||||||
|
assert(ffb_uart.written.bytes != NULL || ffb_uart.written.nbytes == 0);
|
||||||
|
assert(ffb_uart.written.pos <= ffb_uart.written.nbytes);
|
||||||
|
|
||||||
|
// dprintf("FFB TX:\n");
|
||||||
|
|
||||||
|
hr = ffb_req_dispatch((const union ffb_req_any *) ffb_uart.written.bytes);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
dprintf("FFB: Processing error: %x\n", (int)hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump_iobuf(&ffb_uart.written);
|
||||||
|
ffb_uart.written.pos = 0;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ffb_req_dispatch(const union ffb_req_any *req)
|
||||||
|
{
|
||||||
|
switch (req->hdr.cmd) {
|
||||||
|
case FFB_CMD_TOGGLE:
|
||||||
|
return ffb_req_toggle(req->bytes);
|
||||||
|
case FFB_CMD_CONSTANT_FORCE:
|
||||||
|
return ffb_req_constant_force(req->bytes);
|
||||||
|
case FFB_CMD_RUMBLE:
|
||||||
|
return ffb_req_rumble(req->bytes);
|
||||||
|
case FFB_CMD_DAMPER:
|
||||||
|
return ffb_req_damper(req->bytes);
|
||||||
|
|
||||||
|
/* There are some test mode specfic commands which doesn't seem to be used in
|
||||||
|
game at all. The same is true for the initialization phase. */
|
||||||
|
|
||||||
|
default:
|
||||||
|
dprintf("FFB: Unhandled command %02x\n", req->hdr.cmd);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ffb_req_toggle(const uint8_t *bytes)
|
||||||
|
{
|
||||||
|
uint8_t activate = bytes[2];
|
||||||
|
|
||||||
|
if (activate == 0x01) {
|
||||||
|
dprintf("FFB: Activated\n");
|
||||||
|
} else {
|
||||||
|
dprintf("FFB: Deactivated\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ffb_ops->toggle != NULL) {
|
||||||
|
ffb_ops->toggle(activate == 0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ffb_req_constant_force(const uint8_t *bytes)
|
||||||
|
{
|
||||||
|
// dprintf("FFB: Constant force\n");
|
||||||
|
|
||||||
|
uint8_t direction = bytes[1];
|
||||||
|
uint8_t force = bytes[2];
|
||||||
|
|
||||||
|
if (direction == 0x0) {
|
||||||
|
// Right
|
||||||
|
force = 128 - force;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update max strength if the current force is greater
|
||||||
|
if (force > max_constant_force) {
|
||||||
|
max_constant_force = force;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dprintf("FFB: Constant Force Strength: %d (Max: %d)\n", force, max_constant_force);
|
||||||
|
if (ffb_ops->constant_force != NULL) {
|
||||||
|
ffb_ops->constant_force(direction, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ffb_req_rumble(const uint8_t *bytes)
|
||||||
|
{
|
||||||
|
// dprintf("FFB: Rumble\n");
|
||||||
|
|
||||||
|
uint8_t force = bytes[1];
|
||||||
|
uint8_t period = bytes[2];
|
||||||
|
|
||||||
|
// Update max strength if the current force is greater
|
||||||
|
if (force > max_rumble) {
|
||||||
|
max_rumble = force;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (period > max_period) {
|
||||||
|
max_period = period;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dprintf("FFB: Rumble Period: %d (Max %d), Strength: %d (Max: %d)\n", period, max_period, force, max_rumble);
|
||||||
|
if (ffb_ops->rumble != NULL) {
|
||||||
|
ffb_ops->rumble(force, period);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ffb_req_damper(const uint8_t *bytes)
|
||||||
|
{
|
||||||
|
// dprintf("FFB: Damper\n");
|
||||||
|
|
||||||
|
uint8_t force = bytes[2];
|
||||||
|
|
||||||
|
// Update max strength if the current force is greater
|
||||||
|
if (force > max_damper) {
|
||||||
|
max_damper = force;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dprintf("FFB: Damper Strength: %d (Max: %d)\n", force, max_damper);
|
||||||
|
if (ffb_ops->damper != NULL) {
|
||||||
|
ffb_ops->damper(force);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct ffb_config {
|
||||||
|
bool enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ffb_ops {
|
||||||
|
void (*toggle)(bool active);
|
||||||
|
void (*constant_force)(uint8_t direction, uint8_t force);
|
||||||
|
void (*rumble)(uint8_t force, uint8_t period);
|
||||||
|
void (*damper)(uint8_t force);
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT ffb_hook_init(
|
||||||
|
const struct ffb_config *cfg,
|
||||||
|
const struct ffb_ops *ops,
|
||||||
|
unsigned int port_no);
|
72
board/io3.c
72
board/io3.c
|
@ -16,6 +16,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "board/io3.h"
|
#include "board/io3.h"
|
||||||
|
|
||||||
|
@ -79,6 +80,11 @@ static HRESULT io3_cmd_read_analogs(
|
||||||
struct const_iobuf *req_buf,
|
struct const_iobuf *req_buf,
|
||||||
struct iobuf *resp_buf);
|
struct iobuf *resp_buf);
|
||||||
|
|
||||||
|
static HRESULT io3_cmd_read_rotarys(
|
||||||
|
struct io3 *io3,
|
||||||
|
struct const_iobuf *req_buf,
|
||||||
|
struct iobuf *resp_buf);
|
||||||
|
|
||||||
static HRESULT io3_cmd_write_gpio(
|
static HRESULT io3_cmd_write_gpio(
|
||||||
struct io3 *io3,
|
struct io3 *io3,
|
||||||
struct const_iobuf *req_buf,
|
struct const_iobuf *req_buf,
|
||||||
|
@ -116,6 +122,13 @@ static uint8_t io3_features[] = {
|
||||||
|
|
||||||
0x03, 8, 10, 0,
|
0x03, 8, 10, 0,
|
||||||
|
|
||||||
|
/* Feature : 0x04 : Rotary inputs
|
||||||
|
Param1 : 4 : Number of rotary channels
|
||||||
|
Param2 : 0 : N/A
|
||||||
|
Param3 : 0 : N/A */
|
||||||
|
|
||||||
|
0x04, 4, 0, 0,
|
||||||
|
|
||||||
/* Feature : 0x12 : GPIO outputs
|
/* Feature : 0x12 : GPIO outputs
|
||||||
Param1 : 3 : Number of ports (8 bits per port)
|
Param1 : 3 : Number of ports (8 bits per port)
|
||||||
Param2 : 0 : N/A
|
Param2 : 0 : N/A
|
||||||
|
@ -219,6 +232,9 @@ static HRESULT io3_cmd(
|
||||||
case JVS_CMD_READ_ANALOGS:
|
case JVS_CMD_READ_ANALOGS:
|
||||||
return io3_cmd_read_analogs(io3, req, resp);
|
return io3_cmd_read_analogs(io3, req, resp);
|
||||||
|
|
||||||
|
case JVS_CMD_READ_ROTARYS:
|
||||||
|
return io3_cmd_read_rotarys(io3, req, resp);
|
||||||
|
|
||||||
case JVS_CMD_WRITE_GPIO:
|
case JVS_CMD_WRITE_GPIO:
|
||||||
return io3_cmd_write_gpio(io3, req, resp);
|
return io3_cmd_write_gpio(io3, req, resp);
|
||||||
|
|
||||||
|
@ -375,7 +391,7 @@ static HRESULT io3_cmd_read_switches(
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_IO3)
|
||||||
dprintf("JVS I/O: Read switches, np=%i, bpp=%i\n",
|
dprintf("JVS I/O: Read switches, np=%i, bpp=%i\n",
|
||||||
req.num_players,
|
req.num_players,
|
||||||
req.bytes_per_player);
|
req.bytes_per_player);
|
||||||
|
@ -536,6 +552,60 @@ static HRESULT io3_cmd_read_analogs(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT io3_cmd_read_rotarys(
|
||||||
|
struct io3 *io3,
|
||||||
|
struct const_iobuf *req_buf,
|
||||||
|
struct iobuf *resp_buf)
|
||||||
|
{
|
||||||
|
struct jvs_req_read_rotarys req;
|
||||||
|
uint16_t rotarys[4];
|
||||||
|
uint8_t i;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
/* Read req */
|
||||||
|
|
||||||
|
hr = iobuf_read(req_buf, &req, sizeof(req));
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.nrotarys > _countof(rotarys)) {
|
||||||
|
dprintf("JVS I/O: Invalid analog count %i\n", req.nrotarys);
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//dprintf("JVS I/O: Read rotarys, nrotarys=%i\n", req.nrotarys);
|
||||||
|
|
||||||
|
/* Write report byte */
|
||||||
|
|
||||||
|
hr = iobuf_write_8(resp_buf, 0x01);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write analogs */
|
||||||
|
|
||||||
|
memset(rotarys, 0, sizeof(rotarys));
|
||||||
|
|
||||||
|
if (io3->ops->read_rotarys != NULL) {
|
||||||
|
io3->ops->read_rotarys(io3->ops_ctx, rotarys, req.nrotarys);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < req.nrotarys ; i++) {
|
||||||
|
hr = iobuf_write_be16(resp_buf, rotarys[i]);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT io3_cmd_write_gpio(
|
static HRESULT io3_cmd_write_gpio(
|
||||||
struct io3 *io3,
|
struct io3 *io3,
|
||||||
struct const_iobuf *req_buf,
|
struct const_iobuf *req_buf,
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct io3_ops {
|
||||||
void (*write_gpio)(void *ctx, uint32_t state);
|
void (*write_gpio)(void *ctx, uint32_t state);
|
||||||
void (*read_switches)(void *ctx, struct io3_switch_state *out);
|
void (*read_switches)(void *ctx, struct io3_switch_state *out);
|
||||||
void (*read_analogs)(void *ctx, uint16_t *analogs, uint8_t nanalogs);
|
void (*read_analogs)(void *ctx, uint16_t *analogs, uint8_t nanalogs);
|
||||||
|
void (*read_rotarys)(void *ctx, uint16_t *rotaries, uint8_t nrotaries);
|
||||||
void (*read_coin_counter)(void *ctx, uint8_t slot_no, uint16_t *out);
|
void (*read_coin_counter)(void *ctx, uint8_t slot_no, uint16_t *out);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "board/config.h"
|
#include "board/config.h"
|
||||||
#include "board/guid.h"
|
#include "board/guid.h"
|
||||||
|
@ -48,7 +49,7 @@ static_assert(sizeof(struct io4_report_in) == 0x40, "IO4 IN report size");
|
||||||
struct io4_report_out {
|
struct io4_report_out {
|
||||||
uint8_t report_id;
|
uint8_t report_id;
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
uint8_t payload[62];
|
uint8_t payload[IO4_REPORT_OUT_PAYLOAD_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(struct io4_report_out) == 0x40, "IO4 OUT report size");
|
static_assert(sizeof(struct io4_report_out) == 0x40, "IO4 OUT report size");
|
||||||
|
@ -223,7 +224,11 @@ static HRESULT io4_handle_write(struct irp *irp)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
case IO4_CMD_SET_GENERAL_OUTPUT:
|
case IO4_CMD_SET_GENERAL_OUTPUT:
|
||||||
dprintf("USB I/O: GPIO Out\n");
|
// dprintf("USB I/O: GPIO Out\n");
|
||||||
|
|
||||||
|
if (io4_ops->write_gpio != NULL) {
|
||||||
|
return io4_ops->write_gpio(out.payload, IO4_REPORT_OUT_PAYLOAD_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define IO4_REPORT_OUT_PAYLOAD_LEN 62
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* System buttons in button[0] */
|
/* System buttons in button[0] */
|
||||||
|
@ -24,6 +27,7 @@ struct io4_state {
|
||||||
|
|
||||||
struct io4_ops {
|
struct io4_ops {
|
||||||
HRESULT (*poll)(void *ctx, struct io4_state *state);
|
HRESULT (*poll)(void *ctx, struct io4_state *state);
|
||||||
|
HRESULT (*write_gpio)(uint8_t* payload, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT io4_hook_init(
|
HRESULT io4_hook_init(
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "board/led15070-frame.h"
|
||||||
|
|
||||||
|
/* Command IDs */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LED_15070_CMD_RESET = 0x10,
|
||||||
|
LED_15070_CMD_SET_INPUT = 0x28, // No known use case
|
||||||
|
LED_15070_CMD_SET_NORMAL_12BIT = 0x30, // TODO
|
||||||
|
LED_15070_CMD_SET_NORMAL_8BIT = 0x31,
|
||||||
|
LED_15070_CMD_SET_MULTI_FLASH_8BIT = 0x32,
|
||||||
|
LED_15070_CMD_SET_MULTI_FADE_8BIT = 0x33,
|
||||||
|
LED_15070_CMD_SET_PALETTE_7_NORMAL_LED = 0x34, // No known use case
|
||||||
|
LED_15070_CMD_SET_PALETTE_6_FLASH_LED = 0x35, // No known use case
|
||||||
|
LED_15070_CMD_SET_15DC_OUT = 0x36, // No known use case
|
||||||
|
LED_15070_CMD_SET_15GS_OUT = 0x37, // No known use case
|
||||||
|
LED_15070_CMD_SET_PSC_MAX = 0x38, // No known use case
|
||||||
|
LED_15070_CMD_SET_FET_OUTPUT = 0x39,
|
||||||
|
LED_15070_CMD_SET_GS_PALETTE = 0x3A,
|
||||||
|
LED_15070_CMD_DC_UPDATE = 0x3B,
|
||||||
|
LED_15070_CMD_GS_UPDATE = 0x3C,
|
||||||
|
LED_15070_CMD_ROTATE = 0x3E, // No known use case, wtf is this?
|
||||||
|
LED_15070_CMD_SET_DC_DATA = 0x3F,
|
||||||
|
LED_15070_CMD_EEPROM_WRITE = 0x7B,
|
||||||
|
LED_15070_CMD_EEPROM_READ = 0x7C,
|
||||||
|
LED_15070_CMD_ACK_ON = 0x7D,
|
||||||
|
LED_15070_CMD_ACK_OFF = 0x7E,
|
||||||
|
LED_15070_CMD_BOARD_INFO = 0xF0,
|
||||||
|
LED_15070_CMD_BOARD_STATUS = 0xF1,
|
||||||
|
LED_15070_CMD_FW_SUM = 0xF2,
|
||||||
|
LED_15070_CMD_PROTOCOL_VER = 0xF3,
|
||||||
|
LED_15070_CMD_TO_BOOT_MODE = 0xFD,
|
||||||
|
LED_15070_CMD_FW_UPDATE = 0xFE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Response codes */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LED_15070_STATUS_OK = 0x01,
|
||||||
|
LED_15070_STATUS_SUM_ERR = 0x02,
|
||||||
|
LED_15070_STATUS_PARITY_ERR = 0x03,
|
||||||
|
LED_15070_STATUS_FRAMING_ERR = 0x04,
|
||||||
|
LED_15070_STATUS_OVERRUN_ERR = 0x05,
|
||||||
|
LED_15070_STATUS_BUFFER_OVERFLOW = 0x06,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LED_15070_REPORT_OK = 0x01,
|
||||||
|
LED_15070_REPORT_WAIT = 0x02,
|
||||||
|
LED_15070_REPORT_ERR1 = 0x03,
|
||||||
|
LED_15070_REPORT_ERR2 = 0x04,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Request data structures */
|
||||||
|
|
||||||
|
struct led15070_req_any {
|
||||||
|
struct led15070_hdr hdr;
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t payload[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Response data structures */
|
||||||
|
|
||||||
|
struct led15070_resp_any {
|
||||||
|
struct led15070_hdr hdr;
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t report;
|
||||||
|
uint8_t data[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct led15070_resp_board_info {
|
||||||
|
struct led15070_hdr hdr;
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t report;
|
||||||
|
char board_num[8];
|
||||||
|
uint8_t endcode; // Always 0xFF
|
||||||
|
uint8_t fw_ver;
|
||||||
|
};
|
|
@ -0,0 +1,194 @@
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "board/led15070-frame.h"
|
||||||
|
|
||||||
|
#include "hook/iobuf.h"
|
||||||
|
|
||||||
|
static void led15070_frame_sync(struct iobuf *src);
|
||||||
|
static HRESULT led15070_frame_accept(const struct iobuf *dest);
|
||||||
|
static HRESULT led15070_frame_encode_byte(struct iobuf *dest, uint8_t byte);
|
||||||
|
|
||||||
|
/* Frame structure:
|
||||||
|
|
||||||
|
[0] Sync byte (0xE0)
|
||||||
|
[1] Destination address
|
||||||
|
[2] Source Address
|
||||||
|
[3] Length of data/payload
|
||||||
|
[4] Data/payload
|
||||||
|
For requests (host to board):
|
||||||
|
[0] Command
|
||||||
|
... Payload
|
||||||
|
For responses (board to host):
|
||||||
|
[0] Status
|
||||||
|
[1] Command
|
||||||
|
[2] Report
|
||||||
|
... Payload
|
||||||
|
[n] Checksum: Sum of all prior bytes (excluding sync byte)
|
||||||
|
|
||||||
|
Byte stuffing:
|
||||||
|
|
||||||
|
0xD0 is an escape byte. Un-escape the subsequent byte by adding 1. */
|
||||||
|
|
||||||
|
static void led15070_frame_sync(struct iobuf *src)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < src->pos && src->bytes[i] != 0xE0 ; i++);
|
||||||
|
|
||||||
|
src->pos -= i;
|
||||||
|
memmove(&src->bytes[0], &src->bytes[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT led15070_frame_accept(const struct iobuf *dest)
|
||||||
|
{
|
||||||
|
uint8_t checksum;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (dest->pos < 3 || dest->pos != dest->bytes[3] + 5) {
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
checksum = 0;
|
||||||
|
|
||||||
|
for (i = 1 ; i < dest->pos - 1 ; i++) {
|
||||||
|
checksum += dest->bytes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//dprintf("LED checksum %02x, expected %02x\n", checksum, dest->bytes[dest->pos - 1]);
|
||||||
|
|
||||||
|
if (checksum != dest->bytes[dest->pos - 1]) {
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_CRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT led15070_frame_decode(struct iobuf *dest, struct iobuf *src)
|
||||||
|
{
|
||||||
|
uint8_t byte;
|
||||||
|
bool escape;
|
||||||
|
size_t i;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(dest != NULL);
|
||||||
|
assert(dest->bytes != NULL || dest->nbytes == 0);
|
||||||
|
assert(dest->pos <= dest->nbytes);
|
||||||
|
assert(src != NULL);
|
||||||
|
assert(src->bytes != NULL || src->nbytes == 0);
|
||||||
|
assert(src->pos <= src->nbytes);
|
||||||
|
|
||||||
|
led15070_frame_sync(src);
|
||||||
|
|
||||||
|
dest->pos = 0;
|
||||||
|
escape = false;
|
||||||
|
|
||||||
|
for (i = 0, hr = S_FALSE ; i < src->pos && hr == S_FALSE ; i++) {
|
||||||
|
/* Step the FSM to unstuff another byte */
|
||||||
|
|
||||||
|
byte = src->bytes[i];
|
||||||
|
|
||||||
|
if (dest->pos >= dest->nbytes) {
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
} else if (i == 0) {
|
||||||
|
dest->bytes[dest->pos++] = byte;
|
||||||
|
} else if (byte == 0xE0) {
|
||||||
|
hr = E_FAIL;
|
||||||
|
} else if (byte == 0xD0) {
|
||||||
|
if (escape) {
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
escape = true;
|
||||||
|
} else if (escape) {
|
||||||
|
dest->bytes[dest->pos++] = byte + 1;
|
||||||
|
escape = false;
|
||||||
|
} else {
|
||||||
|
dest->bytes[dest->pos++] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to accept the packet we've built up so far */
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = led15070_frame_accept(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle FSM terminal state */
|
||||||
|
|
||||||
|
if (hr != S_FALSE) {
|
||||||
|
/* Frame was either accepted or rejected, remove it from src */
|
||||||
|
memmove(&src->bytes[0], &src->bytes[i], src->pos - i);
|
||||||
|
src->pos -= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT led15070_frame_encode(
|
||||||
|
struct iobuf *dest,
|
||||||
|
const void *ptr,
|
||||||
|
size_t nbytes)
|
||||||
|
{
|
||||||
|
const uint8_t *src;
|
||||||
|
uint8_t checksum;
|
||||||
|
uint8_t byte;
|
||||||
|
size_t i;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(dest != NULL);
|
||||||
|
assert(dest->bytes != NULL || dest->nbytes == 0);
|
||||||
|
assert(dest->pos <= dest->nbytes);
|
||||||
|
assert(ptr != NULL);
|
||||||
|
|
||||||
|
src = ptr;
|
||||||
|
|
||||||
|
assert(nbytes >= 3 && src[0] == 0xE0 && src[3] + 4 == nbytes);
|
||||||
|
|
||||||
|
if (dest->pos >= dest->nbytes) {
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->bytes[dest->pos++] = 0xE0;
|
||||||
|
checksum = 0;
|
||||||
|
// dprintf("%02x ", 0xe0);
|
||||||
|
|
||||||
|
for (i = 1 ; i < nbytes ; i++) {
|
||||||
|
byte = src[i];
|
||||||
|
checksum += byte;
|
||||||
|
// dprintf("%02x ", byte);
|
||||||
|
|
||||||
|
hr = led15070_frame_encode_byte(dest, byte);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dprintf("%02x \n", checksum);
|
||||||
|
|
||||||
|
return led15070_frame_encode_byte(dest, checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT led15070_frame_encode_byte(struct iobuf *dest, uint8_t byte)
|
||||||
|
{
|
||||||
|
if (byte == 0xE0 || byte == 0xD0) {
|
||||||
|
if (dest->pos + 2 > dest->nbytes) {
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->bytes[dest->pos++] = 0xD0;
|
||||||
|
dest->bytes[dest->pos++] = byte - 1;
|
||||||
|
} else {
|
||||||
|
if (dest->pos + 1 > dest->nbytes) {
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->bytes[dest->pos++] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "hook/iobuf.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LED_15070_FRAME_SYNC = 0xE0,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct led15070_hdr {
|
||||||
|
uint8_t sync;
|
||||||
|
uint8_t dest_adr;
|
||||||
|
uint8_t src_adr;
|
||||||
|
uint8_t nbytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT led15070_frame_decode(struct iobuf *dest, struct iobuf *src);
|
||||||
|
|
||||||
|
HRESULT led15070_frame_encode(
|
||||||
|
struct iobuf *dest,
|
||||||
|
const void *ptr,
|
||||||
|
size_t nbytes);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct led15070_config {
|
||||||
|
bool enable;
|
||||||
|
unsigned int port_no[2];
|
||||||
|
char board_number[8];
|
||||||
|
uint8_t fw_ver;
|
||||||
|
uint16_t fw_sum;
|
||||||
|
wchar_t eeprom_path[MAX_PATH];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef HRESULT (*io_led_init_t)(void);
|
||||||
|
typedef void (*io_led_set_fet_output_t)(uint8_t board, const uint8_t *rgb);
|
||||||
|
typedef void (*io_led_dc_update_t)(uint8_t board, const uint8_t *rgb);
|
||||||
|
typedef void (*io_led_gs_update_t)(uint8_t board, const uint8_t *rgb);
|
||||||
|
|
||||||
|
HRESULT led15070_hook_init(
|
||||||
|
const struct led15070_config *cfg,
|
||||||
|
io_led_init_t _led_init,
|
||||||
|
io_led_set_fet_output_t _led_set_fet_output,
|
||||||
|
io_led_dc_update_t _led_dc_update,
|
||||||
|
io_led_gs_update_t _led_gs_update,
|
||||||
|
unsigned int port_no[2]);
|
|
@ -88,7 +88,7 @@ struct led15093_req_reset {
|
||||||
struct led15093_req_set_timeout {
|
struct led15093_req_set_timeout {
|
||||||
struct led15093_req_hdr hdr;
|
struct led15093_req_hdr hdr;
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
uint8_t count;
|
uint16_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct led15093_req_set_disable_response {
|
struct led15093_req_set_disable_response {
|
||||||
|
@ -199,7 +199,7 @@ struct led15093_resp_board_info {
|
||||||
char chip_num[5];
|
char chip_num[5];
|
||||||
uint8_t endcode; // Always 0xFF
|
uint8_t endcode; // Always 0xFF
|
||||||
uint8_t fw_ver;
|
uint8_t fw_ver;
|
||||||
uint8_t rx_buf;
|
uint16_t rx_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct led15093_resp_protocol_ver {
|
struct led15093_resp_protocol_ver {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
SEGA 837-15093-XX LED Controller Board emulator
|
SEGA 837-15093-XX LED Controller Board emulator
|
||||||
|
|
||||||
Supported variants:
|
Supported variants:
|
||||||
|
|
||||||
837-15093
|
837-15093
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "board/led15093-cmd.h"
|
#include "board/led15093-cmd.h"
|
||||||
|
@ -106,9 +107,13 @@ static uint8_t led15093_host_adr = 1;
|
||||||
static io_led_init_t led_init;
|
static io_led_init_t led_init;
|
||||||
static io_led_set_leds_t set_leds;
|
static io_led_set_leds_t set_leds;
|
||||||
|
|
||||||
HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init,
|
HRESULT led15093_hook_init(
|
||||||
io_led_set_leds_t _set_leds, unsigned int first_port, unsigned int num_boards, uint8_t board_adr, uint8_t host_adr)
|
const struct led15093_config *cfg,
|
||||||
|
io_led_init_t _led_init,
|
||||||
|
io_led_set_leds_t _set_leds,
|
||||||
|
unsigned int port_no[2])
|
||||||
{
|
{
|
||||||
|
unsigned int num_boards = 0;
|
||||||
|
|
||||||
assert(cfg != NULL);
|
assert(cfg != NULL);
|
||||||
assert(_led_init != NULL);
|
assert(_led_init != NULL);
|
||||||
|
@ -118,14 +123,24 @@ HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg->port_no != 0) {
|
for (int i = 0; i < led15093_nboards; i++)
|
||||||
first_port = cfg->port_no;
|
{
|
||||||
|
if (cfg->port_no[i] != 0) {
|
||||||
|
port_no[i] = cfg->port_no[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port_no[i] != 0) {
|
||||||
|
num_boards++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(num_boards != 0);
|
||||||
|
|
||||||
|
led15093_board_adr = num_boards;
|
||||||
|
led15093_host_adr = num_boards == 2 ? 1 : 2;
|
||||||
|
|
||||||
led_init = _led_init;
|
led_init = _led_init;
|
||||||
set_leds = _set_leds;
|
set_leds = _set_leds;
|
||||||
led15093_board_adr = board_adr;
|
|
||||||
led15093_host_adr = host_adr;
|
|
||||||
|
|
||||||
memcpy(led15093_board_num, cfg->board_number, sizeof(led15093_board_num));
|
memcpy(led15093_board_num, cfg->board_number, sizeof(led15093_board_num));
|
||||||
memcpy(led15093_chip_num, cfg->chip_number, sizeof(led15093_chip_num));
|
memcpy(led15093_chip_num, cfg->chip_number, sizeof(led15093_chip_num));
|
||||||
|
@ -139,7 +154,7 @@ HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led
|
||||||
|
|
||||||
InitializeCriticalSection(&vb->lock);
|
InitializeCriticalSection(&vb->lock);
|
||||||
|
|
||||||
uart_init(&vb->boarduart, first_port + i);
|
uart_init(&vb->boarduart, port_no[i]);
|
||||||
if (cfg->high_baudrate) {
|
if (cfg->high_baudrate) {
|
||||||
vb->boarduart.baud.BaudRate = 460800;
|
vb->boarduart.baud.BaudRate = 460800;
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,7 +223,6 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp)
|
||||||
_led15093_per_board_vars *v = &led15093_per_board_vars[board];
|
_led15093_per_board_vars *v = &led15093_per_board_vars[board];
|
||||||
struct uart *boarduart = &led15093_per_board_vars[board].boarduart;
|
struct uart *boarduart = &led15093_per_board_vars[board].boarduart;
|
||||||
|
|
||||||
/*
|
|
||||||
if (irp->op == IRP_OP_OPEN) {
|
if (irp->op == IRP_OP_OPEN) {
|
||||||
// Unfortunately the LED board UART gets opened and closed repeatedly
|
// Unfortunately the LED board UART gets opened and closed repeatedly
|
||||||
|
|
||||||
|
@ -235,30 +249,6 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
if (irp->op == IRP_OP_OPEN) {
|
|
||||||
dprintf("LED 15093: Starting backend DLL\n");
|
|
||||||
// int res = led_init();
|
|
||||||
hr = led_init();
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (res != 0) {
|
|
||||||
dprintf("LED 15093: Backend error, LED board disconnected: "
|
|
||||||
"%d\n",
|
|
||||||
res);
|
|
||||||
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dprintf("LED 15093: Backend error, LED board disconnected: "
|
|
||||||
"%x\n",
|
|
||||||
(int) hr);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = uart_handle_irp(boarduart, irp);
|
hr = uart_handle_irp(boarduart, irp);
|
||||||
|
|
||||||
|
@ -267,12 +257,12 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if 0
|
#if defined(LOG_LED15093)
|
||||||
dprintf("TX Buffer:\n");
|
dprintf("TX Buffer:\n");
|
||||||
dump_iobuf(&boarduart->written);
|
dump_iobuf(&boarduart->written);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
req_iobuf.bytes = (byte*)&req;
|
req_iobuf.bytes = (uint8_t*)&req;
|
||||||
req_iobuf.nbytes = sizeof(req.hdr) + sizeof(req.payload);
|
req_iobuf.nbytes = sizeof(req.hdr) + sizeof(req.payload);
|
||||||
req_iobuf.pos = 0;
|
req_iobuf.pos = 0;
|
||||||
|
|
||||||
|
@ -294,7 +284,7 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_LED15093)
|
||||||
dprintf("Deframe Buffer:\n");
|
dprintf("Deframe Buffer:\n");
|
||||||
dump_iobuf(&req_iobuf);
|
dump_iobuf(&req_iobuf);
|
||||||
#endif
|
#endif
|
||||||
|
@ -687,16 +677,6 @@ static HRESULT led15093_req_set_imm_led(int board, const struct led15093_req_set
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if (board == 0) {
|
|
||||||
dprintf("board %d: red: %d, green: %d, blue: %d\n", board, req->data[0x96], req->data[0x97], req->data[0x98]);
|
|
||||||
}
|
|
||||||
else if (board == 1)
|
|
||||||
{
|
|
||||||
dprintf("board %d: red: %d, green: %d, blue: %d\n", board, req->data[0xb4], req->data[0xb5], req->data[0xb6]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Return the current LED data, remove const qualifier
|
// Return the current LED data, remove const qualifier
|
||||||
set_leds(board, (uint8_t *) req->data);
|
set_leds(board, (uint8_t *) req->data);
|
||||||
|
|
||||||
|
@ -717,7 +697,7 @@ static HRESULT led15093_req_set_imm_led(int board, const struct led15093_req_set
|
||||||
resp.status = v->status_code;
|
resp.status = v->status_code;
|
||||||
if (req->cmd == LED_15093_CMD_SET_IMM_LED) {
|
if (req->cmd == LED_15093_CMD_SET_IMM_LED) {
|
||||||
resp.cmd = LED_15093_CMD_SET_IMM_LED;
|
resp.cmd = LED_15093_CMD_SET_IMM_LED;
|
||||||
}
|
}
|
||||||
// else {
|
// else {
|
||||||
// resp.cmd = LED_15093_CMD_SET_IMM_LED_LEGACY;
|
// resp.cmd = LED_15093_CMD_SET_IMM_LED_LEGACY;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
struct led15093_config {
|
struct led15093_config {
|
||||||
bool enable;
|
bool enable;
|
||||||
bool high_baudrate;
|
bool high_baudrate;
|
||||||
unsigned int port_no;
|
unsigned int port_no[2];
|
||||||
char board_number[8];
|
char board_number[8];
|
||||||
char chip_number[5];
|
char chip_number[5];
|
||||||
char boot_chip_number[5];
|
char boot_chip_number[5];
|
||||||
|
@ -20,5 +20,5 @@ typedef HRESULT (*io_led_init_t)(void);
|
||||||
typedef void (*io_led_set_leds_t)(uint8_t board, uint8_t *rgb);
|
typedef void (*io_led_set_leds_t)(uint8_t board, uint8_t *rgb);
|
||||||
|
|
||||||
HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init,
|
HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init,
|
||||||
io_led_set_leds_t _set_leds, unsigned int first_port, unsigned int num_boards, uint8_t board_adr, uint8_t host_adr);
|
io_led_set_leds_t _set_leds, unsigned int port_no[2]);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ board_lib = static_library(
|
||||||
'board',
|
'board',
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
],
|
],
|
||||||
|
@ -25,6 +24,11 @@ board_lib = static_library(
|
||||||
'led15093-frame.h',
|
'led15093-frame.h',
|
||||||
'led15093.c',
|
'led15093.c',
|
||||||
'led15093.h',
|
'led15093.h',
|
||||||
|
'led15070-cmd.h',
|
||||||
|
'led15070-frame.c',
|
||||||
|
'led15070-frame.h',
|
||||||
|
'led15070.c',
|
||||||
|
'led15070.h',
|
||||||
'sg-cmd.c',
|
'sg-cmd.c',
|
||||||
'sg-cmd.h',
|
'sg-cmd.h',
|
||||||
'sg-frame.c',
|
'sg-frame.c',
|
||||||
|
@ -42,5 +46,10 @@ board_lib = static_library(
|
||||||
'slider-frame.h',
|
'slider-frame.h',
|
||||||
'vfd.c',
|
'vfd.c',
|
||||||
'vfd.h',
|
'vfd.h',
|
||||||
|
'vfd-cmd.h',
|
||||||
|
'vfd-frame.c',
|
||||||
|
'vfd-frame.h',
|
||||||
|
'ffb.c',
|
||||||
|
'ffb.h'
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,6 +25,13 @@ struct sg_res_header {
|
||||||
uint8_t payload_len;
|
uint8_t payload_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* struct to save the version string with its length
|
||||||
|
to fix NUL terminator issues */
|
||||||
|
struct version_info {
|
||||||
|
const char *version;
|
||||||
|
uint8_t length;
|
||||||
|
};
|
||||||
|
|
||||||
typedef HRESULT (*sg_dispatch_fn_t)(
|
typedef HRESULT (*sg_dispatch_fn_t)(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
const void *req,
|
const void *req,
|
||||||
|
|
|
@ -27,11 +27,11 @@ static HRESULT sg_led_cmd_set_color(
|
||||||
const struct sg_led *led,
|
const struct sg_led *led,
|
||||||
const struct sg_led_req_set_color *req);
|
const struct sg_led_req_set_color *req);
|
||||||
|
|
||||||
const char *sg_led_info[] = {
|
static const struct version_info led_version[] = {
|
||||||
"15084\xFF\x10\x00\x12",
|
{"15084\xFF\x10\x00\x12", 9},
|
||||||
"000-00000\xFF\x11\x40",
|
{"000-00000\xFF\x11\x40", 12},
|
||||||
// maybe the same?
|
// maybe the same?
|
||||||
"000-00000\xFF\x11\x40"
|
{"000-00000\xFF\x11\x40", 12}
|
||||||
};
|
};
|
||||||
|
|
||||||
void sg_led_init(
|
void sg_led_init(
|
||||||
|
@ -156,10 +156,10 @@ static HRESULT sg_led_cmd_get_info(
|
||||||
{
|
{
|
||||||
sg_led_dprintf(led, "Get info\n");
|
sg_led_dprintf(led, "Get info\n");
|
||||||
|
|
||||||
unsigned int len = strlen(sg_led_info[led->gen - 1]);
|
const struct version_info *fw = &led_version[led->gen - 1];
|
||||||
|
|
||||||
sg_res_init(&res->res, req, len);
|
sg_res_init(&res->res, req, fw->length);
|
||||||
memcpy(res->payload, sg_led_info[led->gen - 1], len);
|
memcpy(res->payload, fw->version, fw->length);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,19 +5,21 @@
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SG_NFC_CMD_GET_FW_VERSION = 0x30,
|
SG_NFC_CMD_GET_FW_VERSION = 0x30,
|
||||||
SG_NFC_CMD_GET_HW_VERSION = 0x32,
|
SG_NFC_CMD_GET_HW_VERSION = 0x32,
|
||||||
SG_NFC_CMD_RADIO_ON = 0x40,
|
SG_NFC_CMD_RADIO_ON = 0x40,
|
||||||
SG_NFC_CMD_RADIO_OFF = 0x41,
|
SG_NFC_CMD_RADIO_OFF = 0x41,
|
||||||
SG_NFC_CMD_POLL = 0x42,
|
SG_NFC_CMD_POLL = 0x42,
|
||||||
SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43,
|
SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43,
|
||||||
SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x50,
|
SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x50,
|
||||||
SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52,
|
SG_NFC_CMD_MIFARE_AUTHENTICATE_AIME = 0x51,
|
||||||
SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x54,
|
SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52,
|
||||||
SG_NFC_CMD_MIFARE_AUTHENTICATE = 0x55, /* guess based on time sent */
|
SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x54,
|
||||||
SG_NFC_CMD_SEND_HEX_DATA = 0x61,
|
SG_NFC_CMD_MIFARE_AUTHENTICATE_BANA = 0x55,
|
||||||
SG_NFC_CMD_RESET = 0x62,
|
SG_NFC_CMD_TO_UPDATE_MODE = 0x60,
|
||||||
SG_NFC_CMD_FELICA_ENCAP = 0x71,
|
SG_NFC_CMD_SEND_HEX_DATA = 0x61,
|
||||||
|
SG_NFC_CMD_RESET = 0x62,
|
||||||
|
SG_NFC_CMD_FELICA_ENCAP = 0x71,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sg_nfc_res_get_fw_version {
|
struct sg_nfc_res_get_fw_version {
|
||||||
|
@ -32,7 +34,7 @@ struct sg_nfc_res_get_hw_version {
|
||||||
|
|
||||||
struct sg_nfc_req_mifare_set_key {
|
struct sg_nfc_req_mifare_set_key {
|
||||||
struct sg_req_header req;
|
struct sg_req_header req;
|
||||||
uint8_t key_a[6];
|
uint8_t key[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sg_nfc_req_mifare_50 {
|
struct sg_nfc_req_mifare_50 {
|
||||||
|
|
131
board/sg-nfc.c
131
board/sg-nfc.c
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/dump.h"
|
#include "util/dump.h"
|
||||||
|
#include "util/slurp.h"
|
||||||
|
|
||||||
static HRESULT sg_nfc_dispatch(
|
static HRESULT sg_nfc_dispatch(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
|
@ -60,21 +62,26 @@ static HRESULT sg_nfc_cmd_felica_encap(
|
||||||
const struct sg_nfc_req_felica_encap *req,
|
const struct sg_nfc_req_felica_encap *req,
|
||||||
struct sg_nfc_res_felica_encap *res);
|
struct sg_nfc_res_felica_encap *res);
|
||||||
|
|
||||||
|
static HRESULT sg_nfc_cmd_send_hex_data(
|
||||||
|
struct sg_nfc *nfc,
|
||||||
|
const struct sg_req_header *req,
|
||||||
|
struct sg_res_header *res);
|
||||||
|
|
||||||
static HRESULT sg_nfc_cmd_dummy(
|
static HRESULT sg_nfc_cmd_dummy(
|
||||||
struct sg_nfc *nfc,
|
struct sg_nfc *nfc,
|
||||||
const struct sg_req_header *req,
|
const struct sg_req_header *req,
|
||||||
struct sg_res_header *res);
|
struct sg_res_header *res);
|
||||||
|
|
||||||
static const char *hw_version[] = {
|
static const struct version_info hw_version[] = {
|
||||||
"TN32MSEC003S H/W Ver3.0",
|
{"TN32MSEC003S H/W Ver3.0", 23},
|
||||||
"837-15286",
|
{"837-15286", 9},
|
||||||
"837-15396"
|
{"837-15396", 9}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *fw_version[] = {
|
static const struct version_info fw_version[] = {
|
||||||
"TN32MSEC003S F/W Ver1.2",
|
{"TN32MSEC003S F/W Ver1.2", 23},
|
||||||
"\x94",
|
{"\x94", 1},
|
||||||
"\x94"
|
{"\x94", 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
void sg_nfc_init(
|
void sg_nfc_init(
|
||||||
|
@ -82,6 +89,8 @@ void sg_nfc_init(
|
||||||
uint8_t addr,
|
uint8_t addr,
|
||||||
const struct sg_nfc_ops *ops,
|
const struct sg_nfc_ops *ops,
|
||||||
unsigned int gen,
|
unsigned int gen,
|
||||||
|
unsigned int proxy_flag,
|
||||||
|
const wchar_t* authdata_path,
|
||||||
void *ops_ctx)
|
void *ops_ctx)
|
||||||
{
|
{
|
||||||
assert(nfc != NULL);
|
assert(nfc != NULL);
|
||||||
|
@ -91,6 +100,8 @@ void sg_nfc_init(
|
||||||
nfc->ops_ctx = ops_ctx;
|
nfc->ops_ctx = ops_ctx;
|
||||||
nfc->addr = addr;
|
nfc->addr = addr;
|
||||||
nfc->gen = gen;
|
nfc->gen = gen;
|
||||||
|
nfc->proxy_flag = proxy_flag;
|
||||||
|
nfc->authdata_path = authdata_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
|
@ -184,13 +195,17 @@ static HRESULT sg_nfc_dispatch(
|
||||||
&req->felica_encap,
|
&req->felica_encap,
|
||||||
&res->felica_encap);
|
&res->felica_encap);
|
||||||
|
|
||||||
case SG_NFC_CMD_MIFARE_AUTHENTICATE:
|
case SG_NFC_CMD_MIFARE_AUTHENTICATE_AIME:
|
||||||
|
case SG_NFC_CMD_MIFARE_AUTHENTICATE_BANA:
|
||||||
|
case SG_NFC_CMD_SEND_HEX_DATA:
|
||||||
|
return sg_nfc_cmd_send_hex_data(nfc, &req->simple, &res->simple);
|
||||||
|
|
||||||
case SG_NFC_CMD_MIFARE_SELECT_TAG:
|
case SG_NFC_CMD_MIFARE_SELECT_TAG:
|
||||||
case SG_NFC_CMD_MIFARE_SET_KEY_AIME:
|
case SG_NFC_CMD_MIFARE_SET_KEY_AIME:
|
||||||
case SG_NFC_CMD_MIFARE_SET_KEY_BANA:
|
case SG_NFC_CMD_MIFARE_SET_KEY_BANA:
|
||||||
case SG_NFC_CMD_RADIO_ON:
|
case SG_NFC_CMD_RADIO_ON:
|
||||||
case SG_NFC_CMD_RADIO_OFF:
|
case SG_NFC_CMD_RADIO_OFF:
|
||||||
case SG_NFC_CMD_SEND_HEX_DATA: // TODO: implement?
|
case SG_NFC_CMD_TO_UPDATE_MODE:
|
||||||
return sg_nfc_cmd_dummy(nfc, &req->simple, &res->simple);
|
return sg_nfc_cmd_dummy(nfc, &req->simple, &res->simple);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -217,11 +232,11 @@ static HRESULT sg_nfc_cmd_get_fw_version(
|
||||||
const struct sg_req_header *req,
|
const struct sg_req_header *req,
|
||||||
struct sg_nfc_res_get_fw_version *res)
|
struct sg_nfc_res_get_fw_version *res)
|
||||||
{
|
{
|
||||||
unsigned int len = strlen(fw_version[nfc->gen - 1]);
|
const struct version_info *fw = &fw_version[nfc->gen - 1];
|
||||||
|
|
||||||
/* Dest version is not NUL terminated, this is intentional */
|
/* Dest version is not NUL terminated, this is intentional */
|
||||||
sg_res_init(&res->res, req, len);
|
sg_res_init(&res->res, req, fw->length);
|
||||||
memcpy(res->version, fw_version[nfc->gen - 1], len);
|
memcpy(res->version, fw->version, fw->length);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -231,11 +246,11 @@ static HRESULT sg_nfc_cmd_get_hw_version(
|
||||||
const struct sg_req_header *req,
|
const struct sg_req_header *req,
|
||||||
struct sg_nfc_res_get_hw_version *res)
|
struct sg_nfc_res_get_hw_version *res)
|
||||||
{
|
{
|
||||||
unsigned int len = strlen(hw_version[nfc->gen - 1]);
|
const struct version_info *hw = &hw_version[nfc->gen - 1];
|
||||||
|
|
||||||
/* Dest version is not NUL terminated, this is intentional */
|
/* Dest version is not NUL terminated, this is intentional */
|
||||||
sg_res_init(&res->res, req, len);
|
sg_res_init(&res->res, req, hw->length);
|
||||||
memcpy(res->version, hw_version[nfc->gen - 1], len);
|
memcpy(res->version, hw->version, hw->length);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -345,13 +360,13 @@ static HRESULT sg_nfc_poll_felica(
|
||||||
felica->type = 0x20;
|
felica->type = 0x20;
|
||||||
felica->id_len = sizeof(felica->IDm) + sizeof(felica->PMm);
|
felica->id_len = sizeof(felica->IDm) + sizeof(felica->PMm);
|
||||||
felica->IDm = _byteswap_uint64(IDm);
|
felica->IDm = _byteswap_uint64(IDm);
|
||||||
felica->PMm = _byteswap_uint64(felica_get_generic_PMm());
|
felica->PMm = _byteswap_uint64(felica_get_amusement_ic_PMm());
|
||||||
|
|
||||||
/* Initialize FeliCa IC emulator */
|
/* Initialize FeliCa IC emulator */
|
||||||
|
|
||||||
nfc->felica.IDm = IDm;
|
nfc->felica.IDm = IDm;
|
||||||
nfc->felica.PMm = felica_get_generic_PMm();
|
nfc->felica.PMm = felica_get_amusement_ic_PMm();
|
||||||
nfc->felica.system_code = 0x0000;
|
nfc->felica.system_code = 0x88b4;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -373,18 +388,62 @@ static HRESULT sg_nfc_cmd_mifare_read_block(
|
||||||
|
|
||||||
sg_nfc_dprintf(nfc, "Read uid %08x block %i\n", uid, req->payload.block_no);
|
sg_nfc_dprintf(nfc, "Read uid %08x block %i\n", uid, req->payload.block_no);
|
||||||
|
|
||||||
if (req->payload.block_no > 3) {
|
if (req->payload.block_no > 14) {
|
||||||
sg_nfc_dprintf(nfc, "MIFARE block number out of range\n");
|
sg_nfc_dprintf(nfc, "MIFARE block number out of range\n");
|
||||||
|
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
} else if (req->payload.block_no >= 5){ // emoney auth encrypted
|
||||||
|
|
||||||
|
sg_res_init(&res->res, &req->req, sizeof(res->block));
|
||||||
|
|
||||||
|
char* auth;
|
||||||
|
long size = wslurp(nfc->authdata_path, &auth, false);
|
||||||
|
if (size < 0){
|
||||||
|
sg_nfc_dprintf(nfc, "Failed to read %ls: %lx!\n", nfc->authdata_path, GetLastError());
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
if (req->payload.block_no == 6){
|
||||||
|
offset = 16;
|
||||||
|
} else if (req->payload.block_no == 8){
|
||||||
|
offset = 32;
|
||||||
|
} else if (req->payload.block_no == 9){
|
||||||
|
offset = 48;
|
||||||
|
} else if (req->payload.block_no == 10){
|
||||||
|
offset = 64;
|
||||||
|
} else if (req->payload.block_no == 12){
|
||||||
|
offset = 82;
|
||||||
|
} else if (req->payload.block_no == 13){
|
||||||
|
offset = 98;
|
||||||
|
} else if (req->payload.block_no == 14){
|
||||||
|
offset = 114;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 16 && offset + i < size; i++){
|
||||||
|
res->block[i] = auth[offset + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(auth);
|
||||||
|
|
||||||
|
} else if (req->payload.block_no == 4){ // emoney auth plain
|
||||||
|
|
||||||
|
sg_res_init(&res->res, &req->req, sizeof(res->block));
|
||||||
|
|
||||||
|
res->block[0] = 0x54; // header
|
||||||
|
res->block[1] = 0x43;
|
||||||
|
res->block[2] = nfc->proxy_flag; // 2 or 3 depending on game (useProxy in env.json)
|
||||||
|
res->block[3] = 0x01; // unknown flag
|
||||||
|
|
||||||
|
} else { // read all other blocks normally
|
||||||
|
|
||||||
|
sg_res_init(&res->res, &req->req, sizeof(res->block));
|
||||||
|
|
||||||
|
memcpy( res->block,
|
||||||
|
nfc->mifare.sectors[0].blocks[req->payload.block_no].bytes,
|
||||||
|
sizeof(res->block));
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_res_init(&res->res, &req->req, sizeof(res->block));
|
|
||||||
|
|
||||||
memcpy( res->block,
|
|
||||||
nfc->mifare.sectors[0].blocks[req->payload.block_no].bytes,
|
|
||||||
sizeof(res->block));
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +479,7 @@ static HRESULT sg_nfc_cmd_felica_encap(
|
||||||
f_res.nbytes = sizeof(res->payload);
|
f_res.nbytes = sizeof(res->payload);
|
||||||
f_res.pos = 1;
|
f_res.pos = 1;
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_NFC)
|
||||||
dprintf("FELICA OUTBOUND:\n");
|
dprintf("FELICA OUTBOUND:\n");
|
||||||
dump_const_iobuf(&f_req);
|
dump_const_iobuf(&f_req);
|
||||||
#endif
|
#endif
|
||||||
|
@ -434,7 +493,7 @@ static HRESULT sg_nfc_cmd_felica_encap(
|
||||||
sg_res_init(&res->res, &req->req, f_res.pos);
|
sg_res_init(&res->res, &req->req, f_res.pos);
|
||||||
res->payload[0] = f_res.pos;
|
res->payload[0] = f_res.pos;
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_NFC)
|
||||||
dprintf("FELICA INBOUND:\n");
|
dprintf("FELICA INBOUND:\n");
|
||||||
dump_iobuf(&f_res);
|
dump_iobuf(&f_res);
|
||||||
#endif
|
#endif
|
||||||
|
@ -442,6 +501,22 @@ static HRESULT sg_nfc_cmd_felica_encap(
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT sg_nfc_cmd_send_hex_data(
|
||||||
|
struct sg_nfc *nfc,
|
||||||
|
const struct sg_req_header *req,
|
||||||
|
struct sg_res_header *res)
|
||||||
|
{
|
||||||
|
sg_res_init(res, req, 0);
|
||||||
|
|
||||||
|
/* Firmware checksum length? */
|
||||||
|
if (req->payload_len == 0x2b) {
|
||||||
|
/* The firmware is identical flag? */
|
||||||
|
res->status = 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT sg_nfc_cmd_dummy(
|
static HRESULT sg_nfc_cmd_dummy(
|
||||||
struct sg_nfc *nfc,
|
struct sg_nfc *nfc,
|
||||||
const struct sg_req_header *req,
|
const struct sg_req_header *req,
|
||||||
|
|
|
@ -23,8 +23,10 @@ struct sg_nfc {
|
||||||
void *ops_ctx;
|
void *ops_ctx;
|
||||||
uint8_t addr;
|
uint8_t addr;
|
||||||
unsigned int gen;
|
unsigned int gen;
|
||||||
|
unsigned int proxy_flag;
|
||||||
struct felica felica;
|
struct felica felica;
|
||||||
struct mifare mifare;
|
struct mifare mifare;
|
||||||
|
const wchar_t* authdata_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sg_nfc_init(
|
void sg_nfc_init(
|
||||||
|
@ -32,6 +34,8 @@ void sg_nfc_init(
|
||||||
uint8_t addr,
|
uint8_t addr,
|
||||||
const struct sg_nfc_ops *ops,
|
const struct sg_nfc_ops *ops,
|
||||||
unsigned int gen,
|
unsigned int gen,
|
||||||
|
unsigned int proxy_flag,
|
||||||
|
const wchar_t* authdata_path,
|
||||||
void *ops_ctx);
|
void *ops_ctx);
|
||||||
|
|
||||||
void sg_nfc_transact(
|
void sg_nfc_transact(
|
||||||
|
|
|
@ -47,7 +47,7 @@ static struct sg_led sg_reader_led;
|
||||||
|
|
||||||
HRESULT sg_reader_hook_init(
|
HRESULT sg_reader_hook_init(
|
||||||
const struct aime_config *cfg,
|
const struct aime_config *cfg,
|
||||||
unsigned int port_no,
|
unsigned int default_port_no,
|
||||||
unsigned int gen,
|
unsigned int gen,
|
||||||
HINSTANCE self)
|
HINSTANCE self)
|
||||||
{
|
{
|
||||||
|
@ -66,6 +66,11 @@ HRESULT sg_reader_hook_init(
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int port_no = cfg->port_no;
|
||||||
|
if (port_no == 0){
|
||||||
|
port_no = default_port_no;
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg->gen != 0) {
|
if (cfg->gen != 0) {
|
||||||
gen = cfg->gen;
|
gen = cfg->gen;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +81,7 @@ HRESULT sg_reader_hook_init(
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_nfc_init(&sg_reader_nfc, 0x00, &sg_reader_nfc_ops, gen, NULL);
|
sg_nfc_init(&sg_reader_nfc, 0x00, &sg_reader_nfc_ops, gen, cfg->proxy_flag, cfg->authdata_path, NULL);
|
||||||
sg_led_init(&sg_reader_led, 0x08, &sg_reader_led_ops, gen, NULL);
|
sg_led_init(&sg_reader_led, 0x08, &sg_reader_led_ops, gen, NULL);
|
||||||
|
|
||||||
InitializeCriticalSection(&sg_reader_lock);
|
InitializeCriticalSection(&sg_reader_lock);
|
||||||
|
@ -85,6 +90,7 @@ HRESULT sg_reader_hook_init(
|
||||||
sg_reader_uart.baud.BaudRate = 38400;
|
sg_reader_uart.baud.BaudRate = 38400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprintf("NFC Assembly: enabling (port=%d)\n", port_no);
|
||||||
uart_init(&sg_reader_uart, port_no);
|
uart_init(&sg_reader_uart, port_no);
|
||||||
sg_reader_uart.written.bytes = sg_reader_written_bytes;
|
sg_reader_uart.written.bytes = sg_reader_written_bytes;
|
||||||
sg_reader_uart.written.nbytes = sizeof(sg_reader_written_bytes);
|
sg_reader_uart.written.nbytes = sizeof(sg_reader_written_bytes);
|
||||||
|
@ -115,14 +121,14 @@ static HRESULT sg_reader_handle_irp_locked(struct irp *irp)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_NFC)
|
||||||
if (irp->op == IRP_OP_WRITE) {
|
if (irp->op == IRP_OP_WRITE) {
|
||||||
dprintf("WRITE:\n");
|
dprintf("WRITE:\n");
|
||||||
dump_const_iobuf(&irp->write);
|
dump_const_iobuf(&irp->write);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_NFC)
|
||||||
if (irp->op == IRP_OP_READ) {
|
if (irp->op == IRP_OP_READ) {
|
||||||
dprintf("READ:\n");
|
dprintf("READ:\n");
|
||||||
dump_iobuf(&sg_reader_uart.readable);
|
dump_iobuf(&sg_reader_uart.readable);
|
||||||
|
|
|
@ -9,12 +9,15 @@
|
||||||
struct aime_config {
|
struct aime_config {
|
||||||
struct aime_dll_config dll;
|
struct aime_dll_config dll;
|
||||||
bool enable;
|
bool enable;
|
||||||
|
unsigned int port_no;
|
||||||
bool high_baudrate;
|
bool high_baudrate;
|
||||||
unsigned int gen;
|
unsigned int gen;
|
||||||
|
unsigned int proxy_flag;
|
||||||
|
wchar_t authdata_path[MAX_PATH];
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT sg_reader_hook_init(
|
HRESULT sg_reader_hook_init(
|
||||||
const struct aime_config *cfg,
|
const struct aime_config *cfg,
|
||||||
unsigned int port_no,
|
unsigned int default_port_no,
|
||||||
unsigned int gen,
|
unsigned int gen,
|
||||||
HINSTANCE self);
|
HINSTANCE self);
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "board/vfd-frame.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VFD_CMD_GET_VERSION = 0x5B,
|
||||||
|
VFD_CMD_RESET = 0x0B,
|
||||||
|
VFD_CMD_CLEAR_SCREEN = 0x0C,
|
||||||
|
VFD_CMD_SET_BRIGHTNESS = 0x20,
|
||||||
|
VFD_CMD_SET_SCREEN_ON = 0x21,
|
||||||
|
VFD_CMD_SET_H_SCROLL = 0x22,
|
||||||
|
VFD_CMD_DRAW_IMAGE = 0x2E,
|
||||||
|
VFD_CMD_SET_CURSOR = 0x30,
|
||||||
|
VFD_CMD_SET_ENCODING = 0x32,
|
||||||
|
VFD_CMD_SET_TEXT_WND = 0x40,
|
||||||
|
VFD_CMD_SET_TEXT_SPEED = 0x41,
|
||||||
|
VFD_CMD_WRITE_TEXT = 0x50,
|
||||||
|
VFD_CMD_ENABLE_SCROLL = 0x51,
|
||||||
|
VFD_CMD_DISABLE_SCROLL = 0x52,
|
||||||
|
VFD_CMD_ROTATE = 0x5D,
|
||||||
|
VFD_CMD_CREATE_CHAR = 0xA3,
|
||||||
|
VFD_CMD_CREATE_CHAR2 = 0xA4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VFD_ENC_GB2312 = 0,
|
||||||
|
VFD_ENC_BIG5 = 1,
|
||||||
|
VFD_ENC_SHIFT_JIS = 2,
|
||||||
|
VFD_ENC_KSC5601 = 3,
|
||||||
|
VFD_ENC_MAX = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_hdr {
|
||||||
|
uint8_t sync;
|
||||||
|
uint8_t cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_any {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t payload[2054];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_board_info {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t unk1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_resp_board_info { // \x0201.20\x03
|
||||||
|
uint8_t unk1;
|
||||||
|
char version[5];
|
||||||
|
uint8_t unk2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_reset {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_cls {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_brightness {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t brightness;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_power {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t power_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_hscroll {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t x_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_draw {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint16_t x0;
|
||||||
|
uint8_t y0;
|
||||||
|
uint16_t x1;
|
||||||
|
uint8_t y1;
|
||||||
|
uint8_t image[2048];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_cursor {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint16_t x;
|
||||||
|
uint8_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_encoding {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t encoding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_wnd {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint16_t x0;
|
||||||
|
uint8_t y0;
|
||||||
|
uint16_t x1;
|
||||||
|
uint8_t y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_speed {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t encoding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_scroll {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_rotate {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t unk1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfd_req_create_char {
|
||||||
|
struct vfd_req_hdr hdr;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t pixels[32];
|
||||||
|
};
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define SUPER_VERBOSE 1
|
||||||
|
|
||||||
|
#include "board/vfd-frame.h"
|
||||||
|
|
||||||
|
#include "hook/iobuf.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static HRESULT vfd_frame_encode_byte(struct iobuf *dest, uint8_t byte);
|
||||||
|
|
||||||
|
/* Frame structure:
|
||||||
|
|
||||||
|
REQUEST:
|
||||||
|
[0] Sync byte (0x1A or 0x1B)
|
||||||
|
[1] Packet ID
|
||||||
|
[2...n-1] Data/payload
|
||||||
|
|
||||||
|
--- OR ---
|
||||||
|
|
||||||
|
if no sync byte is given, plain static text in the currently configured encoding is expected.
|
||||||
|
|
||||||
|
RESPONSE:
|
||||||
|
This thing never responds, unless it's VFD_CMD_GET_VERSION
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool vfd_frame_sync(struct const_iobuf *src) {
|
||||||
|
return src->bytes[src->pos] == VFD_SYNC_BYTE || src->bytes[src->pos] == VFD_SYNC_BYTE2;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT vfd_frame_encode(
|
||||||
|
struct iobuf *dest,
|
||||||
|
const void *ptr,
|
||||||
|
size_t nbytes) {
|
||||||
|
const uint8_t *src;
|
||||||
|
uint8_t byte;
|
||||||
|
size_t i;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(dest != NULL);
|
||||||
|
assert(dest->bytes != NULL || dest->nbytes == 0);
|
||||||
|
assert(dest->pos <= dest->nbytes);
|
||||||
|
assert(ptr != NULL);
|
||||||
|
|
||||||
|
src = ptr;
|
||||||
|
|
||||||
|
if (dest->pos >= dest->nbytes) {
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SUPER_VERBOSE
|
||||||
|
dprintf("VFD: RX Buffer:\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 1; i < nbytes; i++) {
|
||||||
|
byte = src[i];
|
||||||
|
#if SUPER_VERBOSE
|
||||||
|
dprintf("%02x ", byte);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
hr = vfd_frame_encode_byte(dest, byte);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if SUPER_VERBOSE
|
||||||
|
dprintf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT vfd_frame_encode_byte(struct iobuf *dest, uint8_t byte) {
|
||||||
|
if (dest->pos + 1 > dest->nbytes) {
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->bytes[dest->pos++] = byte;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "hook/iobuf.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VFD_SYNC_BYTE = 0x1B,
|
||||||
|
VFD_SYNC_BYTE2 = 0x1A,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool vfd_frame_sync(struct const_iobuf *src);
|
||||||
|
|
||||||
|
HRESULT vfd_frame_encode(
|
||||||
|
struct iobuf *dest,
|
||||||
|
const void *ptr,
|
||||||
|
size_t nbytes);
|
353
board/vfd.c
353
board/vfd.c
|
@ -2,17 +2,17 @@
|
||||||
directly by amdaemon, and it has something to do with displaying the status
|
directly by amdaemon, and it has something to do with displaying the status
|
||||||
of electronic payments.
|
of electronic payments.
|
||||||
|
|
||||||
Part number in schematics is "VFD GP1232A02A FUTABA".
|
Part number in schematics is "VFD GP1232A02A FUTABA". */
|
||||||
|
|
||||||
Little else about this board is known. Black-holing the RS232 comms that it
|
|
||||||
receives seems to be sufficient for the time being. */
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "board/config.h"
|
||||||
#include "board/vfd.h"
|
#include "board/vfd.h"
|
||||||
|
#include "board/vfd-cmd.h"
|
||||||
|
|
||||||
#include "hook/iohook.h"
|
#include "hook/iohook.h"
|
||||||
|
|
||||||
|
@ -21,31 +21,101 @@
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/dump.h"
|
#include "util/dump.h"
|
||||||
|
|
||||||
|
#define SUPER_VERBOSE 0
|
||||||
|
|
||||||
static HRESULT vfd_handle_irp(struct irp *irp);
|
static HRESULT vfd_handle_irp(struct irp *irp);
|
||||||
|
|
||||||
static struct uart vfd_uart;
|
static struct uart vfd_uart;
|
||||||
static uint8_t vfd_written[512];
|
static uint8_t vfd_written[4096];
|
||||||
static uint8_t vfd_readable[512];
|
static uint8_t vfd_readable[4096];
|
||||||
|
|
||||||
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
|
static int encoding = VFD_ENC_SHIFT_JIS;
|
||||||
|
|
||||||
|
HRESULT vfd_handle_get_version(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_reset(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_clear_screen(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_set_brightness(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_set_screen_on(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_set_h_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_draw_image(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_set_cursor(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_set_encoding(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_set_text_wnd(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_set_text_speed(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_write_text(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_enable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_disable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_rotate(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_create_char(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
HRESULT vfd_handle_create_char2(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
|
||||||
|
|
||||||
|
static bool utf_enabled;
|
||||||
|
|
||||||
|
HRESULT vfd_hook_init(struct vfd_config *cfg, unsigned int default_port_no)
|
||||||
{
|
{
|
||||||
assert(cfg != NULL);
|
if (!cfg->enable){
|
||||||
|
|
||||||
if (!cfg->enable) {
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utf_enabled = cfg->utf_conversion;
|
||||||
|
|
||||||
|
unsigned int port_no = cfg->port_no;
|
||||||
|
if (port_no == 0){
|
||||||
|
port_no = default_port_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("VFD: enabling (port=%d)\n", port_no);
|
||||||
uart_init(&vfd_uart, port_no);
|
uart_init(&vfd_uart, port_no);
|
||||||
vfd_uart.written.bytes = vfd_written;
|
vfd_uart.written.bytes = vfd_written;
|
||||||
vfd_uart.written.nbytes = sizeof(vfd_written);
|
vfd_uart.written.nbytes = sizeof(vfd_written);
|
||||||
vfd_uart.readable.bytes = vfd_readable;
|
vfd_uart.readable.bytes = vfd_readable;
|
||||||
vfd_uart.readable.nbytes = sizeof(vfd_readable);
|
vfd_uart.readable.nbytes = sizeof(vfd_readable);
|
||||||
|
|
||||||
dprintf("VFD: hook enabled.\n");
|
|
||||||
|
|
||||||
return iohook_push_handler(vfd_handle_irp);
|
return iohook_push_handler(vfd_handle_irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* get_encoding_name(int b){
|
||||||
|
switch (b){
|
||||||
|
case 0: return "gb2312";
|
||||||
|
case 1: return "big5";
|
||||||
|
case 2: return "shift-jis";
|
||||||
|
case 3: return "ks_c_5601-1987";
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_vfd_text(const char* str, int len){
|
||||||
|
|
||||||
|
if (utf_enabled){
|
||||||
|
|
||||||
|
wchar_t encoded[1024];
|
||||||
|
memset(encoded, 0, 1024 * sizeof(wchar_t));
|
||||||
|
|
||||||
|
int codepage = 0;
|
||||||
|
if (encoding == VFD_ENC_GB2312){
|
||||||
|
codepage = 936;
|
||||||
|
} else if (encoding == VFD_ENC_BIG5){
|
||||||
|
codepage = 950;
|
||||||
|
} else if (encoding == VFD_ENC_SHIFT_JIS){
|
||||||
|
codepage = 932;
|
||||||
|
} else if (encoding == VFD_ENC_KSC5601) {
|
||||||
|
codepage = 949;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MultiByteToWideChar(codepage, MB_USEGLYPHCHARS, str, len, encoded, 1024)){
|
||||||
|
dprintf("VFD: Text conversion failed: %ld", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("VFD: Text: %ls\n", encoded);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
dprintf("VFD: Text: %s\n", str);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT vfd_handle_irp(struct irp *irp)
|
static HRESULT vfd_handle_irp(struct irp *irp)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -56,15 +126,274 @@ static HRESULT vfd_handle_irp(struct irp *irp)
|
||||||
return iohook_invoke_next(irp);
|
return iohook_invoke_next(irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (irp->op == IRP_OP_OPEN){
|
||||||
|
dprintf("VFD: Open\n");
|
||||||
|
} else if (irp->op == IRP_OP_CLOSE){
|
||||||
|
dprintf("VFD: Close\n");
|
||||||
|
}
|
||||||
|
|
||||||
hr = uart_handle_irp(&vfd_uart, irp);
|
hr = uart_handle_irp(&vfd_uart, irp);
|
||||||
|
|
||||||
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SUPER_VERBOSE
|
||||||
dprintf("VFD TX:\n");
|
dprintf("VFD TX:\n");
|
||||||
dump_iobuf(&vfd_uart.written);
|
dump_iobuf(&vfd_uart.written);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct const_iobuf reader;
|
||||||
|
iobuf_flip(&reader, &vfd_uart.written);
|
||||||
|
|
||||||
|
struct iobuf* writer = &vfd_uart.readable;
|
||||||
|
for (; reader.pos < reader.nbytes ; ){
|
||||||
|
|
||||||
|
if (vfd_frame_sync(&reader)) {
|
||||||
|
|
||||||
|
reader.pos++; // get the sync byte out of the way
|
||||||
|
|
||||||
|
uint8_t cmd;
|
||||||
|
iobuf_read_8(&reader, &cmd);
|
||||||
|
|
||||||
|
if (cmd == VFD_CMD_GET_VERSION) {
|
||||||
|
hr = vfd_handle_get_version(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_RESET) {
|
||||||
|
hr = vfd_handle_reset(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_CLEAR_SCREEN) {
|
||||||
|
hr = vfd_handle_clear_screen(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_SET_BRIGHTNESS) {
|
||||||
|
hr = vfd_handle_set_brightness(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_SET_SCREEN_ON) {
|
||||||
|
hr = vfd_handle_set_screen_on(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_SET_H_SCROLL) {
|
||||||
|
hr = vfd_handle_set_h_scroll(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_DRAW_IMAGE) {
|
||||||
|
hr = vfd_handle_draw_image(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_SET_CURSOR) {
|
||||||
|
hr = vfd_handle_set_cursor(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_SET_ENCODING) {
|
||||||
|
hr = vfd_handle_set_encoding(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_SET_TEXT_WND) {
|
||||||
|
hr = vfd_handle_set_text_wnd(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_SET_TEXT_SPEED) {
|
||||||
|
hr = vfd_handle_set_text_speed(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_WRITE_TEXT) {
|
||||||
|
hr = vfd_handle_write_text(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_ENABLE_SCROLL) {
|
||||||
|
hr = vfd_handle_enable_scroll(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_DISABLE_SCROLL) {
|
||||||
|
hr = vfd_handle_disable_scroll(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_ROTATE) {
|
||||||
|
hr = vfd_handle_rotate(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_CREATE_CHAR) {
|
||||||
|
hr = vfd_handle_create_char(&reader, writer, &vfd_uart);
|
||||||
|
} else if (cmd == VFD_CMD_CREATE_CHAR2) {
|
||||||
|
hr = vfd_handle_create_char2(&reader, writer, &vfd_uart);
|
||||||
|
} else {
|
||||||
|
dprintf("VFD: Unknown command 0x%x\n", cmd);
|
||||||
|
dump_const_iobuf(&reader);
|
||||||
|
hr = S_FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// if no sync byte is sent, we are just getting plain text...
|
||||||
|
|
||||||
|
if (reader.pos < reader.nbytes){
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
// read chars until we hit a new sync byte or the data ends
|
||||||
|
while (reader.pos + len + 1 < reader.nbytes && reader.bytes[reader.pos + len] != VFD_SYNC_BYTE && reader.bytes[reader.pos + len] != VFD_SYNC_BYTE2){
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* str = malloc(len);
|
||||||
|
memset(str, 0, len);
|
||||||
|
iobuf_read(&reader, str, len);
|
||||||
|
print_vfd_text(str, len);
|
||||||
|
free(str);
|
||||||
|
|
||||||
|
reader.pos += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr)){
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
vfd_uart.written.pos = 0;
|
vfd_uart.written.pos = 0;
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT vfd_handle_get_version(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
dprintf("VFD: Get Version\n");
|
||||||
|
|
||||||
|
struct vfd_resp_board_info resp;
|
||||||
|
|
||||||
|
memset(&resp, 0, sizeof(resp));
|
||||||
|
resp.unk1 = 2;
|
||||||
|
strcpy(resp.version, "01.20");
|
||||||
|
resp.unk2 = 1;
|
||||||
|
|
||||||
|
return vfd_frame_encode(writer, &resp, sizeof(resp));
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_reset(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
dprintf("VFD: Reset\n");
|
||||||
|
|
||||||
|
encoding = VFD_ENC_SHIFT_JIS;
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_clear_screen(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
dprintf("VFD: Clear Screen\n");
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_set_brightness(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t b;
|
||||||
|
iobuf_read_8(reader, &b);
|
||||||
|
|
||||||
|
if (b > 4){
|
||||||
|
dprintf("VFD: Brightness, invalid argument\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("VFD: Brightness, %d\n", b);
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_set_screen_on(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t b;
|
||||||
|
iobuf_read_8(reader, &b);
|
||||||
|
|
||||||
|
if (b > 1){
|
||||||
|
dprintf("VFD: Screen Power, invalid argument\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("VFD: Screen Power, %d\n", b);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_set_h_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t x;
|
||||||
|
iobuf_read_8(reader, &x);
|
||||||
|
|
||||||
|
dprintf("VFD: Horizontal Scroll, X=%d\n", x);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_draw_image(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
int w, h;
|
||||||
|
uint16_t x0, x1;
|
||||||
|
uint8_t y0, y1;
|
||||||
|
uint8_t image[2048];
|
||||||
|
|
||||||
|
iobuf_read_be16(reader, &x0);
|
||||||
|
iobuf_read_8(reader, &y0);
|
||||||
|
iobuf_read_be16(reader, &x1);
|
||||||
|
iobuf_read_8(reader, &y1);
|
||||||
|
w = x1 - x0;
|
||||||
|
h = y1 - y0;
|
||||||
|
iobuf_read(reader, image, w*h);
|
||||||
|
|
||||||
|
dprintf("VFD: Draw image, %dx%d\n", w, h);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT vfd_handle_set_cursor(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint16_t x;
|
||||||
|
uint8_t y;
|
||||||
|
|
||||||
|
iobuf_read_be16(reader, &x);
|
||||||
|
iobuf_read_8(reader, &y);
|
||||||
|
|
||||||
|
dprintf("VFD: Set Cursor, x=%d,y=%d\n", x, y);
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT vfd_handle_set_encoding(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t b;
|
||||||
|
iobuf_read_8(reader, &b);
|
||||||
|
|
||||||
|
dprintf("VFD: Set Encoding, %d (%s)\n", b, get_encoding_name(b));
|
||||||
|
|
||||||
|
if (b < 0 || b > VFD_ENC_MAX){
|
||||||
|
dprintf("Invalid encoding specified\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoding = b;
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_set_text_wnd(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint16_t x0, x1;
|
||||||
|
uint8_t y0, y1;
|
||||||
|
|
||||||
|
iobuf_read_be16(reader, &x0);
|
||||||
|
iobuf_read_8(reader, &y0);
|
||||||
|
iobuf_read_be16(reader, &x1);
|
||||||
|
iobuf_read_8(reader, &y1);
|
||||||
|
|
||||||
|
dprintf("VFD: Set Text Window, p0:%d,%d, p1:%d,%d\n", x0, y0, x1, y1);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_set_text_speed(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t b;
|
||||||
|
iobuf_read_8(reader, &b);
|
||||||
|
|
||||||
|
dprintf("VFD: Set Text Speed, %d\n", b);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_write_text(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t len;
|
||||||
|
iobuf_read_8(reader, &len);
|
||||||
|
|
||||||
|
char* str = malloc(len);
|
||||||
|
iobuf_read(reader, str, len);
|
||||||
|
|
||||||
|
print_vfd_text(str, len);
|
||||||
|
free(str);
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_enable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
dprintf("VFD: Enable Scrolling\n");
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_disable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
dprintf("VFD: Disable Scrolling\n");
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_rotate(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t b;
|
||||||
|
iobuf_read_8(reader, &b);
|
||||||
|
|
||||||
|
dprintf("VFD: Rotate, %d\n", b);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_create_char(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t b;
|
||||||
|
iobuf_read_8(reader, &b);
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
iobuf_read(reader, buf, 32);
|
||||||
|
|
||||||
|
dprintf("VFD: Create character, %d\n", b);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
HRESULT vfd_handle_create_char2(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
|
||||||
|
uint8_t b, b2;
|
||||||
|
iobuf_read_8(reader, &b);
|
||||||
|
iobuf_read_8(reader, &b2);
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
|
iobuf_read(reader, buf, 16);
|
||||||
|
|
||||||
|
dprintf("VFD: Create character, %d, %d\n", b, b2);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
|
|
||||||
struct vfd_config {
|
struct vfd_config {
|
||||||
bool enable;
|
bool enable;
|
||||||
|
unsigned int port_no;
|
||||||
|
bool utf_conversion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no);
|
HRESULT vfd_hook_init(struct vfd_config *cfg, unsigned int default_port_no);
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ static HRESULT controlbd_frame_decode(struct controlbd_req_any *req, struct iobu
|
||||||
uint8_t checksum_pos = src->pos - 1;
|
uint8_t checksum_pos = src->pos - 1;
|
||||||
uint8_t calculated_checksum = 0;
|
uint8_t calculated_checksum = 0;
|
||||||
uint8_t checksum = 0;
|
uint8_t checksum = 0;
|
||||||
|
|
||||||
if (src->pos < 6) {
|
if (src->pos < 6) {
|
||||||
dprintf("Control Board: Decode Error, request too short (pos is 0x%08X)\n", (int)src->pos);
|
dprintf("Control Board: Decode Error, request too short (pos is 0x%08X)\n", (int)src->pos);
|
||||||
return SEC_E_BUFFER_TOO_SMALL;
|
return SEC_E_BUFFER_TOO_SMALL;
|
||||||
|
@ -137,7 +137,7 @@ static HRESULT controlbd_handle_irp_locked(struct irp *irp)
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (controlbd_uart.written.bytes[0] == 0xE0) {
|
if (controlbd_uart.written.bytes[0] == 0xE0) {
|
||||||
#if 0
|
#if defined(LOG_CAROL_CONTROL_BD)
|
||||||
dprintf("Control Board: TX Buffer:\n");
|
dprintf("Control Board: TX Buffer:\n");
|
||||||
dump_iobuf(&controlbd_uart.written);
|
dump_iobuf(&controlbd_uart.written);
|
||||||
#endif
|
#endif
|
||||||
|
@ -147,12 +147,12 @@ static HRESULT controlbd_handle_irp_locked(struct irp *irp)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = controlbd_req_dispatch(&req);
|
hr = controlbd_req_dispatch(&req);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("Control Board: Dispatch Error: 0X%X\n", (int) hr);
|
dprintf("Control Board: Dispatch Error: 0X%X\n", (int) hr);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
#if 0
|
#if defined(LOG_CAROL_CONTROL_BD)
|
||||||
dprintf("Control Board: RX Buffer:\n");
|
dprintf("Control Board: RX Buffer:\n");
|
||||||
dump_iobuf(&controlbd_uart.readable);
|
dump_iobuf(&controlbd_uart.readable);
|
||||||
#endif
|
#endif
|
||||||
|
@ -206,7 +206,7 @@ static HRESULT controlbd_req_dispatch(const struct controlbd_req_any *req)
|
||||||
case CONTROLBD_CMD_FIRM_SUM:
|
case CONTROLBD_CMD_FIRM_SUM:
|
||||||
return controlbd_req_firmware_checksum();
|
return controlbd_req_firmware_checksum();
|
||||||
|
|
||||||
case CONTROLBD_CMD_TIMEOUT:
|
case CONTROLBD_CMD_TIMEOUT:
|
||||||
dprintf("Control Board: Acknowledge Timeout\n");
|
dprintf("Control Board: Acknowledge Timeout\n");
|
||||||
return controlbd_req_ack_any(req->hdr.cmd);
|
return controlbd_req_ack_any(req->hdr.cmd);
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ static HRESULT controlbd_req_get_board_info(void)
|
||||||
resp.rev = 0x90;
|
resp.rev = 0x90;
|
||||||
resp.bfr_size = 0x0001;
|
resp.bfr_size = 0x0001;
|
||||||
resp.ack = 1;
|
resp.ack = 1;
|
||||||
|
|
||||||
strcpy_s(resp.bd_no, sizeof(resp.bd_no), "15312 ");
|
strcpy_s(resp.bd_no, sizeof(resp.bd_no), "15312 ");
|
||||||
strcpy_s(resp.chip_no, sizeof(resp.chip_no), "6699 ");
|
strcpy_s(resp.chip_no, sizeof(resp.chip_no), "6699 ");
|
||||||
resp.chip_no[5] = 0xFF;
|
resp.chip_no[5] = 0xFF;
|
||||||
|
@ -317,7 +317,7 @@ static HRESULT controlbd_req_polling(const struct controlbd_req_any *req)
|
||||||
resp.unk7 = 3;
|
resp.unk7 = 3;
|
||||||
resp.unk8 = 1;
|
resp.unk8 = 1;
|
||||||
resp.unk9 = 1;
|
resp.unk9 = 1;
|
||||||
|
|
||||||
resp.btns_pressed = 0; // bit 1 is pen button, bit 2 is dodge
|
resp.btns_pressed = 0; // bit 1 is pen button, bit 2 is dodge
|
||||||
resp.coord_x = 0x0;
|
resp.coord_x = 0x0;
|
||||||
resp.coord_y = 0x0;
|
resp.coord_y = 0x0;
|
||||||
|
|
|
@ -1,3 +1,31 @@
|
||||||
|
/*
|
||||||
|
"Wonderland Wars" (carol*) hook
|
||||||
|
|
||||||
|
Devices:
|
||||||
|
|
||||||
|
JVS: 837-14572 "Type 3" I/O Board
|
||||||
|
|
||||||
|
[Satellite]
|
||||||
|
|
||||||
|
USB: "WinTouch" Controller Board
|
||||||
|
^ (DIPSW2 ON, Version 5.xx.xx or above)
|
||||||
|
COM1: 3M Touch Systems 78-0011-2353-4 Touch Controller Board
|
||||||
|
^ (DIPSW2 OFF)
|
||||||
|
COM10: TN32MSEC003S "Gen 1" Aime Reader
|
||||||
|
OR
|
||||||
|
837-15286 "Gen 2" Aime Reader
|
||||||
|
^ (Version 1.6x.xx or above)
|
||||||
|
COM11: 837-15070-02 LED Controller Board
|
||||||
|
COM12: 837-15312 Pen Controller I/O Board
|
||||||
|
|
||||||
|
[Terminal]
|
||||||
|
|
||||||
|
COM10: 837-15286 "Gen 2" Aime Reader
|
||||||
|
|
||||||
|
*: SEGA's abbreviation for Lewis Carroll, author of Alice's Adventures in
|
||||||
|
Wonderland.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -25,6 +53,7 @@
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static HMODULE carol_hook_mod;
|
static HMODULE carol_hook_mod;
|
||||||
static process_entry_t carol_startup;
|
static process_entry_t carol_startup;
|
||||||
|
@ -45,8 +74,6 @@ static DWORD CALLBACK carol_pre_startup(void)
|
||||||
HMODULE dbghelp;
|
HMODULE dbghelp;
|
||||||
|
|
||||||
dprintf("--- Begin carol_pre_startup ---\n");
|
dprintf("--- Begin carol_pre_startup ---\n");
|
||||||
if ( !SetProcessDPIAware() )
|
|
||||||
dprintf("Failed to set process DPI awareness level!\n");
|
|
||||||
|
|
||||||
/* Pin the D3D shader compiler. This makes startup much faster. */
|
/* Pin the D3D shader compiler. This makes startup much faster. */
|
||||||
|
|
||||||
|
@ -72,7 +99,7 @@ static DWORD CALLBACK carol_pre_startup(void)
|
||||||
|
|
||||||
/* Config load */
|
/* Config load */
|
||||||
|
|
||||||
carol_hook_config_load(&carol_hook_cfg, L".\\segatools.ini");
|
carol_hook_config_load(&carol_hook_cfg, get_config_path());
|
||||||
|
|
||||||
/* Hook Win32 APIs */
|
/* Hook Win32 APIs */
|
||||||
|
|
||||||
|
@ -136,7 +163,7 @@ static DWORD CALLBACK carol_pre_startup(void)
|
||||||
}
|
}
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
spike_hook_init(L".\\segatools.ini");
|
spike_hook_init(get_config_path());
|
||||||
|
|
||||||
dprintf("--- End carol_pre_startup ---\n");
|
dprintf("--- End carol_pre_startup ---\n");
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ static HRESULT ledbd_handle_irp_locked(struct irp *irp)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if 0
|
#if defined(LOG_CAROL_LED_BD)
|
||||||
dprintf("LED Board: TX Buffer:\n");
|
dprintf("LED Board: TX Buffer:\n");
|
||||||
dump_iobuf(&ledbd_uart.written);
|
dump_iobuf(&ledbd_uart.written);
|
||||||
#endif
|
#endif
|
||||||
|
@ -165,4 +165,4 @@ static HRESULT ledbd_req_unkF0(uint8_t cmd)
|
||||||
iobuf_write(&ledbd_uart.readable, resp, 16);
|
iobuf_write(&ledbd_uart.readable, resp, 16);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ shared_library(
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
vs_module_defs : 'carolhook.def',
|
vs_module_defs : 'carolhook.def',
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
capnhook.get_variable('hooklib_dep'),
|
capnhook.get_variable('hooklib_dep'),
|
||||||
|
|
|
@ -54,7 +54,7 @@ HRESULT touch_hook_init(const struct touch_config *cfg)
|
||||||
if (!cfg->enable) {
|
if (!cfg->enable) {
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeCriticalSection(&touch_lock);
|
InitializeCriticalSection(&touch_lock);
|
||||||
|
|
||||||
uart_init(&touch_uart, 1);
|
uart_init(&touch_uart, 1);
|
||||||
|
@ -112,7 +112,7 @@ static HRESULT touch_handle_irp_locked(struct irp *irp)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if 0
|
#if defined(LOG_CAROL_TOUCH)
|
||||||
dprintf("Touchscreen: TX Buffer:\n");
|
dprintf("Touchscreen: TX Buffer:\n");
|
||||||
dump_iobuf(&touch_uart.written);
|
dump_iobuf(&touch_uart.written);
|
||||||
#endif
|
#endif
|
||||||
|
@ -188,7 +188,7 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
|
||||||
resp.touches[0].touch_id = 1;
|
resp.touches[0].touch_id = 1;
|
||||||
tmp_x = mouse_x & 0x7FFF;
|
tmp_x = mouse_x & 0x7FFF;
|
||||||
tmp_y = mouse_y & 0x7FFF;
|
tmp_y = mouse_y & 0x7FFF;
|
||||||
|
|
||||||
resp.touches[0].x1 = tmp_x & 0x7F;
|
resp.touches[0].x1 = tmp_x & 0x7F;
|
||||||
resp.touches[0].x2 = (tmp_x >> 7) & 0x7F;
|
resp.touches[0].x2 = (tmp_x >> 7) & 0x7F;
|
||||||
resp.touches[0].y1 = tmp_y & 0x7F;
|
resp.touches[0].y1 = tmp_y & 0x7F;
|
||||||
|
@ -196,12 +196,12 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
|
||||||
|
|
||||||
flg = resp.touches[0].x1 != last_x1 || resp.touches[0].x2 != last_x2 || resp.touches[0].y1 != last_y1 || resp.touches[0].y2 != last_y2;
|
flg = resp.touches[0].x1 != last_x1 || resp.touches[0].x2 != last_x2 || resp.touches[0].y1 != last_y1 || resp.touches[0].y2 != last_y2;
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
if (flg)
|
if (flg)
|
||||||
dprintf("Touch: Mouse down! x %02X %02X y: %02X %02X\n", resp.touches[0].x1, resp.touches[0].x2, resp.touches[0].y1, resp.touches[0].y2);
|
dprintf("Touch: Mouse down! x %02X %02X y: %02X %02X\n", resp.touches[0].x1, resp.touches[0].x2, resp.touches[0].y1, resp.touches[0].y2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
last_x1 = resp.touches[0].x1;
|
last_x1 = resp.touches[0].x1;
|
||||||
last_x2 = resp.touches[0].x2;
|
last_x2 = resp.touches[0].x2;
|
||||||
last_y1 = resp.touches[0].y1;
|
last_y1 = resp.touches[0].y1;
|
||||||
|
@ -220,7 +220,7 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
|
||||||
iobuf_write(&touch_uart.readable, &resp, sizeof(resp));
|
iobuf_write(&touch_uart.readable, &resp, sizeof(resp));
|
||||||
LeaveCriticalSection(&touch_lock);
|
LeaveCriticalSection(&touch_lock);
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_CAROL_TOUCH)
|
||||||
dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos);
|
dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos);
|
||||||
dump_iobuf(&touch_uart.readable);
|
dump_iobuf(&touch_uart.readable);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "carolio/carolio.h"
|
#include "carolio/carolio.h"
|
||||||
#include "carolio/config.h"
|
#include "carolio/config.h"
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx);
|
static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx);
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ uint16_t carol_io_get_api_version(void)
|
||||||
|
|
||||||
HRESULT carol_io_jvs_init(void)
|
HRESULT carol_io_jvs_init(void)
|
||||||
{
|
{
|
||||||
carol_io_config_load(&carol_io_cfg, L".\\segatools.ini");
|
carol_io_config_load(&carol_io_cfg, get_config_path());
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -178,4 +179,4 @@ static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ carolio_lib = static_library(
|
||||||
name_prefix : '',
|
name_prefix : '',
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
sources : [
|
sources : [
|
||||||
'carolio.c',
|
'carolio.c',
|
||||||
'carolio.h',
|
'carolio.h',
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "amex/amex.h"
|
#include "amex/amex.h"
|
||||||
#include "amex/config.h"
|
#include "amex/config.h"
|
||||||
|
@ -55,7 +56,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
|
||||||
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
|
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
|
||||||
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
|
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
|
||||||
cfg->port_no = 0;
|
cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename);
|
||||||
|
cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename);
|
||||||
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
|
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
|
||||||
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
|
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
|
||||||
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);
|
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
/*
|
||||||
|
"CHUNITHM" (chuni) hook
|
||||||
|
|
||||||
|
Devices
|
||||||
|
|
||||||
|
JVS: 837-14572 "Type 3" I/O Board
|
||||||
|
COM1: 837-15330 Ground Slider
|
||||||
|
COM10: 837-15093-06 LED Controller Board
|
||||||
|
COM11: 837-15093-06 LED Controller Board
|
||||||
|
COM12: TN32MSEC003S "Gen 1" Aime Reader
|
||||||
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -24,6 +36,7 @@
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static HMODULE chuni_hook_mod;
|
static HMODULE chuni_hook_mod;
|
||||||
static process_entry_t chuni_startup;
|
static process_entry_t chuni_startup;
|
||||||
|
@ -59,7 +72,7 @@ static DWORD CALLBACK chuni_pre_startup(void)
|
||||||
|
|
||||||
/* Config load */
|
/* Config load */
|
||||||
|
|
||||||
chuni_hook_config_load(&chuni_hook_cfg, L".\\segatools.ini");
|
chuni_hook_config_load(&chuni_hook_cfg, get_config_path());
|
||||||
|
|
||||||
/* Hook Win32 APIs */
|
/* Hook Win32 APIs */
|
||||||
|
|
||||||
|
@ -101,8 +114,9 @@ static DWORD CALLBACK chuni_pre_startup(void)
|
||||||
{
|
{
|
||||||
dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n");
|
dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n");
|
||||||
} else {
|
} else {
|
||||||
|
unsigned int led_port_no[2] = {10, 11};
|
||||||
hr = led15093_hook_init(&chuni_hook_cfg.led15093,
|
hr = led15093_hook_init(&chuni_hook_cfg.led15093,
|
||||||
chuni_dll.led_init, chuni_dll.led_set_leds, 10, 2, 2, 1);
|
chuni_dll.led_init, chuni_dll.led_set_leds, led_port_no);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -117,7 +131,7 @@ static DWORD CALLBACK chuni_pre_startup(void)
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
spike_hook_init(L".\\segatools.ini");
|
spike_hook_init(get_config_path());
|
||||||
|
|
||||||
dprintf("--- End chuni_pre_startup ---\n");
|
dprintf("--- End chuni_pre_startup ---\n");
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ shared_library(
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
vs_module_defs : 'chunihook.def',
|
vs_module_defs : 'chunihook.def',
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
capnhook.get_variable('hooklib_dep'),
|
capnhook.get_variable('hooklib_dep'),
|
||||||
|
|
|
@ -98,7 +98,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if 0
|
#if defined(LOG_CHUNI_SLIDER)
|
||||||
dprintf("TX Buffer:\n");
|
dprintf("TX Buffer:\n");
|
||||||
dump_iobuf(&slider_uart.written);
|
dump_iobuf(&slider_uart.written);
|
||||||
#endif
|
#endif
|
||||||
|
@ -117,7 +117,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_CHUNI_SLIDER)
|
||||||
dprintf("Deframe Buffer:\n");
|
dprintf("Deframe Buffer:\n");
|
||||||
dump_iobuf(&req_iobuf);
|
dump_iobuf(&req_iobuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "chuniio/chuniio.h"
|
#include "chuniio/chuniio.h"
|
||||||
#include "chuniio/config.h"
|
#include "chuniio/config.h"
|
||||||
#include "chuniio/ledoutput.h"
|
#include "chuniio/ledoutput.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx);
|
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx);
|
||||||
|
|
||||||
|
@ -27,7 +29,7 @@ uint16_t chuni_io_get_api_version(void)
|
||||||
|
|
||||||
HRESULT chuni_io_jvs_init(void)
|
HRESULT chuni_io_jvs_init(void)
|
||||||
{
|
{
|
||||||
chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini");
|
chuni_io_config_load(&chuni_io_cfg, get_config_path());
|
||||||
|
|
||||||
led_init_mutex = CreateMutex(
|
led_init_mutex = CreateMutex(
|
||||||
NULL, // default security attributes
|
NULL, // default security attributes
|
||||||
|
@ -92,7 +94,7 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams)
|
||||||
} else {
|
} else {
|
||||||
// Use actual AIR
|
// Use actual AIR
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
if(GetAsyncKeyState(chuni_io_cfg.vk_ir[i]) & 0x8000) {
|
if (GetAsyncKeyState(chuni_io_cfg.vk_ir[i]) & 0x8000) {
|
||||||
*beams |= (1 << i);
|
*beams |= (1 << i);
|
||||||
} else {
|
} else {
|
||||||
*beams &= ~(1 << i);
|
*beams &= ~(1 << i);
|
||||||
|
@ -172,6 +174,20 @@ HRESULT chuni_io_led_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb)
|
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
if (board == 0) {
|
||||||
|
dprintf("CHUNI LED: Left Air 1: red: %d, green: %d, blue: %d\n", rgb[0x96], rgb[0x97], rgb[0x98]);
|
||||||
|
dprintf("CHUNI LED: Left Air 2: red: %d, green: %d, blue: %d\n", rgb[0x99], rgb[0x9A], rgb[0x9B]);
|
||||||
|
dprintf("CHUNI LED: Left Air 3: red: %d, green: %d, blue: %d\n", rgb[0x9C], rgb[0x9D], rgb[0x9E]);
|
||||||
|
}
|
||||||
|
else if (board == 1)
|
||||||
|
{
|
||||||
|
dprintf("CHUNI LED: Right Air 1: red: %d, green: %d, blue: %d\n", rgb[0xB4], rgb[0xB5], rgb[0xB6]);
|
||||||
|
dprintf("CHUNI LED: Right Air 2: red: %d, green: %d, blue: %d\n", rgb[0xB7], rgb[0xB8], rgb[0xB9]);
|
||||||
|
dprintf("CHUNI LED: Right Air 3: red: %d, green: %d, blue: %d\n", rgb[0xBA], rgb[0xBB], rgb[0xBC]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
led_output_update(board, rgb);
|
led_output_update(board, rgb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,9 +139,10 @@ void chuni_io_slider_start(chuni_io_slider_callback_t callback);
|
||||||
void chuni_io_slider_stop(void);
|
void chuni_io_slider_stop(void);
|
||||||
|
|
||||||
/* Update the RGB lighting on the slider. A pointer to an array of 32 * 3 = 96
|
/* Update the RGB lighting on the slider. A pointer to an array of 32 * 3 = 96
|
||||||
bytes is supplied. The illuminated areas on the touch slider are some
|
bytes is supplied, organized in BRG format.
|
||||||
combination of rectangular regions and dividing lines between these regions
|
The first set of bytes is the right-most slider key, and from there the bytes
|
||||||
but the exact mapping of this lighting control buffer is still TBD.
|
alternate between the dividers and the keys until the left-most key.
|
||||||
|
There are 31 illuminated sections in total.
|
||||||
|
|
||||||
Minimum API version: 0x0100 */
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
@ -163,9 +164,17 @@ HRESULT chuni_io_led_init(void);
|
||||||
Chunithm uses two chains/boards with WS2811 protocol (each logical led corresponds to 3 physical leds).
|
Chunithm uses two chains/boards with WS2811 protocol (each logical led corresponds to 3 physical leds).
|
||||||
board 0 is on the left side and board 1 on the right side of the cab
|
board 0 is on the left side and board 1 on the right side of the cab
|
||||||
|
|
||||||
left side has 5*10 rgb values for the billboard, followed by 3 rgb values for the air tower
|
Board 0 has 53 LEDs:
|
||||||
right side has 6*10 rgb values for the billboard, followed by 3 rgb values for the air tower
|
[0]-[49]: snakes through left half of billboard (first column starts at top)
|
||||||
|
[50]-[52]: left side partition LEDs
|
||||||
|
|
||||||
|
Board 1 has 63 LEDs:
|
||||||
|
[0]-[59]: right half of billboard (first column starts at bottom)
|
||||||
|
[60]-[62]: right side partition LEDs
|
||||||
|
|
||||||
|
Board 2 is the slider and has 31 LEDs:
|
||||||
|
[0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
|
||||||
|
|
||||||
Each rgb value is comprised of 3 bytes in R,G,B order
|
Each rgb value is comprised of 3 bytes in R,G,B order
|
||||||
|
|
||||||
NOTE: billboard strips have alternating direction (bottom to top, top to bottom, ...)
|
NOTE: billboard strips have alternating direction (bottom to top, top to bottom, ...)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "chuniio/config.h"
|
#include "chuniio/config.h"
|
||||||
|
@ -57,11 +58,13 @@ void chuni_io_config_load(
|
||||||
filename);
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg->led_output_pipe = GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename);
|
cfg->cab_led_output_pipe = GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename);
|
||||||
cfg->led_output_serial = GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename);
|
cfg->cab_led_output_serial = GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename);
|
||||||
|
|
||||||
cfg->slider_led_output_pipe = GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename);
|
cfg->controller_led_output_pipe = GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename);
|
||||||
cfg->slider_led_output_serial = GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename);
|
cfg->controller_led_output_serial = GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename);
|
||||||
|
|
||||||
|
cfg->controller_led_output_openithm = GetPrivateProfileIntW(L"led", L"controllerLedOutputOpeNITHM", 0, filename);
|
||||||
|
|
||||||
cfg->led_serial_baud = GetPrivateProfileIntW(L"led", L"serialBaud", 921600, filename);
|
cfg->led_serial_baud = GetPrivateProfileIntW(L"led", L"serialBaud", 921600, filename);
|
||||||
|
|
||||||
|
@ -70,7 +73,7 @@ void chuni_io_config_load(
|
||||||
L"serialPort",
|
L"serialPort",
|
||||||
L"COM5",
|
L"COM5",
|
||||||
port_input,
|
port_input,
|
||||||
6,
|
_countof(port_input),
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
// Sanitize the output path. If it's a serial COM port, it needs to be prefixed
|
// Sanitize the output path. If it's a serial COM port, it needs to be prefixed
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct chuni_io_config {
|
struct chuni_io_config {
|
||||||
uint8_t vk_test;
|
uint8_t vk_test;
|
||||||
|
@ -12,16 +13,17 @@ struct chuni_io_config {
|
||||||
uint8_t vk_cell[32];
|
uint8_t vk_cell[32];
|
||||||
|
|
||||||
// Which ways to output LED information are enabled
|
// Which ways to output LED information are enabled
|
||||||
bool led_output_pipe;
|
bool cab_led_output_pipe;
|
||||||
bool led_output_serial;
|
bool cab_led_output_serial;
|
||||||
|
|
||||||
bool slider_led_output_pipe;
|
bool controller_led_output_pipe;
|
||||||
bool slider_led_output_serial;
|
bool controller_led_output_serial;
|
||||||
|
|
||||||
|
bool controller_led_output_openithm;
|
||||||
|
|
||||||
// The name of a COM port to output LED data on, in serial mode
|
// The name of a COM port to output LED data on, in serial mode
|
||||||
wchar_t led_serial_port[12];
|
wchar_t led_serial_port[12];
|
||||||
int32_t led_serial_baud;
|
int32_t led_serial_baud;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void chuni_io_config_load(
|
void chuni_io_config_load(
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
|
|
||||||
// This struct is used to send data related to the slider and billboard LEDs
|
// This struct is used to send data related to the slider and billboard LEDs
|
||||||
struct _chuni_led_data_buf_t {
|
struct _chuni_led_data_buf_t {
|
||||||
byte framing; // Sync byte
|
uint8_t framing; // Sync byte
|
||||||
uint8_t board; // LED output the data is for (0-1: billboard, 2: slider)
|
uint8_t board; // LED output the data is for (0-1: billboard, 2: slider)
|
||||||
byte data[LED_OUTPUT_DATA_SIZE_MAX]; // Buffer for LEDs
|
uint8_t data[LED_OUTPUT_DATA_SIZE_MAX]; // Buffer for LEDs
|
||||||
byte data_len; // How many bytes to output from the buffer
|
uint8_t data_len; // How many bytes to output from the buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
static byte chuni_led_board_data_lens[LED_BOARDS_TOTAL] = {53*3, 63*3, 31*3};
|
static uint8_t chuni_led_board_data_lens[LED_BOARDS_TOTAL] = {53*3, 63*3, 31*3};
|
|
@ -48,15 +48,15 @@ HRESULT led_output_init(struct chuni_io_config* const cfg)
|
||||||
led_escaped_buf[i].data_len = chuni_led_board_data_lens[i];
|
led_escaped_buf[i].data_len = chuni_led_board_data_lens[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
any_outputs_enabled = config->led_output_pipe || config->slider_led_output_pipe
|
any_outputs_enabled = config->cab_led_output_pipe || config->controller_led_output_pipe
|
||||||
|| config->led_output_serial || config->slider_led_output_serial;
|
|| config->cab_led_output_serial || config->controller_led_output_serial;
|
||||||
|
|
||||||
if (config->led_output_pipe || config->slider_led_output_pipe)
|
if (config->cab_led_output_pipe || config->controller_led_output_pipe)
|
||||||
{
|
{
|
||||||
led_pipe_init(); // don't really care about errors here tbh
|
led_pipe_init(); // don't really care about errors here tbh
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->led_output_serial || config->slider_led_output_serial)
|
if (config->cab_led_output_serial || config->controller_led_output_serial)
|
||||||
{
|
{
|
||||||
led_serial_init(config->led_serial_port, config->led_serial_baud);
|
led_serial_init(config->led_serial_port, config->led_serial_baud);
|
||||||
}
|
}
|
||||||
|
@ -73,14 +73,14 @@ struct _chuni_led_data_buf_t* escape_led_data(struct _chuni_led_data_buf_t* unes
|
||||||
{
|
{
|
||||||
struct _chuni_led_data_buf_t* out_struct = &led_escaped_buf[unescaped->board];
|
struct _chuni_led_data_buf_t* out_struct = &led_escaped_buf[unescaped->board];
|
||||||
|
|
||||||
byte* in_buf = unescaped->data;
|
uint8_t* in_buf = unescaped->data;
|
||||||
byte* out_buf = out_struct->data;
|
uint8_t* out_buf = out_struct->data;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int o = 0;
|
int o = 0;
|
||||||
|
|
||||||
while (i < unescaped->data_len)
|
while (i < unescaped->data_len)
|
||||||
{
|
{
|
||||||
byte b = in_buf[i++];
|
uint8_t b = in_buf[i++];
|
||||||
if (b == LED_PACKET_FRAMING || b == LED_PACKET_ESCAPE)
|
if (b == LED_PACKET_FRAMING || b == LED_PACKET_ESCAPE)
|
||||||
{
|
{
|
||||||
out_buf[o++] = LED_PACKET_ESCAPE;
|
out_buf[o++] = LED_PACKET_ESCAPE;
|
||||||
|
@ -94,7 +94,7 @@ struct _chuni_led_data_buf_t* escape_led_data(struct _chuni_led_data_buf_t* unes
|
||||||
return out_struct;
|
return out_struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
void led_output_update(uint8_t board, const byte* rgb)
|
void led_output_update(uint8_t board, const uint8_t* rgb)
|
||||||
{
|
{
|
||||||
if (board < 0 || board > 2 || !any_outputs_enabled)
|
if (board < 0 || board > 2 || !any_outputs_enabled)
|
||||||
{
|
{
|
||||||
|
@ -106,13 +106,13 @@ void led_output_update(uint8_t board, const byte* rgb)
|
||||||
|
|
||||||
if (board < 2)
|
if (board < 2)
|
||||||
{
|
{
|
||||||
// billboard
|
// billboard (cab)
|
||||||
if (config->led_output_pipe)
|
if (config->cab_led_output_pipe)
|
||||||
{
|
{
|
||||||
led_pipe_update(escaped_data);
|
led_pipe_update(escaped_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->led_output_serial)
|
if (config->cab_led_output_serial)
|
||||||
{
|
{
|
||||||
led_serial_update(escaped_data);
|
led_serial_update(escaped_data);
|
||||||
}
|
}
|
||||||
|
@ -120,14 +120,18 @@ void led_output_update(uint8_t board, const byte* rgb)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// slider
|
// slider
|
||||||
if (config->slider_led_output_pipe)
|
if (config->controller_led_output_pipe)
|
||||||
{
|
{
|
||||||
led_pipe_update(escaped_data);
|
led_pipe_update(escaped_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->slider_led_output_serial)
|
if (config->controller_led_output_serial)
|
||||||
{
|
{
|
||||||
led_serial_update(escaped_data);
|
if (config->controller_led_output_openithm){
|
||||||
|
led_serial_update_openithm(rgb);
|
||||||
|
} else {
|
||||||
|
led_serial_update(escaped_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,4 @@
|
||||||
|
|
||||||
extern HANDLE led_init_mutex;
|
extern HANDLE led_init_mutex;
|
||||||
HRESULT led_output_init(struct chuni_io_config* const cfg);
|
HRESULT led_output_init(struct chuni_io_config* const cfg);
|
||||||
void led_output_update(uint8_t board, const byte* rgb);
|
void led_output_update(uint8_t board, const uint8_t* rgb);
|
||||||
|
|
|
@ -3,7 +3,7 @@ chuniio_lib = static_library(
|
||||||
name_prefix : '',
|
name_prefix : '',
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
sources : [
|
sources : [
|
||||||
'chu2to3.c',
|
'chu2to3.c',
|
||||||
'chu2to3.h',
|
'chu2to3.h',
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
Credits:
|
Credits:
|
||||||
somewhatlurker, skogaby
|
somewhatlurker, skogaby
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
|
@ -97,3 +97,27 @@ void led_serial_update(struct _chuni_led_data_buf_t* data)
|
||||||
|
|
||||||
ReleaseMutex(serial_write_mutex);
|
ReleaseMutex(serial_write_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void led_serial_update_openithm(const uint8_t* rgb)
|
||||||
|
{
|
||||||
|
if (serial_port != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
char led_buffer[100];
|
||||||
|
DWORD bytes_to_write; // No of bytes to write into the port
|
||||||
|
DWORD bytes_written = 0; // No of bytes written to the port
|
||||||
|
bytes_to_write = sizeof(led_buffer);
|
||||||
|
BOOL status;
|
||||||
|
|
||||||
|
led_buffer[0] = 0xAA;
|
||||||
|
led_buffer[1] = 0xAA;
|
||||||
|
memcpy(led_buffer+2, rgb, sizeof(uint8_t) * 96);
|
||||||
|
led_buffer[98] = 0xDD;
|
||||||
|
led_buffer[99] = 0xDD;
|
||||||
|
|
||||||
|
status = WriteFile(serial_port, // Handle to the Serial port
|
||||||
|
led_buffer, // Data to be written to the port
|
||||||
|
bytes_to_write, // No of bytes to write
|
||||||
|
&bytes_written, // Bytes written
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "chuniio/leddata.h"
|
#include "chuniio/leddata.h"
|
||||||
|
|
||||||
HRESULT led_serial_init(wchar_t led_com[12], DWORD baud);
|
HRESULT led_serial_init(wchar_t led_com[12], DWORD baud);
|
||||||
void led_serial_update(struct _chuni_led_data_buf_t* data);
|
void led_serial_update(struct _chuni_led_data_buf_t* data);
|
||||||
|
void led_serial_update_openithm(const uint8_t* rgb);
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "chuniio/chu2to3.h"
|
#include "chuniio/chu2to3.h"
|
||||||
#include "chusanhook/chuni-dll.h"
|
#include "chusanhook/chuni-dll.h"
|
||||||
|
@ -170,7 +171,7 @@ HRESULT chuni_dll_init(const struct chuni_dll_config *cfg, HINSTANCE self)
|
||||||
"\"%s\". Please contact your IO DLL's developer for "
|
"\"%s\". Please contact your IO DLL's developer for "
|
||||||
"further assistance.\n",
|
"further assistance.\n",
|
||||||
sym->sym);
|
sym->sym);
|
||||||
dprintf("imported %d symbols\n",bind_count);
|
dprintf("imported %d symbols\n", bind_count);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "board/config.h"
|
#include "board/config.h"
|
||||||
|
|
||||||
|
@ -95,7 +96,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
|
||||||
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
|
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
|
||||||
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
|
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
|
||||||
cfg->port_no = 0;
|
cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename);
|
||||||
|
cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename);
|
||||||
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
|
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
|
||||||
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
|
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
|
||||||
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);
|
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);
|
||||||
|
|
|
@ -1,37 +1,57 @@
|
||||||
#include <windows.h>
|
/*
|
||||||
|
"CHUNITHM NEW" (chusan) hook
|
||||||
|
|
||||||
|
Devices
|
||||||
|
|
||||||
|
USB: 837-15257-02 "Type 4" I/O Board
|
||||||
|
COM1: 837-15330 Ground Slider
|
||||||
|
|
||||||
|
[CVT mode (DIPSW2 ON)]
|
||||||
|
|
||||||
|
COM2: 837-15093-06 LED Controller Board
|
||||||
|
COM3: 837-15093-06 LED Controller Board
|
||||||
|
COM4: 837-15286 "Gen 2" Aime Reader
|
||||||
|
|
||||||
|
[SP mode (DIPSW2 OFF)]
|
||||||
|
|
||||||
|
USB: 837-15067-02 USB Serial I/F Board
|
||||||
|
connected to
|
||||||
|
837-15093-06 LED Controller Board (COM20)
|
||||||
|
837-15093-06 LED Controller Board (COM21)
|
||||||
|
COM2: 200-6275 VFD GP1232A02A FUTABA Board
|
||||||
|
COM4: 837-15396 "Gen 3" Aime Reader
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <windows.h>
|
||||||
#include "amex/amex.h"
|
|
||||||
|
|
||||||
#include "board/sg-reader.h"
|
#include "board/sg-reader.h"
|
||||||
#include "board/vfd.h"
|
#include "board/vfd.h"
|
||||||
|
|
||||||
|
#include "chuniio/chuniio.h"
|
||||||
#include "chusanhook/config.h"
|
#include "chusanhook/config.h"
|
||||||
#include "chusanhook/io4.h"
|
#include "chusanhook/io4.h"
|
||||||
#include "chusanhook/slider.h"
|
#include "chusanhook/slider.h"
|
||||||
|
|
||||||
#include "chuniio/chuniio.h"
|
|
||||||
|
|
||||||
#include "hook/process.h"
|
|
||||||
|
|
||||||
#include "gfxhook/d3d9.h"
|
#include "gfxhook/d3d9.h"
|
||||||
#include "gfxhook/gfx.h"
|
#include "gfxhook/gfx.h"
|
||||||
|
|
||||||
|
#include "hook/process.h"
|
||||||
|
|
||||||
#include "hooklib/serial.h"
|
#include "hooklib/serial.h"
|
||||||
#include "hooklib/spike.h"
|
#include "hooklib/spike.h"
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static HMODULE chusan_hook_mod;
|
static HMODULE chusan_hook_mod;
|
||||||
static process_entry_t chusan_startup;
|
static process_entry_t chusan_startup;
|
||||||
static struct chusan_hook_config chusan_hook_cfg;
|
static struct chusan_hook_config chusan_hook_cfg;
|
||||||
|
|
||||||
static DWORD CALLBACK chusan_pre_startup(void)
|
static DWORD CALLBACK chusan_pre_startup(void) {
|
||||||
{
|
|
||||||
HMODULE d3dc;
|
HMODULE d3dc;
|
||||||
HMODULE dbghelp;
|
HMODULE dbghelp;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -60,10 +80,10 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||||
|
|
||||||
/* Config load */
|
/* Config load */
|
||||||
|
|
||||||
chusan_hook_config_load(&chusan_hook_cfg, L".\\segatools.ini");
|
chusan_hook_config_load(&chusan_hook_cfg, get_config_path());
|
||||||
|
|
||||||
/* Hook Win32 APIs */
|
/* Hook Win32 APIs */
|
||||||
|
|
||||||
dvd_hook_init(&chusan_hook_cfg.dvd, chusan_hook_mod);
|
dvd_hook_init(&chusan_hook_cfg.dvd, chusan_hook_mod);
|
||||||
gfx_hook_init(&chusan_hook_cfg.gfx);
|
gfx_hook_init(&chusan_hook_cfg.gfx);
|
||||||
gfx_d3d9_hook_init(&chusan_hook_cfg.gfx, chusan_hook_mod);
|
gfx_d3d9_hook_init(&chusan_hook_cfg.gfx, chusan_hook_mod);
|
||||||
|
@ -71,6 +91,16 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||||
|
|
||||||
/* Initialize emulation hooks */
|
/* Initialize emulation hooks */
|
||||||
|
|
||||||
|
struct dipsw_config new_dipsw_config[8] = {
|
||||||
|
{L"Delivery Server", L"Server", L"Client"},
|
||||||
|
{L"Monitor Type", L"60FPS", L"120FPS"},
|
||||||
|
{L"Cabinet Type", L"CVT", L"SP"},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the system dip switch configuration
|
||||||
|
memcpy(chusan_hook_cfg.platform.system.dipsw_config, new_dipsw_config,
|
||||||
|
sizeof(new_dipsw_config));
|
||||||
|
|
||||||
hr = platform_hook_init(
|
hr = platform_hook_init(
|
||||||
&chusan_hook_cfg.platform,
|
&chusan_hook_cfg.platform,
|
||||||
"SDHD",
|
"SDHD",
|
||||||
|
@ -99,27 +129,7 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool *dipsw = &chusan_hook_cfg.platform.dipsw.dipsw[0];
|
bool is_cvt = chusan_hook_cfg.platform.system.dipsw[2];
|
||||||
bool is_cvt = dipsw[2];
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
dprintf("DipSw: NetInstall: %s\n", dipsw[0] ? "Server" : "Client");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
dprintf("DipSw: Monitor Type: %dFPS\n", dipsw[1] ? 60 : 120);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
dprintf("DipSw: Cab Type: %s\n", is_cvt ? "CVT" : "SP");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int first_port = is_cvt ? 2 : 20;
|
|
||||||
|
|
||||||
if (!is_cvt) {
|
if (!is_cvt) {
|
||||||
hr = vfd_hook_init(&chusan_hook_cfg.vfd, 2);
|
hr = vfd_hook_init(&chusan_hook_cfg.vfd, 2);
|
||||||
|
@ -129,19 +139,31 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL )
|
unsigned int led_port_no[2];
|
||||||
{
|
|
||||||
dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n");
|
if (is_cvt) {
|
||||||
|
led_port_no[0] = 2;
|
||||||
|
led_port_no[1] = 3;
|
||||||
} else {
|
} else {
|
||||||
hr = led15093_hook_init(&chusan_hook_cfg.led15093,
|
led_port_no[0] = 20;
|
||||||
chuni_dll.led_init, chuni_dll.led_set_leds, first_port, 2, 2, 1);
|
led_port_no[1] = 21;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL) {
|
||||||
|
dprintf(
|
||||||
|
"IO DLL doesn't support led_init/led_set_leds, cannot start "
|
||||||
|
"LED15093 hook\n");
|
||||||
|
} else {
|
||||||
|
hr = led15093_hook_init(&chusan_hook_cfg.led15093, chuni_dll.led_init,
|
||||||
|
chuni_dll.led_set_leds, led_port_no);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_cvt ? 2: 3, chusan_hook_mod);
|
hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_cvt ? 2 : 3,
|
||||||
|
chusan_hook_mod);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -149,7 +171,7 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
spike_hook_init(L".\\segatools.ini");
|
spike_hook_init(get_config_path());
|
||||||
|
|
||||||
dprintf("--- End chusan_pre_startup ---\n");
|
dprintf("--- End chusan_pre_startup ---\n");
|
||||||
|
|
||||||
|
@ -161,8 +183,7 @@ fail:
|
||||||
ExitProcess(EXIT_FAILURE);
|
ExitProcess(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
|
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) {
|
||||||
{
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (cause != DLL_PROCESS_ATTACH) {
|
if (cause != DLL_PROCESS_ATTACH) {
|
||||||
|
@ -174,7 +195,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
|
||||||
hr = process_hijack_startup(chusan_pre_startup, &chusan_startup);
|
hr = process_hijack_startup(chusan_pre_startup, &chusan_startup);
|
||||||
|
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr)) {
|
||||||
dprintf("Failed to hijack process startup: %x\n", (int) hr);
|
dprintf("Failed to hijack process startup: %x\n", (int)hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCEEDED(hr);
|
return SUCCEEDED(hr);
|
||||||
|
|
|
@ -4,7 +4,6 @@ shared_library(
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
vs_module_defs : 'chusanhook.def',
|
vs_module_defs : 'chusanhook.def',
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
capnhook.get_variable('hooklib_dep'),
|
capnhook.get_variable('hooklib_dep'),
|
||||||
|
|
|
@ -98,7 +98,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if 0
|
#if defined(LOG_CHUSAN_SLIDER)
|
||||||
dprintf("TX Buffer:\n");
|
dprintf("TX Buffer:\n");
|
||||||
dump_iobuf(&slider_uart.written);
|
dump_iobuf(&slider_uart.written);
|
||||||
#endif
|
#endif
|
||||||
|
@ -117,7 +117,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if defined(LOG_CHUSAN_SLIDER)
|
||||||
dprintf("Deframe Buffer:\n");
|
dprintf("Deframe Buffer:\n");
|
||||||
dump_iobuf(&req_iobuf);
|
dump_iobuf(&req_iobuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,3 +15,59 @@ EXPORTS
|
||||||
cm_io_get_opbtns
|
cm_io_get_opbtns
|
||||||
cm_io_init
|
cm_io_init
|
||||||
cm_io_poll
|
cm_io_poll
|
||||||
|
CFW_init
|
||||||
|
CFW_term
|
||||||
|
CFW_open
|
||||||
|
CFW_close
|
||||||
|
CFW_listupPrinter
|
||||||
|
CFW_listupPrinterSN
|
||||||
|
CFW_selectPrinter
|
||||||
|
CFW_selectPrinterSN
|
||||||
|
CFW_getPrinterInfo
|
||||||
|
CFW_status
|
||||||
|
CFW_statusAll
|
||||||
|
CFW_resetPrinter
|
||||||
|
CFW_updateFirmware
|
||||||
|
CFW_getFirmwareInfo
|
||||||
|
CHCUSB_init
|
||||||
|
CHCUSB_term
|
||||||
|
CHCUSB_MakeThread
|
||||||
|
CHCUSB_open
|
||||||
|
CHCUSB_close
|
||||||
|
CHCUSB_ReleaseThread
|
||||||
|
CHCUSB_listupPrinter
|
||||||
|
CHCUSB_listupPrinterSN
|
||||||
|
CHCUSB_selectPrinter
|
||||||
|
CHCUSB_selectPrinterSN
|
||||||
|
CHCUSB_getPrinterInfo
|
||||||
|
CHCUSB_imageformat
|
||||||
|
CHCUSB_setmtf
|
||||||
|
CHCUSB_makeGamma
|
||||||
|
CHCUSB_setIcctableProfile
|
||||||
|
CHCUSB_setIcctable
|
||||||
|
CHCUSB_copies
|
||||||
|
CHCUSB_status
|
||||||
|
CHCUSB_statusAll
|
||||||
|
CHCUSB_startpage
|
||||||
|
CHCUSB_endpage
|
||||||
|
CHCUSB_write
|
||||||
|
CHCUSB_writeLaminate
|
||||||
|
CHCUSB_writeHolo
|
||||||
|
CHCUSB_setPrinterInfo
|
||||||
|
CHCUSB_setPrinterToneCurve
|
||||||
|
CHCUSB_getGamma
|
||||||
|
CHCUSB_getMtf
|
||||||
|
CHCUSB_cancelCopies
|
||||||
|
CHCUSB_getPrinterToneCurve
|
||||||
|
CHCUSB_blinkLED
|
||||||
|
CHCUSB_resetPrinter
|
||||||
|
CHCUSB_AttachThreadCount
|
||||||
|
CHCUSB_getPrintIDStatus
|
||||||
|
CHCUSB_setPrintStandby
|
||||||
|
CHCUSB_testCardFeed
|
||||||
|
CHCUSB_exitCard
|
||||||
|
CHCUSB_getCardRfidTID
|
||||||
|
CHCUSB_commCardRfidReader
|
||||||
|
CHCUSB_updateCardRfidReader
|
||||||
|
CHCUSB_getErrorLog
|
||||||
|
CHCUSB_getErrorStatus
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "board/config.h"
|
#include "board/config.h"
|
||||||
|
|
||||||
|
@ -39,5 +40,7 @@ void cm_hook_config_load(
|
||||||
io4_config_load(&cfg->io4, filename);
|
io4_config_load(&cfg->io4, filename);
|
||||||
vfd_config_load(&cfg->vfd, filename);
|
vfd_config_load(&cfg->vfd, filename);
|
||||||
touch_screen_config_load(&cfg->touch, filename);
|
touch_screen_config_load(&cfg->touch, filename);
|
||||||
|
printer_config_load(&cfg->printer, filename);
|
||||||
cm_dll_config_load(&cfg->dll, filename);
|
cm_dll_config_load(&cfg->dll, filename);
|
||||||
|
unity_config_load(&cfg->unity, filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,14 @@
|
||||||
|
|
||||||
#include "hooklib/dvd.h"
|
#include "hooklib/dvd.h"
|
||||||
#include "hooklib/touch.h"
|
#include "hooklib/touch.h"
|
||||||
|
#include "hooklib/printer.h"
|
||||||
|
|
||||||
#include "cmhook/cm-dll.h"
|
#include "cmhook/cm-dll.h"
|
||||||
|
|
||||||
#include "platform/config.h"
|
#include "platform/config.h"
|
||||||
|
|
||||||
|
#include "unityhook/config.h"
|
||||||
|
|
||||||
struct cm_hook_config {
|
struct cm_hook_config {
|
||||||
struct platform_config platform;
|
struct platform_config platform;
|
||||||
struct aime_config aime;
|
struct aime_config aime;
|
||||||
|
@ -19,6 +22,8 @@ struct cm_hook_config {
|
||||||
struct vfd_config vfd;
|
struct vfd_config vfd;
|
||||||
struct cm_dll_config dll;
|
struct cm_dll_config dll;
|
||||||
struct touch_screen_config touch;
|
struct touch_screen_config touch;
|
||||||
|
struct printer_config printer;
|
||||||
|
struct unity_config unity;
|
||||||
};
|
};
|
||||||
|
|
||||||
void cm_dll_config_load(
|
void cm_dll_config_load(
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
/*
|
||||||
|
"Card Maker" (cm) hook
|
||||||
|
|
||||||
|
Devices
|
||||||
|
|
||||||
|
USB: 837-15257-01 "Type 4" I/O Board
|
||||||
|
USB: 838-20006 "WinTouch" Controller Board
|
||||||
|
USB: 630-00009 Sinfonia CHC-C310 Printer
|
||||||
|
COM1: 837-15396 "Gen 3" Aime Reader
|
||||||
|
COM2: 200-6275 VFD GP1232A02A FUTABA Board
|
||||||
|
COM3: 220-5872 AS-6DB Coin Selector
|
||||||
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -16,11 +29,13 @@
|
||||||
#include "cmhook/config.h"
|
#include "cmhook/config.h"
|
||||||
#include "cmhook/io4.h"
|
#include "cmhook/io4.h"
|
||||||
#include "cmhook/cm-dll.h"
|
#include "cmhook/cm-dll.h"
|
||||||
#include "cmhook/unity.h"
|
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
|
#include "unityhook/hook.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static HMODULE cm_hook_mod;
|
static HMODULE cm_hook_mod;
|
||||||
static process_entry_t cm_startup;
|
static process_entry_t cm_startup;
|
||||||
|
@ -34,7 +49,7 @@ static DWORD CALLBACK cm_pre_startup(void)
|
||||||
|
|
||||||
/* Load config */
|
/* Load config */
|
||||||
|
|
||||||
cm_hook_config_load(&cm_hook_cfg, L".\\segatools.ini");
|
cm_hook_config_load(&cm_hook_cfg, get_config_path());
|
||||||
|
|
||||||
/* Hook Win32 APIs */
|
/* Hook Win32 APIs */
|
||||||
|
|
||||||
|
@ -42,8 +57,20 @@ static DWORD CALLBACK cm_pre_startup(void)
|
||||||
touch_screen_hook_init(&cm_hook_cfg.touch, cm_hook_mod);
|
touch_screen_hook_init(&cm_hook_cfg.touch, cm_hook_mod);
|
||||||
serial_hook_init();
|
serial_hook_init();
|
||||||
|
|
||||||
|
/* Hook external DLL APIs */
|
||||||
|
|
||||||
|
printer_hook_init(&cm_hook_cfg.printer, 0, cm_hook_mod);
|
||||||
|
|
||||||
/* Initialize emulation hooks */
|
/* Initialize emulation hooks */
|
||||||
|
|
||||||
|
struct dipsw_config new_dipsw_config[8] = {
|
||||||
|
{L"Delivery Server", L"Client", L"Server"},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the system dip switch configuration
|
||||||
|
memcpy(cm_hook_cfg.platform.system.dipsw_config, new_dipsw_config,
|
||||||
|
sizeof(new_dipsw_config));
|
||||||
|
|
||||||
hr = platform_hook_init(
|
hr = platform_hook_init(
|
||||||
&cm_hook_cfg.platform,
|
&cm_hook_cfg.platform,
|
||||||
"SDED",
|
"SDED",
|
||||||
|
@ -54,6 +81,12 @@ static DWORD CALLBACK cm_pre_startup(void)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = cm_dll_init(&cm_hook_cfg.dll, cm_hook_mod);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
hr = sg_reader_hook_init(&cm_hook_cfg.aime, 1, 1, cm_hook_mod);
|
hr = sg_reader_hook_init(&cm_hook_cfg.aime, 1, 1, cm_hook_mod);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -66,12 +99,6 @@ static DWORD CALLBACK cm_pre_startup(void)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = cm_dll_init(&cm_hook_cfg.dll, cm_hook_mod);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = cm_io4_hook_init(&cm_hook_cfg.io4);
|
hr = cm_io4_hook_init(&cm_hook_cfg.io4);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -83,11 +110,11 @@ static DWORD CALLBACK cm_pre_startup(void)
|
||||||
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
||||||
hooked earlier in the `cmhook` initialization. */
|
hooked earlier in the `cmhook` initialization. */
|
||||||
|
|
||||||
unity_hook_init();
|
unity_hook_init(&cm_hook_cfg.unity, cm_hook_mod, NULL);
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
spike_hook_init(L".\\segatools.ini");
|
spike_hook_init(get_config_path());
|
||||||
|
|
||||||
dprintf("--- End cm_pre_startup ---\n");
|
dprintf("--- End cm_pre_startup ---\n");
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ shared_library(
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
vs_module_defs : 'cmhook.def',
|
vs_module_defs : 'cmhook.def',
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
capnhook.get_variable('hooklib_dep'),
|
capnhook.get_variable('hooklib_dep'),
|
||||||
|
@ -16,6 +15,7 @@ shared_library(
|
||||||
hooklib_lib,
|
hooklib_lib,
|
||||||
cmio_lib,
|
cmio_lib,
|
||||||
platform_lib,
|
platform_lib,
|
||||||
|
unityhook_lib,
|
||||||
util_lib,
|
util_lib,
|
||||||
],
|
],
|
||||||
sources : [
|
sources : [
|
||||||
|
@ -26,7 +26,5 @@ shared_library(
|
||||||
'io4.h',
|
'io4.h',
|
||||||
'cm-dll.c',
|
'cm-dll.c',
|
||||||
'cm-dll.h',
|
'cm-dll.h',
|
||||||
'unity.h',
|
|
||||||
'unity.c',
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "hook/table.h"
|
|
||||||
|
|
||||||
#include "hooklib/dll.h"
|
|
||||||
#include "hooklib/path.h"
|
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
|
||||||
|
|
||||||
static void dll_hook_insert_hooks(HMODULE target);
|
|
||||||
|
|
||||||
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name);
|
|
||||||
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
|
|
||||||
|
|
||||||
static const struct hook_symbol unity_kernel32_syms[] = {
|
|
||||||
{
|
|
||||||
.name = "LoadLibraryW",
|
|
||||||
.patch = my_LoadLibraryW,
|
|
||||||
.link = (void **) &next_LoadLibraryW,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const wchar_t *target_modules[] = {
|
|
||||||
L"mono.dll",
|
|
||||||
L"cri_ware_unity.dll",
|
|
||||||
};
|
|
||||||
static const size_t target_modules_len = _countof(target_modules);
|
|
||||||
|
|
||||||
void unity_hook_init(void)
|
|
||||||
{
|
|
||||||
dll_hook_insert_hooks(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dll_hook_insert_hooks(HMODULE target)
|
|
||||||
{
|
|
||||||
hook_table_apply(
|
|
||||||
target,
|
|
||||||
"kernel32.dll",
|
|
||||||
unity_kernel32_syms,
|
|
||||||
_countof(unity_kernel32_syms));
|
|
||||||
}
|
|
||||||
|
|
||||||
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name)
|
|
||||||
{
|
|
||||||
const wchar_t *name_end;
|
|
||||||
const wchar_t *target_module;
|
|
||||||
bool already_loaded;
|
|
||||||
HMODULE result;
|
|
||||||
size_t name_len;
|
|
||||||
size_t target_module_len;
|
|
||||||
|
|
||||||
if (name == NULL) {
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the module is already loaded
|
|
||||||
already_loaded = GetModuleHandleW(name) != NULL;
|
|
||||||
|
|
||||||
// Must call the next handler so the DLL reference count is incremented
|
|
||||||
result = next_LoadLibraryW(name);
|
|
||||||
|
|
||||||
if (!already_loaded && result != NULL) {
|
|
||||||
name_len = wcslen(name);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < target_modules_len; i++) {
|
|
||||||
target_module = target_modules[i];
|
|
||||||
target_module_len = wcslen(target_module);
|
|
||||||
|
|
||||||
// Check if the newly loaded library is at least the length of
|
|
||||||
// the name of the target module
|
|
||||||
if (name_len < target_module_len) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
name_end = &name[name_len - target_module_len];
|
|
||||||
|
|
||||||
// Check if the name of the newly loaded library is one of the
|
|
||||||
// modules the path hooks should be injected into
|
|
||||||
if (_wcsicmp(name_end, target_module) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("Unity: Loaded %S\n", target_module);
|
|
||||||
|
|
||||||
dll_hook_insert_hooks(result);
|
|
||||||
path_hook_insert_hooks(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
void unity_hook_init(void);
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "cmio/cmio.h"
|
#include "cmio/cmio.h"
|
||||||
#include "cmio/config.h"
|
#include "cmio/config.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static uint8_t cm_opbtn;
|
static uint8_t cm_opbtn;
|
||||||
static struct cm_io_config cm_io_cfg;
|
static struct cm_io_config cm_io_cfg;
|
||||||
|
@ -18,7 +19,7 @@ uint16_t cm_io_get_api_version(void)
|
||||||
|
|
||||||
HRESULT cm_io_init(void)
|
HRESULT cm_io_init(void)
|
||||||
{
|
{
|
||||||
cm_io_config_load(&cm_io_cfg, L".\\segatools.ini");
|
cm_io_config_load(&cm_io_cfg, get_config_path());
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,9 @@ HRESULT cm_io_init(void);
|
||||||
HRESULT cm_io_poll(void);
|
HRESULT cm_io_poll(void);
|
||||||
|
|
||||||
/* Get the state of the cabinet's operator buttons as of the last poll. See
|
/* Get the state of the cabinet's operator buttons as of the last poll. See
|
||||||
cm_IO_OPBTN enum above: this contains bit mask definitions for button
|
CM_IO_OPBTN enum above: this contains bit mask definitions for button
|
||||||
states returned in *opbtn. All buttons are active-high.
|
states returned in *opbtn. All buttons are active-high.
|
||||||
|
|
||||||
Minimum API version: 0x0100 */
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
void cm_io_get_opbtns(uint8_t *opbtn);
|
void cm_io_get_opbtns(uint8_t *opbtn);
|
||||||
|
|
|
@ -3,7 +3,6 @@ cmio_lib = static_library(
|
||||||
name_prefix : '',
|
name_prefix : '',
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
sources : [
|
sources : [
|
||||||
'cmio.c',
|
'cmio.c',
|
||||||
'cmio.h',
|
'cmio.h',
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "amex/amex.h"
|
#include "amex/amex.h"
|
||||||
#include "amex/config.h"
|
#include "amex/config.h"
|
||||||
|
@ -23,22 +24,32 @@ void cxb_dll_config_load(
|
||||||
struct cxb_dll_config *cfg,
|
struct cxb_dll_config *cfg,
|
||||||
const wchar_t *filename)
|
const wchar_t *filename)
|
||||||
{
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
GetPrivateProfileStringW(
|
||||||
|
L"cxbio",
|
||||||
|
L"path",
|
||||||
|
L"",
|
||||||
|
cfg->path,
|
||||||
|
_countof(cfg->path),
|
||||||
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void revio_config_load(struct revio_config *cfg, const wchar_t *filename)
|
void revio_config_load(struct revio_config *cfg, const wchar_t *filename)
|
||||||
{
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
}
|
cfg->enable = GetPrivateProfileIntW(L"revio", L"enable", 1, filename);
|
||||||
|
|
||||||
void network_config_load(struct network_config *cfg, const wchar_t *filename)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void led_config_load(struct led_config *cfg, const wchar_t *filename)
|
void led_config_load(struct led_config *cfg, const wchar_t *filename)
|
||||||
{
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
cfg->enable = GetPrivateProfileIntW(L"led", L"enable", 1, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxb_hook_config_load(
|
void cxb_hook_config_load(
|
||||||
|
@ -56,6 +67,5 @@ void cxb_hook_config_load(
|
||||||
gfx_config_load(&cfg->gfx, filename);
|
gfx_config_load(&cfg->gfx, filename);
|
||||||
cxb_dll_config_load(&cfg->dll, filename);
|
cxb_dll_config_load(&cfg->dll, filename);
|
||||||
revio_config_load(&cfg->revio, filename);
|
revio_config_load(&cfg->revio, filename);
|
||||||
network_config_load(&cfg->network, filename);
|
|
||||||
led_config_load(&cfg->led, filename);
|
led_config_load(&cfg->led, filename);
|
||||||
}
|
}
|
|
@ -10,7 +10,6 @@
|
||||||
#include "cxbhook/cxb-dll.h"
|
#include "cxbhook/cxb-dll.h"
|
||||||
#include "cxbhook/revio.h"
|
#include "cxbhook/revio.h"
|
||||||
#include "cxbhook/led.h"
|
#include "cxbhook/led.h"
|
||||||
#include "cxbhook/network.h"
|
|
||||||
|
|
||||||
#include "gfxhook/gfx.h"
|
#include "gfxhook/gfx.h"
|
||||||
|
|
||||||
|
@ -23,7 +22,6 @@ struct cxb_hook_config {
|
||||||
struct gfx_config gfx;
|
struct gfx_config gfx;
|
||||||
struct cxb_dll_config dll;
|
struct cxb_dll_config dll;
|
||||||
struct revio_config revio;
|
struct revio_config revio;
|
||||||
struct network_config network;
|
|
||||||
struct led_config led;
|
struct led_config led;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +30,6 @@ void cxb_dll_config_load(
|
||||||
const wchar_t *filename);
|
const wchar_t *filename);
|
||||||
|
|
||||||
void revio_config_load(struct revio_config *cfg, const wchar_t *filename);
|
void revio_config_load(struct revio_config *cfg, const wchar_t *filename);
|
||||||
void network_config_load(struct network_config *cfg, const wchar_t *filename);
|
|
||||||
void led_config_load(struct led_config *cfg, const wchar_t *filename);
|
void led_config_load(struct led_config *cfg, const wchar_t *filename);
|
||||||
|
|
||||||
void cxb_hook_config_load(
|
void cxb_hook_config_load(
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "cxbhook/config.h"
|
#include "cxbhook/config.h"
|
||||||
#include "cxbhook/revio.h"
|
#include "cxbhook/revio.h"
|
||||||
#include "cxbhook/led.h"
|
#include "cxbhook/led.h"
|
||||||
#include "cxbhook/network.h"
|
|
||||||
|
|
||||||
#include "cxbio/cxbio.h"
|
#include "cxbio/cxbio.h"
|
||||||
|
|
||||||
|
@ -24,6 +23,7 @@
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static HMODULE cxb_hook_mod;
|
static HMODULE cxb_hook_mod;
|
||||||
static process_entry_t cxb_startup;
|
static process_entry_t cxb_startup;
|
||||||
|
@ -59,7 +59,7 @@ static DWORD CALLBACK cxb_pre_startup(void)
|
||||||
|
|
||||||
/* Config load */
|
/* Config load */
|
||||||
|
|
||||||
cxb_hook_config_load(&cxb_hook_cfg, L".\\segatools.ini");
|
cxb_hook_config_load(&cxb_hook_cfg, get_config_path());
|
||||||
|
|
||||||
/* Hook Win32 APIs */
|
/* Hook Win32 APIs */
|
||||||
|
|
||||||
|
@ -103,12 +103,6 @@ static DWORD CALLBACK cxb_pre_startup(void)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = network_hook_init(&cxb_hook_cfg.network);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = led_hook_init(&cxb_hook_cfg.led);
|
hr = led_hook_init(&cxb_hook_cfg.led);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -117,7 +111,7 @@ static DWORD CALLBACK cxb_pre_startup(void)
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
spike_hook_init(L".\\segatools.ini");
|
spike_hook_init(get_config_path());
|
||||||
|
|
||||||
dprintf("--- End cxb_pre_startup ---\n");
|
dprintf("--- End cxb_pre_startup ---\n");
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "cxbhook/led.h"
|
#include "cxbhook/led.h"
|
||||||
#include "cxbhook/cxb-dll.h"
|
#include "cxbhook/cxb-dll.h"
|
||||||
|
|
||||||
#include "hooklib/procaddr.h"
|
#include "hook/procaddr.h"
|
||||||
|
|
||||||
#include "hook/table.h"
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
@ -49,8 +52,14 @@ static struct hook_symbol lamp_syms[] = {
|
||||||
|
|
||||||
HRESULT led_hook_init(struct led_config *cfg)
|
HRESULT led_hook_init(struct led_config *cfg)
|
||||||
{
|
{
|
||||||
dprintf("LED: Init\n");
|
assert(cfg != NULL);
|
||||||
return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms));
|
|
||||||
|
if (!cfg->enable) {
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("LED: Hook enabled.\n");
|
||||||
|
return proc_addr_table_push(NULL, "CommLamp.dll", lamp_syms, _countof(lamp_syms));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_cCommLamp_Open(char *port)
|
static int my_cCommLamp_Open(char *port)
|
||||||
|
|
|
@ -4,7 +4,6 @@ shared_library(
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
vs_module_defs : 'cxbhook.def',
|
vs_module_defs : 'cxbhook.def',
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
capnhook.get_variable('hooklib_dep'),
|
capnhook.get_variable('hooklib_dep'),
|
||||||
|
@ -30,7 +29,5 @@ shared_library(
|
||||||
'revio.h',
|
'revio.h',
|
||||||
'led.c',
|
'led.c',
|
||||||
'led.h',
|
'led.h',
|
||||||
'network.c',
|
|
||||||
'network.h',
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
#include <windows.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "cxbhook/network.h"
|
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
|
||||||
|
|
||||||
HRESULT network_hook_init(struct network_config *cfg)
|
|
||||||
{
|
|
||||||
dprintf("Network: Init\n");
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
struct network_config {
|
|
||||||
bool enable;
|
|
||||||
bool disable_ssl;
|
|
||||||
char title_server[PATH_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
HRESULT network_hook_init(struct network_config *cfg);
|
|
|
@ -1,12 +1,15 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
|
|
||||||
#include "cxbhook/revio.h"
|
#include "cxbhook/revio.h"
|
||||||
#include "cxbhook/cxb-dll.h"
|
#include "cxbhook/cxb-dll.h"
|
||||||
|
|
||||||
#include "hooklib/procaddr.h"
|
#include "hook/procaddr.h"
|
||||||
|
|
||||||
#include "hook/table.h"
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
@ -82,8 +85,14 @@ static struct hook_symbol revio_syms[] = {
|
||||||
|
|
||||||
HRESULT revio_hook_init(struct revio_config *cfg)
|
HRESULT revio_hook_init(struct revio_config *cfg)
|
||||||
{
|
{
|
||||||
dprintf("Revio: Init\n");
|
assert(cfg != NULL);
|
||||||
return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms));
|
|
||||||
|
if (!cfg->enable) {
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("Revio: Hook enabled.\n");
|
||||||
|
return proc_addr_table_push(NULL, "CommIo.dll", revio_syms, _countof(revio_syms));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_cCommIo_Open(char *port)
|
static int my_cCommIo_Open(char *port)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "cxbio/config.h"
|
#include "cxbio/config.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
static bool cxb_io_coin;
|
static bool cxb_io_coin;
|
||||||
static int cxb_io_coins;
|
static int cxb_io_coins;
|
||||||
|
@ -21,7 +22,7 @@ uint16_t cxb_io_get_api_version(void)
|
||||||
HRESULT cxb_io_revio_init(void)
|
HRESULT cxb_io_revio_init(void)
|
||||||
{
|
{
|
||||||
dprintf("CXB IO: REVIO init\n");
|
dprintf("CXB IO: REVIO init\n");
|
||||||
cxb_io_config_load(&cxb_io_cfg, L".\\segatools.ini");
|
cxb_io_config_load(&cxb_io_cfg, get_config_path());
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -75,4 +76,4 @@ HRESULT cxb_io_led_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxb_io_led_update(int id, int color)
|
void cxb_io_led_update(int id, int color)
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -3,7 +3,6 @@ cxbio_lib = static_library(
|
||||||
name_prefix : '',
|
name_prefix : '',
|
||||||
include_directories : inc,
|
include_directories : inc,
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
c_pch : '../precompiled.h',
|
|
||||||
sources : [
|
sources : [
|
||||||
'cxbio.c',
|
'cxbio.c',
|
||||||
'cxbio.h',
|
'cxbio.h',
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
taskkill /f /im aimeReaderHost.exe > nul 2>&1
|
|
||||||
|
|
||||||
start /min inject -d -k carolhook.dll aimeReaderHost.exe -p 10
|
start /min inject -d -k carolhook.dll aimeReaderHost.exe -p 10
|
||||||
|
|
||||||
inject -d -k carolhook.dll carol_nu.exe
|
inject -d -k carolhook.dll carol_nu.exe
|
||||||
|
|
||||||
taskkill /f /im aimeReaderHost.exe > nul 2>&1
|
taskkill /f /im aimeReaderHost.exe > nul 2>&1
|
||||||
|
|
||||||
echo.
|
echo.
|
|
@ -64,12 +64,16 @@ subnet=192.168.126.0
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[gfx]
|
[gfx]
|
||||||
|
; Enables the graphics hook.
|
||||||
|
enable=1
|
||||||
; Force the game to run windowed.
|
; Force the game to run windowed.
|
||||||
windowed=1
|
windowed=1
|
||||||
; Add a frame to the game window if running windowed.
|
; Add a frame to the game window if running windowed.
|
||||||
framed=1
|
framed=1
|
||||||
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
||||||
monitor=0
|
monitor=0
|
||||||
|
; Enable DPI awareness for the game process, preventing Windows from stretching the game window if a DPI scaling higher than 100% is used
|
||||||
|
dpiAware=1
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Custom IO settings
|
; Custom IO settings
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
start /min inject -d -k chunihook.dll aimeReaderHost.exe -p 12
|
start /min inject -d -k chunihook.dll aimeReaderHost.exe -p 12
|
||||||
|
|
||||||
inject -d -k chunihook.dll chuniApp.exe
|
inject -d -k chunihook.dll chuniApp.exe
|
||||||
|
|
||||||
taskkill /f /im aimeReaderHost.exe > nul 2>&1
|
taskkill /f /im aimeReaderHost.exe > nul 2>&1
|
||||||
|
|
||||||
echo.
|
echo.
|
|
@ -56,26 +56,16 @@ subnet=192.168.139.0
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[gfx]
|
[gfx]
|
||||||
|
; Enables the graphics hook.
|
||||||
|
enable=1
|
||||||
; Force the game to run windowed.
|
; Force the game to run windowed.
|
||||||
windowed=1
|
windowed=1
|
||||||
; Add a frame to the game window if running windowed.
|
; Add a frame to the game window if running windowed.
|
||||||
framed=1
|
framed=1
|
||||||
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
||||||
monitor=0
|
monitor=0
|
||||||
|
; Enable DPI awareness for the game process, preventing Windows from stretching the game window if a DPI scaling higher than 100% is used
|
||||||
; -----------------------------------------------------------------------------
|
dpiAware=1
|
||||||
; Custom IO settings
|
|
||||||
; -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[aimeio]
|
|
||||||
; To use a custom card reader IO DLL enter its path here.
|
|
||||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
|
||||||
path=
|
|
||||||
|
|
||||||
[chuniio]
|
|
||||||
; To use a custom Chunithm IO DLL enter its path here.
|
|
||||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
|
||||||
path=
|
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; LED settings
|
; LED settings
|
||||||
|
@ -96,10 +86,12 @@ cabLedOutputSerial=0
|
||||||
controllerLedOutputPipe=1
|
controllerLedOutputPipe=1
|
||||||
; Output slider LED data to the serial port
|
; Output slider LED data to the serial port
|
||||||
controllerLedOutputSerial=0
|
controllerLedOutputSerial=0
|
||||||
|
; Use the OpeNITHM protocol for serial LED output
|
||||||
|
controllerLedOutputOpeNITHM=0
|
||||||
|
|
||||||
; Serial port to send data to if using serial output. Default is COM5.
|
; Serial port to send data to if using serial output. Default is COM5.
|
||||||
;serialPort=COM5
|
;serialPort=COM5
|
||||||
; Baud rate for serial data
|
; Baud rate for serial data (set to 115200 if using OpeNITHM)
|
||||||
;serialBaud=921600
|
;serialBaud=921600
|
||||||
|
|
||||||
; Data output a sequence of bytes, with JVS-like framing.
|
; Data output a sequence of bytes, with JVS-like framing.
|
||||||
|
@ -122,6 +114,20 @@ controllerLedOutputSerial=0
|
||||||
; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
|
; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
|
||||||
|
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; Custom IO settings
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[aimeio]
|
||||||
|
; To use a custom card reader IO DLL enter its path here.
|
||||||
|
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||||
|
path=
|
||||||
|
|
||||||
|
[chuniio]
|
||||||
|
; To use a custom Chunithm IO DLL enter its path here.
|
||||||
|
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||||
|
path=
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Input settings
|
; Input settings
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -25,7 +25,7 @@ aimePath=DEVICE\aime.txt
|
||||||
;highBaud=1
|
;highBaud=1
|
||||||
|
|
||||||
[vfd]
|
[vfd]
|
||||||
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
|
; Enable VFD emulation. Disable to use a real VFD
|
||||||
; GP1232A02A FUTABA assembly.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ default=127.0.0.1
|
||||||
; Chunithm is extremely picky about its LAN environment, so leaving this
|
; Chunithm is extremely picky about its LAN environment, so leaving this
|
||||||
; setting enabled is strongly recommended.
|
; setting enabled is strongly recommended.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
; The final octet of the local host's IP address on the virtualized subnet (so,
|
; The final octet of the local host's IP address on the virtualized subnet (so,
|
||||||
; if the keychip subnet is `192.168.32.0` and this value is set to `11`, then the
|
; if the keychip subnet is `192.168.32.0` and this value is set to `11`, then the
|
||||||
; local host's virtualized LAN IP is `192.168.32.11`).
|
; local host's virtualized LAN IP is `192.168.32.11`).
|
||||||
|
@ -58,8 +59,8 @@ addrSuffix=11
|
||||||
; that subnet must start with 192.168.
|
; that subnet must start with 192.168.
|
||||||
subnet=192.168.139.0
|
subnet=192.168.139.0
|
||||||
|
|
||||||
[gpio]
|
[system]
|
||||||
; ALLS DIP switches.
|
; Enable ALLS system settings.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
; Enable freeplay mode. This will disable the coin slot and set the game to
|
; Enable freeplay mode. This will disable the coin slot and set the game to
|
||||||
|
@ -81,31 +82,16 @@ dipsw3=1
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[gfx]
|
[gfx]
|
||||||
|
; Enables the graphics hook.
|
||||||
|
enable=1
|
||||||
; Force the game to run windowed.
|
; Force the game to run windowed.
|
||||||
windowed=1
|
windowed=1
|
||||||
; Add a frame to the game window if running windowed.
|
; Add a frame to the game window if running windowed.
|
||||||
framed=0
|
framed=0
|
||||||
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
||||||
monitor=0
|
monitor=0
|
||||||
|
; Enable DPI awareness for the game process, preventing Windows from stretching the game window if a DPI scaling higher than 100% is used
|
||||||
; -----------------------------------------------------------------------------
|
dpiAware=1
|
||||||
; Custom IO settings
|
|
||||||
; -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[aimeio]
|
|
||||||
; To use a custom card reader IO DLL (x64) enter its path here.
|
|
||||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
|
||||||
path=
|
|
||||||
|
|
||||||
[chuniio]
|
|
||||||
; Uncomment this if you have custom chuniio implementation comprised of a single 32bit DLL.
|
|
||||||
; (will use chu2to3 engine internally)
|
|
||||||
;path=
|
|
||||||
|
|
||||||
; Uncomment both of these if you have custom chuniio implementation comprised of two DLLs.
|
|
||||||
; x86 chuniio to path32, x64 to path64. Both are necessary.
|
|
||||||
;path32=
|
|
||||||
;path64=
|
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; LED settings
|
; LED settings
|
||||||
|
@ -126,10 +112,12 @@ cabLedOutputSerial=0
|
||||||
controllerLedOutputPipe=1
|
controllerLedOutputPipe=1
|
||||||
; Output slider LED data to the serial port
|
; Output slider LED data to the serial port
|
||||||
controllerLedOutputSerial=0
|
controllerLedOutputSerial=0
|
||||||
|
; Use the OpeNITHM protocol for serial LED output
|
||||||
|
controllerLedOutputOpeNITHM=0
|
||||||
|
|
||||||
; Serial port to send data to if using serial output. Default is COM5.
|
; Serial port to send data to if using serial output. Default is COM5.
|
||||||
;serialPort=COM5
|
;serialPort=COM5
|
||||||
; Baud rate for serial data
|
; Baud rate for serial data (set to 115200 if using OpeNITHM)
|
||||||
;serialBaud=921600
|
;serialBaud=921600
|
||||||
|
|
||||||
; Data output a sequence of bytes, with JVS-like framing.
|
; Data output a sequence of bytes, with JVS-like framing.
|
||||||
|
@ -152,6 +140,25 @@ controllerLedOutputSerial=0
|
||||||
; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
|
; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
|
||||||
|
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; Custom IO settings
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[aimeio]
|
||||||
|
; To use a custom card reader IO DLL (x64) enter its path here.
|
||||||
|
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||||
|
path=
|
||||||
|
|
||||||
|
[chuniio]
|
||||||
|
; Uncomment this if you have custom chuniio implementation comprised of a single 32bit DLL.
|
||||||
|
; (will use chu2to3 engine internally)
|
||||||
|
;path=
|
||||||
|
|
||||||
|
; Uncomment both of these if you have custom chuniio implementation comprised of two DLLs.
|
||||||
|
; x86 chuniio to path32, x64 to path64. Both are necessary.
|
||||||
|
;path32=
|
||||||
|
;path64=
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Input settings
|
; Input settings
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
@ -201,7 +208,3 @@ ir=0x20
|
||||||
; ... etc ...
|
; ... etc ...
|
||||||
;cell31=0x53
|
;cell31=0x53
|
||||||
;cell32=0x53
|
;cell32=0x53
|
||||||
|
|
||||||
; Enable slider LED serial output. This follows OpeNITHM Serial LED Protocol.
|
|
||||||
; eg. COM5
|
|
||||||
;ledport=
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ enable=1
|
||||||
aimePath=DEVICE\aime.txt
|
aimePath=DEVICE\aime.txt
|
||||||
|
|
||||||
[vfd]
|
[vfd]
|
||||||
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
|
; Enable VFD emulation. Disable to use a real VFD
|
||||||
; GP1232A02A FUTABA assembly.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
@ -50,10 +50,10 @@ enable=1
|
||||||
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
||||||
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
||||||
; that subnet must start with 192.168.
|
; that subnet must start with 192.168.
|
||||||
subnet=192.168.100.0
|
subnet=192.168.165.0
|
||||||
|
|
||||||
[gpio]
|
[system]
|
||||||
; ALLS DIP switches.
|
; Enable ALLS system settings.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
; LAN Install: If multiple machines are present on the same LAN then set
|
; LAN Install: If multiple machines are present on the same LAN then set
|
||||||
|
@ -68,6 +68,19 @@ dipsw1=0
|
||||||
; Enable/Disable WinTouch emulation
|
; Enable/Disable WinTouch emulation
|
||||||
enable=0
|
enable=0
|
||||||
|
|
||||||
|
[unity]
|
||||||
|
; Path to a .NET DLL that should run before the game. Useful for loading
|
||||||
|
; modding frameworks such as BepInEx.
|
||||||
|
targetAssembly=
|
||||||
|
|
||||||
|
[printer]
|
||||||
|
; Sinfonia CHC-C330 printer emulation setting.
|
||||||
|
enable=1
|
||||||
|
; Change the printer serial number here.
|
||||||
|
serial_no="5A-A123"
|
||||||
|
; Insert the path to the image output directory here.
|
||||||
|
printerOutPath="DEVICE\print"
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Custom IO settings
|
; Custom IO settings
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -60,7 +60,7 @@ enable=1
|
||||||
subnet=192.168.150.0
|
subnet=192.168.150.0
|
||||||
billingCa=../DEVICE/ca.crt
|
billingCa=../DEVICE/ca.crt
|
||||||
billingPub=../DEVICE/billing.pub
|
billingPub=../DEVICE/billing.pub
|
||||||
billingType=2
|
billingType=0
|
||||||
|
|
||||||
[eeprom]
|
[eeprom]
|
||||||
; See above
|
; See above
|
||||||
|
@ -75,12 +75,16 @@ path=../DEVICE/sram.bin
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[gfx]
|
[gfx]
|
||||||
|
; Enables the graphics hook.
|
||||||
|
enable=1
|
||||||
; Force the game to run windowed.
|
; Force the game to run windowed.
|
||||||
windowed=1
|
windowed=1
|
||||||
; Add a frame to the game window if running windowed.
|
; Add a frame to the game window if running windowed.
|
||||||
framed=1
|
framed=1
|
||||||
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
|
||||||
monitor=0
|
monitor=0
|
||||||
|
; Enable DPI awareness for the game process, preventing Windows from stretching the game window if a DPI scaling higher than 100% is used
|
||||||
|
dpiAware=1
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Custom IO settings
|
; Custom IO settings
|
||||||
|
@ -110,7 +114,7 @@ path=
|
||||||
|
|
||||||
[revio]
|
[revio]
|
||||||
; Enable emulation of the rev IO board
|
; Enable emulation of the rev IO board
|
||||||
enabe=1
|
enable=1
|
||||||
; Test button virtual-key code. Default is the F1 key.
|
; Test button virtual-key code. Default is the F1 key.
|
||||||
test=0x70
|
test=0x70
|
||||||
; Service button virtual-key code. Default is the F2 key.
|
; Service button virtual-key code. Default is the F2 key.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue