diff --git a/GNUmakefile b/GNUmakefile
index be0bd9ba..c7ffdde3 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -25,7 +25,7 @@ toolchain_64 := x86_64-w64-mingw32-
gitrev := $(shell git rev-parse HEAD)
cppflags := -I src -I src/main -I src/test -DGITREV=$(gitrev)
-cflags := -O2 -pipe -ffunction-sections -fdata-sections \
+cflags := -g -O2 -pipe -ffunction-sections -fdata-sections \
-Wall -std=c99 -DPSAPI_VERSION=1
cflags_release := -Werror
ldflags := -Wl,--gc-sections -static-libgcc
@@ -240,7 +240,6 @@ $$(dll_$1_$2_$3) $$(implib_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) \
$(V)$$(toolchain_$1)gcc -shared \
-o $$(dll_$1_$2_$3) -Wl,--out-implib,$$(implib_$1_$2_$3) \
-Wl,--start-group $$^ -Wl,--end-group $$(ldflags_$3)
- $(V)$$(toolchain_$1)strip $$(dll_$1_$2_$3)
$(V)$$(toolchain_$1)ranlib $$(implib_$1_$2_$3)
endef
@@ -257,7 +256,6 @@ $$(exe_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) $$(absdpl_$1_$2_$3) \
| $$(bindir_$1_$2)
$(V)echo ... $$@
$(V)$$(toolchain_$1)gcc -o $$@ $$^ $$(ldflags_$3)
- $(V)$$(toolchain_$1)strip $$@
endef
diff --git a/Module.mk b/Module.mk
index 4178a424..803bca7a 100644
--- a/Module.mk
+++ b/Module.mk
@@ -80,7 +80,7 @@ cflags += \
# Each AVS-dependent project should consume the earliest AVS import definition
# that is still ABI-compatible with the real build its target links against.
-avsvers_32 := 1700 1603 1601 1508 1403 1304 1101 1002 803 0
+avsvers_32 := 1700 1603 1601 1508 1403 1306 1304 1101 1002 803 0
avsvers_64 := 1700 1603 1601 1509 1508
imps += avs avs-ea3
@@ -91,6 +91,7 @@ include src/main/acioemu/Module.mk
include src/main/aciomgr/Module.mk
include src/main/aciotest/Module.mk
include src/main/asio/Module.mk
+include src/main/avs-util/Module.mk
include src/main/bio2drv/Module.mk
include src/main/bio2emu-iidx/Module.mk
include src/main/bio2emu/Module.mk
@@ -257,6 +258,7 @@ $(zipdir)/iidx-09-to-12.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-09.bat \
dist/iidx/gamestart-10.bat \
@@ -282,6 +284,7 @@ $(zipdir)/iidx-13.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-13.bat \
dist/iidx/iidxhook-13.conf \
@@ -298,6 +301,7 @@ $(zipdir)/iidx-14-to-17.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-14.bat \
dist/iidx/gamestart-15.bat \
@@ -323,6 +327,10 @@ $(zipdir)/iidx-18.zip: \
dist/iidx/config.bat \
dist/iidx/gamestart-18.bat \
dist/iidx/iidxhook-18.conf \
+ dist/iidx/launcher-18.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -335,6 +343,7 @@ $(zipdir)/iidx-18-cn.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-18-cn.bat \
dist/iidx/iidxhook-18-cn.conf \
@@ -351,9 +360,14 @@ $(zipdir)/iidx-19.zip: \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-19.bat \
dist/iidx/iidxhook-19.conf \
+ dist/iidx/launcher-19.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -367,9 +381,14 @@ $(zipdir)/iidx-20.zip: \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-20.bat \
dist/iidx/iidxhook-20.conf \
+ dist/iidx/launcher-20.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -382,6 +401,7 @@ $(zipdir)/iidx-20-cn.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-20-cn.bat \
dist/iidx/iidxhook-20-cn.conf \
@@ -398,6 +418,7 @@ $(zipdir)/iidx-21-to-24.zip: \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-21.bat \
dist/iidx/gamestart-22.bat \
@@ -407,6 +428,13 @@ $(zipdir)/iidx-21-to-24.zip: \
dist/iidx/iidxhook-22.conf \
dist/iidx/iidxhook-23.conf \
dist/iidx/iidxhook-24.conf \
+ dist/iidx/launcher-21.xml \
+ dist/iidx/launcher-22.xml \
+ dist/iidx/launcher-23.xml \
+ dist/iidx/launcher-24.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -420,11 +448,17 @@ $(zipdir)/iidx-25-to-26.zip: \
build/bin/indep-64/geninput.dll \
build/bin/indep-64/iidxio.dll \
build/bin/indep-64/vefxio.dll \
+ dist/dwarfstack/64/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-25.bat \
dist/iidx/gamestart-26.bat \
dist/iidx/iidxhook-25.conf \
dist/iidx/iidxhook-26.conf \
+ dist/iidx/launcher-25.xml \
+ dist/iidx/launcher-26.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -438,6 +472,7 @@ $(zipdir)/iidx-27-to-30.zip: \
build/bin/indep-64/geninput.dll \
build/bin/indep-64/iidxio.dll \
build/bin/indep-64/vefxio.dll \
+ dist/dwarfstack/64/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-27.bat \
dist/iidx/gamestart-28.bat \
@@ -447,6 +482,13 @@ $(zipdir)/iidx-27-to-30.zip: \
dist/iidx/iidxhook-28.conf \
dist/iidx/iidxhook-29.conf \
dist/iidx/iidxhook-30.conf \
+ dist/iidx/launcher-27.xml \
+ dist/iidx/launcher-28.xml \
+ dist/iidx/launcher-29.xml \
+ dist/iidx/launcher-30.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
dist/iidx/vefx.txt \
| $(zipdir)/
$(V)echo ... $@
@@ -485,6 +527,7 @@ $(zipdir)/jb-01.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-01.bat \
dist/jb/jbhook-01.conf \
@@ -499,6 +542,7 @@ $(zipdir)/jb-02.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-02.bat \
dist/jb/jbhook-02.conf \
@@ -513,8 +557,13 @@ $(zipdir)/jb-03.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-03.bat \
+ dist/jb/launcher-03.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -526,8 +575,13 @@ $(zipdir)/jb-04.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-03.bat \
+ dist/jb/launcher-03.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -539,8 +593,13 @@ $(zipdir)/jb-05-to-07.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-04.bat \
+ dist/jb/launcher-04.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -552,8 +611,13 @@ $(zipdir)/jb-08.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-04.bat \
+ dist/jb/launcher-04.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -576,8 +640,13 @@ $(zipdir)/sdvx-01-to-04.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/sdvxio.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/sdvx/config.bat \
dist/sdvx/gamestart.bat \
+ dist/sdvx/launcher.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -589,9 +658,14 @@ $(zipdir)/sdvx-05-to-06.zip: \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
build/bin/indep-64/sdvxio.dll \
+ dist/dwarfstack/64/dwarfstack.dll \
dist/sdvx5/config.bat \
dist/sdvx5/gamestart.bat \
dist/sdvx5/sdvxhook2.conf \
+ dist/sdvx5/launcher.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -603,9 +677,14 @@ $(zipdir)/sdvx-05-cn.zip: \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
build/bin/indep-64/sdvxio.dll \
+ dist/dwarfstack/64/dwarfstack.dll \
dist/sdvx5/config.bat \
dist/sdvx5/gamestart-cn.bat \
dist/sdvx5/sdvxhook2-cn.conf \
+ dist/sdvx5/launcher-cn.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -659,6 +738,7 @@ $(zipdir)/ddr-12-us.zip: \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-12-us.bat \
dist/ddr/gamestart-12-eu.bat \
@@ -678,29 +758,39 @@ $(zipdir)/ddr-12.zip: \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-12.bat \
+ dist/ddr/launcher-12.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-13.zip: \
- build/bin/avs2_1304-32/launcher.exe \
- build/bin/avs2_1304-32/ddrhook2.dll \
- build/bin/avs2_1304-32/unicorntail.dll \
+ build/bin/avs2_1306-32/launcher.exe \
+ build/bin/avs2_1306-32/ddrhook2.dll \
+ build/bin/avs2_1306-32/unicorntail.dll \
build/bin/indep-32/config.exe \
build/bin/indep-32/ddrio.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-13.bat \
+ dist/ddr/launcher-13.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
-$(zipdir)/ddr-14-to-16.zip: \
+$(zipdir)/ddr-14-to-18.zip: \
build/bin/avs2_1508-32/launcher.exe \
build/bin/avs2_1508-32/ddrhook2.dll \
build/bin/avs2_1508-32/unicorntail.dll \
@@ -708,15 +798,26 @@ $(zipdir)/ddr-14-to-16.zip: \
build/bin/indep-32/ddrio.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-14.bat \
dist/ddr/gamestart-15.bat \
dist/ddr/gamestart-16.bat \
+ dist/ddr/gamestart-17.bat \
+ dist/ddr/gamestart-18.bat \
+ dist/ddr/launcher-14.xml \
+ dist/ddr/launcher-15.xml \
+ dist/ddr/launcher-16.xml \
+ dist/ddr/launcher-17.xml \
+ dist/ddr/launcher-18.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
-$(zipdir)/ddr-16-x64.zip: \
+$(zipdir)/ddr-16-to-18-x64.zip: \
build/bin/avs2_1603-64/launcher.exe \
build/bin/avs2_1603-64/ddrhook2.dll \
build/bin/avs2_1603-64/unicorntail.dll \
@@ -724,8 +825,17 @@ $(zipdir)/ddr-16-x64.zip: \
build/bin/indep-64/ddrio.dll \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
+ dist/dwarfstack/64/dwarfstack.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-16.bat \
+ dist/ddr/gamestart-17.bat \
+ dist/ddr/gamestart-18.bat \
+ dist/ddr/launcher-16.xml \
+ dist/ddr/launcher-17.xml \
+ dist/ddr/launcher-18.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -761,9 +871,15 @@ $(zipdir)/bst.zip: \
build/bin/indep-64/config.exe \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
+ dist/dwarfstack/64/dwarfstack.dll \
dist/bst/config.bat \
dist/bst/gamestart1.bat \
dist/bst/gamestart2.bat \
+ dist/bst/launcher-01.xml \
+ dist/bst/launcher-02.xml \
+ dist/shared/ea3-ident.xml \
+ dist/shared/ea3-license.xml \
+ dist/shared/ea3-service.xml \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
@@ -776,6 +892,7 @@ $(zipdir)/popn-15-to-18.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/popnio.dll \
build/bin/indep-32/ezusb2-popn-shim.dll \
+ dist/dwarfstack/32/dwarfstack.dll \
dist/popn/config.bat \
dist/popn/gamestart-15.bat \
dist/popn/gamestart-16.bat \
@@ -807,6 +924,7 @@ $(BUILDDIR)/tests.zip: \
build/bin/indep-32/iidxhook-util-config-gfx-test.exe \
build/bin/indep-32/iidxhook-util-config-misc-test.exe \
build/bin/indep-32/iidxhook-util-config-sec-test.exe \
+ dist/dwarfstack/32/dwarfstack.dll \
build/bin/indep-32/inject.exe \
build/bin/indep-32/security-id-test.exe \
build/bin/indep-32/security-mcode-test.exe \
@@ -827,8 +945,8 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/ddr-12.zip \
$(zipdir)/ddr-12-us.zip \
$(zipdir)/ddr-13.zip \
- $(zipdir)/ddr-14-to-16.zip \
- $(zipdir)/ddr-16-x64.zip \
+ $(zipdir)/ddr-14-to-18.zip \
+ $(zipdir)/ddr-16-to-18-x64.zip \
$(zipdir)/ddr-hwio-x86.zip \
$(zipdir)/ddr-hwio-x64.zip \
$(zipdir)/doc.zip \
diff --git a/README.md b/README.md
index d320361e..cfe7b216 100644
--- a/README.md
+++ b/README.md
@@ -35,9 +35,12 @@ The following games are supported with their corresponding hook-libraries.
* Dance Dance Revolution X (`ddr-11.zip`): [ddrhook1](doc/ddrhook/ddrhook1.md)
* Dance Dance Revolution X2 (US/EU regions) (`ddr-12-us.zip`): [ddrhook1](doc/ddrhook/ddrhook1.md)
* Dance Dance Revolution X2 (JP region) (`ddr-12.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
- * Dance Dance Revolution 2013 (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
- * Dance Dance Revolution 2014 (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
- * Dance Dance Revolution A (`ddr-14-to-16.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
+ * Dance Dance Revolution X3 vs. 2ndMIX (`ddr-13.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
+ * Dance Dance Revolution 2013 (`ddr-14-to-18.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
+ * Dance Dance Revolution 2014 (`ddr-14-to-18.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
+ * Dance Dance Revolution A (`ddr-14-to-18.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
+ * Dance Dance Revolution A20 (`ddr-14-to-18.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
+ * Dance Dance Revolution A20+ (`ddr-14-to-18.zip`): [ddrhook2](doc/ddrhook/ddrhook2.md)
* [Beatmania IIDX](doc/iidxhook/README.md)
* Beatmania IIDX 9th Style (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
* Beatmania IIDX 10th Style (`iidx-09-to-12.zip`): [iidxhook1](doc/iidxhook/iidxhook1.md)
diff --git a/dist/bst/gamestart1.bat b/dist/bst/gamestart1.bat
index 5a3a9155..5bca8eb1 100644
--- a/dist/bst/gamestart1.bat
+++ b/dist/bst/gamestart1.bat
@@ -1,10 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K bsthook.dll -E prop/ea3-config-1.xml beatstream1.dll %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-01.xml %*
\ No newline at end of file
diff --git a/dist/bst/gamestart2.bat b/dist/bst/gamestart2.bat
index 8b6f53f8..55340c37 100644
--- a/dist/bst/gamestart2.bat
+++ b/dist/bst/gamestart2.bat
@@ -1,10 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K bsthook.dll -E prop/ea3-config-2.xml beatstream2.dll %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-02.xml %*
\ No newline at end of file
diff --git a/dist/bst/launcher-01.xml b/dist/bst/launcher-01.xml
new file mode 100644
index 00000000..b62630ef
--- /dev/null
+++ b/dist/bst/launcher-01.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+ ∂
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ beatstream1.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-server.xml
+
+
+
+ bsthook.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/bst/launcher-02.xml b/dist/bst/launcher-02.xml
new file mode 100644
index 00000000..fdad81d9
--- /dev/null
+++ b/dist/bst/launcher-02.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ beatstream2.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ bsthook.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/ddr/gamestart-12.bat b/dist/ddr/gamestart-12.bat
index 7df3fa33..03daa9c3 100644
--- a/dist/ddr/gamestart-12.bat
+++ b/dist/ddr/gamestart-12.bat
@@ -1,11 +1,42 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist conf\nvram mkdir conf\nvram
-if not exist conf\raw mkdir conf\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set COM_DIR=%CONTENT_DIR%\com
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Register video codecs, e.g. required for background videos
+regsvr32 /s %COM_DIR%\k-clvsd.dll
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-regsvr32 /s k-clvsd.dll
-regsvr32 /s xactengine2_10.dll
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-13.xml %*
-.\launcher.exe -K .\ddrhook2.dll .\ddr.dll %*
+:: Unregister video codec to avoid conflicts with other/older video codecs crashing different
+:: game versions, e.g. DDR X
+regsvr32 /u /s %COM_DIR%\k-clvsd.dll
\ No newline at end of file
diff --git a/dist/ddr/gamestart-13.bat b/dist/ddr/gamestart-13.bat
index 7df3fa33..03daa9c3 100644
--- a/dist/ddr/gamestart-13.bat
+++ b/dist/ddr/gamestart-13.bat
@@ -1,11 +1,42 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist conf\nvram mkdir conf\nvram
-if not exist conf\raw mkdir conf\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set COM_DIR=%CONTENT_DIR%\com
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Register video codecs, e.g. required for background videos
+regsvr32 /s %COM_DIR%\k-clvsd.dll
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-regsvr32 /s k-clvsd.dll
-regsvr32 /s xactengine2_10.dll
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-13.xml %*
-.\launcher.exe -K .\ddrhook2.dll .\ddr.dll %*
+:: Unregister video codec to avoid conflicts with other/older video codecs crashing different
+:: game versions, e.g. DDR X
+regsvr32 /u /s %COM_DIR%\k-clvsd.dll
\ No newline at end of file
diff --git a/dist/ddr/gamestart-14.bat b/dist/ddr/gamestart-14.bat
index 2ad52121..2364f521 100644
--- a/dist/ddr/gamestart-14.bat
+++ b/dist/ddr/gamestart-14.bat
@@ -1,14 +1,44 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist conf\nvram mkdir conf\nvram
-if not exist conf\nvram\coin.xml copy prop\coin.xml conf\nvram\coin.xml
-if not exist conf\nvram\eacoin.xml copy prop\eacoin.xml conf\nvram\eacoin.xml
-if not exist conf\nvram\share-config.xml copy prop\share-config.xml conf\nvram\share-config.xml
-if not exist conf\raw mkdir conf\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set COM_DIR=%CONTENT_DIR%\com
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Register video codecs, e.g. required for background videos
+regsvr32 /s %COM_DIR%\k-clvsd.dll
+regsvr32 /s %COM_DIR%\xactengine2_10.dll
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-regsvr32 /s k-clvsd.dll
-regsvr32 /s xactengine2_10.dll
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-14.xml %*
-.\launcher.exe -K .\ddrhook2.dll .\mdxja_945.dll %*
+:: Unregister video codec to avoid conflicts with other/older video codecs crashing different
+:: game versions, e.g. DDR X
+regsvr32 /u /s %COM_DIR%\k-clvsd.dll
+regsvr32 /u /s %COM_DIR%\xactengine2_10.dll
\ No newline at end of file
diff --git a/dist/ddr/gamestart-15.bat b/dist/ddr/gamestart-15.bat
index 2ad52121..97301177 100644
--- a/dist/ddr/gamestart-15.bat
+++ b/dist/ddr/gamestart-15.bat
@@ -1,14 +1,44 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist conf\nvram mkdir conf\nvram
-if not exist conf\nvram\coin.xml copy prop\coin.xml conf\nvram\coin.xml
-if not exist conf\nvram\eacoin.xml copy prop\eacoin.xml conf\nvram\eacoin.xml
-if not exist conf\nvram\share-config.xml copy prop\share-config.xml conf\nvram\share-config.xml
-if not exist conf\raw mkdir conf\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set COM_DIR=%CONTENT_DIR%\com
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Register video codecs, e.g. required for background videos
+regsvr32 /s %COM_DIR%\k-clvsd.dll
+regsvr32 /s %COM_DIR%\xactengine2_10.dll
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-regsvr32 /s k-clvsd.dll
-regsvr32 /s xactengine2_10.dll
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-15.xml %*
-.\launcher.exe -K .\ddrhook2.dll .\mdxja_945.dll %*
+:: Unregister video codec to avoid conflicts with other/older video codecs crashing different
+:: game versions, e.g. DDR X
+regsvr32 /u /s %COM_DIR%\k-clvsd.dll
+regsvr32 /u /s %COM_DIR%\xactengine2_10.dll
\ No newline at end of file
diff --git a/dist/ddr/gamestart-16.bat b/dist/ddr/gamestart-16.bat
index d108118b..b176cb3a 100644
--- a/dist/ddr/gamestart-16.bat
+++ b/dist/ddr/gamestart-16.bat
@@ -1,15 +1,44 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist conf\nvram mkdir conf\nvram
-if not exist conf\nvram\ea3-config.xml copy prop\eamuse-config.xml conf\nvram\ea3-config.xml
-if not exist conf\nvram\coin.xml copy prop\coin.xml conf\nvram\coin.xml
-if not exist conf\nvram\eacoin.xml copy prop\eacoin.xml conf\nvram\eacoin.xml
-if not exist conf\nvram\testmode-v.xml copy prop\testmode-v.xml conf\nvram\testmode-v.xml
-if not exist conf\raw mkdir conf\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set COM_DIR=%CONTENT_DIR%\com
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Register video codecs, e.g. required for background videos
+regsvr32 /s %COM_DIR%\k-clvsd.dll
+regsvr32 /s %COM_DIR%\xactengine2_10.dll
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-regsvr32 /s com\k-clvsd.dll
-regsvr32 /s com\xactengine2_10.dll
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-17.xml %*
-.\launcher.exe -H 33554432 -K .\ddrhook2.dll .\arkmdxp3.dll %*
+:: Unregister video codec to avoid conflicts with other/older video codecs crashing different
+:: game versions, e.g. DDR X
+regsvr32 /u /s %COM_DIR%\k-clvsd.dll
+regsvr32 /u /s %COM_DIR%\xactengine2_10.dll
\ No newline at end of file
diff --git a/dist/ddr/gamestart-17.bat b/dist/ddr/gamestart-17.bat
new file mode 100644
index 00000000..b176cb3a
--- /dev/null
+++ b/dist/ddr/gamestart-17.bat
@@ -0,0 +1,44 @@
+@echo off
+
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set COM_DIR=%CONTENT_DIR%\com
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Register video codecs, e.g. required for background videos
+regsvr32 /s %COM_DIR%\k-clvsd.dll
+regsvr32 /s %COM_DIR%\xactengine2_10.dll
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-17.xml %*
+
+:: Unregister video codec to avoid conflicts with other/older video codecs crashing different
+:: game versions, e.g. DDR X
+regsvr32 /u /s %COM_DIR%\k-clvsd.dll
+regsvr32 /u /s %COM_DIR%\xactengine2_10.dll
\ No newline at end of file
diff --git a/dist/ddr/gamestart-18.bat b/dist/ddr/gamestart-18.bat
new file mode 100644
index 00000000..95a92ed0
--- /dev/null
+++ b/dist/ddr/gamestart-18.bat
@@ -0,0 +1,44 @@
+@echo off
+
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set COM_DIR=%CONTENT_DIR%\com
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Register video codecs, e.g. required for background videos
+regsvr32 /s %COM_DIR%\k-clvsd.dll
+regsvr32 /s %COM_DIR%\xactengine2_10.dll
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-18.xml %*
+
+:: Unregister video codec to avoid conflicts with other/older video codecs crashing different
+:: game versions, e.g. DDR X
+regsvr32 /u /s %COM_DIR%\k-clvsd.dll
+regsvr32 /u /s %COM_DIR%\xactengine2_10.dll
\ No newline at end of file
diff --git a/dist/ddr/launcher-12.xml b/dist/ddr/launcher-12.xml
new file mode 100644
index 00000000..54c0284b
--- /dev/null
+++ b/dist/ddr/launcher-12.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 31457280
+ 31457280
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ ddr.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ ddrhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/ddr/launcher-13.xml b/dist/ddr/launcher-13.xml
new file mode 100644
index 00000000..54c0284b
--- /dev/null
+++ b/dist/ddr/launcher-13.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 31457280
+ 31457280
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ ddr.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ ddrhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/ddr/launcher-14.xml b/dist/ddr/launcher-14.xml
new file mode 100644
index 00000000..9ae27ac3
--- /dev/null
+++ b/dist/ddr/launcher-14.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 31457280
+ 31457280
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ mdxja_945.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ ddrhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/ddr/launcher-15.xml b/dist/ddr/launcher-15.xml
new file mode 100644
index 00000000..9ae27ac3
--- /dev/null
+++ b/dist/ddr/launcher-15.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 31457280
+ 31457280
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ mdxja_945.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ ddrhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/ddr/launcher-16.xml b/dist/ddr/launcher-16.xml
new file mode 100644
index 00000000..cdf16d55
--- /dev/null
+++ b/dist/ddr/launcher-16.xml
@@ -0,0 +1,76 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 33554432
+ 1048576
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ arkmdxp3.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ ddrhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/ddr/launcher-17.xml b/dist/ddr/launcher-17.xml
new file mode 100644
index 00000000..cdf16d55
--- /dev/null
+++ b/dist/ddr/launcher-17.xml
@@ -0,0 +1,76 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 33554432
+ 1048576
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ arkmdxp3.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ ddrhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/ddr/launcher-18.xml b/dist/ddr/launcher-18.xml
new file mode 100644
index 00000000..cdf16d55
--- /dev/null
+++ b/dist/ddr/launcher-18.xml
@@ -0,0 +1,76 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 33554432
+ 1048576
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ arkmdxp3.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ ddrhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/dwarfstack/32/dwarfstack.dll b/dist/dwarfstack/32/dwarfstack.dll
new file mode 100644
index 00000000..74b9796d
Binary files /dev/null and b/dist/dwarfstack/32/dwarfstack.dll differ
diff --git a/dist/dwarfstack/64/dwarfstack.dll b/dist/dwarfstack/64/dwarfstack.dll
new file mode 100644
index 00000000..8944c726
Binary files /dev/null and b/dist/dwarfstack/64/dwarfstack.dll differ
diff --git a/dist/dwarfstack/readme.md b/dist/dwarfstack/readme.md
new file mode 100644
index 00000000..c8ce1e3c
--- /dev/null
+++ b/dist/dwarfstack/readme.md
@@ -0,0 +1 @@
+Version/release: https://github.com/ssbssa/dwarfstack/releases/tag/2.2
\ No newline at end of file
diff --git a/dist/iidx/ea3-ident.xml b/dist/iidx/ea3-ident.xml
new file mode 100644
index 00000000..e24a9b92
--- /dev/null
+++ b/dist/iidx/ea3-ident.xml
@@ -0,0 +1,10 @@
+
+
+
+ LDJ
+ J
+ A
+ A
+ 2022082400
+
+
\ No newline at end of file
diff --git a/dist/iidx/eamuse-server.xml b/dist/iidx/eamuse-server.xml
new file mode 100644
index 00000000..bc706444
--- /dev/null
+++ b/dist/iidx/eamuse-server.xml
@@ -0,0 +1,6 @@
+
+
+
+ http://localhost
+
+
\ No newline at end of file
diff --git a/dist/iidx/gamestart-18.bat b/dist/iidx/gamestart-18.bat
index cce99b03..64398697 100755
--- a/dist/iidx/gamestart-18.bat
+++ b/dist/iidx/gamestart-18.bat
@@ -1,14 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist d mkdir d
-if not exist e mkdir e
-if not exist f mkdir f
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K iidxhook4.dll bm2dx.dll --config iidxhook-18.conf %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-18.xml --config iidxhook-18.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-19.bat b/dist/iidx/gamestart-19.bat
index 8bfd5803..9a1ac95a 100755
--- a/dist/iidx/gamestart-19.bat
+++ b/dist/iidx/gamestart-19.bat
@@ -1,14 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist d mkdir d
-if not exist e mkdir e
-if not exist f mkdir f
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K iidxhook5.dll bm2dx.dll --config iidxhook-19.conf %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-19.xml --config iidxhook-19.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-20.bat b/dist/iidx/gamestart-20.bat
index 2dac80ea..4a9d9f53 100755
--- a/dist/iidx/gamestart-20.bat
+++ b/dist/iidx/gamestart-20.bat
@@ -1,10 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K iidxhook6.dll bm2dx.dll --config iidxhook-20.conf %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-20.xml --config iidxhook-20.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-21.bat b/dist/iidx/gamestart-21.bat
index b79d6416..6c7c91ca 100755
--- a/dist/iidx/gamestart-21.bat
+++ b/dist/iidx/gamestart-21.bat
@@ -1,10 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K iidxhook7.dll bm2dx.dll --config iidxhook-21.conf %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-21.xml --config iidxhook-21.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-22.bat b/dist/iidx/gamestart-22.bat
index d10a945a..bf195d2a 100755
--- a/dist/iidx/gamestart-22.bat
+++ b/dist/iidx/gamestart-22.bat
@@ -1,10 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K iidxhook7.dll bm2dx.dll --config iidxhook-22.conf %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-22.xml --config iidxhook-22.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-23.bat b/dist/iidx/gamestart-23.bat
index 656e1fe2..ec664375 100755
--- a/dist/iidx/gamestart-23.bat
+++ b/dist/iidx/gamestart-23.bat
@@ -1,10 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K iidxhook7.dll bm2dx.dll --config iidxhook-23.conf %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-23.xml --config iidxhook-23.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-24.bat b/dist/iidx/gamestart-24.bat
index 283020c4..c9b5f5e9 100755
--- a/dist/iidx/gamestart-24.bat
+++ b/dist/iidx/gamestart-24.bat
@@ -1,10 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -K iidxhook7.dll bm2dx.dll --config iidxhook-24.conf %*
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-24.xml --config iidxhook-24.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-25.bat b/dist/iidx/gamestart-25.bat
index edff2940..67775e21 100644
--- a/dist/iidx/gamestart-25.bat
+++ b/dist/iidx/gamestart-25.bat
@@ -1,16 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-launcher -H 134217728 -K iidxhook8.dll bm2dx.dll --config iidxhook-25.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-25.xml --config iidxhook-25.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-26.bat b/dist/iidx/gamestart-26.bat
index d41b72b3..749f1205 100644
--- a/dist/iidx/gamestart-26.bat
+++ b/dist/iidx/gamestart-26.bat
@@ -1,16 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-launcher -H 134217728 -K iidxhook8.dll bm2dx.dll --config iidxhook-26.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-26.xml --config iidxhook-26.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-27.bat b/dist/iidx/gamestart-27.bat
index 04a39091..5b3b3782 100644
--- a/dist/iidx/gamestart-27.bat
+++ b/dist/iidx/gamestart-27.bat
@@ -1,16 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-27.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-27.xml --config iidxhook-27.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-28.bat b/dist/iidx/gamestart-28.bat
index 1abb520d..3486de8f 100644
--- a/dist/iidx/gamestart-28.bat
+++ b/dist/iidx/gamestart-28.bat
@@ -1,16 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-28.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-28.xml --config iidxhook-28.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-29.bat b/dist/iidx/gamestart-29.bat
index 1029b8c5..d4d7c1f7 100644
--- a/dist/iidx/gamestart-29.bat
+++ b/dist/iidx/gamestart-29.bat
@@ -1,16 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-29.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-29.xml --config iidxhook-29.conf %*
\ No newline at end of file
diff --git a/dist/iidx/gamestart-30.bat b/dist/iidx/gamestart-30.bat
index 776d7e84..3f960227 100644
--- a/dist/iidx/gamestart-30.bat
+++ b/dist/iidx/gamestart-30.bat
@@ -1,16 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-modules\launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-30.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-30.xml --config iidxhook-30.conf %*
\ No newline at end of file
diff --git a/dist/iidx/launcher-18.xml b/dist/iidx/launcher-18.xml
new file mode 100644
index 00000000..74bf35e3
--- /dev/null
+++ b/dist/iidx/launcher-18.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook4.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-19.xml b/dist/iidx/launcher-19.xml
new file mode 100644
index 00000000..1749cfbd
--- /dev/null
+++ b/dist/iidx/launcher-19.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook5.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-20.xml b/dist/iidx/launcher-20.xml
new file mode 100644
index 00000000..7af7ce4f
--- /dev/null
+++ b/dist/iidx/launcher-20.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook6.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-21.xml b/dist/iidx/launcher-21.xml
new file mode 100644
index 00000000..502407b7
--- /dev/null
+++ b/dist/iidx/launcher-21.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook7.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-22.xml b/dist/iidx/launcher-22.xml
new file mode 100644
index 00000000..502407b7
--- /dev/null
+++ b/dist/iidx/launcher-22.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook7.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-23.xml b/dist/iidx/launcher-23.xml
new file mode 100644
index 00000000..502407b7
--- /dev/null
+++ b/dist/iidx/launcher-23.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook7.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-24.xml b/dist/iidx/launcher-24.xml
new file mode 100644
index 00000000..502407b7
--- /dev/null
+++ b/dist/iidx/launcher-24.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook7.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-25.xml b/dist/iidx/launcher-25.xml
new file mode 100644
index 00000000..733a8807
--- /dev/null
+++ b/dist/iidx/launcher-25.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 134217728
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook8.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-26.xml b/dist/iidx/launcher-26.xml
new file mode 100644
index 00000000..733a8807
--- /dev/null
+++ b/dist/iidx/launcher-26.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 134217728
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook8.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-27.xml b/dist/iidx/launcher-27.xml
new file mode 100644
index 00000000..f903fa68
--- /dev/null
+++ b/dist/iidx/launcher-27.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 134217728
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook9.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-28.xml b/dist/iidx/launcher-28.xml
new file mode 100644
index 00000000..f903fa68
--- /dev/null
+++ b/dist/iidx/launcher-28.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 134217728
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook9.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-29.xml b/dist/iidx/launcher-29.xml
new file mode 100644
index 00000000..f903fa68
--- /dev/null
+++ b/dist/iidx/launcher-29.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 134217728
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook9.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/launcher-30.xml b/dist/iidx/launcher-30.xml
new file mode 100644
index 00000000..f903fa68
--- /dev/null
+++ b/dist/iidx/launcher-30.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 134217728
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ bm2dx.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ iidxhook9.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/iidx/pcbid.xml b/dist/iidx/pcbid.xml
new file mode 100644
index 00000000..bc50cdee
--- /dev/null
+++ b/dist/iidx/pcbid.xml
@@ -0,0 +1,7 @@
+
+
+
+ 0101020304050607083F
+ 0101020304050607083F
+
+
\ No newline at end of file
diff --git a/dist/jb/ea3-ident.xml b/dist/jb/ea3-ident.xml
new file mode 100644
index 00000000..e24a9b92
--- /dev/null
+++ b/dist/jb/ea3-ident.xml
@@ -0,0 +1,10 @@
+
+
+
+ LDJ
+ J
+ A
+ A
+ 2022082400
+
+
\ No newline at end of file
diff --git a/dist/jb/eamuse-server.xml b/dist/jb/eamuse-server.xml
new file mode 100644
index 00000000..bc706444
--- /dev/null
+++ b/dist/jb/eamuse-server.xml
@@ -0,0 +1,6 @@
+
+
+
+ http://localhost
+
+
\ No newline at end of file
diff --git a/dist/jb/gamestart-03.bat b/dist/jb/gamestart-03.bat
index 76acc782..39e1b8fd 100644
--- a/dist/jb/gamestart-03.bat
+++ b/dist/jb/gamestart-03.bat
@@ -1,11 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\ea3-config.xml copy prop\ea3-config.xml dev\nvram\ea3-config.xml
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -H 33554432 -K jbhook2.dll jubeat.dll -v
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-03.xml -v %*
\ No newline at end of file
diff --git a/dist/jb/gamestart-04.bat b/dist/jb/gamestart-04.bat
index 245e314d..14d95e78 100644
--- a/dist/jb/gamestart-04.bat
+++ b/dist/jb/gamestart-04.bat
@@ -1,11 +1,34 @@
@echo off
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
cd /d %~dp0
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\nvram\ea3-config.xml copy prop\ea3-config.xml dev\nvram\ea3-config.xml
-if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
-if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
-if not exist dev\raw mkdir dev\raw
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
-launcher -H 33554432 -K jbhook3.dll jubeat.dll
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-04.xml %*
\ No newline at end of file
diff --git a/dist/jb/launcher-03.xml b/dist/jb/launcher-03.xml
new file mode 100644
index 00000000..095b2f62
--- /dev/null
+++ b/dist/jb/launcher-03.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 33554432
+ 33554432
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ jubeat.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ jbhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/jb/launcher-04.xml b/dist/jb/launcher-04.xml
new file mode 100644
index 00000000..1c85a3c8
--- /dev/null
+++ b/dist/jb/launcher-04.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 33554432
+ 33554432
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ jubeat.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ jbhook3.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/jb/pcbid.xml b/dist/jb/pcbid.xml
new file mode 100644
index 00000000..bc50cdee
--- /dev/null
+++ b/dist/jb/pcbid.xml
@@ -0,0 +1,7 @@
+
+
+
+ 0101020304050607083F
+ 0101020304050607083F
+
+
\ No newline at end of file
diff --git a/dist/sdvx/ea3-ident.xml b/dist/sdvx/ea3-ident.xml
new file mode 100644
index 00000000..e24a9b92
--- /dev/null
+++ b/dist/sdvx/ea3-ident.xml
@@ -0,0 +1,10 @@
+
+
+
+ LDJ
+ J
+ A
+ A
+ 2022082400
+
+
\ No newline at end of file
diff --git a/dist/sdvx/eamuse-server.xml b/dist/sdvx/eamuse-server.xml
new file mode 100644
index 00000000..bc706444
--- /dev/null
+++ b/dist/sdvx/eamuse-server.xml
@@ -0,0 +1,6 @@
+
+
+
+ http://localhost
+
+
\ No newline at end of file
diff --git a/dist/sdvx/gamestart.bat b/dist/sdvx/gamestart.bat
index a286325c..4e97b924 100644
--- a/dist/sdvx/gamestart.bat
+++ b/dist/sdvx/gamestart.bat
@@ -8,3 +8,38 @@ if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin
if not exist dev\raw mkdir dev\raw
launcher -K sdvxhook.dll soundvoltex.dll %*
+
+@echo off
+
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
+
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
+)
+
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher.xml %*
\ No newline at end of file
diff --git a/dist/sdvx/launcher.xml b/dist/sdvx/launcher.xml
new file mode 100644
index 00000000..4876ca76
--- /dev/null
+++ b/dist/sdvx/launcher.xml
@@ -0,0 +1,75 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 16777216
+ 16777216
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ soundvoltex.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ sdvxhook.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/sdvx/pcbid.xml b/dist/sdvx/pcbid.xml
new file mode 100644
index 00000000..bc50cdee
--- /dev/null
+++ b/dist/sdvx/pcbid.xml
@@ -0,0 +1,7 @@
+
+
+
+ 0101020304050607083F
+ 0101020304050607083F
+
+
\ No newline at end of file
diff --git a/dist/sdvx5/ea3-ident.xml b/dist/sdvx5/ea3-ident.xml
new file mode 100644
index 00000000..e24a9b92
--- /dev/null
+++ b/dist/sdvx5/ea3-ident.xml
@@ -0,0 +1,10 @@
+
+
+
+ LDJ
+ J
+ A
+ A
+ 2022082400
+
+
\ No newline at end of file
diff --git a/dist/sdvx5/eamuse-server.xml b/dist/sdvx5/eamuse-server.xml
new file mode 100644
index 00000000..bc706444
--- /dev/null
+++ b/dist/sdvx5/eamuse-server.xml
@@ -0,0 +1,6 @@
+
+
+
+ http://localhost
+
+
\ No newline at end of file
diff --git a/dist/sdvx5/gamestart-cn.bat b/dist/sdvx5/gamestart-cn.bat
index 8435bd73..3976baf0 100644
--- a/dist/sdvx5/gamestart-cn.bat
+++ b/dist/sdvx5/gamestart-cn.bat
@@ -1,17 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\c.dest echo $null >> dev\raw\c.dest
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-launcher -H 268435456 -K sdvxhook2-cn.dll soundvoltex.dll --config sdvxhook2-cn.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher-cn.xml --config sdvxhook2-cn.conf %*
\ No newline at end of file
diff --git a/dist/sdvx5/gamestart.bat b/dist/sdvx5/gamestart.bat
index c1b41ddd..9e77aaa2 100644
--- a/dist/sdvx5/gamestart.bat
+++ b/dist/sdvx5/gamestart.bat
@@ -1,16 +1,34 @@
@echo off
-cd /d %~dp0
-if not exist dev mkdir dev
-if not exist dev\e mkdir dev\e
-if not exist dev\g mkdir dev\g
-if not exist dev\nvram mkdir dev\nvram
-if not exist dev\raw mkdir dev\raw
-if not exist dev\raw\log mkdir dev\raw\log
-if not exist dev\raw\fscache mkdir dev\raw\fscache
+:: Game doesn't work properly when not run with administrator privileges
+>nul 2>&1 net session
-for /R prop\defaults %%D in (*.*) do (
- if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
+if %errorlevel% neq 0 (
+ echo This script requires administrative privileges.
+ echo Please run the script as an administrator.
+ pause
+ exit 1
)
-launcher -H 268435456 -K sdvxhook2.dll soundvoltex.dll --config sdvxhook2.conf %*
+:: Script expects to be located in a subfolder "bemanitools" in the root folder
+:: (contents/) next to the folders modules, data etc.
+cd /d %~dp0
+
+:: Script expects to be located in the root folder (contents/) next to the
+:: folders modules, data etc.
+set CONTENT_DIR=%CD%\..
+set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools
+set MODULES_DIR=%CONTENT_DIR%\modules
+
+:: Keep that data vanilla, no need to copy these around anymore
+:: Just add them to the env PATH so launcher can find the libs and game executable
+:: Remark: This also requires admin privileges to propage correctly to launcher
+set PATH=^
+%MODULES_DIR%;^
+%BEMANITOOLS_DIR%;^
+%PATH%
+
+:: Current working dir is the game's root folder
+cd /d %CONTENT_DIR%
+
+%BEMANITOOLS_DIR%\launcher %BEMANITOOLS_DIR%\launcher.xml --config sdvxhook2.conf %*
\ No newline at end of file
diff --git a/dist/sdvx5/launcher-cn.xml b/dist/sdvx5/launcher-cn.xml
new file mode 100644
index 00000000..4ec2939f
--- /dev/null
+++ b/dist/sdvx5/launcher-cn.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 268435456
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ soundvoltex.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ sdvxhook2-cn.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/sdvx5/launcher.xml b/dist/sdvx5/launcher.xml
new file mode 100644
index 00000000..3ae97c1e
--- /dev/null
+++ b/dist/sdvx5/launcher.xml
@@ -0,0 +1,74 @@
+
+
+
+ bemanitools_local_fs
+
+
+
+
+
+
+
+
+
+
+ prop/avs-config.xml
+ 268435456
+
+
+ info
+
+
+ /dev/nvram/ea3-config.xml
+
+
+ soundvoltex.dll
+
+
+
+
+
+
+
+
+ bemanitools/ea3-ident.xml
+ bemanitools/ea3-license.xml
+
+
+
+
+
+
+ .
+
+
+ dev/nvram
+ fs
+
+
+
+ dev/raw
+ fs
+
+
+
+
+
+
+
+ bemanitools/ea3-service.xml
+
+
+
+ sdvxhook2.dll
+
+
+
+
+
+
+
+ 0
+ 0
+
+
\ No newline at end of file
diff --git a/dist/sdvx5/pcbid.xml b/dist/sdvx5/pcbid.xml
new file mode 100644
index 00000000..bc50cdee
--- /dev/null
+++ b/dist/sdvx5/pcbid.xml
@@ -0,0 +1,7 @@
+
+
+
+ 0101020304050607083F
+ 0101020304050607083F
+
+
\ No newline at end of file
diff --git a/dist/shared/ea3-ident.xml b/dist/shared/ea3-ident.xml
new file mode 100644
index 00000000..ae4161ef
--- /dev/null
+++ b/dist/shared/ea3-ident.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ 000
+ A
+ A
+ A
+ 1969032100
+
+
\ No newline at end of file
diff --git a/dist/shared/ea3-license.xml b/dist/shared/ea3-license.xml
new file mode 100644
index 00000000..fef35346
--- /dev/null
+++ b/dist/shared/ea3-license.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ 0101020304050607083F
+ 0101020304050607083F
+
+
\ No newline at end of file
diff --git a/dist/shared/ea3-service.xml b/dist/shared/ea3-service.xml
new file mode 100644
index 00000000..ffaaa437
--- /dev/null
+++ b/dist/shared/ea3-service.xml
@@ -0,0 +1,7 @@
+
+
+
+
+ http://localhost
+
+
\ No newline at end of file
diff --git a/doc/ddrhook/ddrhook2.md b/doc/ddrhook/ddrhook2.md
index 38c0f44d..0cfddcbe 100644
--- a/doc/ddrhook/ddrhook2.md
+++ b/doc/ddrhook/ddrhook2.md
@@ -9,6 +9,8 @@ The following games are supported by this hook library:
* Dance Dance Revolution 2013
* Dance Dance Revolution 2014
* Dance Dance Revolution A
+* Dance Dance Revolution A20
+* Dance Dance Revolution A20+
Note that different builds of the same hook library are required to run the
different versions. See different distribution packages, e.g. `ddr-12.zip`,
diff --git a/src/imports/avs.h b/src/imports/avs.h
index ff48a33e..a2d439ec 100644
--- a/src/imports/avs.h
+++ b/src/imports/avs.h
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
enum property_create_flag {
PROPERTY_FLAG_READ = 0x1,
@@ -26,18 +27,39 @@ enum property_node_traversal {
};
enum property_type {
- PROPERTY_TYPE_VOID = 1,
- PROPERTY_TYPE_S8 = 2,
- PROPERTY_TYPE_U8 = 3,
- PROPERTY_TYPE_S16 = 4,
- PROPERTY_TYPE_U16 = 5,
- PROPERTY_TYPE_S32 = 6,
- PROPERTY_TYPE_U32 = 7,
- PROPERTY_TYPE_S64 = 8,
- PROPERTY_TYPE_U64 = 9,
- PROPERTY_TYPE_BIN = 10,
- PROPERTY_TYPE_STR = 11,
- PROPERTY_TYPE_BOOL = 52
+ PROPERTY_TYPE_VOID = 0x01,
+ PROPERTY_TYPE_S8 = 0x02,
+ PROPERTY_TYPE_U8 = 0x03,
+ PROPERTY_TYPE_S16 = 0x04,
+ PROPERTY_TYPE_U16 = 0x05,
+ PROPERTY_TYPE_S32 = 0x06,
+ PROPERTY_TYPE_U32 = 0x07,
+ PROPERTY_TYPE_S64 = 0x08,
+ PROPERTY_TYPE_U64 = 0x09,
+ PROPERTY_TYPE_BIN = 0x0A,
+ PROPERTY_TYPE_STR = 0x0B,
+ PROPERTY_TYPE_IP4 = 0x0C,
+ PROPERTY_TYPE_TIME = 0x0D,
+ PROPERTY_TYPE_FLOAT = 0x0E,
+ PROPERTY_TYPE_DOUBLE = 0x0F,
+ PROPERTY_TYPE_4U8 = 0x25,
+ PROPERTY_TYPE_ATTR = 0x2E,
+ PROPERTY_TYPE_BOOL = 0x34,
+
+ // Missing __type attribute
+ PROPERTY_TYPE_VOID_WITH_ATTRIBUTES = 0x40 | PROPERTY_TYPE_VOID,
+ PROPERTY_TYPE_ARRAY_S8 = 0x40 | PROPERTY_TYPE_S8,
+ PROPERTY_TYPE_ARRAY_U8 = 0x40 | PROPERTY_TYPE_U8,
+ PROPERTY_TYPE_ARRAY_S16 = 0x40 | PROPERTY_TYPE_S16,
+ PROPERTY_TYPE_ARRAY_U16 = 0x40 | PROPERTY_TYPE_U16,
+ PROPERTY_TYPE_ARRAY_S32 = 0x40 | PROPERTY_TYPE_S32,
+ PROPERTY_TYPE_ARRAY_U32 = 0x40 | PROPERTY_TYPE_U32,
+ PROPERTY_TYPE_ARRAY_S64 = 0x40 | PROPERTY_TYPE_S64,
+ PROPERTY_TYPE_ARRAY_U64 = 0x40 | PROPERTY_TYPE_U64,
+ PROPERTY_TYPE_ARRAY_TIME = 0x40 | PROPERTY_TYPE_TIME,
+ PROPERTY_TYPE_ARRAY_BOOL = 0x40 | PROPERTY_TYPE_BOOL,
+
+ PROPERTY_TYPE_STR_WITH_ATTRIBUTES = 0x40 | PROPERTY_TYPE_STR,
};
struct property;
@@ -66,6 +88,7 @@ enum psmap_type {
PSMAP_TYPE_STR = 10,
PSMAP_TYPE_ATTR = 45,
PSMAP_TYPE_BOOL = 50,
+ PSMAP_TYPE_TERMINATOR = 0xFF,
};
#define PSMAP_FLAG_HAVE_DEFAULT 0x01
@@ -102,7 +125,7 @@ struct property_psmap {
#define PSMAP_END \
{ \
- 0xFF, 0, 0, 0, NULL, 0 \
+ PSMAP_TYPE_TERMINATOR, 0, 0, 0, NULL, 0 \
} \
} \
;
@@ -160,6 +183,11 @@ void avs_boot(
void avs_shutdown(void);
+typedef uint32_t avs_desc;
+typedef int avs_error;
+
+#define AVS_IS_ERROR(x) x < 0
+
void log_body_fatal(const char *module, const char *fmt, ...);
void log_body_info(const char *module, const char *fmt, ...);
void log_body_misc(const char *module, const char *fmt, ...);
@@ -187,6 +215,7 @@ int property_insert_read(
uint32_t context);
int property_mem_write(struct property *prop, void *bytes, int nbytes);
void *property_desc_to_buffer(struct property *prop);
+avs_error property_query_size(struct property *prop);
void property_file_write(struct property *prop, const char *path);
int property_set_flag(struct property *prop, int flags, int mask);
void property_destroy(struct property *prop);
@@ -203,8 +232,8 @@ int property_psmap_export(
const struct property_psmap *psmap);
struct property_node *property_node_clone(
- struct property *new_parent,
- int unk0,
+ struct property *parent_prop,
+ struct property_node *parent_node,
struct property_node *src,
bool deep);
struct property_node *property_node_create(
@@ -226,15 +255,73 @@ void property_node_remove(struct property_node *node);
enum property_type property_node_type(struct property_node *node);
struct property_node *property_node_traversal(
struct property_node *node, enum property_node_traversal direction);
-void property_node_datasize(struct property_node *node);
+int property_node_datasize(struct property_node *node);
+avs_error property_node_read(struct property_node *node, enum property_type type, void* data, uint32_t data_size);
+
+static inline void property_remove(struct property *prop, struct property_node *node, const char *path)
+{
+ struct property_node *cur = property_search(prop, node, path);
+ while (cur) {
+ struct property_node *next = property_node_traversal(node, TRAVERSE_NEXT_SEARCH_RESULT);
+ property_node_remove(cur);
+ cur = next;
+ }
+}
bool std_getenv(const char *key, char *val, uint32_t nbytes);
void std_setenv(const char *key, const char *val);
-void* avs_fs_open(const char* path, int mode, int flags);
+struct avs_stat {
+ uint64_t st_atime;
+ uint64_t st_mtime;
+ uint64_t st_ctime;
+ uint32_t unk1;
+ uint32_t filesize;
+ struct stat padding;
+};
+
+#if AVS_VERSION <= 1306
+enum avs_file_mode {
+ AVS_FILE_READ = 0x00,
+ AVS_FILE_WRITE = 0x01,
+ AVS_FILE_READ_WRITE = 0x02,
+ AVS_FILE_CREATE = 0x10,
+ AVS_FILE_TRUNCATE = 0x20,
+ AVS_FILE_EXCLUSIVE = 0x80,
+};
+#else
+enum avs_file_mode {
+ AVS_FILE_READ = 0x01,
+ AVS_FILE_WRITE = 0x02,
+ AVS_FILE_CREATE = 0x10,
+ AVS_FILE_TRUNCATE = 0x20,
+ AVS_FILE_EXCLUSIVE = 0x80,
+};
+#endif
+
+enum avs_file_flag {
+ AVS_FILE_FLAG_SHARE_READ = 0x124,
+ AVS_FILE_FLAG_SHARE_WRITE = 0x92,
+};
+
+enum avs_seek_origin {
+ AVS_SEEK_SET = 0,
+ AVS_SEEK_CUR = 1,
+ AVS_SEEK_END = 2,
+};
+
+avs_desc avs_fs_open(const char *path, uint16_t mode, int flags);
+int avs_fs_close(avs_desc desc);
+size_t avs_fs_read(avs_desc desc, char *buf, uint32_t sz);
+int avs_fs_lseek(avs_desc desc, long pos, int whence);
+int avs_fs_lstat(const char *path, struct avs_stat *st);
+int avs_fs_copy(const char *src, const char *dest);
int avs_fs_addfs(void *filesys_struct);
int avs_fs_mount(
const char *mountpoint, const char *fsroot, const char *fstype, void *data);
+avs_desc avs_fs_opendir(const char *path);
+const char* avs_fs_readdir(avs_desc dir);
+void avs_fs_closedir(avs_desc dir);
bool avs_is_active();
diff --git a/src/imports/dwarfstack.h b/src/imports/dwarfstack.h
new file mode 100644
index 00000000..ba2d23c6
--- /dev/null
+++ b/src/imports/dwarfstack.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2013-2019 Hannes Domani
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef __DWARFSTACK_H__
+#define __DWARFSTACK_H__
+
+#include
+
+
+#if defined(DWST_STATIC)
+#define EXPORT
+#elif defined(DWST_SHARED)
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT __declspec(dllimport)
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// dwstCallback(): callback function
+// addr: stack address
+// filename: source file location
+// lineno: line number
+// funcname: function name
+// context: user-provided pointer (callbackContext)
+// columnno: column number
+typedef void dwstCallback(
+ uint64_t addr,const char *filename,int lineno,const char *funcname,
+ void *context,int columnno );
+
+typedef void dwstCallbackW(
+ uint64_t addr,const wchar_t *filename,int lineno,const char *funcname,
+ void *context,int columnno );
+
+// special values for lineno:
+
+// DWST_BASE_ADDR: inform about the used image base address
+// (important in case it's not the same as the preferred image base address)
+// addr: used image base address
+// filename: executable location
+#define DWST_BASE_ADDR 0
+
+// DWST_NO_DBG_SYM: no debug information available
+// addr: stack address
+// filename: executable location
+#define DWST_NO_DBG_SYM -1
+
+// DWST_NO_SRC_FILE: no source file information available
+// addr: stack address
+// filename: executable location
+#define DWST_NO_SRC_FILE -2
+
+// DWST_NOT_FOUND: no information available (invalid address?)
+// addr: stack address
+// filename: executable location
+#define DWST_NOT_FOUND -3
+
+
+// dwstOfFile(): stack information of file
+// name: executable location
+// imageBase: used image base address
+// addr: stack addresses
+// count: number of addresses
+// callbackFunc: callback function
+// callbackContext: user-provided pointer (context)
+// (for example see examples/addr2line/)
+EXPORT int dwstOfFile(
+ const char *name,uint64_t imageBase,
+ uint64_t *addr,int count,
+ dwstCallback *callbackFunc,void *callbackContext );
+
+EXPORT int dwstOfFileW(
+ const wchar_t *name,uint64_t imageBase,
+ uint64_t *addr,int count,
+ dwstCallbackW *callbackFunc,void *callbackContext );
+
+
+// dwstOfProcess(): stack information of current process
+// addr: stack addresses
+// count: number of addresses
+// callbackFunc: callback function
+// callbackContext: user-provided pointer (context)
+EXPORT int dwstOfProcess(
+ uintptr_t *addr,int count,
+ dwstCallback *callbackFunc,void *callbackContext );
+
+EXPORT int dwstOfProcessW(
+ uintptr_t *addr,int count,
+ dwstCallbackW *callbackFunc,void *callbackContext );
+
+
+// dwstOfLocation(): stack information of current location
+// callbackFunc: callback function
+// callbackContext: user-provided pointer (context)
+// (for example see examples/location/)
+EXPORT int dwstOfLocation(
+ dwstCallback *callbackFunc,void *callbackContext );
+
+EXPORT int dwstOfLocationW(
+ dwstCallbackW *callbackFunc,void *callbackContext );
+
+
+// dwstOfException(): stack information of exception
+// context: ContextRecord of exception
+// callbackFunc: callback function
+// callbackContext: user-provided pointer (context)
+// (for example see examples/exception/)
+EXPORT int dwstOfException(
+ void *context,
+ dwstCallback *callbackFunc,void *callbackContext );
+
+EXPORT int dwstOfExceptionW(
+ void *context,
+ dwstCallbackW *callbackFunc,void *callbackContext );
+
+
+// dwstExceptionDialog(): show dialog on unhandled exception
+// extraInfo: extra information shown in dialog
+// (for example see examples/exception-dialog/)
+EXPORT void dwstExceptionDialog(
+ const char *extraInfo );
+
+EXPORT void dwstExceptionDialogW(
+ const wchar_t *extraInfo );
+
+
+#ifndef DWST_STATIC
+// dwstDemangle(): demangle gcc style c++ symbols
+// mangled: mangled name
+// demangled: demangled name
+// length: size of demangled buffer
+EXPORT size_t dwstDemangle(
+ const char *mangled,
+ char *demangled,size_t length );
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/imports/import_32_0_avs.def b/src/imports/import_32_0_avs.def
index cb2ea9d1..273e5be8 100644
--- a/src/imports/import_32_0_avs.def
+++ b/src/imports/import_32_0_avs.def
@@ -2,6 +2,12 @@ LIBRARY libavs-win32
EXPORTS
avs_boot
+ avs_fs_close
+ avs_fs_copy
+ avs_fs_lseek
+ avs_fs_lstat
+ avs_fs_open
+ avs_fs_read
avs_net_ctrl
avs_shutdown
avs_thread_create
@@ -26,6 +32,7 @@ EXPORTS
property_node_clone
property_node_create
property_node_name
+ property_node_read
property_node_refer
property_node_remove
property_node_type
diff --git a/src/imports/import_32_1002_avs.def b/src/imports/import_32_1002_avs.def
index 6d1fd136..e2ff5ae5 100644
--- a/src/imports/import_32_1002_avs.def
+++ b/src/imports/import_32_1002_avs.def
@@ -2,6 +2,15 @@ LIBRARY libavs-win32
EXPORTS
avs_boot
+ avs_fs_close
+ avs_fs_copy
+ avs_fs_lseek
+ avs_fs_lstat
+ avs_fs_open
+ avs_fs_read
+ avs_fs_opendir
+ avs_fs_readdir
+ avs_fs_closedir
avs_net_ctrl
avs_shutdown
avs_thread_create
@@ -27,11 +36,13 @@ EXPORTS
property_node_create
property_node_datasize
property_node_name
+ property_node_read
property_node_refer
property_node_remove
property_node_type
property_node_traversal
property_node_refdata
+ property_query_size
property_psmap_export
property_psmap_import
std_getenv
diff --git a/src/imports/import_32_1101_avs.def b/src/imports/import_32_1101_avs.def
index cfc6f9b5..10c59e4f 100644
--- a/src/imports/import_32_1101_avs.def
+++ b/src/imports/import_32_1101_avs.def
@@ -2,6 +2,15 @@ LIBRARY libavs-win32
EXPORTS
avs_boot @22 NONAME
+ avs_fs_close @60 NONAME
+ avs_fs_copy @63 NONAME
+ avs_fs_lseek @70 NONAME
+ avs_fs_lstat @71 NONAME
+ avs_fs_open @75 NONAME
+ avs_fs_read @77 NONAME
+ avs_fs_opendir @76 NONAME
+ avs_fs_readdir @78 NONAME
+ avs_fs_closedir @61 NONAME
avs_net_ctrl @107 NONAME
avs_shutdown @140 NONAME
avs_thread_create @156 NONAME
@@ -19,8 +28,15 @@ EXPORTS
property_insert_read @255 NONAME
property_node_create @266 NONAME
property_node_datasize @267 NONAME
+ property_node_name @274 NONAME
+ property_node_read @276 NONAME
property_node_refer @278 NONAME
property_node_remove @279 NONAME
+ property_node_type @282 NONAME
+ property_node_clone @280 NONAME
+ property_node_traversal @282 NONAME
+ property_node_refdata @277 NONAME
+ property_query_size @290 NONAME
property_psmap_import @288 NONAME
property_psmap_export @287 NONAME
property_read_query_memsize @291 NONAME
diff --git a/src/imports/import_32_1304_avs.def b/src/imports/import_32_1304_avs.def
index 489944a7..f83d5a5f 100644
--- a/src/imports/import_32_1304_avs.def
+++ b/src/imports/import_32_1304_avs.def
@@ -2,7 +2,15 @@ LIBRARY libavs-win32
EXPORTS
avs_boot @237 NONAME
+ avs_fs_close @276 NONAME
+ avs_fs_copy @283 NONAME
+ avs_fs_lseek @16 NONAME
+ avs_fs_lstat @97 NONAME
avs_fs_open @178 NONAME
+ avs_fs_read @306 NONAME
+ avs_fs_opendir @216 NONAME
+ avs_fs_readdir @130 NONAME
+ avs_fs_closedir @131 NONAME
avs_net_ctrl @15 NONAME
avs_shutdown @333 NONAME
avs_thread_create @183 NONAME
@@ -19,8 +27,15 @@ EXPORTS
property_insert_read @23 NONAME
property_node_create @316 NONAME
property_node_datasize @249 NONAME
+ property_node_name @255 NONAME
+ property_node_read @2 NONAME
property_node_refer @268 NONAME
property_node_remove @129 NONAME
+ property_node_type @329 NONAME
+ property_node_clone @130 NONAME
+ property_node_traversal @93 NONAME
+ property_node_refdata @330 NONAME == XC058ba5000151
+ property_query_size @250 NONAME == XC058ba5000101
property_psmap_import @102 NONAME
property_psmap_export @110 NONAME
property_read_query_memsize @100 NONAME
diff --git a/src/imports/import_32_1306_avs-ea3.def b/src/imports/import_32_1306_avs-ea3.def
new file mode 100644
index 00000000..2606209e
--- /dev/null
+++ b/src/imports/import_32_1306_avs-ea3.def
@@ -0,0 +1,5 @@
+LIBRARY libavs-win32-ea3
+
+EXPORTS
+ ea3_boot @94 NONAME
+ ea3_shutdown @97 NONAME
diff --git a/src/imports/import_32_1306_avs.def b/src/imports/import_32_1306_avs.def
new file mode 100644
index 00000000..f963ec88
--- /dev/null
+++ b/src/imports/import_32_1306_avs.def
@@ -0,0 +1,44 @@
+LIBRARY libavs-win32
+
+EXPORTS
+ avs_boot @237 NONAME == XC058ba50000f4
+ avs_fs_close @276 NONAME == XC058ba500011b
+ avs_fs_copy @283 NONAME == XC058ba5000122
+ avs_fs_lseek @16 NONAME == XC058ba500000f
+ avs_fs_lstat @97 NONAME == XC058ba5000063
+ avs_fs_open @178 NONAME == XC058ba50000b6
+ avs_fs_read @306 NONAME == XC058ba5000139
+ avs_fs_opendir @216 NONAME == XC058ba50000dd
+ avs_fs_readdir @130 NONAME == XC058ba5000086
+ avs_fs_closedir @131 NONAME == XC058ba5000087
+ avs_net_ctrl @15 NONAME == XC058ba500000e
+ avs_shutdown @333 NONAME == XC058ba5000154
+ avs_thread_create @183 NONAME == XC058ba50000bb
+ avs_thread_destroy @76 NONAME == XC058ba500004e
+ avs_thread_exit @147 NONAME == XC058ba5000097
+ avs_thread_join @92 NONAME == XC058ba500005e
+ log_body_misc @44 NONAME == XC058ba500002d
+ log_body_info @339 NONAME == XC058ba500015a
+ log_body_warning @219 NONAME == XC058ba50000e1
+ log_body_fatal @128 NONAME == XC058ba5000084
+ property_create @256 NONAME == XC058ba5000107
+ property_desc_to_buffer @201 NONAME == XC058ba50000cd
+ property_destroy @264 NONAME == XC058ba500010f
+ property_insert_read @23 NONAME == XC058ba5000016
+ property_node_create @316 NONAME == XC058ba5000143
+ property_node_datasize @249 NONAME == XC058ba5000100
+ property_node_name @255 NONAME == XC058ba5000106
+ property_node_read @2 NONAME == XC058ba5000001
+ property_node_refer @268 NONAME == XC058ba5000113
+ property_node_remove @129 NONAME == XC058ba5000085
+ property_node_type @329 NONAME == XC058ba5000150
+ property_node_clone @252 NONAME == XC058ba5000103
+ property_node_traversal @93 NONAME == XC058ba500005f
+ property_node_refdata @330 NONAME == XC058ba5000151
+ property_query_size @250 NONAME == XC058ba5000101
+ property_psmap_import @102 NONAME == XC058ba5000068
+ property_psmap_export @110 NONAME == XC058ba5000071
+ property_read_query_memsize @100 NONAME == XC058ba5000066
+ property_search @244 NONAME == XC058ba50000fb
+ std_getenv @226 NONAME == XC058ba50000e8
+ std_setenv @114 NONAME == XC058ba5000075
diff --git a/src/imports/import_32_1403_avs.def b/src/imports/import_32_1403_avs.def
index 32d68b11..de171c12 100644
--- a/src/imports/import_32_1403_avs.def
+++ b/src/imports/import_32_1403_avs.def
@@ -2,6 +2,15 @@ LIBRARY libavs-win32
EXPORTS
avs_boot @298 NONAME
+ avs_fs_close @573 NONAME == XC0bbe97000119
+ avs_fs_copy @573 NONAME == XC0bbe97000120
+ avs_fs_lseek @573 NONAME ==
+ avs_fs_lstat @573 NONAME == XC0bbe9700005f
+ avs_fs_open @573 NONAME == XC0bbe970000b3
+ avs_fs_read @573 NONAME ==
+ avs_fs_opendir @573 NONAME == XC0bbe970000db
+ avs_fs_readdir @573 NONAME ==
+ avs_fs_closedir @573 NONAME ==
avs_net_ctrl @100 NONAME
avs_shutdown @299 NONAME
avs_thread_create @6 NONAME
@@ -15,7 +24,14 @@ EXPORTS
property_desc_to_buffer @131 NONAME
property_destroy @130 NONAME
property_insert_read @133 NONAME
+ property_node_name @573 NONAME ==
+ property_node_read @573 NONAME ==
property_node_remove @148 NONAME
+ property_node_type @573 NONAME ==
+ property_node_clone @149 NONAME
+ property_node_traversal @151 NONAME
+ property_node_refdata @573 NONAME ==
+ property_query_size @573 NONAME ==
property_psmap_import @163 NONAME
property_psmap_export @164 NONAME
property_read_query_memsize @161 NONAME
diff --git a/src/imports/import_32_1508_avs.def b/src/imports/import_32_1508_avs.def
index 05419ed7..d1625126 100644
--- a/src/imports/import_32_1508_avs.def
+++ b/src/imports/import_32_1508_avs.def
@@ -5,8 +5,13 @@ EXPORTS
avs_fs_close @65 NONAME
avs_fs_lseek @59 NONAME
avs_fs_lseek64 @60 NONAME
+ avs_fs_lstat @79 NONAME
avs_fs_open @58 NONAME
avs_fs_read @61 NONAME
+ avs_fs_copy @81 NONAME
+ avs_fs_opendir @72 NONAME == XCd229cc0000f0
+ avs_fs_readdir @73 NONAME == XCd229cc0000bb
+ avs_fs_closedir @74 NONAME == XCd229cc0000b8
avs_net_ctrl @98 NONAME
avs_shutdown @286 NONAME
avs_thread_create @6 NONAME
@@ -22,8 +27,16 @@ EXPORTS
property_destroy @128 NONAME
property_insert_read @131 NONAME
property_node_create @145 NONAME
+ property_node_name @150 NONAME
+ property_node_read @154 NONAME == XCd229cc0000f3
property_node_refer @158 NONAME
property_node_remove @146 NONAME
+ property_node_type @151 NONAME == XCd229cc000071
+ property_node_clone @147 NONAME
+ property_node_traversal @149 NONAME
+ property_node_refdata @148 NONAME == XCd229cc00009f
+ property_node_datasize @153 NONAME == XCd229cc000083
+ property_query_size @142 NONAME == XCd229cc000032
property_psmap_export @162 NONAME
property_psmap_import @161 NONAME
property_read_query_memsize @159 NONAME
diff --git a/src/imports/import_32_1601_avs.def b/src/imports/import_32_1601_avs.def
index e260a8c6..74332d48 100644
--- a/src/imports/import_32_1601_avs.def
+++ b/src/imports/import_32_1601_avs.def
@@ -1,6 +1,15 @@
LIBRARY libavs-win32
EXPORTS
+ avs_fs_close @65 NONAME
+ avs_fs_copy @81 NONAME
+ avs_fs_lseek @59 NONAME
+ avs_fs_lstat @79 NONAME
+ avs_fs_open @58 NONAME
+ avs_fs_read @61 NONAME
+ avs_fs_opendir @72 NONAME == XCnbrep7000047
+ avs_fs_readdir @73 NONAME == XCnbrep7000048
+ avs_fs_closedir @74 NONAME == XCnbrep7000049
avs_thread_create @5 NONAME
avs_thread_destroy @7 NONAME
avs_thread_exit @11 NONAME
@@ -12,7 +21,15 @@ EXPORTS
property_insert_read @128 NONAME
property_search @141 NONAME
property_node_create @142 NONAME
+ property_node_name @147 NONAME == XCnbrep7000092
property_node_remove @143 NONAME
+ property_node_type @148 NONAME == XCnbrep7000093
+ property_node_clone @144 NONAME
+ property_node_traversal @146 NONAME
+ property_node_refdata @145 NONAME == XCnbrep7000090
+ property_node_datasize @150 NONAME == XCnbrep7000095
+ property_node_read @151 NONAME == XCnbrep7000096
+ property_query_size @139 NONAME == XCnbrep700008a
property_node_refer @155 NONAME
property_read_query_memsize @156 NONAME
property_psmap_export @159 NONAME
diff --git a/src/imports/import_32_1603_avs.def b/src/imports/import_32_1603_avs.def
index 98f5fe7a..21f55c1e 100644
--- a/src/imports/import_32_1603_avs.def
+++ b/src/imports/import_32_1603_avs.def
@@ -1,6 +1,15 @@
LIBRARY libavs-win32
EXPORTS
+ avs_fs_close @86 NONAME == XCnbrep7000055
+ avs_fs_copy @102 NONAME == XCnbrep7000065
+ avs_fs_lseek @80 NONAME == XCnbrep700004f
+ avs_fs_lstat @100 NONAME == XCnbrep7000063
+ avs_fs_open @79 NONAME == XCnbrep700004e
+ avs_fs_read @82 NONAME == XCnbrep7000051
+ avs_fs_opendir @93 NONAME == XCnbrep700005c
+ avs_fs_readdir @94 NONAME == XCnbrep700005d
+ avs_fs_closedir @95 NONAME == XCnbrep700005e
avs_thread_create @5 NONAME
avs_thread_destroy @7 NONAME
avs_thread_exit @11 NONAME
@@ -12,7 +21,15 @@ EXPORTS
property_insert_read @149 NONAME
property_search @162 NONAME
property_node_create @163 NONAME
+ property_node_name @168 NONAME == XCnbrep70000a7
property_node_remove @164 NONAME
+ property_node_type @169 NONAME == XCnbrep70000a8
+ property_node_clone @165 NONAME
+ property_node_traversal @167 NONAME
+ property_node_refdata @166 NONAME == XCnbrep70000a5
+ property_node_datasize @171 NONAME == XCnbrep70000aa
+ property_query_size @160 NONAME == XCnbrep700009f
+ property_node_read @172 NONAME == XCnbrep70000ab
property_node_refer @176 NONAME
property_read_query_memsize @177 NONAME
property_psmap_import @179 NONAME
diff --git a/src/imports/import_32_1700_avs.def b/src/imports/import_32_1700_avs.def
index d8944d9b..7dc4eaa8 100644
--- a/src/imports/import_32_1700_avs.def
+++ b/src/imports/import_32_1700_avs.def
@@ -6,7 +6,16 @@ EXPORTS
avs_thread_exit @11 NONAME
avs_thread_join @12 NONAME
avs_fs_addfs @73 NONAME
+ avs_fs_close @86 NONAME == XCgsqzn0000055
+ avs_fs_copy @102 NONAME == XCgsqzn0000065
+ avs_fs_lseek @80 NONAME == XCgsqzn000004f
+ avs_fs_lstat @100 NONAME == XCgsqzn0000063
avs_fs_mount @76 NONAME
+ avs_fs_open @79 NONAME == XCgsqzn000004e
+ avs_fs_read @82 NONAME == XCgsqzn0000051
+ avs_fs_opendir @93 NONAME == XCgsqzn000005c
+ avs_fs_readdir @94 NONAME == XCgsqzn000005d
+ avs_fs_closedir @95 NONAME == XCgsqzn000005e
avs_net_ctrl @119 NONAME
property_create @145 NONAME
property_destroy @146 NONAME
@@ -14,7 +23,15 @@ EXPORTS
property_insert_read @149 NONAME
property_search @162 NONAME
property_node_create @163 NONAME
+ property_node_name @168 NONAME == XCgsqzn00000a7
property_node_remove @164 NONAME
+ property_node_type @169 NONAME == XCgsqzn00000a8
+ property_node_clone @165 NONAME
+ property_node_traversal @167 NONAME
+ property_node_refdata @166 NONAME == XCgsqzn00000a5
+ property_node_datasize @171 NONAME == XCgsqzn00000aa
+ property_node_read @172 NONAME == XCgsqzn00000ab
+ property_query_size @160 NONAME == XCgsqzn000009f
property_node_refer @176 NONAME
property_read_query_memsize @177 NONAME
property_psmap_import @179 NONAME
diff --git a/src/imports/import_32_803_avs.def b/src/imports/import_32_803_avs.def
index a7f59b51..37f2b3e6 100644
--- a/src/imports/import_32_803_avs.def
+++ b/src/imports/import_32_803_avs.def
@@ -2,6 +2,12 @@ LIBRARY libavs-win32
EXPORTS
avs_boot
+ avs_fs_close
+ avs_fs_copy
+ avs_fs_lseek
+ avs_fs_lstat
+ avs_fs_open
+ avs_fs_read
avs_net_ctrl
avs_shutdown
avs_thread_create
@@ -27,6 +33,7 @@ EXPORTS
property_node_create
property_node_datasize
property_node_name
+ property_node_read
property_node_refer
property_node_remove
property_node_type
diff --git a/src/imports/import_32_indep_dwarfstack.def b/src/imports/import_32_indep_dwarfstack.def
new file mode 100644
index 00000000..71f1aaf5
--- /dev/null
+++ b/src/imports/import_32_indep_dwarfstack.def
@@ -0,0 +1,13 @@
+LIBRARY dwarfstack
+
+EXPORTS
+ dwstOfFile @ 441
+ dwstOfFileW @ 443
+ dwstOfProcess @ 446
+ dwstOfProcessW @ 448
+ dwstOfLocation @ 444
+ dwstOfLocationW @ 445
+ dwstOfException @ 438
+ dwstOfExceptionW @ 440
+ dwstExceptionDialog @ 436
+ dwstExceptionDialogW @ 437
\ No newline at end of file
diff --git a/src/imports/import_64_1508_avs.def b/src/imports/import_64_1508_avs.def
index bc9fbf06..6aeaba1d 100644
--- a/src/imports/import_64_1508_avs.def
+++ b/src/imports/import_64_1508_avs.def
@@ -3,10 +3,15 @@ LIBRARY libavs-win64
EXPORTS
avs_boot @285 NONAME
avs_fs_close @65 NONAME
+ avs_fs_copy @81 NONAME
avs_fs_lseek @59 NONAME
avs_fs_lseek64 @60 NONAME
+ avs_fs_lstat @79 NONAME
avs_fs_open @58 NONAME
avs_fs_read @61 NONAME
+ avs_fs_opendir @72 NONAME == XCd229cc0000f0
+ avs_fs_readdir @73 NONAME == XCd229cc0000bb
+ avs_fs_closedir @74 NONAME == XCd229cc0000b8
avs_net_ctrl @98 NONAME
avs_shutdown @286 NONAME
avs_thread_create @6 NONAME
@@ -22,8 +27,16 @@ EXPORTS
property_destroy @128 NONAME
property_insert_read @131 NONAME
property_node_create @145 NONAME
+ property_node_name @150 NONAME
+ property_node_read @154 NONAME == XCd229cc0000f3
property_node_refer @158 NONAME
property_node_remove @146 NONAME
+ property_node_type @151 NONAME == XCd229cc000071
+ property_node_clone @147 NONAME
+ property_node_traversal @149 NONAME
+ property_node_refdata @148 NONAME == XCd229cc00009f
+ property_node_datasize @153 NONAME == XCd229cc000083
+ property_query_size @142 NONAME == XCd229cc000032
property_psmap_export @162 NONAME
property_psmap_import @161 NONAME
property_read_query_memsize @159 NONAME
diff --git a/src/imports/import_64_1509_avs.def b/src/imports/import_64_1509_avs.def
index ae6110a2..fde35d65 100644
--- a/src/imports/import_64_1509_avs.def
+++ b/src/imports/import_64_1509_avs.def
@@ -3,10 +3,15 @@ LIBRARY libavs-win64
EXPORTS
avs_boot @285 NONAME
avs_fs_close @65 NONAME
+ avs_fs_copy @81 NONAME
avs_fs_lseek @59 NONAME
avs_fs_lseek64 @60 NONAME
+ avs_fs_lstat @78 NONAME
avs_fs_open @58 NONAME
avs_fs_read @61 NONAME
+ avs_fs_opendir @573 NONAME ==
+ avs_fs_readdir @573 NONAME ==
+ avs_fs_closedir @573 NONAME ==
avs_net_ctrl @98 NONAME
avs_shutdown @286 NONAME
avs_thread_create @6 NONAME
@@ -22,8 +27,16 @@ EXPORTS
property_destroy @128 NONAME
property_insert_read @131 NONAME
property_node_create @145 NONAME
+ property_node_name @573 NONAME ==
+ property_node_read @573 NONAME ==
+ property_query_size @573 NONAME ==
property_node_refer @158 NONAME
property_node_remove @146 NONAME
+ property_node_type @573 NONAME ==
+ property_node_clone @147 NONAME
+ property_node_traversal @149 NONAME
+ property_node_refdata @573 NONAME ==
+ property_node_datasize @573 NONAME ==
property_psmap_export @162 NONAME
property_psmap_import @161 NONAME
property_read_query_memsize @159 NONAME
diff --git a/src/imports/import_64_1601_avs.def b/src/imports/import_64_1601_avs.def
index 5bbe4528..418395f7 100644
--- a/src/imports/import_64_1601_avs.def
+++ b/src/imports/import_64_1601_avs.def
@@ -1,6 +1,15 @@
LIBRARY libavs-win64
EXPORTS
+ avs_fs_close @65 NONAME
+ avs_fs_copy @81 NONAME
+ avs_fs_lseek @59 NONAME
+ avs_fs_lstat @79 NONAME
+ avs_fs_open @58 NONAME
+ avs_fs_read @61 NONAME
+ avs_fs_opendir @72 NONAME == XCnbrep7000047
+ avs_fs_readdir @73 NONAME == XCnbrep7000048
+ avs_fs_closedir @74 NONAME == XCnbrep7000049
avs_thread_create @5 NONAME
avs_thread_destroy @7 NONAME
avs_thread_exit @11 NONAME
@@ -12,7 +21,15 @@ EXPORTS
property_insert_read @128 NONAME
property_search @141 NONAME
property_node_create @142 NONAME
+ property_node_name @147 NONAME == XCnbrep7000092
property_node_remove @143 NONAME
+ property_node_type @148 NONAME == XCnbrep7000093
+ property_node_clone @144 NONAME
+ property_node_traversal @146 NONAME
+ property_node_refdata @145 NONAME == XCnbrep7000090
+ property_node_datasize @150 NONAME == XCnbrep7000095
+ property_node_read @151 NONAME == XCnbrep7000096
+ property_query_size @139 NONAME == XCnbrep700008a
property_node_refer @155 NONAME
property_read_query_memsize @156 NONAME
property_psmap_export @159 NONAME
diff --git a/src/imports/import_64_1603_avs.def b/src/imports/import_64_1603_avs.def
index 0355922f..b106ab1b 100644
--- a/src/imports/import_64_1603_avs.def
+++ b/src/imports/import_64_1603_avs.def
@@ -1,6 +1,15 @@
LIBRARY libavs-win64
EXPORTS
+ avs_fs_close @86 NONAME == XCnbrep7000055
+ avs_fs_copy @102 NONAME == XCnbrep7000065
+ avs_fs_lseek @80 NONAME == XCnbrep700004f
+ avs_fs_lstat @100 NONAME == XCnbrep7000063
+ avs_fs_open @79 NONAME == XCnbrep700004e
+ avs_fs_read @82 NONAME == XCnbrep7000051
+ avs_fs_opendir @93 NONAME == XCnbrep700005c
+ avs_fs_readdir @94 NONAME == XCnbrep700005d
+ avs_fs_closedir @95 NONAME == XCnbrep700005e
avs_thread_create @5 NONAME
avs_thread_destroy @7 NONAME
avs_thread_exit @11 NONAME
@@ -12,7 +21,15 @@ EXPORTS
property_insert_read @149 NONAME
property_search @162 NONAME
property_node_create @163 NONAME
+ property_node_name @168 NONAME == XCnbrep70000a7
property_node_remove @164 NONAME
+ property_node_type @169 NONAME == XCnbrep70000a8
+ property_node_clone @165 NONAME
+ property_node_traversal @167 NONAME
+ property_node_refdata @166 NONAME == XCnbrep70000a5
+ property_node_datasize @171 NONAME == XCnbrep70000aa
+ property_node_read @172 NONAME == XCnbrep70000ab
+ property_query_size @160 NONAME == XCnbrep700009f
property_node_refer @176 NONAME
property_read_query_memsize @177 NONAME
property_psmap_import @179 NONAME
diff --git a/src/imports/import_64_1700_avs.def b/src/imports/import_64_1700_avs.def
index fe8cc6e6..8cddba8a 100644
--- a/src/imports/import_64_1700_avs.def
+++ b/src/imports/import_64_1700_avs.def
@@ -6,7 +6,16 @@ EXPORTS
avs_thread_exit @11 NONAME
avs_thread_join @12 NONAME
avs_fs_addfs @73 NONAME
+ avs_fs_close @86 NONAME == XCgsqzn0000055
+ avs_fs_copy @102 NONAME == XCgsqzn0000065
+ avs_fs_lseek @80 NONAME == XCgsqzn000004f
+ avs_fs_lstat @100 NONAME == XCgsqzn0000063
avs_fs_mount @76 NONAME
+ avs_fs_open @79 NONAME == XCgsqzn000004e
+ avs_fs_read @82 NONAME == XCgsqzn0000051
+ avs_fs_opendir @93 NONAME == XCgsqzn000005c
+ avs_fs_readdir @94 NONAME == XCgsqzn000005d
+ avs_fs_closedir @95 NONAME == XCgsqzn000005e
avs_net_ctrl @119 NONAME
property_create @145 NONAME
property_destroy @146 NONAME
@@ -14,7 +23,15 @@ EXPORTS
property_insert_read @149 NONAME
property_search @162 NONAME
property_node_create @163 NONAME
+ property_node_name @168 NONAME == XCgsqzn00000a7
property_node_remove @164 NONAME
+ property_node_type @169 NONAME == XCgsqzn00000a8
+ property_node_clone @165 NONAME
+ property_node_traversal @167 NONAME
+ property_node_refdata @166 NONAME == XCgsqzn00000a5
+ property_node_datasize @171 NONAME == XCgsqzn00000aa
+ property_node_read @172 NONAME == XCgsqzn00000ab
+ property_query_size @160 NONAME == XCgsqzn000009f
property_node_refer @176 NONAME
property_read_query_memsize @177 NONAME
property_psmap_import @179 NONAME
diff --git a/src/imports/import_64_indep_dwarfstack.def b/src/imports/import_64_indep_dwarfstack.def
new file mode 100644
index 00000000..71f1aaf5
--- /dev/null
+++ b/src/imports/import_64_indep_dwarfstack.def
@@ -0,0 +1,13 @@
+LIBRARY dwarfstack
+
+EXPORTS
+ dwstOfFile @ 441
+ dwstOfFileW @ 443
+ dwstOfProcess @ 446
+ dwstOfProcessW @ 448
+ dwstOfLocation @ 444
+ dwstOfLocationW @ 445
+ dwstOfException @ 438
+ dwstOfExceptionW @ 440
+ dwstExceptionDialog @ 436
+ dwstExceptionDialogW @ 437
\ No newline at end of file
diff --git a/src/main/acioemu/icca.c b/src/main/acioemu/icca.c
index 134b14fc..e7713e52 100644
--- a/src/main/acioemu/icca.c
+++ b/src/main/acioemu/icca.c
@@ -511,7 +511,7 @@ static void ac_io_emu_icca_cipher_set_key(
resp.cmd.raw[0] = (reader_key >> 24) & 0xFF;
resp.cmd.raw[1] = (reader_key >> 16) & 0xFF;
resp.cmd.raw[2] = (reader_key >> 8) & 0xFF;
- resp.cmd.raw[3] = (reader_key) &0xFF;
+ resp.cmd.raw[3] = (reader_key) & 0xFF;
// so I looked these constants up, this isn't actually a secure key
// generator it's actually Marsaglia's "KISS" algorithm with different
diff --git a/src/main/aciotest/bi2a-iidx.c b/src/main/aciotest/bi2a-iidx.c
index bd391cf8..01315675 100644
--- a/src/main/aciotest/bi2a-iidx.c
+++ b/src/main/aciotest/bi2a-iidx.c
@@ -29,81 +29,79 @@ bool aciotest_bi2a_iidx_handler_update(
return false;
}
-
-
printf(
- "|---------------------------------------|\n"
- "| R Y G B Neons B G Y R |\n"
- "| %d %d %d %d %d %d %d %d %d |\n"
- "|---------------------------------------|\n"
- "| NOW PLAYING: %c%c%c%c%c%c%c%c%c |\n"
- "|---------------------------------------|\n"
- "| Effect %d S1 S2 S3 S4 S5 Test %d|\n"
- "|StartP1 %d %02d %02d %02d %02d %02d StartP2 %d|\n"
- "| VEFX %d Service %d|\n"
- "_________________________________________\n"
- "| __ __ |\n"
- "| / \\ _ / \\ |\n"
- "| | %03d| %d %d %d |%d| %d %d %d | %03d| |\n"
- "| \\___/ %d %d %d %d |_| %d %d %d %d \\___/ |\n"
- "| |\n"
- "|---------------------------------------|\n"
- "|---------------------------------------|\n",
-
- pout.SPOTLIGHT2[0].l_state,
- pout.SPOTLIGHT2[1].l_state,
- pout.SPOTLIGHT2[2].l_state,
- pout.SPOTLIGHT2[3].l_state,
- pout.NEONLAMP.l_state,
- pout.SPOTLIGHT1[0].l_state,
- pout.SPOTLIGHT1[1].l_state,
- pout.SPOTLIGHT1[2].l_state,
- pout.SPOTLIGHT1[3].l_state,
-
- pout.SEG16[0],
- pout.SEG16[1],
- pout.SEG16[2],
- pout.SEG16[3],
- pout.SEG16[4],
- pout.SEG16[5],
- pout.SEG16[6],
- pout.SEG16[7],
- pout.SEG16[8],
-
- pin.PANEL.y_effect,
- pin.SYSTEM.v_test,
-
- pin.PANEL.y_start1,
- pin.SLIDER1.s_val,
- pin.SLIDER2.s_val,
- pin.SLIDER3.s_val,
- pin.SLIDER4.s_val,
- pin.SLIDER5.s_val,
- pin.PANEL.y_start2,
-
- pin.PANEL.y_vefx,
- pin.SYSTEM.v_service,
-
- pin.TURNTABLE1,
- pin.P1SW2.b_val,
- pin.P1SW4.b_val,
- pin.P1SW6.b_val,
- pin.SYSTEM.v_coin,
- pin.P2SW2.b_val,
- pin.P2SW4.b_val,
- pin.P2SW6.b_val,
- pin.TURNTABLE2,
-
- pin.P1SW1.b_val,
- pin.P1SW3.b_val,
- pin.P1SW5.b_val,
- pin.P1SW7.b_val,
- pin.P2SW1.b_val,
- pin.P2SW3.b_val,
- pin.P2SW5.b_val,
- pin.P2SW7.b_val
-
- );
+ "|---------------------------------------|\n"
+ "| R Y G B Neons B G Y R |\n"
+ "| %d %d %d %d %d %d %d %d %d |\n"
+ "|---------------------------------------|\n"
+ "| NOW PLAYING: %c%c%c%c%c%c%c%c%c |\n"
+ "|---------------------------------------|\n"
+ "| Effect %d S1 S2 S3 S4 S5 Test %d|\n"
+ "|StartP1 %d %02d %02d %02d %02d %02d StartP2 %d|\n"
+ "| VEFX %d Service %d|\n"
+ "_________________________________________\n"
+ "| __ __ |\n"
+ "| / \\ _ / \\ |\n"
+ "| | %03d| %d %d %d |%d| %d %d %d | %03d| |\n"
+ "| \\___/ %d %d %d %d |_| %d %d %d %d \\___/ |\n"
+ "| |\n"
+ "|---------------------------------------|\n"
+ "|---------------------------------------|\n",
+
+ pout.SPOTLIGHT2[0].l_state,
+ pout.SPOTLIGHT2[1].l_state,
+ pout.SPOTLIGHT2[2].l_state,
+ pout.SPOTLIGHT2[3].l_state,
+ pout.NEONLAMP.l_state,
+ pout.SPOTLIGHT1[0].l_state,
+ pout.SPOTLIGHT1[1].l_state,
+ pout.SPOTLIGHT1[2].l_state,
+ pout.SPOTLIGHT1[3].l_state,
+
+ pout.SEG16[0],
+ pout.SEG16[1],
+ pout.SEG16[2],
+ pout.SEG16[3],
+ pout.SEG16[4],
+ pout.SEG16[5],
+ pout.SEG16[6],
+ pout.SEG16[7],
+ pout.SEG16[8],
+
+ pin.PANEL.y_effect,
+ pin.SYSTEM.v_test,
+
+ pin.PANEL.y_start1,
+ pin.SLIDER1.s_val,
+ pin.SLIDER2.s_val,
+ pin.SLIDER3.s_val,
+ pin.SLIDER4.s_val,
+ pin.SLIDER5.s_val,
+ pin.PANEL.y_start2,
+
+ pin.PANEL.y_vefx,
+ pin.SYSTEM.v_service,
+
+ pin.TURNTABLE1,
+ pin.P1SW2.b_val,
+ pin.P1SW4.b_val,
+ pin.P1SW6.b_val,
+ pin.SYSTEM.v_coin,
+ pin.P2SW2.b_val,
+ pin.P2SW4.b_val,
+ pin.P2SW6.b_val,
+ pin.TURNTABLE2,
+
+ pin.P1SW1.b_val,
+ pin.P1SW3.b_val,
+ pin.P1SW5.b_val,
+ pin.P1SW7.b_val,
+ pin.P2SW1.b_val,
+ pin.P2SW3.b_val,
+ pin.P2SW5.b_val,
+ pin.P2SW7.b_val
+
+ );
return true;
}
diff --git a/src/main/aciotest/main.c b/src/main/aciotest/main.c
index a0da1391..4a301c41 100644
--- a/src/main/aciotest/main.c
+++ b/src/main/aciotest/main.c
@@ -1,14 +1,14 @@
#include
#include
-#include
#include
+#include
#include
#include "aciodrv/device.h"
-#include "aciotest/bi2a-sdvx.h"
#include "aciotest/bi2a-iidx.h"
+#include "aciotest/bi2a-sdvx.h"
#include "aciotest/handler.h"
#include "aciotest/icca.h"
#include "aciotest/kfca.h"
@@ -58,25 +58,23 @@ static bool aciotest_assign_handler(
if (bi2a_mode == 255) {
printf(
"Unknown BI2A mode specified, please check your command.\n"
- "Using bi2a-sdvx mode as default, press ENTER to continue\n"
- );
+ "Using bi2a-sdvx mode as default, press ENTER to continue\n");
bi2a_mode = 0;
getchar();
}
- switch (bi2a_mode)
- {
- case 0:
- handler->init = aciotest_bi2a_sdvx_handler_init;
- handler->update = aciotest_bi2a_sdvx_handler_update;
- break;
- case 1:
- handler->init = aciotest_bi2a_iidx_handler_init;
- handler->update = aciotest_bi2a_iidx_handler_update;
- break;
-
- default:
- break;
+ switch (bi2a_mode) {
+ case 0:
+ handler->init = aciotest_bi2a_sdvx_handler_init;
+ handler->update = aciotest_bi2a_sdvx_handler_update;
+ break;
+ case 1:
+ handler->init = aciotest_bi2a_iidx_handler_init;
+ handler->update = aciotest_bi2a_iidx_handler_update;
+ break;
+
+ default:
+ break;
}
return true;
}
@@ -107,9 +105,9 @@ int main(int argc, char **argv)
}
if (argc == 4) {
- if(!strcmp(argv[3],"bi2a-iidx")) {
+ if (!strcmp(argv[3], "bi2a-iidx")) {
bi2a_mode = 1;
- } else if(!strcmp(argv[3],"bi2a-sdvx")) {
+ } else if (!strcmp(argv[3], "bi2a-sdvx")) {
bi2a_mode = 0;
}
}
diff --git a/src/main/avs-util/Module.mk b/src/main/avs-util/Module.mk
new file mode 100644
index 00000000..8db06918
--- /dev/null
+++ b/src/main/avs-util/Module.mk
@@ -0,0 +1,6 @@
+libs += avs-util
+
+libs_avs-util := \
+
+src_avs-util := \
+ error.c \
diff --git a/src/main/avs-util/error.c b/src/main/avs-util/error.c
new file mode 100644
index 00000000..ab09c014
--- /dev/null
+++ b/src/main/avs-util/error.c
@@ -0,0 +1,99 @@
+#include "avs-util/error.h"
+
+#include "util/defs.h"
+
+struct avs_util_avs_error_str {
+ avs_error error;
+ const char *msg;
+};
+
+static const char *avs_util_error_unknown = "unknown error";
+
+// Source: https://github.com/spicetools/spicetools
+static const struct avs_util_avs_error_str AVS_UTIL_ERRORS[] = {
+ {0x80092000, "invalid type"},
+ {0x80092001, "type cannot use as array"},
+ {0x80092002, "invalid"},
+ {0x80092003, "too large data size"},
+ {0x80092004, "too small buffer size"},
+ {0x80092005, "passcode 0 is not allowed"},
+ {0x80092040, "invalid node name"},
+ {0x80092041, "invalid attribute name"},
+ {0x80092042, "reserved attribute name"},
+ {0x80092043, "cannot find node/attribute"},
+ {0x80092080, "cannot allocate node"},
+ {0x80092081, "cannot allocate node value"},
+ {0x80092082, "cannot allocate mdigest for finger-print"},
+ {0x80092083, "cannot allocate nodename"},
+ {0x800920C0, "node type differs"},
+ {0x800920C1, "node type is VOID"},
+ {0x800920C2, "node is array"},
+ {0x800920C3, "node is not array"},
+ {0x80092100, "node is create-disabled"},
+ {0x80092101, "node is read-disabled"},
+ {0x80092102, "node is write-disabled"},
+ {0x80092103, "flag is already locked"},
+ {0x80092104, "passcode differs"},
+ {0x80092105, "insert_read() is applied to attribute"},
+ {0x80092106, "part_write() is applied to attribute"},
+ {0x80092107, "MODE_EXTEND flag differs"},
+ {0x80092140, "root node already exists"},
+ {0x80092141, "attribute cannot have children"},
+ {0x80092142, "node/attribute already exists"},
+ {0x80092143, "number of nodes exceeds 65535"},
+ {0x80092144, "cannot interpret as number"},
+ {0x80092145, "property is empty"},
+ {0x80092180, "I/O error"},
+ {0x80092181, "unexpected EOF"},
+ {0x80092182, "unknown format"},
+ {0x800921C0, "broken magic"},
+ {0x800921C1, "broken metadata"},
+ {0x800921C2, "broken databody"},
+ {0x800921C3, "invalid type"},
+ {0x800921C4, "too large data size"},
+ {0x800921C5, "too long node/attribute name"},
+ {0x800921C6, "attribute name is too long"},
+ {0x800921C7, "node/attribute already exists"},
+ {0x80092200, "invalid encoding"},
+ {0x80092201, "invalid XML token"},
+ {0x80092202, "XML syntax error"},
+ {0x80092203, "start tag / end tag mismatch"},
+ {0x80092204, "too large node data (__size mismatch)"},
+ {0x80092205, "too deep node tree"},
+ {0x80092206, "invalid type"},
+ {0x80092207, "invalid size"},
+ {0x80092208, "invalid count"},
+ {0x80092209, "invalid value"},
+ {0x8009220A, "invalid node name"},
+ {0x8009220B, "invalid attribute name"},
+ {0x8009220C, "reserved attribute name"},
+ {0x8009220D, "node/attribute already exists"},
+ {0x8009220E, "too many elements in node data"},
+ {0x80092240, "JSON syntax error"},
+ {0x80092241, "invalid JSON literal"},
+ {0x80092242, "invalid JSON number"},
+ {0x80092243, "invalid JSON string"},
+ {0x80092244, "invalid JSON object name"},
+ {0x80092245, "object name already exists"},
+ {0x80092246, "too long JSON object name"},
+ {0x80092247, "too deep JSON object/array nesting"},
+ {0x80092248, "cannot convert JSON array to property"},
+ {0x80092249, "cannot convert empty JSON object to property"},
+ {0x8009224A, "root node already exists"},
+ {0x8009224B, "cannot convert root node to TYPE_ARRAY"},
+ {0x8009224C, "name represents reserved attribute"},
+ {0x80092280, "finger-print differs"},
+ {0x800922C0, "operation is not supported"}};
+
+const char *avs_util_error_str(avs_error error)
+{
+ int i;
+
+ for (i = 0; i < lengthof(AVS_UTIL_ERRORS); i++) {
+ if (error == AVS_UTIL_ERRORS[i].error) {
+ return AVS_UTIL_ERRORS[i].msg;
+ }
+ }
+
+ return avs_util_error_unknown;
+}
\ No newline at end of file
diff --git a/src/main/avs-util/error.h b/src/main/avs-util/error.h
new file mode 100644
index 00000000..35988515
--- /dev/null
+++ b/src/main/avs-util/error.h
@@ -0,0 +1,8 @@
+#ifndef AVS_UTIL_ERROR_H
+#define AVS_UTIL_ERROR_H
+
+#include "imports/avs.h"
+
+const char *avs_util_error_str(avs_error error);
+
+#endif
\ No newline at end of file
diff --git a/src/main/ddrio-async/ddrio.c b/src/main/ddrio-async/ddrio.c
index 9b857fd6..fe81f68e 100644
--- a/src/main/ddrio-async/ddrio.c
+++ b/src/main/ddrio-async/ddrio.c
@@ -28,7 +28,8 @@ typedef uint32_t (*ddr_io_read_pad_t)(void);
typedef void (*ddr_io_set_lights_extio_t)(uint32_t extio_lights);
typedef void (*ddr_io_set_lights_p3io_t)(uint32_t p3io_lights);
typedef void (*ddr_io_set_lights_hdxs_panel_t)(uint32_t hdxs_lights);
-typedef void (*ddr_io_set_lights_hdxs_rgb_t)(uint8_t idx, uint8_t r, uint8_t g, uint8_t b);
+typedef void (*ddr_io_set_lights_hdxs_rgb_t)(
+ uint8_t idx, uint8_t r, uint8_t g, uint8_t b);
typedef void (*ddr_io_fini_t)(void);
static HMODULE _child_ddr_io_module;
@@ -66,10 +67,7 @@ static int _io_thread_proc(void *ctx)
uint32_t local_tmp;
- atomic_store_explicit(
- &_io_thread_proc_running,
- true,
- memory_order_seq_cst);
+ atomic_store_explicit(&_io_thread_proc_running, true, memory_order_seq_cst);
log_info("IO thread running");
@@ -85,18 +83,16 @@ static int _io_thread_proc(void *ctx)
local_tmp = _child_ddr_io_read_pad();
atomic_store_explicit(
- &_child_ddr_io_data_pad,
- local_tmp,
- memory_order_relaxed);
+ &_child_ddr_io_data_pad, local_tmp, memory_order_relaxed);
- // Only update outputs when they change gives this loop a major performance boost
- // The write calls on a p3io for the outputs are very expensive (~12 ms) as they
- // are executed over the ACIO protocol compared to only the input read
- // calls (~4 ms) which have a dedicated IOCTL call/endpoint
+ // Only update outputs when they change gives this loop a major
+ // performance boost The write calls on a p3io for the outputs are very
+ // expensive (~12 ms) as they are executed over the ACIO protocol
+ // compared to only the input read calls (~4 ms) which have a dedicated
+ // IOCTL call/endpoint
local_tmp = atomic_load_explicit(
- &_child_ddr_io_data_extio_lights,
- memory_order_relaxed);
+ &_child_ddr_io_data_extio_lights, memory_order_relaxed);
if (local_tmp != prev_child_ddr_io_data_extio_lights) {
_child_ddr_io_set_lights_extio(local_tmp);
@@ -104,9 +100,8 @@ static int _io_thread_proc(void *ctx)
}
local_tmp = atomic_load_explicit(
- &_child_ddr_io_data_p3io_lights,
- memory_order_relaxed);
-
+ &_child_ddr_io_data_p3io_lights, memory_order_relaxed);
+
if (local_tmp != prev_child_ddr_io_data_p3io_lights) {
_child_ddr_io_set_lights_p3io(local_tmp);
prev_child_ddr_io_data_p3io_lights = local_tmp;
@@ -121,22 +116,23 @@ static int _io_thread_proc(void *ctx)
time_end = time_get_counter();
total_time = time_get_elapsed_us(time_end - time_start);
- log_info("IO thread performance: total iterations %lld, avg. loop cycle time %f us",
- loop_counter, ((double) total_time) / loop_counter);
+ log_info(
+ "IO thread performance: total iterations %lld, avg. loop cycle time %f "
+ "us",
+ loop_counter,
+ ((double) total_time) / loop_counter);
atomic_store_explicit(
- &_io_thread_proc_running,
- false,
- memory_order_seq_cst);
+ &_io_thread_proc_running, false, memory_order_seq_cst);
log_info("IO thread shut down");
return 0;
}
-static void* _load_function(HMODULE module, const char* name)
+static void *_load_function(HMODULE module, const char *name)
{
- void* ptr;
+ void *ptr;
ptr = GetProcAddress(module, name);
@@ -175,13 +171,19 @@ bool ddr_io_init(
return false;
}
- _child_ddr_io_set_loggers = _load_function(_child_ddr_io_module, "ddr_io_set_loggers");
+ _child_ddr_io_set_loggers =
+ _load_function(_child_ddr_io_module, "ddr_io_set_loggers");
_child_ddr_io_init = _load_function(_child_ddr_io_module, "ddr_io_init");
- _child_ddr_io_read_pad = _load_function(_child_ddr_io_module, "ddr_io_read_pad");
- _child_ddr_io_set_lights_extio = _load_function(_child_ddr_io_module, "ddr_io_set_lights_extio");
- _child_ddr_io_set_lights_p3io = _load_function(_child_ddr_io_module, "ddr_io_set_lights_p3io");
- _child_ddr_io_set_lights_hdxs_panel = _load_function(_child_ddr_io_module, "ddr_io_set_lights_hdxs_panel");
- _child_ddr_io_set_lights_hdxs_rgb = _load_function(_child_ddr_io_module, "ddr_io_set_lights_hdxs_rgb");
+ _child_ddr_io_read_pad =
+ _load_function(_child_ddr_io_module, "ddr_io_read_pad");
+ _child_ddr_io_set_lights_extio =
+ _load_function(_child_ddr_io_module, "ddr_io_set_lights_extio");
+ _child_ddr_io_set_lights_p3io =
+ _load_function(_child_ddr_io_module, "ddr_io_set_lights_p3io");
+ _child_ddr_io_set_lights_hdxs_panel =
+ _load_function(_child_ddr_io_module, "ddr_io_set_lights_hdxs_panel");
+ _child_ddr_io_set_lights_hdxs_rgb =
+ _load_function(_child_ddr_io_module, "ddr_io_set_lights_hdxs_rgb");
_child_ddr_io_fini = _load_function(_child_ddr_io_module, "ddr_io_fini");
_child_ddr_io_set_loggers(
@@ -199,10 +201,7 @@ bool ddr_io_init(
return false;
}
- atomic_store_explicit(
- &_io_thread_proc_loop,
- true,
- memory_order_seq_cst);
+ atomic_store_explicit(&_io_thread_proc_loop, true, memory_order_seq_cst);
if (!thread_create(_io_thread_proc, NULL, 16384, 0)) {
log_warning("Creating IO thread failed");
@@ -224,17 +223,13 @@ uint32_t ddr_io_read_pad(void)
void ddr_io_set_lights_extio(uint32_t extio_lights)
{
atomic_store_explicit(
- &_child_ddr_io_data_extio_lights,
- extio_lights,
- memory_order_relaxed);
+ &_child_ddr_io_data_extio_lights, extio_lights, memory_order_relaxed);
}
void ddr_io_set_lights_p3io(uint32_t p3io_lights)
{
atomic_store_explicit(
- &_child_ddr_io_data_p3io_lights,
- p3io_lights,
- memory_order_relaxed);
+ &_child_ddr_io_data_p3io_lights, p3io_lights, memory_order_relaxed);
}
void ddr_io_set_lights_hdxs_panel(uint32_t lights)
@@ -249,14 +244,12 @@ void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
void ddr_io_fini(void)
{
- atomic_store_explicit(
- &_io_thread_proc_loop,
- false,
- memory_order_seq_cst);
+ atomic_store_explicit(&_io_thread_proc_loop, false, memory_order_seq_cst);
log_info("Shutting down IO thread and waiting for it to finish...");
- while (atomic_load_explicit(&_io_thread_proc_running, memory_order_seq_cst)) {
+ while (
+ atomic_load_explicit(&_io_thread_proc_running, memory_order_seq_cst)) {
Sleep(1);
}
diff --git a/src/main/geninput/hid-meta-out.c b/src/main/geninput/hid-meta-out.c
index 94402835..4f87602a 100644
--- a/src/main/geninput/hid-meta-out.c
+++ b/src/main/geninput/hid-meta-out.c
@@ -50,8 +50,9 @@ bool hid_meta_out_init(
caps_fail:
/**
* Still allow the device to be used as input.
- * Useful for devices like the Sony DUALSHOCK 4, where it indicates it can receive outputs
- * but it errors out when trying to initialize an output report.
+ * Useful for devices like the Sony DUALSHOCK 4, where it indicates it can
+ * receive outputs but it errors out when trying to initialize an output
+ * report.
*/
return true;
}
@@ -213,7 +214,7 @@ static bool hid_meta_out_init_arrays(struct hid_meta_out *meta)
meta->nreports = 0;
free(meta->reports);
meta->reports = NULL;
-
+
meta->nlights = 0;
meta->nbuttons = 0;
// Failed out before allocating memory
diff --git a/src/main/inject/Module.mk b/src/main/inject/Module.mk
index 549f1792..648ea7f3 100644
--- a/src/main/inject/Module.mk
+++ b/src/main/inject/Module.mk
@@ -1,11 +1,14 @@
exes += inject
+imps += dwarfstack
ldflags_inject := \
-mconsole \
-lpsapi \
+ -ldbghelp \
libs_inject := \
util \
+ dwarfstack \
src_inject := \
main.c \
diff --git a/src/main/inject/debugger.c b/src/main/inject/debugger.c
index 724ed9ba..77d92444 100644
--- a/src/main/inject/debugger.c
+++ b/src/main/inject/debugger.c
@@ -11,10 +11,10 @@
#include "inject/debugger.h"
#include "inject/logger.h"
+#include "util/debug.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/proc.h"
-#include "util/signal.h"
#include "util/str.h"
#define MM_ALLOCATION_GRANULARITY 0x10000
@@ -271,7 +271,7 @@ static uint32_t debugger_loop()
"EXCEPTION_DEBUG_EVENT(pid %ld, tid %ld): x%s 0x%p",
de.dwProcessId,
de.dwThreadId,
- signal_exception_code_to_str(
+ debug_exception_code_to_str(
de.u.Exception.ExceptionRecord.ExceptionCode),
de.u.Exception.ExceptionRecord.ExceptionAddress);
diff --git a/src/main/inject/main.c b/src/main/inject/main.c
index bfb6c1be..475e5ab9 100644
--- a/src/main/inject/main.c
+++ b/src/main/inject/main.c
@@ -16,6 +16,7 @@
#include "inject/version.h"
#include "util/cmdline.h"
+#include "util/debug.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/os.h"
@@ -166,6 +167,7 @@ int main(int argc, char **argv)
os_version_log();
+ debug_init();
signal_exception_handler_init();
// Cleanup remote process on CTRL+C
signal_register_shutdown_handler(signal_shutdown_handler);
diff --git a/src/main/launcher/Module.mk b/src/main/launcher/Module.mk
index c9dfd078..df84eba0 100644
--- a/src/main/launcher/Module.mk
+++ b/src/main/launcher/Module.mk
@@ -3,22 +3,35 @@ rc_launcher := launcher.rc
ldflags_launcher := \
-mconsole \
+ -ldbghelp \
deplibs_launcher := \
avs \
avs-ea3 \
libs_launcher := \
+ avs-util \
hook \
util \
+ dwarfstack \
src_launcher := \
- avs-context.c \
- ea3-config.c \
+ avs-config.c \
+ avs.c \
+ bootstrap-config.c \
+ bootstrap.c \
+ debug.c \
+ ea3-ident-config.c \
+ eamuse-config.c \
+ eamuse.c \
+ hook.c \
+ launcher-config.c \
+ launcher.c \
+ logger.c \
main.c \
module.c \
options.c \
- property.c \
+ property-util.c \
stubs.c \
version.c \
diff --git a/src/main/launcher/avs-config.c b/src/main/launcher/avs-config.c
new file mode 100644
index 00000000..879e1dc5
--- /dev/null
+++ b/src/main/launcher/avs-config.c
@@ -0,0 +1,361 @@
+#define LOG_MODULE "avs-config"
+
+#include
+
+#include "avs-util/error.h"
+
+#include "imports/avs.h"
+
+#include "launcher/avs-config.h"
+#include "launcher/property-util.h"
+
+#include "util/log.h"
+#include "util/str.h"
+
+#define AVS_CONFIG_ROOT_NODE "/config"
+
+struct property *avs_config_load(const char *filepath)
+{
+ struct property *property;
+
+ log_assert(filepath);
+
+ log_info("Loading from file path: %s", filepath);
+
+ property = property_util_load(filepath);
+
+ // Check if root node exists, call already errors if not
+ avs_config_root_get(property);
+
+ return property;
+}
+
+struct property_node *avs_config_root_get(struct property *property)
+{
+ struct property_node *node;
+
+ log_assert(property);
+
+ node = property_search(property, 0, AVS_CONFIG_ROOT_NODE);
+
+ if (node == NULL) {
+ log_fatal("Root node " AVS_CONFIG_ROOT_NODE " in AVS config missing");
+ }
+
+ return node;
+}
+
+void avs_config_fs_root_device_get(
+ struct property_node *node, char *buffer, size_t size)
+{
+ struct property_node *device_node;
+ avs_error error;
+
+ log_assert(node);
+
+ device_node = property_search(NULL, node, "fs/root/device");
+
+ if (device_node == NULL) {
+ log_fatal("Could not find node fs/root/device AVS config");
+ }
+
+ error = property_node_read(device_node, PROPERTY_TYPE_STR, buffer, size);
+
+ if (AVS_IS_ERROR(error)) {
+ log_fatal(
+ "fs/root/device, property read failed: %s",
+ avs_util_error_str(error));
+ }
+}
+
+void avs_config_mode_product_set(struct property_node *node, bool enable)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(NULL, node, "mode/product", enable ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "mode/product", enable);
+#endif
+}
+
+void avs_config_net_raw_set(struct property_node *node, bool enable)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(NULL, node, "net/enable_raw", enable ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "net/enable_raw", enable);
+#endif
+}
+
+void avs_config_net_eaudp_set(struct property_node *node, bool enable)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(
+ NULL, node, "net/eaudp/enable", enable ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "net/eaudp/enable", enable);
+#endif
+}
+
+void avs_config_sntp_ea_set(struct property_node *node, bool on)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(NULL, node, "sntp/ea_on", on ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "sntp/ea_on", on);
+#endif
+}
+
+void avs_config_log_level_set(struct property_node *node, const char *level)
+{
+ log_assert(node);
+ log_assert(level);
+
+#if AVS_VERSION <= 1306
+ uint32_t level_value;
+
+ if (str_eq(level, "fatal")) {
+ level_value = 1;
+ } else if (str_eq(level, "warning")) {
+ level_value = 2;
+ } else if (str_eq(level, "info")) {
+ level_value = 3;
+ } else if (str_eq(level, "misc")) {
+ level_value = 4;
+ } else if (str_eq(level, "all")) {
+ level_value = 4;
+ } else if (str_eq(level, "disable")) {
+ level_value = 0;
+ } else if (str_eq(level, "default")) {
+ level_value = 4;
+ } else {
+ log_fatal("Unknown log level string %s", level);
+ }
+
+ property_util_node_u32_replace(NULL, node, "log/level", level_value);
+#else
+ property_util_node_str_replace(NULL, node, "log/level", level);
+#endif
+}
+
+void avs_config_log_name_set(struct property_node *node, const char *name)
+{
+ log_assert(node);
+ log_assert(name);
+
+ property_util_node_str_replace(NULL, node, "log/name", name);
+}
+
+void avs_config_log_file_set(struct property_node *node, const char *file)
+{
+ log_assert(node);
+ log_assert(file);
+
+ property_util_node_str_replace(NULL, node, "log/file", file);
+}
+
+void avs_config_log_buffer_size_set(struct property_node *node, uint32_t size)
+{
+ log_assert(node);
+
+ property_util_node_u32_replace(NULL, node, "log/sz_buf", size);
+}
+
+void avs_config_log_output_delay_set(
+ struct property_node *node, uint16_t delay_ms)
+{
+ log_assert(node);
+
+ property_util_node_u16_replace(NULL, node, "log/output_delay", delay_ms);
+}
+
+void avs_config_log_enable_console_set(struct property_node *node, bool enable)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(
+ NULL, node, "log/enable_console", enable ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "log/enable_console", enable);
+#endif
+}
+
+void avs_config_log_enable_sci_set(struct property_node *node, bool enable)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(
+ NULL, node, "log/enable_netsci", enable ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "log/enable_netsci", enable);
+#endif
+}
+
+void avs_config_log_enable_net_set(struct property_node *node, bool enable)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(
+ NULL, node, "log/enable_netlog", enable ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "log/enable_netlog", enable);
+#endif
+}
+
+void avs_config_log_enable_file_set(struct property_node *node, bool enable)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(
+ NULL, node, "log/enable_file", enable ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "log/enable_file", enable);
+#endif
+}
+
+void avs_config_log_rotate_set(struct property_node *node, bool rotate)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(NULL, node, "log/rotate", rotate ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "log/rotate", rotate);
+#endif
+}
+
+void avs_config_log_append_set(struct property_node *node, bool append)
+{
+ log_assert(node);
+
+#if AVS_VERSION <= 1306
+ property_util_node_u8_replace(NULL, node, "log/append", append ? 1 : 0);
+#else
+ property_util_node_bool_replace(NULL, node, "log/append", append);
+#endif
+}
+
+void avs_config_log_count_set(struct property_node *node, uint16_t count)
+{
+ log_assert(node);
+
+ property_util_node_u16_replace(NULL, node, "log/gen", count);
+}
+
+void avs_config_set_log_level(
+ struct property_node *node, enum log_level loglevel)
+{
+ const char *str;
+
+ log_assert(node);
+
+ switch (loglevel) {
+ case LOG_LEVEL_FATAL:
+ str = "fatal";
+ break;
+
+ case LOG_LEVEL_WARNING:
+ str = "warn";
+ break;
+
+ case LOG_LEVEL_INFO:
+ str = "info";
+ break;
+
+ case LOG_LEVEL_MISC:
+ str = "misc";
+ break;
+
+ default:
+ log_fatal("Unsupported log level: %d", loglevel);
+ break;
+ }
+
+ avs_config_log_level_set(node, str);
+}
+
+void avs_config_local_fs_path_dev_nvram_and_raw_set(
+ struct property_node *node, const char *dev_nvram_raw_path)
+{
+ char path_dev_raw[MAX_PATH];
+ char path_dev_nvram[MAX_PATH];
+
+ struct property_node *fs_node;
+ struct property_node *mounttable_node;
+ struct property_node *vfs_node;
+
+ log_assert(node);
+ log_assert(dev_nvram_raw_path);
+
+ str_cpy(path_dev_raw, sizeof(path_dev_raw), dev_nvram_raw_path);
+ str_cat(path_dev_raw, sizeof(path_dev_raw), "/dev/raw");
+
+ str_cpy(path_dev_nvram, sizeof(path_dev_nvram), dev_nvram_raw_path);
+ str_cat(path_dev_nvram, sizeof(path_dev_nvram), "/dev/nvram");
+
+ fs_node = property_search(NULL, node, "fs");
+
+ if (!fs_node) {
+ log_fatal("Cannot find 'fs' node in avs config");
+ }
+
+ // Check if "new" mounttable config is used for dev/nvram and dev/raw or
+ // legacy config
+ if (property_search(NULL, fs_node, "mounttable")) {
+ property_remove(NULL, fs_node, "mounttable");
+
+ mounttable_node = property_node_create(
+ NULL, fs_node, PROPERTY_TYPE_VOID, "mounttable");
+
+ vfs_node = property_node_create(
+ NULL, mounttable_node, PROPERTY_TYPE_VOID, "vfs");
+
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "name", "boot");
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "fstype", "fs");
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "src", path_dev_raw);
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "dest", "/dev/raw");
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "opt", "vf=1,posix=1");
+
+ vfs_node = property_node_create(
+ NULL, mounttable_node, PROPERTY_TYPE_VOID, "vfs");
+
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "name", "boot");
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "fstype", "fs");
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "src", path_dev_nvram);
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "dest", "/dev/nvram");
+ property_node_create(
+ NULL, vfs_node, PROPERTY_TYPE_ATTR, "opt", "vf=1,posix=1");
+ } else {
+ property_util_node_str_replace(
+ NULL, fs_node, "nvram/device", path_dev_raw);
+ property_util_node_str_replace(NULL, fs_node, "nvram/fstype", "fs");
+ property_util_node_str_replace(
+ NULL, fs_node, "nvram/option", "vf=1,posix=1");
+
+ property_util_node_str_replace(
+ NULL, fs_node, "raw/device", path_dev_nvram);
+ property_util_node_str_replace(NULL, fs_node, "raw/fstype", "fs");
+ property_util_node_str_replace(
+ NULL, fs_node, "raw/option", "vf=1,posix=1");
+ }
+}
\ No newline at end of file
diff --git a/src/main/launcher/avs-config.h b/src/main/launcher/avs-config.h
new file mode 100644
index 00000000..8b964156
--- /dev/null
+++ b/src/main/launcher/avs-config.h
@@ -0,0 +1,39 @@
+#ifndef LAUNCHER_AVS_CONFIG_H
+#define LAUNCHER_AVS_CONFIG_H
+
+#include "imports/avs.h"
+
+#include "launcher/bootstrap-config.h"
+
+#include "util/log.h"
+
+struct property *avs_config_load(const char *filepath);
+struct property_node *avs_config_root_get(struct property *property);
+
+void avs_config_fs_root_device_get(
+ struct property_node *node, char *buffer, size_t size);
+
+void avs_config_mode_product_set(struct property_node *node, bool enable);
+void avs_config_net_raw_set(struct property_node *node, bool enable);
+void avs_config_net_eaudp_set(struct property_node *node, bool enable);
+void avs_config_sntp_ea_set(struct property_node *node, bool on);
+void avs_config_log_level_set(struct property_node *node, const char *level);
+void avs_config_log_name_set(struct property_node *node, const char *name);
+void avs_config_log_file_set(struct property_node *node, const char *file);
+void avs_config_log_buffer_size_set(struct property_node *node, uint32_t size);
+void avs_config_log_output_delay_set(
+ struct property_node *node, uint16_t delay_ms);
+void avs_config_log_enable_console_set(struct property_node *node, bool enable);
+void avs_config_log_enable_sci_set(struct property_node *node, bool enable);
+void avs_config_log_enable_net_set(struct property_node *node, bool enable);
+void avs_config_log_enable_file_set(struct property_node *node, bool enable);
+void avs_config_log_rotate_set(struct property_node *node, bool rotate);
+void avs_config_log_append_set(struct property_node *node, bool append);
+void avs_config_log_count_set(struct property_node *node, uint16_t count);
+
+void avs_config_set_log_level(
+ struct property_node *node, enum log_level loglevel);
+void avs_config_local_fs_path_dev_nvram_and_raw_set(
+ struct property_node *node, const char *dev_nvram_raw_path);
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/avs-context.c b/src/main/launcher/avs-context.c
deleted file mode 100644
index 1e391db1..00000000
--- a/src/main/launcher/avs-context.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include
-
-#include
-#include
-#include
-
-#include "imports/avs.h"
-
-#include "launcher/avs-context.h"
-
-#include "util/log.h"
-
-static void *avs_heap;
-
-#ifdef AVS_HAS_STD_HEAP
-static void *std_heap;
-#endif
-
-void avs_context_init(
- struct property_node *config,
- uint32_t avs_heap_size,
- uint32_t std_heap_size,
- avs_log_writer_t log_writer,
- void *log_writer_ctx)
-{
- avs_heap = VirtualAlloc(
- NULL, avs_heap_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
-
- if (avs_heap == NULL) {
- log_fatal(
- "Failed to VirtualAlloc %d byte AVS heap: %08x",
- avs_heap_size,
- (unsigned int) GetLastError());
- }
-
-#ifdef AVS_HAS_STD_HEAP
- std_heap = VirtualAlloc(
- NULL, std_heap_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
-
- if (std_heap == NULL) {
- log_fatal(
- "Failed to VirtualAlloc %d byte \"std\" heap: %08x",
- std_heap_size,
- (unsigned int) GetLastError());
- }
-#endif
-
-#ifdef AVS_HAS_STD_HEAP
- avs_boot(
- config,
- std_heap,
- std_heap_size,
- avs_heap,
- avs_heap_size,
- log_writer,
- log_writer_ctx);
-#else
- /* AVS v2.16.xx and I suppose onward uses a unified heap */
- avs_boot(config, avs_heap, avs_heap_size, NULL, log_writer, log_writer_ctx);
-#endif
-}
-
-void avs_context_fini(void)
-{
- avs_shutdown();
-
-#ifdef AVS_HAS_STD_HEAP
- VirtualFree(std_heap, 0, MEM_RELEASE);
-#endif
-
- VirtualFree(avs_heap, 0, MEM_RELEASE);
-}
diff --git a/src/main/launcher/avs-context.h b/src/main/launcher/avs-context.h
deleted file mode 100644
index d4532eb4..00000000
--- a/src/main/launcher/avs-context.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef LAUNCHER_AVS_CONTEXT_H
-#define LAUNCHER_AVS_CONTEXT_H
-
-#include
-
-#include "imports/avs.h"
-
-#if AVS_VERSION < 1600
-#define AVS_HAS_STD_HEAP
-#endif
-
-void avs_context_init(
- struct property_node *config,
- uint32_t avs_heap_size,
- uint32_t std_heap_size,
- avs_log_writer_t log_writer,
- void *log_writer_ctx);
-void avs_context_fini(void);
-
-#endif
diff --git a/src/main/launcher/avs.c b/src/main/launcher/avs.c
new file mode 100644
index 00000000..16dcbd20
--- /dev/null
+++ b/src/main/launcher/avs.c
@@ -0,0 +1,307 @@
+#define LOG_MODULE "avs"
+
+#include
+
+#include
+#include
+#include
+
+#include "imports/avs.h"
+
+#include "launcher/avs-config.h"
+#include "launcher/avs.h"
+#include "launcher/logger.h"
+#include "launcher/property-util.h"
+
+#include "util/codepage.h"
+#include "util/fs.h"
+#include "util/log.h"
+#include "util/mem.h"
+#include "util/str.h"
+
+#if AVS_VERSION < 1600
+#define AVS_HAS_STD_HEAP
+#endif
+
+static void *avs_heap;
+
+#ifdef AVS_HAS_STD_HEAP
+static void *std_heap;
+#endif
+
+/* Gratuitous API changes orz */
+static AVS_LOG_WRITER(_avs_context_log_writer, chars, nchars, ctx)
+{
+ wchar_t *utf16;
+ char *utf8;
+ int utf16_len;
+ int utf8_len;
+ int result;
+
+ /* Ignore existing NUL terminator */
+
+ nchars--;
+
+ /* Transcode shit_jis to UTF-8 */
+
+ utf16_len = MultiByteToWideChar(CP_SHIFT_JIS, 0, chars, nchars, NULL, 0);
+
+ if (utf16_len == 0) {
+ abort();
+ }
+
+ utf16 = xmalloc(sizeof(*utf16) * utf16_len);
+ result =
+ MultiByteToWideChar(CP_SHIFT_JIS, 0, chars, nchars, utf16, utf16_len);
+
+ if (result == 0) {
+ abort();
+ }
+
+ utf8_len =
+ WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, NULL, 0, NULL, NULL);
+
+ if (utf8_len == 0) {
+ abort();
+ }
+
+ utf8 = xmalloc(utf8_len + 3);
+ result = WideCharToMultiByte(
+ CP_UTF8, 0, utf16, utf16_len, utf8, utf8_len, NULL, NULL);
+
+ if (result == 0) {
+ abort();
+ }
+
+#if AVS_VERSION >= 1500
+ utf8[utf8_len + 0] = '\r';
+ utf8[utf8_len + 1] = '\n';
+
+ utf8_len += 2;
+#endif
+
+ // Clean string terminate
+ utf8[utf8_len] = '\0';
+
+ // Write to launcher's dedicated logging backend
+ logger_log_avs_log_message(utf8, utf8_len);
+
+ /* Clean up */
+
+ free(utf8);
+ free(utf16);
+}
+
+void avs_fs_assert_root_device_exists(struct property_node *node)
+{
+ char root_device_path[PATH_MAX];
+ char cwd_path[PATH_MAX];
+
+ avs_config_fs_root_device_get(
+ node, root_device_path, sizeof(root_device_path));
+ getcwd(cwd_path, sizeof(cwd_path));
+
+ if (!path_exists(root_device_path)) {
+ log_fatal(
+ "Root device path '%s' does not exist in current working dir '%s'",
+ root_device_path,
+ cwd_path);
+ }
+}
+
+void avs_fs_mountpoint_dir_create(
+ struct property_node *node, const char *folder_name)
+{
+ char fs_path[1024];
+ char fs_type[255];
+ char device_path[1024];
+ struct property_node *fs_node;
+ int res;
+
+ memset(fs_path, 0, sizeof(fs_path));
+ memset(fs_type, 0, sizeof(fs_type));
+
+ str_cpy(fs_path, sizeof(fs_path), "/fs/");
+ str_cat(fs_path, sizeof(fs_path), folder_name);
+
+ fs_node = property_search(NULL, node, fs_path);
+
+ if (!fs_node) {
+ log_warning(
+ "Could not find file system node %s in avs configuration", fs_path);
+ return;
+ }
+
+ res = property_node_refer(
+ NULL,
+ fs_node,
+ "device",
+ PROPERTY_TYPE_STR,
+ device_path,
+ sizeof(device_path));
+
+ if (res < 0) {
+ log_fatal(
+ "Getting 'device' attribute from avs config entry %s failed",
+ fs_path);
+ }
+
+ // 'fstype' attribute is optional and defaults to value 'fs'
+ if (!property_search(NULL, fs_node, "fstype")) {
+ if (path_exists(device_path)) {
+ // skip if exists already
+ return;
+ }
+
+ log_misc("Creating avs directory %s", device_path);
+
+ if (!path_mkdir(device_path)) {
+ log_fatal("Creating directory %s failed", device_path);
+ }
+ } else {
+ res = property_node_refer(
+ NULL,
+ fs_node,
+ "fstype",
+ PROPERTY_TYPE_STR,
+ fs_type,
+ sizeof(fs_type));
+
+ if (res < 0) {
+ log_fatal(
+ "Getting 'fstype' attribute from avs config entry %s failed",
+ fs_path);
+ }
+
+ if (!strcmp(fs_type, "fs") || !strcmp(fs_type, "nvram")) {
+ if (path_exists(device_path)) {
+ // skip if exists already
+ return;
+ }
+
+ log_misc("Creating avs directory %s", device_path);
+
+ if (!path_mkdir(device_path)) {
+ log_fatal("Creating directory %s failed", device_path);
+ }
+ } else {
+ log_fatal(
+ "Cannot create folders for unsupported file system type %s of "
+ "path %s in avs config",
+ fs_type,
+ fs_path);
+ }
+ }
+}
+
+void avs_init(
+ struct property_node *node, uint32_t avs_heap_size, uint32_t std_heap_size)
+{
+ log_assert(node);
+ log_assert(avs_heap_size > 0);
+ log_assert(std_heap_size > 0);
+
+ log_info("init");
+
+ avs_heap = VirtualAlloc(
+ NULL, avs_heap_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+
+ if (avs_heap == NULL) {
+ log_fatal(
+ "Failed to VirtualAlloc %d byte AVS heap: %08x",
+ avs_heap_size,
+ (unsigned int) GetLastError());
+ }
+
+#ifdef AVS_HAS_STD_HEAP
+ std_heap = VirtualAlloc(
+ NULL, std_heap_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+
+ if (std_heap == NULL) {
+ log_fatal(
+ "Failed to VirtualAlloc %d byte \"std\" heap: %08x",
+ std_heap_size,
+ (unsigned int) GetLastError());
+ }
+#endif
+
+ log_info("Calling avs_boot");
+
+#ifdef AVS_HAS_STD_HEAP
+ avs_boot(
+ node,
+ std_heap,
+ std_heap_size,
+ avs_heap,
+ avs_heap_size,
+ _avs_context_log_writer,
+ NULL);
+#else
+ /* AVS v2.16.xx and I suppose onward uses a unified heap */
+ avs_boot(
+ node, avs_heap, avs_heap_size, NULL, _avs_context_log_writer, NULL);
+#endif
+
+ log_misc("init done");
+}
+
+void avs_fs_file_copy(const char *src, const char *dst)
+{
+ struct avs_stat st;
+
+ log_assert(src);
+ log_assert(dst);
+
+ log_misc("Copying %s to %s...", src, dst);
+
+ if (!avs_fs_lstat(src, &st)) {
+ log_fatal("File source %s does not exist or is not accessible", src);
+ }
+
+ if (avs_fs_copy(src, dst) < 0) {
+ log_fatal("Failed copying file %s to %s", src, dst);
+ }
+}
+
+void avs_fs_dir_log(const char *path)
+{
+ const char *name;
+
+ log_assert(path);
+
+ avs_desc dir = avs_fs_opendir(path);
+
+ if (dir < 0) {
+ log_warning(
+ "Opening avs dir %s failed, skipping logging contents", path);
+ }
+
+ log_misc("Contents of %s:", path);
+
+ do {
+ name = avs_fs_readdir(dir);
+
+ if (name == NULL) {
+ break;
+ }
+
+ log_misc("%s", name);
+ } while (name != NULL);
+
+ avs_fs_closedir(dir);
+}
+
+void avs_fini(void)
+{
+ log_info("fini");
+
+ avs_shutdown();
+
+#ifdef AVS_HAS_STD_HEAP
+ VirtualFree(std_heap, 0, MEM_RELEASE);
+#endif
+
+ VirtualFree(avs_heap, 0, MEM_RELEASE);
+
+ log_misc("fini done");
+}
diff --git a/src/main/launcher/avs.h b/src/main/launcher/avs.h
new file mode 100644
index 00000000..a333f36f
--- /dev/null
+++ b/src/main/launcher/avs.h
@@ -0,0 +1,17 @@
+#ifndef LAUNCHER_AVS_H
+#define LAUNCHER_AVS_H
+
+#include
+
+#include "imports/avs.h"
+
+void avs_fs_assert_root_device_exists(struct property_node *node);
+void avs_fs_mountpoint_dir_create(
+ struct property_node *node, const char *folder_name);
+void avs_init(
+ struct property_node *node, uint32_t avs_heap_size, uint32_t std_heap_size);
+void avs_fs_file_copy(const char *src, const char *dst);
+void avs_fs_dir_log(const char *path);
+void avs_fini(void);
+
+#endif
diff --git a/src/main/launcher/bootstrap-config.c b/src/main/launcher/bootstrap-config.c
new file mode 100644
index 00000000..fa7064e4
--- /dev/null
+++ b/src/main/launcher/bootstrap-config.c
@@ -0,0 +1,538 @@
+#define LOG_MODULE "bootstrap-config"
+
+#include
+
+#include "imports/avs.h"
+
+#include "launcher/avs-config.h"
+#include "launcher/bootstrap-config.h"
+#include "launcher/property-util.h"
+
+#include "util/defs.h"
+#include "util/hex.h"
+#include "util/log.h"
+#include "util/str.h"
+
+// clang-format off
+PSMAP_BEGIN(bootstrap_startup_boot_psmap)
+PSMAP_REQUIRED(PSMAP_TYPE_STR, struct bootstrap_boot_config, config_file,
+ "boot/file")
+PSMAP_REQUIRED(PSMAP_TYPE_U32, struct bootstrap_boot_config, avs_heap_size,
+ "boot/heap_avs")
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_boot_config, std_heap_size,
+ "boot/heap_std", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_boot_config, mount_table_selector,
+ "boot/mounttable_selector", "boot")
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_boot_config, watcher_enable,
+ "boot/watcher", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_boot_config, timemachine_enable,
+ "boot/timemachine", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_boot_config, launch_config_file,
+ "boot/launch_path", "/dev/raw/launch.xml")
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_log_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_log_config, level,
+ "log/level", "all")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_log_config, name,
+ "log/name", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_log_config, file,
+ "log/file", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_log_config, bufsz,
+ "log/sz_buf", 4096)
+PSMAP_OPTIONAL(PSMAP_TYPE_U16, struct bootstrap_log_config, output_delay_ms,
+ "log/output_delay", 10)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_log_config, enable_console,
+ "log/enable_console", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_log_config, enable_sci,
+ "log/enable_netsci", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_log_config, enable_net,
+ "log/enable_netlog", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_log_config, enable_file,
+ "log/enable_file", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_log_config, rotate,
+ "log/rotate", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_log_config, append,
+ "log/append", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_U16, struct bootstrap_log_config, count,
+ "log/gen", 10)
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_minidump_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_U8, struct bootstrap_minidump_config, count,
+ "minidump/gen", 10)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_minidump_config, continue_,
+ "minidump/cont_debug", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_minidump_config, log,
+ "minidump/echo_log", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_U8, struct bootstrap_minidump_config, type,
+ "minidump/dump_type", 2)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_minidump_config, path,
+ "minidump/path", "/dev/raw/minidump")
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_minidump_config, symbufsz,
+ "minidump/sz_symbuf", 32768)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_minidump_config, search_path,
+ "minidump/search", ".")
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_module_psmap)
+PSMAP_REQUIRED(PSMAP_TYPE_STR, struct bootstrap_module_config, file,
+ "component/file")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_module_config, load_type,
+ "component/load_type", "MEMORY")
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_dlm_psmap)
+/* disabled until we implement PSMAP_TYPE_BIN
+ PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_startup_config, ntdll_digest,
+ "dlml/ntdll/hash", "")
+ */
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_dlm_config, size,
+ "dlml/ntdll/size", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_dlm_config, ift_table,
+ "dlml/ntdll/ift_table", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_dlm_config, ift_insert,
+ "dlml/ntdll/insert_ift", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_dlm_config, ift_remove,
+ "dlml/ntdll/remove_ift", 0)
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_shield_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_shield_config, enable,
+ "shield/enable", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_shield_config, verbose,
+ "shield/verbose", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_shield_config, use_loadlibrary,
+ "shield/use_loadlibrary", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_shield_config, logger,
+ "shield/logger", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_shield_config, sleep_min,
+ "shield/sleepmin", 10)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_shield_config, sleep_blur,
+ "shield/sleepblur", 90)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_shield_config, whitelist_file,
+ "shield/whitelist", "prop/whitelist.csv")
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_shield_config, tick_sleep,
+ "shield/ticksleep", 100)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_shield_config, tick_error,
+ "shield/tickerror", 1000)
+PSMAP_OPTIONAL(PSMAP_TYPE_U8, struct bootstrap_shield_config, overwork_threshold,
+ "shield/overwork_threshold", 50)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_shield_config, overwork_delay,
+ "shield/overwork_delay", 100)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_shield_config, pause_delay,
+ "shield/pause_delay", 1000)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_shield_config, unlimited_key,
+ "shield/unlimited_key", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_U16, struct bootstrap_shield_config, killer_port,
+ "shield_killer/port", 5001)
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_dongle_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_dongle_config, license_cn,
+ "dongle/license", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_dongle_config, account_cn,
+ "dongle/account", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_dongle_config, driver_dll,
+ "dongle/pkcs11_driver", "eTPKCS11.dll")
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_dongle_config, disable_gc,
+ "dongle/disable_gc", 0)
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_drm_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_drm_config, dll,
+ "drm/dll", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_drm_config, fstype,
+ "drm/fstype", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_drm_config, device,
+ "drm/device", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_drm_config, mount,
+ "drm/dst", "/")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_drm_config, options,
+ "drm/option", "")
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_lte_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_lte_config, enable,
+ "lte/enable", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_lte_config, config_file,
+ "lte/file", "/dev/nvram/lte-config.xml")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_lte_config, unlimited_key,
+ "lte/unlimited_key", "")
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_ssl_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_ssl_config, options,
+ "ssl/option", "")
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_esign_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_esign_config, enable,
+ "esign/enable", 0)
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_startup_eamuse_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_eamuse_config, enable,
+ "eamuse/enable", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_eamuse_config, sync,
+ "eamuse/sync", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_eamuse_config, enable_model,
+ "eamuse/enable_model", 0)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_eamuse_config, config_file,
+ "eamuse/file", "/dev/nvram/ea3-config.xml")
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct bootstrap_eamuse_config, updatecert_enable,
+ "eamuse/updatecert_enable", 1)
+PSMAP_OPTIONAL(PSMAP_TYPE_U32, struct bootstrap_eamuse_config, updatecert_interval,
+ "eamuse/updatecert_interval", 0)
+PSMAP_END
+
+PSMAP_BEGIN(bootstrap_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_config, release_code, "/release_code", "")
+PSMAP_END
+// clang-format on
+
+#define ROOT_NODE "/config"
+#define MODULE_PATH_PREFIX "modules/"
+
+#define NODE_MISSING_FATAL(subnode) \
+ log_fatal("%s/%s: Node missing", ROOT_NODE, subnode);
+#define NODE_STARTUP_MISSING_FATAL(profile) \
+ log_fatal("%s/startup/%s: Node missing", ROOT_NODE, profile);
+#define NODE_PROFILE_MISSING_FATAL(profile, subnode) \
+ log_fatal("%s/%s/%s: Node missing", ROOT_NODE, profile, subnode);
+#define NODE_PROFILE_LOADING_FATAL(profile, subnode) \
+ log_fatal("%s/startup/%s/%s: Node loading", ROOT_NODE, profile, subnode);
+
+#define DEFAULT_HEAP_SIZE 16777216
+
+const char *const inherited_nodes[] = {
+ "develop",
+ "default",
+ "log",
+ "minidump",
+ "boot",
+ "drm",
+ "ssl",
+ "eamuse",
+ "shield",
+ "esign",
+ "dongle",
+ "lte",
+};
+
+static void _bootstrap_config_profile_node_verify(
+ struct property_node *node, const char *profile)
+{
+ struct property_node *profile_node;
+
+ log_assert(node);
+ log_assert(profile);
+
+ profile_node = property_search(NULL, node, profile);
+
+ if (!profile_node) {
+ NODE_STARTUP_MISSING_FATAL(profile);
+ }
+}
+
+static struct property_node *
+_bootstrap_config_root_node_get(struct property *property)
+{
+ struct property_node *root_node;
+
+ log_assert(property);
+
+ root_node = property_search(property, NULL, ROOT_NODE);
+
+ if (!root_node) {
+ NODE_MISSING_FATAL("");
+ }
+
+ return root_node;
+}
+
+static struct property_node *
+_bootstrap_config_startup_node_get(struct property_node *node)
+{
+ struct property_node *startup_node;
+
+ log_assert(node);
+
+ startup_node = property_search(NULL, node, "startup");
+
+ if (!startup_node) {
+ NODE_MISSING_FATAL("startup");
+ }
+
+ return startup_node;
+}
+
+static void _bootstrap_config_inheritance_resolve(
+ struct property_node *startup_node, const char *profile_name)
+{
+ struct property_node *startup_parent_node;
+ struct property_node *startup_profile_node;
+ struct property_node *tmp_node;
+
+ char inherit_name[64];
+ avs_error error;
+
+ startup_profile_node = property_search(NULL, startup_node, profile_name);
+
+ if (!startup_profile_node) {
+ log_fatal(ROOT_NODE "/startup/%s: missing", profile_name);
+ }
+
+ startup_parent_node = startup_profile_node;
+
+ for (;;) {
+ error = property_node_refer(
+ NULL,
+ startup_parent_node,
+ "inherit@",
+ PROPERTY_TYPE_ATTR,
+ inherit_name,
+ sizeof(inherit_name));
+
+ if (AVS_IS_ERROR(error)) {
+ break;
+ }
+
+ startup_parent_node = property_search(NULL, startup_node, inherit_name);
+
+ if (!startup_parent_node) {
+ NODE_STARTUP_MISSING_FATAL(inherit_name);
+ }
+
+ for (int i = 0; i < _countof(inherited_nodes); i++) {
+ if (property_search(NULL, startup_node, inherited_nodes[i])) {
+ continue;
+ }
+
+ tmp_node =
+ property_search(NULL, startup_parent_node, inherited_nodes[i]);
+
+ if (tmp_node) {
+ log_misc(
+ ROOT_NODE "/startup/%s: merging %s...",
+ inherit_name,
+ inherited_nodes[i]);
+
+ property_node_clone(NULL, startup_profile_node, tmp_node, TRUE);
+ }
+ }
+ }
+}
+
+static void _bootstrap_config_load_bootstrap_module_app_config(
+ struct property_node *profile_node, struct bootstrap_module_config *config)
+{
+ struct property_node *app_node;
+
+ log_assert(profile_node);
+ log_assert(config);
+
+ app_node = property_search(NULL, profile_node, "component/param");
+
+ config->app_config = property_util_clone(app_node);
+}
+
+static void _bootstrap_config_load_bootstrap_default_files_config(
+ const char *profile_name,
+ struct property_node *profile_node,
+ struct bootstrap_default_file_config *config)
+{
+ int i;
+ int result;
+ struct property_node *child;
+
+ log_assert(profile_node);
+ log_assert(config);
+
+ child = property_search(NULL, profile_node, "default/file");
+ i = 0;
+
+ while (child) {
+ if (i >= DEFAULT_FILE_MAX) {
+ log_warning(
+ "Currently not supporting more than %d default files, skipping "
+ "remaining",
+ i);
+ break;
+ }
+
+ result = property_node_refer(
+ NULL,
+ child,
+ "src@",
+ PROPERTY_TYPE_ATTR,
+ &config->file[i].src,
+ sizeof(config->file[i].src));
+
+ if (result < 0) {
+ log_fatal(
+ "Missing src attribute on default file node of profile %s",
+ profile_name);
+ }
+
+ result = property_node_refer(
+ NULL,
+ child,
+ "dst@",
+ PROPERTY_TYPE_ATTR,
+ &config->file[i].dst,
+ sizeof(config->file[i].dst));
+
+ if (result < 0) {
+ log_fatal(
+ "Missing dst attribute on default file node of profile %s",
+ profile_name);
+ }
+
+ child = property_node_traversal(child, TRAVERSE_NEXT_SEARCH_RESULT);
+ i++;
+ }
+}
+
+static void _bootstrap_config_load_bootstrap(
+ struct property_node *startup_node,
+ const char *profile,
+ struct bootstrap_startup_config *config)
+{
+ struct property_node *profile_node;
+
+ profile_node = property_search(NULL, startup_node, profile);
+
+ if (!profile_node) {
+ NODE_PROFILE_LOADING_FATAL(profile, "");
+ }
+
+ _bootstrap_config_load_bootstrap_default_files_config(
+ profile, profile_node, &config->default_file);
+
+ if (!property_psmap_import(
+ NULL, profile_node, &config->boot, bootstrap_startup_boot_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "boot");
+ }
+
+ if (!property_psmap_import(
+ NULL, profile_node, &config->log, bootstrap_startup_log_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "log");
+ }
+
+ if (!property_psmap_import(
+ NULL,
+ profile_node,
+ &config->minidump,
+ bootstrap_startup_minidump_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "minidump");
+ }
+
+ if (!property_psmap_import(
+ NULL,
+ profile_node,
+ &config->module,
+ bootstrap_startup_module_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "component");
+ }
+
+ _bootstrap_config_load_bootstrap_module_app_config(
+ profile_node, &config->module);
+
+ if (!property_psmap_import(
+ NULL,
+ profile_node,
+ &config->dlm_ntdll,
+ bootstrap_startup_dlm_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "dlm/ntdll");
+ }
+
+ if (!property_psmap_import(
+ NULL,
+ profile_node,
+ &config->shield,
+ bootstrap_startup_shield_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "shield");
+ }
+
+ if (!property_psmap_import(
+ NULL,
+ profile_node,
+ &config->dongle,
+ bootstrap_startup_dongle_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "dongle");
+ }
+
+ if (!property_psmap_import(
+ NULL, profile_node, &config->drm, bootstrap_startup_drm_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "drm");
+ }
+
+ if (!property_psmap_import(
+ NULL, profile_node, &config->lte, bootstrap_startup_lte_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "lte");
+ }
+
+ if (!property_psmap_import(
+ NULL, profile_node, &config->ssl, bootstrap_startup_ssl_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "ssl");
+ }
+
+ if (!property_psmap_import(
+ NULL,
+ profile_node,
+ &config->esign,
+ bootstrap_startup_esign_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "esign");
+ }
+
+ if (!property_psmap_import(
+ NULL,
+ profile_node,
+ &config->eamuse,
+ bootstrap_startup_eamuse_psmap)) {
+ NODE_PROFILE_LOADING_FATAL(profile, "eamuse");
+ }
+}
+
+void bootstrap_config_init(struct bootstrap_config *config)
+{
+ log_assert(config);
+
+ memset(config, 0, sizeof(*config));
+}
+
+void bootstrap_config_load(
+ struct property *property,
+ const char *profile,
+ struct bootstrap_config *config)
+{
+ struct property_node *root_node;
+ struct property_node *startup_node;
+
+ log_assert(property);
+ log_assert(profile);
+ log_assert(config);
+
+ log_info(ROOT_NODE ": loading...");
+
+ root_node = _bootstrap_config_root_node_get(property);
+
+ if (!property_psmap_import(NULL, root_node, config, bootstrap_psmap)) {
+ log_fatal(ROOT_NODE ": loading failed");
+ }
+
+ startup_node = _bootstrap_config_startup_node_get(root_node);
+
+ _bootstrap_config_profile_node_verify(startup_node, profile);
+
+ _bootstrap_config_inheritance_resolve(startup_node, profile);
+
+ log_misc(ROOT_NODE "/startup/%s: loading merged result...", profile);
+
+ property_util_node_log(startup_node);
+
+ _bootstrap_config_load_bootstrap(startup_node, profile, &config->startup);
+
+ log_misc("Loading finished");
+}
\ No newline at end of file
diff --git a/src/main/launcher/bootstrap-config.h b/src/main/launcher/bootstrap-config.h
new file mode 100644
index 00000000..596bf93f
--- /dev/null
+++ b/src/main/launcher/bootstrap-config.h
@@ -0,0 +1,139 @@
+#ifndef LAUNCHER_BOOTSTRAP_CONFIG_H
+#define LAUNCHER_BOOTSTRAP_CONFIG_H
+
+#include
+#include
+
+#include "imports/avs.h"
+
+// should be enough for a while
+#define DEFAULT_FILE_MAX 16
+
+struct bootstrap_startup_config {
+ struct bootstrap_default_file_config {
+ struct bootstrap_default_file {
+ char src[64];
+ char dst[64];
+ } file[DEFAULT_FILE_MAX];
+ } default_file;
+
+ struct bootstrap_boot_config {
+ char config_file[64];
+ uint32_t avs_heap_size;
+ uint32_t std_heap_size;
+ char launch_config_file[64];
+ char mount_table_selector[16];
+ bool watcher_enable;
+ bool timemachine_enable;
+ } boot;
+
+ struct bootstrap_log_config {
+ char level[8];
+ char name[64];
+ char file[64];
+ uint32_t bufsz;
+ uint16_t output_delay_ms;
+ bool enable_console;
+ bool enable_sci;
+ bool enable_net;
+ bool enable_file;
+ bool rotate;
+ bool append;
+ uint16_t count;
+ } log;
+
+ struct bootstrap_minidump_config {
+ uint8_t count;
+ bool continue_;
+ bool log;
+ uint8_t type;
+ char path[64];
+ uint32_t symbufsz;
+ char search_path[64];
+ } minidump;
+
+ struct bootstrap_module_config {
+ char file[64];
+ char load_type[64];
+ struct property *app_config;
+ } module;
+
+ struct bootstrap_dlm_config {
+ char digest[16];
+ uint32_t size;
+ uint32_t ift_table;
+ uint32_t ift_insert;
+ uint32_t ift_remove;
+ };
+
+ struct bootstrap_dlm_config dlm_ntdll;
+
+ struct bootstrap_shield_config {
+ bool enable;
+ bool verbose;
+ bool use_loadlibrary;
+ char logger[64];
+ uint32_t sleep_min;
+ uint32_t sleep_blur;
+ uint32_t tick_sleep;
+ uint32_t tick_error;
+ uint8_t overwork_threshold;
+ uint32_t overwork_delay;
+ uint32_t pause_delay;
+ char whitelist_file[64];
+ char unlimited_key[10];
+ uint16_t killer_port;
+ } shield;
+
+ struct bootstrap_dongle_config {
+ char license_cn[32];
+ char account_cn[32];
+ char driver_dll[16];
+ bool disable_gc;
+ } dongle;
+
+ struct bootstrap_drm_config {
+ char dll[64];
+ char device[64];
+ char mount[64];
+ char fstype[64];
+ char options[64];
+ } drm;
+
+ struct bootstrap_lte_config {
+ bool enable;
+ char config_file[64];
+ char unlimited_key[10];
+ } lte;
+
+ struct bootstrap_ssl_config {
+ char options[64];
+ } ssl;
+
+ struct bootstrap_esign_config {
+ bool enable;
+ } esign;
+
+ struct bootstrap_eamuse_config {
+ bool enable;
+ bool sync;
+ bool enable_model;
+ char config_file[64];
+ bool updatecert_enable;
+ uint32_t updatecert_interval;
+ } eamuse;
+};
+
+struct bootstrap_config {
+ char release_code[16];
+ struct bootstrap_startup_config startup;
+};
+
+void bootstrap_config_init(struct bootstrap_config *config);
+
+void bootstrap_config_load(
+ struct property *property,
+ const char *profile,
+ struct bootstrap_config *config);
+
+#endif /* LAUNCHER_BOOTSTRAP_CONFIG_H */
diff --git a/src/main/launcher/bootstrap.c b/src/main/launcher/bootstrap.c
new file mode 100644
index 00000000..a9123786
--- /dev/null
+++ b/src/main/launcher/bootstrap.c
@@ -0,0 +1,294 @@
+#define LOG_MODULE "bootstrap"
+
+#include "launcher/avs-config.h"
+#include "launcher/avs.h"
+#include "launcher/bootstrap-config.h"
+#include "launcher/ea3-ident-config.h"
+#include "launcher/eamuse-config.h"
+#include "launcher/eamuse.h"
+#include "launcher/launcher-config.h"
+#include "launcher/logger.h"
+#include "launcher/module.h"
+#include "launcher/property-util.h"
+
+#include "util/log.h"
+#include "util/str.h"
+
+static bool _bootstrap_log_property_configs;
+static struct module_context _bootstrap_module_context;
+
+static void _bootstrap_eamuse_ea3_ident_config_inject(
+ struct property_node *node, const struct ea3_ident_config *ea3_ident_config)
+{
+ eamuse_config_id_softid_set(node, ea3_ident_config->softid);
+ eamuse_config_id_hardid_set(node, ea3_ident_config->hardid);
+ eamuse_config_id_pcbid_set(node, ea3_ident_config->pcbid);
+ eamuse_config_soft_model_set(node, ea3_ident_config->model);
+ eamuse_config_soft_dest_set(node, ea3_ident_config->dest);
+ eamuse_config_soft_spec_set(node, ea3_ident_config->spec);
+ eamuse_config_soft_rev_set(node, ea3_ident_config->rev);
+ eamuse_config_soft_ext_set(node, ea3_ident_config->ext);
+}
+
+static void
+_bootstrap_avs_config_force_overrides_apply(struct property_node *node)
+{
+ log_assert(node);
+
+ avs_config_mode_product_set(node, true);
+ avs_config_net_raw_set(node, true);
+ avs_config_net_eaudp_set(node, true);
+ avs_config_sntp_ea_set(node, true);
+}
+
+static void _bootstrap_avs_config_log_overrides_apply(
+ struct property_node *node, const struct bootstrap_log_config *log_config)
+{
+ log_assert(node);
+ log_assert(log_config);
+
+ avs_config_log_level_set(node, log_config->level);
+ avs_config_log_name_set(node, log_config->name);
+ avs_config_log_file_set(node, log_config->file);
+ avs_config_log_buffer_size_set(node, log_config->bufsz);
+ avs_config_log_output_delay_set(node, log_config->output_delay_ms);
+ avs_config_log_enable_console_set(node, log_config->enable_console);
+ avs_config_log_enable_sci_set(node, log_config->enable_sci);
+ avs_config_log_enable_net_set(node, log_config->enable_net);
+ avs_config_log_enable_file_set(node, log_config->enable_file);
+ avs_config_log_rotate_set(node, log_config->rotate);
+ avs_config_log_append_set(node, log_config->append);
+ avs_config_log_count_set(node, log_config->count);
+}
+
+static enum logger_level _bootstrap_log_map_level(const char *level)
+{
+ if (str_eq(level, "fatal")) {
+ return LOGGER_LEVEL_FATAL;
+ } else if (str_eq(level, "warning")) {
+ return LOGGER_LEVEL_WARNING;
+ } else if (str_eq(level, "info")) {
+ return LOGGER_LEVEL_INFO;
+ } else if (str_eq(level, "misc")) {
+ return LOGGER_LEVEL_MISC;
+ } else if (str_eq(level, "all")) {
+ return LOGGER_LEVEL_ALL;
+ } else if (str_eq(level, "disable")) {
+ return LOGGER_LEVEL_OFF;
+ } else if (str_eq(level, "default")) {
+ return LOGGER_LEVEL_DEFAULT;
+ } else {
+ log_fatal("Unknown log level string %s", level);
+ }
+}
+
+void bootstrap_init(bool log_property_configs)
+{
+ log_info("init");
+
+ _bootstrap_log_property_configs = log_property_configs;
+
+ log_misc("init done");
+}
+
+void bootstrap_log_init(const struct bootstrap_log_config *config)
+{
+ enum logger_level level;
+
+ log_assert(config);
+
+ log_info("log init");
+
+ logger_init(
+ config->file,
+ config->enable_console,
+ config->enable_file,
+ config->rotate,
+ config->append,
+ config->count);
+
+ level = _bootstrap_log_map_level(config->level);
+ logger_level_set(level);
+
+ log_misc("log init done");
+}
+
+void bootstrap_default_files_create(
+ const struct bootstrap_default_file_config *config)
+{
+ log_assert(config);
+
+ log_info("default files create");
+
+ for (int i = 0; i < DEFAULT_FILE_MAX; i++) {
+ if (strlen(config->file[i].src) > 0 &&
+ strlen(config->file[i].dst) > 0) {
+ avs_fs_file_copy(config->file[i].src, config->file[i].dst);
+ }
+ }
+
+ log_misc("default files create done");
+}
+
+void bootstrap_avs_init(
+ const struct bootstrap_boot_config *config,
+ const struct bootstrap_log_config *log_config,
+ struct property_node *override_node)
+{
+ struct property *property;
+ struct property_node *node;
+
+ log_assert(config);
+ log_assert(log_config);
+ log_assert(override_node);
+
+ log_info("avs init");
+
+ property = avs_config_load(config->config_file);
+ node = avs_config_root_get(property);
+
+ property_util_node_merge(property, node, override_node);
+
+ if (_bootstrap_log_property_configs) {
+ log_misc("avs-config");
+ property_util_node_log(node);
+ }
+
+ _bootstrap_avs_config_force_overrides_apply(node);
+ _bootstrap_avs_config_log_overrides_apply(node, log_config);
+
+ avs_fs_assert_root_device_exists(node);
+
+ log_misc("Creating AVS file system directories for nvram and raw...");
+
+ avs_fs_mountpoint_dir_create(node, "nvram");
+ avs_fs_mountpoint_dir_create(node, "raw");
+
+ avs_init(node, config->avs_heap_size, config->std_heap_size);
+
+ property_util_free(property);
+
+ log_misc("avs init done");
+}
+
+void bootstrap_eamuse_init(
+ const struct bootstrap_eamuse_config *config,
+ const struct ea3_ident_config *ea3_ident_config,
+ struct property_node *override_node)
+{
+ struct property *property;
+ struct property_node *node;
+
+ log_assert(config);
+ log_assert(ea3_ident_config);
+ log_assert(override_node);
+
+ log_info("eamuse init");
+
+ if (config->enable) {
+ property = eamuse_config_avs_load(config->config_file);
+ node = eamuse_config_root_get(property);
+
+ property_util_node_merge(property, node, override_node);
+
+ _bootstrap_eamuse_ea3_ident_config_inject(node, ea3_ident_config);
+
+ property_util_node_log(node);
+
+ if (_bootstrap_log_property_configs) {
+ log_misc("eamuse-config");
+ property_util_node_log(node);
+ }
+
+ eamuse_init(node);
+
+ property_util_free(property);
+ } else {
+ log_warning("Eamuse disabled");
+ }
+
+ log_misc("eamuse init done");
+}
+
+void bootstrap_module_init(
+ const struct bootstrap_module_config *module_config,
+ const struct array *iat_hook_dlls)
+{
+ log_assert(module_config);
+ log_assert(iat_hook_dlls);
+
+ log_info("module init");
+
+ if (iat_hook_dlls->nitems > 0) {
+ log_info(
+ "Load game DLL with IAT hooks (%d): %s",
+ (uint32_t) iat_hook_dlls->nitems,
+ module_config->file);
+
+ module_with_iat_hooks_init(
+ &_bootstrap_module_context, module_config->file, iat_hook_dlls);
+ } else {
+ log_info("Load game DLL: %s", module_config->file);
+
+ module_init(&_bootstrap_module_context, module_config->file);
+ }
+
+ log_misc("module init done");
+}
+
+void bootstrap_module_game_init(
+ const struct bootstrap_module_config *module_config,
+ struct ea3_ident_config *ea3_ident_config)
+{
+ struct property_node *node;
+
+ log_assert(module_config);
+ log_assert(ea3_ident_config);
+
+ log_info("module game init");
+
+ node = property_search(module_config->app_config, NULL, "/param");
+
+ if (!node) {
+ log_fatal("Missing param node on app-config");
+ }
+
+ if (_bootstrap_log_property_configs) {
+ log_misc("app-config");
+ property_util_node_log(node);
+ }
+
+ module_init_invoke(&_bootstrap_module_context, ea3_ident_config, node);
+
+ log_misc("module game init done");
+}
+
+void bootstrap_module_game_run()
+{
+ log_info("module game run");
+
+ module_main_invoke(&_bootstrap_module_context);
+}
+
+void bootstrap_module_game_fini()
+{
+ log_info("module game fini");
+
+ module_fini(&_bootstrap_module_context);
+}
+
+void bootstrap_avs_fini()
+{
+ log_info("avs fini");
+
+ avs_fini();
+}
+
+void bootstrap_eamuse_fini(const struct bootstrap_eamuse_config *config)
+{
+ log_info("eamuse fini");
+
+ if (config->enable) {
+ eamuse_fini();
+ }
+}
\ No newline at end of file
diff --git a/src/main/launcher/bootstrap.h b/src/main/launcher/bootstrap.h
new file mode 100644
index 00000000..9006bf7e
--- /dev/null
+++ b/src/main/launcher/bootstrap.h
@@ -0,0 +1,32 @@
+#ifndef LAUNCHER_BOOTSTRAP_H
+#define LAUNCHER_BOOTSTRAP_H
+
+#include "launcher/bootstrap-config.h"
+#include "launcher/ea3-ident-config.h"
+
+#include "util/array.h"
+
+void bootstrap_init(bool log_property_configs);
+void bootstrap_log_init(const struct bootstrap_log_config *config);
+void bootstrap_default_files_create(
+ const struct bootstrap_default_file_config *config);
+void bootstrap_avs_init(
+ const struct bootstrap_boot_config *config,
+ const struct bootstrap_log_config *log_config,
+ struct property_node *override_node);
+void bootstrap_eamuse_init(
+ const struct bootstrap_eamuse_config *config,
+ const struct ea3_ident_config *ea3_ident_config,
+ struct property_node *override_node);
+void bootstrap_module_init(
+ const struct bootstrap_module_config *module_config,
+ const struct array *iat_hook_dlls);
+void bootstrap_module_game_init(
+ const struct bootstrap_module_config *module_config,
+ struct ea3_ident_config *ea3_ident_config);
+void bootstrap_module_game_run();
+void bootstrap_module_game_fini();
+void bootstrap_avs_fini();
+void bootstrap_eamuse_fini(const struct bootstrap_eamuse_config *config);
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/debug.c b/src/main/launcher/debug.c
new file mode 100644
index 00000000..b8440af2
--- /dev/null
+++ b/src/main/launcher/debug.c
@@ -0,0 +1,33 @@
+
+#define LOG_MODULE "debug"
+
+#include
+#include
+
+#include "launcher/debug.h"
+
+#include "util/log.h"
+
+void debug_remote_debugger_trap()
+{
+ BOOL res;
+
+ log_info("Waiting until debugger attaches to remote process...");
+
+ while (true) {
+ res = FALSE;
+
+ if (!CheckRemoteDebuggerPresent(GetCurrentProcess(), &res)) {
+ log_fatal(
+ "CheckRemoteDebuggerPresent failed: %08x",
+ (unsigned int) GetLastError());
+ }
+
+ if (res) {
+ log_info("Debugger attached, resuming");
+ break;
+ }
+
+ Sleep(1000);
+ }
+}
\ No newline at end of file
diff --git a/src/main/launcher/debug.h b/src/main/launcher/debug.h
new file mode 100644
index 00000000..f57ca8ba
--- /dev/null
+++ b/src/main/launcher/debug.h
@@ -0,0 +1,6 @@
+#ifndef LAUNCHER_DEBUG_H
+#define LAUNCHER_DEBUG_H
+
+void debug_remote_debugger_trap();
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/ea3-config.c b/src/main/launcher/ea3-config.c
deleted file mode 100644
index 684ba466..00000000
--- a/src/main/launcher/ea3-config.c
+++ /dev/null
@@ -1,190 +0,0 @@
-#include
-
-#include "imports/avs.h"
-
-#include "launcher/ea3-config.h"
-#include "launcher/module.h"
-
-#include "util/defs.h"
-#include "util/hex.h"
-#include "util/log.h"
-#include "util/str.h"
-
-PSMAP_BEGIN(ea3_ident_psmap)
-PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct ea3_ident, softid, "/ea3/id/softid", "")
-PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct ea3_ident, hardid, "/ea3/id/hardid", "")
-PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct ea3_ident, pcbid, "/ea3/id/pcbid", "")
-PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident, model, "/ea3/soft/model")
-PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident, dest, "/ea3/soft/dest")
-PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident, spec, "/ea3/soft/spec")
-PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident, rev, "/ea3/soft/rev")
-PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident, ext, "/ea3/soft/ext")
-PSMAP_END
-
-void ea3_ident_init(struct ea3_ident *ident)
-{
- memset(ident, 0, sizeof(*ident));
-}
-
-bool ea3_ident_from_property(
- struct ea3_ident *ident, struct property *ea3_config)
-{
- return property_psmap_import(ea3_config, NULL, ident, ea3_ident_psmap);
-}
-
-void ea3_ident_hardid_from_ethernet(struct ea3_ident *ident)
-{
- struct avs_net_interface netif;
- int result;
-
- result = avs_net_ctrl(1, &netif, sizeof(netif));
-
- if (result < 0) {
- log_fatal(
- "avs_net_ctrl call to get MAC address returned error: %d", result);
- }
-
- ident->hardid[0] = '0';
- ident->hardid[1] = '1';
- ident->hardid[2] = '0';
- ident->hardid[3] = '0';
-
- hex_encode_uc(
- netif.mac_addr,
- sizeof(netif.mac_addr),
- ident->hardid + 4,
- sizeof(ident->hardid) - 4);
-}
-
-bool ea3_ident_invoke_module_init(
- struct ea3_ident *ident,
- const struct module_context *module,
- struct property_node *app_config)
-{
- char sidcode_short[17];
- char sidcode_long[21];
- char security_code[9];
- bool ok;
-
- /* Set up security env vars */
-
- str_format(
- security_code,
- lengthof(security_code),
- "G*%s%s%s%s",
- ident->model,
- ident->dest,
- ident->spec,
- ident->rev);
-
- std_setenv("/env/boot/version", "0.0.0");
- std_setenv("/env/profile/security_code", security_code);
- std_setenv("/env/profile/system_id", ident->pcbid);
- std_setenv("/env/profile/account_id", ident->pcbid);
- std_setenv("/env/profile/license_id", ident->softid);
- std_setenv("/env/profile/software_id", ident->softid);
- std_setenv("/env/profile/hardware_id", ident->hardid);
-
- /* Set up the short sidcode string, let dll_entry_init mangle it */
-
- str_format(
- sidcode_short,
- lengthof(sidcode_short),
- "%s%s%s%s%s",
- ident->model,
- ident->dest,
- ident->spec,
- ident->rev,
- ident->ext);
-
- /* Set up long-form sidcode env var */
-
- str_format(
- sidcode_long,
- lengthof(sidcode_long),
- "%s:%s:%s:%s:%s",
- ident->model,
- ident->dest,
- ident->spec,
- ident->rev,
- ident->ext);
-
- /* Set this up beforehand, as certain games require it in dll_entry_init */
-
- std_setenv("/env/profile/soft_id_code", sidcode_long);
-
- ok = module_context_invoke_init(module, sidcode_short, app_config);
-
- if (!ok) {
- return false;
- }
-
- /* Back-propagate sidcode, as some games modify it during init */
-
- memcpy(ident->model, sidcode_short + 0, sizeof(ident->model) - 1);
- ident->dest[0] = sidcode_short[3];
- ident->spec[0] = sidcode_short[4];
- ident->rev[0] = sidcode_short[5];
- memcpy(ident->ext, sidcode_short + 6, sizeof(ident->ext));
-
- /* Set up long-form sidcode env var again */
-
- str_format(
- sidcode_long,
- lengthof(sidcode_long),
- "%s:%s:%s:%s:%s",
- ident->model,
- ident->dest,
- ident->spec,
- ident->rev,
- ident->ext);
-
- std_setenv("/env/profile/soft_id_code", sidcode_long);
-
- return true;
-}
-
-void ea3_ident_to_property(
- const struct ea3_ident *ident, struct property *ea3_config)
-{
- struct property_node *node;
- int i;
-
- for (i = 0; ea3_ident_psmap[i].type != 0xFF; i++) {
- node = property_search(ea3_config, 0, ea3_ident_psmap[i].path);
-
- if (node != NULL) {
- property_node_remove(node);
- }
- }
-
- property_psmap_export(ea3_config, NULL, ident, ea3_ident_psmap);
-}
-
-void ea3_ident_replace_property_bool(
- struct property_node *node, const char *name, uint8_t val)
-{
- struct property_node *tmp;
-
- tmp = property_search(NULL, node, name);
-
- if (tmp) {
- property_node_remove(tmp);
- }
-
- property_node_create(NULL, node, PROPERTY_TYPE_BOOL, name, val);
-}
-
-void ea3_ident_replace_property_str(
- struct property_node *node, const char *name, const char *val)
-{
- struct property_node *tmp;
-
- tmp = property_search(NULL, node, name);
-
- if (tmp) {
- property_node_remove(tmp);
- }
-
- tmp = property_node_create(NULL, node, PROPERTY_TYPE_STR, name, val);
-}
diff --git a/src/main/launcher/ea3-config.h b/src/main/launcher/ea3-config.h
deleted file mode 100644
index ada44008..00000000
--- a/src/main/launcher/ea3-config.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef LAUNCHER_EA3_CONFIG_H
-#define LAUNCHER_EA3_CONFIG_H
-
-#include "imports/avs.h"
-
-#include "launcher/module.h"
-
-/* N.B. even though this might look like a Konami ABI, this is purely an
- internal data structure. */
-
-struct ea3_ident {
- /* psmapped structure offset can't be zero for some stupid reason */
-
- uint32_t dummy;
-
- /* Initialized from ea3-config.xml, then fed back from sidcode_short */
-
- char model[4];
- char dest[4];
- char spec[4];
- char rev[4];
- char ext[11];
-
- /* Initialized from ea3-config.xml (hardware_id defaults to MAC addr) */
-
- char softid[24];
- char hardid[24];
- char pcbid[24];
-};
-
-void ea3_ident_init(struct ea3_ident *ident);
-bool ea3_ident_from_property(
- struct ea3_ident *ident, struct property *ea3_config);
-void ea3_ident_hardid_from_ethernet(struct ea3_ident *ident);
-bool ea3_ident_invoke_module_init(
- struct ea3_ident *ident,
- const struct module_context *module,
- struct property_node *app_config);
-void ea3_ident_to_property(
- const struct ea3_ident *ident, struct property *ea3_config);
-void ea3_ident_replace_property_bool(
- struct property_node *node, const char *name, uint8_t val);
-void ea3_ident_replace_property_str(
- struct property_node *node, const char *name, const char *val);
-
-#endif
diff --git a/src/main/launcher/ea3-ident-config.c b/src/main/launcher/ea3-ident-config.c
new file mode 100644
index 00000000..f0931f25
--- /dev/null
+++ b/src/main/launcher/ea3-ident-config.c
@@ -0,0 +1,103 @@
+#define LOG_MODULE "ea3-ident-config"
+
+#include
+
+#include "imports/avs.h"
+
+#include "launcher/ea3-ident-config.h"
+#include "launcher/property-util.h"
+
+#include "util/defs.h"
+#include "util/hex.h"
+#include "util/log.h"
+#include "util/str.h"
+
+#define ROOT_NODE "/ea3_conf"
+
+PSMAP_BEGIN(ea3_ident_config_psmap)
+PSMAP_OPTIONAL(
+ PSMAP_TYPE_STR, struct ea3_ident_config, softid, "/id/softid", "")
+PSMAP_OPTIONAL(
+ PSMAP_TYPE_STR, struct ea3_ident_config, hardid, "/id/hardid", "")
+PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct ea3_ident_config, pcbid, "/id/pcbid", "")
+PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident_config, model, "/soft/model")
+PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident_config, dest, "/soft/dest")
+PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident_config, spec, "/soft/spec")
+PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident_config, rev, "/soft/rev")
+PSMAP_REQUIRED(PSMAP_TYPE_STR, struct ea3_ident_config, ext, "/soft/ext")
+PSMAP_END
+
+void ea3_ident_config_init(struct ea3_ident_config *config)
+{
+ memset(config, 0, sizeof(*config));
+}
+
+void ea3_ident_config_from_file_load(
+ const char *path, struct ea3_ident_config *config)
+{
+ struct property *property;
+
+ log_assert(path);
+ log_assert(config);
+
+ log_info("Loading from file path: %s", path);
+
+ property = property_util_load(path);
+
+ ea3_ident_config_load(property, config);
+
+ property_util_free(property);
+}
+
+void ea3_ident_config_load(
+ struct property *property, struct ea3_ident_config *config)
+{
+ struct property_node *node;
+
+ log_assert(property);
+ log_assert(config);
+
+ node = property_search(property, NULL, ROOT_NODE);
+
+ if (node == NULL) {
+ log_fatal("Root node '" ROOT_NODE "' missing");
+ }
+
+ if (!property_psmap_import(
+ property, node, config, ea3_ident_config_psmap)) {
+ log_fatal("Error reading config file");
+ }
+}
+
+bool ea3_ident_config_hardid_is_defined(struct ea3_ident_config *config)
+{
+ log_assert(config);
+
+ return strlen(config->hardid) > 0;
+}
+
+void ea3_ident_config_hardid_from_ethernet_set(struct ea3_ident_config *config)
+{
+ struct avs_net_interface netif;
+ int result;
+
+ log_assert(config);
+
+ result = avs_net_ctrl(1, &netif, sizeof(netif));
+
+ if (result < 0) {
+ log_fatal(
+ "avs_net_ctrl call to get MAC address returned error: %d", result);
+ }
+
+ config->hardid[0] = '0';
+ config->hardid[1] = '1';
+ config->hardid[2] = '0';
+ config->hardid[3] = '0';
+
+ hex_encode_uc(
+ netif.mac_addr,
+ sizeof(netif.mac_addr),
+ config->hardid + 4,
+ sizeof(config->hardid) - 4);
+}
\ No newline at end of file
diff --git a/src/main/launcher/ea3-ident-config.h b/src/main/launcher/ea3-ident-config.h
new file mode 100644
index 00000000..1a6dc7f2
--- /dev/null
+++ b/src/main/launcher/ea3-ident-config.h
@@ -0,0 +1,37 @@
+#ifndef LAUNCHER_EA3_IDENT_CONFIG_H
+#define LAUNCHER_EA3_IDENT_CONFIG_H
+
+#include "imports/avs.h"
+
+/* N.B. even though this might look like a Konami ABI, this is purely an
+ internal data structure. */
+
+struct ea3_ident_config {
+ /* psmapped structure offset can't be zero for some stupid reason */
+
+ uint32_t dummy;
+
+ /* Initialized from ea3-config.xml, then fed back from sidcode_short */
+
+ char model[4];
+ char dest[4];
+ char spec[4];
+ char rev[4];
+ char ext[11];
+
+ /* Initialized from ea3-config.xml (hardware_id defaults to MAC addr) */
+
+ char softid[24];
+ char hardid[24];
+ char pcbid[24];
+};
+
+void ea3_ident_config_init(struct ea3_ident_config *config);
+void ea3_ident_config_from_file_load(
+ const char *path, struct ea3_ident_config *config);
+void ea3_ident_config_load(
+ struct property *property, struct ea3_ident_config *config);
+bool ea3_ident_config_hardid_is_defined(struct ea3_ident_config *config);
+void ea3_ident_config_hardid_from_ethernet_set(struct ea3_ident_config *config);
+
+#endif
diff --git a/src/main/launcher/eamuse-config.c b/src/main/launcher/eamuse-config.c
new file mode 100644
index 00000000..9cc251b1
--- /dev/null
+++ b/src/main/launcher/eamuse-config.c
@@ -0,0 +1,125 @@
+#define LOG_MODULE "eamuse-config"
+
+#include
+
+#include "imports/avs.h"
+
+#include "launcher/ea3-ident-config.h"
+#include "launcher/eamuse-config.h"
+#include "launcher/property-util.h"
+
+#include "util/log.h"
+
+#define EAMUSE_CONFIG_ROOT_NODE "/ea3"
+
+struct property *eamuse_config_avs_load(const char *path)
+{
+ struct property *property;
+
+ log_assert(path);
+
+ log_misc("Loading from avs path: %s", path);
+
+ property = property_util_avs_fs_load(path);
+
+ // Check if root node exists, call already errors if not
+ eamuse_config_root_get(property);
+
+ return property;
+}
+
+struct property_node *eamuse_config_root_get(struct property *property)
+{
+ struct property_node *node;
+
+ log_assert(property);
+
+ node = property_search(property, 0, EAMUSE_CONFIG_ROOT_NODE);
+
+ if (node == NULL) {
+ log_fatal("Root node " EAMUSE_CONFIG_ROOT_NODE
+ " in eamuse config missing");
+ }
+
+ return node;
+}
+
+void eamuse_config_id_softid_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "id/softid", value);
+}
+
+void eamuse_config_id_hardid_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "id/hardid", value);
+}
+
+void eamuse_config_id_pcbid_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "id/pcbid", value);
+}
+
+void eamuse_config_soft_model_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "soft/model", value);
+}
+
+void eamuse_config_soft_dest_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "soft/dest", value);
+}
+
+void eamuse_config_soft_spec_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "soft/spec", value);
+}
+
+void eamuse_config_soft_rev_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "soft/rev", value);
+}
+
+void eamuse_config_soft_ext_set(struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "soft/ext", value);
+}
+
+void eamuse_config_network_url_slash_set(struct property_node *node, bool value)
+{
+ log_assert(node);
+
+ property_util_node_bool_replace(NULL, node, "network/url_slash", value);
+}
+
+void eamuse_config_network_service_url_set(
+ struct property_node *node, const char *value)
+{
+ log_assert(node);
+ log_assert(value);
+
+ property_util_node_str_replace(NULL, node, "network/services", value);
+}
\ No newline at end of file
diff --git a/src/main/launcher/eamuse-config.h b/src/main/launcher/eamuse-config.h
new file mode 100644
index 00000000..2cba227a
--- /dev/null
+++ b/src/main/launcher/eamuse-config.h
@@ -0,0 +1,23 @@
+#ifndef LAUNCHER_EAMUSE_CONFIG_H
+#define LAUNCHER_EAMUSE_CONFIG_H
+
+#include "imports/avs.h"
+
+struct property *eamuse_config_avs_load(const char *path);
+struct property_node *eamuse_config_root_get(struct property *property);
+
+void eamuse_config_id_softid_set(struct property_node *node, const char *value);
+void eamuse_config_id_hardid_set(struct property_node *node, const char *value);
+void eamuse_config_id_pcbid_set(struct property_node *node, const char *value);
+void eamuse_config_soft_model_set(
+ struct property_node *node, const char *value);
+void eamuse_config_soft_dest_set(struct property_node *node, const char *value);
+void eamuse_config_soft_spec_set(struct property_node *node, const char *value);
+void eamuse_config_soft_rev_set(struct property_node *node, const char *value);
+void eamuse_config_soft_ext_set(struct property_node *node, const char *value);
+void eamuse_config_network_url_slash_set(
+ struct property_node *node, bool value);
+void eamuse_config_network_service_url_set(
+ struct property_node *node, const char *value);
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/eamuse.c b/src/main/launcher/eamuse.c
new file mode 100644
index 00000000..e2fd159c
--- /dev/null
+++ b/src/main/launcher/eamuse.c
@@ -0,0 +1,25 @@
+#define LOG_MODULE "eamuse"
+
+#include "imports/avs-ea3.h"
+
+#include "util/log.h"
+
+void eamuse_init(struct property_node *node)
+{
+ log_assert(node);
+
+ log_info("init");
+
+ ea3_boot(node);
+
+ log_misc("init done");
+}
+
+void eamuse_fini()
+{
+ log_info("fini");
+
+ ea3_shutdown();
+
+ log_misc("fini done");
+}
\ No newline at end of file
diff --git a/src/main/launcher/eamuse.h b/src/main/launcher/eamuse.h
new file mode 100644
index 00000000..1cd1f7e7
--- /dev/null
+++ b/src/main/launcher/eamuse.h
@@ -0,0 +1,9 @@
+#ifndef LAUNCHER_EAMUSE_H
+#define LAUNCHER_EAMUSE_H
+
+#include "imports/avs.h"
+
+void eamuse_init(struct property_node *node);
+void eamuse_fini();
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/hook.c b/src/main/launcher/hook.c
new file mode 100644
index 00000000..350106fa
--- /dev/null
+++ b/src/main/launcher/hook.c
@@ -0,0 +1,34 @@
+#define LOG_MODULE "hook"
+
+#include
+
+#include "launcher/hook.h"
+
+#include "util/log.h"
+
+void hook_load_dll(const char *path)
+{
+ log_assert(path);
+
+ log_info("Load hook dll: %s", path);
+
+ if (LoadLibraryA(path) == NULL) {
+ LPSTR buffer;
+
+ FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &buffer,
+ 0,
+ NULL);
+
+ log_fatal("%s: Failed to load hook DLL: %s", path, buffer);
+
+ LocalFree(buffer);
+ }
+
+ log_misc("Load hook dll done");
+}
\ No newline at end of file
diff --git a/src/main/launcher/hook.h b/src/main/launcher/hook.h
new file mode 100644
index 00000000..9d0c5d42
--- /dev/null
+++ b/src/main/launcher/hook.h
@@ -0,0 +1,6 @@
+#ifndef LAUNCHER_HOOK_H
+#define LAUNCHER_HOOK_H
+
+void hook_load_dll(const char *path);
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/launcher-config.c b/src/main/launcher/launcher-config.c
new file mode 100644
index 00000000..aaecd3e4
--- /dev/null
+++ b/src/main/launcher/launcher-config.c
@@ -0,0 +1,371 @@
+#define LOG_MODULE "launcher-config"
+
+#include
+
+#include "imports/avs.h"
+
+#include "launcher/launcher-config.h"
+#include "launcher/property-util.h"
+
+#include "util/log.h"
+#include "util/mem.h"
+#include "util/str.h"
+
+// clang-format off
+PSMAP_BEGIN(launcher_debug_psmap)
+PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct launcher_debug_config, remote_debugger,
+ "debug/remote_debugger", false)
+ PSMAP_OPTIONAL(PSMAP_TYPE_BOOL, struct launcher_debug_config, log_property_configs,
+ "debug/log_property_configs", false)
+PSMAP_END
+// clang-format on
+
+#define ROOT_NODE "/launcher"
+#define MAX_LAYER_CONFIG_NODES 8
+
+#define NODE_MISSING_FATAL(subnode) \
+ log_fatal("%s/%s: Node missing", ROOT_NODE, subnode);
+#define NODE_LOADING_FATAL(subnode) \
+ log_fatal("%s/%s: Node loading", ROOT_NODE, subnode);
+
+static struct property *
+_launcher_config_layered_config_nodes_load(struct property_node *node)
+{
+ char kind[64];
+ char file[MAX_PATH];
+ int res;
+ int cnt;
+
+ struct property_node *cur;
+ struct property *config_property[MAX_LAYER_CONFIG_NODES];
+ struct property *merged_property;
+
+ log_assert(node);
+
+ cnt = 0;
+ cur = property_search(NULL, node, "config");
+
+ while (cur) {
+ if (cnt >= MAX_LAYER_CONFIG_NODES) {
+ log_fatal(
+ "Exceeding max supported config nodes for layering, max is %d",
+ MAX_LAYER_CONFIG_NODES);
+ }
+
+ res = property_node_refer(
+ NULL, cur, "kind@", PROPERTY_TYPE_ATTR, kind, sizeof(kind));
+
+ if (res < 0) {
+ log_fatal("Failed reading 'kind' attribute value of config node");
+ }
+
+ if (!strcmp(kind, "file")) {
+ property_node_read(cur, PROPERTY_TYPE_STR, file, sizeof(file));
+
+ config_property[cnt] = property_util_load(file);
+ } else if (!strcmp(kind, "inline")) {
+ // The nested child is the actual root of the inline, not the outer
+ // node
+ cur = property_node_traversal(cur, TRAVERSE_FIRST_CHILD);
+
+ config_property[cnt] = property_util_clone(cur);
+ } else {
+ log_fatal(
+ "Unsupported 'kind' attribute value '%s' of config node", kind);
+ }
+
+ cnt++;
+ cur = property_node_traversal(cur, TRAVERSE_NEXT_SEARCH_RESULT);
+ }
+
+ if (cnt == 0) {
+ return NULL;
+ }
+
+ merged_property =
+ property_util_merge((struct property **) &config_property[0], cnt);
+
+ for (int i = 0; i < cnt; i++) {
+ property_util_free(config_property[i]);
+ }
+
+ return merged_property;
+}
+
+static void _launcher_config_hook_dlls_parse(
+ struct property_node *node,
+ const char *node_path,
+ char dlls[LAUNCHER_CONFIG_MAX_HOOK_DLL][MAX_PATH])
+{
+ int cnt;
+ struct property_node *cur;
+
+ cnt = 0;
+ cur = property_search(NULL, node, node_path);
+
+ while (cur) {
+ if (cnt >= LAUNCHER_CONFIG_MAX_HOOK_DLL) {
+ log_warning(
+ "Currently not supporting more than %d dlls, skipping "
+ "remaining",
+ cnt);
+ break;
+ }
+
+ property_node_read(cur, PROPERTY_TYPE_STR, dlls[cnt], MAX_PATH);
+
+ cnt++;
+ cur = property_node_traversal(cur, TRAVERSE_NEXT_SEARCH_RESULT);
+ }
+}
+
+static void _launcher_config_bootstrap_load(
+ struct property_node *node, struct launcher_bootstrap_config *config)
+{
+ int res;
+
+ log_assert(node);
+ log_assert(config);
+
+ res = property_node_refer(
+ NULL,
+ node,
+ "selector",
+ PROPERTY_TYPE_STR,
+ config->selector,
+ sizeof(config->selector));
+
+ if (res < 0) {
+ NODE_MISSING_FATAL("bootstrap/selector");
+ }
+
+ config->property = _launcher_config_layered_config_nodes_load(node);
+
+ if (config->property == NULL) {
+ NODE_MISSING_FATAL("bootstrap/config");
+ }
+}
+
+static void _launcher_config_hook_load(
+ struct property_node *node, struct launcher_hook_config *config)
+{
+ log_assert(node);
+ log_assert(config);
+
+ _launcher_config_hook_dlls_parse(node, "hook_dlls/dll", config->hook_dlls);
+ _launcher_config_hook_dlls_parse(
+ node, "before_hook_dlls/dll", config->before_hook_dlls);
+ _launcher_config_hook_dlls_parse(
+ node, "iat_hook_dlls/dll", config->iat_hook_dlls);
+}
+
+static void _launcher_config_debug_load(
+ struct property_node *node, struct launcher_debug_config *config)
+{
+ log_assert(node);
+ log_assert(config);
+
+ if (!property_psmap_import(NULL, node, config, launcher_debug_psmap)) {
+ NODE_LOADING_FATAL("debug");
+ }
+}
+
+void launcher_config_init(struct launcher_config *config)
+{
+ log_assert(config);
+
+ memset(config->bootstrap.selector, 0, sizeof(config->bootstrap.selector));
+ config->bootstrap.property = NULL;
+
+ config->avs.property = NULL;
+
+ config->ea3_ident.property = NULL;
+
+ config->eamuse.property = NULL;
+
+ memset(config->hook.hook_dlls, 0, sizeof(config->hook.hook_dlls));
+ memset(
+ config->hook.before_hook_dlls,
+ 0,
+ sizeof(config->hook.before_hook_dlls));
+ memset(config->hook.iat_hook_dlls, 0, sizeof(config->hook.iat_hook_dlls));
+
+ config->debug.remote_debugger = false;
+ config->debug.log_property_configs = false;
+}
+
+void launcher_config_load(
+ struct property *property, struct launcher_config *config)
+{
+ struct property_node *root_node;
+ struct property_node *node;
+ avs_error error;
+
+ log_assert(property);
+ log_assert(config);
+
+ root_node = property_search(property, NULL, ROOT_NODE);
+
+ if (root_node == NULL) {
+ NODE_MISSING_FATAL("");
+ }
+
+ error = property_node_refer(
+ NULL,
+ root_node,
+ "version@",
+ PROPERTY_TYPE_ATTR,
+ &config->version,
+ sizeof(uint32_t));
+
+ if (AVS_IS_ERROR(error)) {
+ log_fatal("Missing version attribute on root node");
+ }
+
+ // if (config->version != 1) {
+ // log_fatal("Unsupported version of launcher configuration: %d",
+ // config->version);
+ // }
+
+ node = property_search(NULL, root_node, "bootstrap");
+
+ if (node == NULL) {
+ NODE_MISSING_FATAL("bootstrap");
+ }
+
+ _launcher_config_bootstrap_load(node, &config->bootstrap);
+
+ node = property_search(NULL, root_node, "avs");
+
+ if (node) {
+ config->avs.property = _launcher_config_layered_config_nodes_load(node);
+ }
+
+ node = property_search(NULL, root_node, "ea3_ident");
+
+ if (node) {
+ config->ea3_ident.property =
+ _launcher_config_layered_config_nodes_load(node);
+ }
+
+ node = property_search(NULL, root_node, "eamuse");
+
+ if (node) {
+ config->eamuse.property =
+ _launcher_config_layered_config_nodes_load(node);
+ }
+
+ node = property_search(NULL, root_node, "hook");
+
+ if (node) {
+ _launcher_config_hook_load(node, &config->hook);
+ }
+
+ _launcher_config_debug_load(root_node, &config->debug);
+}
+
+bool launcher_config_add_hook_dll(
+ struct launcher_config *config, const char *path)
+{
+ int i;
+
+ log_assert(config);
+ log_assert(path);
+
+ i = 0;
+
+ while (i < LAUNCHER_CONFIG_MAX_HOOK_DLL) {
+ if (strlen(config->hook.hook_dlls[i]) == 0) {
+ break;
+ }
+
+ i++;
+ }
+
+ if (i >= LAUNCHER_CONFIG_MAX_HOOK_DLL) {
+ return false;
+ }
+
+ str_cpy(config->hook.hook_dlls[i], sizeof(config->hook.hook_dlls[i]), path);
+
+ return true;
+}
+
+bool launcher_config_add_before_hook_dll(
+ struct launcher_config *config, const char *path)
+{
+ int i;
+
+ log_assert(config);
+ log_assert(path);
+
+ i = 0;
+
+ while (i < LAUNCHER_CONFIG_MAX_HOOK_DLL) {
+ if (strlen(config->hook.before_hook_dlls[i]) == 0) {
+ break;
+ }
+
+ i++;
+ }
+
+ if (i >= LAUNCHER_CONFIG_MAX_HOOK_DLL) {
+ return false;
+ }
+
+ str_cpy(
+ config->hook.before_hook_dlls[i],
+ sizeof(config->hook.before_hook_dlls[i]),
+ path);
+
+ return true;
+}
+
+bool launcher_config_add_iat_hook_dll(
+ struct launcher_config *config, const char *path)
+{
+ int i;
+
+ log_assert(config);
+ log_assert(path);
+
+ i = 0;
+
+ while (i < LAUNCHER_CONFIG_MAX_HOOK_DLL) {
+ if (strlen(config->hook.iat_hook_dlls[i]) == 0) {
+ break;
+ }
+
+ i++;
+ }
+
+ if (i >= LAUNCHER_CONFIG_MAX_HOOK_DLL) {
+ return false;
+ }
+
+ str_cpy(
+ config->hook.iat_hook_dlls[i],
+ sizeof(config->hook.iat_hook_dlls[i]),
+ path);
+
+ return true;
+}
+
+void launcher_config_fini(struct launcher_config *config)
+{
+ log_assert(config);
+
+ property_util_free(config->bootstrap.property);
+
+ if (config->avs.property) {
+ property_util_free(config->avs.property);
+ }
+
+ if (config->ea3_ident.property) {
+ property_util_free(config->ea3_ident.property);
+ }
+
+ if (config->eamuse.property) {
+ property_util_free(config->eamuse.property);
+ }
+}
\ No newline at end of file
diff --git a/src/main/launcher/launcher-config.h b/src/main/launcher/launcher-config.h
new file mode 100644
index 00000000..7d6b8a6e
--- /dev/null
+++ b/src/main/launcher/launcher-config.h
@@ -0,0 +1,56 @@
+#ifndef LAUNCHER_CONFIG_H
+#define LAUNCHER_CONFIG_H
+
+#include
+
+#include "util/array.h"
+
+#define LAUNCHER_CONFIG_MAX_HOOK_DLL 16
+
+struct launcher_config {
+ uint32_t version;
+
+ struct launcher_bootstrap_config {
+ char selector[128];
+ struct property *property;
+ } bootstrap;
+
+ struct launcher_avs_config {
+ struct property *property;
+ } avs;
+
+ struct launcher_ea3_ident_config {
+ struct property *property;
+ } ea3_ident;
+
+ struct launcher_eamuse_config {
+ struct property *property;
+ } eamuse;
+
+ struct launcher_hook_config {
+ char hook_dlls[LAUNCHER_CONFIG_MAX_HOOK_DLL][MAX_PATH];
+ char before_hook_dlls[LAUNCHER_CONFIG_MAX_HOOK_DLL][MAX_PATH];
+ char iat_hook_dlls[LAUNCHER_CONFIG_MAX_HOOK_DLL][MAX_PATH];
+ } hook;
+
+ struct launcher_debug_config {
+ bool remote_debugger;
+ bool log_property_configs;
+ } debug;
+};
+
+void launcher_config_init(struct launcher_config *config);
+
+void launcher_config_load(
+ struct property *property, struct launcher_config *config);
+
+bool launcher_config_add_hook_dll(
+ struct launcher_config *config, const char *path);
+bool launcher_config_add_before_hook_dll(
+ struct launcher_config *config, const char *path);
+bool launcher_config_add_iat_hook_dll(
+ struct launcher_config *config, const char *path);
+
+void launcher_config_fini(struct launcher_config *config);
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/launcher.c b/src/main/launcher/launcher.c
new file mode 100644
index 00000000..f77c28fd
--- /dev/null
+++ b/src/main/launcher/launcher.c
@@ -0,0 +1,543 @@
+#define LOG_MODULE "launcher"
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include "imports/avs-ea3.h"
+#include "imports/avs.h"
+
+#include "launcher/avs-config.h"
+#include "launcher/avs.h"
+#include "launcher/bootstrap-config.h"
+#include "launcher/bootstrap.h"
+#include "launcher/debug.h"
+#include "launcher/ea3-ident-config.h"
+#include "launcher/eamuse-config.h"
+#include "launcher/eamuse.h"
+#include "launcher/hook.h"
+#include "launcher/launcher-config.h"
+#include "launcher/logger.h"
+#include "launcher/module.h"
+#include "launcher/options.h"
+#include "launcher/property-util.h"
+#include "launcher/stubs.h"
+
+#include "util/debug.h"
+#include "util/defs.h"
+#include "util/fs.h"
+#include "util/log.h"
+#include "util/os.h"
+#include "util/proc.h"
+#include "util/signal.h"
+#include "util/str.h"
+
+static void _launcher_signal_shutdown_handler()
+{
+ logger_finit();
+ ExitProcess(EXIT_FAILURE);
+}
+
+static void _launcher_logger_early_init(const struct options_log *options)
+{
+ log_assert(options);
+
+ // Early logging pre AVS setup depend entirely on command args
+ // We don't even have the bootstrap configuration loaded at this point
+ logger_early_init(options->file_path);
+
+ if (options->level) {
+ log_set_level(*(options->level));
+ }
+}
+
+static void _launcher_env_game_dir_verify()
+{
+ char cwd[MAX_PATH];
+ char modules_dir[MAX_PATH];
+ char prop_dir[MAX_PATH];
+
+ getcwd(cwd, sizeof(cwd));
+
+ log_info("Current working directory: %s", cwd);
+
+ str_cpy(modules_dir, sizeof(modules_dir), cwd);
+ str_cpy(prop_dir, sizeof(prop_dir), cwd);
+
+ str_cat(modules_dir, sizeof(modules_dir), "/modules");
+ str_cat(prop_dir, sizeof(prop_dir), "/prop");
+
+ if (!path_exists(modules_dir)) {
+ log_fatal(
+ "Cannot find 'modules' directory in current working directory: %s",
+ cwd);
+ }
+
+ if (!path_exists(prop_dir)) {
+ log_fatal(
+ "Cannot find 'prop' directory in current working directory: %s",
+ cwd);
+ }
+}
+
+static void _launcher_bootstrap_config_options_override(
+ struct launcher_bootstrap_config *config,
+ const struct options_bootstrap *options)
+{
+ log_assert(config);
+ log_assert(options);
+
+ if (options->config_path) {
+ log_misc(
+ "Command line override bootstrap configuration from file: %s",
+ options->config_path);
+
+ property_util_free(config->property);
+ config->property = property_util_load(options->config_path);
+ }
+
+ if (options->selector) {
+ log_misc(
+ "Command line override bootstrap selector: %s", options->selector);
+
+ str_cpy(config->selector, sizeof(config->selector), options->selector);
+ }
+}
+
+static void _launcher_ea3_ident_config_options_override(
+ struct ea3_ident_config *config, const struct options_eamuse *options)
+{
+ log_assert(config);
+ log_assert(options);
+
+ if (options->softid) {
+ str_cpy(config->softid, sizeof(config->softid), options->softid);
+ }
+
+ if (options->pcbid) {
+ str_cpy(config->pcbid, sizeof(config->pcbid), options->pcbid);
+ }
+}
+
+static void _launcher_hook_config_options_override(
+ struct launcher_config *config, const struct options_hook *options)
+{
+ size_t i;
+ const char *dll;
+
+ log_assert(config);
+ log_assert(options);
+
+ for (i = 0; i < options->hook_dlls.nitems; i++) {
+ dll = *array_item(const char *, &options->hook_dlls, i);
+
+ if (!launcher_config_add_hook_dll(config, dll)) {
+ log_warning(
+ "Adding override hook dll '%s' failed (max supported limit "
+ "exceeded), ignored",
+ dll);
+ }
+ }
+
+ for (i = 0; i < options->before_hook_dlls.nitems; i++) {
+ dll = *array_item(const char *, &options->before_hook_dlls, i);
+
+ if (!launcher_config_add_before_hook_dll(config, dll)) {
+ log_warning(
+ "Adding override before hook dll '%s' failed (max supported "
+ "limit exceeded), ignored",
+ dll);
+ }
+ }
+
+ for (i = 0; i < options->iat_hook_dlls.nitems; i++) {
+ dll = *array_item(const char *, &options->iat_hook_dlls, i);
+
+ if (!launcher_config_add_iat_hook_dll(config, dll)) {
+ log_warning(
+ "Adding override iat hook dll '%s' failed (max supported limit "
+ "exceeded), ignored",
+ dll);
+ }
+ }
+}
+
+static void _launcher_debug_config_options_override(
+ struct launcher_debug_config *config, const struct options_debug *options)
+{
+ log_assert(config);
+ log_assert(options);
+
+ if (options->remote_debugger) {
+ log_misc("Command line override, enable remote debugger");
+
+ config->remote_debugger = true;
+ }
+
+ if (options->log_property_configs) {
+ log_misc("Command line override, log property configs");
+
+ config->log_property_configs = true;
+ }
+}
+
+static void _launcher_config_options_override(
+ struct launcher_config *config, const struct options *options)
+{
+ log_assert(config);
+ log_assert(options);
+
+ // Apply command line overrides on all launcher owned configuration
+ // parameters
+ _launcher_bootstrap_config_options_override(
+ &config->bootstrap, &options->bootstrap);
+ _launcher_hook_config_options_override(config, &options->hook);
+ _launcher_debug_config_options_override(&config->debug, &options->debug);
+}
+
+static void
+_launcher_config_full_resolved_log(const struct launcher_config *config)
+{
+ if (config->debug.log_property_configs) {
+ log_misc("launcher-config resolved properties");
+ log_misc("bootstrap-config");
+ property_util_log(config->bootstrap.property);
+
+ log_misc("avs-config");
+ property_util_log(config->avs.property);
+
+ log_misc("ea3-ident-config");
+ property_util_log(config->ea3_ident.property);
+
+ log_misc("eamuse-config");
+ property_util_log(config->eamuse.property);
+ }
+}
+
+static void
+_launcher_remote_debugger_trap(const struct launcher_debug_config *config)
+{
+ log_assert(config);
+
+ /* If enabled, wait for a remote debugger to attach as early as possible.
+ Spawning launcher with a debugger crashes it for some reason
+ (e.g. on jubeat08). However, starting the launcher separately and
+ attaching a remote debugger works */
+
+ if (config->remote_debugger) {
+ debug_remote_debugger_trap();
+ }
+}
+
+static void _launcher_bootstrap_config_load(
+ const struct launcher_bootstrap_config *launcher_bootstrap_config,
+ struct bootstrap_config *config)
+{
+ bootstrap_config_init(config);
+
+ bootstrap_config_load(
+ launcher_bootstrap_config->property,
+ launcher_bootstrap_config->selector,
+ config);
+}
+
+static void _launcher_bootstrap_log_config_options_override(
+ struct bootstrap_log_config *config, const struct options_log *options)
+{
+ log_assert(config);
+ log_assert(options);
+
+ if (options->level) {
+ log_misc(
+ "Command line override bootstrap log level: %d", *(options->level));
+
+ switch (*(options->level)) {
+ case LOG_LEVEL_FATAL:
+ str_cpy(config->level, sizeof(config->level), "fatal");
+ break;
+
+ case LOG_LEVEL_WARNING:
+ str_cpy(config->level, sizeof(config->level), "warn");
+ break;
+
+ case LOG_LEVEL_INFO:
+ str_cpy(config->level, sizeof(config->level), "info");
+ break;
+
+ case LOG_LEVEL_MISC:
+ str_cpy(config->level, sizeof(config->level), "misc");
+ break;
+
+ default:
+ log_assert(false);
+ }
+ }
+
+ if (options->file_path) {
+ log_misc(
+ "Command line override bootstrap log file: %s", options->file_path);
+ str_cpy(config->file, sizeof(config->file), options->file_path);
+ }
+}
+
+static void _launcher_bootstrap_log_config_verify(
+ const struct launcher_config *launcher_config,
+ const struct bootstrap_config *bootstrap_config)
+{
+ log_assert(launcher_config);
+ log_assert(bootstrap_config);
+
+ if (!str_eq(bootstrap_config->startup.log.level, "misc")) {
+ if (launcher_config->debug.log_property_configs) {
+ log_warning(
+ "Logging of property configs enabled, but requires misc log "
+ "level, current log level: %s",
+ bootstrap_config->startup.log.level);
+ }
+ }
+}
+
+static void
+_launcher_before_hook_dlls_load(const struct launcher_hook_config *config)
+{
+ int i;
+
+ log_assert(config);
+
+ log_misc("Loading before hook dlls...");
+
+ for (i = 0; i < LAUNCHER_CONFIG_MAX_HOOK_DLL; i++) {
+ if (strlen(config->before_hook_dlls[i]) > 0) {
+ hook_load_dll(config->before_hook_dlls[i]);
+ }
+ }
+}
+
+static void _launcher_ea3_ident_config_load(
+ const struct launcher_ea3_ident_config *launcher_config,
+ struct ea3_ident_config *config,
+ bool log_property_configs)
+{
+ log_assert(launcher_config);
+ log_assert(config);
+
+ ea3_ident_config_init(config);
+ ea3_ident_config_load(launcher_config->property, config);
+
+ if (log_property_configs) {
+ log_misc("Property ea3-ident-config");
+
+ property_util_log(launcher_config->property);
+ }
+
+ if (!ea3_ident_config_hardid_is_defined(config)) {
+ log_misc(
+ "No no hardid defined in ea3-ident-config, derive from ethernet");
+
+ ea3_ident_config_hardid_from_ethernet_set(config);
+ }
+}
+
+static void _launcher_bootstrap_module_init(
+ const struct bootstrap_module_config *module_config,
+ const struct launcher_hook_config *hook_config)
+{
+ int i;
+ struct array iat_hook_dlls;
+
+ log_assert(module_config);
+ log_assert(hook_config);
+
+ array_init(&iat_hook_dlls);
+
+ for (i = 0; i < LAUNCHER_CONFIG_MAX_HOOK_DLL; i++) {
+ if (strlen(hook_config->before_hook_dlls[i]) > 0) {
+ *array_append(const char *, &iat_hook_dlls) =
+ (const char *) &hook_config->before_hook_dlls[i];
+ }
+ }
+
+ bootstrap_module_init(module_config, &iat_hook_dlls);
+
+ array_fini(&iat_hook_dlls);
+}
+
+static void _launcher_hook_dlls_load(const struct launcher_hook_config *config)
+{
+ int i;
+
+ log_assert(config);
+
+ log_misc("Loading hook dlls...");
+
+ for (i = 0; i < LAUNCHER_CONFIG_MAX_HOOK_DLL; i++) {
+ if (strlen(config->hook_dlls[i]) > 0) {
+ hook_load_dll(config->hook_dlls[i]);
+ }
+ }
+}
+
+static void _launcher_dongle_stubs_init()
+{
+ stubs_init();
+}
+
+static void _launcher_debugger_break()
+{
+ /* Opportunity for breakpoint setup etc */
+ if (IsDebuggerPresent()) {
+ DebugBreak();
+ }
+}
+
+void _launcher_init(
+ const struct options *options,
+ struct launcher_config *launcher_config,
+ struct bootstrap_config *bootstrap_config,
+ struct ea3_ident_config *ea3_ident_config)
+{
+ struct property *launcher_property;
+
+ log_assert(options);
+ log_assert(launcher_config);
+ log_assert(bootstrap_config);
+ log_assert(ea3_ident_config);
+
+ _launcher_logger_early_init(&options->log);
+
+ debug_init();
+ signal_exception_handler_init(_launcher_signal_shutdown_handler);
+ signal_register_shutdown_handler(&_launcher_signal_shutdown_handler);
+
+ os_version_log();
+ _launcher_env_game_dir_verify();
+
+ if (proc_is_running_as_admin_user()) {
+ log_warning(
+ "Not running as admin user. Launcher and games require elevated "
+ "privileges to run correctly");
+ }
+
+ launcher_config_init(launcher_config);
+
+ if (options->launcher.config_path) {
+ log_info("Loading launcher configuration from file: %s", options->launcher.config_path);
+
+ launcher_property = property_util_load(options->launcher.config_path);
+ launcher_config_load(launcher_property, launcher_config);
+
+ _launcher_config_options_override(launcher_config, options);
+
+ if (launcher_config->debug.log_property_configs) {
+ log_misc("launcher-config");
+ property_util_log(launcher_property);
+ }
+
+ property_util_free(launcher_property);
+ } else {
+ _launcher_config_options_override(launcher_config, options);
+ }
+
+ // Not really fully resolved, but have an early debug dump because there are
+ // still several more steps that can fail before having the entire
+ // configuration resolved
+ _launcher_config_full_resolved_log(launcher_config);
+
+ _launcher_remote_debugger_trap(&launcher_config->debug);
+
+ _launcher_bootstrap_config_load(
+ &launcher_config->bootstrap, bootstrap_config);
+ _launcher_bootstrap_log_config_options_override(
+ &bootstrap_config->startup.log, &options->log);
+ _launcher_bootstrap_log_config_verify(launcher_config, bootstrap_config);
+
+ bootstrap_init(launcher_config->debug.log_property_configs);
+ bootstrap_log_init(&bootstrap_config->startup.log);
+
+ _launcher_before_hook_dlls_load(&launcher_config->hook);
+
+ bootstrap_avs_init(
+ &bootstrap_config->startup.boot,
+ &bootstrap_config->startup.log,
+ avs_config_root_get(launcher_config->avs.property));
+ bootstrap_default_files_create(&bootstrap_config->startup.default_file);
+
+ _launcher_ea3_ident_config_load(
+ &launcher_config->ea3_ident,
+ ea3_ident_config,
+ launcher_config->debug.log_property_configs);
+ _launcher_ea3_ident_config_options_override(
+ ea3_ident_config, &options->eamuse);
+
+ // Execute another one which is now actually final. No more configuration
+ // changes from this point on
+ _launcher_config_full_resolved_log(launcher_config);
+}
+
+void _launcher_run(
+ const struct launcher_config *launcher_config,
+ const struct bootstrap_config *bootstrap_config,
+ struct ea3_ident_config *ea3_ident_config)
+{
+ log_assert(launcher_config);
+ log_assert(bootstrap_config);
+ log_assert(ea3_ident_config);
+
+ _launcher_bootstrap_module_init(
+ &bootstrap_config->startup.module, &launcher_config->hook);
+
+ _launcher_hook_dlls_load(&launcher_config->hook);
+
+ _launcher_dongle_stubs_init();
+
+ _launcher_debugger_break();
+
+ bootstrap_module_game_init(
+ &bootstrap_config->startup.module, ea3_ident_config);
+
+ bootstrap_eamuse_init(
+ &bootstrap_config->startup.eamuse,
+ ea3_ident_config,
+ eamuse_config_root_get(launcher_config->eamuse.property));
+
+ bootstrap_module_game_run();
+}
+
+void _launcher_fini(
+ struct launcher_config *launcher_config,
+ const struct bootstrap_config *bootstrap_config)
+{
+ log_assert(launcher_config);
+ log_assert(bootstrap_config);
+
+ bootstrap_eamuse_fini(&bootstrap_config->startup.eamuse);
+
+ bootstrap_avs_fini();
+
+ bootstrap_module_game_fini();
+
+ launcher_config_fini(launcher_config);
+
+ log_info("Shutdown complete");
+
+ logger_finit();
+}
+
+void launcher_main(const struct options *options)
+{
+ struct launcher_config launcher_config;
+ struct bootstrap_config bootstrap_config;
+ struct ea3_ident_config ea3_ident_config;
+
+ log_assert(options);
+
+ _launcher_init(
+ options, &launcher_config, &bootstrap_config, &ea3_ident_config);
+
+ _launcher_run(&launcher_config, &bootstrap_config, &ea3_ident_config);
+
+ _launcher_fini(&launcher_config, &bootstrap_config);
+}
\ No newline at end of file
diff --git a/src/main/launcher/launcher.h b/src/main/launcher/launcher.h
new file mode 100644
index 00000000..da1995cc
--- /dev/null
+++ b/src/main/launcher/launcher.h
@@ -0,0 +1,8 @@
+#ifndef LAUNCHER_LAUNCHER_H
+#define LAUNCHER_LAUNCHER_H
+
+#include "launcher/options.h"
+
+void launcher_main(const struct options *options);
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/logger.c b/src/main/launcher/logger.c
new file mode 100644
index 00000000..f8ba8097
--- /dev/null
+++ b/src/main/launcher/logger.c
@@ -0,0 +1,365 @@
+#define LOG_MODULE "launcher-logger"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "launcher/logger.h"
+#include "launcher/version.h"
+
+#include "util/fs.h"
+#include "util/log.h"
+#include "util/mem.h"
+
+static FILE *log_file;
+static HANDLE log_mutex;
+
+static const char *logger_get_formatted_timestamp(void)
+{
+ static char buffer[64];
+ time_t cur = 0;
+ struct tm *tm = NULL;
+
+ cur = time(NULL);
+ tm = localtime(&cur);
+
+ strftime(buffer, sizeof(buffer), "[%Y/%m/%d %H:%M:%S] ", tm);
+
+ return buffer;
+}
+
+static char logger_console_determine_color(const char *str)
+{
+ log_assert(str);
+
+ /* Add some color to make spotting warnings/errors easier.
+ Based on debug output level identifier. */
+
+ /* Avoids colored output on strings like "Windows" */
+ if (str[1] != ':') {
+ return 15;
+ }
+
+ switch (str[0]) {
+ /* green */
+ case 'M':
+ return 10;
+ /* blue */
+ case 'I':
+ return 9;
+ /* yellow */
+ case 'W':
+ return 14;
+ /* red */
+ case 'F':
+ return 12;
+ /* default console color */
+ default:
+ return 15;
+ }
+}
+
+static size_t logger_msg_coloring_len(const char *str)
+{
+ // Expected format example: "I:boot: my log message"
+
+ const char *ptr;
+ size_t len;
+ int colon_count;
+
+ ptr = str;
+ len = 0;
+ colon_count = 0;
+
+ while (true) {
+ // End of string = invalid log format
+ if (*ptr == '\0') {
+ return 0;
+ }
+
+ if (*ptr == ':') {
+ colon_count++;
+ }
+
+ if (colon_count == 2) {
+ // Skip current colon, next char is a space
+ return len + 1;
+ }
+
+ len++;
+ ptr++;
+ }
+
+ return 0;
+}
+
+static void logger_console(
+ void *ctx, const char *chars, size_t nchars, const char *timestamp_str)
+{
+ char color;
+ size_t color_len;
+ // See "util/log.c", has to align
+ char buffer[65536];
+ char tmp;
+
+ color_len = logger_msg_coloring_len(chars);
+
+ // Check if we could detect which part to color, otherwise just write the
+ // whole log message without any coloring logic
+ if (color_len > 0) {
+ color = logger_console_determine_color(chars);
+
+ strcpy(buffer, chars);
+
+ // Mask start of log message for coloring
+ tmp = buffer[color_len];
+ buffer[color_len] = '\0';
+
+ printf("%s", timestamp_str);
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
+ printf("%s", buffer);
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
+
+ // Write actual message non colored
+ buffer[color_len] = tmp;
+ printf("%s", buffer + color_len);
+ } else {
+ printf("%s", chars);
+ }
+}
+
+static void logger_console_avs(const char *chars)
+{
+ char color;
+ size_t color_len;
+ // See "util/log.c", has to align
+ char buffer[65536];
+ char tmp;
+ const char *timestamp;
+ const char *msg;
+
+ static const size_t timestamp_len = strlen("[----/--/-- --:--:--]");
+
+ timestamp = chars;
+ msg = timestamp + timestamp_len + 1; // +1 is the space
+
+ color_len = logger_msg_coloring_len(msg);
+
+ // Check if we could detect which part to color, otherwise just write the
+ // whole log message without any coloring logic
+ if (color_len > 0) {
+ color = logger_console_determine_color(msg);
+
+ strcpy(buffer, msg);
+
+ // Mask start of log message for coloring
+ tmp = buffer[color_len];
+ buffer[color_len] = '\0';
+
+ printf("%.21s ", timestamp);
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
+ printf("%s", buffer);
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
+
+ // Write actual message non colored
+ buffer[color_len] = tmp;
+ printf("%s\n", buffer + color_len);
+ } else {
+ printf("%s\n", chars);
+ }
+}
+
+static void logger_file(
+ void *ctx, const char *chars, size_t nchars, const char *timestamp_str)
+{
+ if (ctx) {
+ fwrite(timestamp_str, 1, strlen(timestamp_str), (FILE *) ctx);
+ fwrite(chars, 1, nchars, (FILE *) ctx);
+ fflush((FILE *) ctx);
+ }
+}
+
+static void logger_file_avs(const char *chars, size_t len)
+{
+ if (log_file) {
+ fwrite(chars, 1, len, log_file);
+ fflush(log_file);
+ }
+}
+
+static void logger_writer(void *ctx, const char *chars, size_t nchars)
+{
+ const char *timestamp_str;
+
+ // Different threads logging the same destination, e.g. debugger thread,
+ // main thread
+
+ WaitForSingleObject(log_mutex, INFINITE);
+
+ timestamp_str = logger_get_formatted_timestamp();
+
+ logger_console(ctx, chars, nchars, timestamp_str);
+ logger_file(ctx, chars, nchars, timestamp_str);
+
+ ReleaseMutex(log_mutex);
+}
+
+static void logger_log_header()
+{
+ log_info(
+ "\n"
+ " .__ .__ \n"
+ " | | _____ __ __ ____ ____ | |__ ___________ \n"
+ " | | \\__ \\ | | \\/ \\_/ ___\\| | \\_/ __ \\_ __ \\ \n"
+ " | |__/ __ \\| | / | \\ \\___| Y \\ ___/| | \\/ \n"
+ " |____(____ /____/|___| /\\___ >___| /\\___ >__| \n"
+ " \\/ \\/ \\/ \\/ \\/ ");
+
+ log_info(
+ "launcher build date %s, gitrev %s",
+ launcher_build_date,
+ launcher_gitrev);
+}
+
+void logger_early_init(const char *log_file_path)
+{
+ if (log_file_path) {
+ log_file = fopen(log_file_path, "w+");
+ } else {
+ log_file = NULL;
+ }
+
+ log_to_writer(logger_writer, log_file);
+
+ logger_log_header();
+
+ if (log_file_path) {
+ log_info("Log file: %s", log_file_path);
+
+ if (!log_file) {
+ log_fatal(
+ "ERROR: Opening log file %s failed: %s",
+ log_file_path,
+ strerror(errno));
+ }
+ }
+
+ log_mutex = CreateMutex(NULL, FALSE, NULL);
+}
+
+void logger_init(
+ const char *filename,
+ bool enable_console,
+ bool enable_file,
+ bool rotate_file,
+ bool append_file,
+ uint16_t count_file)
+{
+ // Remark: very basic implementation for now, logger needs a proper cleanup
+ // anyway before implementing more features such as rotation
+
+ if (enable_file) {
+ if (log_file) {
+ // Log file stitching of early log output
+ fseek(log_file, 0, SEEK_END);
+ size_t file_size = ftell(log_file);
+ fseek(log_file, 0, SEEK_SET);
+
+ void *buffer = xmalloc(file_size);
+
+ fread(buffer, file_size, 1, log_file);
+
+ fclose(log_file);
+
+ log_file = fopen(filename, "w+");
+
+ fwrite(buffer, file_size, 1, log_file);
+ fflush(log_file);
+ free(buffer);
+ }
+ } else {
+ if (log_file) {
+ fclose(log_file);
+ log_file = NULL;
+ }
+ }
+}
+
+void logger_level_set(enum logger_level level)
+{
+ enum log_level internal_level;
+
+ switch (level) {
+ case LOGGER_LEVEL_OFF:
+ case LOGGER_LEVEL_FATAL:
+ internal_level = LOG_LEVEL_FATAL;
+ break;
+
+ case LOGGER_LEVEL_WARNING:
+ internal_level = LOG_LEVEL_WARNING;
+ break;
+
+ case LOGGER_LEVEL_DEFAULT:
+ case LOGGER_LEVEL_INFO:
+ internal_level = LOG_LEVEL_INFO;
+ break;
+
+ case LOGGER_LEVEL_MISC:
+ case LOGGER_LEVEL_ALL:
+ internal_level = LOG_LEVEL_MISC;
+ break;
+
+ default:
+ internal_level = LOG_LEVEL_FATAL;
+ log_assert(false);
+ }
+
+ log_set_level(internal_level);
+}
+
+void logger_log_avs_log_message(char *str, size_t len)
+{
+ bool use_crlf;
+
+#if AVS_VERSION >= 1500
+ use_crlf = true;
+#else
+ use_crlf = false;
+#endif
+
+ // Different threads logging the same destination, e.g. debugger thread,
+ // main thread
+
+ WaitForSingleObject(log_mutex, INFINITE);
+
+ // Write to file first, tokenizing trashes the string
+ logger_file_avs(str, len);
+
+ // The character stream provided here can contain multiple lines as AVS
+ // manages buffered writes to the logger backend. We need to split them
+ // up for the logging backend to allow for further enhancements
+
+ char *line = strtok(str, use_crlf ? "\r\n" : "\n");
+
+ while (line) {
+ logger_console_avs(line);
+ line = strtok(NULL, use_crlf ? "\r\n" : "\n");
+ }
+
+ ReleaseMutex(log_mutex);
+}
+
+void logger_finit()
+{
+ log_misc("Logger finit");
+
+ if (log_file) {
+ fflush(log_file);
+ fclose(log_file);
+ }
+
+ CloseHandle(log_mutex);
+}
\ No newline at end of file
diff --git a/src/main/launcher/logger.h b/src/main/launcher/logger.h
new file mode 100644
index 00000000..5b665b98
--- /dev/null
+++ b/src/main/launcher/logger.h
@@ -0,0 +1,42 @@
+#ifndef LAUNCHER_LOGGER_H
+#define LAUNCHER_LOGGER_H
+
+#include
+#include
+
+enum logger_level {
+ LOGGER_LEVEL_OFF = 0,
+ LOGGER_LEVEL_FATAL = 1,
+ LOGGER_LEVEL_WARNING = 2,
+ LOGGER_LEVEL_INFO = 3,
+ LOGGER_LEVEL_MISC = 4,
+ LOGGER_LEVEL_ALL = 5,
+ LOGGER_LEVEL_DEFAULT = 6
+};
+
+void logger_early_init(const char *log_file_path);
+
+void logger_init(
+ const char *filename,
+ bool enable_console,
+ bool enable_file,
+ bool rotate_file,
+ bool append_file,
+ uint16_t count_file);
+
+void logger_level_set(enum logger_level level);
+
+/**
+ * Write a log message from AVS to the logging backend.
+ *
+ * @param str String to log
+ * @param len Total length of the log string
+ */
+void logger_log_avs_log_message(char *str, size_t len);
+
+/**
+ * Shutdown and cleanup the logging backend.
+ */
+void logger_finit();
+
+#endif
\ No newline at end of file
diff --git a/src/main/launcher/main.c b/src/main/launcher/main.c
index 70c5184d..4b1b68a0 100644
--- a/src/main/launcher/main.c
+++ b/src/main/launcher/main.c
@@ -1,338 +1,23 @@
-#include
-
-#include
-#include
-#include
#include
-#include "imports/avs-ea3.h"
-#include "imports/avs.h"
-
-#include "launcher/avs-context.h"
-#include "launcher/ea3-config.h"
-#include "launcher/module.h"
+#include "launcher/launcher.h"
#include "launcher/options.h"
-#include "launcher/property.h"
-#include "launcher/stubs.h"
-#include "launcher/version.h"
-
-#include "util/codepage.h"
-#include "util/defs.h"
-#include "util/fs.h"
-#include "util/log.h"
-#include "util/mem.h"
-#include "util/os.h"
-#include "util/str.h"
-
-/* Gratuitous API changes orz */
-static AVS_LOG_WRITER(log_callback, chars, nchars, ctx)
-{
- wchar_t *utf16;
- char *utf8;
- int utf16_len;
- int utf8_len;
- int result;
- DWORD nwritten;
- HANDLE console;
- HANDLE file;
-
- /* Ignore existing NUL terminator */
-
- nchars--;
-
- /* Transcode shit_jis to UTF-8 */
-
- utf16_len = MultiByteToWideChar(CP_SHIFT_JIS, 0, chars, nchars, NULL, 0);
-
- if (utf16_len == 0) {
- abort();
- }
-
- utf16 = xmalloc(sizeof(*utf16) * utf16_len);
- result =
- MultiByteToWideChar(CP_SHIFT_JIS, 0, chars, nchars, utf16, utf16_len);
-
- if (result == 0) {
- abort();
- }
-
- utf8_len =
- WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, NULL, 0, NULL, NULL);
-
- if (utf8_len == 0) {
- abort();
- }
-
- utf8 = xmalloc(utf8_len + 2);
- result = WideCharToMultiByte(
- CP_UTF8, 0, utf16, utf16_len, utf8, utf8_len, NULL, NULL);
-
- if (result == 0) {
- abort();
- }
-
-#if AVS_VERSION >= 1500
- utf8[utf8_len + 0] = '\r';
- utf8[utf8_len + 1] = '\n';
-
- utf8_len += 2;
-#endif
-
- /* Write to console and log file */
-
- file = (HANDLE) ctx;
- console = GetStdHandle(STD_OUTPUT_HANDLE);
-
- if (ctx != INVALID_HANDLE_VALUE) {
- WriteFile(file, utf8, utf8_len, &nwritten, NULL);
- }
-
- WriteFile(console, utf8, utf8_len, &nwritten, NULL);
-
- /* Clean up */
-
- free(utf8);
- free(utf16);
-}
-
-static void load_hook_dlls(struct array *hook_dlls)
-{
- const char *hook_dll;
-
- for (size_t i = 0; i < hook_dlls->nitems; i++) {
- hook_dll = *array_item(char *, hook_dlls, i);
-
- if (LoadLibraryA(hook_dll) == NULL) {
- LPSTR buffer;
-
- FormatMessageA(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPSTR) &buffer,
- 0,
- NULL);
-
- log_fatal("%s: Failed to load hook DLL: %s", hook_dll, buffer);
-
- LocalFree(buffer);
- }
- }
-}
int main(int argc, const char **argv)
{
- bool ok;
- HANDLE logfile;
-
- struct ea3_ident ea3;
- struct module_context module;
struct options options;
- struct property *app_config;
- struct property *avs_config;
- struct property *ea3_config;
-
- struct property_node *app_config_root;
- struct property_node *avs_config_root;
- struct property_node *ea3_config_root;
-
- log_to_writer(log_writer_file, stdout);
- log_info(
- "launcher build date %s, gitrev %s",
- launcher_build_date,
- launcher_gitrev);
-
- /* Read command line */
-
options_init(&options);
if (!options_read_cmdline(&options, argc, argv)) {
options_print_usage();
- return EXIT_FAILURE;
- }
-
- /* If enabled, wait for a remote debugger to attach. Spawning launcher
- with a debugger crashes it for some reason (e.g. on jubeat08). However,
- starting the launcher separately and attaching a remote debugger works */
-
- if (options.remote_debugger) {
- log_info("Waiting until debugger attaches to remote process...");
-
- while (true) {
- BOOL res = FALSE;
- if (!CheckRemoteDebuggerPresent(GetCurrentProcess(), &res)) {
- log_fatal(
- "CheckRemoteDebuggerPresent failed: %08x",
- (unsigned int) GetLastError());
- }
-
- if (res) {
- log_info("Debugger attached, resuming");
- break;
- }
-
- Sleep(1000);
- }
- }
-
- /* Start up AVS */
-
- if (options.logfile != NULL) {
- logfile = CreateFileA(
- options.logfile,
- GENERIC_WRITE,
- FILE_SHARE_READ,
- NULL,
- CREATE_ALWAYS,
- 0,
- NULL);
- } else {
- logfile = INVALID_HANDLE_VALUE;
- }
-
- avs_config = boot_property_load(options.avs_config_path);
- avs_config_root = property_search(avs_config, 0, "/config");
-
- if (avs_config_root == NULL) {
- log_fatal("%s: /config missing", options.avs_config_path);
- }
-
- load_hook_dlls(&options.before_hook_dlls);
-
- avs_context_init(
- avs_config_root,
- options.avs_heap_size,
- options.std_heap_size,
- log_callback,
- logfile);
-
- boot_property_free(avs_config);
-
- log_to_external(
- log_body_misc, log_body_info, log_body_warning, log_body_fatal);
-
- os_version_log();
-
- /* Load game DLL */
-
- if (options.iat_hook_dlls.nitems > 0) {
- module_context_init_with_iat_hooks(
- &module, options.module, &options.iat_hook_dlls);
- } else {
- module_context_init(&module, options.module);
+ exit(EXIT_FAILURE);
}
- /* Load hook DLLs */
-
- load_hook_dlls(&options.hook_dlls);
-
- /* Inject GetModuleHandle hooks */
-
- stubs_init();
-
- /* Prepare ea3 config */
-
- ea3_config = boot_property_load(options.ea3_config_path);
- ea3_config_root = property_search(ea3_config, 0, "/ea3");
-
- if (ea3_config_root == NULL) {
- log_fatal("%s: /ea3 missing", options.ea3_config_path);
- }
-
- ea3_ident_init(&ea3);
-
- if (!ea3_ident_from_property(&ea3, ea3_config)) {
- log_fatal(
- "%s: Error reading IDs from config file", options.ea3_config_path);
- }
-
- if (options.softid != NULL) {
- str_cpy(ea3.softid, lengthof(ea3.softid), options.softid);
- }
-
- if (options.pcbid != NULL) {
- str_cpy(ea3.pcbid, lengthof(ea3.pcbid), options.pcbid);
- }
-
- if (!ea3.hardid[0]) {
- ea3_ident_hardid_from_ethernet(&ea3);
- }
-
- /* Invoke dll_entry_init */
-
- if (path_exists(options.app_config_path)) {
- app_config = boot_property_load(options.app_config_path);
- } else {
- log_warning(
- "%s: app config file missing, using empty",
- options.app_config_path);
- app_config = boot_property_load_cstring("dummy");
- }
-
- app_config_root = property_search(app_config, 0, "/param");
-
- if (app_config_root == NULL) {
- log_fatal("%s: /param missing", options.app_config_path);
- }
-
- if (IsDebuggerPresent()) {
- /* Opportunity for breakpoint setup etc */
- DebugBreak();
- }
-
- ok = ea3_ident_invoke_module_init(&ea3, &module, app_config_root);
-
- if (!ok) {
- log_fatal("%s: dll_module_init() returned failure", options.module);
- }
-
- boot_property_free(app_config);
-
- ea3_ident_to_property(&ea3, ea3_config);
-
- if (options.override_urlslash_enabled) {
- log_info(
- "Overriding url_slash to: %d", options.override_urlslash_value);
-
- ea3_ident_replace_property_bool(
- ea3_config_root,
- "/network/url_slash",
- options.override_urlslash_value);
- }
-
- if (options.override_service != NULL) {
- log_info("Overriding service url to: %s", options.override_service);
-
- ea3_ident_replace_property_str(
- ea3_config_root, "/network/services", options.override_service);
- }
-
- /* Start up e-Amusement client */
-
- ea3_boot(ea3_config_root);
- boot_property_free(ea3_config);
-
- /* Run application */
-
- module_context_invoke_main(&module);
-
- /* Shut down */
-
- ea3_shutdown();
-
- log_to_writer(log_writer_file, stdout);
- avs_context_fini();
-
- if (logfile != INVALID_HANDLE_VALUE) {
- CloseHandle(logfile);
- }
+ launcher_main(&options);
- module_context_fini(&module);
options_fini(&options);
return EXIT_SUCCESS;
-}
+}
\ No newline at end of file
diff --git a/src/main/launcher/module.c b/src/main/launcher/module.c
index b3beff26..0ad0d518 100644
--- a/src/main/launcher/module.c
+++ b/src/main/launcher/module.c
@@ -1,3 +1,5 @@
+#define LOG_MODULE "module"
+
#include
#include "hook/pe.h"
@@ -6,17 +8,21 @@
#include "imports/eapki.h"
#include "launcher/module.h"
+#include "launcher/property-util.h"
#include "util/log.h"
#include "util/str.h"
#define MM_ALLOCATION_GRANULARITY 0x10000
-static bool module_replace_dll_iat(HMODULE hModule, struct array *iat_hook_dlls)
+static bool
+module_replace_dll_iat(HMODULE hModule, const struct array *iat_hook_dlls)
{
log_assert(hModule);
log_assert(iat_hook_dlls);
+ log_misc("replace dll iat: %p", hModule);
+
if (iat_hook_dlls->nitems == 0)
return true;
@@ -127,11 +133,13 @@ static bool module_replace_dll_iat(HMODULE hModule, struct array *iat_hook_dlls)
return false;
}
-void module_context_init(struct module_context *module, const char *path)
+void module_init(struct module_context *module, const char *path)
{
log_assert(module != NULL);
log_assert(path != NULL);
+ log_info("init: %s", path);
+
module->dll = LoadLibrary(path);
if (module->dll == NULL) {
@@ -159,16 +167,20 @@ void module_context_init(struct module_context *module, const char *path)
}
module->path = str_dup(path);
+
+ log_misc("init done");
}
-void module_context_init_with_iat_hooks(
+void module_with_iat_hooks_init(
struct module_context *module,
const char *path,
- struct array *iat_hook_dlls)
+ const struct array *iat_hook_dlls)
{
log_assert(module != NULL);
log_assert(path != NULL);
+ log_info("init iat hooks: %s", path);
+
module->dll = LoadLibraryExA(path, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (module->dll == NULL) {
@@ -211,16 +223,71 @@ void module_context_init_with_iat_hooks(
module->path = str_dup(path);
}
-bool module_context_invoke_init(
+void module_init_invoke(
const struct module_context *module,
- char *sidcode,
- struct property_node *app_config)
+ struct ea3_ident_config *ea3_ident_config,
+ struct property_node *app_params_node)
{
+ char sidcode_short[17];
+ char sidcode_long[21];
+ char security_code[9];
dll_entry_init_t init;
+ bool ok;
- log_assert(module != NULL);
- log_assert(sidcode != NULL);
- log_assert(app_config != NULL);
+ log_info("init invoke");
+
+ /* Set up security env vars */
+
+ str_format(
+ security_code,
+ lengthof(security_code),
+ "G*%s%s%s%s",
+ ea3_ident_config->model,
+ ea3_ident_config->dest,
+ ea3_ident_config->spec,
+ ea3_ident_config->rev);
+
+ log_misc("security code: %s", security_code);
+
+ std_setenv("/env/boot/version", "0.0.0");
+ std_setenv("/env/profile/security_code", security_code);
+ std_setenv("/env/profile/system_id", ea3_ident_config->pcbid);
+ std_setenv("/env/profile/account_id", ea3_ident_config->pcbid);
+ std_setenv("/env/profile/license_id", ea3_ident_config->softid);
+ std_setenv("/env/profile/software_id", ea3_ident_config->softid);
+ std_setenv("/env/profile/hardware_id", ea3_ident_config->hardid);
+
+ /* Set up the short sidcode string, let dll_entry_init mangle it */
+
+ str_format(
+ sidcode_short,
+ lengthof(sidcode_short),
+ "%s%s%s%s%s",
+ ea3_ident_config->model,
+ ea3_ident_config->dest,
+ ea3_ident_config->spec,
+ ea3_ident_config->rev,
+ ea3_ident_config->ext);
+
+ log_misc("sidcode short: %s", sidcode_short);
+
+ /* Set up long-form sidcode env var */
+
+ str_format(
+ sidcode_long,
+ lengthof(sidcode_long),
+ "%s:%s:%s:%s:%s",
+ ea3_ident_config->model,
+ ea3_ident_config->dest,
+ ea3_ident_config->spec,
+ ea3_ident_config->rev,
+ ea3_ident_config->ext);
+
+ log_misc("sidecode long: %s", sidcode_long);
+
+ /* Set this up beforehand, as certain games require it in dll_entry_init */
+
+ std_setenv("/env/profile/soft_id_code", sidcode_long);
init = (void *) GetProcAddress(module->dll, "dll_entry_init");
@@ -229,16 +296,67 @@ bool module_context_invoke_init(
"%s: dll_entry_init not found. Is this a game DLL?", module->path);
}
- return init(sidcode, app_config);
+ log_info("Invoking game init...");
+
+ struct property *prop =
+ property_util_cstring_load("p3io");
+
+ struct property_node *prop_node = property_search(prop, NULL, "/param");
+
+ property_util_log(prop);
+ property_util_node_log(prop_node);
+
+ ok = init(sidcode_short, prop_node);
+
+ if (!ok) {
+ log_fatal("%s: dll_module_init() returned failure", module->path);
+ } else {
+ log_info("Game init done");
+ }
+
+ /* Back-propagate sidcode, as some games modify it during init */
+
+ memcpy(
+ ea3_ident_config->model,
+ sidcode_short + 0,
+ sizeof(ea3_ident_config->model) - 1);
+ ea3_ident_config->dest[0] = sidcode_short[3];
+ ea3_ident_config->spec[0] = sidcode_short[4];
+ ea3_ident_config->rev[0] = sidcode_short[5];
+ memcpy(
+ ea3_ident_config->ext,
+ sidcode_short + 6,
+ sizeof(ea3_ident_config->ext));
+
+ /* Set up long-form sidcode env var again */
+
+ str_format(
+ sidcode_long,
+ lengthof(sidcode_long),
+ "%s:%s:%s:%s:%s",
+ ea3_ident_config->model,
+ ea3_ident_config->dest,
+ ea3_ident_config->spec,
+ ea3_ident_config->rev,
+ ea3_ident_config->ext);
+
+ std_setenv("/env/profile/soft_id_code", sidcode_long);
+
+ log_misc("back-propagated sidcode long: %s", sidcode_long);
+
+ log_misc("init invoke done");
}
-bool module_context_invoke_main(const struct module_context *module)
+bool module_main_invoke(const struct module_context *module)
{
/* GCC warns if you call a variable "main" */
dll_entry_main_t main_;
+ bool result;
log_assert(module != NULL);
+ log_info("main invoke");
+
main_ = (void *) GetProcAddress(module->dll, "dll_entry_main");
if (main_ == NULL) {
@@ -246,11 +364,19 @@ bool module_context_invoke_main(const struct module_context *module)
"%s: dll_entry_main not found. Is this a game DLL?", module->path);
}
- return main_();
+ log_info("Invoking game's main function...");
+
+ result = main_();
+
+ log_info("Main terminated, result: %d", result);
+
+ return result;
}
-void module_context_fini(struct module_context *module)
+void module_fini(struct module_context *module)
{
+ log_info("fini");
+
if (module == NULL) {
return;
}
@@ -260,4 +386,6 @@ void module_context_fini(struct module_context *module)
if (module->dll != NULL) {
FreeLibrary(module->dll);
}
+
+ log_misc("fini done");
}
diff --git a/src/main/launcher/module.h b/src/main/launcher/module.h
index f2a851eb..ed9b7327 100644
--- a/src/main/launcher/module.h
+++ b/src/main/launcher/module.h
@@ -5,6 +5,8 @@
#include "imports/avs.h"
+#include "launcher/ea3-ident-config.h"
+
#include "util/array.h"
struct module_context {
@@ -12,16 +14,16 @@ struct module_context {
char *path;
};
-void module_context_init(struct module_context *module, const char *path);
-void module_context_init_with_iat_hooks(
+void module_init(struct module_context *module, const char *path);
+void module_with_iat_hooks_init(
struct module_context *module,
const char *path,
- struct array *iat_hook_dlls);
-bool module_context_invoke_init(
+ const struct array *iat_hook_dlls);
+void module_init_invoke(
const struct module_context *module,
- char *sidcode,
- struct property_node *app_config);
-bool module_context_invoke_main(const struct module_context *module);
-void module_context_fini(struct module_context *module);
+ struct ea3_ident_config *ea3_ident_config,
+ struct property_node *app_params_node);
+bool module_main_invoke(const struct module_context *module);
+void module_fini(struct module_context *module);
#endif
diff --git a/src/main/launcher/options.c b/src/main/launcher/options.c
index 757555ec..8bbd6df4 100644
--- a/src/main/launcher/options.c
+++ b/src/main/launcher/options.c
@@ -1,3 +1,5 @@
+#define LOG_MODULE "options"
+
#include
#include
#include
@@ -6,62 +8,42 @@
#include "launcher/options.h"
-#include "util/array.h"
-#include "util/log.h"
+#include "util/mem.h"
#include "util/str.h"
-#define DEFAULT_HEAP_SIZE 16777216
-
void options_init(struct options *options)
{
- options->std_heap_size = DEFAULT_HEAP_SIZE;
- options->avs_heap_size = DEFAULT_HEAP_SIZE;
- options->app_config_path = "prop/app-config.xml";
- options->avs_config_path = "prop/avs-config.xml";
- options->ea3_config_path = "prop/ea3-config.xml";
- options->softid = NULL;
- options->pcbid = NULL;
- options->module = NULL;
- options->logfile = NULL;
- options->remote_debugger = false;
- array_init(&options->hook_dlls);
- array_init(&options->before_hook_dlls);
- array_init(&options->iat_hook_dlls);
-
- options->override_service = NULL;
- options->override_urlslash_enabled = false;
- options->override_urlslash_value = false;
+ memset(options, 0, sizeof(struct options));
+
+ array_init(&options->hook.hook_dlls);
+ array_init(&options->hook.before_hook_dlls);
+ array_init(&options->hook.iat_hook_dlls);
}
bool options_read_cmdline(struct options *options, int argc, const char **argv)
{
+ bool got_launcher_config;
+
+ got_launcher_config = false;
+
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
- case 'A':
- if (i + 1 >= argc) {
- return false;
- }
-
- options->app_config_path = argv[++i];
-
- break;
-
- case 'E':
+ case 'T':
if (i + 1 >= argc) {
return false;
}
- options->ea3_config_path = argv[++i];
+ options->bootstrap.config_path = argv[++i];
break;
- case 'V':
+ case 'Z':
if (i + 1 >= argc) {
return false;
}
- options->avs_config_path = argv[++i];
+ options->bootstrap.selector = argv[++i];
break;
@@ -70,7 +52,7 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
return false;
}
- options->pcbid = argv[++i];
+ options->eamuse.pcbid = argv[++i];
break;
@@ -79,7 +61,7 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
return false;
}
- options->softid = argv[++i];
+ options->eamuse.softid = argv[++i];
break;
@@ -88,70 +70,63 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
return false;
}
- options->avs_heap_size =
- (size_t) strtol(argv[++i], NULL, 0);
-
- if (options->avs_heap_size == 0) {
- return false;
- }
+ *array_append(const char *, &options->hook.hook_dlls) =
+ argv[++i];
break;
-#ifdef AVS_HAS_STD_HEAP
- case 'T':
+ case 'B':
if (i + 1 >= argc) {
return false;
}
- options->std_heap_size =
- (size_t) strtol(argv[++i], NULL, 0);
-
- if (options->std_heap_size == 0) {
- return false;
- }
+ *array_append(
+ const char *, &options->hook.before_hook_dlls) =
+ argv[++i];
break;
-#endif
- case 'K':
+ case 'I': {
if (i + 1 >= argc) {
return false;
}
- *array_append(const char *, &options->hook_dlls) =
- argv[++i];
+ const char *dll = argv[++i];
+ log_assert(strstr(dll, "=") != NULL);
+
+ *array_append(const char *, &options->hook.iat_hook_dlls) =
+ dll;
break;
+ }
- case 'B':
+ case 'L':
if (i + 1 >= argc) {
return false;
}
- *array_append(const char *, &options->before_hook_dlls) =
- argv[++i];
+ long tmp = strtol(argv[++i], NULL, 0);
- break;
-
- case 'I': {
- if (i + 1 >= argc) {
+ if (tmp < LOG_LEVEL_FATAL || tmp > LOG_LEVEL_MISC) {
return false;
}
- const char *dll = argv[++i];
- log_assert(strstr(dll, "=") != NULL);
-
- *array_append(const char *, &options->iat_hook_dlls) = dll;
+ options->log.level = xmalloc(sizeof(enum log_level));
+ *(options->log.level) = (enum log_level) tmp;
break;
- }
case 'Y':
if (i + 1 >= argc) {
return false;
}
- options->logfile = argv[++i];
+ options->log.file_path = argv[++i];
+
+ break;
+
+ case 'C':
+ options->debug.log_property_configs = true;
break;
@@ -160,7 +135,7 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
return false;
}
- options->override_service = argv[++i];
+ options->eamuse.service_url = argv[++i];
break;
@@ -169,22 +144,23 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
return false;
}
- options->override_urlslash_enabled = true;
+ options->eamuse.urlslash = xmalloc(sizeof(bool));
const char *urlslash_value = argv[++i];
- options->override_urlslash_value = false;
+ *(options->eamuse.urlslash) = false;
+
if (_stricmp(urlslash_value, "1") == 0) {
- options->override_urlslash_value = true;
+ *(options->eamuse.urlslash) = true;
}
if (_stricmp(urlslash_value, "true") == 0) {
- options->override_urlslash_value = true;
+ *(options->eamuse.urlslash) = true;
}
break;
case 'D':
- options->remote_debugger = true;
+ options->debug.remote_debugger = true;
break;
@@ -192,59 +168,71 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
break;
}
} else {
- if (!options->module) {
- options->module = argv[i];
+ if (!got_launcher_config) {
+ options->launcher.config_path = argv[i];
+ got_launcher_config = true;
}
}
}
- if (options->module) {
- return true;
- } else {
- return false;
- }
+ return got_launcher_config;
}
void options_print_usage(void)
{
fprintf(
stderr,
- "Usage: launcher.exe [launcher options...] [hooks "
- "options...] \n"
+ "Usage:\n"
+ " launcher.exe [launcher options as overrides...] "
+ "[further options, e.g. for hook libraries to pick up...]\n"
"\n"
- " The following options can be specified before the app DLL "
- "path:\n"
+ " The following options can be specified before the launcher.xml "
+ "configuration file:\n"
"\n"
- " -A [filename] App configuration file (default: "
- "prop/app-config.xml)\n"
- " -V [filename] AVS configuration file (default: "
- "prop/avs-config.xml)\n"
- " -E [filename] ea3 configuration file (default: "
- "prop/ea3-config.xml)\n"
- " -H [bytes] AVS heap size (default: 16777216)\n"
-#ifdef AVS_HAS_STD_HEAP
- " -T [bytes] 'std' heap size (default 16777216)\n"
-#endif
- " -P [pcbid] Specify PCBID (default: use ea3 config)\n"
- " -R [pcbid] Specify Soft ID (default: use ea3 config)\n"
- " -S [url] Specify service url (default: use ea3 config)\n"
- " -U [0/1] Specify url_slash (default: use ea3 config)\n"
- " -K [filename] Load hook DLL (can be specified multiple "
+ " Bootstrap\n"
+ " -T [filename] Bootstrap configuration file\n"
+ " -Z [selector] Bootstrap selector used in configuration\n"
+ "\n"
+ " Eamuse\n"
+ " -P [pcbid] Specify PCBID\n"
+ " -R [softid] Specify Soft ID\n"
+ " -S [url] Specify service url\n"
+ " -U [0/1] Specify url_slash enabled/disabled\n"
+ "\n"
+ " Hook\n"
+ " -H [filename] Load hook DLL (can be specified multiple "
"times)\n"
" -B [filename] Load pre-hook DLL loaded before avs boot "
"(can be specified multiple times)\n"
" -I [filename] Load pre-hook DLL that overrides IAT reference "
- "before execution"
- "(can be specified multiple times)\n"
+ "before execution (can be specified multiple times)\n"
+ "\n"
+ " Logging\n"
+ " -L [0/1/2/3] Log level for both console and file with "
+ "increasing verbosity (0 = fatal, 1 = warn, 2 = info, 3 = misc)\n"
" -Y [filename] Log to a file in addition to the console\n"
+ "\n"
+ " Debug\n"
" -D Halt the launcher before bootstrapping AVS "
- "until a"
- " remote debugger is attached\n");
+ "until a remote debugger is attached\n"
+ " -C Log all loaded and final (property) "
+ "configuration that launcher uses for bootstrapping. IMPORTANT: DO NOT "
+ "ENABLE unless you know what you are doing. This prints sensitive data "
+ "and credentials to the console and logfile. BE CAUTIOUS not to share "
+ "this information before redaction.");
}
void options_fini(struct options *options)
{
- array_fini(&options->hook_dlls);
- array_fini(&options->before_hook_dlls);
- array_fini(&options->iat_hook_dlls);
+ array_fini(&options->hook.hook_dlls);
+ array_fini(&options->hook.before_hook_dlls);
+ array_fini(&options->hook.iat_hook_dlls);
+
+ if (options->log.level) {
+ free(options->log.level);
+ }
+
+ if (options->eamuse.urlslash) {
+ free(options->eamuse.urlslash);
+ }
}
diff --git a/src/main/launcher/options.h b/src/main/launcher/options.h
index 13f1c0fb..9f80dfd0 100644
--- a/src/main/launcher/options.h
+++ b/src/main/launcher/options.h
@@ -5,24 +5,50 @@
#include
#include "util/array.h"
+#include "util/log.h"
+#include "launcher/bootstrap-config.h"
+
+// Launcher options (cmd params) are limited to:
+// - Options to run a (vanilla) game without additional launcher features, e.g.
+// hooking
+// - Options that are handy to have for development/debugging purpose, e.g.
+// quickly switching on/off
+// logging levels
+//
+// Everything else is driven by a composable configuration file (launcher.xml)
struct options {
- size_t std_heap_size;
- size_t avs_heap_size;
- const char *app_config_path;
- const char *avs_config_path;
- const char *ea3_config_path;
- const char *softid;
- const char *pcbid;
- const char *module;
- const char *logfile;
- struct array hook_dlls;
- struct array before_hook_dlls;
- struct array iat_hook_dlls;
- bool remote_debugger;
- const char *override_service;
- bool override_urlslash_enabled;
- bool override_urlslash_value;
+ struct options_launcher {
+ const char *config_path;
+ } launcher;
+
+ struct options_bootstrap {
+ const char *config_path;
+ const char *selector;
+ } bootstrap;
+
+ struct options_log {
+ enum log_level *level;
+ const char *file_path;
+ } log;
+
+ struct options_eamuse {
+ const char *softid;
+ const char *pcbid;
+ const char *service_url;
+ bool *urlslash;
+ } eamuse;
+
+ struct options_hook {
+ struct array hook_dlls;
+ struct array before_hook_dlls;
+ struct array iat_hook_dlls;
+ } hook;
+
+ struct options_debug {
+ bool remote_debugger;
+ bool log_property_configs;
+ } debug;
};
void options_init(struct options *options);
diff --git a/src/main/launcher/property-util.c b/src/main/launcher/property-util.c
new file mode 100644
index 00000000..4c44b04a
--- /dev/null
+++ b/src/main/launcher/property-util.c
@@ -0,0 +1,618 @@
+#define LOG_MODULE "property-util"
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include "avs-util/error.h"
+
+#include "imports/avs.h"
+
+#include "launcher/property-util.h"
+
+#include "util/log.h"
+#include "util/mem.h"
+#include "util/str.h"
+
+#define PROPERTY_STRUCTURE_META_SIZE 576
+
+typedef void (*rewinder)(uint32_t context);
+
+struct cstring_read_handle {
+ const char *buffer;
+ size_t buffer_len;
+ size_t offset;
+};
+
+static struct property *property_util_do_load(
+ avs_reader_t reader, rewinder rewinder, uint32_t context, const char *name)
+{
+ struct property *prop;
+ void *buffer;
+ int nbytes;
+
+ nbytes = property_read_query_memsize(reader, context, 0, 0);
+
+ if (nbytes < 0) {
+ log_fatal("%s: Error querying configuration file", name);
+ }
+
+ buffer = xmalloc(nbytes);
+ prop = property_create(
+ PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE |
+ PROPERTY_FLAG_APPEND,
+ buffer,
+ nbytes);
+ rewinder(context);
+
+ if (!property_insert_read(prop, 0, reader, context)) {
+ log_fatal("%s: Error reading configuration file", name);
+ }
+
+ return prop;
+}
+
+static int property_util_fread(uint32_t context, void *bytes, size_t nbytes)
+{
+ FILE *f;
+
+ f = TlsGetValue(context);
+
+ return fread(bytes, 1, nbytes, f);
+}
+
+static void property_util_frewind(uint32_t context)
+{
+ FILE *f = TlsGetValue(context);
+ rewind(f);
+}
+
+static void property_util_log_node_tree_rec(
+ struct property_node *parent_node, const char *parent_path)
+{
+ char cur_path[4096];
+ // 256 found in AVS code as size used on property_node_name
+ char cur_node_name[256];
+
+ struct property_node *child_node;
+ enum property_type property_type;
+
+ int8_t value_s8;
+ int16_t value_s16;
+ int32_t value_s32;
+ int64_t value_s64;
+ uint8_t value_u8;
+ uint16_t value_u16;
+ uint32_t value_u32;
+ uint64_t value_u64;
+ char value_str[4096];
+ bool value_bool;
+
+ avs_error error;
+
+ // Carry on the full root path down the node tree
+ property_node_name(parent_node, cur_node_name, sizeof(cur_node_name));
+
+ str_cpy(cur_path, sizeof(cur_path), parent_path);
+ str_cat(cur_path, sizeof(cur_path), "/");
+ str_cat(cur_path, sizeof(cur_path), cur_node_name);
+
+ child_node = property_node_traversal(parent_node, TRAVERSE_FIRST_CHILD);
+
+ // parent node is a leaf node, print all data of it
+ if (child_node == NULL) {
+ property_type = property_node_type(parent_node);
+
+ switch (property_type) {
+ case PROPERTY_TYPE_VOID:
+ log_misc("%s: ", cur_path);
+ break;
+
+ case PROPERTY_TYPE_S8:
+ property_node_read(
+ parent_node, property_type, &value_s8, sizeof(value_s8));
+ log_misc("%s: %" PRId8, cur_path, value_s8);
+ break;
+
+ case PROPERTY_TYPE_S16:
+ property_node_read(
+ parent_node, property_type, &value_s16, sizeof(value_s16));
+ log_misc("%s: %" PRId16, cur_path, value_s16);
+ break;
+
+ case PROPERTY_TYPE_S32:
+ property_node_read(
+ parent_node, property_type, &value_s32, sizeof(value_s32));
+ log_misc("%s: %" PRId32, cur_path, value_s32);
+ break;
+
+ case PROPERTY_TYPE_S64:
+ property_node_read(
+ parent_node, property_type, &value_s64, sizeof(value_s64));
+ log_misc("%s: %" PRId64, cur_path, value_s64);
+ break;
+
+ case PROPERTY_TYPE_U8:
+ property_node_read(
+ parent_node, property_type, &value_u8, sizeof(value_u8));
+ log_misc("%s: %" PRIu8, cur_path, value_u8);
+ break;
+
+ case PROPERTY_TYPE_U16:
+ property_node_read(
+ parent_node, property_type, &value_u16, sizeof(value_u16));
+ log_misc("%s: %" PRIu16, cur_path, value_u16);
+ break;
+
+ case PROPERTY_TYPE_U32:
+ property_node_read(
+ parent_node, property_type, &value_u32, sizeof(value_u32));
+ log_misc("%s: %" PRIu32, cur_path, value_u32);
+ break;
+
+ case PROPERTY_TYPE_U64:
+ property_node_read(
+ parent_node, property_type, &value_u64, sizeof(value_u64));
+ log_misc("%s: %" PRIu64, cur_path, value_u64);
+ break;
+
+ case PROPERTY_TYPE_STR:
+ property_node_read(
+ parent_node, property_type, value_str, sizeof(value_str));
+ log_misc("%s: %s", cur_path, value_str);
+
+ break;
+
+ case PROPERTY_TYPE_BOOL:
+ property_node_read(
+ parent_node,
+ property_type,
+ &value_bool,
+ sizeof(value_bool));
+ log_misc("%s: %d", cur_path, value_bool);
+
+ break;
+
+ case PROPERTY_TYPE_BIN:
+ log_misc("%s: ", cur_path);
+ break;
+
+ case PROPERTY_TYPE_ATTR:
+ error = property_node_read(
+ parent_node, property_type, value_str, sizeof(value_str));
+
+ if (AVS_IS_ERROR(error)) {
+ log_fatal(
+ "%s, property read failed: %s",
+ cur_path,
+ avs_util_error_str(error));
+ }
+
+ log_misc("%s@: %s", cur_path, value_str);
+
+ break;
+
+ case PROPERTY_TYPE_VOID_WITH_ATTRIBUTES:
+ log_misc("%s: ", cur_path);
+
+ child_node =
+ property_node_traversal(parent_node, TRAVERSE_FIRST_ATTR);
+
+ while (child_node) {
+ property_util_log_node_tree_rec(child_node, cur_path);
+
+ child_node = property_node_traversal(
+ child_node, TRAVERSE_NEXT_SIBLING);
+ }
+
+ break;
+
+ case PROPERTY_TYPE_STR_WITH_ATTRIBUTES:
+ error = property_node_read(
+ parent_node, property_type, value_str, sizeof(value_str));
+
+ if (AVS_IS_ERROR(error)) {
+ log_fatal(
+ "%s, property read failed: %s",
+ cur_path,
+ avs_util_error_str(error));
+ }
+
+ log_misc("%s: %s", cur_path, value_str);
+
+ child_node =
+ property_node_traversal(parent_node, TRAVERSE_FIRST_ATTR);
+
+ while (child_node) {
+ property_util_log_node_tree_rec(child_node, cur_path);
+
+ child_node = property_node_traversal(
+ child_node, TRAVERSE_NEXT_SIBLING);
+ }
+
+ break;
+
+ default:
+ log_misc("%s: (%d)", cur_path, property_type);
+ break;
+ }
+ } else {
+ while (child_node) {
+ property_util_log_node_tree_rec(child_node, cur_path);
+
+ child_node =
+ property_node_traversal(child_node, TRAVERSE_NEXT_SIBLING);
+ }
+ }
+}
+
+static int
+property_util_cstring_read(uint32_t context, void *bytes, size_t nbytes)
+{
+ int result = 0;
+ struct cstring_read_handle *h = TlsGetValue(context);
+
+ if (h->offset < h->buffer_len) {
+ result = min(nbytes, h->buffer_len - h->offset);
+ memcpy(bytes, (const void *) (h->buffer + h->offset), result);
+ h->offset += result;
+ }
+ return result;
+}
+
+static void property_util_cstring_rewind(uint32_t context)
+{
+ struct cstring_read_handle *h = TlsGetValue(context);
+ h->offset = 0;
+}
+
+static int property_util_avs_read(uint32_t context, void *bytes, size_t nbytes)
+{
+ avs_desc desc = (avs_desc) context;
+ return avs_fs_read(desc, bytes, nbytes);
+}
+
+static void property_util_avs_rewind(uint32_t context)
+{
+ avs_desc desc = (avs_desc) context;
+ avs_fs_lseek(desc, 0, AVS_SEEK_SET);
+}
+
+void property_util_log(struct property *property)
+{
+ property_util_log_node_tree_rec(property_search(property, NULL, "/"), "");
+}
+
+void property_util_node_log(struct property_node *node)
+{
+ property_util_log_node_tree_rec(node, "");
+}
+
+struct property *property_util_load(const char *filename)
+{
+ FILE *f;
+ uint32_t f_keyhole;
+ struct property *prop;
+
+ log_assert(filename);
+
+ /* AVS callbacks are only given a 32-bit context parameter, even in 64-bit
+ builds of AVS. We allocate a 32-bit TLS key and pass the context in this
+ manner instead. Inefficient, but it works. */
+
+ f = fopen(filename, "r");
+
+ f_keyhole = TlsAlloc();
+ TlsSetValue(f_keyhole, f);
+
+ if (f == NULL) {
+ log_fatal("%s: Error opening configuration file", filename);
+ }
+
+ prop = property_util_do_load(
+ property_util_fread, property_util_frewind, f_keyhole, filename);
+
+ TlsFree(f_keyhole);
+
+ fclose(f);
+
+ return prop;
+}
+
+struct property *property_util_avs_fs_load(const char *filename)
+{
+ avs_desc desc;
+ struct property *prop;
+
+ log_assert(filename);
+
+ desc = avs_fs_open(filename, AVS_FILE_READ, AVS_FILE_FLAG_SHARE_READ);
+
+ if (!desc) {
+ log_fatal("%s: Error opening configuration file", filename);
+ }
+
+ prop = property_util_do_load(
+ property_util_avs_read, property_util_avs_rewind, desc, filename);
+
+ avs_fs_close(desc);
+
+ return prop;
+}
+
+struct property *property_util_cstring_load(const char *cstring)
+{
+ uint32_t s_keyhole;
+ struct property *prop;
+
+ log_assert(cstring);
+
+ // see above
+ struct cstring_read_handle read_handle;
+ read_handle.buffer = cstring;
+ read_handle.buffer_len = strlen(cstring);
+ read_handle.offset = 0;
+
+ s_keyhole = TlsAlloc();
+ TlsSetValue(s_keyhole, &read_handle);
+
+ prop = property_util_do_load(
+ property_util_cstring_read,
+ property_util_cstring_rewind,
+ s_keyhole,
+ "");
+
+ TlsFree(s_keyhole);
+
+ return prop;
+}
+
+uint32_t property_util_property_query_real_size(struct property *property)
+{
+ avs_error size;
+
+ log_assert(property);
+
+ // Returns the size of the actual data in the property structure only
+ // Hence, using that size only, allocating another buffer for a copy
+ // of this might fail or copying the data will fail because the buffer
+ // is too small
+ size = property_query_size(property);
+
+ if (AVS_IS_ERROR(size)) {
+ log_fatal(
+ "Querying property size failed: %s", avs_util_error_str(size));
+ }
+
+ // Hack: *2 to have enough space and not cut off data when cloning/copying
+ // property data because...reasons? I haven't figured this one out and
+ // there doesn't seem to be an actual API call for that to return the
+ // "true" size that allows the caller to figure out how much memory
+ // they have to allocate to create a copy of the property structure
+ // with property_create and
+ return (PROPERTY_STRUCTURE_META_SIZE + size) * 2;
+}
+
+void property_util_node_u8_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ uint8_t val)
+{
+ struct property_node *tmp;
+
+ log_assert(node);
+ log_assert(name);
+
+ tmp = property_search(property, node, name);
+
+ if (tmp) {
+ property_node_remove(tmp);
+ }
+
+ property_node_create(property, node, PROPERTY_TYPE_U8, name, val);
+}
+
+void property_util_node_u16_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ uint16_t val)
+{
+ struct property_node *tmp;
+
+ log_assert(node);
+ log_assert(name);
+
+ tmp = property_search(property, node, name);
+
+ if (tmp) {
+ property_node_remove(tmp);
+ }
+
+ property_node_create(property, node, PROPERTY_TYPE_U16, name, val);
+}
+
+void property_util_node_u32_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ uint32_t val)
+{
+ struct property_node *tmp;
+
+ log_assert(node);
+ log_assert(name);
+
+ tmp = property_search(property, node, name);
+
+ if (tmp) {
+ property_node_remove(tmp);
+ }
+
+ property_node_create(property, node, PROPERTY_TYPE_U32, name, val);
+}
+
+void property_util_node_str_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ const char *val)
+{
+ struct property_node *tmp;
+
+ log_assert(node);
+ log_assert(name);
+
+ tmp = property_search(property, node, name);
+
+ if (tmp) {
+ property_node_remove(tmp);
+ }
+
+ property_node_create(property, node, PROPERTY_TYPE_STR, name, val);
+}
+
+void property_util_node_bool_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ bool val)
+{
+ struct property_node *tmp;
+
+ log_assert(node);
+ log_assert(name);
+
+ tmp = property_search(property, node, name);
+
+ if (tmp) {
+ property_node_remove(tmp);
+ }
+
+ property_node_create(property, node, PROPERTY_TYPE_BOOL, name, val);
+}
+
+static void _property_util_node_merge_rec(
+ struct property *parent_property,
+ struct property_node *parent,
+ struct property_node *source)
+{
+ char name[256];
+ struct property_node *child;
+ struct property_node *matching_child;
+
+ log_assert(parent_property);
+
+ if (!source) {
+ return;
+ }
+
+ if (!parent) {
+ property_node_clone(parent_property, parent, source, true);
+ return;
+ }
+
+ child = property_node_traversal(source, TRAVERSE_FIRST_CHILD);
+
+ while (child) {
+ property_node_name(child, name, sizeof(name));
+
+ matching_child = property_search(parent_property, parent, name);
+
+ if (!matching_child) {
+ property_node_clone(parent_property, parent, child, true);
+ } else {
+ _property_util_node_merge_rec(
+ parent_property, matching_child, child);
+ }
+
+ child = property_node_traversal(child, TRAVERSE_NEXT_SIBLING);
+ }
+}
+
+struct property *property_util_merge(struct property **properties, size_t count)
+{
+ uint32_t total_size;
+ void *buffer;
+ struct property *merged_property;
+ int i;
+ struct property_node *parent_node;
+ struct property_node *to_merge_node;
+
+ log_assert(properties);
+ log_assert(count > 0);
+
+ total_size = 0;
+
+ for (int i = 0; i < count; i++) {
+ total_size += property_util_property_query_real_size(properties[i]);
+ }
+
+ buffer = xmalloc(total_size);
+
+ merged_property = property_create(
+ PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE |
+ PROPERTY_FLAG_APPEND,
+ buffer,
+ total_size);
+
+ for (i = 0; i < count; i++) {
+ parent_node = property_search(merged_property, NULL, "/");
+ to_merge_node = property_search(properties[i], NULL, "/");
+
+ property_util_node_merge(merged_property, parent_node, to_merge_node);
+ }
+
+ return merged_property;
+}
+
+struct property *property_util_clone(struct property_node *node)
+{
+ struct property *property;
+ struct property_node *root_node;
+ uint32_t size;
+ void *buffer;
+
+ if (!node) {
+ return NULL;
+ }
+
+ // Hack: Is it even possible to get the size of a (sub-) node without
+ // the property? 256kb should be fine for now, even for larger
+ // configurations. Obviously, this scales horribly and wastes a lot of
+ // memory for most smaller sub-nodes
+ size = 1024 * 256;
+
+ buffer = xmalloc(size);
+ property = property_create(
+ PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE |
+ PROPERTY_FLAG_APPEND,
+ buffer,
+ size);
+ root_node = property_search(property, NULL, "");
+
+ property_node_clone(property, root_node, node, true);
+
+ return property;
+}
+
+void property_util_node_merge(
+ struct property *parent_property,
+ struct property_node *parent,
+ struct property_node *source)
+{
+ _property_util_node_merge_rec(parent_property, parent, source);
+}
+
+void property_util_free(struct property *prop)
+{
+ void *buffer;
+
+ buffer = property_desc_to_buffer(prop);
+ property_destroy(prop);
+ free(buffer);
+}
diff --git a/src/main/launcher/property-util.h b/src/main/launcher/property-util.h
new file mode 100644
index 00000000..07649c26
--- /dev/null
+++ b/src/main/launcher/property-util.h
@@ -0,0 +1,46 @@
+#ifndef PROPERTY_UTIL_H
+#define PROPERTY_UTIL_H
+
+#include "imports/avs.h"
+
+void property_util_log(struct property *property);
+void property_util_node_log(struct property_node *node);
+struct property *property_util_load(const char *filename);
+struct property *property_util_avs_fs_load(const char *filename);
+struct property *property_util_cstring_load(const char *cstring);
+uint32_t property_util_property_query_real_size(struct property *property);
+void property_util_node_u8_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ uint8_t val);
+void property_util_node_u16_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ uint16_t val);
+void property_util_node_u32_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ uint32_t val);
+void property_util_node_str_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ const char *val);
+void property_util_node_bool_replace(
+ struct property *property,
+ struct property_node *node,
+ const char *name,
+ bool val);
+struct property *property_util_clone(struct property_node *node);
+struct property *
+property_util_merge(struct property **properties, size_t count);
+void property_util_node_merge(
+ struct property *parent_property,
+ struct property_node *parent_node,
+ struct property_node *source_node);
+void property_util_free(struct property *prop);
+
+#endif
diff --git a/src/main/launcher/property.c b/src/main/launcher/property.c
deleted file mode 100644
index 2f5ded94..00000000
--- a/src/main/launcher/property.c
+++ /dev/null
@@ -1,135 +0,0 @@
-#include
-
-#include
-#include
-#include
-
-#include "imports/avs.h"
-
-#include "launcher/property.h"
-
-#include "util/log.h"
-#include "util/mem.h"
-
-static int boot_property_fread(uint32_t context, void *bytes, size_t nbytes)
-{
- FILE *f;
-
- f = TlsGetValue(context);
-
- return fread(bytes, 1, nbytes, f);
-}
-
-struct cstring_read_handle {
- const char *buffer;
- size_t buffer_len;
- size_t offset;
-};
-
-static int
-boot_property_cstring_read(uint32_t context, void *bytes, size_t nbytes)
-{
- int result = 0;
- struct cstring_read_handle *h = TlsGetValue(context);
-
- if (h->offset < h->buffer_len) {
- result = min(nbytes, h->buffer_len - h->offset);
- memcpy(bytes, (const void *) (h->buffer + h->offset), result);
- h->offset += result;
- }
- return result;
-}
-
-struct property *boot_property_load(const char *filename)
-{
- struct property *prop;
- void *buffer;
- int nbytes;
- FILE *f;
- uint32_t f_keyhole;
-
- /* AVS callbacks are only given a 32-bit context parameter, even in 64-bit
- builds of AVS. We allocate a 32-bit TLS key and pass the context in this
- manner instead. Inefficient, but it works. */
-
- f = fopen(filename, "r");
-
- f_keyhole = TlsAlloc();
- TlsSetValue(f_keyhole, f);
-
- if (f == NULL) {
- log_fatal("%s: Error opening configuration file", filename);
- }
-
- nbytes = property_read_query_memsize(boot_property_fread, f_keyhole, 0, 0);
-
- if (nbytes < 0) {
- log_fatal("%s: Error querying configuration file", filename);
- }
-
- buffer = xmalloc(nbytes);
- prop = property_create(
- PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE |
- PROPERTY_FLAG_APPEND,
- buffer,
- nbytes);
- rewind(f);
-
- if (!property_insert_read(prop, 0, boot_property_fread, f_keyhole)) {
- log_fatal("%s: Error reading configuration file", filename);
- }
-
- TlsFree(f_keyhole);
-
- fclose(f);
-
- return prop;
-}
-struct property *boot_property_load_cstring(const char *cstring)
-{
- struct property *prop;
- void *buffer;
- int nbytes;
- uint32_t s_keyhole;
-
- // see above
- struct cstring_read_handle read_handle;
- read_handle.buffer = cstring;
- read_handle.buffer_len = strlen(cstring);
- read_handle.offset = 0;
-
- s_keyhole = TlsAlloc();
- TlsSetValue(s_keyhole, &read_handle);
-
- nbytes = property_read_query_memsize(
- boot_property_cstring_read, s_keyhole, 0, 0);
-
- if (nbytes < 0) {
- log_fatal("Error querying configuration string");
- }
-
- buffer = xmalloc(nbytes);
- prop = property_create(
- PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE |
- PROPERTY_FLAG_APPEND,
- buffer,
- nbytes);
-
- read_handle.offset = 0;
- if (!property_insert_read(prop, 0, boot_property_cstring_read, s_keyhole)) {
- log_fatal("Error inserting configuration string");
- }
-
- TlsFree(s_keyhole);
-
- return prop;
-}
-
-void boot_property_free(struct property *prop)
-{
- void *buffer;
-
- buffer = property_desc_to_buffer(prop);
- property_destroy(prop);
- free(buffer);
-}
diff --git a/src/main/launcher/property.h b/src/main/launcher/property.h
deleted file mode 100644
index c3f14d0e..00000000
--- a/src/main/launcher/property.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef LAUNCHER_PROPERTY_H
-#define LAUNCHER_PROPERTY_H
-
-#include "imports/avs.h"
-
-struct property *boot_property_load(const char *filename);
-struct property *boot_property_load_cstring(const char *cstring);
-void boot_property_free(struct property *prop);
-
-#endif
diff --git a/src/main/launcher/stubs.c b/src/main/launcher/stubs.c
index a524273b..80cb18bf 100644
--- a/src/main/launcher/stubs.c
+++ b/src/main/launcher/stubs.c
@@ -1,3 +1,5 @@
+#define LOG_MODULE "stubs"
+
#include
#include
@@ -116,6 +118,8 @@ static void *STDCALL my_GetProcAddress(HMODULE dll, const char *name)
void stubs_init(void)
{
+ log_info("Init");
+
hook_table_apply(
NULL, "kernel32.dll", stub_hook_syms, lengthof(stub_hook_syms));
}
diff --git a/src/main/p3ioemu/emu.c b/src/main/p3ioemu/emu.c
index dbf2c8a5..6486d595 100644
--- a/src/main/p3ioemu/emu.c
+++ b/src/main/p3ioemu/emu.c
@@ -48,8 +48,8 @@ static void p3io_cmd_get_cab_type_or_dipsw(
static void p3io_cmd_get_video_freq(
const struct p3io_req_get_video_freq *req,
struct p3io_resp_get_video_freq *resp);
-static void
-p3io_cmd_unknown_2b(const struct p3io_req_unknown_2b *req, struct p3io_resp_unknown_2b *resp);
+static void p3io_cmd_unknown_2b(
+ const struct p3io_req_unknown_2b *req, struct p3io_resp_unknown_2b *resp);
static void
p3io_cmd_init(const struct p3io_req_init *req, struct p3io_resp_init *resp);
static void p3io_cmd_get_coinstock(
@@ -57,8 +57,9 @@ static void p3io_cmd_get_coinstock(
static void p3io_cmd_set_coin_counter(
const struct p3io_req_set_coin_counter *req,
struct p3io_resp_set_coin_counter *resp);
-static void
-p3io_cmd_unknown(const struct p3io_req_unknown_generic *req, struct p3io_resp_unknown_generic *resp);
+static void p3io_cmd_unknown(
+ const struct p3io_req_unknown_generic *req,
+ struct p3io_resp_unknown_generic *resp);
void p3io_emu_init(const struct p3io_ops *ops, void *ctx)
{
@@ -518,8 +519,8 @@ static void p3io_cmd_get_video_freq(
}
}
-static void
-p3io_cmd_unknown_2b(const struct p3io_req_unknown_2b *req, struct p3io_resp_unknown_2b *resp)
+static void p3io_cmd_unknown_2b(
+ const struct p3io_req_unknown_2b *req, struct p3io_resp_unknown_2b *resp)
{
log_misc("Unknown 2b");
@@ -573,10 +574,13 @@ static void p3io_cmd_set_coin_counter(
resp->status = 0;
}
-static void
-p3io_cmd_unknown(const struct p3io_req_unknown_generic *req, struct p3io_resp_unknown_generic *resp)
+static void p3io_cmd_unknown(
+ const struct p3io_req_unknown_generic *req,
+ struct p3io_resp_unknown_generic *resp)
{
- log_warning("Unsupported P3IO command, sending default response (might not work/crash though): %02x",
+ log_warning(
+ "Unsupported P3IO command, sending default response (might not "
+ "work/crash though): %02x",
req->hdr.cmd);
p3io_resp_hdr_init(&resp->hdr, sizeof(*resp), &req->hdr);
diff --git a/src/main/util/Module.mk b/src/main/util/Module.mk
index ab8d4956..af7851ec 100644
--- a/src/main/util/Module.mk
+++ b/src/main/util/Module.mk
@@ -5,6 +5,7 @@ src_util := \
cmdline.c \
crc.c \
crypto.c \
+ debug.c \
fs.c \
hex.c \
iobuf.c \
diff --git a/src/main/util/debug.c b/src/main/util/debug.c
new file mode 100644
index 00000000..f07e401c
--- /dev/null
+++ b/src/main/util/debug.c
@@ -0,0 +1,184 @@
+#define LOG_MODULE "util-debug"
+
+#include
+
+#include
+
+#include "imports/dwarfstack.h"
+
+#include "util/debug.h"
+#include "util/log.h"
+
+#define EX_DESC(name) \
+ case EXCEPTION_##name: \
+ desc = " (" #name ")"; \
+ break
+
+static void _debug_stacktrace_printer(
+ uint64_t addr,
+ const char *filename,
+ int lineno,
+ const char *funcname,
+ void *context,
+ int columnno)
+{
+ int *count;
+ const char *delim;
+ void *ptr;
+ char buffer[512];
+ char *buffer_ptr;
+
+ count = context;
+ delim = strrchr(filename, '/');
+
+ if (delim) {
+ filename = delim + 1;
+ }
+
+ delim = strrchr(filename, '\\');
+
+ if (delim) {
+ filename = delim + 1;
+ }
+
+ ptr = (void *) (uintptr_t) addr;
+
+ switch (lineno) {
+ case DWST_BASE_ADDR:
+ log_exception_handler("base address: 0x%p (%s)", ptr, filename);
+ break;
+
+ case DWST_NOT_FOUND:
+ case DWST_NO_DBG_SYM:
+ case DWST_NO_SRC_FILE:
+ log_exception_handler(
+ " stack %02d: 0x%p (%s)", (*count)++, ptr, filename);
+ break;
+
+ default:
+ buffer_ptr = buffer;
+ memset(buffer, 0, sizeof(buffer));
+
+ if (ptr) {
+ buffer_ptr += sprintf(
+ buffer_ptr, " stack %02d: 0x%p", (*count)++, ptr);
+ } else {
+ buffer_ptr += sprintf(
+ buffer_ptr,
+ " %*s",
+ (int) sizeof(void *) * 2,
+ "");
+ }
+
+ buffer_ptr += sprintf(buffer_ptr, " (%s:%d", filename, lineno);
+
+ if (columnno > 0) {
+ buffer_ptr += sprintf(buffer_ptr, ":%d", columnno);
+ }
+
+ buffer_ptr += sprintf(buffer_ptr, ")");
+
+ if (funcname) {
+ buffer_ptr += sprintf(buffer_ptr, " [%s]", funcname);
+ }
+
+ log_exception_handler(buffer);
+
+ break;
+ }
+}
+
+static LONG WINAPI _debug_unhandled_exception_filter(LPEXCEPTION_POINTERS ep)
+{
+ DWORD code;
+ const char *desc;
+ ULONG_PTR flag;
+ ULONG_PTR addr;
+ int count;
+
+ log_exception_handler(
+ "==========================================================");
+ log_exception_handler(
+ "The application has crashed due to an unhandled exception!");
+
+ code = ep->ExceptionRecord->ExceptionCode;
+ desc = debug_exception_code_to_str(code);
+
+ log_exception_handler("code: 0x%08lX", code);
+ log_exception_handler("desc: %s", desc);
+
+ if (code == EXCEPTION_ACCESS_VIOLATION &&
+ ep->ExceptionRecord->NumberParameters == 2) {
+ flag = ep->ExceptionRecord->ExceptionInformation[0];
+ addr = ep->ExceptionRecord->ExceptionInformation[1];
+
+ log_exception_handler(
+ "%s violation at 0x%p",
+ flag == 8 ? "data execution prevention" :
+ (flag ? "write access" : "read access"),
+ (void *) addr);
+ }
+
+ log_exception_handler("stacktrace:");
+
+ count = 0;
+
+ dwstOfException(ep->ContextRecord, &_debug_stacktrace_printer, &count);
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+void debug_init()
+{
+ SetUnhandledExceptionFilter(_debug_unhandled_exception_filter);
+
+ log_info("Initialized");
+}
+
+void debug_print_stacktrace()
+{
+ int count;
+
+ count = 0;
+
+ log_exception_handler(
+ "==========================================================");
+ log_exception_handler("Debug stacktrace");
+
+ dwstOfLocation(&_debug_stacktrace_printer, &count);
+}
+
+const char *debug_exception_code_to_str(DWORD code)
+{
+ const char *desc = "";
+
+ switch (code) {
+ EX_DESC(ACCESS_VIOLATION);
+ EX_DESC(ARRAY_BOUNDS_EXCEEDED);
+ EX_DESC(BREAKPOINT);
+ EX_DESC(DATATYPE_MISALIGNMENT);
+ EX_DESC(FLT_DENORMAL_OPERAND);
+ EX_DESC(FLT_DIVIDE_BY_ZERO);
+ EX_DESC(FLT_INEXACT_RESULT);
+ EX_DESC(FLT_INVALID_OPERATION);
+ EX_DESC(FLT_OVERFLOW);
+ EX_DESC(FLT_STACK_CHECK);
+ EX_DESC(FLT_UNDERFLOW);
+ EX_DESC(ILLEGAL_INSTRUCTION);
+ EX_DESC(IN_PAGE_ERROR);
+ EX_DESC(INT_DIVIDE_BY_ZERO);
+ EX_DESC(INT_OVERFLOW);
+ EX_DESC(INVALID_DISPOSITION);
+ EX_DESC(NONCONTINUABLE_EXCEPTION);
+ EX_DESC(PRIV_INSTRUCTION);
+ EX_DESC(SINGLE_STEP);
+ EX_DESC(STACK_OVERFLOW);
+ case DBG_CONTROL_C:
+ return "DBG_CONTROL_C";
+ default:
+ log_warning("Unknown exception code: %lX", code);
+ return "Unknown";
+ }
+
+ return desc;
+}
\ No newline at end of file
diff --git a/src/main/util/debug.h b/src/main/util/debug.h
new file mode 100644
index 00000000..80519050
--- /dev/null
+++ b/src/main/util/debug.h
@@ -0,0 +1,10 @@
+#ifndef UTIL_DEBUG_H
+#define UTIL_DEBUG_H
+
+#include
+
+void debug_init();
+void debug_print_stacktrace();
+const char *debug_exception_code_to_str(DWORD code);
+
+#endif
\ No newline at end of file
diff --git a/src/main/util/log.c b/src/main/util/log.c
index 7da1d63a..bd643293 100644
--- a/src/main/util/log.c
+++ b/src/main/util/log.c
@@ -64,6 +64,15 @@ static void log_builtin_format(
}
}
+void log_exception_handler(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ log_builtin_format(LOG_LEVEL_FATAL, LOG_MODULE, fmt, ap);
+ va_end(ap);
+}
+
void log_assert_body(const char *file, int line, const char *function)
{
log_impl_fatal("assert", "%s:%d: function `%s'", file, line, function);
diff --git a/src/main/util/log.h b/src/main/util/log.h
index 47603fa1..e8a0bd0c 100644
--- a/src/main/util/log.h
+++ b/src/main/util/log.h
@@ -66,6 +66,7 @@ enum log_level {
LOG_LEVEL_MISC = 3,
};
+void log_exception_handler(const char *fmt, ...);
void log_assert_body(const char *file, int line, const char *function);
void log_to_external(
log_formatter_t misc,
diff --git a/src/main/util/proc.c b/src/main/util/proc.c
index 19cec50d..84731133 100644
--- a/src/main/util/proc.c
+++ b/src/main/util/proc.c
@@ -1,7 +1,55 @@
+#define LOG_MODULE "util-proc"
+
#include
+#include
+#include
#include
+#include "util/log.h"
+
+bool proc_is_running_as_admin_user()
+{
+ SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
+ PSID sid;
+ BOOL res;
+ BOOL is_admin;
+
+ res = AllocateAndInitializeSid(
+ &authority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ &sid);
+
+ if (!res) {
+ log_warning(
+ "Failed to allocate memory for is admin check: %lX",
+ GetLastError());
+ return false;
+ }
+
+ is_admin = false;
+
+ res = CheckTokenMembership(NULL, sid, &is_admin);
+
+ if (!res) {
+ log_warning(
+ "Failed to check admin group membership: %lX", GetLastError());
+ return false;
+ }
+
+ FreeSid(sid);
+
+ return is_admin;
+}
+
void proc_terminate_current_process(uint32_t exit_code)
{
HANDLE hnd;
diff --git a/src/main/util/proc.h b/src/main/util/proc.h
index 3dc69062..be47a40d 100644
--- a/src/main/util/proc.h
+++ b/src/main/util/proc.h
@@ -1,5 +1,8 @@
#pragma once
+#include
#include
+bool proc_is_running_as_admin_user();
+
void proc_terminate_current_process(uint32_t exit_code);
\ No newline at end of file
diff --git a/src/main/util/signal.c b/src/main/util/signal.c
index 4c15acd5..c35cb270 100644
--- a/src/main/util/signal.c
+++ b/src/main/util/signal.c
@@ -1,5 +1,4 @@
#include
-#include
#include "util/hex.h"
#include "util/log.h"
@@ -45,40 +44,9 @@ static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType)
return FALSE;
}
-static LONG WINAPI
-unhandled_exception_filter(struct _EXCEPTION_POINTERS *ExceptionInfo)
-{
- // no exception info provided
- if (ExceptionInfo != NULL) {
- struct _EXCEPTION_RECORD *ExceptionRecord =
- ExceptionInfo->ExceptionRecord;
-
- log_warning(
- "Exception raised: %s",
- signal_exception_code_to_str(ExceptionRecord->ExceptionCode));
-
- struct _EXCEPTION_RECORD *record_cause =
- ExceptionRecord->ExceptionRecord;
-
- while (record_cause != NULL) {
- log_warning(
- "Caused by: %s",
- signal_exception_code_to_str(record_cause->ExceptionCode));
- record_cause = record_cause->ExceptionRecord;
- }
-
- // TODO print stacktrace
-
- log_fatal("End exception handler");
- }
-
- return EXCEPTION_CONTINUE_SEARCH;
-}
-
void signal_exception_handler_init()
{
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
- SetUnhandledExceptionFilter(unhandled_exception_filter);
log_info("Initialized");
}
@@ -88,55 +56,4 @@ void signal_register_shutdown_handler(signal_shutdown_handler_t handler)
shutdown_handler = handler;
log_misc("Registered shutdown handler");
-}
-
-const char *signal_exception_code_to_str(DWORD code)
-{
- switch (code) {
- case EXCEPTION_ACCESS_VIOLATION:
- return "EXCEPTION_ACCESS_VIOLATION";
- case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
- return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
- case EXCEPTION_BREAKPOINT:
- return "EXCEPTION_BREAKPOINT";
- case EXCEPTION_DATATYPE_MISALIGNMENT:
- return "EXCEPTION_DATATYPE_MISALIGNMENT";
- case EXCEPTION_FLT_DENORMAL_OPERAND:
- return "EXCEPTION_FLT_DENORMAL_OPERAND";
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
- case EXCEPTION_FLT_INEXACT_RESULT:
- return "EXCEPTION_FLT_INEXACT_RESULT";
- case EXCEPTION_FLT_INVALID_OPERATION:
- return "EXCEPTION_FLT_INVALID_OPERATION";
- case EXCEPTION_FLT_OVERFLOW:
- return "EXCEPTION_FLT_OVERFLOW";
- case EXCEPTION_FLT_STACK_CHECK:
- return "EXCEPTION_FLT_STACK_CHECK";
- case EXCEPTION_FLT_UNDERFLOW:
- return "EXCEPTION_FLT_UNDERFLOW";
- case EXCEPTION_ILLEGAL_INSTRUCTION:
- return "EXCEPTION_ILLEGAL_INSTRUCTION";
- case EXCEPTION_IN_PAGE_ERROR:
- return "EXCEPTION_IN_PAGE_ERROR";
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- return "EXCEPTION_INT_DIVIDE_BY_ZERO";
- case EXCEPTION_INT_OVERFLOW:
- return "EXCEPTION_INT_OVERFLOW";
- case EXCEPTION_INVALID_DISPOSITION:
- return "EXCEPTION_INVALID_DISPOSITION";
- case EXCEPTION_NONCONTINUABLE_EXCEPTION:
- return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
- case EXCEPTION_PRIV_INSTRUCTION:
- return "EXCEPTION_PRIV_INSTRUCTION";
- case EXCEPTION_SINGLE_STEP:
- return "EXCEPTION_SINGLE_STEP";
- case EXCEPTION_STACK_OVERFLOW:
- return "EXCEPTION_STACK_OVERFLOW";
- case DBG_CONTROL_C:
- return "DBG_CONTROL_C";
- default:
- log_warning("Unknown exception code: %lX", code);
- return "Unknown";
- }
}
\ No newline at end of file