diff --git a/CHANGELOG.md b/CHANGELOG.md index a8529ba0..58ae6d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,117 @@ Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions given in tags. The pipeline will pick this up and cuts out the relevant section for release notes. +## 6.0.0-alpha.3 + +**THIS IS A HIGHLY WORK/DEVELOPMENT IN PROGRESS VERSION** + +**THINGS ARE BROKEN AND EVERYTHING IS SUBJECT TO CHANGE** + +Goals of this version: + +* property (node) API implementation without AVS -> [mxml](https://github.com/michaelrsweet/mxml) +* inject refactoring similar to launcher + * Re-structure modules + * Use bemanitools config API backed by property (node) API with mxml (because no AVS2) +* SDK foundation for hook libraries bootstrapping with DllMain +* iidxhook1 refactoring to use new SDK hook foundation and bemanitools config API + +This brings inject and launcher closer together regarding common functionality. inject is also +using a "bootstrap.xml" style approach with a XML configuration file. That configuration file +can also include further inlined or referenced configuration for any hooks to be loaded. + +With a new module that will serve as a piece of a public SDK in the future, any library that just +bootstraps with DllMain can implement the Bemanitools 6 hook API transparently. This solution +isn't ideal, but it works with a bit of duct-tape fairly well. A future improve would be to have +improved hooking in inject to have a pre- and post-main function hook. However, that is a lot more +work as it requires our own PE loader to bootstrap the entire executable to get more fine grained +control. + +Remarks regarding what's known to be broken: Inject command line args + overrides + +## 6.0.0-alpha.2 + +**THIS IS A HIGHLY WORK/DEVELOPMENT IN PROGRESS VERSION** + +**THINGS ARE BROKEN AND EVERYTHING IS SUBJECT TO CHANGE** + +Goal of this version: Fix blocking logging which results in performance impact on many games using +both launcher and inject. The impact typically materialized as the game stuttering, briefly slowing +down, music de-syncing or occasional laggy input. + +This was a fundamental issue to the previous logging architecture in bemanitools. With the pre-work +of having a more modular logging API that can be shared and used across internal components as well +as public APIs including hooks, unified logging can be applied throughout the bemanitools stack. + +With this, all logging is channeled to a single logger, the bemanitools logger, where we have full +control over how we log any log output (but also full control of messing it up =)). + +With this, we can also move away from the band aid of the log-server that's been used in iidx +versions 19 to 24 because non AVS threads logging through the AVS logging system were crashing (see +[this document](doc/dev/journal/2018-02-10-logging-breakdown-avs.md) for details). + +A new async log sink takes care of de-coupling the non blocking producing/posting of messages to +a configurable queue by any number of threads concurrently, with a single producer thread consuming +these messages from the queue and forwarding them to a configured target sink, e.g. file, terminal. + +With this, we ensure that threads with log messages don't have to wait for synchronization on +expensive and slow IO. + +These changes have been applied to to launcher and inject. The log-server module has been removed +entirely from any (iidx) games using it. + +## 6.0.0-alpha.1 + +**THIS IS A HIGHLY WORK/DEVELOPMENT IN PROGRESS VERSION** + +**THINGS ARE BROKEN AND EVERYTHING IS SUBJECT TO CHANGE** + +First cut after massive refactoring with most critical and fundamental changes implemented. +We need to start somewhere, and this might be as good as anything else, so we can get started +with testing, bug fixing and iterating for the next releases. + +The following list is non-exhaustive, does not guarantee anything does work, yet, and is supposed +to give a high level idea of what all of this is about. Updated documentation will reflect all of +this at some later point in time in more detail. + +* A common "core" now abstracts logging, thread, property and configuration infrastructure and + provides a common interface. This is used by bemanitools internally as well as all tools, hooks + and APIs provided and don't depend on the game, version of the game or AVS version available + anymore +* New bemanitools (public) API + * Versioned API allowing for handling incremental API changes as well as breaking changes by + providing a new/different version when necessary + * Unified interfaces for bemanitools core API, i.e. logging, threads, configuration + * SDK with examples (TBD) + * Dogfooding approach: Bemanitools uses its own (public) API to implement and provide fundamental + features like configurable keyboard implementations for IO or hooks for different games and + versions +* All bemanitools hooks and IO libraries have been or are about to be re-worked to use the new APIs +* New hook API allows for more fine grained runtime control when stages of the hook are to be + executed, i.e. pre AVS, before main game, iat hooking instead of relying purely on DllMain + (which is still a compatible option though) +* launcher as a replacement for bootstrap: Bring it significantly closer to the original bootstrap + by supporting completely vanilla data and bootstrap.xml configurations to run the games. Note + that bemanitools does not include any code or means to run DRM'd data, only decrypted +* inject is also being reworked to use as much of the same "infrastructure" as launcher to provide + a more seamless bootstrapping process for games that keeps pre-eapki data as vanilla as possible + +### What works + +* inject: Basic functionality, launches games iidx 09 to 17 with iidxhook1 to iidxhook4 +* launcher: Basic functionality, launches games iidx 09 to 17 with iidxhook5 to iidxhook7 +* iidxhook1: Boots, reaching in-game with keyboard inputs working +* iidxhook2: Boots, reaching in-game with keyboard inputs working +* iidxhook3: Boots, reaching in-game with keyboard inputs working +* iidxhook4: Boots, reaching in-game with keyboard inputs working +* iidxhook5: Boots, reaching in-game with keyboard inputs working +* iidxhook6: Boots, reaching in-game with keyboard inputs working +* iidxhook7: Boots, reaching in-game with keyboard inputs working + +### What's broken + +Since everything else is untested, consider it (very) broken + ## 5.49 ### Features diff --git a/GNUmakefile b/GNUmakefile index 9aef0b1b..d2f8ed57 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -27,7 +27,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 @@ -139,13 +139,14 @@ libs := avsdlls := avsexes := +avslibs := testdlls := testexes := include Module.mk -modules := $(dlls) $(exes) $(libs) $(avsdlls) $(avsexes) $(testdlls) $(testexes) +modules := $(dlls) $(exes) $(libs) $(avsdlls) $(avsexes) $(avslibs) $(testdlls) $(testexes) # # $1: Bitness @@ -200,6 +201,7 @@ $$(bindir_$1_$2): $$(eval $$(foreach imp,$(imps),$$(call t_import,$1,$2,$$(imp)))) $$(eval $$(foreach dll,$(avsdlls),$$(call t_linkdll,$1,$2,$$(dll)))) $$(eval $$(foreach exe,$(avsexes),$$(call t_linkexe,$1,$2,$$(exe)))) +$$(eval $$(foreach lib,$(avslibs),$$(call t_archive,$1,$2,$$(lib)))) endef @@ -209,6 +211,7 @@ define t_compile depdir_$1_$2_$3 := $(depdir)/$$(subdir_$1_$2)/$3 abslib_$1_$2_$3 := $$(libs_$3:%=$$(bindir_$1_indep)/lib%.a) +avslib_$1_$2_$3 := $$(avslibs_$3:%=$$(bindir_$1_$2)/lib%.a) absdpl_$1_$2_$3 := $$(deplibs_$3:%=$$(bindir_$1_$2)/lib%.a) objdir_$1_$2_$3 := $(objdir)/$$(subdir_$1_$2)/$3 obj_$1_$2_$3 := $$(src_$3:%.c=$$(objdir_$1_$2_$3)/%.o) \ @@ -260,13 +263,13 @@ dll_$1_$2_$3 := $$(bindir_$1_$2)/$3.dll implib_$1_$2_$3 := $$(bindir_$1_$2)/lib$3.a $$(dll_$1_$2_$3) $$(implib_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) \ + $$(avslib_$1_$2_$3) \ $$(absdpl_$1_$2_$3) \ $$(srcdir_$3)/$3.def | $$(bindir_$1_$2) $(V)echo ... $$(dll_$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 @@ -279,11 +282,10 @@ $(t_compile) exe_$1_$2_$3 := $$(bindir_$1_$2)/$3.exe -$$(exe_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) $$(absdpl_$1_$2_$3) \ +$$(exe_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) $$(avslib_$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 16a1177f..423c1060 100644 --- a/Module.mk +++ b/Module.mk @@ -85,21 +85,23 @@ avsvers_64 := 1700 1603 1601 1509 1508 imps += avs avs-ea3 +include src/main/mxml/Module.mk + include src/main/aciodrv/Module.mk include src/main/aciodrv-proc/Module.mk include src/main/acioemu/Module.mk -include src/main/aciomgr/Module.mk +include src/main/acio-mgr/Module.mk include src/main/aciotest/Module.mk include src/main/asio/Module.mk -include src/main/avs-util/Module.mk +include src/main/avs-ext/Module.mk include src/main/bio2drv/Module.mk include src/main/bio2emu-iidx/Module.mk include src/main/bio2emu/Module.mk include src/main/bsthook/Module.mk include src/main/bstio/Module.mk include src/main/camhook/Module.mk -include src/main/cconfig/Module.mk include src/main/config/Module.mk +include src/main/core/Module.mk include src/main/d3d9-util/Module.mk include src/main/d3d9exhook/Module.mk include src/main/ddrhook-util/Module.mk @@ -115,6 +117,7 @@ include src/main/dinput/Module.mk include src/main/eamio-icca/Module.mk include src/main/eamio/Module.mk include src/main/eamiotest/Module.mk +include src/main/exceptiontrace/Module.mk include src/main/extio/Module.mk include src/main/extiodrv/Module.mk include src/main/extiotest/Module.mk @@ -137,6 +140,10 @@ include src/main/ezusb2/Module.mk include src/main/geninput/Module.mk include src/main/hook/Module.mk include src/main/hooklib/Module.mk +include src/main/iface/Module.mk +include src/main/iface-acio/Module.mk +include src/main/iface-core/Module.mk +include src/main/iface-io/Module.mk include src/main/iidx-bio2-exit-hook/Module.mk include src/main/iidx-ezusb-exit-hook/Module.mk include src/main/iidx-ezusb2-exit-hook/Module.mk @@ -172,6 +179,7 @@ include src/main/jbhook3/Module.mk include src/main/launcher/Module.mk include src/main/mempatch-hook/Module.mk include src/main/mm/Module.mk +include src/main/module/Module.mk include src/main/p3io/Module.mk include src/main/p3iodrv/Module.mk include src/main/p3ioemu/Module.mk @@ -181,7 +189,9 @@ include src/main/p4ioemu/Module.mk include src/main/popnhook-util/Module.mk include src/main/popnhook1/Module.mk include src/main/popnio/Module.mk +include src/main/procmon/Module.mk include src/main/pcbidgen/Module.mk +include src/main/sdk-hook/Module.mk include src/main/sdvxhook/Module.mk include src/main/sdvxhook2-cn/Module.mk include src/main/sdvxhook2/Module.mk @@ -197,10 +207,7 @@ include src/main/vigem-sdvxio/Module.mk include src/main/vigem-ddrio/Module.mk include src/main/vigemstub/Module.mk -include src/test/cconfig/Module.mk include src/test/d3d9hook/Module.mk -include src/test/iidxhook-util/Module.mk -include src/test/iidxhook8/Module.mk include src/test/security/Module.mk include src/test/test/Module.mk include src/test/util/Module.mk @@ -232,6 +239,7 @@ $(zipdir)/tools.zip: \ build/bin/indep-32/ezusb2-dbg-hook.dll \ build/bin/indep-32/ezusb2-tool.exe \ build/bin/indep-32/ezusb-tool.exe \ + build/bin/indep-32/procmon.dll \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -246,6 +254,7 @@ $(zipdir)/tools-x64.zip: \ build/bin/indep-64/iidx-ezusb2-exit-hook.dll \ build/bin/indep-64/jbiotest.exe \ build/bin/indep-64/mempatch-hook.dll \ + build/bin/indep-64/procmon.dll \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -258,15 +267,17 @@ $(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 \ dist/iidx/gamestart-11.bat \ dist/iidx/gamestart-12.bat \ - dist/iidx/iidxhook-09.conf \ - dist/iidx/iidxhook-10.conf \ - dist/iidx/iidxhook-11.conf \ - dist/iidx/iidxhook-12.conf \ + dist/iidx/inject-09.xml \ + dist/iidx/inject-10.xml \ + dist/iidx/inject-11.xml \ + dist/iidx/inject-12.xml \ + dist/iidx/inject-09.xml \ dist/iidx/vefx.txt \ build/bin/indep-32/iidx-irbeat-patch.exe \ dist/iidx/iidx-irbeat-patch-09.bat \ @@ -283,9 +294,10 @@ $(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 \ + dist/iidx/inject-13.xml \ dist/iidx/vefx.txt \ | $(zipdir)/ $(V)echo ... $@ @@ -299,15 +311,16 @@ $(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 \ dist/iidx/gamestart-16.bat \ dist/iidx/gamestart-17.bat \ - dist/iidx/iidxhook-14.conf \ - dist/iidx/iidxhook-15.conf \ - dist/iidx/iidxhook-16.conf \ - dist/iidx/iidxhook-17.conf \ + dist/iidx/inject-14.xml \ + dist/iidx/inject-15.xml \ + dist/iidx/inject-16.xml \ + dist/iidx/inject-17.xml \ dist/iidx/vefx.txt \ | $(zipdir)/ $(V)echo ... $@ @@ -323,7 +336,10 @@ $(zipdir)/iidx-18.zip: \ build/bin/indep-32/vefxio.dll \ 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 ... $@ @@ -338,7 +354,7 @@ $(zipdir)/iidx-18-cn.zip: \ build/bin/indep-32/inject.exe \ dist/iidx/config.bat \ dist/iidx/gamestart-18-cn.bat \ - dist/iidx/iidxhook-18-cn.conf \ + dist/iidx/inject-18-cn.xml \ dist/iidx/vefx.txt \ | $(zipdir)/ $(V)echo ... $@ @@ -354,7 +370,10 @@ $(zipdir)/iidx-19.zip: \ build/bin/indep-32/vefxio.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 ... $@ @@ -370,7 +389,10 @@ $(zipdir)/iidx-20.zip: \ build/bin/indep-32/vefxio.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 ... $@ @@ -385,7 +407,7 @@ $(zipdir)/iidx-20-cn.zip: \ build/bin/indep-32/inject.exe \ dist/iidx/config.bat \ dist/iidx/gamestart-20-cn.bat \ - dist/iidx/iidxhook-20-cn.conf \ + dist/iidx/inject-20-cn.xml \ dist/iidx/vefx.txt \ | $(zipdir)/ $(V)echo ... $@ @@ -404,10 +426,13 @@ $(zipdir)/iidx-21-to-24.zip: \ dist/iidx/gamestart-22.bat \ dist/iidx/gamestart-23.bat \ dist/iidx/gamestart-24.bat \ - dist/iidx/iidxhook-21.conf \ - 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 ... $@ @@ -424,8 +449,11 @@ $(zipdir)/iidx-25-to-26.zip: \ 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 ... $@ @@ -444,37 +472,42 @@ $(zipdir)/iidx-27-to-30.zip: \ dist/iidx/gamestart-28.bat \ dist/iidx/gamestart-29.bat \ dist/iidx/gamestart-30.bat \ - dist/iidx/iidxhook-27.conf \ - 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 ... $@ $(V)zip -j $@ $^ $(zipdir)/iidx-hwio-x86.zip: \ - build/bin/indep-32/aciomgr.dll \ + build/bin/indep-32/acio-mgr.dll \ build/bin/indep-32/eamio-icca.dll \ build/bin/indep-32/iidxio-bio2.dll \ build/bin/indep-32/iidxio-ezusb.dll \ build/bin/indep-32/iidxio-ezusb2.dll \ - dist/iidx/iidxio-bio2.conf \ build/bin/indep-32/vigem-iidxio.exe \ - dist/iidx/vigem-iidxio.conf \ + dist/iidx/eamio-icca.xml \ + dist/iidx/iidxio-bio2.xml \ + dist/iidx/vigem-iidxio.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ $(zipdir)/iidx-hwio-x64.zip: \ - build/bin/indep-64/aciomgr.dll \ + build/bin/indep-64/acio-mgr.dll \ build/bin/indep-64/eamio-icca.dll \ build/bin/indep-64/iidxio-bio2.dll \ build/bin/indep-64/iidxio-ezusb.dll \ build/bin/indep-64/iidxio-ezusb2.dll \ - dist/iidx/iidxio-bio2.conf \ build/bin/indep-64/vigem-iidxio.exe \ - dist/iidx/vigem-iidxio.conf \ + dist/iidx/eamio-icca.xml \ + dist/iidx/iidxio-bio2.xml \ + dist/iidx/vigem-iidxio.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -486,9 +519,10 @@ $(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 \ + dist/jb/inject-01.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -500,9 +534,10 @@ $(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 \ + dist/jb/inject-02.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -516,6 +551,10 @@ $(zipdir)/jb-03.zip: \ build/bin/indep-32/jbio.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 $@ $^ @@ -529,6 +568,10 @@ $(zipdir)/jb-04.zip: \ build/bin/indep-32/jbio.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 $@ $^ @@ -542,6 +585,10 @@ $(zipdir)/jb-05-to-07.zip: \ build/bin/indep-32/jbio.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 $@ $^ @@ -555,17 +602,21 @@ $(zipdir)/jb-08.zip: \ build/bin/indep-32/jbio.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 $@ $^ $(zipdir)/jb-hwio.zip: \ - build/bin/indep-32/aciomgr.dll \ + build/bin/indep-32/acio-mgr.dll \ build/bin/indep-32/eamio-icca.dll \ build/bin/indep-32/jbio-magicbox.dll \ build/bin/indep-32/jbio-p4io.dll \ - dist/jb/jbio-h44b.conf \ - dist/jb/eamio-icc.conf \ + dist/jb/jbio-h44b.xml \ + dist/jb/eamio-icca.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -579,6 +630,10 @@ $(zipdir)/sdvx-01-to-04.zip: \ build/bin/indep-32/sdvxio.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 $@ $^ @@ -592,7 +647,10 @@ $(zipdir)/sdvx-05-to-06.zip: \ build/bin/indep-64/sdvxio.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 $@ $^ @@ -606,27 +664,38 @@ $(zipdir)/sdvx-05-cn.zip: \ build/bin/indep-64/sdvxio.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 $@ $^ $(zipdir)/sdvx-hwio-x86.zip: \ - build/bin/indep-32/aciomgr.dll \ + build/bin/indep-32/acio-mgr.dll \ build/bin/indep-32/eamio-icca.dll \ build/bin/indep-32/sdvxio-kfca.dll \ build/bin/indep-32/sdvxio-bio2.dll \ build/bin/indep-32/vigem-sdvxio.exe \ + dist/sdvx/eamio-icca.xml \ + dist/sdvx/sdvxio-bio2.xml \ + dist/sdvx/sdvxio-kfca.xml \ + dist/sdvx/vigem-sdvxio.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ $(zipdir)/sdvx-hwio-x64.zip: \ - build/bin/indep-64/aciomgr.dll \ + build/bin/indep-64/acio-mgr.dll \ build/bin/indep-64/eamio-icca.dll \ build/bin/indep-64/sdvxio-kfca.dll \ build/bin/indep-64/sdvxio-bio2.dll \ build/bin/indep-64/vigem-sdvxio.exe \ + dist/sdvx/eamio-icca.xml \ + dist/sdvx/sdvxio-bio2.xml \ + dist/sdvx/sdvxio-kfca.xml \ + dist/sdvx/vigem-sdvxio.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -660,6 +729,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 \ @@ -681,6 +751,10 @@ $(zipdir)/ddr-12.zip: \ build/bin/indep-32/geninput.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 $@ $^ @@ -697,6 +771,10 @@ $(zipdir)/ddr-13.zip: \ build/bin/indep-32/geninput.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 $@ $^ @@ -717,6 +795,14 @@ $(zipdir)/ddr-14-to-18.zip: \ 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 $@ $^ @@ -735,6 +821,12 @@ $(zipdir)/ddr-16-to-18-x64.zip: \ 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 $@ $^ @@ -747,6 +839,7 @@ $(zipdir)/ddr-hwio-x86.zip: \ build/bin/indep-32/extiotest.exe \ build/bin/indep-32/p3io-ddr-tool.exe \ build/bin/indep-32/vigem-ddrio.exe \ + dist/ddr/vigem-ddrio.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -759,6 +852,7 @@ $(zipdir)/ddr-hwio-x64.zip: \ build/bin/indep-64/extiotest.exe \ build/bin/indep-64/p3io-ddr-tool.exe \ build/bin/indep-64/vigem-ddrio.exe \ + dist/ddr/vigem-ddrio.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -773,6 +867,11 @@ $(zipdir)/bst.zip: \ 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 $@ $^ @@ -785,15 +884,16 @@ $(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 \ dist/popn/gamestart-17.bat \ dist/popn/gamestart-18.bat \ - dist/popn/popnhook-15.conf \ - dist/popn/popnhook-16.conf \ - dist/popn/popnhook-17.conf \ - dist/popn/popnhook-18.conf \ + dist/popn/inject-15.xml \ + dist/popn/inject-16.xml \ + dist/popn/inject-17.xml \ + dist/popn/inject-18.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -807,15 +907,9 @@ $(zipdir)/doc.zip: \ $(BUILDDIR)/tests.zip: \ build/bin/indep-32/iidxhook1.dll \ build/bin/avs2_0-32/iidxhook2.dll \ - build/bin/indep-32/cconfig-test.exe \ - build/bin/indep-32/cconfig-util-test.exe \ - build/bin/indep-32/cconfig-cmd-test.exe \ build/bin/indep-32/d3d9hook.dll \ build/bin/indep-32/d3d9hook-test.exe \ - build/bin/indep-32/iidxhook-util-config-eamuse-test.exe \ - 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 \ @@ -824,7 +918,6 @@ $(BUILDDIR)/tests.zip: \ build/bin/indep-32/security-rp3-test.exe \ build/bin/indep-32/security-util-test.exe \ build/bin/indep-32/util-net-test.exe \ - build/bin/indep-64/iidxhook8-config-cam-test.exe \ dist/test/run-tests.sh \ | $(zipdir)/ $(V)echo ... $@ diff --git a/README.md b/README.md index 6827f954..0b5db644 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ -# Bemanitools 5 +# Bemanitools 6 -Version: `5.49` +**THIS IS A HIGHLY WORK/DEVELOPMENT IN PROGRESS VERSION** + +**THINGS ARE BROKEN AND EVERYTHING IS SUBJECT TO CHANGE** + +**ALL DOCUMENTATION IS CONSIDERED OUTDATED AND IS NOT NECESSARILY REVISED UNTIL FURTHER NOTICE** + +Version: `6.0.0-alpha.4` [Changelog](CHANGELOG.md) @@ -148,21 +154,36 @@ helpful or important to know and should be added. ### Setup and dependencies -Most (older generation) games were developed for Windows XP Embedded but should run fine on any -consumer version of Windows XP. Newer versions of Windows, e.g. Windows 7, 8 and 10, should be fine -as well. Some hooks also include fixes required to run the games on a more recent version. +The games bemanitools support span several generations of (embedded) Windows versions: XP, 7 and 10 +(IoT). With these come different generations of dependencies as requirements. + +Simplified, this boils down to the following list of C++ Redistributable (vcredist) packages that +are recommended to be installed without going into detail which game needs exactly which version. +Keep in mind the "bitness" (32-bit vs. 64-bit) of each specific game and download the right ones +accordingly. + +You can use a tool like [dependencywalker](https://www.dependencywalker.com/) to figure that out if +it is relevant to you. + +Links/files are also provided by +[bemanitools-supplement](https://github.com/djhackersdev/bemanitools-supplement/tree/master/misc/win-runtime#windows-runtimes-and-libraries) + +#### Visual C++ Redistributable Packages -Depending on the game, you also need the following dependencies installed: +- 2010 + - [32-bit (x86)](http://download.microsoft.com/download/5/B/C/5BC5DBB3-652D-4DCE-B14A-475AB85EEF6E/vcredist_x86.exe) + - [64-bit (x64)](http://download.microsoft.com/download/d/2/4/d242c3fb-da5a-4542-ad66-f9661d0a8d19/vcredist_x64.exe) +- 2013 + - [32-bit (x86)](http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe) + - [64-bit (x64)](http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe) +- 2015 + - [32-bit (x86)](https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe) + - [64-bit (x64)](https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe) -- The 32-bit (x86) version of - [Microsoft Visual C++ 2010 Service Pack 1 Redistributable Package MFC Security Update](https://www.microsoft.com/en-sg/download/details.aspx?id=26999) -- The 32-bit (x86) and 64-bit (x64) versions of - [Microsoft Visual C++ Redistributable Packages for Visual Studio 2013](https://www.microsoft.com/en-sg/download/details.aspx?id=40784) -- The - [DirectX 9 End-User Runtimes (June 2010)](https://www.microsoft.com/en-us/download/details.aspx?id=8109) +#### DirectX 9 -See also [bemanitools-supplement](https://www.github.com/djhackersdev/bemanitools-supplement/) for -files. +Most/nearly all games support to this day use the DirectX 9(ex) API. Make sure to install the +[DirectX 9 End-User Runtimes (June 2010)](https://www.microsoft.com/en-us/download/details.aspx?id=8109) ## Development diff --git a/btsdk/example/hook-example/hook.c b/btsdk/example/hook-example/hook.c new file mode 100644 index 00000000..9a1dc1cc --- /dev/null +++ b/btsdk/example/hook-example/hook.c @@ -0,0 +1,42 @@ +#define LOG_MODULE "btsdk-hook-example" + +#include + +#include +#include + +#include "btapi/hook-core.h" +#include "btapi/hook-main.h" + +#include "core/log.h" +#include "core/thread.h" + +void btapi_hook_core_thread_impl_set( + btapi_thread_create_t create, + btapi_thread_join_t join, + btapi_thread_destroy_t destroy) +{ + core_thread_impl_set(create, join, destroy); +} + +void btapi_hook_core_log_impl_set( + btapi_log_formatter_t misc, + btapi_log_formatter_t info, + btapi_log_formatter_t warning, + btapi_log_formatter_t fatal) +{ + core_log_impl_set(misc, info, warning, fatal); +} + +bool btapi_hook_main_init( + HMODULE game_module, struct property_node *property_node_config) +{ + log_info("btapi_hook_main_init"); + + return true; +} + +void btapi_hook_main_fini() +{ + log_info("btapi_hook_main_fini"); +} \ No newline at end of file diff --git a/btsdk/example/hook/config.c b/btsdk/example/hook/config.c new file mode 100644 index 00000000..e69de29b diff --git a/btsdk/example/hook/dllmain copy.c b/btsdk/example/hook/dllmain copy.c new file mode 100644 index 00000000..431306b5 --- /dev/null +++ b/btsdk/example/hook/dllmain copy.c @@ -0,0 +1,74 @@ +#define LOG_MODULE "procmon-dllmain" + +#include + +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/thread-crt-ext.h" +#include "launcher/property-util.h" + +#include "procmon/config.h" +#include "procmon/procmon.h" + +#include "util/fs.h" + +// TODO move this to a separate "standalone dllmain bootstrap" module in sdk + +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ + struct property *property; + struct property_node *root_node; + struct procmon_config config; + + // TODO provide compatibility mode here? ctx set to...something? + // to figure out if this is loaded/run by any bemanitools loader + // or not. + + if (reason == DLL_PROCESS_ATTACH) { + core_thread_crt_ext_impl_set(); + core_log_bt_ext_init_with_stderr(); + + // TODO make this somehow configurable? + // have additional stuff on procmon configuration xml + // + // + // have the same log stuff here as with launcher like file, level, rotation etc + // + // + // .... + // + // + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_INFO); + + log_info("DLL_PROCESS_ATTACH"); + + if (path_exists("procmon-config.xml")) { + property = property_util_load("procmon-config.xml"); + + root_node = property_search(NULL, "hook/procmon"); + + if (!root_node) { + // TODO error handling + } + + procmon_config_init(&config); + procmon_config_load(root_node, &config); + + procmon_init(&config); + } else { + log_warning("No configuration file found, defaulting"); + + procmon_config_init(&config); + + procmon_init(&config); + } + + } else if (reason == DLL_PROCESS_DETACH) { + log_info("DLL_PROCESS_DETACH"); + + procmon_fini(); + core_log_bt_fini(); + } + + return TRUE; +} diff --git a/btsdk/example/hook/dllmain-bootstrap.c b/btsdk/example/hook/dllmain-bootstrap.c new file mode 100644 index 00000000..f6200c31 --- /dev/null +++ b/btsdk/example/hook/dllmain-bootstrap.c @@ -0,0 +1,15 @@ + + +void btsdk_dllmain_bootstrap_process_attach() +{ + // TODO have the whole stuff to bootstrap independently of hook API + // with logging setup etc. + // provide stuff via recovering from command line args or env vars? +} + +void btsdk_dllmain_bootstrap_process_detach() +{ + // TODO cleanup + + core_log_bt_fini(); +} \ No newline at end of file diff --git a/btsdk/example/hook/dllmain-bootstrap.h b/btsdk/example/hook/dllmain-bootstrap.h new file mode 100644 index 00000000..8b602488 --- /dev/null +++ b/btsdk/example/hook/dllmain-bootstrap.h @@ -0,0 +1,12 @@ +#ifndef DLLMAIN_BOOTSTRAP_H +#define DLLMAIN_BOOTSTRAP_H + +#include + +#include "imports/avs.h" + +void btsdk_dllmain_bootstrap_process_attach(); + +void btsdk_dllmain_bootstrap_process_detach(); + +#endif \ No newline at end of file diff --git a/btsdk/example/hook/log.c b/btsdk/example/hook/log.c new file mode 100644 index 00000000..e69de29b diff --git a/btsdk/example/hook/thread.c b/btsdk/example/hook/thread.c new file mode 100644 index 00000000..ff58f4df --- /dev/null +++ b/btsdk/example/hook/thread.c @@ -0,0 +1,21 @@ + + +void btapi_thread_impl_set() +{ + +} + +int btapi_thread_create(int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority) +{ + +} + +void btapi_thread_join(int thread_id, int *result) +{ + +} + +void btapi_thread_destroy(int thread_id) +{ + +} \ No newline at end of file diff --git a/btsdk/example/hook/thread.h b/btsdk/example/hook/thread.h new file mode 100644 index 00000000..9e77e3c9 --- /dev/null +++ b/btsdk/example/hook/thread.h @@ -0,0 +1,3 @@ + + +void btapi_thread_impl_set(); \ No newline at end of file diff --git a/btsdk/hook-btapi/dllmain.c b/btsdk/hook-btapi/dllmain.c new file mode 100644 index 00000000..e69de29b diff --git a/btsdk/hook-btapi/hook.c b/btsdk/hook-btapi/hook.c new file mode 100644 index 00000000..0848499e --- /dev/null +++ b/btsdk/hook-btapi/hook.c @@ -0,0 +1,30 @@ +#include "api/hook.h" + +void btapi_hook_thread_impl_set( + btapi_thread_create_t create, + btapi_thread_join_t join, + btapi_thread_destroy_t destroy) +{ + // TODO some simple example how to use basic functionality of the API +} + +void btapi_hook_log_impl_set( + btapi_log_formatter_t misc, + btapi_log_formatter_t info, + btapi_log_formatter_t warning, + btapi_log_formatter_t fatal) +{ + // TODO some simple example how to use basic functionality of the API +} + +bool btapi_hook_init(struct property_node *config) +{ + // TODO some simple example how to use basic functionality of the API + + return true; +} + +void btapi_hook_fini() +{ + // TODO some simple example how to use basic functionality of the API +} \ No newline at end of file diff --git a/btsdk/hook-simple/dllmain.c b/btsdk/hook-simple/dllmain.c new file mode 100644 index 00000000..069d231c --- /dev/null +++ b/btsdk/hook-simple/dllmain.c @@ -0,0 +1,2 @@ +// TODO simple hook example with DllMain only +// ignoring the BT5 API \ No newline at end of file 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/eamio-icca.xml b/dist/ddr/eamio-icca.xml new file mode 100644 index 00000000..d89bf432 --- /dev/null +++ b/dist/ddr/eamio-icca.xml @@ -0,0 +1,5 @@ + + + COM1 + 57600 + \ 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 index d108118b..89c15da0 100644 --- a/dist/ddr/gamestart-17.bat +++ b/dist/ddr/gamestart-17.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 diff --git a/dist/ddr/gamestart-18.bat b/dist/ddr/gamestart-18.bat index d108118b..d73ddf34 100644 --- a/dist/ddr/gamestart-18.bat +++ b/dist/ddr/gamestart-18.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-18.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 diff --git a/dist/ddr/launcher-12.xml b/dist/ddr/launcher-12.xml new file mode 100644 index 00000000..7aa1a477 --- /dev/null +++ b/dist/ddr/launcher-12.xml @@ -0,0 +1,71 @@ + + + + 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..7aa1a477 --- /dev/null +++ b/dist/ddr/launcher-13.xml @@ -0,0 +1,71 @@ + + + + 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..b6ab267e --- /dev/null +++ b/dist/ddr/launcher-14.xml @@ -0,0 +1,71 @@ + + + + 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..b6ab267e --- /dev/null +++ b/dist/ddr/launcher-15.xml @@ -0,0 +1,71 @@ + + + + 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..36c84569 --- /dev/null +++ b/dist/ddr/launcher-16.xml @@ -0,0 +1,72 @@ + + + + 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..36c84569 --- /dev/null +++ b/dist/ddr/launcher-17.xml @@ -0,0 +1,72 @@ + + + + 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..36c84569 --- /dev/null +++ b/dist/ddr/launcher-18.xml @@ -0,0 +1,72 @@ + + + + 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/vigem-ddrio.xml b/dist/ddr/vigem-ddrio.xml new file mode 100644 index 00000000..6d22ae8a --- /dev/null +++ b/dist/ddr/vigem-ddrio.xml @@ -0,0 +1,4 @@ + + + 1 + \ 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..03c83200 --- /dev/null +++ b/dist/dwarfstack/readme.md @@ -0,0 +1 @@ +Version/release: https://github.com/ssbssa/dwarfstack/releases/tag/2.2 diff --git a/dist/iidx/eamio-icca.xml b/dist/iidx/eamio-icca.xml new file mode 100644 index 00000000..d89bf432 --- /dev/null +++ b/dist/iidx/eamio-icca.xml @@ -0,0 +1,5 @@ + + + COM1 + 57600 + \ No newline at end of file diff --git a/dist/iidx/gamestart-09.bat b/dist/iidx/gamestart-09.bat index 0913f2f6..de3dc1ad 100755 --- a/dist/iidx/gamestart-09.bat +++ b/dist/iidx/gamestart-09.bat @@ -1,6 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 -inject iidxhook1.dll bm2dx.exe -D --config iidxhook-09.conf %* +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\JAG + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-09.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-10.bat b/dist/iidx/gamestart-10.bat index 37736ae3..f6f6b719 100755 --- a/dist/iidx/gamestart-10.bat +++ b/dist/iidx/gamestart-10.bat @@ -1,6 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 -inject iidxhook1.dll bm2dx.exe -D --config iidxhook-10.conf %* +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\JAE + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-10.xml^ + %* diff --git a/dist/iidx/gamestart-11.bat b/dist/iidx/gamestart-11.bat index a4516f74..15b6f1ed 100755 --- a/dist/iidx/gamestart-11.bat +++ b/dist/iidx/gamestart-11.bat @@ -1,6 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 -inject iidxhook1.dll bm2dx.exe -D --config iidxhook-11.conf %* +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\JAA + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-11.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-12.bat b/dist/iidx/gamestart-12.bat index 91be7f37..450641e3 100755 --- a/dist/iidx/gamestart-12.bat +++ b/dist/iidx/gamestart-12.bat @@ -1,5 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 -inject iidxhook1.dll bm2dx.exe -D --config iidxhook-12.conf %* +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\JAD + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-12.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-13.bat b/dist/iidx/gamestart-13.bat index 199fc5ad..77e17c45 100755 --- a/dist/iidx/gamestart-13.bat +++ b/dist/iidx/gamestart-13.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\JAG + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist d mkdir d if not exist e mkdir e if not exist f mkdir f @@ -11,5 +53,6 @@ if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW -inject iidxhook2.dll bm2dx.exe -D --config iidxhook-13.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-13.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-14.bat b/dist/iidx/gamestart-14.bat index 387ef669..ffd91e4e 100755 --- a/dist/iidx/gamestart-14.bat +++ b/dist/iidx/gamestart-14.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\2007072301 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist d mkdir d if not exist e mkdir e if not exist f mkdir f @@ -11,5 +53,6 @@ if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW -inject iidxhook3.dll bm2dx.exe -D --config iidxhook-14.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-14.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-15.bat b/dist/iidx/gamestart-15.bat index 7bac4ec6..9d2ca204 100755 --- a/dist/iidx/gamestart-15.bat +++ b/dist/iidx/gamestart-15.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\2008031100 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist d mkdir d if not exist e mkdir e if not exist f mkdir f @@ -11,5 +53,6 @@ if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW -inject iidxhook3.dll bm2dx.exe -D --config iidxhook-15.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-15.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-16.bat b/dist/iidx/gamestart-16.bat index 9df8f277..658970ba 100755 --- a/dist/iidx/gamestart-16.bat +++ b/dist/iidx/gamestart-16.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\2009072200 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist d mkdir d if not exist e mkdir e if not exist f mkdir f @@ -9,7 +51,8 @@ if not exist f mkdir f if not exist e\avs_conf mkdir e\avs_conf if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM -if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW - -inject iidxhook3.dll bm2dx.exe -D --config iidxhook-16.conf %* +if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-16.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-17.bat b/dist/iidx/gamestart-17.bat index 027dbfd7..52caa228 100755 --- a/dist/iidx/gamestart-17.bat +++ b/dist/iidx/gamestart-17.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\2010071200 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist d mkdir d if not exist e mkdir e if not exist f mkdir f @@ -11,5 +53,6 @@ if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW -inject iidxhook3.dll bm2dx.exe -D --config iidxhook-17.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-17.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-18-cn.bat b/dist/iidx/gamestart-18-cn.bat index 53d9822f..e9b56129 100644 --- a/dist/iidx/gamestart-18-cn.bat +++ b/dist/iidx/gamestart-18-cn.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR% + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist d mkdir d if not exist e mkdir e if not exist f mkdir f @@ -14,4 +56,6 @@ if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW if not exist dev\nvram mkdir dev\nvram if not exist dev\raw mkdir dev\raw -inject iidxhook4-cn.dll bm2dx.exe -D --config iidxhook-18-cn.conf %* +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-18-cn.xml^ + %* diff --git a/dist/iidx/gamestart-18.bat b/dist/iidx/gamestart-18.bat index cce99b03..f31449e7 100755 --- a/dist/iidx/gamestart-18.bat +++ b/dist/iidx/gamestart-18.bat @@ -1,14 +1,51 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%BEMANITOOLS_DIR%;^ +%MODULES_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 root/content directory of the game +cd /d %CONTENT_DIR% -launcher -K iidxhook4.dll bm2dx.dll --config iidxhook-18.conf %* +%BEMANITOOLS_DIR%\launcher.exe^ + %BEMANITOOLS_DIR%\launcher-18.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-19.bat b/dist/iidx/gamestart-19.bat index 8bfd5803..bb78b20d 100755 --- a/dist/iidx/gamestart-19.bat +++ b/dist/iidx/gamestart-19.bat @@ -1,14 +1,51 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-19.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-20-cn.bat b/dist/iidx/gamestart-20-cn.bat index c54d056e..6ef1b40b 100644 --- a/dist/iidx/gamestart-20-cn.bat +++ b/dist/iidx/gamestart-20-cn.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR% + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist d mkdir d if not exist e mkdir e if not exist f mkdir f @@ -14,4 +56,6 @@ if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW if not exist dev\nvram mkdir dev\nvram if not exist dev\raw mkdir dev\raw -inject iidxhook5-cn.dll bm2dx.exe -D --config iidxhook-20-cn.conf %* +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-20-cn.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-20.bat b/dist/iidx/gamestart-20.bat index 2dac80ea..0be08223 100755 --- a/dist/iidx/gamestart-20.bat +++ b/dist/iidx/gamestart-20.bat @@ -1,10 +1,51 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-20.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-21.bat b/dist/iidx/gamestart-21.bat index b79d6416..05bad2da 100755 --- a/dist/iidx/gamestart-21.bat +++ b/dist/iidx/gamestart-21.bat @@ -1,10 +1,51 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-21.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-22.bat b/dist/iidx/gamestart-22.bat index d10a945a..2ebb529d 100755 --- a/dist/iidx/gamestart-22.bat +++ b/dist/iidx/gamestart-22.bat @@ -1,10 +1,51 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-22.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-23.bat b/dist/iidx/gamestart-23.bat index 656e1fe2..06821d97 100755 --- a/dist/iidx/gamestart-23.bat +++ b/dist/iidx/gamestart-23.bat @@ -1,10 +1,51 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-23.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-24.bat b/dist/iidx/gamestart-24.bat index 283020c4..2e236952 100755 --- a/dist/iidx/gamestart-24.bat +++ b/dist/iidx/gamestart-24.bat @@ -1,10 +1,51 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-24.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-25.bat b/dist/iidx/gamestart-25.bat index edff2940..a4674794 100644 --- a/dist/iidx/gamestart-25.bat +++ b/dist/iidx/gamestart-25.bat @@ -1,16 +1,51 @@ @echo off + +:: Keep all vars scoped to this script +setlocal + +:: 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 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 +:: 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 -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -launcher -H 134217728 -K iidxhook8.dll bm2dx.dll --config iidxhook-25.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-25.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-26.bat b/dist/iidx/gamestart-26.bat index d41b72b3..508a8ecb 100644 --- a/dist/iidx/gamestart-26.bat +++ b/dist/iidx/gamestart-26.bat @@ -1,16 +1,51 @@ @echo off + +:: Keep all vars scoped to this script +setlocal + +:: 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 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 +:: 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 -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -launcher -H 134217728 -K iidxhook8.dll bm2dx.dll --config iidxhook-26.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-26.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-27.bat b/dist/iidx/gamestart-27.bat index 04a39091..bb0865ae 100644 --- a/dist/iidx/gamestart-27.bat +++ b/dist/iidx/gamestart-27.bat @@ -1,16 +1,51 @@ @echo off + +:: Keep all vars scoped to this script +setlocal + +:: 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 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 +:: 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 -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-27.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-27.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-28.bat b/dist/iidx/gamestart-28.bat index 1abb520d..78614ee7 100644 --- a/dist/iidx/gamestart-28.bat +++ b/dist/iidx/gamestart-28.bat @@ -1,16 +1,51 @@ @echo off + +:: Keep all vars scoped to this script +setlocal + +:: 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 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 +:: 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 -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-28.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-28.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-29.bat b/dist/iidx/gamestart-29.bat index 1029b8c5..fac21578 100644 --- a/dist/iidx/gamestart-29.bat +++ b/dist/iidx/gamestart-29.bat @@ -1,16 +1,51 @@ @echo off + +:: Keep all vars scoped to this script +setlocal + +:: 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 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 +:: 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 -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-29.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-29.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/gamestart-30.bat b/dist/iidx/gamestart-30.bat index 776d7e84..21916bb8 100644 --- a/dist/iidx/gamestart-30.bat +++ b/dist/iidx/gamestart-30.bat @@ -1,16 +1,51 @@ @echo off + +:: Keep all vars scoped to this script +setlocal + +:: 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 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 +:: 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 -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -modules\launcher -H 134217728 -B iidxhook9.dll bm2dx.dll --config iidxhook-30.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-30.xml^ + %* \ No newline at end of file diff --git a/dist/iidx/iidxhook-09.conf b/dist/iidx/iidxhook-09.conf deleted file mode 100755 index 077e3d2c..00000000 --- a/dist/iidx/iidxhook-09.conf +++ /dev/null @@ -1,71 +0,0 @@ -# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) -eamuse.card_type=C02 - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Enable monitoring of ezusb.dll calls by logging call traces. Only works on 9th and 10th style! -ezusb.api_call_monitoring=false - -# Set the type of ezusb IO board. 0 = C02, 1 = D01. Note: Impacts security settings! -ezusb.io_board_type=0 - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Stub calls to rteffect.dll (10th to DistorteD) -misc.rteffect_stub=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security boot version (e.g. GEC02). -sec.boot_version=GEC02 - -# Security boot seeds for ezusb, format: X:X:X where X is a number of 0-9 (e.g. 0:0:0). -sec.boot_seeds=0:0:0 - -# Security black plug mcode id string (e.g. GEC02JAA). -sec.black_plug_mcode=GEC02JAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-10.conf b/dist/iidx/iidxhook-10.conf deleted file mode 100755 index a9874eaa..00000000 --- a/dist/iidx/iidxhook-10.conf +++ /dev/null @@ -1,71 +0,0 @@ -# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) -eamuse.card_type=D01 - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Enable monitoring of ezusb.dll calls by logging call traces. Only works on 9th and 10th style! -ezusb.api_call_monitoring=false - -# Set the type of ezusb IO board. 0 = C02, 1 = D01. Note: Impacts security settings! -ezusb.io_board_type=1 - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Stub calls to rteffect.dll (10th to DistorteD) -misc.rteffect_stub=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security boot version (e.g. GEC02). -sec.boot_version=GEC02 - -# Security boot seeds for ezusb, format: X:X:X where X is a number of 0-9 (e.g. 0:0:0). -sec.boot_seeds=0:1:1 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQD01JAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-11.conf b/dist/iidx/iidxhook-11.conf deleted file mode 100755 index e1dc01e6..00000000 --- a/dist/iidx/iidxhook-11.conf +++ /dev/null @@ -1,71 +0,0 @@ -# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) -eamuse.card_type=E11 - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Enable monitoring of ezusb.dll calls by logging call traces. Only works on 9th and 10th style! -ezusb.api_call_monitoring=false - -# Set the type of ezusb IO board. 0 = C02, 1 = D01. Note: Impacts security settings! -ezusb.io_board_type=1 - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Stub calls to rteffect.dll (10th to DistorteD) -misc.rteffect_stub=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security boot version (e.g. GEC02). -sec.boot_version=GEC02 - -# Security boot seeds for ezusb, format: X:X:X where X is a number of 0-9 (e.g. 0:0:0). -sec.boot_seeds=0:2:2 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQE11JAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-12.conf b/dist/iidx/iidxhook-12.conf deleted file mode 100755 index a3518e3a..00000000 --- a/dist/iidx/iidxhook-12.conf +++ /dev/null @@ -1,74 +0,0 @@ -# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) -eamuse.card_type=ECO - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Enable monitoring of ezusb.dll calls by logging call traces. Only works on 9th and 10th style! -ezusb.api_call_monitoring=false - -# Set the type of ezusb IO board. 0 = C02, 1 = D01. Note: Impacts security settings! -ezusb.io_board_type=1 - -# Fix broken 3D background on Happy Sky's music select (if appearing completely white) -misc.happy_sky_ms_bg_fix=false - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Stub calls to rteffect.dll (10th to DistorteD) -misc.rteffect_stub=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security boot version (e.g. GEC02). -sec.boot_version=GEC02 - -# Security boot seeds for ezusb, format: X:X:X where X is a number of 0-9 (e.g. 0:0:0). -sec.boot_seeds=0:3:3 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQECOJAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-13.conf b/dist/iidx/iidxhook-13.conf deleted file mode 100755 index 1f8525f6..00000000 --- a/dist/iidx/iidxhook-13.conf +++ /dev/null @@ -1,74 +0,0 @@ -# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) -eamuse.card_type=C02 - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Enable monitoring of ezusb.dll calls by logging call traces. Only works on 9th and 10th style! -ezusb.api_call_monitoring=false - -# Set the type of ezusb IO board. 0 = C02, 1 = D01. Note: Impacts security settings! -ezusb.io_board_type=1 - -# Fix broken 3D background on DistorteD's music select (if appearing completely black) -misc.distorted_ms_bg_fix=false - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Stub calls to rteffect.dll (10th to DistorteD) -misc.rteffect_stub=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security boot version (e.g. GEC02). -sec.boot_version=GEC02 - -# Security boot seeds for ezusb, format: X:X:X where X is a number of 0-9 (e.g. 0:0:0). -sec.boot_seeds=0:4:4 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQFDDJAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-14.conf b/dist/iidx/iidxhook-14.conf deleted file mode 100755 index 935d75dc..00000000 --- a/dist/iidx/iidxhook-14.conf +++ /dev/null @@ -1,53 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQGLDJAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-15.conf b/dist/iidx/iidxhook-15.conf deleted file mode 100755 index b41ebaff..00000000 --- a/dist/iidx/iidxhook-15.conf +++ /dev/null @@ -1,53 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQHDDJAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-16.conf b/dist/iidx/iidxhook-16.conf deleted file mode 100755 index 1051ea7e..00000000 --- a/dist/iidx/iidxhook-16.conf +++ /dev/null @@ -1,56 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQI00JAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-17.conf b/dist/iidx/iidxhook-17.conf deleted file mode 100755 index 06f25d92..00000000 --- a/dist/iidx/iidxhook-17.conf +++ /dev/null @@ -1,56 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Fix stretched BG videos on newer GPUs. Might appear on SIRIUS and older. On 9th and 10th style this issue may only affect older BGAs (from 1st-3rd style) -gfx.bgvideo_uv_fix=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable operator clock setting system clock time -misc.disable_clock_set=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GCJDJJAA \ No newline at end of file diff --git a/dist/iidx/iidxhook-18-cn.conf b/dist/iidx/iidxhook-18-cn.conf deleted file mode 100644 index 10bb8022..00000000 --- a/dist/iidx/iidxhook-18-cn.conf +++ /dev/null @@ -1,50 +0,0 @@ -# PCBID -eamuse.pcbid=0101020304050607086F - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Fix diagonal tearing with video cards other than Radeon X1300 and HD3450 -gfx.diagonal_tearing_fix=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GKJDZCAA diff --git a/dist/iidx/iidxhook-18.conf b/dist/iidx/iidxhook-18.conf deleted file mode 100755 index 2380cde4..00000000 --- a/dist/iidx/iidxhook-18.conf +++ /dev/null @@ -1,47 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Fix diagonal tearing with video cards other than Radeon X1300 and HD3450 -gfx.diagonal_tearing_fix=false - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) -io.disable_card_reader_emu=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ \ No newline at end of file diff --git a/dist/iidx/iidxhook-19.conf b/dist/iidx/iidxhook-19.conf deleted file mode 100755 index 2380cde4..00000000 --- a/dist/iidx/iidxhook-19.conf +++ /dev/null @@ -1,47 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Enable/disable software monitor check/auto timebase or set a pre-determined refresh value. -1 disables this feature. 0 enables auto detecting the current refresh rate on startup. Setting any positive value > 0 allows you to set a pre-determined refresh rate (e.g. retrieved from the monitor check on newer IIDX games). Either the auto detected value or pre-determined value is used to patch any chart files in-memory to fix song synchronization issues. Requires constant refresh rate!!! -gfx.monitor_check=-1.000000 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Fix diagonal tearing with video cards other than Radeon X1300 and HD3450 -gfx.diagonal_tearing_fix=false - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) -io.disable_card_reader_emu=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ \ No newline at end of file diff --git a/dist/iidx/iidxhook-20-cn.conf b/dist/iidx/iidxhook-20-cn.conf deleted file mode 100644 index 77aef4f9..00000000 --- a/dist/iidx/iidxhook-20-cn.conf +++ /dev/null @@ -1,47 +0,0 @@ -# PCBID -eamuse.pcbid=0101020304050607086F - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Fix diagonal tearing with video cards other than Radeon X1300 and HD3450 -gfx.diagonal_tearing_fix=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false - -# Path to store the settings, e.g. bookkeeping, operator settings. d:, e: and f: drive configuration/settings data -misc.settings_path=.\ - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GKJDZCAA diff --git a/dist/iidx/iidxhook-20.conf b/dist/iidx/iidxhook-20.conf deleted file mode 100755 index d5ed89e5..00000000 --- a/dist/iidx/iidxhook-20.conf +++ /dev/null @@ -1,38 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) -io.disable_card_reader_emu=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false \ No newline at end of file diff --git a/dist/iidx/iidxhook-21.conf b/dist/iidx/iidxhook-21.conf deleted file mode 100755 index d5ed89e5..00000000 --- a/dist/iidx/iidxhook-21.conf +++ /dev/null @@ -1,38 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) -io.disable_card_reader_emu=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false \ No newline at end of file diff --git a/dist/iidx/iidxhook-22.conf b/dist/iidx/iidxhook-22.conf deleted file mode 100755 index d5ed89e5..00000000 --- a/dist/iidx/iidxhook-22.conf +++ /dev/null @@ -1,38 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) -io.disable_card_reader_emu=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false \ No newline at end of file diff --git a/dist/iidx/iidxhook-23.conf b/dist/iidx/iidxhook-23.conf deleted file mode 100755 index d5ed89e5..00000000 --- a/dist/iidx/iidxhook-23.conf +++ /dev/null @@ -1,38 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) -io.disable_card_reader_emu=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false \ No newline at end of file diff --git a/dist/iidx/iidxhook-24.conf b/dist/iidx/iidxhook-24.conf deleted file mode 100755 index d5ed89e5..00000000 --- a/dist/iidx/iidxhook-24.conf +++ /dev/null @@ -1,38 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers) -io.disable_card_reader_emu=false - -# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware -io.disable_io_emu=false \ No newline at end of file diff --git a/dist/iidx/iidxhook-25.conf b/dist/iidx/iidxhook-25.conf deleted file mode 100644 index f14335a6..00000000 --- a/dist/iidx/iidxhook-25.conf +++ /dev/null @@ -1,56 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disables the camera emulation -cam.disable_emu=false - -# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame. -cam.disable_camera1=false - -# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame. -cam.disable_camera2=false - -# Override camera device ID 1 detection (copy from device manager, do not escape) Leave blank to automatically detect -cam.device_id1= - -# Override camera device ID 2 detection (copy from device manager, do not escape) Leave blank to automatically detect -cam.device_id2= - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers) -io.disable_card_reader_emu=false - -# Disable BIO2 emulation and enable usage of real BIO2 hardware -io.disable_bio2_emu=false - -# Disables the poll limiter, warning very high CPU usage may arise -io.disable_poll_limiter=false diff --git a/dist/iidx/iidxhook-26.conf b/dist/iidx/iidxhook-26.conf deleted file mode 100644 index f14335a6..00000000 --- a/dist/iidx/iidxhook-26.conf +++ /dev/null @@ -1,56 +0,0 @@ -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) -gfx.frame_rate_limit=0.0 - -# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) -gfx.pci_id=1002:7146 - -# Run the game windowed -gfx.windowed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. -gfx.scale_back_buffer_width=0 - -# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. -gfx.scale_back_buffer_height=0 - -# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). -gfx.scale_back_buffer_filter=none - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Disables the camera emulation -cam.disable_emu=false - -# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame. -cam.disable_camera1=false - -# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame. -cam.disable_camera2=false - -# Override camera device ID 1 detection (copy from device manager, do not escape) Leave blank to automatically detect -cam.device_id1= - -# Override camera device ID 2 detection (copy from device manager, do not escape) Leave blank to automatically detect -cam.device_id2= - -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers) -io.disable_card_reader_emu=false - -# Disable BIO2 emulation and enable usage of real BIO2 hardware -io.disable_bio2_emu=false - -# Disables the poll limiter, warning very high CPU usage may arise -io.disable_poll_limiter=false diff --git a/dist/iidx/iidxhook-27.conf b/dist/iidx/iidxhook-27.conf deleted file mode 100644 index 008c3fa5..00000000 --- a/dist/iidx/iidxhook-27.conf +++ /dev/null @@ -1,87 +0,0 @@ -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers) -io.disable_card_reader_emu=false - -# Disable BIO2 emulation and enable usage of real BIO2 hardware -io.disable_bio2_emu=false - -# Disables the poll limiter, warning very high CPU usage may arise -io.disable_poll_limiter=false - -# Lightning cab mode (requires additional IO emulation) -io.lightning_mode=false - -# Disable camera connection -io.disable_cams=true - -# Disables the built in file hooks, requiring manual file creation -io.disable_file_hooks=false - -# Turntable sensitivity multiplier (1.0 is default) -io.tt_multiplier=1.0 - -# Disables the camera emulation -cam.disable_emu=true - -# Camera port layout (0 = LDJ, 1 = CLDJ/TDJ-JA, 2 = TDJ-JB) -cam.port_layout=1 - -# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame. -cam.disable_camera1=false - -# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame. -cam.disable_camera2=false - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id1= - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id2= - -# Run the game in a framed window (requires windowed option) -gfx.framed=true - -# Run the game windowed -gfx.windowed=false - -# Confine mouse cursor to window -gfx.confined=false - -# Windowed width, -1 for default size -gfx.window_width=-1 - -# Windowed height, -1 for default size -gfx.window_height=-1 - -# Windowed X, -1 for default X position -gfx.window_x=-1 - -# Windowed Y, -1 for default Y position -gfx.window_y=-1 - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees -gfx.force_orientation=-1 - -# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.width=-1 - -# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.height=-1 - -# IP of adapter to force override with -adapter.override_ip= - -# Force ASIO audio mode/device (if applicable / TDJ default) -asio.force_asio=false - -# Force WASAPI audio mode (if applicable / LDJ default) -asio.force_wasapi=true - -# The ASIO device name to use -asio.device_name=XONAR SOUND CARD(64) - diff --git a/dist/iidx/iidxhook-28.conf b/dist/iidx/iidxhook-28.conf deleted file mode 100644 index 008c3fa5..00000000 --- a/dist/iidx/iidxhook-28.conf +++ /dev/null @@ -1,87 +0,0 @@ -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers) -io.disable_card_reader_emu=false - -# Disable BIO2 emulation and enable usage of real BIO2 hardware -io.disable_bio2_emu=false - -# Disables the poll limiter, warning very high CPU usage may arise -io.disable_poll_limiter=false - -# Lightning cab mode (requires additional IO emulation) -io.lightning_mode=false - -# Disable camera connection -io.disable_cams=true - -# Disables the built in file hooks, requiring manual file creation -io.disable_file_hooks=false - -# Turntable sensitivity multiplier (1.0 is default) -io.tt_multiplier=1.0 - -# Disables the camera emulation -cam.disable_emu=true - -# Camera port layout (0 = LDJ, 1 = CLDJ/TDJ-JA, 2 = TDJ-JB) -cam.port_layout=1 - -# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame. -cam.disable_camera1=false - -# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame. -cam.disable_camera2=false - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id1= - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id2= - -# Run the game in a framed window (requires windowed option) -gfx.framed=true - -# Run the game windowed -gfx.windowed=false - -# Confine mouse cursor to window -gfx.confined=false - -# Windowed width, -1 for default size -gfx.window_width=-1 - -# Windowed height, -1 for default size -gfx.window_height=-1 - -# Windowed X, -1 for default X position -gfx.window_x=-1 - -# Windowed Y, -1 for default Y position -gfx.window_y=-1 - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees -gfx.force_orientation=-1 - -# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.width=-1 - -# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.height=-1 - -# IP of adapter to force override with -adapter.override_ip= - -# Force ASIO audio mode/device (if applicable / TDJ default) -asio.force_asio=false - -# Force WASAPI audio mode (if applicable / LDJ default) -asio.force_wasapi=true - -# The ASIO device name to use -asio.device_name=XONAR SOUND CARD(64) - diff --git a/dist/iidx/iidxhook-29.conf b/dist/iidx/iidxhook-29.conf deleted file mode 100644 index 23fe34e7..00000000 --- a/dist/iidx/iidxhook-29.conf +++ /dev/null @@ -1,87 +0,0 @@ -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers) -io.disable_card_reader_emu=false - -# Disable BIO2 emulation and enable usage of real BIO2 hardware -io.disable_bio2_emu=false - -# Disables the poll limiter, warning very high CPU usage may arise -io.disable_poll_limiter=false - -# Lightning cab mode (requires additional IO emulation) -io.lightning_mode=false - -# Disable camera connection -io.disable_cams=true - -# Disables the built in file hooks, requiring manual file creation -io.disable_file_hooks=false - -# Turntable sensitivity multiplier (1.0 is default) -io.tt_multiplier=1.0 - -# Disables the camera emulation -cam.disable_emu=true - -# Camera port layout (0 = LDJ, 1 = CLDJ/TDJ-JA, 2 = TDJ-JB) -cam.port_layout=1 - -# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame. -cam.disable_camera1=true - -# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame. -cam.disable_camera2=false - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id1= - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id2= - -# Run the game in a framed window (requires windowed option) -gfx.framed=true - -# Run the game windowed -gfx.windowed=false - -# Confine mouse cursor to window -gfx.confined=false - -# Windowed width, -1 for default size -gfx.window_width=-1 - -# Windowed height, -1 for default size -gfx.window_height=-1 - -# Windowed X, -1 for default X position -gfx.window_x=-1 - -# Windowed Y, -1 for default Y position -gfx.window_y=-1 - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees -gfx.force_orientation=-1 - -# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.width=-1 - -# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.height=-1 - -# IP of adapter to force override with -adapter.override_ip= - -# Force ASIO audio mode/device (if applicable / TDJ default) -asio.force_asio=false - -# Force WASAPI audio mode (if applicable / LDJ default) -asio.force_wasapi=true - -# The ASIO device name to use -asio.device_name=XONAR SOUND CARD(64) - diff --git a/dist/iidx/iidxhook-30.conf b/dist/iidx/iidxhook-30.conf deleted file mode 100644 index 23fe34e7..00000000 --- a/dist/iidx/iidxhook-30.conf +++ /dev/null @@ -1,87 +0,0 @@ -# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted readers) -io.disable_card_reader_emu=false - -# Disable BIO2 emulation and enable usage of real BIO2 hardware -io.disable_bio2_emu=false - -# Disables the poll limiter, warning very high CPU usage may arise -io.disable_poll_limiter=false - -# Lightning cab mode (requires additional IO emulation) -io.lightning_mode=false - -# Disable camera connection -io.disable_cams=true - -# Disables the built in file hooks, requiring manual file creation -io.disable_file_hooks=false - -# Turntable sensitivity multiplier (1.0 is default) -io.tt_multiplier=1.0 - -# Disables the camera emulation -cam.disable_emu=true - -# Camera port layout (0 = LDJ, 1 = CLDJ/TDJ-JA, 2 = TDJ-JB) -cam.port_layout=1 - -# Disable camera 1. Use, i.e., if you only have one camera and want it to be mapped to camera 2 ingame. -cam.disable_camera1=true - -# Disable camera 2. Use, i.e., if you have more than one camera but only want to map camera 1 ingame. -cam.disable_camera2=false - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id1= - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id2= - -# Run the game in a framed window (requires windowed option) -gfx.framed=true - -# Run the game windowed -gfx.windowed=false - -# Confine mouse cursor to window -gfx.confined=false - -# Windowed width, -1 for default size -gfx.window_width=-1 - -# Windowed height, -1 for default size -gfx.window_height=-1 - -# Windowed X, -1 for default X position -gfx.window_x=-1 - -# Windowed Y, -1 for default Y position -gfx.window_y=-1 - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees -gfx.force_orientation=-1 - -# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.width=-1 - -# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.height=-1 - -# IP of adapter to force override with -adapter.override_ip= - -# Force ASIO audio mode/device (if applicable / TDJ default) -asio.force_asio=false - -# Force WASAPI audio mode (if applicable / LDJ default) -asio.force_wasapi=true - -# The ASIO device name to use -asio.device_name=XONAR SOUND CARD(64) - diff --git a/dist/iidx/iidxio-bio2.conf b/dist/iidx/iidxio-bio2.conf deleted file mode 100644 index 4b42af03..00000000 --- a/dist/iidx/iidxio-bio2.conf +++ /dev/null @@ -1,8 +0,0 @@ -# Autodetect BIO2 port (default: on) -bio2.autodetect=true - -# BIO2 serial port. Optional, if autodetect property is turned on -bio2.port=COM4 - -# BIO2 bus baudrate (real devices expect 115200) -bio2.baud=115200 \ No newline at end of file diff --git a/dist/iidx/iidxio-bio2.xml b/dist/iidx/iidxio-bio2.xml new file mode 100644 index 00000000..80145686 --- /dev/null +++ b/dist/iidx/iidxio-bio2.xml @@ -0,0 +1,6 @@ + + + 1 + COM4 + 115200 + \ No newline at end of file diff --git a/dist/iidx/inject-09.xml b/dist/iidx/inject-09.xml new file mode 100644 index 00000000..0ab002e1 --- /dev/null +++ b/dist/iidx/inject-09.xml @@ -0,0 +1,105 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook1.dll + + + + + C02 + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + + + C02 + + + GEC02 + 0:0:0 + + GEC02JAA + + + 0 + + + + + .\ + 1 + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-10.xml b/dist/iidx/inject-10.xml new file mode 100644 index 00000000..8e1e307e --- /dev/null +++ b/dist/iidx/inject-10.xml @@ -0,0 +1,105 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook1.dll + + + + + D01 + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + + + D01 + + + GEC02 + 0:1:1 + + GQD01JAA + + + 0 + + + + + .\ + 1 + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-11.xml b/dist/iidx/inject-11.xml new file mode 100644 index 00000000..22fde173 --- /dev/null +++ b/dist/iidx/inject-11.xml @@ -0,0 +1,105 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook1.dll + + + + + E11 + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + + + D01 + + + GEC02 + 0:2:2 + + GQE11JAA + + + 0 + + + + + .\ + 1 + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-12.xml b/dist/iidx/inject-12.xml new file mode 100644 index 00000000..a0414d1f --- /dev/null +++ b/dist/iidx/inject-12.xml @@ -0,0 +1,107 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook1.dll + + + + + ECO + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + 0 + + + + D01 + + + GEC02 + 0:3:3 + + GQECOJAA + + + 0 + + + + + .\ + 1 + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-13.xml b/dist/iidx/inject-13.xml new file mode 100644 index 00000000..9a8066c2 --- /dev/null +++ b/dist/iidx/inject-13.xml @@ -0,0 +1,105 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook2.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + 0 + + + + D01 + + + GEC02 + 0:4:4 + + GQFDDJAA + + + 0 + + + + + .\ + 1 + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-14.xml b/dist/iidx/inject-14.xml new file mode 100644 index 00000000..97ed5431 --- /dev/null +++ b/dist/iidx/inject-14.xml @@ -0,0 +1,94 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook3.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + + + + GQGLDJAA + + + + + .\ + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-15.xml b/dist/iidx/inject-15.xml new file mode 100644 index 00000000..9ec0b44f --- /dev/null +++ b/dist/iidx/inject-15.xml @@ -0,0 +1,94 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook3.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + + + + GQHDDJAA + + + + + .\ + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-16.xml b/dist/iidx/inject-16.xml new file mode 100644 index 00000000..ed3e6a9a --- /dev/null +++ b/dist/iidx/inject-16.xml @@ -0,0 +1,97 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook3.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + + + + GQI00JAA + + + + + .\ + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-17.xml b/dist/iidx/inject-17.xml new file mode 100644 index 00000000..edfd41bb --- /dev/null +++ b/dist/iidx/inject-17.xml @@ -0,0 +1,97 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook3.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 1 + + + + + GCJDJJAA + + + + + .\ + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-18-cn.xml b/dist/iidx/inject-18-cn.xml new file mode 100644 index 00000000..10e3fa03 --- /dev/null +++ b/dist/iidx/inject-18-cn.xml @@ -0,0 +1,97 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook4-cn.dll + + + + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 0 + + + + + GKJDZCAA + + + + 0 + + + + .\ + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/iidx/inject-20-cn.xml b/dist/iidx/inject-20-cn.xml new file mode 100644 index 00000000..1c51f51e --- /dev/null +++ b/dist/iidx/inject-20-cn.xml @@ -0,0 +1,97 @@ + + + 1 + + + bm2dx.exe + + + inject + + + + 1 + iidxhook5-cn.dll + + + + 0101020304050607086F + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 0 + + + + + GKJDZCAA + + + + 0 + + + + .\ + 1 + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ 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..3641ebf1 --- /dev/null +++ b/dist/iidx/launcher-18.xml @@ -0,0 +1,120 @@ + + + 1 + + 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 + + + + + + + . + fs + + + + dev/nvram + fs + + + + dev/raw + fs + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook4.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 0 + + + + 0 + 0 + + + + .\ + + + + + + + 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..6474c422 --- /dev/null +++ b/dist/iidx/launcher-19.xml @@ -0,0 +1,120 @@ + + + 1 + + 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 + + + + + + + . + fs + + + + dev/nvram + fs + + + + dev/raw + fs + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook5.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + -1.000000 + + 0 + + + + 0 + 0 + + + + .\ + + + + + + + 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..e76fe313 --- /dev/null +++ b/dist/iidx/launcher-20.xml @@ -0,0 +1,110 @@ + + + 1 + + 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 + + + + + + + . + fs + + + + dev/nvram + fs + + + + dev/raw + fs + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook6.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + 0 + 0 + + + + + + + 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..92df8341 --- /dev/null +++ b/dist/iidx/launcher-21.xml @@ -0,0 +1,110 @@ + + + 1 + + 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 + + + + + + + . + fs + + + + dev/nvram + fs + + + + dev/raw + fs + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook7.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + 0 + 0 + + + + + + + 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..92df8341 --- /dev/null +++ b/dist/iidx/launcher-22.xml @@ -0,0 +1,110 @@ + + + 1 + + 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 + + + + + + + . + fs + + + + dev/nvram + fs + + + + dev/raw + fs + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook7.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + 0 + 0 + + + + + + + 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..92df8341 --- /dev/null +++ b/dist/iidx/launcher-23.xml @@ -0,0 +1,110 @@ + + + 1 + + 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 + + + + + + + . + fs + + + + dev/nvram + fs + + + + dev/raw + fs + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook7.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + 0 + 0 + + + + + + + 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..92df8341 --- /dev/null +++ b/dist/iidx/launcher-24.xml @@ -0,0 +1,110 @@ + + + 1 + + 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 + + + + + + + . + fs + + + + dev/nvram + fs + + + + dev/raw + fs + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook7.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + 0 + 0 + + + + + + + 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..8c7ead41 --- /dev/null +++ b/dist/iidx/launcher-25.xml @@ -0,0 +1,127 @@ + + + 1 + + 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 + + + + 1 + iidxhook8.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + + 0 + + + 0 + + + + + + 0 + + + + + + + 0 + + 0 + + 0 + + + + + + + 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..8c7ead41 --- /dev/null +++ b/dist/iidx/launcher-26.xml @@ -0,0 +1,127 @@ + + + 1 + + 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 + + + + 1 + iidxhook8.dll + + + + + + -1 + + -1 + + 0.0 + + 1002 + 7146 + + + 1 + 1 + + 0 + 0 + + + + 0 + 0 + + none + + + + + 0 + + + 0 + + + + + + 0 + + + + + + + 0 + + 0 + + 0 + + + + + + + 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..fc704ee9 --- /dev/null +++ b/dist/iidx/launcher-27.xml @@ -0,0 +1,155 @@ + + + 1 + + bemanitools_local_fs + + + + + + + + + + + prop/avs-config.xml + 134217728 + + + info + + + /dev/nvram/ea3-config.xml + + + bm2dx.dll + + + + + + + + + bemanitools/ea3-ident.xml + bemanitools/ea3-license.xml + + + + + + + . + + boot + + + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook9.dll + + + + + + + + + false + + true + + XONAR SOUND CARD(64) + + + + + -1 + + -1 + + -1 + + + -1 + -1 + + + + + 1 + + 1 + + 0 + + -1 + + -1 + + -1 + + -1 + + + + 0 + 0 + + none + + + + + 0 + + 1 + + + 0 + + + + + + 0 + + + + + + + 0 + + 0 + + 0 + + 0 + + 1 + + 0 + + 1.0 + + + + + + + 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..fc704ee9 --- /dev/null +++ b/dist/iidx/launcher-28.xml @@ -0,0 +1,155 @@ + + + 1 + + bemanitools_local_fs + + + + + + + + + + + prop/avs-config.xml + 134217728 + + + info + + + /dev/nvram/ea3-config.xml + + + bm2dx.dll + + + + + + + + + bemanitools/ea3-ident.xml + bemanitools/ea3-license.xml + + + + + + + . + + boot + + + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook9.dll + + + + + + + + + false + + true + + XONAR SOUND CARD(64) + + + + + -1 + + -1 + + -1 + + + -1 + -1 + + + + + 1 + + 1 + + 0 + + -1 + + -1 + + -1 + + -1 + + + + 0 + 0 + + none + + + + + 0 + + 1 + + + 0 + + + + + + 0 + + + + + + + 0 + + 0 + + 0 + + 0 + + 1 + + 0 + + 1.0 + + + + + + + 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..f84c73ae --- /dev/null +++ b/dist/iidx/launcher-29.xml @@ -0,0 +1,155 @@ + + + 1 + + bemanitools_local_fs + + + + + + + + + + + prop/avs-config.xml + 134217728 + + + info + + + /dev/nvram/ea3-config.xml + + + bm2dx.dll + + + + + + + + + bemanitools/ea3-ident.xml + bemanitools/ea3-license.xml + + + + + + + . + + boot + + + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook9.dll + + + + + + + + + false + + true + + XONAR SOUND CARD(64) + + + + + -1 + + -1 + + -1 + + + -1 + -1 + + + + + 1 + + 1 + + 0 + + -1 + + -1 + + -1 + + -1 + + + + 0 + 0 + + none + + + + + 0 + + 1 + + + 1 + + + + + + 0 + + + + + + + 0 + + 0 + + 0 + + 0 + + 1 + + 0 + + 1.0 + + + + + + + 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..132e6cb7 --- /dev/null +++ b/dist/iidx/launcher-30.xml @@ -0,0 +1,155 @@ + + + 1 + + bemanitools_local_fs + + + + + + + + + + + prop/avs-config.xml + 134217728 + + + info + + + /dev/nvram/ea3-config.xml + + + bm2dx.dll + + + + + + + + + bemanitools/ea3-ident.xml + bemanitools/ea3-license.xml + + + + + + + . + + boot + + + + + + + + + + bemanitools/ea3-service.xml + + + + 1 + iidxhook9.dll + + + + + + + + + false + + true + + XONAR SOUND CARD(64) + + + + + -1 + + -1 + + -1 + + + -1 + -1 + + + + + 1 + + 1 + + 0 + + -1 + + -1 + + -1 + + -1 + + + + 0 + 0 + + none + + + + + 0 + + 1 + + + 1 + + + + + + 0 + + + + + + + 0 + + 0 + + 0 + + 0 + + 1 + + 0 + + 1.0 + + + + + + + 0 + 0 + + \ No newline at end of file diff --git a/dist/iidx/vigem-iidxio.conf b/dist/iidx/vigem-iidxio.conf deleted file mode 100644 index 08cd05dd..00000000 --- a/dist/iidx/vigem-iidxio.conf +++ /dev/null @@ -1,26 +0,0 @@ -# Use relative mode analog mapping instead of absolute analog values -vigem.iidxio.tt.anlog.relative=false - -# Sensitivity value for relative mode (1 to 32767). Tweak if you are having issues with jittering/misfiring/unresponsiveness -vigem.iidxio.tt.anlog.relative_sensitivity=1024 - -# Button turntable: "debounce" value (1 to 50, recommend 20). Tweak if you are having issues with TT button misfiring/unresponsiveness -vigem.iidxio.tt.button.debounce=20 - -# Button turntable: minimum ticks required within (debounce * 2) ms to register movement (1 to 4, recommend 2). Tweak if you button input is too (un-) responsive -vigem.iidxio.tt.button.threshold=2 - -# Print verbose debug output to the console for debugging turntable sensitivity issues -vigem.iidxio.tt.debug_output=false - -# Enable input based key lighting -vigem.iidxio.cab_light.enable_keylight=true - -# Different cabinet light modes: 0 = off, 1 = neons sequence, 2 = neons flash on TT spin -vigem.iidxio.cab_light.light_mode=0 - -# Display text on 16seg. If text exceeds 9 char display limit, it will scroll + cycle -vigem.iidxio.cab_light.text_16seg= - -# Cycle time/scroll speed for text exceeding 16seg display length (9) to scroll from right -vigem.iidxio.cab_light.text_scroll_cycle_time_ms=500 \ No newline at end of file diff --git a/dist/iidx/vigem-iidxio.xml b/dist/iidx/vigem-iidxio.xml new file mode 100644 index 00000000..44f9e863 --- /dev/null +++ b/dist/iidx/vigem-iidxio.xml @@ -0,0 +1,29 @@ + + + + + + 0 + + 1024 + + + + 0 + + + + 1 + + 0 + + + + 500 + + \ 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/eamio-icc.conf b/dist/jb/eamio-icc.conf deleted file mode 100644 index eef32684..00000000 --- a/dist/jb/eamio-icc.conf +++ /dev/null @@ -1,5 +0,0 @@ -# ICCA serial port -icc.port=COM2 - -# ICCA bus baudrate (real devices expect 57600) -icc.baud=57600 diff --git a/dist/jb/eamio-icca.xml b/dist/jb/eamio-icca.xml new file mode 100644 index 00000000..c0a185c6 --- /dev/null +++ b/dist/jb/eamio-icca.xml @@ -0,0 +1,5 @@ + + + COM2 + 57600 + \ 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-01.bat b/dist/jb/gamestart-01.bat index 60d1ca86..84a1cf9d 100644 --- a/dist/jb/gamestart-01.bat +++ b/dist/jb/gamestart-01.bat @@ -1,5 +1,41 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 -inject jbhook1.dll jubeat.exe --config jbhook-01.conf %* +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is content dir which contains the exe and the data folder +cd /d %CONTENT_DIR% + +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-01.xml^ + %* \ No newline at end of file diff --git a/dist/jb/gamestart-02.bat b/dist/jb/gamestart-02.bat index 60914508..0cc6f322 100644 --- a/dist/jb/gamestart-02.bat +++ b/dist/jb/gamestart-02.bat @@ -1,7 +1,43 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is content dir which contains the exe and the data folder +cd /d %CONTENT_DIR% + if not exist dev\nvram mkdir dev\nvram -inject jbhook1.dll jubeat.exe --config jbhook-02.conf %* +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-02.xml^ + %* \ 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/inject-01.xml b/dist/jb/inject-01.xml new file mode 100644 index 00000000..84ac5464 --- /dev/null +++ b/dist/jb/inject-01.xml @@ -0,0 +1,63 @@ + + + 1 + + + jubeat.exe + + + inject + + + + 1 + jbhook1.dll + + + + + 0 + + 1 + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + GCH44JAB + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/jb/inject-02.xml b/dist/jb/inject-02.xml new file mode 100644 index 00000000..ec7a9dd6 --- /dev/null +++ b/dist/jb/inject-02.xml @@ -0,0 +1,63 @@ + + + 1 + + + jubeat.exe + + + inject + + + + 1 + jbhook1.dll + + + + + 0 + + 1 + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + GCI44JAA + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/jb/jbhook-01.conf b/dist/jb/jbhook-01.conf deleted file mode 100755 index 0070a7a8..00000000 --- a/dist/jb/jbhook-01.conf +++ /dev/null @@ -1,18 +0,0 @@ -# Run the game windowed -gfx.windowed=false - -# rotate the normally-horizontal game window to be vertical -gfx.vertical=true - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Mcode of the game to run. -security.mcode=GCH44JAB - diff --git a/dist/jb/jbhook-02.conf b/dist/jb/jbhook-02.conf deleted file mode 100644 index aca6d97d..00000000 --- a/dist/jb/jbhook-02.conf +++ /dev/null @@ -1,18 +0,0 @@ -# Run the game windowed -gfx.windowed=false - -# rotate the normally-horizontal game window to be vertical -gfx.vertical=true - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Mcode of the game to run. -security.mcode=GCI44JAA - diff --git a/dist/jb/jbio-h44b.conf b/dist/jb/jbio-h44b.conf deleted file mode 100644 index 7c984b54..00000000 --- a/dist/jb/jbio-h44b.conf +++ /dev/null @@ -1,5 +0,0 @@ -# H44B serial port -h44b.port=COM2 - -# H44B bus baudrate (real devices expect 57600) -h44b.baud=57600 diff --git a/dist/jb/jbio-h44b.xml b/dist/jb/jbio-h44b.xml new file mode 100644 index 00000000..aaaf54f3 --- /dev/null +++ b/dist/jb/jbio-h44b.xml @@ -0,0 +1,7 @@ + + + + COM2 + + 57600 + 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/popn/gamestart-15.bat b/dist/popn/gamestart-15.bat index f9b67096..b1cf4338 100644 --- a/dist/popn/gamestart-15.bat +++ b/dist/popn/gamestart-15.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data and prog cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\prog\2007091800 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist e\bookkeeping mkdir e\bookkeeping if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0 @@ -12,5 +54,6 @@ if not exist e\CONF\RAW mkdir e\CONF\RAW if not exist e\settings mkdir e\settings if not exist e\UP mkdir e\UP -inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn15.exe --config popnhook-15.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-15.xml^ + %* \ No newline at end of file diff --git a/dist/popn/gamestart-16.bat b/dist/popn/gamestart-16.bat index 8841818f..7f1deed0 100644 --- a/dist/popn/gamestart-16.bat +++ b/dist/popn/gamestart-16.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data and prog cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\prog\2008052700 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist e\bookkeeping mkdir e\bookkeeping if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0 @@ -12,5 +54,6 @@ if not exist e\CONF\RAW mkdir e\CONF\RAW if not exist e\settings mkdir e\settings if not exist e\UP mkdir e\UP -inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn16.exe --config popnhook-16.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-16.xml^ + %* \ No newline at end of file diff --git a/dist/popn/gamestart-17.bat b/dist/popn/gamestart-17.bat index e35442d6..e8d0bcac 100644 --- a/dist/popn/gamestart-17.bat +++ b/dist/popn/gamestart-17.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data and prog cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\prog\2009022500 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist e\bookkeeping mkdir e\bookkeeping if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0 @@ -12,5 +54,6 @@ if not exist e\CONF\RAW mkdir e\CONF\RAW if not exist e\settings mkdir e\settings if not exist e\UP mkdir e\UP -inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn17.exe --config popnhook-17.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-17.xml^ + %* \ No newline at end of file diff --git a/dist/popn/gamestart-18.bat b/dist/popn/gamestart-18.bat index 8cbce7c5..40b748f6 100644 --- a/dist/popn/gamestart-18.bat +++ b/dist/popn/gamestart-18.bat @@ -1,7 +1,49 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: 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 +:: next to the folders data and prog cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools +set REVISION_DIR=%CONTENT_DIR%\prog\2010040500 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +if not exist "%REVISION_DIR%" ( + echo The game modules directory "%REVISION_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%REVISION_DIR%;^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is the selected game revision root folder +cd /d %REVISION_DIR% + if not exist e\bookkeeping mkdir e\bookkeeping if not exist e\CONF\NVRAM mkdir e\CONF\NVRAM if not exist e\CONF\NVRAM\0 mkdir e\CONF\NVRAM\0 @@ -12,5 +54,6 @@ if not exist e\CONF\RAW mkdir e\CONF\RAW if not exist e\settings mkdir e\settings if not exist e\UP mkdir e\UP -inject popnhook1.dll ezusb.dll=ezusb2-popn-shim.dll popn18.exe --config popnhook-18.conf %* - +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-18.xml^ + %* \ No newline at end of file diff --git a/dist/popn/inject-15.xml b/dist/popn/inject-15.xml new file mode 100644 index 00000000..3d0ecdb9 --- /dev/null +++ b/dist/popn/inject-15.xml @@ -0,0 +1,68 @@ + + + 1 + + + popn15.exe + + + inject + + + + 1 + ezusb.dll + ezusb2-popn-shim.dll + + + 1 + popnhook1.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + 1 + 1 + 0 + 0 + + + GQG15JAA + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/popn/inject-16.xml b/dist/popn/inject-16.xml new file mode 100644 index 00000000..c4766128 --- /dev/null +++ b/dist/popn/inject-16.xml @@ -0,0 +1,68 @@ + + + 1 + + + popn16.exe + + + inject + + + + 1 + ezusb.dll + ezusb2-popn-shim.dll + + + 1 + popnhook1.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + 1 + 1 + 0 + 0 + + + GQH16JAA + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/popn/inject-17.xml b/dist/popn/inject-17.xml new file mode 100644 index 00000000..001cecbc --- /dev/null +++ b/dist/popn/inject-17.xml @@ -0,0 +1,68 @@ + + + 1 + + + popn17.exe + + + inject + + + + 1 + ezusb.dll + ezusb2-popn-shim.dll + + + 1 + popnhook1.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + 1 + 1 + 0 + 0 + + + GQI17JAA + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/popn/inject-18.xml b/dist/popn/inject-18.xml new file mode 100644 index 00000000..d516ea52 --- /dev/null +++ b/dist/popn/inject-18.xml @@ -0,0 +1,68 @@ + + + 1 + + + popn18.exe + + + inject + + + + 1 + ezusb.dll + ezusb2-popn-shim.dll + + + 1 + popnhook1.dll + + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + 1 + 1 + 0 + 0 + + + GCJ39JAA + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/popn/popnhook-15.conf b/dist/popn/popnhook-15.conf deleted file mode 100644 index c429407e..00000000 --- a/dist/popn/popnhook-15.conf +++ /dev/null @@ -1,23 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Run the game windowed -gfx.windowed=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQG15JAA diff --git a/dist/popn/popnhook-16.conf b/dist/popn/popnhook-16.conf deleted file mode 100644 index 4c7affa8..00000000 --- a/dist/popn/popnhook-16.conf +++ /dev/null @@ -1,23 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Run the game windowed -gfx.windowed=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQH16JAA diff --git a/dist/popn/popnhook-17.conf b/dist/popn/popnhook-17.conf deleted file mode 100644 index cd32bd14..00000000 --- a/dist/popn/popnhook-17.conf +++ /dev/null @@ -1,23 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Run the game windowed -gfx.windowed=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GQI17JAA \ No newline at end of file diff --git a/dist/popn/popnhook-18.conf b/dist/popn/popnhook-18.conf deleted file mode 100644 index bb11e6ad..00000000 --- a/dist/popn/popnhook-18.conf +++ /dev/null @@ -1,23 +0,0 @@ -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Run the game windowed -gfx.windowed=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=false - -# Windowed width, 0 for default size -gfx.window_width=0 - -# Windowed height, 0 for default size -gfx.window_height=0 - -# Security black plug mcode id string (e.g. GQC02JAA). -sec.black_plug_mcode=GCJ39JAA \ 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/eamio-icca.xml b/dist/sdvx/eamio-icca.xml new file mode 100644 index 00000000..d89bf432 --- /dev/null +++ b/dist/sdvx/eamio-icca.xml @@ -0,0 +1,5 @@ + + + COM1 + 57600 + \ 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/sdvx/sdvxio-bio2.xml b/dist/sdvx/sdvxio-bio2.xml new file mode 100644 index 00000000..50282142 --- /dev/null +++ b/dist/sdvx/sdvxio-bio2.xml @@ -0,0 +1,6 @@ + + + 1 + COM4 + 115200 + \ No newline at end of file diff --git a/dist/sdvx/sdvxio-kfca.xml b/dist/sdvx/sdvxio-kfca.xml new file mode 100644 index 00000000..830daa8e --- /dev/null +++ b/dist/sdvx/sdvxio-kfca.xml @@ -0,0 +1,8 @@ + + + COM4 + 115200 + -1 + -1 + -1 + diff --git a/dist/sdvx/vigem-sdvxio.xml b/dist/sdvx/vigem-sdvxio.xml new file mode 100644 index 00000000..0e99984f --- /dev/null +++ b/dist/sdvx/vigem-sdvxio.xml @@ -0,0 +1,8 @@ + + + 1 + 0 + 128 + 64 + 48 + \ 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..bf836d36 100644 --- a/dist/sdvx5/gamestart-cn.bat +++ b/dist/sdvx5/gamestart-cn.bat @@ -1,17 +1,48 @@ @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 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 - -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +:: 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 + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -launcher -H 268435456 -K sdvxhook2-cn.dll soundvoltex.dll --config sdvxhook2-cn.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher-cn.xml^ + %* \ No newline at end of file diff --git a/dist/sdvx5/gamestart.bat b/dist/sdvx5/gamestart.bat index c1b41ddd..6f5a3629 100644 --- a/dist/sdvx5/gamestart.bat +++ b/dist/sdvx5/gamestart.bat @@ -1,16 +1,48 @@ @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 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 +:: 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 -for /R prop\defaults %%D in (*.*) do ( - if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 ) -launcher -H 268435456 -K sdvxhook2.dll soundvoltex.dll --config sdvxhook2.conf %* +if not exist "%MODULES_DIR%" ( + echo The game modules directory "%MODULES_DIR%" does not exist. + pause + exit 1 +) + +:: 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.exe^ + %BEMANITOOLS_DIR%\launcher.xml^ + %* \ 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..bbb1610b --- /dev/null +++ b/dist/sdvx5/launcher-cn.xml @@ -0,0 +1,122 @@ + + + + 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 + + + + 1 + sdvxhook2-cn.dll + + + + + + -1 + + -1 + + -1 + + + -1 + -1 + + + + + 0 + + 1 + + 0 + + 720 + + 1280 + + -1 + + -1 + + + + + 0 + + + 1 + + + + + + + 0 + + prop/unis.xml + + + + + + + 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..736a3a37 --- /dev/null +++ b/dist/sdvx5/launcher.xml @@ -0,0 +1,138 @@ + + + + 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 + + + + 1 + sdvxhook2.dll + + + + + + + + + + -1 + + -1 + + -1 + + + -1 + -1 + + + + + 0 + + 1 + + 0 + + 1080 + + 1920 + + -1 + + -1 + + + + + 0 + + + 1 + + + + + + + 0 + + 0 + + 0 + + 0 + + 0 + + 0 + + 0 + + 0 + + + + + + + 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/sdvx5/sdvxhook2-cn.conf b/dist/sdvx5/sdvxhook2-cn.conf deleted file mode 100644 index c02c139b..00000000 --- a/dist/sdvx5/sdvxhook2-cn.conf +++ /dev/null @@ -1,24 +0,0 @@ -# Disable IO emulation and enable usage of real KFCA hardware -io.disable_io_emu=false - -# Path to unis version file under the prop.s folder -cn.unis_path=prop/unis.xml - -# Run the game in a framed window (requires windowed option) -gfx.framed=true - -# Run the game windowed -gfx.windowed=false - -# Windowed width, -1 for default size -gfx.window_width=720 - -# Windowed height, -1 for default size -gfx.window_height=1280 - -# Disables the camera emulation -cam.disable_emu=false - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id1= - diff --git a/dist/sdvx5/sdvxhook2.conf b/dist/sdvx5/sdvxhook2.conf deleted file mode 100644 index 8d2b3864..00000000 --- a/dist/sdvx5/sdvxhook2.conf +++ /dev/null @@ -1,69 +0,0 @@ -# Disable card reader emulation and enable usage of real card reader hardware on COM2 -io.disable_card_reader_emu=false - -# Disable BIO2 emulation and enable usage of real BIO2 hardware -io.disable_bio2_emu=false - -# Disables the poll limiter, warning very high CPU usage may arise -io.disable_poll_limiter=false - -# Forces game to think headphones are attached -io.force_headphones=false - -# Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest) -io.disable_file_hooks=false - -# Disables the built in power control hooks, allowing game to modify system power settings -io.disable_power_hooks=false - -# Disables the built in NVAPI control hooks, allowing game to modify system monitor settings -io.disable_nvapi_hooks=false - -# Emulates the card reader on COM1 instead of COM2 -io.com1_card_reader=false - -# Run the game in a framed window (requires windowed option) -gfx.framed=true - -# Run the game windowed -gfx.windowed=false - -# Confine mouse cursor to window -gfx.confined=false - -# Windowed width, -1 for default size -gfx.window_width=1080 - -# Windowed height, -1 for default size -gfx.window_height=1920 - -# Windowed X, -1 for default X position -gfx.window_x=-1 - -# Windowed Y, -1 for default Y position -gfx.window_y=-1 - -# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) -gfx.forced_refresh_rate=-1 - -# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter -gfx.device_adapter=-1 - -# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees -gfx.force_orientation=-1 - -# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.width=-1 - -# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. -gfx.force_screen_res.height=-1 - -# Disables the camera emulation -cam.disable_emu=false - -# Override camera device ID detection (copy from device manager, do not escape) -cam.device_id1= - -# IP of adapter to force override with -adapter.override_ip= - 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/dist/test/run-tests.sh b/dist/test/run-tests.sh index 5e4ac918..fb68f9c6 100644 --- a/dist/test/run-tests.sh +++ b/dist/test/run-tests.sh @@ -8,15 +8,6 @@ cd $DIR echo "Running tests..." -wine ./cconfig-test.exe -wine ./cconfig-util-test.exe -wine ./cconfig-cmd-test.exe -wine ./iidxhook-util-config-eamuse-test.exe -wine ./iidxhook-util-config-gfx-test.exe -# wine ./iidxhook-config-iidxhook1-test.exe -# wine ./iidxhook-config-iidxhook2-test.exe -wine ./iidxhook-util-config-misc-test.exe -wine ./iidxhook-util-config-sec-test.exe wine ./security-id-test.exe wine ./security-mcode-test.exe wine ./security-util-test.exe diff --git a/src/api/acio/mgr.h b/src/api/acio/mgr.h new file mode 100644 index 00000000..57e2ec80 --- /dev/null +++ b/src/api/acio/mgr.h @@ -0,0 +1,42 @@ +#ifndef BT_API_ACIO_MGR_H +#define BT_API_ACIO_MGR_H + +#include +#include + +#define BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN 4 + +typedef struct ac_io_message bt_acio_message_t; +typedef struct aciodrv_device_ctx bt_acio_drv_device_ctx_t; +typedef struct bt_acio_mgr_port_dispatcher bt_acio_mgr_port_dispatcher_t; + +typedef bt_acio_mgr_port_dispatcher_t *(*bt_acio_mgr_port_init_t)(const char *path, uint32_t baud); +typedef void (*bt_acio_mgr_port_fini_t)(bt_acio_mgr_port_dispatcher_t *dispatcher); +typedef uint8_t (*bt_acio_mgr_node_count_get_t)(const bt_acio_mgr_port_dispatcher_t *dispatcher); +typedef bool (*bt_acio_mgr_node_product_ident_get_t)( + const bt_acio_mgr_port_dispatcher_t *dispatcher, + uint8_t node_id, + char product[BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN]); +typedef bool (*bt_acio_mgr_port_packet_submit_t)( + bt_acio_mgr_port_dispatcher_t *dispatcher, + bt_acio_message_t *msg, + uint32_t max_resp_size); +typedef bt_acio_drv_device_ctx_t *(*bt_acio_mgr_port_checkout_t)(bt_acio_mgr_port_dispatcher_t *dispatcher); +typedef void (*bt_acio_mgr_port_checkin_t)(bt_acio_mgr_port_dispatcher_t *dispatcher); + +typedef struct bt_acio_mgr_api { + uint16_t version; + + struct { + // Required to be implemented + bt_acio_mgr_port_init_t port_init; + bt_acio_mgr_port_fini_t port_fini; + bt_acio_mgr_node_count_get_t node_count_get; + bt_acio_mgr_node_product_ident_get_t node_product_ident_get; + bt_acio_mgr_port_packet_submit_t port_packet_submit; + bt_acio_mgr_port_checkout_t port_checkout; + bt_acio_mgr_port_checkin_t port_checkin; + } v1; +} bt_acio_mgr_api_t; + +#endif diff --git a/src/api/core/config.h b/src/api/core/config.h new file mode 100644 index 00000000..7b65e8a6 --- /dev/null +++ b/src/api/core/config.h @@ -0,0 +1,54 @@ +#ifndef BT_API_CORE_CONFIG_H +#define BT_API_CORE_CONFIG_H + +#include +#include +#include + +typedef struct bt_core_config bt_core_config_t; + +#define BT_CORE_CONFIG_RESULT_IS_ERROR(x) \ + (x > BT_CORE_CONFIG_RESULT_SUCCESS) + +typedef enum bt_core_config_result { + BT_CORE_CONFIG_RESULT_SUCCESS = 0, + BT_CORE_CONFIG_RESULT_ERROR_INTERNAL = 1, + BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND = 2, + BT_CORE_CONFIG_RESULT_TYPE_MISMATCH = 3, +} bt_core_config_result_t; + +typedef bt_core_config_result_t (*bt_core_config_s8_get_t)(const bt_core_config_t *config, const char *path, int8_t *value); +typedef bt_core_config_result_t (*bt_core_config_u8_get_t)(const bt_core_config_t *config, const char *path, uint8_t *value); +typedef bt_core_config_result_t (*bt_core_config_s16_get_t)(const bt_core_config_t *config, const char *path, int16_t *value); +typedef bt_core_config_result_t (*bt_core_config_u16_get_t)(const bt_core_config_t *config, const char *path, uint16_t *value); +typedef bt_core_config_result_t (*bt_core_config_s32_get_t)(const bt_core_config_t *config, const char *path, int32_t *value); +typedef bt_core_config_result_t (*bt_core_config_u32_get_t)(const bt_core_config_t *config, const char *path, uint32_t *value); +typedef bt_core_config_result_t (*bt_core_config_s64_get_t)(const bt_core_config_t *config, const char *path, int64_t *value); +typedef bt_core_config_result_t (*bt_core_config_u64_get_t)(const bt_core_config_t *config, const char *path, uint64_t *value); +typedef bt_core_config_result_t (*bt_core_config_float_get_t)(const bt_core_config_t *config, const char *path, float *value); +typedef bt_core_config_result_t (*bt_core_config_double_get_t)(const bt_core_config_t *config, const char *path, double *value); +typedef bt_core_config_result_t (*bt_core_config_bool_get_t)(const bt_core_config_t *config, const char *path, bool *value); +typedef bt_core_config_result_t (*bt_core_config_bin_get_t)(const bt_core_config_t *config, const char *path, void *value, size_t len); +typedef bt_core_config_result_t (*bt_core_config_str_get_t)(const bt_core_config_t *config, const char *path, char *value, size_t len); + +typedef struct bt_core_config_api { + uint16_t version; + + struct { + bt_core_config_s8_get_t s8_get; + bt_core_config_u8_get_t u8_get; + bt_core_config_s16_get_t s16_get; + bt_core_config_u16_get_t u16_get; + bt_core_config_s32_get_t s32_get; + bt_core_config_u32_get_t u32_get; + bt_core_config_s64_get_t s64_get; + bt_core_config_u64_get_t u64_get; + bt_core_config_float_get_t float_get; + bt_core_config_double_get_t double_get; + bt_core_config_bool_get_t bool_get; + bt_core_config_bin_get_t bin_get; + bt_core_config_str_get_t str_get; + } v1; +} bt_core_config_api_t; + +#endif \ No newline at end of file diff --git a/src/api/core/log.h b/src/api/core/log.h new file mode 100644 index 00000000..e6429683 --- /dev/null +++ b/src/api/core/log.h @@ -0,0 +1,19 @@ +#ifndef BT_API_CORE_LOG_H +#define BT_API_CORE_LOG_H + +#include + +typedef void (*bt_core_log_message_t)(const char *module, const char *fmt, ...); + +typedef struct bt_core_log_api { + uint16_t version; + + struct { + bt_core_log_message_t misc; + bt_core_log_message_t info; + bt_core_log_message_t warning; + bt_core_log_message_t fatal; + } v1; +} bt_core_log_api_t; + +#endif \ No newline at end of file diff --git a/src/api/core/thread.h b/src/api/core/thread.h new file mode 100644 index 00000000..1ab5d837 --- /dev/null +++ b/src/api/core/thread.h @@ -0,0 +1,31 @@ +#ifndef BT_API_CORE_THREAD_H +#define BT_API_CORE_THREAD_H + +#include + +#define BT_CORE_THREAD_RESULT_IS_ERROR(x) \ + (x > BT_CORE_THREAD_RESULT_SUCCESS) + +typedef enum bt_core_thread_result { + BT_CORE_THREAD_RESULT_SUCCESS = 0, + BT_CORE_THREAD_RESULT_ERROR_INTERNAL = 1, +} bt_core_thread_result_t; + +typedef int bt_core_thread_id_t; + +typedef bt_core_thread_result_t (*bt_core_thread_create_t)( + int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority, bt_core_thread_id_t *thread_id); +typedef bt_core_thread_result_t (*bt_core_thread_join_t)(bt_core_thread_id_t thread_id, int *result); +typedef bt_core_thread_result_t (*bt_core_thread_destroy_t)(bt_core_thread_id_t thread_id); + +typedef struct bt_core_thread_api { + uint16_t version; + + struct { + bt_core_thread_create_t create; + bt_core_thread_join_t join; + bt_core_thread_destroy_t destroy; + } v1; +} bt_core_thread_api_t; + +#endif \ No newline at end of file diff --git a/src/api/hook.h b/src/api/hook.h new file mode 100644 index 00000000..1dd62bb6 --- /dev/null +++ b/src/api/hook.h @@ -0,0 +1,35 @@ +#ifndef BT_API_HOOK_H +#define BT_API_HOOK_H + +#include + +#include +#include +#include + +#include "api/core/config.h" + +typedef void (*bt_hook_iat_dll_name_get_t)(char *buffer, size_t size); +typedef bool (*bt_hook_pre_avs_init_t)(const bt_core_config_t *config); +// game module reference, either the exe or dll. allow for further targeted hooking/patching +// remark: you can't own the memory of the property_node config. whatever you need form that, make sure to copy the data and not just reference it. +// there is no guarantee the data is not free'd/gone after this call returns +// use the property api to iterate the data and parse it into your own custom configuration struct +// it is advised to also validate all parameters +// if no configuration was provided upon loading, the config_node contains an empty root node +typedef bool (*bt_hook_main_init_t)(HMODULE game_module, const bt_core_config_t *config); +typedef void (*bt_hook_main_fini_t)(); + +typedef struct bt_hook_api { + uint16_t version; + + struct { + // Optional + bt_hook_iat_dll_name_get_t iat_dll_name_get; + bt_hook_pre_avs_init_t pre_avs_init; + bt_hook_main_init_t main_init; + bt_hook_main_fini_t main_fini; + } v1; +} bt_hook_api_t; + +#endif \ No newline at end of file diff --git a/src/api/input.h b/src/api/input.h new file mode 100644 index 00000000..a193f7f9 --- /dev/null +++ b/src/api/input.h @@ -0,0 +1,28 @@ +#ifndef BT_API_INPUT_H +#define BT_API_INPUT_H + +#include +#include + +typedef bool (*bt_input_init_t)(); +typedef void (*bt_input_fini_t)(); +typedef bool (*bt_input_mapper_config_load_t)(const char *game_type); +typedef uint8_t (*bt_input_mapper_analog_read_t)(uint8_t analog); +typedef uint64_t (*bt_input_mapper_update_t)(); +typedef void (*bt_input_mapper_light_write_t)(uint8_t light, uint8_t intensity); + +typedef struct bt_input_api { + uint16_t version; + + struct { + // Required to be implemented + bt_input_init_t init; + bt_input_fini_t fini; + bt_input_mapper_config_load_t mapper_config_load; + bt_input_mapper_analog_read_t mapper_analog_read; + bt_input_mapper_update_t mapper_update; + bt_input_mapper_light_write_t mapper_light_write; + } v1; +} bt_input_api_t; + +#endif diff --git a/src/api/io.h b/src/api/io.h new file mode 100644 index 00000000..b88d5cfb --- /dev/null +++ b/src/api/io.h @@ -0,0 +1,20 @@ +#ifndef BT_API_IO_H +#define BT_API_IO_H + +#include +#include + +#include "api/core/config.h" + +typedef bool (*bt_io_configure_t)(const bt_core_config_t *config); + +typedef struct bt_io_api { + uint16_t version; + + struct { + // Optional + bt_io_configure_t configure; + } v1; +} bt_hook_api_t; + +#endif \ No newline at end of file diff --git a/src/api/io/bst.h b/src/api/io/bst.h new file mode 100644 index 00000000..752b2d51 --- /dev/null +++ b/src/api/io/bst.h @@ -0,0 +1,30 @@ +#ifndef BT_API_IO_BST_H +#define BT_API_IO_BST_H + +#include +#include + +typedef enum bt_io_bst_gpio_sys_bit { + BT_IO_BST_GPIO_SYS_COIN = 2, + BT_IO_BST_GPIO_SYS_TEST = 4, + BT_IO_BST_GPIO_SYS_SERVICE = 5, +} bt_io_bst_gpio_sys_bit_t; + +typedef bool (*bt_io_bst_init_t)(); +typedef void (*bt_io_bst_fini_t)(); +typedef bool (*bt_io_bst_input_read_t)(); +typedef uint8_t (*bt_io_bst_input_get_t)(); + +typedef struct bt_io_bst_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_bst_init_t init; + bt_io_bst_fini_t fini; + bt_io_bst_input_read_t input_read; + bt_io_bst_input_get_t input_get; + } v1; +} bt_io_bst_api_t; + +#endif \ No newline at end of file diff --git a/src/api/io/ddr.h b/src/api/io/ddr.h new file mode 100644 index 00000000..e22defe7 --- /dev/null +++ b/src/api/io/ddr.h @@ -0,0 +1,106 @@ +#ifndef BT_API_IO_DDR_H +#define BT_API_IO_DDR_H + +#include +#include + +typedef enum bt_io_ddr_pad_bit { + BT_IO_DDR_TEST = 0x04, + BT_IO_DDR_COIN = 0x05, + BT_IO_DDR_SERVICE = 0x06, + + BT_IO_DDR_P2_START = 0x08, + BT_IO_DDR_P2_UP = 0x09, + BT_IO_DDR_P2_DOWN = 0x0A, + BT_IO_DDR_P2_LEFT = 0x0B, + BT_IO_DDR_P2_RIGHT = 0x0C, + BT_IO_DDR_P2_MENU_LEFT = 0x0E, + BT_IO_DDR_P2_MENU_RIGHT = 0x0F, + BT_IO_DDR_P2_MENU_UP = 0x02, + BT_IO_DDR_P2_MENU_DOWN = 0x03, + + BT_IO_DDR_P1_START = 0x10, + BT_IO_DDR_P1_UP = 0x11, + BT_IO_DDR_P1_DOWN = 0x12, + BT_IO_DDR_P1_LEFT = 0x13, + BT_IO_DDR_P1_RIGHT = 0x14, + BT_IO_DDR_P1_MENU_LEFT = 0x16, + BT_IO_DDR_P1_MENU_RIGHT = 0x17, + BT_IO_DDR_P1_MENU_UP = 0x00, + BT_IO_DDR_P1_MENU_DOWN = 0x01, +} bt_io_ddr_pad_bit_t; + +// see the functions below for more information + +typedef enum bt_io_ddr_p3io_light_bit { + BT_IO_DDR_P3IO_LIGHT_P1_MENU = 0x00, + BT_IO_DDR_P3IO_LIGHT_P2_MENU = 0x01, + BT_IO_DDR_P3IO_LIGHT_P2_LOWER_LAMP = 0x04, + BT_IO_DDR_P3IO_LIGHT_P2_UPPER_LAMP = 0x05, + BT_IO_DDR_P3IO_LIGHT_P1_LOWER_LAMP = 0x06, + BT_IO_DDR_P3IO_LIGHT_P1_UPPER_LAMP = 0x07, +} bt_io_ddr_p3io_light_bit_t; + +typedef enum bt_io_ddr_hdxs_light_bit { + BT_IO_DDR_HDXS_LIGHT_HD_P1_START = 0x08, + BT_IO_DDR_HDXS_LIGHT_HD_P1_UP_DOWN = 0x09, + BT_IO_DDR_HDXS_LIGHT_HD_P1_LEFT_RIGHT = 0x0A, + BT_IO_DDR_HDXS_LIGHT_HD_P2_START = 0x0B, + BT_IO_DDR_HDXS_LIGHT_HD_P2_UP_DOWN = 0x0C, + BT_IO_DDR_HDXS_LIGHT_HD_P2_LEFT_RIGHT = 0x0D, +} bt_io_ddr_hdxs_light_bit_t; + +// the indexing starts from 0x20 if you're looking in geninput +typedef enum bt_io_ddr_hdxs_rgb_light_idx { + BT_IO_DDR_HDXS_LIGHT_HD_P1_SPEAKER_F_R = 0x00, + BT_IO_DDR_HDXS_LIGHT_HD_P1_SPEAKER_F_G = 0x01, + BT_IO_DDR_HDXS_LIGHT_HD_P1_SPEAKER_F_B = 0x02, + BT_IO_DDR_HDXS_LIGHT_HD_P2_SPEAKER_F_R = 0x03, + BT_IO_DDR_HDXS_LIGHT_HD_P2_SPEAKER_F_G = 0x04, + BT_IO_DDR_HDXS_LIGHT_HD_P2_SPEAKER_F_B = 0x05, + BT_IO_DDR_HDXS_LIGHT_HD_P1_SPEAKER_W_R = 0x06, + BT_IO_DDR_HDXS_LIGHT_HD_P1_SPEAKER_W_G = 0x07, + BT_IO_DDR_HDXS_LIGHT_HD_P1_SPEAKER_W_B = 0x08, + BT_IO_DDR_HDXS_LIGHT_HD_P2_SPEAKER_W_R = 0x09, + BT_IO_DDR_HDXS_LIGHT_HD_P2_SPEAKER_W_G = 0x0A, + BT_IO_DDR_HDXS_LIGHT_HD_P2_SPEAKER_W_B = 0x0B, +} bt_io_ddr_hdxs_rgb_light_idx_t; + +typedef enum bt_io_ddr_extio_light_bit { + BT_IO_DDR_EXTIO_LIGHT_NEONS = 0x0E, + + BT_IO_DDR_EXTIO_LIGHT_P2_RIGHT = 0x13, + BT_IO_DDR_EXTIO_LIGHT_P2_LEFT = 0x14, + BT_IO_DDR_EXTIO_LIGHT_P2_DOWN = 0x15, + BT_IO_DDR_EXTIO_LIGHT_P2_UP = 0x16, + + BT_IO_DDR_EXTIO_LIGHT_P1_RIGHT = 0x1B, + BT_IO_DDR_EXTIO_LIGHT_P1_LEFT = 0x1C, + BT_IO_DDR_EXTIO_LIGHT_P1_DOWN = 0x1D, + BT_IO_DDR_EXTIO_LIGHT_P1_UP = 0x1E +} bt_io_ddr_extio_light_bit_t; + +typedef bool (*bt_io_ddr_init_t)(); +typedef void (*bt_io_ddr_fini_t)(); +typedef uint32_t (*bt_io_ddr_pad_read_t)(); +typedef void (*bt_io_ddr_extio_lights_set_t)(uint32_t extio_lights); +typedef void (*bt_io_ddr_p3io_lights_set_t)(uint32_t p3io_lights); +typedef void (*bt_io_ddr_hdxs_lights_panel_set_t)(uint32_t hdxs_lights); +typedef void (*bt_io_ddr_hdxs_lights_rgb_set_t)(uint8_t idx, uint8_t r, uint8_t g, uint8_t b); + +typedef struct bt_io_ddr_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_ddr_init_t init; + bt_io_ddr_fini_t fini; + bt_io_ddr_pad_read_t pad_read; + bt_io_ddr_extio_lights_set_t extio_lights_set; + bt_io_ddr_p3io_lights_set_t p3io_lights_set; + bt_io_ddr_hdxs_lights_panel_set_t hdxs_lights_panel_set; + bt_io_ddr_hdxs_lights_rgb_set_t hdxs_lights_rgb_set; + } v1; +} bt_io_ddr_api_t; + +#endif diff --git a/src/api/io/eam.h b/src/api/io/eam.h new file mode 100644 index 00000000..7bd4c456 --- /dev/null +++ b/src/api/io/eam.h @@ -0,0 +1,88 @@ +#ifndef BT_API_IO_EAM_H +#define BT_API_IO_EAM_H + +/* Card reader emulator API. You may replace the stock EAMIO.DLL supplied by + Bemanitools with your own custom implementation, which should implement the + interface contract defined in this header file. */ + +#include +#include + +/* Scan codes for the so-called "10 key" button panel on each card reader. Each + scan code corresponds to a bit position within the 16-bit bitfield that you + return from eam_io_get_keypad_state(). */ + +typedef enum bt_io_eam_keypad_scan_code { + BT_IO_EAM_KEYPAD_SCAN_CODE_0 = 0, + BT_IO_EAM_KEYPAD_SCAN_CODE_1 = 1, + BT_IO_EAM_KEYPAD_SCAN_CODE_4 = 2, + BT_IO_EAM_KEYPAD_SCAN_CODE_7 = 3, + BT_IO_EAM_KEYPAD_SCAN_CODE_00 = 4, + BT_IO_EAM_KEYPAD_SCAN_CODE_2 = 5, + BT_IO_EAM_KEYPAD_SCAN_CODE_5 = 6, + BT_IO_EAM_KEYPAD_SCAN_CODE_8 = 7, + BT_IO_EAM_KEYPAD_SCAN_CODE_DECIMAL = 8, + BT_IO_EAM_KEYPAD_SCAN_CODE_3 = 9, + BT_IO_EAM_KEYPAD_SCAN_CODE_6 = 10, + BT_IO_EAM_KEYPAD_SCAN_CODE_9 = 11, + + BT_IO_EAM_KEYPAD_COUNT = 12, /* Not an actual scan code */ +} bt_io_eam_keypad_scan_code_t; + +/* Emulating the sensors of a slotted card reader. The reader has one + sensor at the front that detects if a card is getting inserted or + if the card is not fully removed. When the back sensor is triggered + the card is locked in the slot and its data is read. */ + +typedef enum bt_io_eam_sensor_state { + BT_IO_EAM_SENSOR_STATE_FRONT = 0, + BT_IO_EAM_SENSOR_STATE_BACK = 1, +} bt_io_eam_sensor_state_t; + +/* Different commands for the (slotted) reader. The game triggers one + of these actions and the card slot as to execute it. When non-slotted + readers are emulated, these states are not used/set. */ + +typedef enum bt_io_eam_card_slot_cmd { + BT_IO_EAM_CARD_SLOT_CMD_CLOSE = 0, + BT_IO_EAM_CARD_SLOT_CMD_OPEN = 1, + BT_IO_EAM_CARD_SLOT_CMD_EJECT = 2, + BT_IO_EAM_CARD_SLOT_CMD_READ = 3, +} bt_io_eam_card_slot_cmd_t; + +/* Emulating of the card type for new readers. */ + +typedef enum bt_io_eam_read_card_result { + BT_IO_EAM_READ_CARD_RESULT_NONE = 0, + BT_IO_EAM_READ_CARD_RESULT_ISO15696 = 1, + BT_IO_EAM_READ_CARD_RESULT_FELICA = 2, +} bt_io_eam_read_card_result_t; + +typedef struct bt_io_eam_config_api bt_io_eam_config_api_t; + +typedef bool (*bt_io_eam_init_t)(); +typedef void (*bt_io_eam_fini_t)(); +typedef uint16_t (*bt_io_eam_keypad_state_get_t)(uint8_t unit_no); +typedef uint8_t (*bt_io_eam_sensor_state_get_t)(uint8_t unit_no); +typedef uint8_t (*bt_io_eam_card_read_t)(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes); +typedef bool (*bt_io_eam_card_slot_cmd_send_t)(uint8_t unit_no, uint8_t cmd); +typedef bool (*bt_io_eam_poll_t)(uint8_t unit_no); +typedef const bt_io_eam_config_api_t *(*bt_io_eam_config_api_get_t)(); + +typedef struct bt_io_eam_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_eam_init_t init; + bt_io_eam_fini_t fini; + bt_io_eam_keypad_state_get_t keypad_state_get; + bt_io_eam_sensor_state_get_t sensor_state_get; + bt_io_eam_card_read_t card_read; + bt_io_eam_card_slot_cmd_send_t card_slot_cmd_send; + bt_io_eam_poll_t poll; + bt_io_eam_config_api_get_t config_api_get; + } v1; +} bt_io_eam_api_t; + +#endif diff --git a/src/api/io/iidx.h b/src/api/io/iidx.h new file mode 100644 index 00000000..1187f3b2 --- /dev/null +++ b/src/api/io/iidx.h @@ -0,0 +1,122 @@ +#ifndef BT_API_IO_IIDX_H +#define BT_API_IO_IIDX_H + +/* IO emulation provider for beatmania IIDX. */ + +#include +#include + +/* Bit mapping for the "pad" word */ + +typedef enum bt_io_iidx_sys_bit { + BT_IO_IIDX_SYS_TEST = 0x00, + BT_IO_IIDX_SYS_SERVICE = 0x01, + BT_IO_IIDX_SYS_COIN = 0x02 +} bt_io_iidx_sys_bit_t; + +typedef enum bt_io_iidx_panel_bit { + BT_IO_IIDX_PANEL_P1_START = 0x00, + BT_IO_IIDX_PANEL_P2_START = 0x01, + BT_IO_IIDX_PANEL_VEFX = 0x02, + BT_IO_IIDX_PANEL_EFFECT = 0x03 +} bt_io_iidx_panel_bit_t; + +typedef enum bt_io_iidx_key_bit { + BT_IO_IIDX_KEY_P1_1 = 0x00, + BT_IO_IIDX_KEY_P1_2 = 0x01, + BT_IO_IIDX_KEY_P1_3 = 0x02, + BT_IO_IIDX_KEY_P1_4 = 0x03, + BT_IO_IIDX_KEY_P1_5 = 0x04, + BT_IO_IIDX_KEY_P1_6 = 0x05, + BT_IO_IIDX_KEY_P1_7 = 0x06, + + BT_IO_IIDX_KEY_P2_1 = 0x07, + BT_IO_IIDX_KEY_P2_2 = 0x08, + BT_IO_IIDX_KEY_P2_3 = 0x09, + BT_IO_IIDX_KEY_P2_4 = 0x0A, + BT_IO_IIDX_KEY_P2_5 = 0x0B, + BT_IO_IIDX_KEY_P2_6 = 0x0C, + BT_IO_IIDX_KEY_P2_7 = 0x0D +} bt_io_iidx_key_bit_t; + +/* Bit mapping for the P1 and P2 deck lights */ + +typedef enum bt_io_iidx_deck_light { + BT_IO_IIDX_DECK_LIGHT_P1_1 = 0, + BT_IO_IIDX_DECK_LIGHT_P1_2 = 1, + BT_IO_IIDX_DECK_LIGHT_P1_3 = 2, + BT_IO_IIDX_DECK_LIGHT_P1_4 = 3, + BT_IO_IIDX_DECK_LIGHT_P1_5 = 4, + BT_IO_IIDX_DECK_LIGHT_P1_6 = 5, + BT_IO_IIDX_DECK_LIGHT_P1_7 = 6, + + BT_IO_IIDX_DECK_LIGHT_P2_1 = 8, + BT_IO_IIDX_DECK_LIGHT_P2_2 = 9, + BT_IO_IIDX_DECK_LIGHT_P2_3 = 10, + BT_IO_IIDX_DECK_LIGHT_P2_4 = 11, + BT_IO_IIDX_DECK_LIGHT_P2_5 = 12, + BT_IO_IIDX_DECK_LIGHT_P2_6 = 13, + BT_IO_IIDX_DECK_LIGHT_P2_7 = 14, +} bt_io_iidx_deck_light_t; + +/* Bit mapping for the front panel lights */ + +typedef enum bt_io_iidx_panel_light { + BT_IO_IIDX_PANEL_LIGHT_P1_START = 0, + BT_IO_IIDX_PANEL_LIGHT_P2_START = 1, + BT_IO_IIDX_PANEL_LIGHT_VEFX = 2, + BT_IO_IIDX_PANEL_LIGHT_EFFECT = 3, +} bt_io_iidx_panel_light_t; + +/* Bit mapping for the top lamps from left to right when facing cabinet screen + */ + +typedef enum bt_io_iidx_top_lamp { + BT_IO_IIDX_TOP_LAMP_LEFT_BLUE = 0, + BT_IO_IIDX_TOP_LAMP_LEFT_GREEN = 1, + BT_IO_IIDX_TOP_LAMP_LEFT_YELLOW = 2, + BT_IO_IIDX_TOP_LAMP_LEFT_RED = 3, + BT_IO_IIDX_TOP_LAMP_RIGHT_BLUE = 4, + BT_IO_IIDX_TOP_LAMP_RIGHT_GREEN = 5, + BT_IO_IIDX_TOP_LAMP_RIGHT_YELLOW = 6, + BT_IO_IIDX_TOP_LAMP_RIGHT_RED = 7, +} bt_io_iidx_top_lamp_t; + +typedef bool (*bt_io_iidx_init_t)(); +typedef void (*bt_io_iidx_fini_t)(); +typedef void (*bt_io_iidx_ep1_deck_lights_set_t)(uint16_t deck_lights); +typedef void (*bt_io_iidx_ep1_panel_lights_set_t)(uint8_t panel_lights); +typedef void (*bt_io_iidx_ep1_top_lamps_set_t)(uint8_t top_lamps); +typedef void (*bt_io_iidx_ep1_top_neons_set_t)(bool top_neons); +typedef bool (*bt_io_iidx_ep1_send_t)(); +typedef bool (*bt_io_iidx_ep2_recv_t)(); +typedef uint8_t (*bt_io_iidx_ep2_turntable_get_t)(uint8_t player_no); +typedef uint8_t (*bt_io_iidx_ep2_slider_get_t)(uint8_t slider_no); +typedef uint8_t (*bt_io_iidx_ep2_sys_get_t)(); +typedef uint8_t (*bt_io_iidx_ep2_panel_get_t)(); +typedef uint16_t (*bt_io_iidx_ep2_keys_get_t)(); +typedef bool (*bt_io_iidx_ep3_16seg_send_t)(const char *text); + +typedef struct bt_io_iidx_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_iidx_init_t init; + bt_io_iidx_fini_t fini; + bt_io_iidx_ep1_deck_lights_set_t ep1_deck_lights_set; + bt_io_iidx_ep1_panel_lights_set_t ep1_panel_lights_set; + bt_io_iidx_ep1_top_lamps_set_t ep1_top_lamps_set; + bt_io_iidx_ep1_top_neons_set_t ep1_top_neons_set; + bt_io_iidx_ep1_send_t ep1_send; + bt_io_iidx_ep2_recv_t ep2_recv; + bt_io_iidx_ep2_turntable_get_t ep2_turntable_get; + bt_io_iidx_ep2_slider_get_t ep2_slider_get; + bt_io_iidx_ep2_sys_get_t ep2_sys_get; + bt_io_iidx_ep2_panel_get_t ep2_panel_get; + bt_io_iidx_ep2_keys_get_t ep2_keys_get; + bt_io_iidx_ep3_16seg_send_t ep3_16seg_send; + } v1; +} bt_io_iidx_api_t; + +#endif diff --git a/src/api/io/jb.h b/src/api/io/jb.h new file mode 100644 index 00000000..5359a2e0 --- /dev/null +++ b/src/api/io/jb.h @@ -0,0 +1,85 @@ +#ifndef BT_API_IO_JB_H +#define BT_API_IO_JB_H + +/* IO emulation provider for jubeat. */ + +#include +#include + +/* input bit mappings. Panels on the controller are + panel 1 top left corner down to panel 16 bottom right corner */ +typedef enum bt_io_jb_panel_bit { + BT_IO_JB_PANEL_01 = 0x00, + BT_IO_JB_PANEL_02 = 0x01, + BT_IO_JB_PANEL_03 = 0x02, + BT_IO_JB_PANEL_04 = 0x03, + BT_IO_JB_PANEL_05 = 0x04, + BT_IO_JB_PANEL_06 = 0x05, + BT_IO_JB_PANEL_07 = 0x06, + BT_IO_JB_PANEL_08 = 0x07, + BT_IO_JB_PANEL_09 = 0x08, + BT_IO_JB_PANEL_10 = 0x09, + BT_IO_JB_PANEL_11 = 0x0A, + BT_IO_JB_PANEL_12 = 0x0B, + BT_IO_JB_PANEL_13 = 0x0C, + BT_IO_JB_PANEL_14 = 0x0D, + BT_IO_JB_PANEL_15 = 0x0E, + BT_IO_JB_PANEL_16 = 0x0F, +} bt_io_jb_panel_bit_t; + +/* input "single button mode" mappings. Allows you to check each corner of each + button to determine any flaky inputs +*/ +typedef enum bt_io_jb_panel_mode { + BT_IO_JB_PANEL_MODE_ALL = 0, // any of the four corners will trigger a panel + BT_IO_JB_PANEL_MODE_TOP_LEFT = 1, + BT_IO_JB_PANEL_MODE_TOP_RIGHT = 2, + BT_IO_JB_PANEL_MODE_BOTTOM_RIGHT = 3, + BT_IO_JB_PANEL_MODE_BOTTOM_LEFT = 4, +} bt_io_jb_panel_mode_t; + +/* Bit mappings for "system" inputs */ +typedef enum bt_io_jb_sys_bit { + BT_IO_JB_SYS_TEST = 0x00, + BT_IO_JB_SYS_SERVICE = 0x01, + BT_IO_JB_SYS_COIN = 0x02, +} bt_io_jb_sys_bit_t; + +/* RGB led units to address */ +typedef enum bt_io_jb_rgb_led { + BT_IO_JB_RGB_LED_FRONT = 0, + BT_IO_JB_RGB_LED_TOP = 1, + BT_IO_JB_RGB_LED_LEFT = 2, + BT_IO_JB_RGB_LED_RIGHT = 3, + BT_IO_JB_RGB_LED_TITLE = 4, + BT_IO_JB_RGB_LED_WOOFER = 5 +} bt_io_jb_rgb_led_t; + +typedef bool (*bt_io_jb_init_t)(); +typedef void (*bt_io_jb_fini_t)(); +typedef bool (*bt_io_jb_inputs_read_t)(); +typedef uint8_t (*bt_io_jb_sys_inputs_get_t)(); +typedef uint16_t (*bt_io_jb_panel_inputs_get_t)(); +typedef void (*bt_io_jb_rgb_led_set_t)(bt_io_jb_rgb_led_t unit, uint8_t r, uint8_t g, uint8_t b); +typedef bool (*bt_io_jb_lights_write_t)(); +typedef bool (*bt_io_jb_panel_mode_set_t)(bt_io_jb_panel_mode_t mode); +typedef bool (*bt_io_jb_coin_blocker_set_t)(bool blocked); + +typedef struct bt_io_jb_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_jb_init_t init; + bt_io_jb_fini_t fini; + bt_io_jb_inputs_read_t inputs_read; + bt_io_jb_sys_inputs_get_t sys_inputs_get; + bt_io_jb_panel_inputs_get_t panel_inputs_get; + bt_io_jb_rgb_led_set_t rgb_led_set; + bt_io_jb_lights_write_t lights_write; + bt_io_jb_panel_mode_set_t panel_mode_set; + bt_io_jb_coin_blocker_set_t coin_blocker_set; + } v1; +} bt_io_jb_api_t; + +#endif diff --git a/src/api/io/popn.h b/src/api/io/popn.h new file mode 100644 index 00000000..388f7eaa --- /dev/null +++ b/src/api/io/popn.h @@ -0,0 +1,80 @@ +#ifndef BT_API_IO_POPN_H +#define BT_API_IO_POPN_H + +/* IO emulation provider for pop'n music. */ + +#include +#include + +/* Bit mapping for the "buttons" word */ + +typedef enum bt_io_popn_sys_bit { + BT_IO_POPN_SYS_SERVICE = 0x06, + BT_IO_POPN_SYS_TEST = 0x07, +} bt_io_popn_sys_bit_t; + +typedef enum bt_io_popn_button_bit { + BT_IO_POPN_BUTTON_1 = 0x08, + BT_IO_POPN_BUTTON_2 = 0x09, + BT_IO_POPN_BUTTON_3 = 0x0a, + BT_IO_POPN_BUTTON_4 = 0x0b, + BT_IO_POPN_BUTTON_5 = 0x0c, + BT_IO_POPN_BUTTON_6 = 0x0d, + BT_IO_POPN_BUTTON_7 = 0x0e, + BT_IO_POPN_BUTTON_8 = 0x0f, + BT_IO_POPN_BUTTON_9 = 0x10, +} bt_io_popn_button_bit_t; + +typedef enum bt_io_popn_light_top_lamp_bit { + BT_IO_POPN_LIGHT_HI_LAMP1 = 0x00, + BT_IO_POPN_LIGHT_HI_LAMP2 = 0x01, + BT_IO_POPN_LIGHT_HI_LAMP3 = 0x02, + BT_IO_POPN_LIGHT_HI_LAMP4 = 0x03, + BT_IO_POPN_LIGHT_HI_LAMP5 = 0x04, +} bt_io_popn_light_top_lamp_bit_t; + +typedef enum bt_io_popn_light_side_lamp_bit { + BT_IO_POPN_LIGHT_LEFT_LAMP1 = 0x00, + BT_IO_POPN_LIGHT_LEFT_LAMP2 = 0x01, + BT_IO_POPN_LIGHT_RIGHT_LAMP1 = 0x02, + BT_IO_POPN_LIGHT_RIGHT_LAMP2 = 0x03, +} bt_io_popn_light_side_lamp_bit_t; + +typedef enum bt_io_popn_light_switch_lamp_bit { + BT_IO_POPN_LIGHT_SW_LAMP1 = 0x00, // Is actually 4 bits wide + BT_IO_POPN_LIGHT_SW_LAMP2 = 0x04, + BT_IO_POPN_LIGHT_SW_LAMP3 = 0x05, + BT_IO_POPN_LIGHT_SW_LAMP4 = 0x06, + BT_IO_POPN_LIGHT_SW_LAMP5 = 0x07, + BT_IO_POPN_LIGHT_SW_LAMP6 = 0x08, + BT_IO_POPN_LIGHT_SW_LAMP7 = 0x09, + BT_IO_POPN_LIGHT_SW_LAMP8 = 0x0a, + BT_IO_POPN_LIGHT_SW_LAMP9 = 0x0b, +} bt_io_popn_light_switch_lamp_bit_t; + +typedef bool (*bt_io_popn_init_t)(); +typedef void (*bt_io_popn_fini_t)(); +typedef uint32_t (*bt_io_popn_buttons_get_t)(); +typedef void (*bt_io_popn_top_lights_set_t)(uint32_t lights); +typedef void (*bt_io_popn_side_lights_set_t)(uint32_t lights); +typedef void (*bt_io_popn_button_lights_set_t)(uint32_t lights); +typedef void (*bt_io_popn_coin_blocker_light_set_t)(bool enabled); +typedef void (*bt_io_popn_coin_counter_light_set_t)(bool enabled); + +typedef struct bt_io_popn_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_popn_init_t init; + bt_io_popn_fini_t fini; + bt_io_popn_buttons_get_t buttons_get; + bt_io_popn_top_lights_set_t top_lights_set; + bt_io_popn_side_lights_set_t side_lights_set; + bt_io_popn_button_lights_set_t button_lights_set; + bt_io_popn_coin_blocker_light_set_t coin_blocker_light_set; + bt_io_popn_coin_counter_light_set_t coin_counter_light_set; + } v1; +} bt_io_popn_api_t; + +#endif diff --git a/src/api/io/sdvx.h b/src/api/io/sdvx.h new file mode 100644 index 00000000..a60f2488 --- /dev/null +++ b/src/api/io/sdvx.h @@ -0,0 +1,70 @@ +#ifndef BT_API_IO_SDVX_H +#define BT_API_IO_SDVX_H + +/* IO emulation provider for SOUND VOLTEX */ + +#include +#include + +typedef enum bt_io_sdvx_in_gpio_sys_bit { + BT_IO_SDVX_IN_GPIO_SYS_COIN = 2, + BT_IO_SDVX_IN_GPIO_SYS_SERVICE = 4, + BT_IO_SDVX_IN_GPIO_SYS_TEST = 5, +} bt_io_sdvx_in_gpio_sys_bit_t; + +typedef enum bt_io_sdvx_in_gpio_0_bit { + BT_IO_SDVX_IN_GPIO_0_C = 0, + BT_IO_SDVX_IN_GPIO_0_B = 1, + BT_IO_SDVX_IN_GPIO_0_A = 2, + BT_IO_SDVX_IN_GPIO_0_START = 3, + BT_IO_SDVX_IN_GPIO_0_RECORDER = 4, + BT_IO_SDVX_IN_GPIO_0_HEADPHONE = 5, +} bt_io_sdvx_in_gpio_0_bit_t; + +typedef enum bt_io_sdvx_in_gpio_1_bit { + BT_IO_SDVX_IN_GPIO_1_FX_R = 3, + BT_IO_SDVX_IN_GPIO_1_FX_L = 4, + BT_IO_SDVX_IN_GPIO_1_D = 5, +} bt_io_sdvx_in_gpio_1_bit_t; + +typedef enum bt_io_sdvx_out_gpio_bit { + BT_IO_SDVX_OUT_GPIO_D = 0, + BT_IO_SDVX_OUT_GPIO_FX_L = 1, + BT_IO_SDVX_OUT_GPIO_FX_R = 2, + BT_IO_SDVX_OUT_GPIO_GENERATOR_B = 3, + BT_IO_SDVX_OUT_GPIO_START = 12, + BT_IO_SDVX_OUT_GPIO_A = 13, + BT_IO_SDVX_OUT_GPIO_B = 14, + BT_IO_SDVX_OUT_GPIO_C = 15, +} bt_io_sdvx_out_gpio_bit_t; + +typedef bool (*bt_io_sdvx_init_t)(); +typedef void (*bt_io_sdvx_fini_t)(); +typedef void (*bt_io_sdvx_gpio_lights_set_t)(uint32_t gpio_lights); +typedef void (*bt_io_sdvx_pwm_light_set_t)(uint8_t light_no, uint8_t intensity); +typedef bool (*bt_io_sdvx_output_write_t)(); +typedef bool (*bt_io_sdvx_input_read_t)(); +typedef uint8_t (*bt_io_sdvx_input_gpio_sys_get_t)(); +typedef uint16_t (*bt_io_sdvx_input_gpio_get_t)(uint8_t gpio_bank); +typedef uint16_t (*bt_io_sdvx_spinner_pos_get_t)(uint8_t spinner_no); +typedef bool (*bt_io_sdvx_amp_volume_set_t)(uint8_t primary, uint8_t headphone, uint8_t subwoofer); + +typedef struct bt_io_sdvx_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_sdvx_init_t init; + bt_io_sdvx_fini_t fini; + bt_io_sdvx_gpio_lights_set_t gpio_lights_set; + bt_io_sdvx_pwm_light_set_t pwm_light_set; + bt_io_sdvx_output_write_t output_write; + bt_io_sdvx_input_read_t input_read; + bt_io_sdvx_input_gpio_sys_get_t input_gpio_sys_get; + bt_io_sdvx_input_gpio_get_t input_gpio_get; + bt_io_sdvx_spinner_pos_get_t spinner_pos_get; + bt_io_sdvx_amp_volume_set_t amp_volume_set; + } v1; +} bt_io_sdvx_api_t; + +#endif diff --git a/src/api/io/vefx.h b/src/api/io/vefx.h new file mode 100644 index 00000000..362a3c14 --- /dev/null +++ b/src/api/io/vefx.h @@ -0,0 +1,28 @@ +#ifndef BT_API_IO_VEFX_H +#define BT_API_IO_VEFX_H + +/* IO emulation provider for beatmania IIDX Effector Panel. */ + +#include +#include + +typedef bool (*bt_io_vefx_init_t)(); +typedef void (*bt_io_vefx_fini_t)(); +typedef bool (*bt_io_vefx_recv_t)(uint64_t *ppad); +typedef uint8_t (*bt_io_vefx_slider_get_t)(uint8_t slider_no); +typedef bool (*bt_io_vefx_16seg_send_t)(const char *text); + +typedef struct bt_io_vefx_api { + uint16_t version; + + struct { + // Required to be implemented + bt_io_vefx_init_t init; + bt_io_vefx_fini_t fini; + bt_io_vefx_recv_t recv; + bt_io_vefx_slider_get_t slider_get; + bt_io_vefx_16seg_send_t _16seg_send; + } v1; +} bt_io_vefx_api_t; + +#endif diff --git a/src/imports/avs.h b/src/imports/avs.h index ae054e5c..2e6ddc7b 100644 --- a/src/imports/avs.h +++ b/src/imports/avs.h @@ -142,7 +142,7 @@ typedef void (*avs_log_writer_t)(const char *chars, uint32_t nchars, void *ctx); typedef void (*avs_log_writer_t)(void *ctx, const char *chars, uint32_t nchars); #endif -typedef int (*avs_reader_t)(uint32_t context, void *bytes, size_t nbytes); +typedef size_t (*avs_reader_t)(uint32_t context, void *bytes, size_t nbytes); #if AVS_VERSION >= 1600 /* "avs" and "std" heaps have been unified */ @@ -186,7 +186,7 @@ void avs_shutdown(void); typedef uint32_t avs_desc; typedef int avs_error; -#define AVS_IS_ERROR(x) x < 0 +#define AVS_IS_ERROR(x) ((avs_error) x) < 0 void log_body_fatal(const char *module, const char *fmt, ...); void log_body_info(const char *module, const char *fmt, ...); @@ -223,12 +223,12 @@ void property_destroy(struct property *prop); avs_error property_get_error(struct property *prop); void property_clear_error(struct property *prop); -int property_psmap_import( +avs_error property_psmap_import( struct property *prop, struct property_node *root, void *dest, const struct property_psmap *psmap); -int property_psmap_export( +avs_error property_psmap_export( struct property *prop, struct property_node *root, const void *src, @@ -254,7 +254,7 @@ int property_node_refer( enum property_type type, void *bytes, uint32_t nbytes); -void property_node_remove(struct property_node *node); +avs_error 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); @@ -315,7 +315,7 @@ enum avs_seek_origin { 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); +size_t avs_fs_read(avs_desc desc, void *buf, size_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); 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_1101_avs.def b/src/imports/import_32_1101_avs.def index 776dc712..332c0f2f 100644 --- a/src/imports/import_32_1101_avs.def +++ b/src/imports/import_32_1101_avs.def @@ -26,8 +26,8 @@ EXPORTS property_desc_to_buffer @246 NONAME property_destroy @247 NONAME property_insert_read @255 NONAME - property_clear_error @573 NONAME - property_get_error @573 NONAME + property_clear_error @244 NONAME + property_get_error @253 NONAME property_node_create @266 NONAME property_node_datasize @267 NONAME property_node_name @274 NONAME @@ -35,8 +35,8 @@ EXPORTS 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_clone @265 NONAME + property_node_traversal @281 NONAME property_node_refdata @277 NONAME property_query_size @290 NONAME property_psmap_import @288 NONAME diff --git a/src/imports/import_32_1304_avs.def b/src/imports/import_32_1304_avs.def index 18dad23a..cff9b299 100644 --- a/src/imports/import_32_1304_avs.def +++ b/src/imports/import_32_1304_avs.def @@ -1,46 +1,46 @@ 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 - avs_thread_destroy @76 NONAME - avs_thread_exit @147 NONAME - avs_thread_join @92 NONAME - log_body_misc @44 NONAME - log_body_info @339 NONAME - log_body_warning @219 NONAME - log_body_fatal @128 NONAME - property_create @256 NONAME - property_desc_to_buffer @201 NONAME - property_destroy @264 NONAME - property_insert_read @23 NONAME - property_clear_error @573 NONAME - property_get_error @573 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 + 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_clear_error @163 NONAME == XC058ba50000a7 + property_get_error @295 NONAME == XC058ba500012e + 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 - property_psmap_export @110 NONAME - property_read_query_memsize @100 NONAME - property_search @244 NONAME - std_getenv @226 NONAME - std_setenv @114 NONAME + 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_1306_avs.def b/src/imports/import_32_1306_avs.def index f6deed72..cff9b299 100644 --- a/src/imports/import_32_1306_avs.def +++ b/src/imports/import_32_1306_avs.def @@ -25,8 +25,8 @@ EXPORTS property_desc_to_buffer @201 NONAME == XC058ba50000cd property_destroy @264 NONAME == XC058ba500010f property_insert_read @23 NONAME == XC058ba5000016 - property_clear_error @573 NONAME - property_get_error @573 NONAME + property_clear_error @163 NONAME == XC058ba50000a7 + property_get_error @295 NONAME == XC058ba500012e property_node_create @316 NONAME == XC058ba5000143 property_node_datasize @249 NONAME == XC058ba5000100 property_node_name @255 NONAME == XC058ba5000106 diff --git a/src/imports/import_32_1508_avs.def b/src/imports/import_32_1508_avs.def index 504a303f..f7a74632 100644 --- a/src/imports/import_32_1508_avs.def +++ b/src/imports/import_32_1508_avs.def @@ -6,8 +6,8 @@ EXPORTS 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_open @58 NONAME == XCd229cc000090 + avs_fs_read @61 NONAME == XCd229cc00010d avs_fs_copy @81 NONAME avs_fs_opendir @72 NONAME == XCd229cc0000f0 avs_fs_readdir @73 NONAME == XCd229cc0000bb @@ -26,8 +26,8 @@ EXPORTS property_desc_to_buffer @129 NONAME property_destroy @128 NONAME property_insert_read @131 NONAME - property_clear_error @573 NONAME - property_get_error @573 NONAME + property_clear_error @140 NONAME == XCd229cc00014b + property_get_error @141 NONAME == XCd229cc0000b5 property_node_create @145 NONAME property_node_name @150 NONAME property_node_read @154 NONAME == XCd229cc0000f3 @@ -41,7 +41,7 @@ EXPORTS property_query_size @142 NONAME == XCd229cc000032 property_psmap_export @162 NONAME property_psmap_import @161 NONAME - property_read_query_memsize @159 NONAME + property_read_query_memsize @159 NONAME == XCd229cc0000ff property_search @144 NONAME std_getenv @207 NONAME std_setenv @208 NONAME diff --git a/src/imports/import_32_1601_avs.def b/src/imports/import_32_1601_avs.def index 286806bf..4921e35c 100644 --- a/src/imports/import_32_1601_avs.def +++ b/src/imports/import_32_1601_avs.def @@ -5,8 +5,8 @@ EXPORTS 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_open @58 NONAME == XCnbrep7000039 + avs_fs_read @61 NONAME == XCnbrep700003c avs_fs_opendir @72 NONAME == XCnbrep7000047 avs_fs_readdir @73 NONAME == XCnbrep7000048 avs_fs_closedir @74 NONAME == XCnbrep7000049 @@ -19,8 +19,8 @@ EXPORTS property_destroy @125 NONAME property_desc_to_buffer @126 NONAME property_insert_read @128 NONAME - property_clear_error @573 NONAME - property_get_error @573 NONAME + property_clear_error @137 NONAME == XCnbrep7000088 + property_get_error @138 NONAME == XCnbrep7000089 property_search @141 NONAME property_node_create @142 NONAME property_node_name @147 NONAME == XCnbrep7000092 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_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/acio-mgr/Module.mk b/src/main/acio-mgr/Module.mk new file mode 100644 index 00000000..4f02bc83 --- /dev/null +++ b/src/main/acio-mgr/Module.mk @@ -0,0 +1,11 @@ +dlls += acio-mgr + +libs_acio-mgr := \ + aciodrv \ + iface-core \ + core \ + util \ + +src_acio-mgr := \ + dllmain.c \ + mgr.c \ diff --git a/src/main/acio-mgr/acio-mgr.def b/src/main/acio-mgr/acio-mgr.def new file mode 100644 index 00000000..1b99720f --- /dev/null +++ b/src/main/acio-mgr/acio-mgr.def @@ -0,0 +1,20 @@ +LIBRARY acio-mgr + +EXPORTS + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_acio_mgr_api_get + + ; Not exporting as these are called in DllMain + ; bt_acio_mgr_init + ; bt_acio_mgr_fini + DllMain@12 @1 NONAME + + ; Direct API + bt_acio_mgr_port_init + bt_acio_mgr_port_fini + bt_acio_mgr_node_count_get + bt_acio_mgr_node_product_ident_get + bt_acio_mgr_port_packet_submit + bt_acio_mgr_port_checkout + bt_acio_mgr_port_checkin diff --git a/src/main/aciomgr/dllmain.c b/src/main/acio-mgr/dllmain.c similarity index 69% rename from src/main/aciomgr/dllmain.c rename to src/main/acio-mgr/dllmain.c index 9ab5aa92..37cd4df2 100644 --- a/src/main/aciomgr/dllmain.c +++ b/src/main/acio-mgr/dllmain.c @@ -1,15 +1,15 @@ #include -#include "manager-init.h" +#include "acio-mgr/internal.h" BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - _aciomgr_init(); + bt_acio_mgr_init(); } if (reason == DLL_PROCESS_DETACH) { - _aciomgr_fini(); + bt_acio_mgr_fini(); } return TRUE; diff --git a/src/main/acio-mgr/internal.h b/src/main/acio-mgr/internal.h new file mode 100644 index 00000000..0a4d7a4a --- /dev/null +++ b/src/main/acio-mgr/internal.h @@ -0,0 +1,7 @@ +#ifndef ACIO_MGR_INTERNAL_T +#define ACIO_MGR_INTERNAL_T + +void bt_acio_mgr_init(); +void bt_acio_mgr_fini(); + +#endif \ No newline at end of file diff --git a/src/main/aciomgr/manager.c b/src/main/acio-mgr/mgr.c similarity index 59% rename from src/main/aciomgr/manager.c rename to src/main/acio-mgr/mgr.c index e73b18e2..ea40cfa5 100644 --- a/src/main/aciomgr/manager.c +++ b/src/main/acio-mgr/mgr.c @@ -4,39 +4,43 @@ #include -#include "aciomgr/manager-init.h" +#include "acio/acio.h" +#include "aciodrv/device.h" -#include "aciomgr/manager.h" +#include "acio-mgr/internal.h" -#include "acio/acio.h" +#include "api/core/log.h" + +#include "iface-core/log.h" + +#include "sdk/module/acio/mgr.h" +#include "sdk/module/core/log.h" -#include "aciodrv/device.h" #include "util/array.h" -#include "util/log.h" #define MAX_PORT_PATH_LENGTH 256 -struct aciomgr_port_dispatcher { +typedef struct bt_acio_mgr_port_dispatcher { CRITICAL_SECTION cs; atomic_size_t references; struct aciodrv_device_ctx *device; char path[MAX_PORT_PATH_LENGTH]; int baud; bool has_failure; -}; +} bt_acio_mgr_port_dispatcher_t; -static void _aciomgr_setup_port_dispatcher( - struct aciomgr_port_dispatcher *dispatcher, const char *path, int baud); +static void _bt_acio_mgr_setup_port_dispatcher( + bt_acio_mgr_port_dispatcher_t *dispatcher, const char *path, int baud); static void -_aciomgr_destroy_port_dispatcher(struct aciomgr_port_dispatcher *dispatcher); +_bt_acio_mgr_destroy_port_dispatcher(bt_acio_mgr_port_dispatcher_t *dispatcher); // DLL-globals static atomic_bool running; static CRITICAL_SECTION mgr_cs; static struct array active_ports; -static void _aciomgr_setup_port_dispatcher( - struct aciomgr_port_dispatcher *dispatcher, const char *path, int baud) +static void _bt_acio_mgr_setup_port_dispatcher( + bt_acio_mgr_port_dispatcher_t *dispatcher, const char *path, int baud) { InitializeCriticalSection(&dispatcher->cs); @@ -55,17 +59,17 @@ static void _aciomgr_setup_port_dispatcher( } static void -_aciomgr_destroy_port_dispatcher(struct aciomgr_port_dispatcher *dispatcher) +_bt_acio_mgr_destroy_port_dispatcher(bt_acio_mgr_port_dispatcher_t *dispatcher) { aciodrv_device_close(dispatcher->device); DeleteCriticalSection(&dispatcher->cs); } -void _aciomgr_init() +void bt_acio_mgr_init() { if (running) { log_warning("_aciomgr_init called when already running"); - _aciomgr_fini(); + bt_acio_mgr_fini(); } InitializeCriticalSection(&mgr_cs); array_init(&active_ports); @@ -73,7 +77,7 @@ void _aciomgr_init() running = true; } -void _aciomgr_fini() +void bt_acio_mgr_fini() { if (!running) { log_warning("_aciomgr_fini called when not running"); @@ -84,16 +88,8 @@ void _aciomgr_fini() array_fini(&active_ports); } -void aciomgr_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - log_to_external(misc, info, warning, fatal); -} - -struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud) +bt_acio_mgr_port_dispatcher_t * +bt_acio_mgr_port_init(const char *path, uint32_t baud) { if (!running) { log_warning("aciomgr_port_init: called when not running"); @@ -105,12 +101,12 @@ struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud) return NULL; } - struct aciomgr_port_dispatcher *entry; + bt_acio_mgr_port_dispatcher_t *entry; EnterCriticalSection(&mgr_cs); for (size_t i = 0; i < active_ports.nitems; i++) { - entry = array_item(struct aciomgr_port_dispatcher, &active_ports, i); + entry = array_item(bt_acio_mgr_port_dispatcher_t, &active_ports, i); if (strcmp(entry->path, path) == 0) { // found @@ -125,8 +121,8 @@ struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud) } } - entry = array_append(struct aciomgr_port_dispatcher, &active_ports); - _aciomgr_setup_port_dispatcher(entry, path, baud); + entry = array_append(bt_acio_mgr_port_dispatcher_t, &active_ports); + _bt_acio_mgr_setup_port_dispatcher(entry, path, baud); done: if (!entry->has_failure) { @@ -142,7 +138,7 @@ struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud) return entry; } -void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher) +void bt_acio_mgr_port_fini(bt_acio_mgr_port_dispatcher_t *dispatcher) { if (!running) { log_warning("aciomgr_port_fini: called when not running"); @@ -154,30 +150,31 @@ void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher) LeaveCriticalSection(&mgr_cs); if (dispatcher->references == 0) { - _aciomgr_destroy_port_dispatcher(dispatcher); + _bt_acio_mgr_destroy_port_dispatcher(dispatcher); } } // this function don't require the lock -uint8_t aciomgr_get_node_count(struct aciomgr_port_dispatcher *dispatcher) +uint8_t +bt_acio_mgr_node_count_get(const bt_acio_mgr_port_dispatcher_t *dispatcher) { return aciodrv_device_get_node_count(dispatcher->device); } // this function don't require the lock -bool aciomgr_get_node_product_ident( - struct aciomgr_port_dispatcher *dispatcher, +bool bt_acio_mgr_node_product_ident_get( + const bt_acio_mgr_port_dispatcher_t *dispatcher, uint8_t node_id, - char product[ACIOMGR_NODE_PRODUCT_CODE_LEN]) + char product[BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN]) { return aciodrv_device_get_node_product_ident( dispatcher->device, node_id, product); } -bool aciomgr_port_submit_packet( - struct aciomgr_port_dispatcher *dispatcher, - struct ac_io_message *msg, - int max_resp_size) +bool bt_acio_mgr_port_packet_submit( + bt_acio_mgr_port_dispatcher_t *dispatcher, + bt_acio_message_t *msg, + uint32_t max_resp_size) { // CS's although lightweight, may still be a burden, short circuit if (dispatcher->references > 1) { @@ -191,8 +188,8 @@ bool aciomgr_port_submit_packet( return aciodrv_send_and_recv(dispatcher->device, msg, max_resp_size); } -struct aciodrv_device_ctx * -aciomgr_port_checkout(struct aciomgr_port_dispatcher *dispatcher) +bt_acio_drv_device_ctx_t * +bt_acio_mgr_port_checkout(bt_acio_mgr_port_dispatcher_t *dispatcher) { if (dispatcher->references > 1) { EnterCriticalSection(&dispatcher->cs); @@ -201,9 +198,27 @@ aciomgr_port_checkout(struct aciomgr_port_dispatcher *dispatcher) return dispatcher->device; } -void aciomgr_port_checkin(struct aciomgr_port_dispatcher *dispatcher) +void bt_acio_mgr_port_checkin(bt_acio_mgr_port_dispatcher_t *dispatcher) { if (dispatcher->references > 1) { LeaveCriticalSection(&dispatcher->cs); } } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_acio_mgr_api_get(bt_acio_mgr_api_t *api) +{ + api->version = 1; + + api->v1.port_init = bt_acio_mgr_port_init; + api->v1.port_fini = bt_acio_mgr_port_fini; + api->v1.node_count_get = bt_acio_mgr_node_count_get; + api->v1.node_product_ident_get = bt_acio_mgr_node_product_ident_get; + api->v1.port_packet_submit = bt_acio_mgr_port_packet_submit; + api->v1.port_checkout = bt_acio_mgr_port_checkout; + api->v1.port_checkin = bt_acio_mgr_port_checkin; +} \ No newline at end of file diff --git a/src/main/aciodrv-proc/Module.mk b/src/main/aciodrv-proc/Module.mk index e347f778..9fa6b381 100644 --- a/src/main/aciodrv-proc/Module.mk +++ b/src/main/aciodrv-proc/Module.mk @@ -1,6 +1,7 @@ libs += aciodrv-proc libs_aciodrv-proc := \ + core \ src_aciodrv-proc := \ panb.c \ diff --git a/src/main/aciodrv-proc/panb.c b/src/main/aciodrv-proc/panb.c index c054e21f..4eda113b 100644 --- a/src/main/aciodrv-proc/panb.c +++ b/src/main/aciodrv-proc/panb.c @@ -5,8 +5,8 @@ #include "aciodrv/device.h" #include "aciodrv/panb.h" -#include "util/log.h" -#include "util/thread.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" static int auto_poll_proc(void *auto_poll_param); static int auto_poll_threadid; @@ -40,6 +40,8 @@ static int auto_poll_proc(void *param) bool aciodrv_proc_panb_init(struct aciodrv_device_ctx *device) { + bt_core_thread_result_t result; + log_assert(device); if (!aciodrv_panb_start_auto_input(device, 0, AC_IO_PANB_NUM_NODES)) { @@ -49,8 +51,10 @@ bool aciodrv_proc_panb_init(struct aciodrv_device_ctx *device) auto_poll_stop = false; InitializeCriticalSection(&keypair_lock); InitializeCriticalSection(&auto_poll_stop_lock); - auto_poll_threadid = - thread_create(auto_poll_proc, (void *) device, 0x4000, 0); + + result = bt_core_thread_create( + auto_poll_proc, (void *) device, 0x4000, 0, &auto_poll_threadid); + bt_core_thread_fatal_on_error(result); return true; } @@ -76,12 +80,17 @@ bool aciodrv_proc_panb_get_state(uint8_t *button_state) void aciodrv_proc_panb_fini(struct aciodrv_device_ctx *device) { + bt_core_thread_result_t result; + EnterCriticalSection(&auto_poll_stop_lock); auto_poll_stop = true; LeaveCriticalSection(&auto_poll_stop_lock); - thread_join(auto_poll_threadid, NULL); - thread_destroy(auto_poll_threadid); + result = bt_core_thread_join(auto_poll_threadid, NULL); + bt_core_thread_fatal_on_error(result); + + result = bt_core_thread_destroy(auto_poll_threadid); + bt_core_thread_fatal_on_error(result); DeleteCriticalSection(&keypair_lock); DeleteCriticalSection(&auto_poll_stop_lock); diff --git a/src/main/aciodrv/device.c b/src/main/aciodrv/device.c index 39bf8afc..0a6751f4 100644 --- a/src/main/aciodrv/device.c +++ b/src/main/aciodrv/device.c @@ -7,8 +7,9 @@ #include "aciodrv/port.h" +#include "iface-core/log.h" + #include "util/hex.h" -#include "util/log.h" #include "util/mem.h" /* Enable to dump all data to the logger */ diff --git a/src/main/aciodrv/h44b.c b/src/main/aciodrv/h44b.c index afbab429..89df4335 100644 --- a/src/main/aciodrv/h44b.c +++ b/src/main/aciodrv/h44b.c @@ -7,7 +7,7 @@ #include "aciodrv/device.h" -#include "util/log.h" +#include "iface-core/log.h" bool aciodrv_h44b_init(struct aciodrv_device_ctx *device, uint8_t node_id) { diff --git a/src/main/aciodrv/icca.c b/src/main/aciodrv/icca.c index ac56d0ea..9ee8599f 100644 --- a/src/main/aciodrv/icca.c +++ b/src/main/aciodrv/icca.c @@ -5,7 +5,7 @@ #include "aciodrv/device.h" #include "aciodrv/icca.h" -#include "util/log.h" +#include "iface-core/log.h" static bool aciodrv_icca_queue_loop_start( struct aciodrv_device_ctx *device, uint8_t node_id) diff --git a/src/main/aciodrv/kfca.c b/src/main/aciodrv/kfca.c index e21a0b84..f3a00b3c 100644 --- a/src/main/aciodrv/kfca.c +++ b/src/main/aciodrv/kfca.c @@ -5,7 +5,7 @@ #include "aciodrv/device.h" -#include "util/log.h" +#include "iface-core/log.h" static bool aciodrv_kfca_watchdog_start(struct aciodrv_device_ctx *device, uint8_t node_id) diff --git a/src/main/aciodrv/panb.c b/src/main/aciodrv/panb.c index 1412e160..5d213c36 100644 --- a/src/main/aciodrv/panb.c +++ b/src/main/aciodrv/panb.c @@ -5,8 +5,7 @@ #include "aciodrv/device.h" #include "aciodrv/panb.h" -#include "util/log.h" -#include "util/thread.h" +#include "iface-core/log.h" bool aciodrv_panb_start_auto_input( struct aciodrv_device_ctx *device, uint8_t node_id, uint8_t node_count) diff --git a/src/main/aciodrv/port.c b/src/main/aciodrv/port.c index b38ad2a7..f0fc6297 100644 --- a/src/main/aciodrv/port.c +++ b/src/main/aciodrv/port.c @@ -6,7 +6,7 @@ #include -#include "util/log.h" +#include "iface-core/log.h" HANDLE aciodrv_port_open(const char *port_path, int baud) { diff --git a/src/main/aciodrv/rvol.c b/src/main/aciodrv/rvol.c index a9e0c36f..8591eb39 100644 --- a/src/main/aciodrv/rvol.c +++ b/src/main/aciodrv/rvol.c @@ -5,7 +5,7 @@ #include "aciodrv/device.h" -#include "util/log.h" +#include "iface-core/log.h" static bool aciodrv_rvol_change_expand_mode( struct aciodrv_device_ctx *device, uint8_t node_id, uint8_t mode) diff --git a/src/main/acioemu/addr.c b/src/main/acioemu/addr.c index 8d85487e..2958fb7c 100644 --- a/src/main/acioemu/addr.c +++ b/src/main/acioemu/addr.c @@ -5,7 +5,7 @@ #include "acioemu/addr.h" #include "acioemu/emu.h" -#include "util/log.h" +#include "iface-core/log.h" void ac_io_emu_cmd_assign_addrs( struct ac_io_emu *emu, const struct ac_io_message *req, uint8_t node_count) diff --git a/src/main/acioemu/emu.c b/src/main/acioemu/emu.c index 11cf35a4..cff00cb7 100644 --- a/src/main/acioemu/emu.c +++ b/src/main/acioemu/emu.c @@ -14,9 +14,10 @@ #include "acioemu/emu.h" #include "acioemu/pipe.h" +#include "iface-core/log.h" + #include "hook/iohook.h" -#include "util/log.h" #include "util/str.h" static HRESULT ac_io_emu_open(struct ac_io_emu *emu, struct irp *irp); diff --git a/src/main/acioemu/h44b.c b/src/main/acioemu/h44b.c index dde446e9..8f879153 100644 --- a/src/main/acioemu/h44b.c +++ b/src/main/acioemu/h44b.c @@ -11,7 +11,7 @@ #include "acioemu/emu.h" -#include "bemanitools/jbio.h" +#include "iface-io/jb.h" #include "util/hex.h" @@ -54,14 +54,14 @@ void ac_io_emu_h44b_dispatch_request( case AC_IO_H44B_CMD_SET_OUTPUTS: /* Not using the struct ac_io_h44b_output here */ for (int i = 0; i < 6; i++) { - jb_io_set_rgb_led( - (enum jb_io_rgb_led) i, + bt_io_jb_rgb_led_set( + (enum bt_io_jb_rgb_led) i, req->cmd.raw[i * 3], req->cmd.raw[i * 3 + 1], req->cmd.raw[i * 3 + 2]); } - jb_io_write_lights(); + bt_io_jb_lights_write(); ac_io_emu_h44b_send_status(h44b, req, 0x00); diff --git a/src/main/acioemu/h44b.h b/src/main/acioemu/h44b.h index cfaafcc9..e067a331 100644 --- a/src/main/acioemu/h44b.h +++ b/src/main/acioemu/h44b.h @@ -6,14 +6,14 @@ #include "acioemu/emu.h" +#include "api/io/jb.h" + struct ac_io_emu_h44b { struct ac_io_emu *emu; uint8_t unit_no; // TODO }; -void acioemu_h44b_init(void); - void ac_io_emu_h44b_init( struct ac_io_emu_h44b *h44b, struct ac_io_emu *emu, uint8_t unit_no); diff --git a/src/main/acioemu/hdxs.c b/src/main/acioemu/hdxs.c index 9a38beee..5ce5c536 100644 --- a/src/main/acioemu/hdxs.c +++ b/src/main/acioemu/hdxs.c @@ -6,7 +6,7 @@ #include "acioemu/emu.h" #include "acioemu/hdxs.h" -#include "util/log.h" +#include "iface-core/log.h" static void ac_io_emu_hdxs_cmd_send_version( struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req); diff --git a/src/main/acioemu/icca.c b/src/main/acioemu/icca.c index e7713e52..a57c100f 100644 --- a/src/main/acioemu/icca.c +++ b/src/main/acioemu/icca.c @@ -12,7 +12,7 @@ #include "acioemu/emu.h" #include "acioemu/icca.h" -#include "bemanitools/eamio.h" +#include "iface-io/eam.h" #include "util/crc.h" #include "util/time.h" @@ -58,6 +58,7 @@ void ac_io_emu_icca_init( memset(icca, 0, sizeof(*icca)); icca->emu = emu; icca->unit_no = unit_no; + // queue must be started icca->fault = true; @@ -156,20 +157,20 @@ void ac_io_emu_icca_dispatch_request( switch (misc->subcmd) { case AC_IO_ICCA_SUBCMD_CARD_SLOT_CLOSE: - cmd = EAM_IO_CARD_SLOT_CMD_CLOSE; + cmd = BT_IO_EAM_CARD_SLOT_CMD_CLOSE; break; case AC_IO_ICCA_SUBCMD_CARD_SLOT_OPEN: - cmd = EAM_IO_CARD_SLOT_CMD_OPEN; + cmd = BT_IO_EAM_CARD_SLOT_CMD_OPEN; break; case AC_IO_ICCA_SUBCMD_CARD_SLOT_EJECT: - cmd = EAM_IO_CARD_SLOT_CMD_EJECT; + cmd = BT_IO_EAM_CARD_SLOT_CMD_EJECT; icca->engaged = false; break; case 3: - cmd = EAM_IO_CARD_SLOT_CMD_READ; + cmd = BT_IO_EAM_CARD_SLOT_CMD_READ; break; default: @@ -182,7 +183,7 @@ void ac_io_emu_icca_dispatch_request( } if (cmd != 0xFF) { - if (!eam_io_card_slot_cmd(icca->unit_no, cmd)) { + if (!bt_io_eam_card_slot_cmd_send(icca->unit_no, cmd)) { log_warning( "Eamio failed to handle slot cmd %d for node %d", cmd, @@ -326,33 +327,34 @@ static void ac_io_emu_icca_send_state( uint8_t sensor_state; bool card_full_insert; - if (!eam_io_poll(icca->unit_no)) { + if (!bt_io_eam_poll(icca->unit_no)) { log_warning("Polling eamio failed"); } memset(&resp, 0, sizeof(resp)); - keypad = eam_io_get_keypad_state(icca->unit_no); - sensor_state = eam_io_get_sensor_state(icca->unit_no); + keypad = bt_io_eam_keypad_state_get(icca->unit_no); + sensor_state = bt_io_eam_sensor_state_get(icca->unit_no); keypad_rise = keypad & (icca->last_keypad ^ keypad); - card_full_insert = sensor_state & (1 << EAM_IO_SENSOR_FRONT) && - sensor_state & (1 << EAM_IO_SENSOR_BACK); + card_full_insert = sensor_state & (1 << BT_IO_EAM_SENSOR_STATE_FRONT) && + sensor_state & (1 << BT_IO_EAM_SENSOR_STATE_BACK); if (sensor_state != icca->last_sensor) { if (card_full_insert) { - if (!eam_io_card_slot_cmd( - icca->unit_no, EAM_IO_CARD_SLOT_CMD_READ)) { + if (!bt_io_eam_card_slot_cmd_send( + icca->unit_no, BT_IO_EAM_CARD_SLOT_CMD_READ)) { log_warning( - "EAM_IO_CARD_SLOT_CMD_READ to unit %d failed", + "BT_IO_EAM_CARD_SLOT_CMD_READ to unit %d failed", icca->unit_no); } - icca->card_result = - eam_io_read_card(icca->unit_no, icca->uid, sizeof(icca->uid)); + icca->card_result = bt_io_eam_card_read( + icca->unit_no, icca->uid, sizeof(icca->uid)); // fault if sensor says to read but we got no card - icca->fault = (icca->card_result == EAM_IO_CARD_NONE); + icca->fault = + (icca->card_result == BT_IO_EAM_READ_CARD_RESULT_NONE); } else { icca->fault = false; } @@ -385,11 +387,11 @@ static void ac_io_emu_icca_send_state( body->sensor_state = 0; - if (sensor_state & (1 << EAM_IO_SENSOR_FRONT)) { + if (sensor_state & (1 << BT_IO_EAM_SENSOR_STATE_FRONT)) { body->sensor_state |= AC_IO_ICCA_FLAG_FRONT_SENSOR; } - if (sensor_state & (1 << EAM_IO_SENSOR_BACK)) { + if (sensor_state & (1 << BT_IO_EAM_SENSOR_STATE_BACK)) { body->sensor_state |= AC_IO_ICCA_FLAG_REAR_SENSOR; } diff --git a/src/main/acioemu/icca.h b/src/main/acioemu/icca.h index a1823986..b40e3e84 100644 --- a/src/main/acioemu/icca.h +++ b/src/main/acioemu/icca.h @@ -6,6 +6,8 @@ #include "acioemu/emu.h" +#include "api/io/eam.h" + enum ac_io_emu_icca_version { v150 = 0x5, v160 = 0x6, @@ -20,6 +22,7 @@ enum ac_io_emu_icca_version { struct ac_io_emu_icca { struct ac_io_emu *emu; uint8_t unit_no; + bool fault; bool engaged; uint8_t last_sensor; diff --git a/src/main/acioemu/pipe.h b/src/main/acioemu/pipe.h index ad442fc2..5a83bdd3 100644 --- a/src/main/acioemu/pipe.h +++ b/src/main/acioemu/pipe.h @@ -7,9 +7,10 @@ #include "acio/acio.h" +#include "iface-core/log.h" + #include "util/iobuf.h" #include "util/list.h" -#include "util/log.h" /* This uses the USB convention where OUT and IN are from the host's (game's) perspective. So an OUT transaction comes in to us and vice versa. diff --git a/src/main/aciomgr/Module.mk b/src/main/aciomgr/Module.mk deleted file mode 100644 index 0a17e8cd..00000000 --- a/src/main/aciomgr/Module.mk +++ /dev/null @@ -1,9 +0,0 @@ -dlls += aciomgr - -libs_aciomgr := \ - aciodrv \ - util \ - -src_aciomgr := \ - dllmain.c \ - manager.c \ diff --git a/src/main/aciomgr/aciomgr.def b/src/main/aciomgr/aciomgr.def deleted file mode 100644 index 06bc21fc..00000000 --- a/src/main/aciomgr/aciomgr.def +++ /dev/null @@ -1,12 +0,0 @@ -LIBRARY aciomgr - -EXPORTS - aciomgr_set_loggers - aciomgr_port_init - aciomgr_port_fini - aciomgr_get_node_count - aciomgr_get_node_product_ident - aciomgr_port_submit_packet - aciomgr_port_checkout - aciomgr_port_checkin - DllMain@12 @1 NONAME diff --git a/src/main/aciomgr/manager-init.h b/src/main/aciomgr/manager-init.h deleted file mode 100644 index b0b4b1b8..00000000 --- a/src/main/aciomgr/manager-init.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ACIOMGR_MANAGER_INIT_H -#define ACIOMGR_MANAGER_INIT_H - -// internal, used by DllMain -void _aciomgr_init(); -void _aciomgr_fini(); - -#endif diff --git a/src/main/aciotest/Module.mk b/src/main/aciotest/Module.mk index af04652b..d077aa57 100644 --- a/src/main/aciotest/Module.mk +++ b/src/main/aciotest/Module.mk @@ -1,10 +1,12 @@ exes += aciotest libs_aciotest := \ + core \ bio2drv \ aciodrv \ aciodrv-proc \ util \ + iface-core src_aciotest := \ icca.c \ diff --git a/src/main/aciotest/main.c b/src/main/aciotest/main.c index 4a301c41..69ee1b09 100644 --- a/src/main/aciotest/main.c +++ b/src/main/aciotest/main.c @@ -15,7 +15,12 @@ #include "aciotest/panb.h" #include "aciotest/rvol.h" -#include "util/log.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" +#include "core/thread-crt.h" + +#include "iface-core/log.h" static uint8_t aciotest_cnt = 0; static uint8_t bi2a_mode = 255; @@ -112,7 +117,11 @@ int main(int argc, char **argv) } } - log_to_writer(log_writer_stdout, NULL); + core_log_bt_core_api_set(); + core_thread_crt_core_api_set(); + + core_log_bt_ext_init_with_stdout(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); struct aciodrv_device_ctx *device = aciodrv_device_open_path(argv[1], atoi(argv[2])); diff --git a/src/main/asio/asio-reghook.c b/src/main/asio/asio-reghook.c index 161b13b1..6f37c901 100644 --- a/src/main/asio/asio-reghook.c +++ b/src/main/asio/asio-reghook.c @@ -10,13 +10,14 @@ #include +#include "asio/asio-reghook.h" + #include "hook/com-proxy.h" #include "hook/table.h" -#include "asio/asio-reghook.h" +#include "iface-core/log.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #include "util/time.h" diff --git a/src/main/asio/config-asio.c b/src/main/asio/config-asio.c index b29f99c8..d1532d3e 100644 --- a/src/main/asio/config-asio.c +++ b/src/main/asio/config-asio.c @@ -1,74 +1,10 @@ -#include "cconfig/cconfig-util.h" - #include "asio/config-asio.h" -#include "util/log.h" - -#define ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY "asio.force_asio" -#define ASIOHOOK_CONFIG_IO_FORCE_WASAPI_KEY "asio.force_wasapi" -#define ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY "asio.device_name" - -#define ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE false -#define ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_WASAPI_VALUE false -#define ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE "XONAR SOUND CARD(64)" - -void asiohook_config_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY, - ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE, - "Force ASIO audio mode/device (if applicable)"); - - cconfig_util_set_bool( - config, - ASIOHOOK_CONFIG_IO_FORCE_WASAPI_KEY, - ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_WASAPI_VALUE, - "Force WASAPI audio mode (if applicable)"); - - cconfig_util_set_str( - config, - ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY, - ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE, - "The ASIO device name to use"); -} - void asiohook_config_asio_get( - struct asiohook_config_asio *config_asio, struct cconfig *config) + const bt_core_config_t *config, + struct asiohook_config_asio *config_asio) { - if (!cconfig_util_get_bool( - config, - ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY, - &config_asio->force_asio, - ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY, - ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE); - } - if (!cconfig_util_get_bool( - config, - ASIOHOOK_CONFIG_IO_FORCE_WASAPI_KEY, - &config_asio->force_wasapi, - ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_WASAPI_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - ASIOHOOK_CONFIG_IO_FORCE_WASAPI_KEY, - ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_WASAPI_VALUE); - } - - if (!cconfig_util_get_str( - config, - ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY, - config_asio->replacement_name, - sizeof(config_asio->replacement_name) - 1, - ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY, - ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE); - } -} + bt_core_config_bool_get(config, "asio/force_asio", &config_asio->force_asio); + bt_core_config_bool_get(config, "asio/force_wasapi", &config_asio->force_wasapi); + bt_core_config_str_get(config, "asio/device_name", config_asio->replacement_name, sizeof(config_asio->replacement_name)); +} \ No newline at end of file diff --git a/src/main/asio/config-asio.h b/src/main/asio/config-asio.h index 3df72f52..9eadef76 100644 --- a/src/main/asio/config-asio.h +++ b/src/main/asio/config-asio.h @@ -1,9 +1,9 @@ #ifndef ASIOHOOK_CONFIG_IO_H #define ASIOHOOK_CONFIG_IO_H -#include +#include -#include "cconfig/cconfig.h" +#include "iface-core/config.h" struct asiohook_config_asio { bool force_asio; @@ -11,9 +11,8 @@ struct asiohook_config_asio { char replacement_name[128]; }; -void asiohook_config_init(struct cconfig *config); - void asiohook_config_asio_get( - struct asiohook_config_asio *config_asio, struct cconfig *config); + const bt_core_config_t *config, + struct asiohook_config_asio *config_asio); #endif \ No newline at end of file diff --git a/src/main/avs-ext/Module.mk b/src/main/avs-ext/Module.mk new file mode 100644 index 00000000..423d223b --- /dev/null +++ b/src/main/avs-ext/Module.mk @@ -0,0 +1,11 @@ +avslibs += avs-ext + +libs_avs-ext := \ + iface-core \ + +src_avs-ext := \ + fs.c \ + error.c \ + property-ext.c \ + property-node.c \ + property.c \ diff --git a/src/main/avs-util/error.c b/src/main/avs-ext/error.c similarity index 83% rename from src/main/avs-util/error.c rename to src/main/avs-ext/error.c index d31b2e18..00cec6fc 100644 --- a/src/main/avs-util/error.c +++ b/src/main/avs-ext/error.c @@ -1,16 +1,20 @@ -#include "avs-util/error.h" +#include "avs-ext/error.h" #include "util/defs.h" -struct avs_util_avs_error_str { +struct avs_ext_error_str { avs_error error; const char *msg; }; -static const char *avs_util_error_unknown = "unknown error"; +static const char *_avs_ext_error_unknown = "unknown error"; // Source: https://github.com/spicetools/spicetools -static const struct avs_util_avs_error_str AVS_UTIL_ERRORS[] = { +static const struct avs_ext_error_str _avs_ext_errors[] = { + {0x80070002, "cannot find file or directory"}, + {0x80070009, "invalid data type"}, + {0x80070012, "TODO unknown error code"}, + {0x80070016, "invalid parameter"}, {0x80092000, "invalid type"}, {0x80092001, "type cannot use as array"}, {0x80092002, "invalid"}, @@ -85,25 +89,25 @@ static const struct avs_util_avs_error_str AVS_UTIL_ERRORS[] = { {0x80092280, "finger-print differs"}, {0x800922C0, "operation is not supported"}}; -const char *avs_util_error_str(avs_error error) +const char *avs_ext_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; + for (i = 0; i < lengthof(_avs_ext_errors); i++) { + if (error == _avs_ext_errors[i].error) { + return _avs_ext_errors[i].msg; } } - return avs_util_error_unknown; + return _avs_ext_error_unknown; } -const char *avs_util_property_error_get_and_clear(struct property *prop) +const char *avs_ext_property_error_get_and_clear(struct property *prop) { avs_error error; error = property_get_error(prop); property_clear_error(prop); - return avs_util_error_str(error); + return avs_ext_error_str(error); } \ No newline at end of file diff --git a/src/main/avs-ext/error.h b/src/main/avs-ext/error.h new file mode 100644 index 00000000..d6590480 --- /dev/null +++ b/src/main/avs-ext/error.h @@ -0,0 +1,10 @@ +#ifndef AVS_EXT_ERROR_H +#define AVS_EXT_ERROR_H + +#include "imports/avs.h" + +const char *avs_ext_error_str(avs_error error); + +const char *avs_ext_error_property_error_get_and_clear(struct property *prop); + +#endif diff --git a/src/main/avs-ext/fs.c b/src/main/avs-ext/fs.c new file mode 100644 index 00000000..3c277992 --- /dev/null +++ b/src/main/avs-ext/fs.c @@ -0,0 +1,33 @@ +#define LOG_MODULE "avs-ext-fs" + +#include "api/core/log.h" + +#include "iface-core/log.h" + +#include "imports/avs.h" + +void avs_ext_fs_dir_list_log( + const char *path, bt_core_log_message_t log_message) +{ + avs_desc desc; + const char *dirent_name; + + desc = avs_fs_opendir(path); + + if (!desc) { + log_warning("Opening directory '%s' failed", path); + return; + } + + log_message(LOG_MODULE, "Directory contents of: %s", path); + + dirent_name = avs_fs_readdir(desc); + + while (dirent_name != NULL) { + log_message(LOG_MODULE, " %s", dirent_name); + + dirent_name = avs_fs_readdir(desc); + } + + avs_fs_closedir(desc); +} \ No newline at end of file diff --git a/src/main/avs-ext/fs.h b/src/main/avs-ext/fs.h new file mode 100644 index 00000000..c582f135 --- /dev/null +++ b/src/main/avs-ext/fs.h @@ -0,0 +1,9 @@ +#ifndef AVS_EXT_FS_H +#define AVS_EXT_FS_H + +#include "api/core/log.h" + +void avs_ext_fs_dir_list_log( + const char *path, bt_core_log_message_t log_message); + +#endif diff --git a/src/main/avs-ext/property-ext.c b/src/main/avs-ext/property-ext.c new file mode 100644 index 00000000..917b13d7 --- /dev/null +++ b/src/main/avs-ext/property-ext.c @@ -0,0 +1,71 @@ +#include "avs-ext/error.h" +#include "avs-ext/property-internal.h" + +#include "imports/avs.h" + +#include "iface-core/log.h" + +#include "main/core/property.h" + +#include "util/mem.h" + +#include "avs-ext/fs.h" + +void avs_ext_property_ext_avs_file_load( + const char *path, core_property_t **property_) +{ + avs_desc desc; + void *buffer; + int nbytes; + avs_error error; + + struct property *prop; + avs_ext_property_internal_property_t *property; + + log_assert(path); + log_assert(property_); + + desc = avs_fs_open(path, AVS_FILE_READ, AVS_FILE_FLAG_SHARE_READ); + + if (AVS_IS_ERROR(desc)) { + log_fatal( + "%s: Error opening avs property file: %s", + path, + avs_ext_error_str(desc)); + } + + nbytes = property_read_query_memsize(avs_fs_read, desc, 0, 0); + + if (AVS_IS_ERROR(nbytes)) { + log_fatal( + "%s: Error querying avs property file: ", + path, + avs_ext_error_str(nbytes)); + } + + buffer = xmalloc(nbytes); + prop = property_create( + PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE | + PROPERTY_FLAG_APPEND, + buffer, + nbytes); + + avs_fs_lseek(desc, 0, AVS_SEEK_SET); + + error = property_insert_read(prop, 0, avs_fs_read, desc); + + if (AVS_IS_ERROR(error)) { + log_fatal( + "%s: Error reading avs property file: %s", + path, + avs_ext_error_str(error)); + } + + avs_fs_close(desc); + + *property_ = xmalloc(sizeof(avs_ext_property_internal_property_t)); + + property = (avs_ext_property_internal_property_t *) *property_; + + property->property = prop; +} \ No newline at end of file diff --git a/src/main/avs-ext/property-ext.h b/src/main/avs-ext/property-ext.h new file mode 100644 index 00000000..6ee10afe --- /dev/null +++ b/src/main/avs-ext/property-ext.h @@ -0,0 +1,9 @@ +#ifndef AVS_EXT_PROPERTY_EXT_H +#define AVS_EXT_PROPERTY_EXT_H + +#include "main/core/property.h" + +void avs_ext_property_ext_avs_file_load( + const char *path, core_property_t **property); + +#endif \ No newline at end of file diff --git a/src/main/avs-ext/property-internal.h b/src/main/avs-ext/property-internal.h new file mode 100644 index 00000000..5f441d94 --- /dev/null +++ b/src/main/avs-ext/property-internal.h @@ -0,0 +1,26 @@ +#ifndef AVS_EXT_PROPERTY_INTERNAL_H +#define AVS_EXT_PROPERTY_INTERNAL_H + +#include "core/property-node.h" +#include "core/property.h" + +#include "imports/avs.h" + +typedef struct avs_ext_property_internal_property { + struct property *property; +} avs_ext_property_internal_property_t; + +_Static_assert( + sizeof(avs_ext_property_internal_property_t) <= sizeof(core_property_t), + "Not enough space for stack allocations"); + +typedef struct avs_ext_property_internal_node { + avs_ext_property_internal_property_t *property; + struct property_node *node; +} avs_ext_property_internal_node_t; + +_Static_assert( + sizeof(avs_ext_property_internal_node_t) <= sizeof(core_property_node_t), + "Not enough space for stack allocations"); + +#endif \ No newline at end of file diff --git a/src/main/avs-ext/property-node.c b/src/main/avs-ext/property-node.c new file mode 100644 index 00000000..67a4c571 --- /dev/null +++ b/src/main/avs-ext/property-node.c @@ -0,0 +1,1123 @@ +#define LOG_MODULE "avs-ext-property-node" + +#include + +#include "avs-ext/error.h" +#include "avs-ext/property-internal.h" +#include "avs-ext/property-node.h" + +#include "iface-core/log.h" + +#include "imports/avs.h" + +#include "util/mem.h" +#include "util/str.h" + +#define AVS_PROPERTY_STRUCTURE_META_SIZE 576 + +static core_property_node_result_t _avs_ext_property_node_name_get( + const core_property_node_t *node_, char *name, size_t len) +{ + avs_ext_property_internal_node_t *node; + + node = (avs_ext_property_internal_node_t *) node_; + + property_node_name(node->node, name, len); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t +_avs_ext_property_node_size(const core_property_node_t *node_, size_t *size) +{ + avs_ext_property_internal_node_t *node; + avs_error error; + + node = (avs_ext_property_internal_node_t *) node_; + + // No idea how to get the size of the memory that this node with all + // subnodes requires. Use the total size of the property it is owned by. + // This potentially wastes a lot of memory, but is considered ok for now + // because the known use-cases are fairly limited regarding usage of this + + // Copy-paste from avs_ext_property_size implementation + + // 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 + error = property_query_size(node->property->property); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + + // 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 + *size = (AVS_PROPERTY_STRUCTURE_META_SIZE + error) * 2; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_search( + const core_property_node_t *node_, + const char *path, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + node = (avs_ext_property_internal_node_t *) node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + tmp = property_search(NULL, node->node, path); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + node_out->property = node->property; + node_out->node = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_next_result_search( + const core_property_node_t *node_, core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + node = (avs_ext_property_internal_node_t *) node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + tmp = property_node_traversal(node->node, TRAVERSE_NEXT_SEARCH_RESULT); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + node_out->property = node->property; + node_out->node = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_child_get( + const core_property_node_t *node_, core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + node = (avs_ext_property_internal_node_t *) node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + tmp = property_node_traversal(node->node, TRAVERSE_FIRST_CHILD); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + node_out->property = node->property; + node_out->node = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_next_sibling_get( + const core_property_node_t *node_, core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + node = (avs_ext_property_internal_node_t *) node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + tmp = property_node_traversal(node->node, TRAVERSE_NEXT_SIBLING); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + node_out->property = node->property; + node_out->node = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_void_create( + const core_property_node_t *parent_node_, + const char *key, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_VOID, + key); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s8_create( + const core_property_node_t *parent_node_, + const char *key, + int8_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_S8, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u8_create( + const core_property_node_t *parent_node_, + const char *key, + uint8_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_U8, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s16_create( + const core_property_node_t *parent_node_, + const char *key, + int16_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_S16, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u16_create( + const core_property_node_t *parent_node_, + const char *key, + uint16_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_U16, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s32_create( + const core_property_node_t *parent_node_, + const char *key, + int32_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_S32, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u32_create( + const core_property_node_t *parent_node_, + const char *key, + uint32_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_U32, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s64_create( + const core_property_node_t *parent_node_, + const char *key, + int64_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_S64, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u64_create( + const core_property_node_t *parent_node_, + const char *key, + uint64_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_U64, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_bin_create( + const core_property_node_t *parent_node_, + const char *key, + void *data, + size_t len, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_BIN, + key, + data, + len); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_str_create( + const core_property_node_t *parent_node_, + const char *key, + const char *value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_STR, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_ipv4_create( + const core_property_node_t *parent_node_, + const char *key, + uint32_t value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_IP4, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_float_create( + const core_property_node_t *parent_node_, + const char *key, + float value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_FLOAT, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_double_create( + const core_property_node_t *parent_node_, + const char *key, + double value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_DOUBLE, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_attr_create( + const core_property_node_t *parent_node_, + const char *key, + const char *value) +{ + avs_ext_property_internal_node_t *parent_node; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_ATTR, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_bool_create( + const core_property_node_t *parent_node_, + const char *key, + bool value, + core_property_node_t *node_out_) +{ + avs_ext_property_internal_node_t *parent_node; + avs_ext_property_internal_node_t *node_out; + struct property_node *tmp; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + node_out = (avs_ext_property_internal_node_t *) node_out_; + + tmp = property_node_create( + parent_node->property->property, + parent_node->node, + PROPERTY_TYPE_BOOL, + key, + value); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(avs_ext_property_internal_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s8_read( + const core_property_node_t *parent_node_, int8_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_S8, value, sizeof(int8_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u8_read( + const core_property_node_t *parent_node_, uint8_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_U8, value, sizeof(uint8_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s16_read( + const core_property_node_t *parent_node_, int16_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_S16, value, sizeof(int16_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u16_read( + const core_property_node_t *parent_node_, uint16_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_U16, value, sizeof(uint16_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s32_read( + const core_property_node_t *parent_node_, int32_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_S32, value, sizeof(int32_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u32_read( + const core_property_node_t *parent_node_, uint32_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_U32, value, sizeof(uint32_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_s64_read( + const core_property_node_t *parent_node_, int64_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_S64, value, sizeof(int64_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_u64_read( + const core_property_node_t *parent_node_, uint64_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_U64, value, sizeof(uint64_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_bin_read( + const core_property_node_t *parent_node_, void *value, size_t len) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = + property_node_read(parent_node->node, PROPERTY_TYPE_BIN, value, len); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_str_read( + const core_property_node_t *parent_node_, char *value, size_t len) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = + property_node_read(parent_node->node, PROPERTY_TYPE_STR, value, len); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_ipv4_read( + const core_property_node_t *parent_node_, uint32_t *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_IP4, value, sizeof(uint32_t)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_float_read( + const core_property_node_t *parent_node_, float *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_FLOAT, value, sizeof(float)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_double_read( + const core_property_node_t *parent_node_, double *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_DOUBLE, value, sizeof(double)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_attr_read( + const core_property_node_t *parent_node_, const char *key, char *value, size_t len) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + size_t attr_key_len; + char *attr_key; + struct property_node *node_attr; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + // Append @ denoting an attribute, plus null terminator + attr_key_len = strlen(key) + 1 + 1; + + attr_key = xmalloc(sizeof(char) * attr_key_len); + + str_cpy(attr_key, attr_key_len, key); + str_cat(attr_key, attr_key_len, "@"); + + node_attr = property_search(NULL, parent_node->node, attr_key); + + if (node_attr == NULL) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + error = + property_node_read(node_attr, PROPERTY_TYPE_ATTR, value, len); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_bool_read( + const core_property_node_t *parent_node_, bool *value) +{ + avs_ext_property_internal_node_t *parent_node; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + error = property_node_read( + parent_node->node, PROPERTY_TYPE_BOOL, value, sizeof(bool)); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_attr_remove( + const core_property_node_t *parent_node_, const char *key) +{ + avs_ext_property_internal_node_t *parent_node; + struct property_node *attr_node; + size_t attr_key_len; + char *attr_key; + avs_error error; + + parent_node = (avs_ext_property_internal_node_t *) parent_node_; + + // Append @ denoting an attribute, plus null terminator + attr_key_len = strlen(key) + 1 + 1; + + attr_key = xmalloc(sizeof(char) * attr_key_len); + + str_cpy(attr_key, attr_key_len, key); + str_cat(attr_key, attr_key_len, "@"); + + // AVS property treats attributes as a type of node + attr_node = property_search(NULL, parent_node->node, attr_key); + + if (attr_node == NULL) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + error = property_node_remove(attr_node); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t +_avs_ext_property_node_remove(const core_property_node_t *node_) +{ + avs_ext_property_internal_node_t *node; + avs_error error; + + node = (avs_ext_property_internal_node_t *) node_; + + error = property_node_remove(node->node); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _avs_ext_property_node_copy( + core_property_node_t *dst_node_, const core_property_node_t *src_node_) +{ + avs_ext_property_internal_node_t *dst_node; + avs_ext_property_internal_node_t *src_node; + + dst_node = (avs_ext_property_internal_node_t *) dst_node_; + src_node = (avs_ext_property_internal_node_t *) src_node_; + + if (!property_node_clone( + dst_node->property->property, + dst_node->node, + src_node->node, + true)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } else { + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } +} + +void avs_ext_property_node_core_api_get(core_property_node_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.name_get = _avs_ext_property_node_name_get; + api->v1.size = _avs_ext_property_node_size; + api->v1.search = _avs_ext_property_node_search; + api->v1.next_result_search = _avs_ext_property_node_next_result_search; + api->v1.child_get = _avs_ext_property_node_child_get; + api->v1.next_sibling_get = _avs_ext_property_node_next_sibling_get; + api->v1.void_create = _avs_ext_property_node_void_create; + api->v1.s8_create = _avs_ext_property_node_s8_create; + api->v1.u8_create = _avs_ext_property_node_u8_create; + api->v1.s16_create = _avs_ext_property_node_s16_create; + api->v1.u16_create = _avs_ext_property_node_u16_create; + api->v1.s32_create = _avs_ext_property_node_s32_create; + api->v1.u32_create = _avs_ext_property_node_u32_create; + api->v1.s64_create = _avs_ext_property_node_s64_create; + api->v1.u64_create = _avs_ext_property_node_u64_create; + api->v1.bin_create = _avs_ext_property_node_bin_create; + api->v1.str_create = _avs_ext_property_node_str_create; + api->v1.ipv4_create = _avs_ext_property_node_ipv4_create; + api->v1.float_create = _avs_ext_property_node_float_create; + api->v1.double_create = _avs_ext_property_node_double_create; + api->v1.attr_create = _avs_ext_property_node_attr_create; + api->v1.bool_create = _avs_ext_property_node_bool_create; + api->v1.s8_read = _avs_ext_property_node_s8_read; + api->v1.u8_read = _avs_ext_property_node_u8_read; + api->v1.s16_read = _avs_ext_property_node_s16_read; + api->v1.u16_read = _avs_ext_property_node_u16_read; + api->v1.s32_read = _avs_ext_property_node_s32_read; + api->v1.u32_read = _avs_ext_property_node_u32_read; + api->v1.s64_read = _avs_ext_property_node_s64_read; + api->v1.u64_read = _avs_ext_property_node_u64_read; + api->v1.bin_read = _avs_ext_property_node_bin_read; + api->v1.str_read = _avs_ext_property_node_str_read; + api->v1.ipv4_read = _avs_ext_property_node_ipv4_read; + api->v1.float_read = _avs_ext_property_node_float_read; + api->v1.double_read = _avs_ext_property_node_double_read; + api->v1.attr_read = _avs_ext_property_node_attr_read; + api->v1.bool_read = _avs_ext_property_node_bool_read; + api->v1.remove = _avs_ext_property_node_remove; + api->v1.attr_remove = _avs_ext_property_node_attr_remove; + api->v1.copy = _avs_ext_property_node_copy; +} + +void avs_ext_property_node_core_api_set() +{ + core_property_node_api_t api; + + avs_ext_property_node_core_api_get(&api); + core_property_node_api_set(&api); +} + +struct property_node * +avs_ext_property_node_avs_property_node_get(const core_property_node_t *node) +{ + avs_ext_property_internal_node_t *internal_node; + + log_assert(node); + + internal_node = (avs_ext_property_internal_node_t *) node; + + return internal_node->node; +} \ No newline at end of file diff --git a/src/main/avs-ext/property-node.h b/src/main/avs-ext/property-node.h new file mode 100644 index 00000000..4863abb2 --- /dev/null +++ b/src/main/avs-ext/property-node.h @@ -0,0 +1,16 @@ +#ifndef AVS_EXT_PROPERTY_NODE_H +#define AVS_EXT_PROPERTY_NODE_H + +#include "imports/avs.h" + +#include "main/core/property-node.h" + +void avs_ext_property_node_core_api_get(core_property_node_api_t *api); + +void avs_ext_property_node_core_api_set(); + +// Don't use this unless you need to interface directly with avs +struct property_node * +avs_ext_property_node_avs_property_node_get(const core_property_node_t *node); + +#endif \ No newline at end of file diff --git a/src/main/avs-ext/property.c b/src/main/avs-ext/property.c new file mode 100644 index 00000000..67111616 --- /dev/null +++ b/src/main/avs-ext/property.c @@ -0,0 +1,369 @@ +#define LOG_MODULE "avs-ext-property" + +#include + +#include +#include + +#include "avs-ext/error.h" +#include "avs-ext/property-internal.h" +#include "avs-ext/property-node.h" +#include "avs-ext/property.h" + +#include "iface-core/log.h" + +#include "imports/avs.h" + +#include "util/mem.h" + +#define AVS_PROPERTY_STRUCTURE_META_SIZE 576 + +typedef void (*avs_ext_property_rewinder_t)(uint32_t context); + +struct avs_ext_property_str_read_handle { + const char *buffer; + size_t buffer_len; + size_t offset; +}; + +static void _avs_ext_property_free(core_property_t **property_); + +static size_t +_avs_ext_property_str_read(uint32_t context, void *bytes, size_t nbytes) +{ + int result; + struct avs_ext_property_str_read_handle *handle; + + result = 0; + handle = TlsGetValue(context); + + if (handle->offset < handle->buffer_len) { + result = min(nbytes, handle->buffer_len - handle->offset); + memcpy(bytes, (const void *) (handle->buffer + handle->offset), result); + handle->offset += result; + } + + return result; +} + +static void _avs_ext_property_str_rewind(uint32_t context) +{ + struct avs_ext_property_str_read_handle *handle; + + handle = TlsGetValue(context); + handle->offset = 0; +} + +static size_t +_avs_ext_property_fread(uint32_t context, void *bytes, size_t nbytes) +{ + FILE *f; + + f = TlsGetValue(context); + + return fread(bytes, 1, nbytes, f); +} + +static void _avs_ext_property_frewind(uint32_t context) +{ + FILE *f = TlsGetValue(context); + rewind(f); +} + +static core_property_result_t _avs_ext_property_do_load( + avs_reader_t reader, + avs_ext_property_rewinder_t rewinder, + uint32_t context, + const char *name, + avs_ext_property_internal_property_t **property) +{ + struct property *prop; + void *buffer; + int nbytes; + + nbytes = property_read_query_memsize(reader, context, 0, 0); + + if (nbytes < 0) { + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + + buffer = xmalloc(nbytes); + prop = property_create( + PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE | + PROPERTY_FLAG_APPEND, + buffer, + nbytes); + + if (!prop) { + free(buffer); + return CORE_PROPERTY_RESULT_ERROR_ALLOC; + } + + rewinder(context); + + if (!property_insert_read(prop, 0, reader, context)) { + property_destroy(prop); + free(buffer); + return CORE_PROPERTY_RESULT_ERROR_READ; + } + + *property = xmalloc(sizeof(avs_ext_property_internal_property_t)); + (*property)->property = prop; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t +_avs_ext_property_create(size_t size, core_property_t **property_) +{ + avs_ext_property_internal_property_t *property; + void *buffer; + struct property *prop; + + if (size > UINT32_MAX) { + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + + buffer = xmalloc(size); + prop = property_create( + PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE | + PROPERTY_FLAG_APPEND, + buffer, + (uint32_t) size); + + if (!prop) { + free(buffer); + return CORE_PROPERTY_RESULT_ERROR_ALLOC; + } + + *property_ = xmalloc(sizeof(core_property_t)); + + property = (avs_ext_property_internal_property_t *) (*property_); + property->property = prop; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t +_avs_ext_property_file_load(const char *path, core_property_t **property) +{ + FILE *file; + uint32_t f_keyhole; + core_property_result_t result; + + file = fopen(path, "r"); + + if (!file) { + switch (errno) { + case EACCES: + return CORE_PROPERTY_RESULT_ERROR_PERMISSIONS; + case ENOENT: + return CORE_PROPERTY_RESULT_NOT_FOUND; + default: + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + } + + /* 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_keyhole = TlsAlloc(); + TlsSetValue(f_keyhole, file); + + result = _avs_ext_property_do_load( + _avs_ext_property_fread, + _avs_ext_property_frewind, + f_keyhole, + path, + (avs_ext_property_internal_property_t **) property); + + TlsFree(f_keyhole); + + fclose(file); + + return result; +} + +static core_property_result_t +_avs_ext_property_str_load(const char *str, core_property_t **property) +{ + struct avs_ext_property_str_read_handle read_handle; + uint32_t s_keyhole; + core_property_result_t result; + + read_handle.buffer = str; + read_handle.buffer_len = strlen(str); + read_handle.offset = 0; + + s_keyhole = TlsAlloc(); + TlsSetValue(s_keyhole, &read_handle); + + result = _avs_ext_property_do_load( + _avs_ext_property_str_read, + _avs_ext_property_str_rewind, + s_keyhole, + "", + (avs_ext_property_internal_property_t **) property); + + TlsFree(s_keyhole); + + return result; +} + +static core_property_result_t +_avs_ext_property_size(const core_property_t *property_, size_t *size) +{ + avs_ext_property_internal_property_t *property; + avs_error error; + + property = (avs_ext_property_internal_property_t *) 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 + error = property_query_size(property->property); + + if (AVS_IS_ERROR(error)) { + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + + // 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 + *size = (AVS_PROPERTY_STRUCTURE_META_SIZE + error) * 2; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t _avs_ext_property_clone( + const core_property_t *property_, core_property_t **property_cloned_) +{ + avs_ext_property_internal_property_t *property; + avs_ext_property_internal_property_t *property_cloned; + + size_t size; + core_property_result_t result; + + struct property_node *node; + avs_error error; + + property = (avs_ext_property_internal_property_t *) property_; + + result = _avs_ext_property_size(property_, &size); + + if (CORE_PROPERTY_RESULT_IS_ERROR(result)) { + return result; + } + + result = _avs_ext_property_create(size, property_cloned_); + + property_cloned = + (avs_ext_property_internal_property_t *) *property_cloned_; + + if (CORE_PROPERTY_RESULT_IS_ERROR(result)) { + return result; + } + + node = property_search(property->property, NULL, "/"); + + if (!node) { + error = property_get_error(property_cloned->property); + + if (AVS_IS_ERROR(error)) { + _avs_ext_property_free(property_cloned_); + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + } + + if (!property_node_clone(property_cloned->property, NULL, node, true)) { + error = property_get_error(property_cloned->property); + + if (AVS_IS_ERROR(error)) { + _avs_ext_property_free(property_cloned_); + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + } + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t _avs_ext_property_root_node_get( + const core_property_t *property_, core_property_node_t *node_) +{ + avs_ext_property_internal_property_t *property; + avs_ext_property_internal_node_t *node; + + property = (avs_ext_property_internal_property_t *) property_; + node = (avs_ext_property_internal_node_t *) node_; + + memset(node, 0, sizeof(avs_ext_property_internal_node_t)); + + node->property = property; + node->node = property_search(property->property, NULL, "/"); + + if (node->node == NULL) { + return CORE_PROPERTY_RESULT_NOT_FOUND; + } else { + return CORE_PROPERTY_RESULT_SUCCESS; + } +} + +static core_property_result_t _avs_ext_property_other_node_insert( + core_property_t *property_, const core_property_node_t *node_) +{ + avs_ext_property_internal_property_t *property; + avs_ext_property_internal_node_t *node; + + property = (avs_ext_property_internal_property_t *) property_; + node = (avs_ext_property_internal_node_t *) node_; + + if (!property_node_clone(property->property, NULL, node->node, true)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } else { + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } +} + +static void _avs_ext_property_free(core_property_t **property_) +{ + avs_ext_property_internal_property_t *property; + void *buffer; + + property = (avs_ext_property_internal_property_t *) (*property_); + + buffer = property_desc_to_buffer(property->property); + property_destroy(property->property); + free(buffer); + + free(*property_); + *property_ = NULL; +} + +static void _avs_ext_property_core_api_get(core_property_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.create = _avs_ext_property_create; + api->v1.file_load = _avs_ext_property_file_load; + api->v1.str_load = _avs_ext_property_str_load; + api->v1.size = _avs_ext_property_size; + api->v1.clone = _avs_ext_property_clone; + api->v1.root_node_get = _avs_ext_property_root_node_get; + api->v1.other_node_insert = _avs_ext_property_other_node_insert; + api->v1.free = _avs_ext_property_free; +} + +void avs_ext_property_core_api_set() +{ + core_property_api_t api; + + _avs_ext_property_core_api_get(&api); + core_property_api_set(&api); +} diff --git a/src/main/avs-ext/property.h b/src/main/avs-ext/property.h new file mode 100644 index 00000000..041ccd98 --- /dev/null +++ b/src/main/avs-ext/property.h @@ -0,0 +1,8 @@ +#ifndef AVS_EXT_PROPERTY_H +#define AVS_EXT_PROPERTY_H + +#include "main/core/property.h" + +void avs_ext_property_core_api_set(); + +#endif \ No newline at end of file diff --git a/src/main/avs-util/Module.mk b/src/main/avs-util/Module.mk deleted file mode 100644 index 8db06918..00000000 --- a/src/main/avs-util/Module.mk +++ /dev/null @@ -1,6 +0,0 @@ -libs += avs-util - -libs_avs-util := \ - -src_avs-util := \ - error.c \ diff --git a/src/main/avs-util/error.h b/src/main/avs-util/error.h deleted file mode 100644 index 88d68c5b..00000000 --- a/src/main/avs-util/error.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef AVS_UTIL_ERROR_H -#define AVS_UTIL_ERROR_H - -#include "imports/avs.h" - -const char *avs_util_error_str(avs_error error); - -const char *avs_util_property_error_get_and_clear(struct property *prop); - -#endif diff --git a/src/main/bemanitools/bstio.h b/src/main/bemanitools/bstio.h deleted file mode 100644 index 162e230c..00000000 --- a/src/main/bemanitools/bstio.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef BEMANITOOLS_SDVXIO_H -#define BEMANITOOLS_SDVXIO_H - -/* IO emulation provider for BeatStream */ - -#include -#include - -#include "bemanitools/glue.h" - -enum bst_io_in_gpio_sys_bit { - SDVX_IO_IN_GPIO_SYS_COIN = 2, - SDVX_IO_IN_GPIO_SYS_TEST = 4, - SDVX_IO_IN_GPIO_SYS_SERVICE = 5, -}; - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void bst_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your BST IO emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - eam_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool bst_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down your SDVX IO emulation DLL */ - -void bst_io_fini(void); - -/* Read input state. Returns true if successful. */ - -bool bst_io_read_input(void); - -/* Get state of coin, test, service inputs */ - -uint8_t bst_io_get_input(void); - -// TODO: Lighting - -#endif diff --git a/src/main/bemanitools/ddrio.h b/src/main/bemanitools/ddrio.h deleted file mode 100644 index f543797f..00000000 --- a/src/main/bemanitools/ddrio.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef BEMANITOOLS_DDRIO_H -#define BEMANITOOLS_DDRIO_H - -#include -#include - -#include "bemanitools/glue.h" - -enum ddr_pad_bit { - DDR_TEST = 0x04, - DDR_COIN = 0x05, - DDR_SERVICE = 0x06, - - DDR_P2_START = 0x08, - DDR_P2_UP = 0x09, - DDR_P2_DOWN = 0x0A, - DDR_P2_LEFT = 0x0B, - DDR_P2_RIGHT = 0x0C, - DDR_P2_MENU_LEFT = 0x0E, - DDR_P2_MENU_RIGHT = 0x0F, - DDR_P2_MENU_UP = 0x02, - DDR_P2_MENU_DOWN = 0x03, - - DDR_P1_START = 0x10, - DDR_P1_UP = 0x11, - DDR_P1_DOWN = 0x12, - DDR_P1_LEFT = 0x13, - DDR_P1_RIGHT = 0x14, - DDR_P1_MENU_LEFT = 0x16, - DDR_P1_MENU_RIGHT = 0x17, - DDR_P1_MENU_UP = 0x00, - DDR_P1_MENU_DOWN = 0x01, -}; - -// see the functions below for more information - -enum p3io_light_bit { - LIGHT_P1_MENU = 0x00, - LIGHT_P2_MENU = 0x01, - LIGHT_P2_LOWER_LAMP = 0x04, - LIGHT_P2_UPPER_LAMP = 0x05, - LIGHT_P1_LOWER_LAMP = 0x06, - LIGHT_P1_UPPER_LAMP = 0x07, -}; - -enum hdxs_light_bit { - LIGHT_HD_P1_START = 0x08, - LIGHT_HD_P1_UP_DOWN = 0x09, - LIGHT_HD_P1_LEFT_RIGHT = 0x0A, - LIGHT_HD_P2_START = 0x0B, - LIGHT_HD_P2_UP_DOWN = 0x0C, - LIGHT_HD_P2_LEFT_RIGHT = 0x0D, -}; - -// the indexing starts from 0x20 if you're looking in geninput -enum hdxs_rgb_light_idx { - LIGHT_HD_P1_SPEAKER_F_R = 0x00, - LIGHT_HD_P1_SPEAKER_F_G = 0x01, - LIGHT_HD_P1_SPEAKER_F_B = 0x02, - LIGHT_HD_P2_SPEAKER_F_R = 0x03, - LIGHT_HD_P2_SPEAKER_F_G = 0x04, - LIGHT_HD_P2_SPEAKER_F_B = 0x05, - LIGHT_HD_P1_SPEAKER_W_R = 0x06, - LIGHT_HD_P1_SPEAKER_W_G = 0x07, - LIGHT_HD_P1_SPEAKER_W_B = 0x08, - LIGHT_HD_P2_SPEAKER_W_R = 0x09, - LIGHT_HD_P2_SPEAKER_W_G = 0x0A, - LIGHT_HD_P2_SPEAKER_W_B = 0x0B, -}; - -enum extio_light_bit { - LIGHT_NEONS = 0x0E, - - LIGHT_P2_RIGHT = 0x13, - LIGHT_P2_LEFT = 0x14, - LIGHT_P2_DOWN = 0x15, - LIGHT_P2_UP = 0x16, - - LIGHT_P1_RIGHT = 0x1B, - LIGHT_P1_LEFT = 0x1C, - LIGHT_P1_DOWN = 0x1D, - LIGHT_P1_UP = 0x1E -}; - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void ddr_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your DDR IO emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - eam_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool ddr_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* used to poll the IO for input, note that this is also where lights are - flushed to the device for geninput */ -uint32_t ddr_io_read_pad(void); - -/* The following are optional to implement, and allow lights to be set and - emulated as needed */ - -/* used to set pad lights, as well as the bass neon on SD cabs */ -void ddr_io_set_lights_extio(uint32_t extio_lights); - -/* used to set SD panel lights, and HD spot lights */ -void ddr_io_set_lights_p3io(uint32_t p3io_lights); - -/* used to set HD cab front panel lights */ -void ddr_io_set_lights_hdxs_panel(uint32_t hdxs_lights); - -/* used to set HD cab speaker RGB lights */ -void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b); - -void ddr_io_fini(void); - -#endif diff --git a/src/main/bemanitools/eamio.h b/src/main/bemanitools/eamio.h deleted file mode 100644 index 1c5d9b8b..00000000 --- a/src/main/bemanitools/eamio.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef BEMANITOOLS_EAM_H -#define BEMANITOOLS_EAM_H - -/* Card reader emulator API. You may replace the stock EAMIO.DLL supplied by - Bemanitools with your own custom implementation, which should implement the - interface contract defined in this header file. */ - -#include -#include - -#include "bemanitools/glue.h" - -/* Scan codes for the so-called "10 key" button panel on each card reader. Each - scan code corresponds to a bit position within the 16-bit bitfield that you - return from eam_io_get_keypad_state(). */ - -enum eam_io_keypad_scan_code { - EAM_IO_KEYPAD_0 = 0, - EAM_IO_KEYPAD_1 = 1, - EAM_IO_KEYPAD_4 = 2, - EAM_IO_KEYPAD_7 = 3, - EAM_IO_KEYPAD_00 = 4, - EAM_IO_KEYPAD_2 = 5, - EAM_IO_KEYPAD_5 = 6, - EAM_IO_KEYPAD_8 = 7, - EAM_IO_KEYPAD_DECIMAL = 8, - EAM_IO_KEYPAD_3 = 9, - EAM_IO_KEYPAD_6 = 10, - EAM_IO_KEYPAD_9 = 11, - - EAM_IO_KEYPAD_COUNT = 12, /* Not an actual scan code */ -}; - -/* Emulating the sensors of a slotted card reader. The reader has one - sensor at the front that detects if a card is getting inserted or - if the card is not fully removed. When the back sensor is triggered - the card is locked in the slot and its data is read. */ - -enum eam_io_sensor_state { - EAM_IO_SENSOR_FRONT = 0, - EAM_IO_SENSOR_BACK = 1, -}; - -/* Different commands for the (slotted) reader. The game triggers one - of these actions and the card slot as to execute it. When non-slotted - readers are emulated, these states are not used/set. */ - -enum eam_io_card_slot_cmd { - EAM_IO_CARD_SLOT_CMD_CLOSE = 0, - EAM_IO_CARD_SLOT_CMD_OPEN = 1, - EAM_IO_CARD_SLOT_CMD_EJECT = 2, - EAM_IO_CARD_SLOT_CMD_READ = 3, -}; - -/* Emulating of the card type for new readers. */ - -enum eam_io_read_card_result { - EAM_IO_CARD_NONE = 0, - EAM_IO_CARD_ISO15696 = 1, - EAM_IO_CARD_FELICA = 2, -}; - -/* A private function pointer table returned by the stock EAMIO.DLL - implementation and consumed by config.exe. The contents of this table are - undocumented and subject to change without notice. */ - -struct eam_io_config_api; - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void eam_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your card reader emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - eam_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool eam_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down your card reader emulation DLL. */ - -void eam_io_fini(void); - -/* Return the state of the number pad on your reader. This function will be - called frequently. See enum eam_io_keypad_scan_code above for the meaning of - each bit within the return value. - - This function will be called even if the running game does not actually have - a number pad on the real cabinet (e.g. Jubeat). - - unit_no is either 0 or 1. Games with only a single reader (jubeat, popn, - drummania) will only use unit_no 0. */ - -uint16_t eam_io_get_keypad_state(uint8_t unit_no); - -/* Indicate which sensors (front and back) are triggered for a slotted reader - (refer to enum). To emulate non-slotted readers, just set both sensors - to on to indicate the card is in range of the reader. This function - will be called frequently. */ - -uint8_t eam_io_get_sensor_state(uint8_t unit_no); - -/* Read a card ID. This function is only called when the return value of - eam_io_get_sensor_state() changes from false to true, so you may take your - time and perform file I/O etc, within reason. You must return exactly eight - bytes into the buffer pointed to by card_id. */ - -uint8_t eam_io_read_card(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes); - -/* Send a command to the card slot. This is called by the game to execute - certain actions on a slotted reader (refer to enum). When emulating - wave pass readers, this is function is never called. */ - -bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd); - -/* This function is called frequently. Update your device and states in here */ - -bool eam_io_poll(uint8_t unit_no); - -/* Return a pointer to an internal configuration API for use by config.exe. - Custom implementations should return NULL. */ - -const struct eam_io_config_api *eam_io_get_config_api(void); - -#endif diff --git a/src/main/bemanitools/glue.h b/src/main/bemanitools/glue.h deleted file mode 100644 index 7c9906d1..00000000 --- a/src/main/bemanitools/glue.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef BEMANITOOLS_GLUE_H -#define BEMANITOOLS_GLUE_H - -/* Common definitions for integration bindings */ - -#include - -#ifdef __GNUC__ -/* Bemanitools is compiled with GCC (MinGW, specifically) as of version 5 */ -#define LOG_CHECK_FMT __attribute__((format(printf, 2, 3))) -#else -/* Compile it out for MSVC plebs */ -#define LOG_CHECK_FMT -#endif - -/* An AVS-style logger function. Comes in four flavors: misc, info, warning, - and fatal, with increasing severity. Fatal loggers do not return, they - abort the running process after writing their message to the log. - - "module" is an arbitrary short string identifying the source of the log - message. The name of the calling DLL is a good default choice for this - string, although you might want to identify a module within your DLL here - instead. - - "fmt" is a printf-style format string. Depending on the context in which - your DLL is running you might end up calling a logger function exported - from libavs, which has its own printf implementation (including a number of - proprietary extensions), so don't use any overly exotic formats. */ - -typedef void (*log_formatter_t)(const char *module, const char *fmt, ...) - LOG_CHECK_FMT; - -/* An API for spawning threads. This API is defined by libavs, although - Bemanitools itself may supply compatible implementations of these functions - to your DLL, depending on the context in which it runs. - - NOTE: You may only use the logging functions from a thread where Bemanitools - calls you, or a thread that you create using this API. Failure to observe - this restriction will cause the process to crash. This is a limitation of - libavs itself, not Bemanitools. */ - -typedef int (*thread_create_t)( - int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority); -typedef void (*thread_join_t)(int thread_id, int *result); -typedef void (*thread_destroy_t)(int thread_id); - -#endif diff --git a/src/main/bemanitools/iidxio.h b/src/main/bemanitools/iidxio.h deleted file mode 100644 index d18905da..00000000 --- a/src/main/bemanitools/iidxio.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef BEMANITOOLS_IIDXIO_H -#define BEMANITOOLS_IIDXIO_H - -/* IO emulation provider for beatmania IIDX. */ - -#include -#include - -#include "bemanitools/glue.h" - -/* Bit mapping for the "pad" word */ - -enum iidx_io_sys_bit { - IIDX_IO_SYS_TEST = 0x00, - IIDX_IO_SYS_SERVICE = 0x01, - IIDX_IO_SYS_COIN = 0x02 -}; - -enum iidx_io_panel_bit { - IIDX_IO_PANEL_P1_START = 0x00, - IIDX_IO_PANEL_P2_START = 0x01, - IIDX_IO_PANEL_VEFX = 0x02, - IIDX_IO_PANEL_EFFECT = 0x03 -}; - -enum iidx_io_key_bit { - IIDX_IO_KEY_P1_1 = 0x00, - IIDX_IO_KEY_P1_2 = 0x01, - IIDX_IO_KEY_P1_3 = 0x02, - IIDX_IO_KEY_P1_4 = 0x03, - IIDX_IO_KEY_P1_5 = 0x04, - IIDX_IO_KEY_P1_6 = 0x05, - IIDX_IO_KEY_P1_7 = 0x06, - - IIDX_IO_KEY_P2_1 = 0x07, - IIDX_IO_KEY_P2_2 = 0x08, - IIDX_IO_KEY_P2_3 = 0x09, - IIDX_IO_KEY_P2_4 = 0x0A, - IIDX_IO_KEY_P2_5 = 0x0B, - IIDX_IO_KEY_P2_6 = 0x0C, - IIDX_IO_KEY_P2_7 = 0x0D -}; - -/* Bit mapping for the P1 and P2 deck lights */ - -enum iidx_io_deck_light { - IIDX_IO_DECK_LIGHT_P1_1 = 0, - IIDX_IO_DECK_LIGHT_P1_2 = 1, - IIDX_IO_DECK_LIGHT_P1_3 = 2, - IIDX_IO_DECK_LIGHT_P1_4 = 3, - IIDX_IO_DECK_LIGHT_P1_5 = 4, - IIDX_IO_DECK_LIGHT_P1_6 = 5, - IIDX_IO_DECK_LIGHT_P1_7 = 6, - - IIDX_IO_DECK_LIGHT_P2_1 = 8, - IIDX_IO_DECK_LIGHT_P2_2 = 9, - IIDX_IO_DECK_LIGHT_P2_3 = 10, - IIDX_IO_DECK_LIGHT_P2_4 = 11, - IIDX_IO_DECK_LIGHT_P2_5 = 12, - IIDX_IO_DECK_LIGHT_P2_6 = 13, - IIDX_IO_DECK_LIGHT_P2_7 = 14, -}; - -/* Bit mapping for the front panel lights */ - -enum iidx_io_panel_light { - IIDX_IO_PANEL_LIGHT_P1_START = 0, - IIDX_IO_PANEL_LIGHT_P2_START = 1, - IIDX_IO_PANEL_LIGHT_VEFX = 2, - IIDX_IO_PANEL_LIGHT_EFFECT = 3, -}; - -/* Bit mapping for the top lamps from left to right when facing cabinet screen - */ - -enum iidx_io_top_lamp { - IIDX_IO_TOP_LAMP_LEFT_BLUE = 0, - IIDX_IO_TOP_LAMP_LEFT_GREEN = 1, - IIDX_IO_TOP_LAMP_LEFT_YELLOW = 2, - IIDX_IO_TOP_LAMP_LEFT_RED = 3, - IIDX_IO_TOP_LAMP_RIGHT_BLUE = 4, - IIDX_IO_TOP_LAMP_RIGHT_GREEN = 5, - IIDX_IO_TOP_LAMP_RIGHT_YELLOW = 6, - IIDX_IO_TOP_LAMP_RIGHT_RED = 7, -}; - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void iidx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your IIDX IO emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - eam_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool iidx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down your IIDX IO emulation DLL */ - -void iidx_io_fini(void); - -/* Set the deck lighting state. See enum iidx_io_deck_light above. */ - -void iidx_io_ep1_set_deck_lights(uint16_t deck_lights); - -/* Set front panel lighting state. See enum iidx_io_panel_light above. */ - -void iidx_io_ep1_set_panel_lights(uint8_t panel_lights); - -/* Set state of the eight halogens above the marquee. */ - -void iidx_io_ep1_set_top_lamps(uint8_t top_lamps); - -/* Switch the top neons on or off. */ - -void iidx_io_ep1_set_top_neons(bool top_neons); - -/* Transmit the lighting state to the lighting controller. This function is - called immediately after all of the other iidx_io_ep1_set_*() functions. - - Return false in the event of an IO error. This will lock the game into an - IO error screen. */ - -bool iidx_io_ep1_send(void); - -/* Read input state from the input controller. This function is called - immediately before all of the iidx_io_ep2_get_*() functions. - - Return false in the event of an IO error. This will lock the game into an - IO error screen. */ - -bool iidx_io_ep2_recv(void); - -/* Get absolute turntable position, expressed in 1/256ths of a rotation. - player_no is either 0 or 1. */ - -uint8_t iidx_io_ep2_get_turntable(uint8_t player_no); - -/* Get slider position, where 0 is the bottom position and 15 is the topmost - position. slider_no is a number between 0 (leftmost) and 4 (rightmost). */ - -uint8_t iidx_io_ep2_get_slider(uint8_t slider_no); - -/* Get the state of the system buttons. See enums above. */ - -uint8_t iidx_io_ep2_get_sys(void); - -/* Get the state of the panel buttons. See enums above. */ - -uint8_t iidx_io_ep2_get_panel(void); - -/* Get the state of the 14 key buttons. See enums above. */ - -uint16_t iidx_io_ep2_get_keys(void); - -/* Write a nine-character string to the 16-segment display. This happens on a - different schedule to all of the other IO operations, so you should initiate - the communication as soon as this function is called */ - -bool iidx_io_ep3_write_16seg(const char *text); - -#endif diff --git a/src/main/bemanitools/input.h b/src/main/bemanitools/input.h deleted file mode 100644 index df809039..00000000 --- a/src/main/bemanitools/input.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef BEMANITOOLS_INPUT_H -#define BEMANITOOLS_INPUT_H - -/* Generic input API. This header file defines the public API for geninput.dll. - - You may use geninput to supply generic input mapping services for controls - that your custom IO DLLs do not natively provide. For instance, you might - want to make a custom IIDXIO.DLL that interfaces with your own 16-segment - LCD marquee device while still using the stock IIDXIO.DLL input and lighting - code, which uses the generic services provided by geninput.dll. - - All other exports from geninput.dll are undocumented and subject to change - without notice. */ - -#include -#include - -#include "bemanitools/glue.h" - -/* Supply logging functions to geninput. You should pass on the logging - functions that are supplied to your own custom DLLs. - - This is the only function that can safely be called before input_init(). */ - -void input_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize the generic input subsystem. You must pass on the thread - management functions that have been supplied to your DLL. - - Calling any geninput functions other than input_set_loggers() before calling - input_init() will probably crash the running process. - - You will also need to call mapper_config_load() with the appropriate - game_type parameter, otherwise you will not receive any input, and any - attempts to set a light output level will have no effect. */ - -void input_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down the generic input subsystem. After calling this function, no - geninput functions other than input_set_loggers() or input_init() may be - called. */ - -void input_fini(void); - -/* Load input mappings for a particular game, as configured from config.exe. - - Currently recognized game types are: - - ddr: Dance Dance Revolution - dm: Drum Mania - gf: Guitar Freaks - iidx: beatmania IIDX - pnm: pop'n music - sdvx: Sound Voltex - ju: jubeat - - Returns true if a suitable config file was found and successfully loaded. */ - -bool mapper_config_load(const char *game_type); - -/* Return the absolute position of an analog spinner, expressed in 1/256ths of - a complete rotation. */ - -uint8_t mapper_read_analog(uint8_t analog); - -/* Map the current state of all attached input devices to a 64-bit bit field. - The exact layout of this bit field varies between game types, although we - try to approximate the contents of each emulated IO PCB's own state packet - as closely as is reasonably practical. */ - -uint64_t mapper_update(void); - -/* Set the intensity of any light on a controller corresponding to a particular - software-controlled light on an arcade cabinet, where 0 is off and 255 is - full intensity. Consult the header files for the light identifiers used for - each game type. The mappings between these light identifiers and the actual - lights on the user's controller (if any) are configured by the user by means - of the config.exe program. - - Note that any calls to this function do not take effect until the next call - to mapper_update(). */ - -void mapper_write_light(uint8_t light, uint8_t intensity); - -#endif diff --git a/src/main/bemanitools/jbio.h b/src/main/bemanitools/jbio.h deleted file mode 100644 index 1a58617e..00000000 --- a/src/main/bemanitools/jbio.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef BEMANITOOLS_JBIO_H -#define BEMANITOOLS_JBIO_H - -/* IO emulation provider for jubeat. */ - -#include -#include - -#include "bemanitools/glue.h" - -/* input bit mappings. Panels on the controller are - panel 1 top left corner down to panel 16 bottom right corner */ -enum jb_io_panel_bit { - JB_IO_PANEL_01 = 0x00, - JB_IO_PANEL_02 = 0x01, - JB_IO_PANEL_03 = 0x02, - JB_IO_PANEL_04 = 0x03, - JB_IO_PANEL_05 = 0x04, - JB_IO_PANEL_06 = 0x05, - JB_IO_PANEL_07 = 0x06, - JB_IO_PANEL_08 = 0x07, - JB_IO_PANEL_09 = 0x08, - JB_IO_PANEL_10 = 0x09, - JB_IO_PANEL_11 = 0x0A, - JB_IO_PANEL_12 = 0x0B, - JB_IO_PANEL_13 = 0x0C, - JB_IO_PANEL_14 = 0x0D, - JB_IO_PANEL_15 = 0x0E, - JB_IO_PANEL_16 = 0x0F, -}; - -/* input "single button mode" mappings. Allows you to check each corner of each - button to determine any flaky inputs -*/ -enum jb_io_panel_mode { - JB_IO_PANEL_MODE_ALL = 0, // any of the four corners will trigger a panel - JB_IO_PANEL_MODE_TOP_LEFT = 1, - JB_IO_PANEL_MODE_TOP_RIGHT = 2, - JB_IO_PANEL_MODE_BOTTOM_RIGHT = 3, - JB_IO_PANEL_MODE_BOTTOM_LEFT = 4, -}; - -/* Bit mappings for "system" inputs */ -enum jb_io_sys_bit { - JB_IO_SYS_TEST = 0x00, - JB_IO_SYS_SERVICE = 0x01, - JB_IO_SYS_COIN = 0x02, -}; - -/* RGB led units to address */ -enum jb_io_rgb_led { - JB_IO_RGB_LED_FRONT = 0, - JB_IO_RGB_LED_TOP = 1, - JB_IO_RGB_LED_LEFT = 2, - JB_IO_RGB_LED_RIGHT = 3, - JB_IO_RGB_LED_TITLE = 4, - JB_IO_RGB_LED_WOOFER = 5 -}; - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void jb_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your JB IO emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - jb_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool jb_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down your JB IO emulation DLL */ - -void jb_io_fini(void); - -/* Read input state */ - -bool jb_io_read_inputs(void); - -/* Get state of coin, test, service inputs */ - -uint8_t jb_io_get_sys_inputs(void); - -/* Get panel button state. Will return either any button being pressed, or a - particular panel corner depending on previous call to jb_io_set_panel_mode */ - -uint16_t jb_io_get_panel_inputs(void); - -/* Set state of a PWM (dimmable) light */ - -void jb_io_set_rgb_led( - enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b); - -/* Transmit the light state to the IOPCB */ - -bool jb_io_write_lights(void); - -/* Select operating mode for the panel. Should be immediately sent to the IOPCB - */ - -bool jb_io_set_panel_mode(enum jb_io_panel_mode mode); - -/* Open or close the coin chute - true will redirect all coins to the return - slot. Required for jb_io_set_panel_mode to operate correctly on p4io. - Should be immediately sent to the IOPCB */ - -bool jb_io_set_coin_blocker(bool blocked); - -#endif diff --git a/src/main/bemanitools/popnio.h b/src/main/bemanitools/popnio.h deleted file mode 100644 index 29829aba..00000000 --- a/src/main/bemanitools/popnio.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef BEMANITOOLS_POPNIO_H -#define BEMANITOOLS_POPNIO_H - -/* IO emulation provider for pop'n music. */ - -#include -#include - -#include "bemanitools/glue.h" - -/* Bit mapping for the "buttons" word */ - -enum popn_io_sys_bit { - POPN_IO_SYS_SERVICE = 0x06, - POPN_IO_SYS_TEST = 0x07, -}; - -enum popn_io_button_bit { - POPN_IO_BUTTON_1 = 0x08, - POPN_IO_BUTTON_2 = 0x09, - POPN_IO_BUTTON_3 = 0x0a, - POPN_IO_BUTTON_4 = 0x0b, - POPN_IO_BUTTON_5 = 0x0c, - POPN_IO_BUTTON_6 = 0x0d, - POPN_IO_BUTTON_7 = 0x0e, - POPN_IO_BUTTON_8 = 0x0f, - POPN_IO_BUTTON_9 = 0x10, -}; - -enum popn_io_light_top_lamp_bit { - POPN_LIGHT_HI_LAMP1 = 0x00, - POPN_LIGHT_HI_LAMP2 = 0x01, - POPN_LIGHT_HI_LAMP3 = 0x02, - POPN_LIGHT_HI_LAMP4 = 0x03, - POPN_LIGHT_HI_LAMP5 = 0x04, -}; - -enum popn_io_light_side_lamp_bit { - POPN_LIGHT_LEFT_LAMP1 = 0x00, - POPN_LIGHT_LEFT_LAMP2 = 0x01, - POPN_LIGHT_RIGHT_LAMP1 = 0x02, - POPN_LIGHT_RIGHT_LAMP2 = 0x03, -}; - -enum popn_io_light_switch_lamp_bit { - POPN_LIGHT_SW_LAMP1 = 0x00, // Is actually 4 bits wide - POPN_LIGHT_SW_LAMP2 = 0x04, - POPN_LIGHT_SW_LAMP3 = 0x05, - POPN_LIGHT_SW_LAMP4 = 0x06, - POPN_LIGHT_SW_LAMP5 = 0x07, - POPN_LIGHT_SW_LAMP6 = 0x08, - POPN_LIGHT_SW_LAMP7 = 0x09, - POPN_LIGHT_SW_LAMP8 = 0x0a, - POPN_LIGHT_SW_LAMP9 = 0x0b, -}; - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void popn_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your pop'n music IO emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - eam_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool popn_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down your pop'n music IO emulation DLL */ - -void popn_io_fini(void); - -/* Get the state of the buttons. See enums above. */ - -uint32_t popn_io_get_buttons(void); - -/* Set the top light state. See enum popn_io_light_top_lamp_bit above. */ - -void popn_io_set_top_lights(uint32_t lights); - -/* Set the side light state. See enum popn_io_light_side_lamp_bit above. */ - -void popn_io_set_side_lights(uint32_t lights); - -/* Set the button light state. See enum popn_io_light_switch_lamp_bit above. */ - -void popn_io_set_button_lights(uint32_t lights); - -/* Set the coin blocker light state. */ - -void popn_io_set_coin_blocker_light(bool enabled); - -/* Set the coin counter light state. */ - -void popn_io_set_coin_counter_light(bool enabled); - -#endif diff --git a/src/main/bemanitools/sdvxio.h b/src/main/bemanitools/sdvxio.h deleted file mode 100644 index 2ebab7bb..00000000 --- a/src/main/bemanitools/sdvxio.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef BEMANITOOLS_SDVXIO_H -#define BEMANITOOLS_SDVXIO_H - -/* IO emulation provider for SOUND VOLTEX */ - -#include -#include - -#include "bemanitools/glue.h" - -enum sdvx_io_in_gpio_sys_bit { - SDVX_IO_IN_GPIO_SYS_COIN = 2, - SDVX_IO_IN_GPIO_SYS_SERVICE = 4, - SDVX_IO_IN_GPIO_SYS_TEST = 5, -}; - -enum sdvx_io_in_gpio_0_bit { - SDVX_IO_IN_GPIO_0_C = 0, - SDVX_IO_IN_GPIO_0_B = 1, - SDVX_IO_IN_GPIO_0_A = 2, - SDVX_IO_IN_GPIO_0_START = 3, - SDVX_IO_IN_GPIO_0_RECORDER = 4, - SDVX_IO_IN_GPIO_0_HEADPHONE = 5, -}; - -enum sdvx_io_in_gpio_1_bit { - SDVX_IO_IN_GPIO_1_FX_R = 3, - SDVX_IO_IN_GPIO_1_FX_L = 4, - SDVX_IO_IN_GPIO_1_D = 5, -}; - -enum sdvx_io_out_gpio_bit { - SDVX_IO_OUT_GPIO_D = 0, - SDVX_IO_OUT_GPIO_FX_L = 1, - SDVX_IO_OUT_GPIO_FX_R = 2, - SDVX_IO_OUT_GPIO_GENERATOR_B = 3, - SDVX_IO_OUT_GPIO_START = 12, - SDVX_IO_OUT_GPIO_A = 13, - SDVX_IO_OUT_GPIO_B = 14, - SDVX_IO_OUT_GPIO_C = 15, -}; - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void sdvx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your SDVX IO emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - eam_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool sdvx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down your SDVX IO emulation DLL */ - -void sdvx_io_fini(void); - -/* Set state of the GPIO (on/off) lights (see bit definitions above) */ - -void sdvx_io_set_gpio_lights(uint32_t gpio_lights); - -/* Set state of a PWM (dimmable) light channel. These come in groups of three - (red, green, blue). There are a six group of three PWM channels, for a - total of 18 channels (0 through 17). */ - -void sdvx_io_set_pwm_light(uint8_t light_no, uint8_t intensity); - -/* Transmit the light state to the IOPCB */ - -bool sdvx_io_write_output(void); - -/* Read input state */ - -bool sdvx_io_read_input(void); - -/* Get state of coin, test, service inputs */ - -uint8_t sdvx_io_get_input_gpio_sys(void); - -/* Get gameplay button state. Parameter selects GPIO bank 0 or 1. See bit - definitions above for details. */ - -uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank); - -/* Get a 10-bit (!) spinner position, where spinner_no is 0 or 1. - High six bits are ignored. */ - -uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no); - -/* Sets the volume of the digital amps if possible. - Range is between 0-96, where 0 is MAX and 96 is LOW. */ - -bool sdvx_io_set_amp_volume( - uint8_t primary, uint8_t headphone, uint8_t subwoofer); - -#endif diff --git a/src/main/bemanitools/vefxio.h b/src/main/bemanitools/vefxio.h deleted file mode 100644 index 9bf170ee..00000000 --- a/src/main/bemanitools/vefxio.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef BEMANITOOLS_VEFXIO_H -#define BEMANITOOLS_VEFXIO_H - -/* IO emulation provider for beatmania IIDX Effector Panel. */ - -#include -#include - -#include "bemanitools/glue.h" - -/* The first function that will be called on your DLL. You will be supplied - with four function pointers that may be used to log messages to the game's - log file. See comments in glue.h for further information. */ - -void vefx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - -/* Initialize your IIDX IO emulation DLL. Thread management functions are - provided to you; you must use these functions to create your own threads if - you want to make use of the logging functions that are provided to - eam_io_set_loggers(). You will also need to pass these thread management - functions on to geninput if you intend to make use of that library. - - See glue.h and geninput.h for further details. */ - -bool vefx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); - -/* Shut down your IIDX IO emulation DLL */ - -void vefx_io_fini(void); - -/* Read input state from the input controller. This function is called - immediately before the vefx_io_get_slider() function. - - Return false in the event of an IO error. This will lock the game into an - IO error screen. - - If making a custom driver, ppad can be used to update regular IO if needed - - See iidxio.c for mappings. */ - -bool vefx_io_recv(uint64_t *ppad); - -/* Get slider position, where 0 is the bottom position and 15 is the topmost - position. slider_no is a number between 0 (leftmost) and 4 (rightmost). */ - -uint8_t vefx_io_get_slider(uint8_t slider_no); - -/* Write a nine-character string to the 16-segment display. This happens on a - different schedule to all of the other IO operations, so you should initiate - the communication as soon as this function is called */ - -bool vefx_io_write_16seg(const char *text); - -#endif diff --git a/src/main/bio2drv/Module.mk b/src/main/bio2drv/Module.mk index f5bdb568..2da24e1b 100644 --- a/src/main/bio2drv/Module.mk +++ b/src/main/bio2drv/Module.mk @@ -1,10 +1,11 @@ libs += bio2drv libs_bio2drv := \ - aciodrv + core \ + aciodrv \ src_bio2drv := \ + config.c \ detect.c \ - config-bio2.c \ bi2a-iidx.c \ - bi2a-sdvx.c + bi2a-sdvx.c \ diff --git a/src/main/bio2drv/bi2a-iidx.c b/src/main/bio2drv/bi2a-iidx.c index 1119876f..ebf119c7 100644 --- a/src/main/bio2drv/bi2a-iidx.c +++ b/src/main/bio2drv/bi2a-iidx.c @@ -7,7 +7,7 @@ #include "aciodrv/device.h" -#include "util/log.h" +#include "iface-core/log.h" // Must be provided on init command. Actual meaning unknown right now. // Not providing this will not initialize the IO correctly resulting diff --git a/src/main/bio2drv/bi2a-sdvx.c b/src/main/bio2drv/bi2a-sdvx.c index 93edf496..0d11e304 100644 --- a/src/main/bio2drv/bi2a-sdvx.c +++ b/src/main/bio2drv/bi2a-sdvx.c @@ -7,7 +7,7 @@ #include "aciodrv/device.h" -#include "util/log.h" +#include "iface-core/log.h" static const uint8_t _BIO2DR_BI2A_SDVX_INIT_DATA = 0x3B; diff --git a/src/main/bio2drv/config-bio2.c b/src/main/bio2drv/config-bio2.c deleted file mode 100644 index 492cdefd..00000000 --- a/src/main/bio2drv/config-bio2.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "cconfig/cconfig-util.h" - -#include "bio2drv/config-bio2.h" - -#include "util/log.h" - -#define BIO2DRV_CONFIG_BIO2_AUTO_KEY "bio2.autodetect" -#define BIO2DRV_CONFIG_BIO2_PORT_KEY "bio2.port" -#define BIO2DRV_CONFIG_BIO2_BAUD_KEY "bio2.baud" - -#define BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE true -#define BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE "COM4" -#define BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE 115200 - -void bio2drv_config_bio2_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - BIO2DRV_CONFIG_BIO2_AUTO_KEY, - BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE, - "Autodetect BIO2 port (default: on)"); - - cconfig_util_set_str( - config, - BIO2DRV_CONFIG_BIO2_PORT_KEY, - BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE, - "BIO2 serial port. Optional, if autodetect property is turned on"); - - cconfig_util_set_int( - config, - BIO2DRV_CONFIG_BIO2_BAUD_KEY, - BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE, - "BIO2 bus baudrate (real devices expect 115200)"); -} - -void bio2drv_config_bio2_get( - struct bio2drv_config_bio2 *config_bio2, struct cconfig *config) -{ - if (!cconfig_util_get_bool( - config, - BIO2DRV_CONFIG_BIO2_AUTO_KEY, - &config_bio2->autodetect, - BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - BIO2DRV_CONFIG_BIO2_AUTO_KEY, - BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE); - } - - if (!cconfig_util_get_str( - config, - BIO2DRV_CONFIG_BIO2_PORT_KEY, - config_bio2->port, - sizeof(config_bio2->port) - 1, - BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - BIO2DRV_CONFIG_BIO2_PORT_KEY, - BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE); - } - - if (!cconfig_util_get_int( - config, - BIO2DRV_CONFIG_BIO2_BAUD_KEY, - &config_bio2->baud, - BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - BIO2DRV_CONFIG_BIO2_BAUD_KEY, - BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE); - } -} diff --git a/src/main/bio2drv/config-bio2.h b/src/main/bio2drv/config-bio2.h deleted file mode 100644 index a626e861..00000000 --- a/src/main/bio2drv/config-bio2.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef BIO2DRV_CONFIG_BIO2_H -#define BIO2DRV_CONFIG_BIO2_H - -#include - -#include "cconfig/cconfig.h" - -struct bio2drv_config_bio2 { - bool autodetect; - char port[64]; - int32_t baud; -}; - -void bio2drv_config_bio2_init(struct cconfig *config); - -void bio2drv_config_bio2_get( - struct bio2drv_config_bio2 *config_bio2, struct cconfig *config); - -#endif diff --git a/src/main/bio2drv/config.c b/src/main/bio2drv/config.c new file mode 100644 index 00000000..8782cb69 --- /dev/null +++ b/src/main/bio2drv/config.c @@ -0,0 +1,11 @@ +#include "bio2drv/config.h" + +#include "core/config-ext.h" + +void bio2drv_config_bio2_get( + const bt_core_config_t *config, bio2drv_config_t *config_out) +{ + bt_core_config_ext_bool_get(config, "autodetect", &config_out->autodetect); + bt_core_config_ext_str_get(config, "port", config_out->port, sizeof(config_out->port)); + bt_core_config_ext_s32_get(config, "baud", &config_out->baud); +} \ No newline at end of file diff --git a/src/main/bio2drv/config.h b/src/main/bio2drv/config.h new file mode 100644 index 00000000..b229e28d --- /dev/null +++ b/src/main/bio2drv/config.h @@ -0,0 +1,15 @@ +#ifndef BIO2DRV_CONFIG_BIO2_H +#define BIO2DRV_CONFIG_BIO2_H + +#include "api/core/config.h" + +typedef struct bio2drv_config { + bool autodetect; + char port[64]; + int32_t baud; +} bio2drv_config_t; + +void bio2drv_config_bio2_get( + const bt_core_config_t *config, bio2drv_config_t *config_out); + +#endif diff --git a/src/main/bio2drv/detect.c b/src/main/bio2drv/detect.c index d559175d..35465a43 100644 --- a/src/main/bio2drv/detect.c +++ b/src/main/bio2drv/detect.c @@ -6,12 +6,12 @@ #include #include -#include "bio2drv/detect.h" - #include #include -#include "util/log.h" +#include "bio2drv/detect.h" + +#include "iface-core/log.h" DEFINE_GUID( GUID_COM_BUS_ENUMERATOR, @@ -136,15 +136,6 @@ static bool get_device_by_filter( return false; } -void bio2drv_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - log_to_external(misc, info, warning, fatal); -} - bool bio2drv_detect( enum bio2drv_detect_mode mode, size_t index, char *path, size_t length) { diff --git a/src/main/bio2drv/detect.h b/src/main/bio2drv/detect.h index 21ab725f..dd86dae4 100644 --- a/src/main/bio2drv/detect.h +++ b/src/main/bio2drv/detect.h @@ -3,20 +3,12 @@ #include -#include "bemanitools/glue.h" - enum bio2drv_detect_mode { DETECT_DEVICEDESC = 0x1, // look for serial devices containing BIO2(VIDEO) DETECT_FRIENDLYNAME = 0x2, // look for serial devices containing BIO2(VIDEO) DETECT_DEVICEID = 0x3, // look for serial devices by vid/pid }; -void bio2drv_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); - bool bio2drv_detect( enum bio2drv_detect_mode mode, size_t devnum, char *path, size_t length); diff --git a/src/main/bio2emu-iidx/bi2a.c b/src/main/bio2emu-iidx/bi2a.c index cd2b56a5..bdc05c79 100644 --- a/src/main/bio2emu-iidx/bi2a.c +++ b/src/main/bio2emu-iidx/bi2a.c @@ -10,9 +10,10 @@ #include #include "acioemu/emu.h" -#include "util/math.h" -#include "bemanitools/iidxio.h" +#include "iface-io/iidx.h" + +#include "util/math.h" static int get_default_slider_valid(size_t idx); static void bio2_emu_bi2a_cmd_send_version( @@ -178,7 +179,7 @@ static void bio2_emu_bi2a_send_status( static int16_t tt_mult_delta(size_t tt_no) { - int16_t current_tt = iidx_io_ep2_get_turntable(tt_no); + int16_t current_tt = bt_io_iidx_ep2_turntable_get(tt_no); int16_t delta = get_wrapped_delta_s16(current_tt, tt_last[tt_no], 256); tt_last[tt_no] = current_tt; @@ -233,17 +234,17 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req) } } - iidx_io_ep1_set_deck_lights(packed_lights.deck_lights); - iidx_io_ep1_set_panel_lights(packed_lights.panel_lights); - iidx_io_ep1_set_top_lamps(packed_lights.top_lamps); - iidx_io_ep1_set_top_neons(req_bi2a->NEONLAMP.l_state); + bt_io_iidx_ep1_deck_lights_set(packed_lights.deck_lights); + bt_io_iidx_ep1_panel_lights_set(packed_lights.panel_lights); + bt_io_iidx_ep1_top_lamps_set(packed_lights.top_lamps); + bt_io_iidx_ep1_top_neons_set(req_bi2a->NEONLAMP.l_state); - if (!iidx_io_ep1_send()) { + if (!bt_io_iidx_ep1_send()) { log_warning("BIO2: iidx_io_ep1_send error"); return bio2_emu_bi2a_send_status(emu, req, 0); } - if (!iidx_io_ep3_write_16seg((const char *) req_bi2a->SEG16)) { + if (!bt_io_iidx_ep3_16seg_send((const char *) req_bi2a->SEG16)) { log_warning("BIO2: iidx_io_ep3_write_16seg error"); return bio2_emu_bi2a_send_status(emu, req, 0); } @@ -256,7 +257,7 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req) Sleep(1); } - if (!iidx_io_ep2_recv()) { + if (!bt_io_iidx_ep2_recv()) { log_warning("BIO2: iidx_io_ep2_recv error"); return bio2_emu_bi2a_send_status(emu, req, 0); } @@ -268,52 +269,52 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req) body->TURNTABLE1 = tt_accum[0]; body->TURNTABLE2 = tt_accum[1]; } else { - body->TURNTABLE1 = iidx_io_ep2_get_turntable(0); - body->TURNTABLE2 = iidx_io_ep2_get_turntable(1); + body->TURNTABLE1 = bt_io_iidx_ep2_turntable_get(0); + body->TURNTABLE2 = bt_io_iidx_ep2_turntable_get(1); } body->SLIDER1.s_val = get_default_slider_valid(0) ? default_sliders[0] : - iidx_io_ep2_get_slider(0); + bt_io_iidx_ep2_slider_get(0); body->SLIDER2.s_val = get_default_slider_valid(1) ? default_sliders[1] : - iidx_io_ep2_get_slider(1); + bt_io_iidx_ep2_slider_get(1); body->SLIDER3.s_val = get_default_slider_valid(2) ? default_sliders[2] : - iidx_io_ep2_get_slider(2); + bt_io_iidx_ep2_slider_get(2); body->SLIDER4.s_val = get_default_slider_valid(3) ? default_sliders[3] : - iidx_io_ep2_get_slider(3); + bt_io_iidx_ep2_slider_get(3); body->SLIDER5.s_val = get_default_slider_valid(4) ? default_sliders[4] : - iidx_io_ep2_get_slider(4); - - input_keys = iidx_io_ep2_get_keys(); - input_sys = iidx_io_ep2_get_sys(); - input_panel = iidx_io_ep2_get_panel(); - body->P1SW1.b_val = (input_keys >> IIDX_IO_KEY_P1_1) & 1; - body->P1SW2.b_val = (input_keys >> IIDX_IO_KEY_P1_2) & 1; - body->P1SW3.b_val = (input_keys >> IIDX_IO_KEY_P1_3) & 1; - body->P1SW4.b_val = (input_keys >> IIDX_IO_KEY_P1_4) & 1; - body->P1SW5.b_val = (input_keys >> IIDX_IO_KEY_P1_5) & 1; - body->P1SW6.b_val = (input_keys >> IIDX_IO_KEY_P1_6) & 1; - body->P1SW7.b_val = (input_keys >> IIDX_IO_KEY_P1_7) & 1; - body->P2SW1.b_val = (input_keys >> IIDX_IO_KEY_P2_1) & 1; - body->P2SW2.b_val = (input_keys >> IIDX_IO_KEY_P2_2) & 1; - body->P2SW3.b_val = (input_keys >> IIDX_IO_KEY_P2_3) & 1; - body->P2SW4.b_val = (input_keys >> IIDX_IO_KEY_P2_4) & 1; - body->P2SW5.b_val = (input_keys >> IIDX_IO_KEY_P2_5) & 1; - body->P2SW6.b_val = (input_keys >> IIDX_IO_KEY_P2_6) & 1; - body->P2SW7.b_val = (input_keys >> IIDX_IO_KEY_P2_7) & 1; - - body->PANEL.y_start1 = (input_panel >> IIDX_IO_PANEL_P1_START) & 1; - body->PANEL.y_start2 = (input_panel >> IIDX_IO_PANEL_P2_START) & 1; - body->PANEL.y_vefx = (input_panel >> IIDX_IO_PANEL_VEFX) & 1; - body->PANEL.y_effect = (input_panel >> IIDX_IO_PANEL_EFFECT) & 1; - - body->SYSTEM.v_test = (input_sys >> IIDX_IO_SYS_TEST) & 1; - body->SYSTEM.v_service = (input_sys >> IIDX_IO_SYS_SERVICE) & 1; - body->SYSTEM.v_coin = (input_sys >> IIDX_IO_SYS_COIN) & 1; + bt_io_iidx_ep2_slider_get(4); + + input_keys = bt_io_iidx_ep2_keys_get(); + input_sys = bt_io_iidx_ep2_sys_get(); + input_panel = bt_io_iidx_ep2_panel_get(); + body->P1SW1.b_val = (input_keys >> BT_IO_IIDX_KEY_P1_1) & 1; + body->P1SW2.b_val = (input_keys >> BT_IO_IIDX_KEY_P1_2) & 1; + body->P1SW3.b_val = (input_keys >> BT_IO_IIDX_KEY_P1_3) & 1; + body->P1SW4.b_val = (input_keys >> BT_IO_IIDX_KEY_P1_4) & 1; + body->P1SW5.b_val = (input_keys >> BT_IO_IIDX_KEY_P1_5) & 1; + body->P1SW6.b_val = (input_keys >> BT_IO_IIDX_KEY_P1_6) & 1; + body->P1SW7.b_val = (input_keys >> BT_IO_IIDX_KEY_P1_7) & 1; + body->P2SW1.b_val = (input_keys >> BT_IO_IIDX_KEY_P2_1) & 1; + body->P2SW2.b_val = (input_keys >> BT_IO_IIDX_KEY_P2_2) & 1; + body->P2SW3.b_val = (input_keys >> BT_IO_IIDX_KEY_P2_3) & 1; + body->P2SW4.b_val = (input_keys >> BT_IO_IIDX_KEY_P2_4) & 1; + body->P2SW5.b_val = (input_keys >> BT_IO_IIDX_KEY_P2_5) & 1; + body->P2SW6.b_val = (input_keys >> BT_IO_IIDX_KEY_P2_6) & 1; + body->P2SW7.b_val = (input_keys >> BT_IO_IIDX_KEY_P2_7) & 1; + + body->PANEL.y_start1 = (input_panel >> BT_IO_IIDX_PANEL_P1_START) & 1; + body->PANEL.y_start2 = (input_panel >> BT_IO_IIDX_PANEL_P2_START) & 1; + body->PANEL.y_vefx = (input_panel >> BT_IO_IIDX_PANEL_VEFX) & 1; + body->PANEL.y_effect = (input_panel >> BT_IO_IIDX_PANEL_EFFECT) & 1; + + body->SYSTEM.v_test = (input_sys >> BT_IO_IIDX_SYS_TEST) & 1; + body->SYSTEM.v_service = (input_sys >> BT_IO_IIDX_SYS_SERVICE) & 1; + body->SYSTEM.v_coin = (input_sys >> BT_IO_IIDX_SYS_COIN) & 1; if (body->SYSTEM.v_coin) { if (!coin_latch) { diff --git a/src/main/bio2emu/emu.c b/src/main/bio2emu/emu.c index 9fbcb3d8..81f73d01 100644 --- a/src/main/bio2emu/emu.c +++ b/src/main/bio2emu/emu.c @@ -20,12 +20,13 @@ #include "bio2emu/emu.h" #include "bio2emu/setupapi.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "util/array.h" #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct array bio2_active_ports; diff --git a/src/main/bio2emu/setupapi.c b/src/main/bio2emu/setupapi.c index 5dbfffc7..cb74bd16 100644 --- a/src/main/bio2emu/setupapi.c +++ b/src/main/bio2emu/setupapi.c @@ -6,13 +6,14 @@ #include #include -#include "hook/table.h" - #include "bio2emu/emu.h" #include "bio2emu/setupapi.h" +#include "hook/table.h" + +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #include "util/time.h" diff --git a/src/main/bsthook/Module.mk b/src/main/bsthook/Module.mk index ef61d283..22a7615e 100644 --- a/src/main/bsthook/Module.mk +++ b/src/main/bsthook/Module.mk @@ -3,13 +3,18 @@ avsdlls += bsthook deplibs_bsthook := \ avs \ +avslibs_bsthook := \ + avs-ext \ + libs_bsthook := \ + util \ + core \ acioemu \ - bstio \ hook \ hooklib \ - util \ - eamio \ + iface-io \ + module \ + iface-core \ src_bsthook := \ acio.c \ diff --git a/src/main/bsthook/acio.c b/src/main/bsthook/acio.c index fe5f8cc1..3aa641a3 100644 --- a/src/main/bsthook/acio.c +++ b/src/main/bsthook/acio.c @@ -19,13 +19,14 @@ #include "bsthook/acio.h" #include "bsthook/kfca.h" +#include "iface-core/log.h" + #include "hook/iohook.h" #include "imports/avs.h" #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu ac_io_emu; diff --git a/src/main/bsthook/acio.h b/src/main/bsthook/acio.h index d6d6ee2f..57d7c65f 100644 --- a/src/main/bsthook/acio.h +++ b/src/main/bsthook/acio.h @@ -3,6 +3,9 @@ #include +#include "api/io/bst.h" +#include "api/io/eam.h" + #include "hook/iohook.h" void ac_io_bus_init(void); diff --git a/src/main/bsthook/bsthook.def b/src/main/bsthook/bsthook.def index 70715743..10517fc2 100644 --- a/src/main/bsthook/bsthook.def +++ b/src/main/bsthook/bsthook.def @@ -2,3 +2,8 @@ LIBRARY bsthook EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/bsthook/dllmain.c b/src/main/bsthook/dllmain.c index 57d38e03..29dcff1d 100644 --- a/src/main/bsthook/dllmain.c +++ b/src/main/bsthook/dllmain.c @@ -2,121 +2,156 @@ #include -#include "bemanitools/bstio.h" -#include "bemanitools/eamio.h" +#include "bsthook/acio.h" +#include "bsthook/gfx.h" +#include "bsthook/settings.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/bst.h" +#include "iface-io/eam.h" #include "hook/iohook.h" -#include "hooklib/app.h" #include "hooklib/rs232.h" -#include "imports/avs.h" +#include "module/io-ext.h" -#include "bsthook/acio.h" -#include "bsthook/gfx.h" -#include "bsthook/settings.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" #include "util/cmdline.h" #include "util/defs.h" -#include "util/log.h" -static bool my_dll_entry_init(char *sidcode, struct property_node *config); -static bool my_dll_entry_main(void); +static module_io_t *_bsthook_module_io_bst; +static module_io_t *_bsthook_module_io_eam; + +static void _bsthook_io_bst_init(module_io_t **module) +{ + bt_io_bst_api_t api; + + module_io_ext_load_and_init( + "bstio.dll", "bt_module_io_bst_api_get", module); + module_io_api_get(*module, &api); + bt_io_bst_api_set(&api); +} + +static void _bsthook_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; -static bool my_dll_entry_init(char *sidcode, struct property_node *config) + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_bsthook_main_init(HMODULE game_module, const bt_core_config_t *config_) { + int i; + int argc; + char **argv; bool ok; - log_info("--- Begin bsthook dll_entry_init ---"); + args_recover(&argc, &argv); - ac_io_bus_init(); + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + continue; + } + + switch (argv[i][1]) { + case 'w': + gfx_set_windowed(); + + break; + } + } + + args_free(argc, argv); + + iohook_push_handler(ac_io_bus_dispatch_irp); + rs232_hook_init(); + + gfx_init(); + settings_hook_init(); + + log_info("--- Begin bsthook dll_entry_init ---"); log_info("Starting up BeatStream IO backend"); - bst_io_set_loggers( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); + _bsthook_io_bst_init(&_bsthook_module_io_bst); - ok = bst_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + ok = bt_io_bst_init(); if (!ok) { goto bst_io_fail; } - eam_io_set_loggers( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); + _bsthook_io_eam_init(&_bsthook_module_io_eam); - ok = eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + ok = bt_io_eam_init(); if (!ok) { goto eam_io_fail; } + ac_io_bus_init(); + log_info("--- End bsthook dll_entry_init ---"); - return app_hook_invoke_init(sidcode, config); + return true; eam_io_fail: - bst_io_fini(); + bt_io_bst_fini(); + + bt_io_bst_api_clear(); + module_io_free(&_bsthook_module_io_bst); bst_io_fail: - ac_io_bus_fini(); return false; } -static bool my_dll_entry_main(void) +static void _bsthook_main_fini() { - bool result; + log_info("Shutting down card reader backend"); + bt_io_eam_fini(); - result = app_hook_invoke_main(); + bt_io_eam_api_clear(); + module_io_free(&_bsthook_module_io_eam); - log_info("Shutting down card reader backend"); - eam_io_fini(); + log_info("Shutting down BeatStream IO backend"); + bt_io_bst_fini(); - log_info("Shutting down SDVX IO backend"); - bst_io_fini(); + bt_io_bst_api_clear(); + module_io_free(&_bsthook_module_io_bst); ac_io_bus_fini(); - - return result; } -BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - int i; - int argc; - char **argv; - - if (reason != DLL_PROCESS_ATTACH) { - return TRUE; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - args_recover(&argc, &argv); - - for (i = 1; i < argc; i++) { - if (argv[i][0] != '-') { - continue; - } - - switch (argv[i][1]) { - case 'w': - gfx_set_windowed(); - - break; - } - } + bt_core_log_api_set(api); +} - args_free(argc, argv); +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} - app_hook_init(my_dll_entry_init, my_dll_entry_main); - iohook_push_handler(ac_io_bus_dispatch_irp); - rs232_hook_init(); +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; - gfx_init(); - settings_hook_init(); + api->v1.main_init = _bsthook_main_init; + api->v1.main_fini = _bsthook_main_fini; +} +BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +{ return TRUE; } diff --git a/src/main/bsthook/gfx.c b/src/main/bsthook/gfx.c index 43d88a2d..ae98eb07 100644 --- a/src/main/bsthook/gfx.c +++ b/src/main/bsthook/gfx.c @@ -3,6 +3,8 @@ #include +#include "iface-core/log.h" + #include "hook/com-proxy.h" #include "hook/pe.h" #include "hook/table.h" @@ -10,7 +12,6 @@ #include "sdvxhook/gfx.h" #include "util/defs.h" -#include "util/log.h" static HRESULT STDCALL my_CreateDevice( IDirect3D9 *self, diff --git a/src/main/bsthook/kfca.c b/src/main/bsthook/kfca.c index 0e3ff02e..0ff4b5fb 100644 --- a/src/main/bsthook/kfca.c +++ b/src/main/bsthook/kfca.c @@ -7,7 +7,7 @@ #include "acioemu/emu.h" -#include "bemanitools/bstio.h" +#include "iface-io/bst.h" #include "util/defs.h" @@ -122,7 +122,7 @@ static void kfca_poll(const struct ac_io_message *req) struct ac_io_message resp; struct ac_io_kfca_poll_in *pin; - bst_io_read_input(); + bt_io_bst_input_read(); pin = &resp.cmd.kfca_poll_in; @@ -133,7 +133,7 @@ static void kfca_poll(const struct ac_io_message *req) memset(pin, 0, sizeof(*pin)); - pin->gpio_sys = ac_io_u16(bst_io_get_input()); + pin->gpio_sys = ac_io_u16(bt_io_bst_input_get()); ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0); } diff --git a/src/main/bsthook/settings.c b/src/main/bsthook/settings.c index 8f48ea8e..36cac884 100644 --- a/src/main/bsthook/settings.c +++ b/src/main/bsthook/settings.c @@ -7,10 +7,11 @@ #include #include +#include "iface-core/log.h" + #include "hook/table.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" /* ------------------------------------------------------------------------- */ diff --git a/src/main/bstio/Module.mk b/src/main/bstio/Module.mk index 1e37a612..61288b94 100644 --- a/src/main/bstio/Module.mk +++ b/src/main/bstio/Module.mk @@ -1,7 +1,11 @@ dlls += bstio libs_bstio := \ - geninput \ + module \ + iface-core \ + core \ + iface \ + util \ src_bstio := \ bstio.c \ diff --git a/src/main/bstio/bstio.c b/src/main/bstio/bstio.c index c719074e..d3e90b4d 100644 --- a/src/main/bstio/bstio.c +++ b/src/main/bstio/bstio.c @@ -1,46 +1,83 @@ +#define LOG_MODULE "bstio" + #include #include #include -#include "bemanitools/bstio.h" -#include "bemanitools/glue.h" -#include "bemanitools/input.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/input.h" + +#include "module/input.h" + +#include "main/module/input-ext.h" +#include "main/module/input.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/bst.h" + +static module_input_t *_bst_io_module_input; +static uint8_t _bst_io_gpio_sys; + +bool bt_io_bst_init() +{ + bool result; + bt_input_api_t input_api; + + module_input_ext_load_and_init("geninput.dll", &_bst_io_module_input); + module_input_api_get(_bst_io_module_input, &input_api); + bt_input_api_set(&input_api); -static uint8_t bst_io_gpio_sys; + result = bt_input_init(); -void bst_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) + if (!result) { + return false; + } + + return bt_input_mapper_config_load("bst"); +} + +void bt_io_bst_fini() { - input_set_loggers(misc, info, warning, fatal); + bt_input_fini(); + + bt_input_api_clear(); + module_input_free(&_bst_io_module_input); } -bool bst_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_bst_input_read() { - input_init(thread_create, thread_join, thread_destroy); - mapper_config_load("bst"); + _bst_io_gpio_sys = bt_input_mapper_update(); return true; } -void bst_io_fini(void) +uint8_t bt_io_bst_input_get() { - input_fini(); + return _bst_io_gpio_sys; } -bool bst_io_read_input(void) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - bst_io_gpio_sys = mapper_update(); - - return true; + bt_core_log_api_set(api); } -uint8_t bst_io_get_input(void) +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) { - return bst_io_gpio_sys; + bt_core_thread_api_set(api); } + +void bt_module_io_bst_api_get(bt_io_bst_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_bst_init; + api->v1.fini = bt_io_bst_fini; + api->v1.input_read = bt_io_bst_input_read; + api->v1.input_get = bt_io_bst_input_get; +} \ No newline at end of file diff --git a/src/main/bstio/bstio.def b/src/main/bstio/bstio.def index 7c85a5f7..0cef03d5 100644 --- a/src/main/bstio/bstio.def +++ b/src/main/bstio/bstio.def @@ -1,8 +1,13 @@ LIBRARY bstio EXPORTS - bst_io_fini - bst_io_get_input - bst_io_init - bst_io_read_input - bst_io_set_loggers + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_bst_api_get + + ; Direct API + bt_io_bst_init + bt_io_bst_fini + bt_io_bst_input_read + bt_io_bst_input_get diff --git a/src/main/camhook/Module.mk b/src/main/camhook/Module.mk index 0a6b19e7..ee812622 100644 --- a/src/main/camhook/Module.mk +++ b/src/main/camhook/Module.mk @@ -1,9 +1,10 @@ libs += camhook libs_camhook := \ + core \ + iface-core \ hook \ hooklib \ - cconfig \ util \ src_camhook := \ diff --git a/src/main/camhook/cam-detect.c b/src/main/camhook/cam-detect.c index cbff8bec..ccc4155d 100644 --- a/src/main/camhook/cam-detect.c +++ b/src/main/camhook/cam-detect.c @@ -17,8 +17,9 @@ #include "camhook/cam-detect.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/str.h" EXTERN_GUID( diff --git a/src/main/camhook/cam.c b/src/main/camhook/cam.c index db380f13..a0357f96 100644 --- a/src/main/camhook/cam.c +++ b/src/main/camhook/cam.c @@ -17,6 +17,10 @@ #include +#include "camhook/cam.h" + +#include "iface-core/log.h" + #include "hook/com-proxy.h" #include "hook/table.h" @@ -24,7 +28,6 @@ #include "camhook/cam-detect.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #define CAMHOOK_NUM_LAYOUTS 3 diff --git a/src/main/camhook/config-cam.c b/src/main/camhook/config-cam.c index 43a852b6..41714d06 100644 --- a/src/main/camhook/config-cam.c +++ b/src/main/camhook/config-cam.c @@ -1,126 +1,30 @@ -#include "cconfig/cconfig-util.h" - #include "camhook/config-cam.h" -#include "util/log.h" - -#define CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY "cam.disable_emu" -#define CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE false - -#define CAMHOOK_CONFIG_CAM_PORT_LAYOUT_KEY "cam.port_layout" -#define CAMHOOK_CONFIG_CAM_DEFAULT_PORT_LAYOUT_VALUE 0 - -// the following four arrays are based on CAMHOOK_CONFIG_CAM_MAX -// please insert more elements if more cams are added -const char *camhook_config_disable_camera[CAMHOOK_CONFIG_CAM_MAX] = { - "cam.disable_camera1", - "cam.disable_camera2", -}; - -const int camhook_config_disable_camera_default_values[CAMHOOK_CONFIG_CAM_MAX] = - { - false, - false, -}; - -const char *camhook_config_device_id_keys[CAMHOOK_CONFIG_CAM_MAX] = { - "cam.device_id1", - "cam.device_id2", -}; - -const char *camhook_config_device_default_values[CAMHOOK_CONFIG_CAM_MAX] = { - "", - "", -}; - -void camhook_config_cam_init(struct cconfig *config, size_t num_cams, bool use_port_layout) -{ - cconfig_util_set_bool( - config, - CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY, - CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE, - "Disables the camera emulation"); +#include "core/config-ext.h" - if (use_port_layout) { - cconfig_util_set_int( - config, - CAMHOOK_CONFIG_CAM_PORT_LAYOUT_KEY, - CAMHOOK_CONFIG_CAM_DEFAULT_PORT_LAYOUT_VALUE, - "Camera port layout (0 = LDJ, 1 = CLDJ/TDJ-JA, 2 = TDJ-JB)"); - } +#include "iface-core/log.h" - for (size_t i = 0; i < num_cams; ++i) { - cconfig_util_set_bool( - config, - camhook_config_disable_camera[i], - camhook_config_disable_camera_default_values[i], - "Disable camera"); - cconfig_util_set_str( - config, - camhook_config_device_id_keys[i], - camhook_config_device_default_values[i], - "Override camera device ID detection (copy from device manager, do " - "not escape)"); - } -} +#include "util/str.h" void camhook_config_cam_get( - struct camhook_config_cam *config_cam, - struct cconfig *config, + const bt_core_config_t *config, + camhook_config_cam_t *config_cam, size_t num_cams, bool use_port_layout) { - config_cam->num_devices = num_cams; + char key[32]; - if (!cconfig_util_get_bool( - config, - CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY, - &config_cam->disable_emu, - CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY, - CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE); - } + bt_core_config_ext_bool_get(config, "camera/disable_emu", &config_cam->disable_emu); if (use_port_layout) { - if (!cconfig_util_get_int( - config, - CAMHOOK_CONFIG_CAM_PORT_LAYOUT_KEY, - &config_cam->port_layout, - CAMHOOK_CONFIG_CAM_DEFAULT_PORT_LAYOUT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - CAMHOOK_CONFIG_CAM_PORT_LAYOUT_KEY, - CAMHOOK_CONFIG_CAM_DEFAULT_PORT_LAYOUT_VALUE); - } + bt_core_config_ext_s32_get(config, "camera/port_layout", &config_cam->port_layout); } for (size_t i = 0; i < num_cams; ++i) { - if (!cconfig_util_get_bool( - config, - camhook_config_disable_camera[i], - &config_cam->disable_camera[i], - camhook_config_disable_camera_default_values[i])) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - camhook_config_disable_camera[i], - camhook_config_disable_camera_default_values[i]); - } - if (!cconfig_util_get_str( - config, - camhook_config_device_id_keys[i], - config_cam->device_id[i], - sizeof(config_cam->device_id[i]) - 1, - camhook_config_device_default_values[i])) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - camhook_config_device_id_keys[i], - camhook_config_device_default_values[i]); - } - } -} + str_format(key, sizeof(key), "camera/device_%d/disable", i); + bt_core_config_ext_bool_get(config, key, &config_cam->disable_camera[i]); + + str_format(key, sizeof(key), "camera/device_%d/id", i); + bt_core_config_ext_str_get(config, key, config_cam->device_id[i], sizeof(config_cam->device_id[i]) - 1); + } +} \ No newline at end of file diff --git a/src/main/camhook/config-cam.h b/src/main/camhook/config-cam.h index df0ad7d0..d72b1f8a 100644 --- a/src/main/camhook/config-cam.h +++ b/src/main/camhook/config-cam.h @@ -3,26 +3,21 @@ #include -#include "cconfig/cconfig.h" +#include "iface-core/config.h" #define CAMHOOK_CONFIG_CAM_MAX 2 -struct camhook_config_cam { +typedef struct camhook_config_cam { bool disable_emu; size_t num_devices; int port_layout; char device_id[CAMHOOK_CONFIG_CAM_MAX][MAX_PATH]; bool disable_camera[CAMHOOK_CONFIG_CAM_MAX]; -}; - -void camhook_config_cam_init( - struct cconfig *config, - size_t num_cams, - bool use_port_layout); +} camhook_config_cam_t; void camhook_config_cam_get( - struct camhook_config_cam *config_cam, - struct cconfig *config, + const bt_core_config_t *config, + camhook_config_cam_t *config_cam, size_t num_cams, bool use_port_layout); diff --git a/src/main/cconfig/Module.mk b/src/main/cconfig/Module.mk deleted file mode 100644 index 5f16b1d7..00000000 --- a/src/main/cconfig/Module.mk +++ /dev/null @@ -1,12 +0,0 @@ -libs += cconfig - -libs_cconfig := \ - util \ - -src_cconfig := \ - cconfig-main.c \ - cconfig-hook.c \ - cconfig-util.c \ - cconfig.c \ - cmd.c \ - conf.c \ diff --git a/src/main/cconfig/cconfig-hook.c b/src/main/cconfig/cconfig-hook.c deleted file mode 100644 index e917fa7b..00000000 --- a/src/main/cconfig/cconfig-hook.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "cconfig/cconfig-util.h" -#include "cconfig/cmd.h" - -#include "cconfig/cconfig-hook.h" -#include "cconfig/cconfig-main.h" - -bool cconfig_hook_config_init( - struct cconfig *config, - const char *usage_header, - enum cconfig_cmd_usage_out cmd_usage_out) -{ - return cconfig_main_config_init( - config, "--config", NULL, "--help", "-h", usage_header, cmd_usage_out); -} diff --git a/src/main/cconfig/cconfig-hook.h b/src/main/cconfig/cconfig-hook.h deleted file mode 100644 index 055464db..00000000 --- a/src/main/cconfig/cconfig-hook.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef CCONFIG_HOOK_H -#define CCONFIG_HOOK_H - -#include "cconfig/cconfig.h" -#include "cconfig/cmd.h" - -/** - * Init function for cconfig for hooks - * - * calls cconfig_main_config_init with some defaults for hook dlls - * see: cconfig_main_config_init for more details - */ -bool cconfig_hook_config_init( - struct cconfig *config, - const char *usage_header, - enum cconfig_cmd_usage_out cmd_usage_out); - -#endif diff --git a/src/main/cconfig/cconfig-main.c b/src/main/cconfig/cconfig-main.c deleted file mode 100644 index 342a9120..00000000 --- a/src/main/cconfig/cconfig-main.c +++ /dev/null @@ -1,113 +0,0 @@ -#include - -#include "cconfig/cconfig-util.h" -#include "cconfig/cmd.h" -#include "cconfig/conf.h" - -#include "cconfig/cconfig-main.h" - -#include "util/cmdline.h" -#include "util/log.h" - -bool cconfig_main_config_init( - struct cconfig *config, - const char *config_parameter_name, - const char *default_config_path, - const char *help_parameter_name, - const char *help_parameter_short_name, - const char *usage_header, - enum cconfig_cmd_usage_out cmd_usage_out) -{ - bool success; - int argc; - char **argv; - enum cconfig_conf_error conf_error; - const char *config_path; - - success = true; - - args_recover(&argc, &argv); - - for (int i = 0; i < argc; i++) { - if (!strcmp(argv[i], help_parameter_short_name) || - !strcmp(argv[i], help_parameter_name)) { - goto failure_usage; - } - } - - config_path = NULL; - - if (config_parameter_name != NULL) { - for (int i = 0; i < argc; i++) { - if (!strcmp(argv[i], config_parameter_name)) { - if (i + 1 >= argc) { - log_fatal( - "--config parameter not followed by a config file " - "path param"); - goto failure; - } - - config_path = argv[i + 1]; - - break; - } - } - } - - if (config_path == NULL && default_config_path != NULL) { - log_misc("Using default config path: %s", default_config_path); - config_path = default_config_path; - } - - if (config_path) { - log_misc("Loading config file: %s", config_path); - conf_error = cconfig_conf_load_from_file(config, config_path, false); - - if (conf_error == CCONFIG_CONF_ERROR_NO_SUCH_FILE) { - /* Create default config */ - if (cconfig_conf_save_to_file(config, config_path) != - CCONFIG_CONF_SUCCESS) { - log_fatal( - "Creating default config file '%s' failed", config_path); - goto failure; - } else { - log_info( - "Default configuration '%s' created. Restart " - "application", - config_path); - goto failure; - } - } else if (conf_error != CCONFIG_CONF_SUCCESS) { - log_fatal( - "Error loading config file '%s': %d", config_path, conf_error); - goto failure; - } - - log_misc("Config state after file loading:"); - cconfig_util_log(config, log_impl_misc); - } - - log_misc("Parsing override config parameters from cmd"); - - /* Override defaults or values loaded from file with values from cmd */ - if (!cconfig_cmd_parse(config, "-p", argc, argv, false)) { - log_fatal("Error parsing cmd args for config values"); - goto failure_usage; - } - - log_misc("Config state after cmd parameter overrides:"); - cconfig_util_log(config, log_impl_misc); - - goto success; - -failure_usage: - cconfig_cmd_print_usage(config, usage_header, cmd_usage_out); - -failure: - success = false; - -success: - args_free(argc, argv); - - return success; -} diff --git a/src/main/cconfig/cconfig-main.h b/src/main/cconfig/cconfig-main.h deleted file mode 100644 index eea223ac..00000000 --- a/src/main/cconfig/cconfig-main.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CCONFIG_MAIN_H -#define CCONFIG_MAIN_H - -#include "cconfig/cconfig.h" -#include "cconfig/cmd.h" - -/** - * Init function for cconfig after all cconfig_util_set's have been called - * - * will parse a config file first (if specified) - * then uses override config parameters from cmd - */ -bool cconfig_main_config_init( - struct cconfig *config, - const char *config_cmd_param_name, - const char *config_default_path, - const char *help_cmd_param_name, - const char *help_cmd_param_shortname, - const char *usage_header, - enum cconfig_cmd_usage_out cmd_usage_out); - -#endif diff --git a/src/main/cconfig/cconfig-util.c b/src/main/cconfig/cconfig-util.c deleted file mode 100644 index f4ce05f3..00000000 --- a/src/main/cconfig/cconfig-util.c +++ /dev/null @@ -1,232 +0,0 @@ -#define LOG_MODULE "cconfig-util" - -#include -#include - -#include "cconfig/cconfig-util.h" - -#include "util/hex.h" -#include "util/log.h" -#include "util/mem.h" - -bool cconfig_util_get_int( - struct cconfig *config, - const char *key, - int32_t *ret, - int32_t default_value) -{ - struct cconfig_entry *entry; - - log_assert(config); - log_assert(key); - - entry = cconfig_get(config, key); - - if (entry) { - if (sscanf(entry->value, "%d", ret) == 1) { - return true; - } - } - - *ret = default_value; - return false; -} - -bool cconfig_util_get_float( - struct cconfig *config, const char *key, float *ret, float default_value) -{ - struct cconfig_entry *entry; - - log_assert(config); - log_assert(key); - - entry = cconfig_get(config, key); - - if (entry) { - if (sscanf(entry->value, "%f", ret) == 1) { - return true; - } - } - - *ret = default_value; - return false; -} - -bool cconfig_util_get_bool( - struct cconfig *config, const char *key, bool *ret, bool default_value) -{ - struct cconfig_entry *entry; - - log_assert(config); - log_assert(key); - - entry = cconfig_get(config, key); - - if (entry) { - if (!strcmp(entry->value, "true")) { - *ret = true; - return true; - } else if (!strcmp(entry->value, "false")) { - *ret = false; - return true; - } - } - - *ret = default_value; - return false; -} - -bool cconfig_util_get_str( - struct cconfig *config, - const char *key, - char *buffer, - size_t len, - const char *default_value) -{ - struct cconfig_entry *entry; - size_t str_len; - - log_assert(config); - log_assert(key); - - entry = cconfig_get(config, key); - - if (entry) { - str_len = strlen(entry->value); - - if (str_len <= len) { - strcpy(buffer, entry->value); - return true; - } - } - - strcpy(buffer, default_value); - return false; -} - -bool cconfig_util_get_data( - struct cconfig *config, - const char *key, - uint8_t *buffer, - size_t len, - const uint8_t *default_value) -{ - size_t res_len; - struct cconfig_entry *entry; - - log_assert(config); - log_assert(key); - log_assert(len); - - entry = cconfig_get(config, key); - - if (entry) { - res_len = strlen(entry->value); - res_len = res_len / 2 + res_len % 2; - - if (len <= res_len) { - if (hex_decode(buffer, len, entry->value, strlen(entry->value))) { - return true; - } - } - } - - memcpy(buffer, default_value, len); - return false; -} - -void cconfig_util_set_int( - struct cconfig *config, const char *key, int32_t value, const char *desc) -{ - char *str; - size_t str_len; - - log_assert(config); - log_assert(key); - log_assert(desc); - - str_len = snprintf(NULL, 0, "%d", value) + 1; - str = xmalloc(str_len); - snprintf(str, str_len, "%d", value); - - cconfig_set(config, key, str, desc); - - free(str); -} - -void cconfig_util_set_float( - struct cconfig *config, const char *key, float value, const char *desc) -{ - char *str; - size_t str_len; - - log_assert(config); - log_assert(key); - log_assert(desc); - - str_len = snprintf(NULL, 0, "%f", value) + 1; - str = xmalloc(str_len); - snprintf(str, str_len, "%f", value); - - cconfig_set(config, key, str, desc); - - free(str); -} - -void cconfig_util_set_bool( - struct cconfig *config, const char *key, bool value, const char *desc) -{ - log_assert(config); - log_assert(key); - log_assert(desc); - - cconfig_set(config, key, value ? "true" : "false", desc); -} - -void cconfig_util_set_str( - struct cconfig *config, - const char *key, - const char *value, - const char *desc) -{ - log_assert(config); - log_assert(key); - log_assert(desc); - log_assert(value); - - cconfig_set(config, key, value, desc); -} - -void cconfig_util_set_data( - struct cconfig *config, - const char *key, - const uint8_t *value, - size_t len, - const char *desc) -{ - char *str; - size_t str_len; - - log_assert(config); - log_assert(key); - log_assert(desc); - - str_len = len * 2 + 1; - str = xmalloc(str_len); - hex_encode_uc(value, len, str, str_len); - - cconfig_set(config, key, str, desc); - - free(str); -} - -void cconfig_util_log(struct cconfig *config, log_formatter_t log_formatter) -{ - for (uint32_t i = 0; i < config->nentries; i++) { - log_formatter( - LOG_MODULE, - "%s=%s", - config->entries[i].key, - config->entries[i].value); - } -} \ No newline at end of file diff --git a/src/main/cconfig/cconfig-util.h b/src/main/cconfig/cconfig-util.h deleted file mode 100644 index aa9b5004..00000000 --- a/src/main/cconfig/cconfig-util.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef CCONFIG_UTIL_H -#define CCONFIG_UTIL_H - -#include -#include -#include - -#include "cconfig/cconfig.h" - -#include "util/log.h" - -bool cconfig_util_get_int( - struct cconfig *config, - const char *key, - int32_t *ret, - int32_t default_value); - -bool cconfig_util_get_float( - struct cconfig *config, const char *key, float *ret, float default_value); - -bool cconfig_util_get_bool( - struct cconfig *config, const char *key, bool *ret, bool default_value); - -bool cconfig_util_get_str( - struct cconfig *config, - const char *key, - char *buffer, - size_t len, - const char *default_value); - -bool cconfig_util_get_data( - struct cconfig *config, - const char *key, - uint8_t *buffer, - size_t len, - const uint8_t *default_value); - -void cconfig_util_set_int( - struct cconfig *config, const char *key, int32_t value, const char *desc); - -void cconfig_util_set_float( - struct cconfig *config, const char *key, float value, const char *desc); - -void cconfig_util_set_bool( - struct cconfig *config, const char *key, bool value, const char *desc); - -void cconfig_util_set_str( - struct cconfig *config, - const char *key, - const char *value, - const char *desc); - -void cconfig_util_set_data( - struct cconfig *config, - const char *key, - const uint8_t *value, - size_t len, - const char *desc); - -void cconfig_util_log(struct cconfig *config, log_formatter_t log_formatter); - -#endif \ No newline at end of file diff --git a/src/main/cconfig/cconfig.c b/src/main/cconfig/cconfig.c deleted file mode 100644 index 1cfcbedb..00000000 --- a/src/main/cconfig/cconfig.c +++ /dev/null @@ -1,114 +0,0 @@ -#include - -#include "cconfig/cconfig.h" - -#include "util/log.h" -#include "util/mem.h" -#include "util/str.h" - -static struct cconfig_entry *cconfig_extend_config(struct cconfig *config) -{ - config->nentries++; - - config->entries = xrealloc( - config->entries, config->nentries * sizeof(struct cconfig_entry)); - memset( - &config->entries[config->nentries - 1], - 0, - sizeof(struct cconfig_entry)); - - return &config->entries[config->nentries - 1]; -} - -struct cconfig *cconfig_init() -{ - struct cconfig *config; - - config = xmalloc(sizeof(struct cconfig)); - memset(config, 0, sizeof(struct cconfig)); - - return config; -} - -struct cconfig_entry *cconfig_get(struct cconfig *config, const char *key) -{ - log_assert(config); - log_assert(key); - - for (uint32_t i = 0; i < config->nentries; i++) { - if (!strcmp(config->entries[i].key, key)) { - return &config->entries[i]; - } - } - - return NULL; -} - -void cconfig_set( - struct cconfig *config, - const char *key, - const char *value, - const char *desc) -{ - struct cconfig_entry *entry; - - log_assert(config); - log_assert(key); - log_assert(value); - log_assert(desc); - - entry = cconfig_get(config, key); - - if (!entry) { - entry = cconfig_extend_config(config); - } else { - free(entry->key); - free(entry->value); - free(entry->desc); - - memset(entry, 0, sizeof(struct cconfig_entry)); - } - - entry->key = str_dup(key); - entry->desc = str_dup(desc); - entry->value = str_dup(value); -} - -void cconfig_set2(struct cconfig *config, const char *key, const char *value) -{ - struct cconfig_entry *entry; - - log_assert(config); - log_assert(key); - log_assert(value); - - entry = cconfig_get(config, key); - - if (!entry) { - entry = cconfig_extend_config(config); - } else { - free(entry->key); - free(entry->value); - } - - entry->key = str_dup(key); - entry->value = str_dup(value); - - /* Description optional, but do not wipe previous description if - available */ - if (!entry->desc) { - entry->desc = ""; - } -} - -void cconfig_finit(struct cconfig *config) -{ - for (uint32_t i = 0; i < config->nentries; i++) { - free(config->entries[i].key); - free(config->entries[i].value); - free(config->entries[i].desc); - } - - free(config->entries); - free(config); -} \ No newline at end of file diff --git a/src/main/cconfig/cconfig.h b/src/main/cconfig/cconfig.h deleted file mode 100644 index 4372deb1..00000000 --- a/src/main/cconfig/cconfig.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef CCONFIG_H -#define CCONFIG_H - -#include -#include -#include - -struct cconfig_entry { - char *key; - char *value; - char *desc; -}; - -struct cconfig { - uint32_t nentries; - struct cconfig_entry *entries; -}; - -struct cconfig *cconfig_init(); - -struct cconfig_entry *cconfig_get(struct cconfig *config, const char *key); - -void cconfig_set( - struct cconfig *config, - const char *key, - const char *value, - const char *desc); - -void cconfig_set2(struct cconfig *config, const char *key, const char *value); - -void cconfig_finit(struct cconfig *config); - -#endif \ No newline at end of file diff --git a/src/main/cconfig/cmd.c b/src/main/cconfig/cmd.c deleted file mode 100644 index 3d4f32fc..00000000 --- a/src/main/cconfig/cmd.c +++ /dev/null @@ -1,141 +0,0 @@ -#define LOG_MODULE "cconfig-cmd" - -#include -#include -#include -#include - -#include "cconfig/cmd.h" - -#include "util/hex.h" -#include "util/log.h" -#include "util/str.h" - -static void -cconfig_cmd_usage_print(enum cconfig_cmd_usage_out output, const char *fmt, ...) -{ - char buffer[32768]; - va_list ap; - - va_start(ap, fmt); - - switch (output) { - case CCONFIG_CMD_USAGE_OUT_STDOUT: - vfprintf(stdout, fmt, ap); - break; - - case CCONFIG_CMD_USAGE_OUT_STDERR: - vfprintf(stderr, fmt, ap); - break; - - case CCONFIG_CMD_USAGE_OUT_DBG: - _vsnprintf(buffer, sizeof(buffer), fmt, ap); - OutputDebugString(buffer); - break; - - case CCONFIG_CMD_USAGE_OUT_LOG: - _vsnprintf(buffer, sizeof(buffer), fmt, ap); - log_info("%s", buffer); - break; - - default: - log_assert(false); - break; - } - - va_end(ap); -} - -bool cconfig_cmd_parse( - struct cconfig *config, - const char *key_ident, - int argc, - char **argv, - bool add_params_if_absent) -{ - bool no_error; - struct cconfig_entry *entry; - char *tmp; - char *cur_tok; - int ntok; - char *toks[2]; - - no_error = true; - - for (int i = 0; i < argc; i++) { - if (!strcmp(argv[i], key_ident)) { - if (i + 1 >= argc) { - no_error = false; - break; - } - - /* Not another key ident is following */ - if (!strcmp(argv[i + 1], key_ident)) { - no_error = false; - break; - } - - ++i; - - tmp = str_dup(argv[i]); - ntok = 0; - - cur_tok = strtok(tmp, "="); - - while (cur_tok != NULL) { - toks[ntok] = cur_tok; - ntok++; - cur_tok = strtok(NULL, "="); - - if (ntok == 2) { - break; - } - } - - if (ntok != 2) { - /* Tokenizing key=value parameter error */ - log_warning("Parsing parameter '%s' failed, ignore", argv[i]); - - free(tmp); - no_error = false; - continue; - } - - log_misc("Key: %s, Value: %s", toks[0], toks[1]); - - entry = cconfig_get(config, toks[0]); - - if (entry || add_params_if_absent) { - cconfig_set2(config, toks[0], toks[1]); - } else { - /* Ignore cmd params that are not found in config */ - log_warning( - "Could not find cmd parameter with key '%s' in " - "config, ignored", - toks[0]); - } - - free(tmp); - } - } - - return no_error; -} - -void cconfig_cmd_print_usage( - struct cconfig *config, - const char *usage_header, - enum cconfig_cmd_usage_out output) -{ - cconfig_cmd_usage_print(output, "%s\n", usage_header); - - for (uint32_t i = 0; i < config->nentries; i++) { - cconfig_cmd_usage_print( - output, - " %s: %s\n" - " default: %s\n", - config->entries[i].key, - config->entries[i].desc, - config->entries[i].value); - } -} \ No newline at end of file diff --git a/src/main/cconfig/cmd.h b/src/main/cconfig/cmd.h deleted file mode 100644 index fec39e4d..00000000 --- a/src/main/cconfig/cmd.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CCONFIG_CMD_H -#define CCONFIG_CMD_H - -#include - -#include "cconfig/cconfig.h" - -enum cconfig_cmd_usage_out { - CCONFIG_CMD_USAGE_OUT_STDOUT, - CCONFIG_CMD_USAGE_OUT_STDERR, - CCONFIG_CMD_USAGE_OUT_DBG, - CCONFIG_CMD_USAGE_OUT_LOG, -}; - -bool cconfig_cmd_parse( - struct cconfig *config, - const char *key_ident, - int argc, - char **argv, - bool add_params_if_absent); - -void cconfig_cmd_print_usage( - struct cconfig *config, - const char *usage_header, - enum cconfig_cmd_usage_out output); - -#endif \ No newline at end of file diff --git a/src/main/cconfig/conf.c b/src/main/cconfig/conf.c deleted file mode 100644 index de21f8b9..00000000 --- a/src/main/cconfig/conf.c +++ /dev/null @@ -1,128 +0,0 @@ -#define LOG_MODULE "cconfig-conf" - -#include -#include -#include - -#include "cconfig/conf.h" - -#include "util/fs.h" -#include "util/log.h" -#include "util/str.h" - -enum cconfig_conf_error cconfig_conf_load_from_file( - struct cconfig *config, const char *path, bool add_params_if_absent) -{ - char *pos_lines; - char *pos_key_val; - char *ctx_lines; - char *ctx_key_val; - char *data; - size_t len; - bool use_crlf; - - if (!file_load(path, (void **) &data, &len, true)) { - /* If file does not exist, create one with default configuration - values */ - if (path_exists(path)) { - return CCONFIG_CONF_ERROR_FILE_CORRUPTED; - } else { - return CCONFIG_CONF_ERROR_NO_SUCH_FILE; - } - } - - use_crlf = false; - if (strstr(data, "\r\n")) { - use_crlf = true; - } - pos_lines = strtok_r(data, use_crlf ? "\r\n" : "\n", &ctx_lines); - - while (pos_lines != NULL) { - char *pos_line_dup; - char *key = NULL; - char *val = NULL; - int cnt = 0; - struct cconfig_entry *entry; - - /* ignore comments and empty lines */ - if (strlen(pos_lines) > 0 && pos_lines[0] != '#') { - pos_line_dup = str_dup(pos_lines); - pos_key_val = strtok_r(pos_line_dup, "=", &ctx_key_val); - - log_misc("Line: %s", pos_lines); - - while (pos_key_val != NULL) { - if (cnt == 0) { - key = pos_key_val; - } else if (cnt == 1) { - val = pos_key_val; - } - - pos_key_val = strtok_r(NULL, "=", &ctx_key_val); - cnt++; - } - - /* Key requiured, value can be NULL */ - if (cnt != 1 && cnt != 2) { - log_warning( - "Invalid options line %s in options file %s", - pos_lines, - path); - free(pos_line_dup); - free(data); - return CCONFIG_CONF_ERROR_PARSING; - } - - /* NULL not allowed but empty string */ - if (!val) { - val = ""; - } - - log_misc("Key: %s, Value: %s", key, val); - - entry = cconfig_get(config, key); - - if (entry || add_params_if_absent) { - cconfig_set2(config, key, val); - } else { - /* Ignore cmd params that are not found in config */ - log_warning( - "Could not find parameter with key '%s' in " - "config, ignored", - key); - } - - free(pos_line_dup); - } - - pos_lines = strtok_r(NULL, use_crlf ? "\r\n" : "\n", &ctx_lines); - } - - free(data); - - return CCONFIG_CONF_SUCCESS; -} - -enum cconfig_conf_error -cconfig_conf_save_to_file(struct cconfig *config, const char *path) -{ - FILE *file; - - file = fopen(path, "wb+"); - - if (file == NULL) { - return CCONFIG_CONF_ERROR_NO_SUCH_FILE; - } - - for (uint32_t i = 0; i < config->nentries; i++) { - fprintf(file, "# %s\n", config->entries[i].desc); - fprintf( - file, - "%s=%s\n\n", - config->entries[i].key, - config->entries[i].value); - } - - fclose(file); - return CCONFIG_CONF_SUCCESS; -} \ No newline at end of file diff --git a/src/main/cconfig/conf.h b/src/main/cconfig/conf.h deleted file mode 100644 index 6fd194cd..00000000 --- a/src/main/cconfig/conf.h +++ /dev/null @@ -1,16 +0,0 @@ -#include - -#include "cconfig/cconfig.h" - -enum cconfig_conf_error { - CCONFIG_CONF_SUCCESS = 0, - CCONFIG_CONF_ERROR_NO_SUCH_FILE = 1, - CCONFIG_CONF_ERROR_FILE_CORRUPTED = 2, - CCONFIG_CONF_ERROR_PARSING = 3, -}; - -enum cconfig_conf_error cconfig_conf_load_from_file( - struct cconfig *config, const char *path, bool add_params_if_absent); - -enum cconfig_conf_error -cconfig_conf_save_to_file(struct cconfig *config, const char *path); \ No newline at end of file diff --git a/src/main/config/Module.mk b/src/main/config/Module.mk index 2f7bac83..6c7b7577 100644 --- a/src/main/config/Module.mk +++ b/src/main/config/Module.mk @@ -3,9 +3,15 @@ rc_config := config.rc cppflags_config := -DUNICODE libs_config := \ + core \ + iface-io \ + iface \ + module \ eamio \ geninput \ util \ + iface-core \ + mxml \ ldflags_config := \ -lcomctl32 \ diff --git a/src/main/config/analogs.c b/src/main/config/analogs.c index 5a7bceeb..d75253c2 100644 --- a/src/main/config/analogs.c +++ b/src/main/config/analogs.c @@ -11,13 +11,15 @@ #include "config/schema.h" #include "config/usages.h" +#include "iface-core/log.h" +#include "iface/input.h" + #include "geninput/hid-mgr.h" #include "geninput/input-config.h" #include "geninput/mapper.h" #include "util/array.h" #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" @@ -167,7 +169,7 @@ static INT_PTR analogs_ui_handle_tick(HWND hwnd) struct analogs_ui *ui; size_t i; - mapper_update(); + bt_input_mapper_update(); ui = (struct analogs_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA); @@ -362,7 +364,8 @@ static void analog_ui_handle_init_invert(HWND hwnd) ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (mapper_get_analog_invert(ui->def->tag)) { - SendMessage(GetDlgItem(hwnd, IDC_ANALOG_INVERT), BM_SETCHECK, BST_CHECKED, 0); + SendMessage( + GetDlgItem(hwnd, IDC_ANALOG_INVERT), BM_SETCHECK, BST_CHECKED, 0); } } @@ -565,7 +568,7 @@ static INT_PTR analog_ui_handle_tick(HWND hwnd) ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA); pos_ctl = GetDlgItem(hwnd, IDC_POSITION); - ui->pos = mapper_read_analog(ui->def->tag); + ui->pos = bt_input_mapper_analog_read(ui->def->tag); SendMessage(pos_ctl, WM_USER, 0, (LPARAM) ui->pos); diff --git a/src/main/config/buttons.c b/src/main/config/buttons.c index f4a498b8..a058fc13 100644 --- a/src/main/config/buttons.c +++ b/src/main/config/buttons.c @@ -15,11 +15,12 @@ #include "config/schema.h" #include "config/usages.h" +#include "iface-core/log.h" + #include "geninput/input-config.h" #include "geninput/mapper.h" #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/winres.h" diff --git a/src/main/config/eam.c b/src/main/config/eam.c index e9bb76ce..12b01ea5 100644 --- a/src/main/config/eam.c +++ b/src/main/config/eam.c @@ -13,6 +13,10 @@ #include "config/resource.h" #include "config/schema.h" +#include "iface-core/log.h" +#include "iface-io/eam.h" +#include "iface/input.h" + #include "eamio/eam-config.h" #include "geninput/hid-mgr.h" @@ -21,7 +25,6 @@ #include "util/array.h" #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" @@ -71,13 +74,13 @@ static INT_PTR eam_unit_ui_handle_change_device(HWND hwnd); static INT_PTR eam_unit_ui_handle_tick(HWND hwnd); static INT_PTR eam_unit_ui_handle_fini(HWND hwnd); -static const struct eam_io_config_api *eam_io_config_api; +static const bt_io_eam_config_api_t *eam_io_config_api; HPROPSHEETPAGE eam_ui_tab_create( HINSTANCE inst, const struct schema *schema, - const struct eam_io_config_api *api) + const bt_io_eam_config_api_t *api) { PROPSHEETPAGE psp; @@ -215,7 +218,7 @@ static INT_PTR eam_ui_handle_tick(HWND hwnd) ui = (struct eam_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA); - mapper_update(); + bt_input_mapper_update(); for (i = 0; i < ui->children.nitems; i++) { child = *array_item(HWND, &ui->children, i); @@ -461,7 +464,7 @@ static INT_PTR eam_unit_ui_handle_tick(HWND hwnd) wchar_t state_str[9]; ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA); - state = eam_io_get_keypad_state(ui->def->unit_no); + state = bt_io_eam_keypad_state_get(ui->def->unit_no); wstr_format(state_str, lengthof(state_str), L"%04x", state); diff --git a/src/main/config/gametype.c b/src/main/config/gametype.c index e7e7353b..506484cd 100644 --- a/src/main/config/gametype.c +++ b/src/main/config/gametype.c @@ -6,8 +6,9 @@ #include "config/resource.h" #include "config/schema.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" static INT_PTR CALLBACK game_type_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); diff --git a/src/main/config/main.c b/src/main/config/main.c index ba515554..ad22e4f3 100644 --- a/src/main/config/main.c +++ b/src/main/config/main.c @@ -14,14 +14,27 @@ #include "config/spinner.h" #include "config/usages.h" +#include "core/boot.h" +#include "core/log-bt.h" +#include "core/log-bt-ext.h" +#include "core/thread-crt.h" + #include "eamio/eam-config.h" #include "geninput/input-config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface-io/eam.h" +#include "iface/input.h" + +#include "module/input-ext.h" +#include "module/input.h" +#include "module/io-ext.h" +#include "module/io.h" + #include "util/defs.h" -#include "util/log.h" #include "util/str.h" -#include "util/thread.h" #include "util/winres.h" HPROPSHEETPAGE @@ -32,7 +45,7 @@ HPROPSHEETPAGE eam_ui_tab_create( HINSTANCE inst, const struct schema *schema, - const struct eam_io_config_api *eam_io_config_api); + const bt_io_eam_config_api_t *eam_io_config_api); static void my_fatal(const char *module, const char *fmt, ...) { @@ -49,6 +62,17 @@ static void my_fatal(const char *module, const char *fmt, ...) ExitProcess(-1); } +static void log_api_set() +{ + bt_core_log_api_t api; + + core_log_bt_core_api_get(&api); + + api.v1.fatal = my_fatal; + + bt_core_log_api_set(&api); +} + int main(int argc, char **argv) { INITCOMMONCONTROLSEX iccx; @@ -56,16 +80,35 @@ int main(int argc, char **argv) HPROPSHEETPAGE psp[4]; PROPSHEETHEADER psh; intptr_t result; - const struct eam_io_config_api *eam_io_config_api; + const bt_io_eam_config_api_t *eam_io_config_api; const struct schema *schema; wchar_t text[1024]; int max_light; size_t i; + bt_input_api_t input_api; + module_input_t *module_input; + bt_io_eam_api_t eam_api; + module_io_t *module_io_eam; - inst = GetModuleHandle(NULL); + // TODO turn this into optional parameters, same for log level and output to + // file + AttachConsole(ATTACH_PARENT_PROCESS); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + freopen("CONIN$", "r", stdin); - log_to_writer(log_writer_debug, NULL); - log_to_external(log_impl_misc, log_impl_info, log_impl_warning, my_fatal); + core_boot("config"); + + core_log_bt_ext_init_with_stderr(); + + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); + core_log_bt_core_api_set(); + + core_thread_crt_core_api_set(); + + log_api_set(); + + inst = GetModuleHandle(NULL); usages_init(inst); @@ -96,14 +139,16 @@ int main(int argc, char **argv) } } - input_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - input_init(crt_thread_create, crt_thread_join, crt_thread_destroy); + module_input_ext_load_and_init("geninput.dll", &module_input); + module_input_api_get(module_input, &input_api); + bt_input_api_set(&input_api); + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", &module_io_eam); + module_io_api_get(module_io_eam, &eam_api); + bt_io_eam_api_set(&eam_api); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - eam_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy); - eam_io_config_api = eam_io_get_config_api(); + eam_io_config_api = bt_io_eam_config_api_get(); // calculate these and check against the loaded config max_light = -1; @@ -114,11 +159,14 @@ int main(int argc, char **argv) } } - if (!mapper_config_load(schema->name)) { + if (!bt_input_mapper_config_load(schema->name)) { log_info("Initializing empty config for %s", schema->name); + log_info(">>>>1"); mapper_set_nlights((uint8_t) (max_light + 1)); + log_info(">>>>1"); mapper_set_nanalogs((uint8_t) schema->nanalogs); + log_info(">>>>1"); } else { // make sure that these are right @@ -167,10 +215,16 @@ int main(int argc, char **argv) mapper_config_save(schema->name); } - eam_io_fini(); - input_fini(); + bt_io_eam_fini(); + bt_input_fini(); spinner_fini(inst); usages_fini(); + bt_input_api_clear(); + bt_io_eam_api_clear(); + + module_input_free(&module_input); + module_io_free(&module_io_eam); + return EXIT_SUCCESS; } diff --git a/src/main/config/snap.c b/src/main/config/snap.c index 8981c686..983fd4bb 100644 --- a/src/main/config/snap.c +++ b/src/main/config/snap.c @@ -8,8 +8,9 @@ #include "geninput/hid-mgr.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" enum snap_control_heuristic { CONTROL_CENTERING_AXIS, CONTROL_MULTISWITCH }; diff --git a/src/main/config/usages.c b/src/main/config/usages.c index 5e28ad9b..6d2691f0 100644 --- a/src/main/config/usages.c +++ b/src/main/config/usages.c @@ -9,8 +9,9 @@ #include "config/resource.h" +#include "iface-core/log.h" + #include "util/array.h" -#include "util/log.h" #include "util/str.h" #include "util/winres.h" diff --git a/src/main/core/Module.mk b/src/main/core/Module.mk new file mode 100644 index 00000000..6f5364f3 --- /dev/null +++ b/src/main/core/Module.mk @@ -0,0 +1,28 @@ +libs += core + +libs_core := \ + util \ + +src_core := \ + boot.c \ + config-ext.c \ + config-property-node.c \ + log-bt-ext.c \ + log-bt.c \ + log-ext.c \ + log-sink-async.c \ + log-sink-debug.c \ + log-sink-file.c \ + log-sink-list.c \ + log-sink-mutex.c \ + log-sink-null.c \ + log-sink-std.c \ + property-ext.c \ + property-mxml.c \ + property-node-ext.c \ + property-node-mxml.c \ + property-node-trace.c \ + property-node.c \ + property-trace.c \ + property.c \ + thread-crt.c \ diff --git a/src/main/core/boot.c b/src/main/core/boot.c new file mode 100644 index 00000000..ee87f17a --- /dev/null +++ b/src/main/core/boot.c @@ -0,0 +1,110 @@ +#define LOG_MODULE "core-boot" + +#include + +#include + +#include "core/config-property-node.h" +#include "core/property-mxml.h" +#include "core/property-node-mxml.h" +#include "core/thread-crt.h" + +#include "iface-core/log.h" + +#include "util/str.h" + +#define CORE_BOOT_LOG_MSG_SIZE_MAX 8192 + +static void _core_boot_log_std_msg(const char *module, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + printf("[%s] ", module); + vfprintf(stderr, fmt, args); + printf("\n"); + + va_end(args); +} + +static void _core_boot_log_debug_msg(const char *module, const char *fmt, ...) +{ + char msg[CORE_BOOT_LOG_MSG_SIZE_MAX]; + char msg2[CORE_BOOT_LOG_MSG_SIZE_MAX]; + va_list args; + + va_start(args, fmt); + + str_vformat(msg, sizeof(msg), fmt, args); + + va_end(args); + + str_format(msg2, sizeof(msg2), "[%s] %s\n", module, msg); + + OutputDebugStringA(msg2); +} + +static void _core_boot_minimal_logging_std_env_init() +{ + _core_boot_log_std_msg( + LOG_MODULE, "Init minimal logging environment (std)"); + + // Initialize logging directly to avoid a bootstrapping issue + // with not having any kind of logging to bootstrap the full + // featured logging system + _bt_core_log_api.version = 1; + + _bt_core_log_api.v1.misc = _core_boot_log_std_msg; + _bt_core_log_api.v1.info = _core_boot_log_std_msg; + _bt_core_log_api.v1.warning = _core_boot_log_std_msg; + _bt_core_log_api.v1.fatal = _core_boot_log_std_msg; + + log_misc("Init minimal logging environment done"); +} + +static void _core_boot_minimal_logging_debug_env_init() +{ + _core_boot_log_debug_msg( + LOG_MODULE, "Init minimal logging environment (debug)"); + + // Initialize logging directly to avoid a bootstrapping issue + // with not having any kind of logging to bootstrap the full + // featured logging system + _bt_core_log_api.version = 1; + + _bt_core_log_api.v1.misc = _core_boot_log_debug_msg; + _bt_core_log_api.v1.info = _core_boot_log_debug_msg; + _bt_core_log_api.v1.warning = _core_boot_log_debug_msg; + _bt_core_log_api.v1.fatal = _core_boot_log_debug_msg; + + log_misc("Init minimal logging environment done"); +} + +void core_boot(const char *name) +{ + _core_boot_log_std_msg(LOG_MODULE, "Boot: %s", name); + + _core_boot_minimal_logging_std_env_init(); + + core_thread_crt_core_api_set(); + + core_property_mxml_core_api_set(); + core_property_node_mxml_core_api_set(); + + core_config_property_node_core_api_set(); +} + +void core_boot_dll(const char *name) +{ + _core_boot_log_debug_msg(LOG_MODULE, "Boot: %s", name); + + _core_boot_minimal_logging_debug_env_init(); + + core_thread_crt_core_api_set(); + + core_property_mxml_core_api_set(); + core_property_node_mxml_core_api_set(); + + core_config_property_node_core_api_set(); +} \ No newline at end of file diff --git a/src/main/core/boot.h b/src/main/core/boot.h new file mode 100644 index 00000000..908aa73c --- /dev/null +++ b/src/main/core/boot.h @@ -0,0 +1,8 @@ +#ifndef CORE_BOOT_H +#define CORE_BOOT_H + +void core_boot(const char *name); + +void core_boot_dll(const char *name); + +#endif \ No newline at end of file diff --git a/src/main/core/config-ext.c b/src/main/core/config-ext.c new file mode 100644 index 00000000..6b016052 --- /dev/null +++ b/src/main/core/config-ext.c @@ -0,0 +1,458 @@ +#include "iface-core/config.h" +#include "iface-core/log.h" + +#include "security/id.h" +#include "security/mcode.h" + +#include "util/net.h" + +void bt_core_config_ext_s8_get( + const bt_core_config_t *config, const char *path, int8_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s8_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_u8_get( + const bt_core_config_t *config, const char *path, uint8_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u8_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_s16_get( + const bt_core_config_t *config, const char *path, int16_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s16_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_u16_get( + const bt_core_config_t *config, const char *path, uint16_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u16_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_s32_get( + const bt_core_config_t *config, const char *path, int32_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s32_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_u32_get( + const bt_core_config_t *config, const char *path, uint32_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u32_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_s64_get( + const bt_core_config_t *config, const char *path, int64_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s64_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_u64_get( + const bt_core_config_t *config, const char *path, uint64_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u64_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_float_get( + const bt_core_config_t *config, const char *path, float *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_float_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_double_get( + const bt_core_config_t *config, const char *path, double *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_double_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_bool_get( + const bt_core_config_t *config, const char *path, bool *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_bool_get(config, path, value); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_bin_get( + const bt_core_config_t *config, const char *path, void *value, size_t len) +{ + bt_core_config_result_t result; + + result = bt_core_config_bin_get(config, path, value, len); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_str_get( + const bt_core_config_t *config, const char *path, char *value, size_t len) +{ + bt_core_config_result_t result; + + result = bt_core_config_str_get(config, path, value, len); + bt_core_config_fatal_on_error(result, path); +} + +void bt_core_config_ext_net_addr_get(const bt_core_config_t *config, const char *path, struct net_addr *addr) +{ + char buffer[1024]; + + bt_core_config_ext_str_get(config, path, buffer, sizeof(buffer)); + + if (!net_str_parse(buffer, addr)) { + log_fatal("Cannot parse server address: %s", buffer); + } +} + +void bt_core_config_ext_security_id_get(const bt_core_config_t *config, const char *path, security_id_t *id) +{ + char buffer[16]; + + bt_core_config_ext_bin_get(config, path, buffer, sizeof(buffer)); + + if (!security_id_parse(buffer, id)) { + log_fatal("Cannot parse security id: %s", buffer); + } +} + +void bt_core_config_ext_security_mcode_get(const bt_core_config_t *config, const char *path, security_mcode_t *mcode) +{ + char buffer[16]; + + bt_core_config_ext_str_get(config, path, buffer, sizeof(buffer)); + + if (!security_mcode_parse(buffer, mcode)) { + log_fatal("Cannot parse security mcode: %s", buffer); + } +} + +bool bt_core_config_ext_s8_optional_get( + const bt_core_config_t *config, const char *path, int8_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s8_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_u8_optional_get( + const bt_core_config_t *config, const char *path, uint8_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u8_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_s16_optional_get( + const bt_core_config_t *config, const char *path, int16_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s16_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_u16_optional_get( + const bt_core_config_t *config, const char *path, uint16_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u16_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_s32_optional_get( + const bt_core_config_t *config, const char *path, int32_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s32_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_u32_optional_get( + const bt_core_config_t *config, const char *path, uint32_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u32_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_s64_optional_get( + const bt_core_config_t *config, const char *path, int64_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_s64_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_u64_optional_get( + const bt_core_config_t *config, const char *path, uint64_t *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_u64_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_float_optional_get( + const bt_core_config_t *config, const char *path, float *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_float_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_double_optional_get( + const bt_core_config_t *config, const char *path, double *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_double_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_bool_optional_get( + const bt_core_config_t *config, const char *path, bool *value) +{ + bt_core_config_result_t result; + + result = bt_core_config_bool_get(config, path, value); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_bin_optional_get( + const bt_core_config_t *config, const char *path, void *value, size_t len) +{ + bt_core_config_result_t result; + + result = bt_core_config_bin_get(config, path, value, len); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_str_optional_get( + const bt_core_config_t *config, const char *path, char *value, size_t len) +{ + bt_core_config_result_t result; + + result = bt_core_config_str_get(config, path, value, len); + + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return true; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return false; + default: + bt_core_config_fatal_on_error(result, path); + // Should not reach + return false; + } +} + +bool bt_core_config_ext_net_addr_optional_get(const bt_core_config_t *config, const char *path, struct net_addr *addr) +{ + char buffer[1024]; + bool result; + + result = bt_core_config_ext_str_optional_get(config, path, buffer, sizeof(buffer)); + + if (!result) { + return false; + } + + if (!net_str_parse(buffer, addr)) { + log_fatal("Cannot parse server address: %s", buffer); + } + + return true; +} + +bool bt_core_config_ext_security_id_optional_get(const bt_core_config_t *config, const char *path, security_id_t *id) +{ + char buffer[16]; + bool result; + + result = bt_core_config_ext_bin_optional_get(config, path, buffer, sizeof(buffer)); + + if (!result) { + return false; + } + + if (!security_id_parse(buffer, id)) { + log_fatal("Cannot parse security id: %s", buffer); + } + + return true; +} + +bool bt_core_config_ext_security_mcode_optional_get(const bt_core_config_t *config, const char *path, security_mcode_t *mcode) +{ + char buffer[16]; + bool result; + + result = bt_core_config_ext_str_optional_get(config, path, buffer, sizeof(buffer)); + + if (!result) { + return false; + } + + if (!security_mcode_parse(buffer, mcode)) { + log_fatal("Cannot parse security mcode: %s", buffer); + } + + return true; +} \ No newline at end of file diff --git a/src/main/core/config-ext.h b/src/main/core/config-ext.h new file mode 100644 index 00000000..72086255 --- /dev/null +++ b/src/main/core/config-ext.h @@ -0,0 +1,71 @@ +#ifndef CORE_CONFIG_EXT_H +#define CORE_CONFIG_EXT_H + +#include "iface-core/config.h" + +#include "security/id.h" +#include "security/mcode.h" + +#include "util/net.h" + +void bt_core_config_ext_s8_get( + const bt_core_config_t *config, const char *path, int8_t *value); +void bt_core_config_ext_u8_get( + const bt_core_config_t *config, const char *path, uint8_t *value); +void bt_core_config_ext_s16_get( + const bt_core_config_t *config, const char *path, int16_t *value); +void bt_core_config_ext_u16_get( + const bt_core_config_t *config, const char *path, uint16_t *value); +void bt_core_config_ext_s32_get( + const bt_core_config_t *config, const char *path, int32_t *value); +void bt_core_config_ext_u32_get( + const bt_core_config_t *config, const char *path, uint32_t *value); +void bt_core_config_ext_s64_get( + const bt_core_config_t *config, const char *path, int64_t *value); +void bt_core_config_ext_u64_get( + const bt_core_config_t *config, const char *path, uint64_t *value); +void bt_core_config_ext_float_get( + const bt_core_config_t *config, const char *path, float *value); +void bt_core_config_ext_double_get( + const bt_core_config_t *config, const char *path, double *value); +void bt_core_config_ext_bool_get( + const bt_core_config_t *config, const char *path, bool *value); +void bt_core_config_ext_bin_get( + const bt_core_config_t *config, const char *path, void *value, size_t len); +void bt_core_config_ext_str_get( + const bt_core_config_t *config, const char *path, char *value, size_t len); +void bt_core_config_ext_net_addr_get(const bt_core_config_t *config, const char *path, struct net_addr *addr); +void bt_core_config_ext_security_id_get(const bt_core_config_t *config, const char *path, security_id_t *id); +void bt_core_config_ext_security_mcode_get(const bt_core_config_t *config, const char *path, security_mcode_t *mcode); + +bool bt_core_config_ext_s8_optional_get( + const bt_core_config_t *config, const char *path, int8_t *value); +bool bt_core_config_ext_u8_optional_get( + const bt_core_config_t *config, const char *path, uint8_t *value); +bool bt_core_config_ext_s16_optional_get( + const bt_core_config_t *config, const char *path, int16_t *value); +bool bt_core_config_ext_u16_optional_get( + const bt_core_config_t *config, const char *path, uint16_t *value); +bool bt_core_config_ext_s32_optional_get( + const bt_core_config_t *config, const char *path, int32_t *value); +bool bt_core_config_ext_u32_optional_get( + const bt_core_config_t *config, const char *path, uint32_t *value); +bool bt_core_config_ext_s64_optional_get( + const bt_core_config_t *config, const char *path, int64_t *value); +bool bt_core_config_ext_u64_optional_get( + const bt_core_config_t *config, const char *path, uint64_t *value); +bool bt_core_config_ext_float_optional_get( + const bt_core_config_t *config, const char *path, float *value); +bool bt_core_config_ext_double_optional_get( + const bt_core_config_t *config, const char *path, double *value); +bool bt_core_config_ext_bool_optional_get( + const bt_core_config_t *config, const char *path, bool *value); +bool bt_core_config_ext_bin_optional_get( + const bt_core_config_t *config, const char *path, void *value, size_t len); +bool bt_core_config_ext_str_optional_get( + const bt_core_config_t *config, const char *path, char *value, size_t len); +bool bt_core_config_ext_net_addr_optional_get(const bt_core_config_t *config, const char *path, struct net_addr *addr); +bool bt_core_config_ext_security_id_optional_get(const bt_core_config_t *config, const char *path, security_id_t *id); +bool bt_core_config_ext_security_mcode_optional_get(const bt_core_config_t *config, const char *path, security_mcode_t *mcode); + +#endif \ No newline at end of file diff --git a/src/main/core/config-property-node.c b/src/main/core/config-property-node.c new file mode 100644 index 00000000..90ba85d0 --- /dev/null +++ b/src/main/core/config-property-node.c @@ -0,0 +1,346 @@ +#define LOG_MODULE "core-config-property-node" + +#include "api/core/config.h" + +#include "main/core/config-property-node.h" +#include "main/core/property-node.h" +#include "main/core/property.h" + +#include "iface-core/log.h" + +#include "util/mem.h" + +typedef struct core_config_property_node { + const core_property_node_t *node; +} core_config_property_node_t; + +static bt_core_config_result_t +_core_config_property_node_result_map(core_property_node_result_t result) +{ + switch (result) { + case CORE_PROPERTY_NODE_RESULT_SUCCESS: + return BT_CORE_CONFIG_RESULT_SUCCESS; + case CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL: + return BT_CORE_CONFIG_RESULT_ERROR_INTERNAL; + case CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND: + return BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND; + default: + return BT_CORE_CONFIG_RESULT_ERROR_INTERNAL; + } +} + +static bt_core_config_result_t _core_config_property_node_s8_get( + const bt_core_config_t *config_, const char *path, int8_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_s8_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_u8_get( + const bt_core_config_t *config_, const char *path, uint8_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_u8_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_s16_get( + const bt_core_config_t *config_, const char *path, int16_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_s16_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_u16_get( + const bt_core_config_t *config_, const char *path, uint16_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_u16_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_s32_get( + const bt_core_config_t *config_, const char *path, int32_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_s32_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_u32_get( + const bt_core_config_t *config_, const char *path, uint32_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_u32_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_s64_get( + const bt_core_config_t *config_, const char *path, int64_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_s64_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_u64_get( + const bt_core_config_t *config_, const char *path, uint64_t *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_u64_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_float_get( + const bt_core_config_t *config_, const char *path, float *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_float_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_double_get( + const bt_core_config_t *config_, const char *path, double *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_double_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_bool_get( + const bt_core_config_t *config_, const char *path, bool *value) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_bool_read(&node, value); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_bin_get( + const bt_core_config_t *config_, const char *path, void *value, size_t len) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_bin_read(&node, value, len); + + return _core_config_property_node_result_map(result); +} + +static bt_core_config_result_t _core_config_property_node_str_get( + const bt_core_config_t *config_, const char *path, char *value, size_t len) +{ + const core_config_property_node_t *config; + core_property_node_t node; + core_property_node_result_t result; + + config = (const core_config_property_node_t *) config_; + + result = core_property_node_search(config->node, path, &node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return _core_config_property_node_result_map(result); + } + + result = core_property_node_str_read(&node, value, len); + + return _core_config_property_node_result_map(result); +} + +static void _core_config_property_node_core_api_get(bt_core_config_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.s8_get = _core_config_property_node_s8_get; + api->v1.u8_get = _core_config_property_node_u8_get; + api->v1.s16_get = _core_config_property_node_s16_get; + api->v1.u16_get = _core_config_property_node_u16_get; + api->v1.s32_get = _core_config_property_node_s32_get; + api->v1.u32_get = _core_config_property_node_u32_get; + api->v1.s64_get = _core_config_property_node_s64_get; + api->v1.u64_get = _core_config_property_node_u64_get; + api->v1.float_get = _core_config_property_node_float_get; + api->v1.double_get = _core_config_property_node_double_get; + api->v1.bool_get = _core_config_property_node_bool_get; + api->v1.bin_get = _core_config_property_node_bin_get; + api->v1.str_get = _core_config_property_node_str_get; +} + +void core_config_property_node_core_api_set() +{ + bt_core_config_api_t api; + + _core_config_property_node_core_api_get(&api); + bt_core_config_api_set(&api); +} + +void core_config_property_node_init( + const core_property_node_t *node, bt_core_config_t **config_) +{ + core_config_property_node_t *config; + + log_assert(node); + log_assert(config_); + + config = xmalloc(sizeof(core_config_property_node_t)); + + config->node = node; + + *config_ = (bt_core_config_t *) config; +} + +void core_config_property_node_free(bt_core_config_t **config_) +{ + core_config_property_node_t **config; + + log_assert(config_); + + config = (core_config_property_node_t **) config_; + + free(*config); + *config = NULL; +} \ No newline at end of file diff --git a/src/main/core/config-property-node.h b/src/main/core/config-property-node.h new file mode 100644 index 00000000..843f7bb4 --- /dev/null +++ b/src/main/core/config-property-node.h @@ -0,0 +1,15 @@ +#ifndef CORE_CONFIG_PROPERTY_NODE_H +#define CORE_CONFIG_PROPERTY_NODE_H + +#include "iface-core/config.h" + +#include "core/property-node.h" + +void core_config_property_node_core_api_set(); + +void core_config_property_node_init( + const core_property_node_t *node, bt_core_config_t **config); + +void core_config_property_node_free(bt_core_config_t **config); + +#endif \ No newline at end of file diff --git a/src/main/core/log-bt-ext.c b/src/main/core/log-bt-ext.c new file mode 100644 index 00000000..8492caac --- /dev/null +++ b/src/main/core/log-bt-ext.c @@ -0,0 +1,130 @@ +#define LOG_MODULE "core-log-bt-ext" + +#include + +#include "core/log-bt.h" +#include "core/log-sink-async.h" +#include "core/log-sink-debug.h" +#include "core/log-sink-file.h" +#include "core/log-sink-list.h" +#include "core/log-sink-mutex.h" +#include "core/log-sink-null.h" +#include "core/log-sink-std.h" + +// so we can log data dumps of rs232 streams without crashing +#define CORE_LOG_BT_EXT_MSG_BUFFER_SIZE 1024 * 64 +// 64 kb * 64 = 4 MB for logging total +#define CORE_LOG_BT_EXT_ASYNC_QUEUE_LENGTH 64 + +void core_log_bt_ext_init_with_null() +{ + core_log_sink_t sink; + + core_log_sink_null_open(&sink); + + // Size doesn't matter (but must be valid) + // logger is entirely disabled + core_log_bt_init(1024, &sink); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_OFF); +} + +void core_log_bt_ext_init_with_stdout() +{ + core_log_sink_t sink; + + core_log_sink_std_out_open(true, &sink); + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink); +} + +void core_log_bt_ext_init_with_stderr() +{ + core_log_sink_t sink; + + core_log_sink_std_err_open(true, &sink); + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink); +} + +void core_log_bt_ext_init_with_debug() +{ + core_log_sink_t sink; + + core_log_sink_debug_open(&sink); + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink); +} + +void core_log_bt_ext_init_with_file( + const char *path, bool append, bool rotate, uint8_t max_rotations) +{ + core_log_sink_t sink; + + core_log_sink_file_open(path, append, rotate, max_rotations, &sink); + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink); +} + +void core_log_bt_ext_init_with_stdout_and_file( + const char *path, bool append, bool rotate, uint8_t max_rotations) +{ + core_log_sink_t sinks[2]; + core_log_sink_t sink_composed; + core_log_sink_t sink_mutex; + + core_log_sink_std_out_open(true, &sinks[0]); + core_log_sink_file_open(path, append, rotate, max_rotations, &sinks[1]); + core_log_sink_list_open(sinks, 2, &sink_composed); + + core_log_sink_mutex_open(&sink_composed, &sink_mutex); + + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink_mutex); +} + +void core_log_bt_ext_init_with_stderr_and_file( + const char *path, bool append, bool rotate, uint8_t max_rotations) +{ + core_log_sink_t sinks[2]; + core_log_sink_t sink_composed; + core_log_sink_t sink_mutex; + + core_log_sink_std_err_open(true, &sinks[0]); + core_log_sink_file_open(path, append, rotate, max_rotations, &sinks[1]); + core_log_sink_list_open(sinks, 2, &sink_composed); + + core_log_sink_mutex_open(&sink_composed, &sink_mutex); + + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink_mutex); +} + +void core_log_bt_ext_init_async_with_stderr() +{ + core_log_sink_t sink; + core_log_sink_t sink_async; + + core_log_sink_std_err_open(true, &sink); + + core_log_sink_async_open( + CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, + CORE_LOG_BT_EXT_ASYNC_QUEUE_LENGTH, + CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_DISCARD_NEW, + &sink, &sink_async); + + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink_async); +} + +void core_log_bt_ext_init_async_with_stderr_and_file( + const char *path, bool append, bool rotate, uint8_t max_rotations) +{ + core_log_sink_t sinks[2]; + core_log_sink_t sink_composed; + core_log_sink_t sink_async; + + core_log_sink_std_err_open(true, &sinks[0]); + core_log_sink_file_open(path, append, rotate, max_rotations, &sinks[1]); + core_log_sink_list_open(sinks, 2, &sink_composed); + + core_log_sink_async_open( + CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, + CORE_LOG_BT_EXT_ASYNC_QUEUE_LENGTH, + CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_DISCARD_NEW, + &sink_composed, &sink_async); + + core_log_bt_init(CORE_LOG_BT_EXT_MSG_BUFFER_SIZE, &sink_async); +} \ No newline at end of file diff --git a/src/main/core/log-bt-ext.h b/src/main/core/log-bt-ext.h new file mode 100644 index 00000000..50f436a0 --- /dev/null +++ b/src/main/core/log-bt-ext.h @@ -0,0 +1,63 @@ +#ifndef CORE_LOG_BT_EXT_H +#define CORE_LOG_BT_EXT_H + +#include +#include + +void core_log_bt_ext_init_with_null(); + +/** + * Helper to setup the bemanitools log implementation with a stdout sink. + */ +void core_log_bt_ext_init_with_stdout(); + +/** + * Helper to setup the bemanitools log implementation with a stderr sink. + */ +void core_log_bt_ext_init_with_stderr(); + +/** + * Helper to setup the bemanitools log implementation with a OutputDebugStr + * sink. + */ +void core_log_bt_ext_init_with_debug(); + +/** + * Helper to setup the bemanitools log implementation with a file sink + * + * @param path Path to the log file to write the log output to + * @param append If true, then append to an existing file, false to overwrite + * any existing file + * @param rotate If true, rotates an existing log file and creates a new one + * for this session + * @param max_rotations Max number of rotations for the log files + */ +void core_log_bt_ext_init_with_file( + const char *path, bool append, bool rotate, uint8_t max_rotations); + +/** + * Helper to setup the bemanitools log implementation with a stdout and file + * sink + * + * Important: This combined sink is guarded by a mutex to avoid data races on + * logging to two different sinks. + * + * @param path Path to the log file to write the log output to + * @param append If true, then append to an existing file, false to overwrite + * any existing file + * @param rotate If true, rotates an existing log file and creates a new one + * for this session + * @param max_rotations Max number of rotations for the log files + */ +void core_log_bt_ext_init_with_stdout_and_file( + const char *path, bool append, bool rotate, uint8_t max_rotations); + +void core_log_bt_ext_init_with_stderr_and_file( + const char *path, bool append, bool rotate, uint8_t max_rotations); + +void core_log_bt_ext_init_async_with_stderr(); + +void core_log_bt_ext_init_async_with_stderr_and_file( + const char *path, bool append, bool rotate, uint8_t max_rotations); + +#endif \ No newline at end of file diff --git a/src/main/core/log-bt.c b/src/main/core/log-bt.c new file mode 100644 index 00000000..1c29d71e --- /dev/null +++ b/src/main/core/log-bt.c @@ -0,0 +1,193 @@ +#define LOG_MODULE "core-log-bt" + +#include +#include +#include + +#include "iface-core/log.h" + +#include "main/core/log-bt.h" +#include "main/core/log-sink.h" + +#include "util/mem.h" +#include "util/str.h" + +#define CORE_LOG_TIMESTAMP_SIZE_MAX 64 + +static uint32_t _core_log_bt_msg_buffer_size; +static enum core_log_bt_log_level _core_log_bt_log_level; +static core_log_sink_t *_core_log_bt_sink; + +static void _core_log_bt_vformat_timestamp_log_level_write( + enum core_log_bt_log_level level, + const char *module, + const char *fmt, + va_list ap) +{ + static const char chars[] = "FFWIM"; + + char timestamp[CORE_LOG_TIMESTAMP_SIZE_MAX]; + char msg[_core_log_bt_msg_buffer_size]; + char line[_core_log_bt_msg_buffer_size]; + int result; + + time_t curtime; + struct tm *tm; + + curtime = 0; + tm = NULL; + + curtime = time(NULL); + tm = localtime(&curtime); + + // TODO truncate messages if too large and emit log warning message this happened + + strftime(timestamp, sizeof(timestamp), "[%Y/%m/%d %H:%M:%S]", tm); + + str_vformat(msg, sizeof(msg), fmt, ap); + + result = str_format( + line, + sizeof(line), + "%s %c:%s: %s\n", + timestamp, + chars[level], + module, + msg); + + _core_log_bt_sink->write(_core_log_bt_sink->ctx, line, result); +} + +static void _core_log_bt_log_misc(const char *module, const char *fmt, ...) +{ + va_list args; + + // Cut off logging as early as possible if the logging level isn't configured + // This saves processing time that might have performance impact on the + // calling thread + if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_MISC) { + va_start(args, fmt); + _core_log_bt_vformat_timestamp_log_level_write( + CORE_LOG_BT_LOG_LEVEL_MISC, module, fmt, args); + va_end(args); + } +} + +static void _core_log_bt_log_info(const char *module, const char *fmt, ...) +{ + va_list args; + + // Cut off logging as early as possible if the logging level isn't configured + // This saves processing time that might have performance impact on the + // calling thread + if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_INFO) { + va_start(args, fmt); + _core_log_bt_vformat_timestamp_log_level_write( + CORE_LOG_BT_LOG_LEVEL_INFO, module, fmt, args); + va_end(args); + } +} + +static void _core_log_bt_log_warning(const char *module, const char *fmt, ...) +{ + va_list args; + + // Cut off logging as early as possible if the logging level isn't configured + // This saves processing time that might have performance impact on the + // calling thread + if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_WARNING) { + va_start(args, fmt); + _core_log_bt_vformat_timestamp_log_level_write( + CORE_LOG_BT_LOG_LEVEL_WARNING, module, fmt, args); + va_end(args); + } +} + +static void _core_log_bt_log_fatal(const char *module, const char *fmt, ...) +{ + va_list args; + + // Cut off logging as early as possible if the logging level isn't configured + // This saves processing time that might have performance impact on the + // calling thread + if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_FATAL) { + va_start(args, fmt); + _core_log_bt_vformat_timestamp_log_level_write( + CORE_LOG_BT_LOG_LEVEL_FATAL, module, fmt, args); + va_end(args); + } +} + +void core_log_bt_core_api_get(bt_core_log_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.misc = _core_log_bt_log_misc; + api->v1.info = _core_log_bt_log_info; + api->v1.warning = _core_log_bt_log_warning; + api->v1.fatal = _core_log_bt_log_fatal; +} + +void core_log_bt_core_api_set() +{ + bt_core_log_api_t api; + + core_log_bt_core_api_get(&api); + bt_core_log_api_set(&api); +} + +void core_log_bt_init( + size_t msg_buffer_size, + const core_log_sink_t *sink) +{ + // Sanity check for sizes we consider too much or too less + log_assert(msg_buffer_size > 1024); // 1 kB + log_assert(msg_buffer_size <= 1024 * 1024); // 1 MB + log_assert(sink); + + _core_log_bt_msg_buffer_size = msg_buffer_size; + + _core_log_bt_sink = xmalloc(sizeof(core_log_sink_t)); + memcpy(_core_log_bt_sink, sink, sizeof(core_log_sink_t)); + + _core_log_bt_log_level = CORE_LOG_BT_LOG_LEVEL_OFF; + + log_misc("Init: msg_buffer_size %d", msg_buffer_size); +} + +void core_log_bt_reinit( + size_t msg_buffer_size, + const core_log_sink_t *sink) +{ + log_assert(_core_log_bt_sink); + + log_misc("Re-init"); + + core_log_bt_fini(); + core_log_bt_init(msg_buffer_size, sink); +} + +void core_log_bt_level_set(enum core_log_bt_log_level level) +{ + log_misc("Log level change from %d to %d", _core_log_bt_log_level, level); + + _core_log_bt_log_level = level; +} + +void core_log_bt_fini() +{ + log_assert(_core_log_bt_sink); + + log_misc("Fini"); + + _core_log_bt_sink->close(_core_log_bt_sink->ctx); + + free(_core_log_bt_sink); +} + +void core_log_bt_direct_sink_write(const char *chars, size_t nchars) +{ + _core_log_bt_sink->write(_core_log_bt_sink->ctx, chars, nchars); +} diff --git a/src/main/core/log-bt.h b/src/main/core/log-bt.h new file mode 100644 index 00000000..b80a6daf --- /dev/null +++ b/src/main/core/log-bt.h @@ -0,0 +1,80 @@ +#ifndef CORE_LOG_BT_H +#define CORE_LOG_BT_H + +#include "api/core/log.h" + +#include "main/core/log-sink.h" + +/** + * Log API implementation for games/applications without AVS + */ + +enum core_log_bt_log_level { + CORE_LOG_BT_LOG_LEVEL_OFF = 0, + CORE_LOG_BT_LOG_LEVEL_FATAL = 1, + CORE_LOG_BT_LOG_LEVEL_WARNING = 2, + CORE_LOG_BT_LOG_LEVEL_INFO = 3, + CORE_LOG_BT_LOG_LEVEL_MISC = 4, +}; + +void core_log_bt_core_api_get(bt_core_log_api_t *api); + +// Note: this logger requires a minimal logger to be set-up beforehand +// (log-mini) +void core_log_bt_core_api_set(); + +/** + * Initialize the logging backend + * + * This must be called as early as possible in your application to setup + * a logging sink according to your needs. Until this is finished, no + * log output is available. + * + * By default, logging is turned off entirely and must be enabled by setting + * a desired logging level explicitly. + * + * @param sink Pointer to a log sink implementation. The caller owns the memory + * of this. + */ +void core_log_bt_init( + size_t msg_buffer_size, + const core_log_sink_t *sink); + +// special version to use when switching loggers +void core_log_bt_reinit(size_t msg_buffer_size, const core_log_sink_t *sink); + +/** + * Set the current logging level. This can be changed at any given time, e.g. + * to increase/decrease verbosity. + * + * @param level The logging level to set. + */ +void core_log_bt_level_set(enum core_log_bt_log_level level); + +/** + * Cleanup the logging backend. + * + * Ensure to call this on application exit and cleanup. + */ +void core_log_bt_fini(); + +/** + * Allow AVS to by-pass the core log API/engine. + * + * This function must only be called by AVS in an appropriate log callback + * function that is passed to avs_boot. + * + * AVS has it's own logging engine and manages aspects such as async logging, + * log levels and decorating log messages. + * + * Thus, proper interoperability only requires the writer/sink part to be shared + * with AVS. + * + * @param chars Buffer with text data to write to the configured sinks. The + * buffer might contain several log messages separated by newline + * characters. + * @param nchars Number of chars to write to the sink. + */ +void core_log_bt_direct_sink_write(const char *chars, size_t nchars); + +#endif \ No newline at end of file diff --git a/src/main/core/log-ext.c b/src/main/core/log-ext.c new file mode 100644 index 00000000..87c89b33 --- /dev/null +++ b/src/main/core/log-ext.c @@ -0,0 +1,27 @@ + + +#include + +#include "iface-core/log.h" + +void core_log_ext_win_last_error_log(const char *module, bt_core_log_message_t log_message) +{ + LPSTR buffer; + DWORD last_error; + + last_error = GetLastError(); + + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + last_error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR) &buffer, + 0, + NULL); + + log_message(module, "Last error (%08X): %s", last_error, buffer); + + LocalFree(buffer); +} \ No newline at end of file diff --git a/src/main/core/log-ext.h b/src/main/core/log-ext.h new file mode 100644 index 00000000..0b909069 --- /dev/null +++ b/src/main/core/log-ext.h @@ -0,0 +1,22 @@ +#ifndef CORE_LOG_EXT_H +#define CORE_LOG_EXT_H + +#include "iface-core/log.h" + +#define log_fatal_on_win_last_error(...) \ + if (GetLastError() != 0) { \ + _bt_core_log_api.v1.fatal( \ + LOG_MODULE, \ + "%s:%d: function `%s'", \ + __FILE__, \ + __LINE__, \ + __FUNCTION__); \ + _bt_core_log_api.v1.fatal(LOG_MODULE, __VA_ARGS__); \ + core_log_ext_win_last_error_log(LOG_MODULE, _bt_core_log_api.v1.fatal); \ + _bt_core_log_api.v1.fatal(LOG_MODULE, ""); \ + abort(); \ + } + +void core_log_ext_win_last_error_log(const char *module, bt_core_log_message_t log_message); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink-async.c b/src/main/core/log-sink-async.c new file mode 100644 index 00000000..e1240c0f --- /dev/null +++ b/src/main/core/log-sink-async.c @@ -0,0 +1,408 @@ +#define LOG_MODULE "core-log-sink-async" + +#include + +#include +#include +#include +#include + +#include "core/log-bt.h" +#include "core/log-sink.h" +#include "core/log-sink-async.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "util/mem.h" +#include "util/str.h" + +#define CORE_LOG_SINK_ASYNC_TIMESTAMP_SIZE_MAX 64 +// That's plenty for the few messages with fairly bounded message size we got +#define CORE_LOG_SINK_ASYNC_DIRECT_LOG_BUFFER_SIZE 1024 * 4 + +#define log_safe_direct_misc(ctx, ...) \ + _core_log_sink_async_direct_log(ctx, CORE_LOG_BT_LOG_LEVEL_MISC, __VA_ARGS__) +#define log_safe_direct_info(ctx, ...) \ + _core_log_sink_async_direct_log(ctx, CORE_LOG_BT_LOG_LEVEL_INFO, __VA_ARGS__) +#define log_safe_direct_warning(ctx, ...) \ + _core_log_sink_async_direct_log(ctx, CORE_LOG_BT_LOG_LEVEL_WARNING, __VA_ARGS__) +#define log_safe_direct_fatal(ctx, ...) \ + do { \ + _core_log_sink_async_direct_log(ctx, CORE_LOG_BT_LOG_LEVEL_FATAL, __VA_ARGS__); \ + ctx->target_sink.close(ctx->target_sink.ctx); \ + abort(); \ + } while (false) + +typedef struct core_log_sink_async_queue_elem { + char *buffer; + size_t len; +} core_log_sink_async_queue_elem_t; + +typedef struct core_log_sink_async_queue { + size_t len_public; + size_t len_internal; + core_log_sink_async_queue_elem_t *elem; + size_t pos_front; + size_t pos_back; + HANDLE mutex; +} core_log_sink_async_queue_t; + +typedef struct core_log_sink_async { + uint32_t msg_buffer_size; + core_log_sink_async_overflow_policy_t overflow_policy; + core_log_sink_t target_sink; + + core_log_sink_async_queue_t *queue; + + HANDLE semaphore_producer; + HANDLE semaphore_consumer; + + bt_core_thread_id_t thread_id; + _Atomic(bool) thread_proc_loop; + _Atomic(bool) thread_proc_running; +} core_log_sink_async_t; + +static core_log_sink_async_queue_t *_core_log_sink_async_queue_alloc(size_t buffer_size, size_t len) +{ + size_t len_internal; + core_log_sink_async_queue_t *queue; + + queue = xmalloc(sizeof(core_log_sink_async_queue_t)); + + // Actual queue length is always len + 1 because we need one "dead spot" + // that isn't used when the queue is considered full. Otherwise, there + // is no way to distinguish an empty from a full queue with this setup + // Example: + // - Queue that can store 4 elements + // - It is empty when front_pos == back_pos + // - Filling up the queue with 4 elements back_pos increments 4 times + // - Applying wrap-around with modulo, back_pos points to first index + // again which is front_pos if no elements were consumed thus far + len_internal = len + 1; + + queue->elem = xmalloc(sizeof(core_log_sink_async_queue_elem_t) * len_internal); + + for (size_t i = 0; i < len_internal; i++) { + queue->elem[i].buffer = xmalloc(sizeof(char) * buffer_size); + queue->elem[i].len = 0; + } + + queue->len_public = len; + queue->len_internal = len_internal; + queue->pos_front = 0; + queue->pos_back = 0; + queue->mutex = CreateMutex(NULL, FALSE, NULL); + + return queue; +} + +static bool _core_log_sink_async_queue_push(core_log_sink_async_queue_t *queue, const char *buffer, size_t len) +{ + size_t back; + size_t front; + size_t index; + + back = queue->pos_back; + front = queue->pos_front; + + // Optimistic check outside of lock to reduce lock contention + // Queue full + if (back + 1 % queue->len_internal == front % queue->len_internal) { + return false; + } + + WaitForSingleObject(queue->mutex, INFINITE); + + // Repeat operation within lock to get consistent state + if (queue->pos_back + 1 % queue->len_internal == queue->pos_front % queue->len_internal) { + ReleaseMutex(queue->mutex); + return false; + } + + index = (queue->pos_back + 1) % queue->len_internal; + + memcpy(queue->elem[index].buffer, buffer, len); + queue->elem[index].len = len; + + queue->pos_back++; + + ReleaseMutex(queue->mutex); + + return true; +} + +static bool _core_log_sink_async_queue_pop(core_log_sink_async_queue_t *queue, char *buffer, size_t *len) +{ + size_t front; + size_t back; + size_t index; + + // Be "optimistic" and do this outside the lock to reduce lock contention + // with producers + front = queue->pos_front; + back = queue->pos_back; + + // Empty + if (front % queue->len_internal == back % queue->len_internal) { + return false; + } + + WaitForSingleObject(queue->mutex, INFINITE); + + // Another check within the lock + if (queue->pos_front % queue->len_internal == queue->pos_back % queue->len_internal) { + ReleaseMutex(queue->mutex); + return false; + } + + index = queue->pos_front % queue->len_internal; + + memcpy(buffer, queue->elem[index].buffer, queue->elem[index].len); + *len = queue->elem[index].len; + + queue->pos_front++; + + ReleaseMutex(queue->mutex); + + return true; +} + +static void _core_log_sink_async_queue_free(core_log_sink_async_queue_t *queue) +{ + for (size_t i = 0; i < queue->len_internal; i++) { + free(queue->elem[i].buffer); + } + + free(queue->elem); + CloseHandle(queue->mutex); + free(queue); +} + +// Consumer and producer must write directly to the sink in case there is +// an issue with the async sink itself. They can't go through the logging +// system because that's hooked up to this sink +// Copy-paste of log-bt with minor tweaks to have log levels and timestamps available +static void _core_log_sink_async_direct_log( + core_log_sink_async_t *ctx, + enum core_log_bt_log_level level, + const char *fmt, + ...) +{ + static const char chars[] = "FFWIM"; + + va_list args; + char timestamp[CORE_LOG_SINK_ASYNC_TIMESTAMP_SIZE_MAX]; + char msg[CORE_LOG_SINK_ASYNC_DIRECT_LOG_BUFFER_SIZE]; + char line[CORE_LOG_SINK_ASYNC_DIRECT_LOG_BUFFER_SIZE]; + int result; + + time_t curtime; + struct tm *tm; + + va_start(args, fmt); + + curtime = 0; + tm = NULL; + + curtime = time(NULL); + tm = localtime(&curtime); + + strftime(timestamp, sizeof(timestamp), "[%Y/%m/%d %H:%M:%S]", tm); + + str_vformat(msg, sizeof(msg), fmt, args); + + va_end(args); + + result = str_format( + line, + sizeof(line), + "%s %c:%s: %s\n", + timestamp, + chars[level], + LOG_MODULE, + msg); + + ctx->target_sink.write(ctx->target_sink.ctx, line, result); +} + +static int _core_log_sink_async_thread_proc(void *ctx_) +{ + core_log_sink_async_t *ctx; + char *buffer; + size_t len; + bool is_empty; + + ctx = (core_log_sink_async_t*) ctx_; + + // Own private buffer, pop from queue copies data to it + buffer = xmalloc(sizeof(char) * ctx->msg_buffer_size); + len = 0; + + atomic_store_explicit(&ctx->thread_proc_running, true, memory_order_seq_cst); + + log_safe_direct_misc(ctx, "Thread running"); + + while (atomic_load_explicit(&ctx->thread_proc_loop, memory_order_seq_cst)) { + // Wait until any producer signals that there is data in the queue + // Use this instead of polling the queue to save CPU resources + if (WaitForSingleObject(ctx->semaphore_producer, INFINITE)) { + // Need to write directly to sink as the logging system might be broken + log_safe_direct_fatal(ctx, "WaitForSingleObject failed: %08x", (unsigned int) GetLastError()); + } + + is_empty = !_core_log_sink_async_queue_pop(ctx->queue, buffer, &len); + + ReleaseSemaphore(ctx->semaphore_consumer, 1, NULL); + + // Execute potentially expensive IO writing the data outside of critical section + // to avoid lock contention + if (!is_empty) { + ctx->target_sink.write(ctx->target_sink.ctx, buffer, len); + } else { + log_safe_direct_warning(ctx, "Popping from queue failed, queue is empty"); + } + } + + free(buffer); + + atomic_store_explicit(&ctx->thread_proc_running, false, memory_order_seq_cst); + + log_safe_direct_misc(ctx, "Thread running"); + + return 0; +} + +static void +_core_log_sink_async_write(void *ctx_, const char *chars, size_t nchars) +{ + core_log_sink_async_t *ctx; + DWORD result; + bool is_full; + + ctx = (core_log_sink_async_t*) ctx_; + + // "Try acquire" a semaphore to avoid blocking the caller if not desired + // (see overflow policy) + result = WaitForSingleObject(ctx->semaphore_consumer, 0); + + if (result == WAIT_TIMEOUT) { + switch (ctx->overflow_policy) { + case CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_DISCARD_NEW: + return; + case CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_BLOCK: + if (WaitForSingleObject(ctx->semaphore_consumer, INFINITE)) { + log_safe_direct_fatal(ctx, "WaitForSingleObject failed: %08x", (unsigned int) GetLastError()); + } + + break; + default: + log_safe_direct_fatal(ctx, "Illegal state for overflow policy: %d", ctx->overflow_policy); + } + } else if (result != WAIT_OBJECT_0) { + log_safe_direct_fatal(ctx, "WaitForSingleObject 2 failed: %08x", (unsigned int) GetLastError()); + } + + // This copies the data to the buffers allocated with the queue which + // is a non-blocking operation at this point. The semaphores are + // orchestrating multiple threads to ensure that only if there is + // capacity in the queue threads will get here + is_full = !_core_log_sink_async_queue_push(ctx->queue, chars, nchars); + + if (is_full) { + log_safe_direct_warning(ctx, "Invalid state, pushing log message to queue failed, queue full"); + } else { + ReleaseSemaphore(ctx->semaphore_producer, 1, NULL); + } +} + +static void _core_log_sink_async_close(void *ctx_) +{ + core_log_sink_async_t *ctx; + bt_core_thread_result_t result; + + ctx = (core_log_sink_async_t*) ctx_; + + log_safe_direct_info(ctx, "Shutting down logger thread and waiting for it to finish..."); + + atomic_store_explicit(&ctx->thread_proc_loop, false, memory_order_seq_cst); + + result = bt_core_thread_join(ctx->thread_id, NULL); + + if (BT_CORE_THREAD_RESULT_IS_ERROR(BT_CORE_THREAD_RESULT_SUCCESS)) { + log_safe_direct_fatal(ctx, "Joining logger thread failed"); + } else { + log_safe_direct_info(ctx, "Logger thread finished"); + } + + result = bt_core_thread_destroy(ctx->thread_id); + + if (BT_CORE_THREAD_RESULT_IS_ERROR(result)) { + log_safe_direct_fatal(ctx, "Destroying logger thread failed"); + } + + CloseHandle(ctx->semaphore_producer); + CloseHandle(ctx->semaphore_consumer); + + _core_log_sink_async_queue_free(ctx->queue); + + // Last message before closing the child sink + log_safe_direct_misc(ctx, "Shutting down done"); + + ctx->target_sink.close(ctx->target_sink.ctx); + + free(ctx); +} + +void core_log_sink_async_open( + uint32_t msg_buffer_size, + uint8_t queue_length, + core_log_sink_async_overflow_policy_t overflow_policy, + const core_log_sink_t *child_sink, + core_log_sink_t *sink) +{ + core_log_sink_async_t *ctx; + bt_core_thread_result_t result; + + // Sanity check for sizes we consider too much or too less + log_assert(msg_buffer_size > 1024); // 1 kB + log_assert(msg_buffer_size <= 1024 * 1024); // 1 MB + // Limits max space for buffers to 128 MB which is plenty for excessive + // debug logging tasks of stuff like IO dumps, if necessary + log_assert(queue_length < 128); + log_assert(child_sink); + log_assert(sink); + + ctx = xmalloc(sizeof(core_log_sink_async_t)); + + ctx->msg_buffer_size = msg_buffer_size; + ctx->overflow_policy = overflow_policy; + + ctx->target_sink.ctx = child_sink->ctx; + ctx->target_sink.write = child_sink->write; + ctx->target_sink.close = child_sink->close; + + ctx->queue = _core_log_sink_async_queue_alloc(msg_buffer_size, queue_length); + + ctx->semaphore_producer = CreateSemaphore(NULL, 0, queue_length, NULL); + ctx->semaphore_consumer = CreateSemaphore(NULL, queue_length, queue_length, NULL); + + atomic_store_explicit(&ctx->thread_proc_loop, true, memory_order_seq_cst); + atomic_store_explicit(&ctx->thread_proc_running, false, memory_order_seq_cst); + + result = bt_core_thread_create(_core_log_sink_async_thread_proc, ctx, 16384, 0, &ctx->thread_id); + bt_core_thread_fatal_on_error(result); + + log_misc("Waiting for thread to start..."); + + // wait until thread is running + while (!atomic_load_explicit(&ctx->thread_proc_running, memory_order_seq_cst)) { + Sleep(10); + } + + sink->ctx = ctx; + sink->write = _core_log_sink_async_write; + sink->close = _core_log_sink_async_close; + + log_misc("Open: msg_buffer_size %d, queue_length %d, overflow_policy %d", msg_buffer_size, queue_length, overflow_policy); +} \ No newline at end of file diff --git a/src/main/core/log-sink-async.h b/src/main/core/log-sink-async.h new file mode 100644 index 00000000..bbeeb5ce --- /dev/null +++ b/src/main/core/log-sink-async.h @@ -0,0 +1,45 @@ +#ifndef CORE_LOG_SINK_ASYNC_H +#define CORE_LOG_SINK_ASYNC_H + +#include +#include + +#include "core/log-sink.h" + +typedef enum core_log_sink_async_overflow_policy { + // Any to be posted new messages will be dropped, the thread posting the + // message will not block and wait for space in the queue to be available + CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_DISCARD_NEW = 0, + // Any thread posting messages to the queue will fully block and wait + // until it acquires space to post the message + CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_BLOCK = 1, +} core_log_sink_async_overflow_policy_t; + +/** + * Open a async log sink + * + * The sink passes data to log to a separate thread which executes the actual + * logging of the data + * + * @param msg_buffer_size Size for the backend message buffer, ensure this is + * at least as large as any buffer sizes the logger uses (i.e. make it + * the same size) + * @param queue_length Length of the queue shared between the threads posting + * messages to it and the async background thread consuming them. A + * longer queue size increases the memory footprint but allows for + * buffering more messages before the overflow policy is applied + * @param overflow_policy Apply this policy if the threads posting messages + * to the queue are facing a full queue (see the overflow policy enum) + * @param child_sink The target sink the async background will write any + * messages consumed from the queue to + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_async_open( + // Ensure that buffer size is the same as for the logger + uint32_t msg_buffer_size, + uint8_t queue_length, + core_log_sink_async_overflow_policy_t overflow_policy, + const core_log_sink_t *child_sink, + core_log_sink_t *sink); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink-debug.c b/src/main/core/log-sink-debug.c new file mode 100644 index 00000000..54c622b3 --- /dev/null +++ b/src/main/core/log-sink-debug.c @@ -0,0 +1,31 @@ +#define LOG_MODULE "core-log-sink-debug" + +#include + +#include + +#include "core/log-sink.h" + +#include "iface-core/log.h" + +static void +_core_log_sink_debug_write(void *ctx, const char *chars, size_t nchars) +{ + OutputDebugStringA(chars); +} + +static void _core_log_sink_debug_close(void *ctx) +{ + // noop +} + +void core_log_sink_debug_open(core_log_sink_t *sink) +{ + log_assert(sink); + + log_misc("Open"); + + sink->ctx = NULL; + sink->write = _core_log_sink_debug_write; + sink->close = _core_log_sink_debug_close; +} \ No newline at end of file diff --git a/src/main/core/log-sink-debug.h b/src/main/core/log-sink-debug.h new file mode 100644 index 00000000..6b68dfd3 --- /dev/null +++ b/src/main/core/log-sink-debug.h @@ -0,0 +1,15 @@ +#ifndef CORE_LOG_SINK_DEBUG_H +#define CORE_LOG_SINK_DEBUG_H + +#include + +#include "core/log-sink.h" + +/** + * Open a log sink that uses OutputDebugStr + * + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_debug_open(core_log_sink_t *sink); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink-file.c b/src/main/core/log-sink-file.c new file mode 100644 index 00000000..fb642085 --- /dev/null +++ b/src/main/core/log-sink-file.c @@ -0,0 +1,105 @@ +#define LOG_MODULE "core-log-sink-file" + +#include + +#include +#include +#include +#include + +#include "core/log-sink.h" + +#include "iface-core/log.h" + +#include "util/fs.h" +#include "util/str.h" + +static void _core_log_sink_file_rotate(const char *path, uint8_t max_rotations) +{ + uint8_t i; + char rotate_file[MAX_PATH]; + char rotate_file_next[MAX_PATH]; + char version[8]; + char version_next[8]; + + for (i = max_rotations; i > 0; i++) { + str_cpy(rotate_file, sizeof(rotate_file), path); + str_cpy(rotate_file_next, sizeof(rotate_file_next), path); + + if (i - 1 != 0) { + sprintf(version, ".%d", i); + } else { + memset(version, 0, sizeof(version)); + } + + sprintf(version_next, ".%d", i); + + str_cat(rotate_file, sizeof(rotate_file), version); + str_cat(rotate_file_next, sizeof(rotate_file_next), version_next); + + if (path_exists(rotate_file)) { + CopyFile(rotate_file, rotate_file_next, FALSE); + } + } +} + +static void +_core_log_sink_file_write(void *ctx, const char *chars, size_t nchars) +{ + FILE *file; + + file = (FILE *) ctx; + + fwrite(chars, 1, nchars, file); +} + +static void _core_log_sink_file_close(void *ctx) +{ + FILE *file; + + file = (FILE *) ctx; + + fflush(file); + fclose(file); +} + +void core_log_sink_file_open( + const char *path, + bool append, + bool rotate, + uint8_t max_rotations, + core_log_sink_t *sink) +{ + FILE *file; + + log_assert(path); + log_assert(sink); + + log_info( + "Open: %s, append %s, rotate %d, max_rotations %d", + path, + append, + rotate, + max_rotations); + + if (rotate) { + _core_log_sink_file_rotate(path, max_rotations); + + // Appending doesn't matter when file is rotated anyway + file = fopen(path, "w+"); + } else { + if (append) { + file = fopen(path, "a+"); + } else { + file = fopen(path, "w+"); + } + } + + if (!file) { + log_fatal("Cannot open log file: %s", path); + } + + sink->ctx = (void *) file; + sink->write = _core_log_sink_file_write; + sink->close = _core_log_sink_file_close; +} \ No newline at end of file diff --git a/src/main/core/log-sink-file.h b/src/main/core/log-sink-file.h new file mode 100644 index 00000000..488fa37e --- /dev/null +++ b/src/main/core/log-sink-file.h @@ -0,0 +1,28 @@ +#ifndef CORE_LOG_SINK_FILE_H +#define CORE_LOG_SINK_FILE_H + +#include +#include +#include + +#include "core/log-sink.h" + +/** + * Open a log sink writing data to a file + * + * @param path Path to the log file to write the log output to + * @param append If true, then append to an existing file, false to overwrite + * any existing file + * @param rotate If true, rotates an existing log file and creates a new one + * for this session + * @param max_rotations Max number of rotations for the log files + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_file_open( + const char *path, + bool append, + bool rotate, + uint8_t max_rotations, + core_log_sink_t *sink); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink-list.c b/src/main/core/log-sink-list.c new file mode 100644 index 00000000..2ba560db --- /dev/null +++ b/src/main/core/log-sink-list.c @@ -0,0 +1,75 @@ +#define LOG_MODULE "core-log-sink-list" + +#include +#include + +#include "core/log-sink-list.h" +#include "core/log-sink.h" + +#include "iface-core/log.h" + +#include "util/mem.h" + +#define MAX_SINKS 8 + +typedef struct core_log_sink_list { + core_log_sink_t entries[MAX_SINKS]; + uint8_t num; +} core_log_sink_list_t; + +static void +_core_log_sink_list_write(void *ctx, const char *chars, size_t nchars) +{ + core_log_sink_list_t *sink_list; + int i; + + sink_list = (core_log_sink_list_t *) ctx; + + for (i = 0; i < sink_list->num; i++) { + sink_list->entries[i].write(sink_list->entries[i].ctx, chars, nchars); + } +} + +static void _core_log_sink_list_close(void *ctx) +{ + core_log_sink_list_t *sink_list; + int i; + + sink_list = (core_log_sink_list_t *) ctx; + + for (i = 0; i < sink_list->num; i++) { + sink_list->entries[i].close(sink_list->entries[i].ctx); + } + + free(sink_list); +} + +void core_log_sink_list_open( + const core_log_sink_t *entry, uint8_t num, core_log_sink_t *sink) +{ + core_log_sink_list_t *sink_list; + int i; + + log_assert(entry); + log_assert(sink); + + log_misc("Open: %d", num); + + if (num > MAX_SINKS) { + abort(); + } + + sink_list = xmalloc(sizeof(core_log_sink_list_t)); + + for (i = 0; i < num; i++) { + sink_list->entries[i].ctx = entry[i].ctx; + sink_list->entries[i].write = entry[i].write; + sink_list->entries[i].close = entry[i].close; + } + + sink_list->num = num; + + sink->ctx = (void *) sink_list; + sink->write = _core_log_sink_list_write; + sink->close = _core_log_sink_list_close; +} \ No newline at end of file diff --git a/src/main/core/log-sink-list.h b/src/main/core/log-sink-list.h new file mode 100644 index 00000000..91db79dd --- /dev/null +++ b/src/main/core/log-sink-list.h @@ -0,0 +1,24 @@ +#ifndef CORE_LOG_SINK_LIST_H +#define CORE_LOG_SINK_LIST_H + +#include +#include + +#include "core/log-sink.h" + +/** + * Combine multiple log sinks into a list of sinks. + * + * Upon invoking a list sink, all sinks contained within the list are + * being invoked in the configured order. + * + * @param entry A pointer to allocated memory with a sequence of opened sinks + * that you want to add to the list. Ownership of these sinks + * is transferred, i.e. closing the list sink closes its children. + * @param num The number of elements in the sequence of opened sinks pointed to. + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_list_open( + const core_log_sink_t *entry, uint8_t num, core_log_sink_t *sink); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink-mutex.c b/src/main/core/log-sink-mutex.c new file mode 100644 index 00000000..b5fa5f60 --- /dev/null +++ b/src/main/core/log-sink-mutex.c @@ -0,0 +1,62 @@ +#define LOG_MODULE "core-log-sink-mutex" + +#include + +#include + +#include "core/log-sink.h" + +#include "iface-core/log.h" + +#include "util/mem.h" + +typedef struct core_log_sink_mutex { + core_log_sink_t child; + HANDLE mutex; +} core_log_sink_mutex_t; + +static void +_core_log_sink_mutex_write(void *ctx_, const char *chars, size_t nchars) +{ + core_log_sink_mutex_t *ctx; + + ctx = (core_log_sink_mutex_t *) ctx_; + + WaitForSingleObject(ctx->mutex, INFINITE); + + ctx->child.write(ctx->child.ctx, chars, nchars); + + ReleaseMutex(ctx->mutex); +} + +static void _core_log_sink_mutex_close(void *ctx_) +{ + core_log_sink_mutex_t *ctx; + + ctx = (core_log_sink_mutex_t *) ctx_; + + CloseHandle(ctx->mutex); + + ctx->child.close(ctx->child.ctx); + free(ctx); +} + +void core_log_sink_mutex_open( + const core_log_sink_t *child_sink, core_log_sink_t *sink) +{ + core_log_sink_mutex_t *ctx; + + log_assert(child_sink); + log_assert(sink); + + log_misc("Open"); + + ctx = xmalloc(sizeof(core_log_sink_mutex_t)); + + memcpy(&ctx->child, child_sink, sizeof(core_log_sink_t)); + ctx->mutex = CreateMutex(NULL, FALSE, NULL); + + sink->ctx = ctx; + sink->write = _core_log_sink_mutex_write; + sink->close = _core_log_sink_mutex_close; +} \ No newline at end of file diff --git a/src/main/core/log-sink-mutex.h b/src/main/core/log-sink-mutex.h new file mode 100644 index 00000000..dadfff0a --- /dev/null +++ b/src/main/core/log-sink-mutex.h @@ -0,0 +1,21 @@ +#ifndef CORE_LOG_SINK_MUTEX_H +#define CORE_LOG_SINK_MUTEX_H + +#include + +#include "core/log-sink.h" + +/** + * Create a sink that surrounds another sink with a mutex. + * + * Use this to make other sink implementations thread-safe. + * + * @param child_sink Another opened sink to surround with the mutex. Ownership + * of the sink is transferred, i.e. closing the mutex sink + * also closes the wrapped child sink. + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_mutex_open( + const core_log_sink_t *child_sink, core_log_sink_t *sink); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink-null.c b/src/main/core/log-sink-null.c new file mode 100644 index 00000000..a02ea80a --- /dev/null +++ b/src/main/core/log-sink-null.c @@ -0,0 +1,29 @@ +#define LOG_MODULE "core-log-sink-null" + +#include + +#include "core/log-sink.h" + +#include "iface-core/log.h" + +static void +_core_log_sink_null_write(void *ctx, const char *chars, size_t nchars) +{ + // noop +} + +static void _core_log_sink_null_close(void *ctx) +{ + // noop +} + +void core_log_sink_null_open(core_log_sink_t *sink) +{ + log_assert(sink); + + log_misc("Open"); + + sink->ctx = NULL; + sink->write = _core_log_sink_null_write; + sink->close = _core_log_sink_null_close; +} \ No newline at end of file diff --git a/src/main/core/log-sink-null.h b/src/main/core/log-sink-null.h new file mode 100644 index 00000000..9bb3f372 --- /dev/null +++ b/src/main/core/log-sink-null.h @@ -0,0 +1,17 @@ +#ifndef CORE_LOG_SINK_NULL_H +#define CORE_LOG_SINK_NULL_H + +#include + +#include "core/log-sink.h" + +/** + * Create a null/dummy sink. + * + * Use this to disable any logging entirely. + * + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_null_open(core_log_sink_t *sink); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink-std.c b/src/main/core/log-sink-std.c new file mode 100644 index 00000000..aa9f225e --- /dev/null +++ b/src/main/core/log-sink-std.c @@ -0,0 +1,218 @@ +#define LOG_MODULE "core-log-sink-std" + +#include + +#include + +#include "core/log-sink.h" + +#include "iface-core/log.h" + +#include "util/mem.h" + +typedef struct core_log_sink_std { + HANDLE handle; + bool color; + HANDLE mutex; +} core_log_sink_std_t; + +static char _core_log_sink_std_determine_color(const char *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 _core_log_sink_std_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 +_core_log_sink_std_write(void *ctx_, const char *chars, size_t nchars) +{ + static const size_t timestamp_len = strlen("[----/--/-- --:--:--]"); + + core_log_sink_std_t *ctx; + + char color; + size_t color_len; + size_t msg_len; + const char *msg_start; + const char *msg_end; + DWORD written; + DWORD write_pos; + + ctx = (core_log_sink_std_t *) ctx_; + + if (ctx->color) { + // Coloring needs to be mutex'd as the writes are non atomic + // and get messed up when this is called by multiple threads + // e.g. AVS logging engine and core bt logging engine + + write_pos = 0; + + WaitForSingleObject(ctx->mutex, INFINITE); + + // Support multiple buffered log messages, e.g. from the AVS logging + // engine + while (write_pos < nchars) { + // Expects the AVS timestamp format + msg_start = chars + timestamp_len + 1; // +1 is the space + + color_len = _core_log_sink_std_msg_coloring_len(msg_start); + + // 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 = _core_log_sink_std_determine_color(msg_start); + + // Timestamp + WriteConsole( + ctx->handle, chars, timestamp_len + 1, &written, NULL); + write_pos += written; + chars += written; + + // Log level + module colored + SetConsoleTextAttribute(ctx->handle, color); + WriteConsole(ctx->handle, chars, color_len, &written, NULL); + write_pos += written; + chars += written; + SetConsoleTextAttribute(ctx->handle, 15); + + msg_end = strchr(chars, '\n'); + + if (msg_end != NULL) { + msg_len = msg_end - chars; + + // Write \n as well + msg_len++; + + // Write actual message non colored + WriteConsole(ctx->handle, chars, msg_len, &written, NULL); + write_pos += written; + chars += written; + } else { + WriteConsole( + ctx->handle, chars, nchars - write_pos, &written, NULL); + write_pos += written; + chars += written; + } + } else { + WriteConsole( + ctx->handle, + chars + write_pos, + nchars - write_pos, + &written, + NULL); + write_pos += written; + } + } + + ReleaseMutex(ctx->mutex); + } else { + WriteConsole(ctx->handle, chars, nchars, &written, NULL); + } +} + +static void _core_log_sink_std_close(void *ctx_) +{ + core_log_sink_std_t *ctx; + + ctx = (core_log_sink_std_t *) ctx_; + + // Remark: Don't close the ctx->handle, see win API docs + + CloseHandle(ctx->mutex); + + free(ctx); +} + +void core_log_sink_std_out_open(bool color, core_log_sink_t *sink) +{ + core_log_sink_std_t *ctx; + + log_assert(sink); + + log_misc("Open stdout"); + + ctx = xmalloc(sizeof(core_log_sink_std_t)); + + ctx->handle = GetStdHandle(STD_OUTPUT_HANDLE); + ctx->color = color; + ctx->mutex = CreateMutex(NULL, FALSE, NULL); + + sink->ctx = (void *) ctx; + sink->write = _core_log_sink_std_write; + sink->close = _core_log_sink_std_close; +} + +void core_log_sink_std_err_open(bool color, core_log_sink_t *sink) +{ + core_log_sink_std_t *ctx; + + log_assert(sink); + + log_misc("Open stderr"); + + ctx = xmalloc(sizeof(core_log_sink_std_t)); + + ctx->handle = GetStdHandle(STD_ERROR_HANDLE); + ctx->color = color; + ctx->mutex = CreateMutex(NULL, FALSE, NULL); + + sink->ctx = (void *) ctx; + sink->write = _core_log_sink_std_write; + sink->close = _core_log_sink_std_close; +} \ No newline at end of file diff --git a/src/main/core/log-sink-std.h b/src/main/core/log-sink-std.h new file mode 100644 index 00000000..d91bd9ff --- /dev/null +++ b/src/main/core/log-sink-std.h @@ -0,0 +1,25 @@ +#ifndef CORE_LOG_SINK_STD_H +#define CORE_LOG_SINK_STD_H + +#include +#include + +#include "core/log-sink.h" + +/** + * Create a sink that writes to stdout. + * + * @param color If true, messages are colored by log level. + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_std_out_open(bool color, core_log_sink_t *sink); + +/** + * Create a sink that writes to stderr. + * + * @param color If true, messages are colored by log level. + * @param sink Pointer to allocated memory that receives the opened sink + */ +void core_log_sink_std_err_open(bool color, core_log_sink_t *sink); + +#endif \ No newline at end of file diff --git a/src/main/core/log-sink.h b/src/main/core/log-sink.h new file mode 100644 index 00000000..c2dac059 --- /dev/null +++ b/src/main/core/log-sink.h @@ -0,0 +1,45 @@ +#ifndef CORE_LOG_SINK_H +#define CORE_LOG_SINK_H + +#include + +/** + * Write function for a log sink implementation. + * + * Write the given data to your target output destination. + * + * @param ctx Context defined by the implementation when opening the sink. + * @param chars Buffer with text data to log. This can contain partial data of + * a single log line, a full log line terminated by a newline + * character or multiple log lines (each terminated by a newline + * character). + * @param nchars Number of characters to write. + */ +typedef void (*core_log_sink_write_t)( + void *ctx, const char *chars, size_t nchars); + +/** + * Close your log sink and cleanup resources + * + * Depending on your implementation, you might want to flush any + * outstanding/buffered data. + * + * @param ctx Context defined by the implementation when opening the sink. + */ +typedef void (*core_log_sink_close_t)(void *ctx); + +/** + * Log sink structure. + * + * This must be set-up and populated when opening your log sink implementation. + * The ctx field contains any arbitrary data that you need for your log sink + * to operate, e.g. a file handle, additional buffers etc. Make sure these + * resources are cleaned up upon closing the sink. + */ +typedef struct core_log_sink { + void *ctx; + core_log_sink_write_t write; + core_log_sink_close_t close; +} core_log_sink_t; + +#endif \ No newline at end of file diff --git a/src/main/core/property-ext.c b/src/main/core/property-ext.c new file mode 100644 index 00000000..bcedba0f --- /dev/null +++ b/src/main/core/property-ext.c @@ -0,0 +1,85 @@ +#define LOG_MODULE "core-property-ext" + +#include "iface-core/log.h" + +#include "main/core/property-node-ext.h" +#include "main/core/property.h" + +void core_property_ext_log( + const core_property_t *property, bt_core_log_message_t log_message) +{ + core_property_node_t node; + core_property_node_result_t node_result; + + node_result = core_property_root_node_get(property, &node); + + if (node_result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_message(LOG_MODULE, ""); + return; + } else if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(node_result)) { + return; + } + + core_property_node_ext_log(&node, log_message); +} + +core_property_result_t core_property_ext_many_merge( + const core_property_t **properties, + size_t count, + core_property_t **out_property) +{ + core_property_t *merged_property; + core_property_t *tmp; + core_property_result_t result; + core_property_node_result_t result2; + int i; + + log_assert(properties); + log_assert(count > 0); + log_assert(out_property); + + result = core_property_clone(properties[0], &merged_property); + + if (CORE_PROPERTY_RESULT_IS_ERROR(result)) { + return result; + } + + if (count == 1) { + *out_property = merged_property; + return CORE_PROPERTY_RESULT_SUCCESS; + } + + for (i = 1; i < count; i++) { + result2 = core_property_node_ext_merge_do( + merged_property, properties[i], &tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result2)) { + core_property_free(&merged_property); + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + + core_property_free(&merged_property); + merged_property = tmp; + } + + *out_property = merged_property; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +core_property_result_t core_property_ext_merge( + const core_property_t *property_1, + const core_property_t *property_2, + core_property_t **out_property) +{ + const core_property_t *properties[2]; + + log_assert(property_1); + log_assert(property_2); + log_assert(out_property); + + properties[0] = property_1; + properties[1] = property_2; + + return core_property_ext_many_merge(properties, 2, out_property); +} \ No newline at end of file diff --git a/src/main/core/property-ext.h b/src/main/core/property-ext.h new file mode 100644 index 00000000..ad934461 --- /dev/null +++ b/src/main/core/property-ext.h @@ -0,0 +1,19 @@ +#ifndef CORE_PROPERTY_EXT_H +#define CORE_PROPERTY_EXT_H + +#include "iface-core/log.h" + +#include "main/core/property.h" + +void core_property_ext_log( + const core_property_t *property, bt_core_log_message_t log_message); + +core_property_result_t core_property_ext_many_merge( + core_property_t **properties, size_t count, core_property_t **out_property); + +core_property_result_t core_property_ext_merge( + const core_property_t *property_1, + const core_property_t *property_2, + core_property_t **out_property); + +#endif diff --git a/src/main/core/property-mxml-internal.h b/src/main/core/property-mxml-internal.h new file mode 100644 index 00000000..ad290816 --- /dev/null +++ b/src/main/core/property-mxml-internal.h @@ -0,0 +1,33 @@ +#ifndef CORE_PROPERTY_MXML_INTERNAL_H +#define CORE_PROPERTY_MXML_INTERNAL_H + +#include + +#include "core/property.h" +#include "core/property-node.h" + +// As there is no need to have a fixed size allocated for properties with +// everything dynamically growing on the heap when necessary, just +// use this as a dummy value to be compatible with the property interface +#define CORE_PROPERTY_MXML_INTERNAL_FIXED_SIZE_DUMMY 573 + +typedef struct core_property_mxml_internal_property { + mxml_node_t *document; +} core_property_mxml_internal_property_t; + +_Static_assert( + sizeof(core_property_mxml_internal_property_t) <= sizeof(core_property_t), + "Not enough space for stack allocations"); + +typedef struct core_property_mxml_internal_property_node { + core_property_mxml_internal_property_t *property; + mxml_node_t *node; + // Used when node is being iterated to remember the root of the iteration + mxml_node_t *node_root_iter; +} core_property_mxml_internal_property_node_t; + +_Static_assert( + sizeof(core_property_mxml_internal_property_node_t) <= sizeof(core_property_node_t), + "Not enough space for stack allocations"); + +#endif \ No newline at end of file diff --git a/src/main/core/property-mxml.c b/src/main/core/property-mxml.c new file mode 100644 index 00000000..a567476d --- /dev/null +++ b/src/main/core/property-mxml.c @@ -0,0 +1,240 @@ +#define LOG_MODULE "core-property-mxml" + +#include + +#include +#include + +#include + +#include "core/property-mxml-internal.h" +#include "core/property-node-mxml.h" +#include "core/property-mxml.h" + +#include "iface-core/log.h" + +#include "util/fs.h" +#include "util/mem.h" + +static core_property_result_t +_core_property_mxml_create(size_t size, core_property_t **property_) +{ + mxml_node_t *node; + core_property_mxml_internal_property_t *property; + + // There is no need to use the size parameter here as everything's allocated + // dynamically on the heap and no initial fixed size is needed + node = mxmlNewXML(NULL); + + if (!node) { + return CORE_PROPERTY_RESULT_ERROR_ALLOC; + } + + property = xmalloc(sizeof(core_property_mxml_internal_property_t)); + + property->document = node; + + *property_ = (core_property_t *) property; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t +_core_property_mxml_file_load(const char *path, core_property_t **property_) +{ + mxml_node_t *node; + core_property_mxml_internal_property_t *property; + + // The return value NULL of the loading function + // doesn't distinguish file not found and loading error =| + if (!path_exists(path)) { + return CORE_PROPERTY_RESULT_NOT_FOUND; + } + + node = mxmlLoadFilename(NULL, NULL, path); + + if (!node) { + return CORE_PROPERTY_RESULT_ERROR_READ; + } + + property = xmalloc(sizeof(core_property_mxml_internal_property_t)); + + property->document = node; + + *property_ = (core_property_t *) property; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t +_core_property_mxml_str_load(const char *str, core_property_t **property_) +{ + mxml_node_t *node; + core_property_mxml_internal_property_t *property; + + node = mxmlLoadString(NULL, NULL, str); + + if (!node) { + return CORE_PROPERTY_RESULT_ERROR_READ; + } + + property = xmalloc(sizeof(core_property_mxml_internal_property_t)); + + property->document = node; + + *property_ = (core_property_t *) property; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t +_core_property_mxml_size(const core_property_t *property_, size_t *size) +{ + *size = CORE_PROPERTY_MXML_INTERNAL_FIXED_SIZE_DUMMY; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t _core_property_mxml_clone( + const core_property_t *property_, core_property_t **property_cloned_) +{ + const core_property_mxml_internal_property_t *property; + core_property_mxml_internal_property_t **property_cloned; + + char *str_copy; + mxml_node_t *node_cloned; + + property = (const core_property_mxml_internal_property_t*) property_; + property_cloned = (core_property_mxml_internal_property_t**) property_cloned_; + + // Ensure actual cloning by storing and loading this + // Just "adding it" to the other tree with mxml creates a reference only + + str_copy = mxmlSaveAllocString(property->document, NULL); + + if (str_copy == NULL) { + return CORE_PROPERTY_RESULT_ERROR_READ; + } + + node_cloned = mxmlLoadString(NULL, NULL, str_copy); + + if (node_cloned == NULL) { + return CORE_PROPERTY_RESULT_ERROR_WRITE; + } + + *property_cloned = xmalloc(sizeof(core_property_mxml_internal_property_t)); + + (*property_cloned)->document = node_cloned; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t _core_property_mxml_root_node_get( + const core_property_t *property_, core_property_node_t *node_) +{ + core_property_mxml_internal_property_t *property; + core_property_mxml_internal_property_node_t *node; + mxml_node_t *mxml_node; + mxml_type_t type; + + property = (core_property_mxml_internal_property_t *) property_; + node = (core_property_mxml_internal_property_node_t *) node_; + + memset(node, 0, sizeof(core_property_mxml_internal_property_node_t)); + + // Walk the nodes as the loaded xml node is the document root + // which can be the xml directive, or if missing, the first root + // element + for (mxml_node = property->document; + mxml_node != NULL; + mxml_node = mxmlWalkNext(mxml_node, property->document, MXML_DESCEND_FIRST)) + { + type = mxmlGetType(mxml_node); + // Consider the first element to be found the root element of the + // document. Having multiple roots isn't a valid XML document + // anyway + if (type == MXML_TYPE_ELEMENT) { + break; + } + } + + if (mxml_node == NULL) { + return CORE_PROPERTY_RESULT_NOT_FOUND; + } + + node->property = property; + // No difference for property vs. property_node + node->node = mxml_node; + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +static core_property_result_t _core_property_mxml_other_node_insert( + core_property_t *property_, const core_property_node_t *node_) +{ + core_property_mxml_internal_property_t *property; + core_property_mxml_internal_property_node_t *node; + + char *str_copy; + mxml_node_t *node_cloned; + + property = (core_property_mxml_internal_property_t *) property_; + node = (core_property_mxml_internal_property_node_t *) node_; + + // Ensure actual cloning by storing and loading this + // Just "adding it" to the other tree with mxml creates a reference only + + str_copy = mxmlSaveAllocString(node->node, NULL); + + if (str_copy == NULL) { + return CORE_PROPERTY_RESULT_ERROR_READ; + } + + node_cloned = mxmlLoadString(NULL, NULL, str_copy); + + if (node_cloned == NULL) { + return CORE_PROPERTY_RESULT_ERROR_WRITE; + } + + // Hook the new node into the existing tree + + mxmlAdd(property->document, MXML_ADD_AFTER, NULL, node_cloned); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static void _core_property_mxml_free(core_property_t **property_) +{ + core_property_mxml_internal_property_t *property; + + property = (core_property_mxml_internal_property_t *) (*property_); + + mxmlDelete(property->document); + + free(*property_); + *property_ = NULL; +} + +static void _core_property_mxml_core_api_get(core_property_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.create = _core_property_mxml_create; + api->v1.file_load = _core_property_mxml_file_load; + api->v1.str_load = _core_property_mxml_str_load; + api->v1.size = _core_property_mxml_size; + api->v1.clone = _core_property_mxml_clone; + api->v1.root_node_get = _core_property_mxml_root_node_get; + api->v1.other_node_insert = _core_property_mxml_other_node_insert; + api->v1.free = _core_property_mxml_free; +} + +void core_property_mxml_core_api_set() +{ + core_property_api_t api; + + _core_property_mxml_core_api_get(&api); + core_property_api_set(&api); +} diff --git a/src/main/core/property-mxml.h b/src/main/core/property-mxml.h new file mode 100644 index 00000000..e061f494 --- /dev/null +++ b/src/main/core/property-mxml.h @@ -0,0 +1,8 @@ +#ifndef CORE_PROPERTY_MXML_H +#define CORE_PROPERTY_MXML_H + +#include "main/core/property.h" + +void core_property_mxml_core_api_set(); + +#endif \ No newline at end of file diff --git a/src/main/core/property-node-ext.c b/src/main/core/property-node-ext.c new file mode 100644 index 00000000..8d0bbdc6 --- /dev/null +++ b/src/main/core/property-node-ext.c @@ -0,0 +1,873 @@ +#define LOG_MODULE "core-property-node-ext" + +#include +#include + +#include "iface-core/log.h" + +#include "core/property-node-ext.h" +#include "core/property-node.h" + +#include "util/hex.h" +#include "util/str.h" + +struct core_property_node_ext_merge_ctx { + const char *path; + const core_property_node_ext_merge_strategies_t *strategies; +}; + +typedef struct core_property_node_ext_merge_ctx + core_property_node_ext_merge_ctx_t; + +static core_property_node_result_t _core_property_node_ext_merge_recursive_do( + core_property_node_t *parent, + const core_property_node_t *source, + void *ctx_) +{ + const core_property_node_ext_merge_ctx_t *ctx; + core_property_node_ext_merge_ctx_t ctx_next; + + char parent_name[CORE_PROPERTY_NODE_NAME_SIZE_MAX]; + char parent_path[CORE_PROPERTY_NODE_PATH_LEN_MAX]; + + core_property_node_result_t result; + bool consumed; + uint8_t i; + + log_assert(parent); + log_assert(source); + log_assert(ctx_); + + ctx = (const core_property_node_ext_merge_ctx_t *) ctx_; + + log_assert(ctx->path); + log_assert(ctx->strategies); + log_assert(ctx->strategies->num > 0); + + result = + core_property_node_name_get(parent, parent_name, sizeof(parent_name)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + str_cpy(parent_path, sizeof(parent_path), ctx->path); + str_cat(parent_path, sizeof(parent_path), "/"); + str_cat(parent_path, sizeof(parent_path), parent_name); + + ctx_next.path = parent_path; + ctx_next.strategies = ctx->strategies; + + consumed = false; + + // Apply given strategies, one MUST consume + for (i = 0; i < ctx->strategies->num; i++) { + log_assert(ctx->strategies->entry[i].path); + + // path == "" matches everything + if (str_eq(ctx->strategies->entry[i].path, "") || + str_eq(ctx->strategies->entry[i].path, parent_path)) { + + result = ctx->strategies->entry[i].merge_strategy_do( + parent, + source, + &ctx_next, + &consumed, + _core_property_node_ext_merge_recursive_do); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + log_misc( + "Merge strategy for '%s' consumed: %d", + ctx->strategies->entry[i].path, + consumed); + + if (consumed) { + break; + } + } + } + + log_assert(consumed); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_ext_log_rec( + const core_property_node_t *parent_node, + const char *parent_path, + bt_core_log_message_t log_message) +{ + core_property_node_result_t result; + + char property_type[16]; + + char cur_path[CORE_PROPERTY_NODE_PATH_LEN_MAX]; + char cur_node_name[CORE_PROPERTY_NODE_NAME_SIZE_MAX]; + + core_property_node_t child_node; + core_property_node_t tmp; + + 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; + float value_float; + double value_double; + char value_bin[128]; + + // Carry on the full root path down the node tree + result = core_property_node_name_get(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); + + result = core_property_node_child_get(parent_node, &child_node); + + // parent node is a leaf node, print all data of it + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + result = core_property_node_attr_read(parent_node, "__type", property_type, sizeof(property_type)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // void type if doesn't have __type attribute + log_message(LOG_MODULE, "%s: ", cur_path); + } else if (str_eq(property_type, "s8")) { + result = core_property_node_s8_read(parent_node, &value_s8); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRId8, cur_path, value_s8); + } else if (str_eq(property_type, "s16")) { + result = core_property_node_s16_read(parent_node, &value_s16); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRId16, cur_path, value_s16); + } else if (str_eq(property_type, "s32")) { + result = core_property_node_s32_read(parent_node, &value_s32); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRId32, cur_path, value_s32); + } else if (str_eq(property_type, "s64")) { + result = core_property_node_s64_read(parent_node, &value_s64); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRId64, cur_path, value_s64); + } else if (str_eq(property_type, "u8")) { + result = core_property_node_u8_read(parent_node, &value_u8); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRIu8, cur_path, value_u8); + } else if (str_eq(property_type, "u16")) { + result = core_property_node_u16_read(parent_node, &value_u16); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRIu16, cur_path, value_u16); + } else if (str_eq(property_type, "u32")) { + result = core_property_node_u32_read(parent_node, &value_u32); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRIu32, cur_path, value_u32); + } else if (str_eq(property_type, "u64")) { + result = core_property_node_u64_read(parent_node, &value_u64); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %" PRIu64, cur_path, value_u64); + } else if (str_eq(property_type, "str")) { + result = core_property_node_str_read(parent_node, value_str, sizeof(value_str)); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %s", cur_path, value_str); + } else if (str_eq(property_type, "bool")) { + result = core_property_node_bool_read(parent_node, &value_bool); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %d", cur_path, value_bool); + } else if (str_eq(property_type, "float")) { + result = core_property_node_float_read(parent_node, &value_float); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %f", cur_path, value_float); + } else if (str_eq(property_type, "double")) { + result = core_property_node_double_read(parent_node, &value_double); + core_property_node_fatal_on_error(result); + + log_message(LOG_MODULE, "%s: %f", cur_path, value_double); + } else if (str_eq(property_type, "bin")) { + memset(value_bin, 0, sizeof(value_bin)); + result = core_property_node_bin_read(parent_node, value_bin, sizeof(value_bin)); + core_property_node_fatal_on_error(result); + + hex_encode_lc(value_bin, sizeof(value_bin), value_str, sizeof(value_str)); + + log_message(LOG_MODULE, "%s (truncated to 128 bytes): %s", cur_path, value_str); + } else { + log_fatal("%s: (%d)", cur_path, property_type); + } + + // TODO attribute traversal is missing here, needs an interface allowing arbitrary + // traversal on core_property_node + } else { + do { + result = _core_property_node_ext_log_rec(&child_node, cur_path, log_message); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + result = core_property_node_next_sibling_get(&child_node, &tmp); + memcpy(&child_node, &tmp, sizeof(core_property_node_t)); + + // No more siblings + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + break; + } + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + } while (true); + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +void core_property_node_ext_log( + const core_property_node_t *node, bt_core_log_message_t log_message) +{ + _core_property_node_ext_log_rec(node, "", log_message); +} + +core_property_node_result_t core_property_node_ext_u8_read( + const core_property_node_t *node, const char *name, uint8_t *value) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_search(node, name, &tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + return core_property_node_u8_read(&tmp, value); +} + +core_property_node_result_t core_property_node_ext_u16_read( + const core_property_node_t *node, const char *name, uint16_t *value) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_search(node, name, &tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + return core_property_node_u16_read(&tmp, value); +} + +core_property_node_result_t core_property_node_ext_u32_read( + const core_property_node_t *node, const char *name, uint32_t *value) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_search(node, name, &tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + return core_property_node_u32_read(&tmp, value); +} + +core_property_node_result_t core_property_node_ext_bool_read( + const core_property_node_t *node, const char *name, bool *value) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_search(node, name, &tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + return core_property_node_bool_read(&tmp, value); +} + +core_property_node_result_t core_property_node_ext_str_read( + const core_property_node_t *node, const char *name, char *value, size_t len) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + log_assert(len > 0); + + result = core_property_node_search(node, name, &tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + return core_property_node_str_read(&tmp, value, len); +} + +core_property_node_result_t core_property_node_ext_u8_read_or_default( + const core_property_node_t *node, + const char *name, + uint8_t *value, + uint8_t _default) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_ext_u8_read(node, name, value); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + *value = _default; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } else { + return result; + } +} + +core_property_node_result_t core_property_node_ext_u16_read_or_default( + const core_property_node_t *node, + const char *name, + uint16_t *value, + uint16_t _default) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_ext_u16_read(node, name, value); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + *value = _default; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } else { + return result; + } +} + +core_property_node_result_t core_property_node_ext_u32_read_or_default( + const core_property_node_t *node, + const char *name, + uint32_t *value, + uint32_t _default) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_ext_u32_read(node, name, value); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + *value = _default; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } else { + return result; + } +} + +core_property_node_result_t core_property_node_ext_bool_read_or_default( + const core_property_node_t *node, + const char *name, + bool *value, + bool _default) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + + result = core_property_node_ext_bool_read(node, name, value); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + *value = _default; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } else { + return result; + } +} + +core_property_node_result_t core_property_node_ext_str_read_or_default( + const core_property_node_t *node, + const char *name, + char *value, + size_t len, + const char *_default) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(value); + log_assert(len > 0); + log_assert(_default); + + result = core_property_node_ext_str_read(node, name, value, len); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + str_cpy(value, len, _default); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } else { + return result; + } +} + +core_property_node_result_t core_property_node_ext_u8_replace( + core_property_node_t *node, const char *name, uint8_t val) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + + result = core_property_node_search(node, name, &tmp); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + result = core_property_node_remove(&tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + } + + return core_property_node_u8_create(node, name, val, NULL); +} + +core_property_node_result_t core_property_node_ext_u16_replace( + core_property_node_t *node, const char *name, uint16_t val) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + + result = core_property_node_search(node, name, &tmp); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + result = core_property_node_remove(&tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + } + + return core_property_node_u16_create(node, name, val, NULL); +} + +core_property_node_result_t core_property_node_ext_u32_replace( + core_property_node_t *node, const char *name, uint32_t val) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + + result = core_property_node_search(node, name, &tmp); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + result = core_property_node_remove(&tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + } + + return core_property_node_u32_create(node, name, val, NULL); +} + +core_property_node_result_t core_property_node_ext_str_replace( + core_property_node_t *node, const char *name, const char *val) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + + result = core_property_node_search(node, name, &tmp); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + result = core_property_node_remove(&tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + } + + return core_property_node_str_create(node, name, val, NULL); +} + +core_property_node_result_t core_property_node_ext_bool_replace( + core_property_node_t *node, const char *name, bool val) +{ + core_property_node_t tmp; + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + + result = core_property_node_search(node, name, &tmp); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + result = core_property_node_remove(&tmp); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + } + + return core_property_node_bool_create(node, name, val, NULL); +} + +core_property_node_result_t core_property_node_ext_attr_replace( + core_property_node_t *node, const char *name, const char *val) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + log_assert(val); + + result = core_property_node_attr_remove(node, name); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + } + + return core_property_node_attr_create(node, name, val); +} + +core_property_node_result_t core_property_node_ext_extract( + const core_property_node_t *node, core_property_t **out_property) +{ + size_t size; + core_property_node_result_t result; + core_property_t *property; + core_property_result_t property_result; + + log_assert(node); + log_assert(out_property); + + result = core_property_node_size(node, &size); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + return result; + } + + property_result = core_property_create(size, &property); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + result = core_property_other_node_insert(property, node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + core_property_free(&property); + + return result; + } + + *out_property = property; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +core_property_node_result_t core_property_node_ext_merge_do( + const core_property_t *parent, + const core_property_t *source, + core_property_t **out_property) +{ + core_property_node_ext_merge_strategies_t strategies; + + log_assert(parent); + log_assert(source); + log_assert(out_property); + + strategies.num = 1; + + strategies.entry[0].path = ""; + strategies.entry[0].merge_strategy_do = + core_property_node_ext_merge_strategy_default_do; + + return core_property_node_ext_merge_with_strategies_do( + parent, source, &strategies, out_property); +} + +core_property_node_result_t core_property_node_ext_merge_with_strategies_do( + const core_property_t *parent, + const core_property_t *source, + const core_property_node_ext_merge_strategies_t *strategies, + core_property_t **merged) +{ + size_t size; + size_t total_size; + core_property_result_t property_result; + core_property_node_result_t property_node_result; + core_property_t *merged_property; + core_property_node_t parent_node; + core_property_node_t merged_node; + core_property_node_t source_node; + core_property_node_ext_merge_ctx_t ctx; + + log_assert(parent); + log_assert(source); + log_assert(strategies); + + // We can't estimate how these two are being merged as in how much new + // data is being inserted from source into parent. Therefore, worse-case + // estimate memory requirement for no overlap + total_size = 0; + + property_result = core_property_size(parent, &size); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + total_size += size; + + property_result = core_property_size(source, &size); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + total_size += size; + + property_result = core_property_create(total_size, &merged_property); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + property_result = core_property_root_node_get(parent, &parent_node); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + core_property_free(&merged_property); + + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + property_result = + core_property_other_node_insert(merged_property, &parent_node); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + core_property_free(&merged_property); + + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + property_result = + core_property_root_node_get(merged_property, &merged_node); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + core_property_free(&merged_property); + + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + property_result = core_property_root_node_get(source, &source_node); + + if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) { + core_property_free(&merged_property); + + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + ctx.path = ""; + ctx.strategies = strategies; + + property_node_result = _core_property_node_ext_merge_recursive_do( + &merged_node, &source_node, &ctx); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(property_node_result)) { + core_property_free(&merged_property); + } + + *merged = merged_property; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +core_property_node_result_t core_property_node_ext_merge_strategy_default_do( + core_property_node_t *parent, + const core_property_node_t *source, + void *ctx, + bool *consumed, + core_property_node_ext_merge_recursion_do_t node_merge_recursion_do) +{ + core_property_node_t tmp; + core_property_node_t source_child; + core_property_node_result_t result; + char source_child_name[CORE_PROPERTY_NODE_NAME_SIZE_MAX]; + core_property_node_t parent_child; + core_property_node_t source_child_child; + + log_assert(parent); + log_assert(source); + log_assert(consumed); + + result = core_property_node_child_get(source, &source_child); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + *consumed = true; + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } + + while (true) { + result = core_property_node_name_get( + &source_child, source_child_name, sizeof(source_child_name)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } + + result = + core_property_node_search(parent, source_child_name, &parent_child); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // Could not find an identical child on parent, copy entire source + // to parent + result = core_property_node_copy(parent, &source_child); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } + } else if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } else { + // Go deeper, more levels to traverse + result = core_property_node_child_get( + &source_child, &source_child_child); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // Found identical leaf node, remove the matching parent's child + // and copy the source child over to the parent and terminate + // the recursion + result = core_property_node_remove(&parent_child); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } + + result = core_property_node_copy(parent, &source_child); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } + } else if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } else { + // Continue recursion if there are actually more children + result = + node_merge_recursion_do(&parent_child, &source_child, ctx); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } + } + } + + // Iterate siblings on same level + result = core_property_node_next_sibling_get(&source_child, &tmp); + memcpy(&source_child, &tmp, sizeof(core_property_node_t)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + break; + } + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + *consumed = false; + return result; + } + } + + // Default strategy always consumes when successful + *consumed = true; + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} diff --git a/src/main/core/property-node-ext.h b/src/main/core/property-node-ext.h new file mode 100644 index 00000000..b9a0aa30 --- /dev/null +++ b/src/main/core/property-node-ext.h @@ -0,0 +1,113 @@ +#ifndef CORE_PROPERTY_NODE_EXT_H +#define CORE_PROPERTY_NODE_EXT_H + +#include +#include + +#include "core/property-node.h" + +#define CORE_PROPERTY_NODE_EXT_MAX_NODE_NAME_RESOLVERS 4 + +typedef core_property_node_result_t ( + *core_property_node_ext_merge_recursion_do_t)( + core_property_node_t *parent, + const core_property_node_t *source, + void *ctx); + +typedef core_property_node_result_t ( + *core_property_node_ext_merge_strategy_do_t)( + core_property_node_t *parent, + const core_property_node_t *source, + void *ctx, + bool *consumed, + core_property_node_ext_merge_recursion_do_t node_merge_recursion_do); + +typedef struct core_property_node_ext_merge_strategies { + struct { + const char *path; + core_property_node_ext_merge_strategy_do_t merge_strategy_do; + } entry[CORE_PROPERTY_NODE_EXT_MAX_NODE_NAME_RESOLVERS]; + uint8_t num; +} core_property_node_ext_merge_strategies_t; + +void core_property_node_ext_log( + const core_property_node_t *node, bt_core_log_message_t log_message); + +core_property_node_result_t core_property_node_ext_u8_read( + const core_property_node_t *node, const char *name, uint8_t *value); +core_property_node_result_t core_property_node_ext_u16_read( + const core_property_node_t *node, const char *name, uint16_t *value); +core_property_node_result_t core_property_node_ext_u32_read( + const core_property_node_t *node, const char *name, uint32_t *value); +core_property_node_result_t core_property_node_ext_bool_read( + const core_property_node_t *node, const char *name, bool *value); +core_property_node_result_t core_property_node_ext_str_read( + const core_property_node_t *node, + const char *name, + char *value, + size_t len); + +core_property_node_result_t core_property_node_ext_u8_read_or_default( + const core_property_node_t *node, + const char *name, + uint8_t *value, + uint8_t _default); +core_property_node_result_t core_property_node_ext_u16_read_or_default( + const core_property_node_t *node, + const char *name, + uint16_t *value, + uint16_t _default); +core_property_node_result_t core_property_node_ext_u32_read_or_default( + const core_property_node_t *node, + const char *name, + uint32_t *value, + uint32_t _default); +core_property_node_result_t core_property_node_ext_bool_read_or_default( + const core_property_node_t *node, + const char *name, + bool *value, + bool _default); +core_property_node_result_t core_property_node_ext_str_read_or_default( + const core_property_node_t *node, + const char *name, + char *value, + size_t len, + const char *_default); + +core_property_node_result_t core_property_node_ext_u8_replace( + core_property_node_t *node, const char *name, uint8_t val); +core_property_node_result_t core_property_node_ext_u16_replace( + core_property_node_t *node, const char *name, uint16_t val); +core_property_node_result_t core_property_node_ext_u32_replace( + core_property_node_t *node, const char *name, uint32_t val); +core_property_node_result_t core_property_node_ext_str_replace( + core_property_node_t *node, const char *name, const char *val); +core_property_node_result_t core_property_node_ext_bool_replace( + core_property_node_t *node, const char *name, bool val); +core_property_node_result_t core_property_node_ext_attr_replace( + core_property_node_t *node, const char *name, const char *val); + +core_property_node_result_t core_property_node_ext_extract( + const core_property_node_t *node, core_property_t **out_property); + +core_property_node_result_t core_property_node_ext_merge_do( + const core_property_t *parent, + const core_property_t *source, + core_property_t **out_property); +// Strategies are applied in order and first consumer terminates +// applying further strategies Typically, you want to include the default +// strategy after your custom strategies for special cases +core_property_node_result_t core_property_node_ext_merge_with_strategies_do( + const core_property_t *parent, + const core_property_t *source, + const core_property_node_ext_merge_strategies_t *strategies, + core_property_t **merged); + +core_property_node_result_t core_property_node_ext_merge_strategy_default_do( + core_property_node_t *parent, + const core_property_node_t *source, + void *ctx, + bool *consumed, + core_property_node_ext_merge_recursion_do_t node_merge_recursion_do); + +#endif \ No newline at end of file diff --git a/src/main/core/property-node-mxml.c b/src/main/core/property-node-mxml.c new file mode 100644 index 00000000..f2a25dad --- /dev/null +++ b/src/main/core/property-node-mxml.c @@ -0,0 +1,1086 @@ +#define LOG_MODULE "core-property-node-mxml" + +#include +#include +#include +#include + +#include + +#include "core/property-mxml-internal.h" + +#include "iface-core/log.h" + +#include "util/hex.h" +#include "util/mem.h" +#include "util/str.h" + +static core_property_node_result_t _core_property_node_mxml_node_type_create( + const core_property_node_t *parent_node_, + core_property_node_t *node_out_, + const char *key, + const char *type, + const char *format, + ...) +{ + core_property_mxml_internal_property_node_t *parent_node; + core_property_mxml_internal_property_node_t *node_out; + mxml_node_t *node_new; + mxml_node_t *tmp; + va_list args; + char buffer[16384]; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + node_out = (core_property_mxml_internal_property_node_t *) node_out_; + + node_new = mxmlNewElement(parent_node->node, key); + + if (node_new == NULL) { + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + + // No return value + mxmlElementSetAttr(node_new, "__type", type); + + va_start(args, format); + vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + + tmp = mxmlNewText(node_new, false, buffer); + + if (tmp == NULL) { + return CORE_PROPERTY_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(core_property_mxml_internal_property_node_t)); + + node_out->property = parent_node->property; + node_out->node = node_new; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_name_get( + const core_property_node_t *node_, char *name, size_t len) +{ + core_property_mxml_internal_property_node_t *node; + const char *elem_name; + + node = (core_property_mxml_internal_property_node_t *) node_; + + elem_name = mxmlGetElement(node->node); + + if (elem_name == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + str_cpy(name, len, elem_name); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t +_core_property_node_mxml_size(const core_property_node_t *node_, size_t *size) +{ + *size = CORE_PROPERTY_MXML_INTERNAL_FIXED_SIZE_DUMMY; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_search( + const core_property_node_t *node_, + const char *path, + core_property_node_t *node_out_) +{ + core_property_mxml_internal_property_node_t *node; + core_property_mxml_internal_property_node_t *node_out; + mxml_node_t *tmp; + + node = (core_property_mxml_internal_property_node_t *) node_; + node_out = (core_property_mxml_internal_property_node_t *) node_out_; + + memset(node_out, 0, sizeof(core_property_mxml_internal_property_node_t)); + + tmp = mxmlFindPath(node->node, path); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + node_out->property = node->property; + node_out->node = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_next_result_search( + const core_property_node_t *node_, core_property_node_t *node_out_) +{ + core_property_mxml_internal_property_node_t *node; + core_property_mxml_internal_property_node_t *node_out; + mxml_node_t *tmp; + const char *elem_name; + + node = (core_property_mxml_internal_property_node_t *) node_; + node_out = (core_property_mxml_internal_property_node_t *) node_out_; + + memset(node_out, 0, sizeof(core_property_mxml_internal_property_node_t)); + + elem_name = mxmlGetElement(node->node); + + if (elem_name == NULL) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + tmp = mxmlFindElement(node->node, node->node, elem_name, NULL, NULL, MXML_DESCEND_NONE); + + if (tmp == NULL) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + node_out->property = node->property; + node_out->node = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_child_get( + const core_property_node_t *node_, core_property_node_t *node_out_) +{ + core_property_mxml_internal_property_node_t *node; + core_property_mxml_internal_property_node_t *node_out; + mxml_node_t *tmp; + mxml_node_t *tree; + + node = (core_property_mxml_internal_property_node_t *) node_; + node_out = (core_property_mxml_internal_property_node_t *) node_out_; + + tree = node->node; + + tmp = mxmlFindElement(tree, tree, NULL, NULL, NULL, MXML_DESCEND_FIRST); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + memset(node_out, 0, sizeof(core_property_mxml_internal_property_node_t)); + + node_out->property = node->property; + node_out->node = tmp; + node_out->node_root_iter = tree; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_next_sibling_get( + const core_property_node_t *node_, core_property_node_t *node_out_) +{ + core_property_mxml_internal_property_node_t *node; + core_property_mxml_internal_property_node_t *node_out; + mxml_node_t *tmp; + + node = (core_property_mxml_internal_property_node_t *) node_; + node_out = (core_property_mxml_internal_property_node_t *) node_out_; + + log_assert(node->node_root_iter); + + tmp = mxmlFindElement(node->node, node->node_root_iter, NULL, NULL, NULL, MXML_DESCEND_NONE); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + memset(node_out, 0, sizeof(core_property_mxml_internal_property_node_t)); + + node_out->property = node->property; + node_out->node = tmp; + node_out->node_root_iter = node->node_root_iter; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_void_create( + const core_property_node_t *parent_node_, + const char *key, + core_property_node_t *node_out_) +{ + core_property_mxml_internal_property_node_t *parent_node; + core_property_mxml_internal_property_node_t *node_out; + mxml_node_t *tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + node_out = (core_property_mxml_internal_property_node_t *) node_out_; + + tmp = mxmlNewElement(parent_node->node, key); + + if (!tmp) { + return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL; + } + + if (node_out) { + memset(node_out, 0, sizeof(core_property_mxml_internal_property_node_t)); + + node_out->property = parent_node->property; + node_out->node = tmp; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_s8_create( + const core_property_node_t *parent_node_, + const char *key, + int8_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "s8", "%d", value); +} + +static core_property_node_result_t _core_property_node_mxml_u8_create( + const core_property_node_t *parent_node_, + const char *key, + uint8_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "u8", "%u", value); +} + +static core_property_node_result_t _core_property_node_mxml_s16_create( + const core_property_node_t *parent_node_, + const char *key, + int16_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "s16", "%d", value); +} + +static core_property_node_result_t _core_property_node_mxml_u16_create( + const core_property_node_t *parent_node_, + const char *key, + uint16_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "u16", "%u", value); +} + +static core_property_node_result_t _core_property_node_mxml_s32_create( + const core_property_node_t *parent_node_, + const char *key, + int32_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "s32", "%d", value); +} + +static core_property_node_result_t _core_property_node_mxml_u32_create( + const core_property_node_t *parent_node_, + const char *key, + uint32_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "u32", "%u", value); +} + +static core_property_node_result_t _core_property_node_mxml_s64_create( + const core_property_node_t *parent_node_, + const char *key, + int64_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "s64", "%lld", value); +} + +static core_property_node_result_t _core_property_node_mxml_u64_create( + const core_property_node_t *parent_node_, + const char *key, + uint64_t value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "u64", "%llu", value); +} + +static core_property_node_result_t _core_property_node_mxml_bin_create( + const core_property_node_t *parent_node_, + const char *key, + void *data, + size_t len, + core_property_node_t *node_out_) +{ + size_t size; + char *buffer; + core_property_node_result_t result; + + // Each byte needs 2 chars + null terminator at the end + size = len * 2 + 1; + buffer = xmalloc(size); + + hex_encode_uc(data, len, buffer, size); + + result = _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "bin", "%s", buffer); + + free(buffer); + + return result; +} + +static core_property_node_result_t _core_property_node_mxml_str_create( + const core_property_node_t *parent_node_, + const char *key, + const char *value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "str", "%s", value); +} + +static core_property_node_result_t _core_property_node_mxml_ipv4_create( + const core_property_node_t *parent_node_, + const char *key, + uint32_t value, + core_property_node_t *node_out_) +{ + char buffer[4 * 3 + 3 + 1]; + core_property_node_result_t result; + + str_format(buffer, sizeof(buffer), "%d.%d.%d.%d", + (value >> 24) & 0xFF, + (value >> 16) & 0xFF, + (value >> 8) & 0xFF, + value & 0xFF); + + result = _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "ip4", "%s", buffer); + + return result; +} + +static core_property_node_result_t _core_property_node_mxml_float_create( + const core_property_node_t *parent_node_, + const char *key, + float value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "float", "%f", value); +} + +static core_property_node_result_t _core_property_node_mxml_double_create( + const core_property_node_t *parent_node_, + const char *key, + double value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "double", "%f", value); +} + +static core_property_node_result_t _core_property_node_mxml_attr_create( + const core_property_node_t *parent_node_, + const char *key, + const char *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + // No return value + mxmlElementSetAttr(parent_node->node, key, value); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_bool_create( + const core_property_node_t *parent_node_, + const char *key, + bool value, + core_property_node_t *node_out_) +{ + return _core_property_node_mxml_node_type_create(parent_node_, node_out_, key, "bool", "%d", value ? "1" : "0"); +} + +static core_property_node_result_t _core_property_node_mxml_s8_read( + const core_property_node_t *parent_node_, int8_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "s8")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (tmp < INT8_MIN || tmp > INT8_MAX) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_u8_read( + const core_property_node_t *parent_node_, uint8_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "u8")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (tmp < 0 || tmp > UINT8_MAX) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_s16_read( + const core_property_node_t *parent_node_, int16_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "s16")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (tmp < INT16_MIN || tmp > INT16_MAX) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_u16_read( + const core_property_node_t *parent_node_, uint16_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "u16")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (tmp < 0 || tmp > UINT16_MAX) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_s32_read( + const core_property_node_t *parent_node_, int32_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "s32")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (tmp < INT32_MIN || tmp > INT32_MAX) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_u32_read( + const core_property_node_t *parent_node_, uint32_t *value) +{ +core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "u32")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (tmp < 0 || tmp > UINT32_MAX) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_s64_read( + const core_property_node_t *parent_node_, int64_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "s64")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_u64_read( + const core_property_node_t *parent_node_, uint64_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + uint64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "u64")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoull(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_bin_read( + const core_property_node_t *parent_node_, void *value, size_t len) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "bin")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (!hex_decode(value, len, text, strlen(text))) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_str_read( + const core_property_node_t *parent_node_, char *value, size_t len) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "str")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + str_cpy(value, len, text); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_ipv4_read( + const core_property_node_t *parent_node_, uint32_t *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + uint8_t *tmp; + int res; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "ip4")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = 0; + tmp = (uint8_t*) value; + + res = sscanf(text, "%u.%u.%u.%u", &tmp[3], &tmp[2], &tmp[1], &tmp[0]); + + if (res != 4) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_float_read( + const core_property_node_t *parent_node_, float *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + float tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "float")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtof(text, NULL); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_double_read( + const core_property_node_t *parent_node_, double *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + double tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "double")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtod(text, NULL); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_attr_read( + const core_property_node_t *parent_node_, const char *key, char *value, size_t len) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr = mxmlElementGetAttr(parent_node->node, key); + + if (attr == NULL) { + return CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND; + } + + str_cpy(value, len, attr); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_bool_read( + const core_property_node_t *parent_node_, bool *value) +{ + core_property_mxml_internal_property_node_t *parent_node; + const char *attr_type; + const char *text; + int64_t tmp; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + attr_type = mxmlElementGetAttr(parent_node->node, "__type"); + + if (attr_type == NULL) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE; + } + + if (!str_eq(attr_type, "bool")) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE; + } + + text = mxmlGetText(parent_node->node, NULL); + + if (!text) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + errno = 0; + + tmp = strtoll(text, NULL, 10); + + if (errno != 0) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + if (tmp != 0 && tmp != 1) { + return CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA; + } + + *value = tmp > 0; + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t +_core_property_node_mxml_remove(const core_property_node_t *node_) +{ + core_property_mxml_internal_property_node_t *node; + + node = (core_property_mxml_internal_property_node_t *) node_; + + mxmlDelete(node->node); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_attr_remove( + const core_property_node_t *parent_node_, const char *key) +{ + core_property_mxml_internal_property_node_t *parent_node; + + parent_node = (core_property_mxml_internal_property_node_t *) parent_node_; + + mxmlElementClearAttr(parent_node->node, key); + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +static core_property_node_result_t _core_property_node_mxml_copy( + core_property_node_t *dst_node_, const core_property_node_t *src_node_) +{ + core_property_mxml_internal_property_node_t *dst_node; + const core_property_mxml_internal_property_node_t *src_node; + + dst_node = (core_property_mxml_internal_property_node_t *) dst_node_; + src_node = (const core_property_mxml_internal_property_node_t *) src_node_; + + char *str_copy; + mxml_node_t *node_cloned; + + // Ensure actual cloning by storing and loading this + // Just "adding it" to the other tree with mxml creates a reference only + + str_copy = mxmlSaveAllocString(src_node->node, NULL); + + if (str_copy == NULL) { + return CORE_PROPERTY_RESULT_ERROR_READ; + } + + node_cloned = mxmlLoadString(NULL, NULL, str_copy); + + if (node_cloned == NULL) { + return CORE_PROPERTY_RESULT_ERROR_WRITE; + } + + mxmlAdd(dst_node->node, MXML_ADD_AFTER, NULL, node_cloned); + + return CORE_PROPERTY_RESULT_SUCCESS; +} + +void core_property_node_mxml_core_api_get(core_property_node_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.name_get = _core_property_node_mxml_name_get; + api->v1.size = _core_property_node_mxml_size; + api->v1.search = _core_property_node_mxml_search; + api->v1.next_result_search = _core_property_node_mxml_next_result_search; + api->v1.child_get = _core_property_node_mxml_child_get; + api->v1.next_sibling_get = _core_property_node_mxml_next_sibling_get; + api->v1.void_create = _core_property_node_mxml_void_create; + api->v1.s8_create = _core_property_node_mxml_s8_create; + api->v1.u8_create = _core_property_node_mxml_u8_create; + api->v1.s16_create = _core_property_node_mxml_s16_create; + api->v1.u16_create = _core_property_node_mxml_u16_create; + api->v1.s32_create = _core_property_node_mxml_s32_create; + api->v1.u32_create = _core_property_node_mxml_u32_create; + api->v1.s64_create = _core_property_node_mxml_s64_create; + api->v1.u64_create = _core_property_node_mxml_u64_create; + api->v1.bin_create = _core_property_node_mxml_bin_create; + api->v1.str_create = _core_property_node_mxml_str_create; + api->v1.ipv4_create = _core_property_node_mxml_ipv4_create; + api->v1.float_create = _core_property_node_mxml_float_create; + api->v1.double_create = _core_property_node_mxml_double_create; + api->v1.attr_create = _core_property_node_mxml_attr_create; + api->v1.bool_create = _core_property_node_mxml_bool_create; + api->v1.s8_read = _core_property_node_mxml_s8_read; + api->v1.u8_read = _core_property_node_mxml_u8_read; + api->v1.s16_read = _core_property_node_mxml_s16_read; + api->v1.u16_read = _core_property_node_mxml_u16_read; + api->v1.s32_read = _core_property_node_mxml_s32_read; + api->v1.u32_read = _core_property_node_mxml_u32_read; + api->v1.s64_read = _core_property_node_mxml_s64_read; + api->v1.u64_read = _core_property_node_mxml_u64_read; + api->v1.bin_read = _core_property_node_mxml_bin_read; + api->v1.str_read = _core_property_node_mxml_str_read; + api->v1.ipv4_read = _core_property_node_mxml_ipv4_read; + api->v1.float_read = _core_property_node_mxml_float_read; + api->v1.double_read = _core_property_node_mxml_double_read; + api->v1.attr_read = _core_property_node_mxml_attr_read; + api->v1.bool_read = _core_property_node_mxml_bool_read; + api->v1.remove = _core_property_node_mxml_remove; + api->v1.attr_remove = _core_property_node_mxml_attr_remove; + api->v1.copy = _core_property_node_mxml_copy; +} + +void core_property_node_mxml_core_api_set() +{ + core_property_node_api_t api; + + core_property_node_mxml_core_api_get(&api); + core_property_node_api_set(&api); +} diff --git a/src/main/core/property-node-mxml.h b/src/main/core/property-node-mxml.h new file mode 100644 index 00000000..c77fc63e --- /dev/null +++ b/src/main/core/property-node-mxml.h @@ -0,0 +1,10 @@ +#ifndef CORE_PROPERTY_NODE_MXML_H +#define CORE_PROPERTY_NODE_MXML_H + +#include "main/core/property-node.h" + +void core_property_node_mxml_core_api_get(core_property_node_api_t *api); + +void core_property_node_mxml_core_api_set(); + +#endif \ No newline at end of file diff --git a/src/main/core/property-node-trace.c b/src/main/core/property-node-trace.c new file mode 100644 index 00000000..11dc15c1 --- /dev/null +++ b/src/main/core/property-node-trace.c @@ -0,0 +1,865 @@ +#define LOG_MODULE "property-node-trace" + +#include + +#include "core/property-node.h" + +#include "iface-core/log.h" + +static core_property_node_api_t _core_property_node_trace_target_api; + +static core_property_node_result_t _core_property_node_trace_name_get( + const core_property_node_t *node, char *name, size_t len) +{ + core_property_node_result_t result; + + log_misc(">>> name_get(%p, %p, %d)", node, name, len); + + result = _core_property_node_trace_target_api.v1.name_get(node, name, len); + + log_misc( + "<<< name_get(%p, %s): %s", + node, + name, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t +_core_property_node_trace_size(const core_property_node_t *node, size_t *size) +{ + core_property_node_result_t result; + + log_misc(">>> size(%p)", node); + + result = _core_property_node_trace_target_api.v1.size(node, size); + + log_misc( + "<<< size(%p, %d): %s", + node, + *size, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_search( + const core_property_node_t *node, + const char *path, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc(">>> search(%p, %s, %p)", node, path, node_out); + + result = + _core_property_node_trace_target_api.v1.search(node, path, node_out); + + log_misc( + "<<< search(%p, %s): %s", + node, + path, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_next_result_search( + const core_property_node_t *node, core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc(">>> next_result_search(%p, %p)", node, node_out); + + result = _core_property_node_trace_target_api.v1.next_result_search( + node, node_out); + + log_misc( + "<<< next_result_search(%p): %s", + node, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_child_get( + const core_property_node_t *node, core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc(">>> child_get(%p, %p)", node, node_out); + + result = _core_property_node_trace_target_api.v1.child_get(node, node_out); + + log_misc( + "<<< child_get(%p): %s", + node, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_next_sibling_get( + const core_property_node_t *node, core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc(">>> next_sibling_get(%p, %p)", node, node_out); + + result = _core_property_node_trace_target_api.v1.next_sibling_get( + node, node_out); + + log_misc( + "<<< next_sibling_get(%p): %s", + node, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_void_create( + const core_property_node_t *parent_node, + const char *key, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc(">>> void_create(%p, %s, %p)", parent_node, key, node_out); + + result = _core_property_node_trace_target_api.v1.void_create( + parent_node, key, node_out); + + log_misc( + "<<< void_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s8_create( + const core_property_node_t *parent_node, + const char *key, + int8_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> s8_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.s8_create( + parent_node, key, value, node_out); + + log_misc( + "<<< s8_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u8_create( + const core_property_node_t *parent_node, + const char *key, + uint8_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> u8_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.u8_create( + parent_node, key, value, node_out); + + log_misc( + "<<< u8_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s16_create( + const core_property_node_t *parent_node, + const char *key, + int16_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> s16_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.s16_create( + parent_node, key, value, node_out); + + log_misc( + "<<< s16_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u16_create( + const core_property_node_t *parent_node, + const char *key, + uint16_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> u16_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.u16_create( + parent_node, key, value, node_out); + + log_misc( + "<<< u16_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s32_create( + const core_property_node_t *parent_node, + const char *key, + int32_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> s32_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.s32_create( + parent_node, key, value, node_out); + + log_misc( + "<<< s32_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u32_create( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> u32_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.u32_create( + parent_node, key, value, node_out); + + log_misc( + "<<< u32_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s64_create( + const core_property_node_t *parent_node, + const char *key, + int64_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> s64_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.s64_create( + parent_node, key, value, node_out); + + log_misc( + "<<< s64_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u64_create( + const core_property_node_t *parent_node, + const char *key, + uint64_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> u64_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.u64_create( + parent_node, key, value, node_out); + + log_misc( + "<<< u64_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_bin_create( + const core_property_node_t *parent_node, + const char *key, + void *data, + size_t len, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> bin_create(%p, %s, %p, %d, %p)", + parent_node, + key, + data, + len, + node_out); + + result = _core_property_node_trace_target_api.v1.bin_create( + parent_node, key, data, len, node_out); + + log_misc( + "<<< bin_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_str_create( + const core_property_node_t *parent_node, + const char *key, + const char *value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> str_create(%p, %s, %s, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.str_create( + parent_node, key, value, node_out); + + log_misc( + "<<< str_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_ipv4_create( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> ipv4_create(%p, %s, %X, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.ipv4_create( + parent_node, key, value, node_out); + + log_misc( + "<<< ipv4_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_float_create( + const core_property_node_t *parent_node, + const char *key, + float value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> float_create(%p, %s, %f, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.float_create( + parent_node, key, value, node_out); + + log_misc( + "<<< float_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_double_create( + const core_property_node_t *parent_node, + const char *key, + double value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> double_create(%p, %s, %f, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.double_create( + parent_node, key, value, node_out); + + log_misc( + "<<< double_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_attr_create( + const core_property_node_t *parent_node, + const char *key, + const char *value) +{ + core_property_node_result_t result; + + log_misc( + ">>> attr_create(%p, %s, %s, %p)", parent_node, key, value); + + result = _core_property_node_trace_target_api.v1.attr_create( + parent_node, key, value); + + log_misc( + "<<< attr_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_bool_create( + const core_property_node_t *parent_node, + const char *key, + bool value, + core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_misc( + ">>> bool_create(%p, %s, %d, %p)", parent_node, key, value, node_out); + + result = _core_property_node_trace_target_api.v1.bool_create( + parent_node, key, value, node_out); + + log_misc( + "<<< bool_create(%p, %s): %s", + parent_node, + key, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s8_read( + const core_property_node_t *parent_node, int8_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> s8_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.s8_read(parent_node, value); + + log_misc( + "<<< s8_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u8_read( + const core_property_node_t *parent_node, uint8_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> u8_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.u8_read(parent_node, value); + + log_misc( + "<<< u8_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s16_read( + const core_property_node_t *parent_node, int16_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> s16_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.s16_read(parent_node, value); + + log_misc( + "<<< s16_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u16_read( + const core_property_node_t *parent_node, uint16_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> u16_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.u16_read(parent_node, value); + + log_misc( + "<<< u16_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s32_read( + const core_property_node_t *parent_node, int32_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> s32_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.s32_read(parent_node, value); + + log_misc( + "<<< s32_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u32_read( + const core_property_node_t *parent_node, uint32_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> u32_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.u32_read(parent_node, value); + + log_misc( + "<<< u32_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_s64_read( + const core_property_node_t *parent_node, int64_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> s64_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.s64_read(parent_node, value); + + log_misc( + "<<< s64_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_u64_read( + const core_property_node_t *parent_node, uint64_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> u64_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.u64_read(parent_node, value); + + log_misc( + "<<< u64_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_bin_read( + const core_property_node_t *parent_node, void *value, size_t len) +{ + core_property_node_result_t result; + + log_misc(">>> bin_read(%p, %p, %d)", parent_node, value, len); + + result = _core_property_node_trace_target_api.v1.bin_read( + parent_node, value, len); + + log_misc( + "<<< bin_read(%p): %s", + parent_node, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_str_read( + const core_property_node_t *parent_node, char *value, size_t len) +{ + core_property_node_result_t result; + + log_misc(">>> str_read(%p, %p, %d)", parent_node, value, len); + + result = _core_property_node_trace_target_api.v1.str_read( + parent_node, value, len); + + log_misc( + "<<< str_read(%p, %s): %s", + parent_node, + value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_ipv4_read( + const core_property_node_t *parent_node, uint32_t *value) +{ + core_property_node_result_t result; + + log_misc(">>> ipv4_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.ipv4_read(parent_node, value); + + log_misc( + "<<< ipv4_read(%p, %X): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_float_read( + const core_property_node_t *parent_node, float *value) +{ + core_property_node_result_t result; + + log_misc(">>> float_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.float_read(parent_node, value); + + log_misc( + "<<< float_read(%p, %f): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_double_read( + const core_property_node_t *parent_node, double *value) +{ + core_property_node_result_t result; + + log_misc(">>> double_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.double_read(parent_node, value); + + log_misc( + "<<< double_read(%p, %f): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_attr_read( + const core_property_node_t *parent_node, const char *key, char *value, size_t len) +{ + core_property_node_result_t result; + + log_misc(">>> attr_read(%p, %s, %p, %d)", parent_node, key, value, len); + + result = _core_property_node_trace_target_api.v1.attr_read( + parent_node, key, value, len); + + log_misc( + "<<< attr_read(%p, %s): %s", + parent_node, + value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_bool_read( + const core_property_node_t *parent_node, bool *value) +{ + core_property_node_result_t result; + + log_misc(">>> bool_read(%p)", parent_node); + + result = + _core_property_node_trace_target_api.v1.bool_read(parent_node, value); + + log_misc( + "<<< bool_read(%p, %d): %s", + parent_node, + *value, + core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t +_core_property_node_trace_remove(const core_property_node_t *node) +{ + core_property_node_result_t result; + + log_misc(">>> remove(%p)", node); + + result = _core_property_node_trace_target_api.v1.remove(node); + + log_misc( + "<<< remove(%p): %s", node, core_property_node_result_to_str(result)); + + return result; +} + +static core_property_node_result_t _core_property_node_trace_copy( + core_property_node_t *dst_node, const core_property_node_t *src_node) +{ + core_property_node_result_t result; + + log_misc(">>> copy(%p, %p)", dst_node, src_node); + + result = _core_property_node_trace_target_api.v1.copy(dst_node, src_node); + + log_misc( + "<<< copy(%p, %p): %s", + dst_node, + src_node, + core_property_node_result_to_str(result)); + + return result; +} + +void core_property_node_trace_target_api_set( + const core_property_node_api_t *target_api) +{ + log_assert(target_api); + + memcpy( + &_core_property_node_trace_target_api, + target_api, + sizeof(core_property_node_api_t)); +} + +void core_property_node_trace_core_api_get(core_property_node_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.name_get = _core_property_node_trace_name_get; + api->v1.size = _core_property_node_trace_size; + api->v1.search = _core_property_node_trace_search; + api->v1.next_result_search = _core_property_node_trace_next_result_search; + api->v1.child_get = _core_property_node_trace_child_get; + api->v1.next_sibling_get = _core_property_node_trace_next_sibling_get; + api->v1.void_create = _core_property_node_trace_void_create; + api->v1.s8_create = _core_property_node_trace_s8_create; + api->v1.u8_create = _core_property_node_trace_u8_create; + api->v1.s16_create = _core_property_node_trace_s16_create; + api->v1.u16_create = _core_property_node_trace_u16_create; + api->v1.s32_create = _core_property_node_trace_s32_create; + api->v1.u32_create = _core_property_node_trace_u32_create; + api->v1.s64_create = _core_property_node_trace_s64_create; + api->v1.u64_create = _core_property_node_trace_u64_create; + api->v1.bin_create = _core_property_node_trace_bin_create; + api->v1.str_create = _core_property_node_trace_str_create; + api->v1.ipv4_create = _core_property_node_trace_ipv4_create; + api->v1.float_create = _core_property_node_trace_float_create; + api->v1.double_create = _core_property_node_trace_double_create; + api->v1.attr_create = _core_property_node_trace_attr_create; + api->v1.bool_create = _core_property_node_trace_bool_create; + api->v1.s8_read = _core_property_node_trace_s8_read; + api->v1.u8_read = _core_property_node_trace_u8_read; + api->v1.s16_read = _core_property_node_trace_s16_read; + api->v1.u16_read = _core_property_node_trace_u16_read; + api->v1.s32_read = _core_property_node_trace_s32_read; + api->v1.u32_read = _core_property_node_trace_u32_read; + api->v1.s64_read = _core_property_node_trace_s64_read; + api->v1.u64_read = _core_property_node_trace_u64_read; + api->v1.bin_read = _core_property_node_trace_bin_read; + api->v1.str_read = _core_property_node_trace_str_read; + api->v1.ipv4_read = _core_property_node_trace_ipv4_read; + api->v1.float_read = _core_property_node_trace_float_read; + api->v1.double_read = _core_property_node_trace_double_read; + api->v1.attr_read = _core_property_node_trace_attr_read; + api->v1.bool_read = _core_property_node_trace_bool_read; + api->v1.remove = _core_property_node_trace_remove; + api->v1.copy = _core_property_node_trace_copy; +} \ No newline at end of file diff --git a/src/main/core/property-node-trace.h b/src/main/core/property-node-trace.h new file mode 100644 index 00000000..d6a9f368 --- /dev/null +++ b/src/main/core/property-node-trace.h @@ -0,0 +1,11 @@ +#ifndef CORE_PROPERTY_NODE_TRACE_H +#define CORE_PROPERTY_NODE_TRACE_H + +#include "main/core/property-node.h" + +void core_property_node_trace_target_api_set( + const core_property_node_api_t *target_api); + +void core_property_node_trace_core_api_get(core_property_node_api_t *api); + +#endif diff --git a/src/main/core/property-node.c b/src/main/core/property-node.c new file mode 100644 index 00000000..d1d33ca5 --- /dev/null +++ b/src/main/core/property-node.c @@ -0,0 +1,598 @@ +#define LOG_MODULE "core-property-node" + +#include + +#include "iface-core/log.h" + +#include "main/core/property-node-trace.h" +#include "main/core/property-node.h" + +#define CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bool _core_property_node_trace_log_enable; +static core_property_node_api_t _core_property_node_api; + +static bool _core_property_node_api_is_valid() +{ + return _core_property_node_api.version > 0; +} + +void core_property_node_trace_log_enable(bool enable) +{ + _core_property_node_trace_log_enable = enable; +} + +void core_property_node_api_set(const core_property_node_api_t *api) +{ + core_property_node_api_t trace_api; + + log_assert(api); + + if (_core_property_node_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.name_get, name_get); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.size, size); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.search, search); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED( + api->v1.next_result_search, next_result_search); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.child_get, child_get); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED( + api->v1.next_sibling_get, next_sibling_get); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.void_create, void_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s8_create, s8_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u8_create, u8_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s16_create, s16_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u16_create, u16_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s32_create, s32_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u32_create, u32_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s64_create, s64_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u64_create, u64_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bin_create, bin_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.str_create, str_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.ipv4_create, ipv4_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED( + api->v1.float_create, float_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED( + api->v1.double_create, double_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.attr_create, attr_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bool_create, bool_create); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s8_read, s8_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u8_read, u8_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s16_read, s16_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u16_read, u16_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s32_read, s32_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u32_read, u32_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s64_read, s64_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u64_read, u64_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bin_read, bin_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.str_read, str_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.ipv4_read, ipv4_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.float_read, float_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.double_read, double_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.attr_read, attr_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bool_read, bool_read); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.remove, remove); + CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.copy, copy); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } + + if (_core_property_node_trace_log_enable) { + log_info("API trace log enabled"); + + core_property_node_trace_target_api_set(api); + core_property_node_trace_core_api_get(&trace_api); + + memcpy( + &_core_property_node_api, + &trace_api, + sizeof(core_property_node_api_t)); + } else { + memcpy(&_core_property_node_api, api, sizeof(core_property_node_api_t)); + } +} + +void core_property_node_api_get(core_property_node_api_t *api) +{ + log_assert(api); + log_assert(_core_property_node_api_is_valid()); + + memcpy(api, &_core_property_node_api, sizeof(core_property_node_api_t)); +} + +const char *core_property_node_result_to_str(core_property_node_result_t result) +{ + switch (result) { + case CORE_PROPERTY_NODE_RESULT_SUCCESS: + return "Success"; + case CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL: + return "Internal"; + case CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND: + return "Node not found"; + case CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE: + return "Invalid node type"; + case CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE: + return "Invalid node structure"; + case CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA: + return "Invalid node data"; + default: + return "Undefined error"; + } +} + +core_property_node_result_t core_property_node_name_get( + const core_property_node_t *node, char *name, size_t len) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(node); + log_assert(name); + log_assert(len > 0); + + return _core_property_node_api.v1.name_get(node, name, len); +} + +core_property_node_result_t +core_property_node_size(const core_property_node_t *node, size_t *size) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(node); + log_assert(size); + + return _core_property_node_api.v1.size(node, size); +} + +core_property_node_result_t core_property_node_search( + const core_property_node_t *node, + const char *path, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(node); + log_assert(path); + log_assert(node_out); + + return _core_property_node_api.v1.search(node, path, node_out); +} + +core_property_node_result_t core_property_node_next_result_search( + const core_property_node_t *node, core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(node); + log_assert(node_out); + + return _core_property_node_api.v1.next_result_search(node, node_out); +} + +core_property_node_result_t core_property_node_child_get( + const core_property_node_t *node, core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(node); + log_assert(node_out); + + return _core_property_node_api.v1.child_get(node, node_out); +} + +core_property_node_result_t core_property_node_next_sibling_get( + const core_property_node_t *node, core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(node); + log_assert(node_out); + + return _core_property_node_api.v1.next_sibling_get(node, node_out); +} + +core_property_node_result_t core_property_node_void_create( + const core_property_node_t *parent_node, + const char *key, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.void_create(parent_node, key, node_out); +} + +core_property_node_result_t core_property_node_s8_create( + const core_property_node_t *parent_node, + const char *key, + int8_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.s8_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_u8_create( + const core_property_node_t *parent_node, + const char *key, + uint8_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.u8_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_s16_create( + const core_property_node_t *parent_node, + const char *key, + int16_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.s16_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_u16_create( + const core_property_node_t *parent_node, + const char *key, + uint16_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.u16_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_s32_create( + const core_property_node_t *parent_node, + const char *key, + int32_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.s32_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_u32_create( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.u32_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_s64_create( + const core_property_node_t *parent_node, + const char *key, + int64_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.s64_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_u64_create( + const core_property_node_t *parent_node, + const char *key, + uint64_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.u64_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_bin_create( + const core_property_node_t *parent_node, + const char *key, + void *data, + size_t len, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + log_assert(data); + + return _core_property_node_api.v1.bin_create( + parent_node, key, data, len, node_out); +} + +core_property_node_result_t core_property_node_str_create( + const core_property_node_t *parent_node, + const char *key, + const char *value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + log_assert(value); + + return _core_property_node_api.v1.str_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_ipv4_create( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.ipv4_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_float_create( + const core_property_node_t *parent_node, + const char *key, + float value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.float_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_double_create( + const core_property_node_t *parent_node, + const char *key, + double value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.double_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_attr_create( + const core_property_node_t *parent_node, + const char *key, + const char *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + log_assert(value); + + return _core_property_node_api.v1.attr_create( + parent_node, key, value); +} + +core_property_node_result_t core_property_node_bool_create( + const core_property_node_t *parent_node, + const char *key, + bool value, + core_property_node_t *node_out) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.bool_create( + parent_node, key, value, node_out); +} + +core_property_node_result_t core_property_node_s8_read( + const core_property_node_t *parent_node, int8_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.s8_read(parent_node, value); +} + +core_property_node_result_t core_property_node_u8_read( + const core_property_node_t *parent_node, uint8_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.u8_read(parent_node, value); +} + +core_property_node_result_t core_property_node_s16_read( + const core_property_node_t *parent_node, int16_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.s16_read(parent_node, value); +} + +core_property_node_result_t core_property_node_u16_read( + const core_property_node_t *parent_node, uint16_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.u16_read(parent_node, value); +} + +core_property_node_result_t core_property_node_s32_read( + const core_property_node_t *parent_node, int32_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.s32_read(parent_node, value); +} + +core_property_node_result_t core_property_node_u32_read( + const core_property_node_t *parent_node, uint32_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.u32_read(parent_node, value); +} + +core_property_node_result_t core_property_node_s64_read( + const core_property_node_t *parent_node, int64_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.s64_read(parent_node, value); +} + +core_property_node_result_t core_property_node_u64_read( + const core_property_node_t *parent_node, uint64_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.u64_read(parent_node, value); +} + +core_property_node_result_t core_property_node_bin_read( + const core_property_node_t *parent_node, void *value, size_t len) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.bin_read(parent_node, value, len); +} + +core_property_node_result_t core_property_node_str_read( + const core_property_node_t *parent_node, char *value, size_t len) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.str_read(parent_node, value, len); +} + +core_property_node_result_t core_property_node_ipv4_read( + const core_property_node_t *parent_node, uint32_t *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.ipv4_read(parent_node, value); +} + +core_property_node_result_t core_property_node_float_read( + const core_property_node_t *parent_node, float *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.float_read(parent_node, value); +} + +core_property_node_result_t core_property_node_double_read( + const core_property_node_t *parent_node, double *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.double_read(parent_node, value); +} + +core_property_node_result_t core_property_node_attr_read( + const core_property_node_t *parent_node, const char *key, char *value, size_t len) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + log_assert(value); + + return _core_property_node_api.v1.attr_read(parent_node, key, value, len); +} + +core_property_node_result_t core_property_node_bool_read( + const core_property_node_t *parent_node, bool *value) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(value); + + return _core_property_node_api.v1.bool_read(parent_node, value); +} + +core_property_node_result_t +core_property_node_remove(const core_property_node_t *node) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(node); + + return _core_property_node_api.v1.remove(node); +} + +core_property_node_result_t core_property_node_attr_remove( + const core_property_node_t *parent_node, const char *key) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(parent_node); + log_assert(key); + + return _core_property_node_api.v1.attr_remove(parent_node, key); +} + +core_property_node_result_t core_property_node_copy( + core_property_node_t *dst_node, const core_property_node_t *src_node) +{ + log_assert(_core_property_node_api_is_valid()); + log_assert(dst_node); + log_assert(src_node); + + return _core_property_node_api.v1.copy(dst_node, src_node); +} diff --git a/src/main/core/property-node.h b/src/main/core/property-node.h new file mode 100644 index 00000000..cb1083e4 --- /dev/null +++ b/src/main/core/property-node.h @@ -0,0 +1,356 @@ +#ifndef CORE_PROPERTY_NODE_H +#define CORE_PROPERTY_NODE_H + +#include +#include +#include + +#include "api/core/log.h" + +#include "main/core/property.h" + +#define CORE_PROPERTY_NODE_RESULT_IS_ERROR(x) \ + (x != CORE_PROPERTY_NODE_RESULT_SUCCESS) +// Based on actual AVS impl max size +#define CORE_PROPERTY_NODE_NAME_SIZE_MAX 256 +// Guestimate, should be enough, I hope? +#define CORE_PROPERTY_NODE_ATTR_NAME_SIZE_MAX 128 +// Guestimate, should be long enough, I hope? +#define CORE_PROPERTY_NODE_PATH_LEN_MAX 4096 + +// Macro to allow inlining of the caller function and line numbers +// to make debugging easier +#define core_property_node_fatal_on_error(result) \ + if (result != CORE_PROPERTY_NODE_RESULT_SUCCESS) { \ + log_fatal( \ + "Operation on property-node failed: %s", \ + core_property_node_result_to_str(result)); \ + } \ + +typedef struct core_property_node core_property_node_t; + +typedef enum core_property_node_result { + CORE_PROPERTY_NODE_RESULT_SUCCESS = 0, + CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL = 1, + CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND = 2, + CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE = 3, + CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE = 4, + CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA = 5, +} core_property_node_result_t; + +typedef core_property_node_result_t (*core_property_node_name_get_t)( + const core_property_node_t *node, char *name, size_t len); +typedef core_property_node_result_t (*core_property_node_size_t)( + const core_property_node_t *node, size_t *size); +typedef core_property_node_result_t (*core_property_node_search_t)( + const core_property_node_t *node, + const char *path, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_next_result_search_t)( + const core_property_node_t *node, core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_child_get_t)( + const core_property_node_t *node, core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_next_sibling_get_t)( + const core_property_node_t *node, core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_void_create_t)( + const core_property_node_t *parent_node, + const char *key, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_s8_create_t)( + const core_property_node_t *parent_node, + const char *key, + int8_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_u8_create_t)( + const core_property_node_t *parent_node, + const char *key, + uint8_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_s16_create_t)( + const core_property_node_t *parent_node, + const char *key, + int16_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_u16_create_t)( + const core_property_node_t *parent_node, + const char *key, + uint16_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_s32_create_t)( + const core_property_node_t *parent_node, + const char *key, + int32_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_u32_create_t)( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_s64_create_t)( + const core_property_node_t *parent_node, + const char *key, + int64_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_u64_create_t)( + const core_property_node_t *parent_node, + const char *key, + uint64_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_bin_create_t)( + const core_property_node_t *parent_node, + const char *key, + void *data, + size_t len, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_str_create_t)( + const core_property_node_t *parent_node, + const char *key, + const char *value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_ipv4_create_t)( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_float_create_t)( + const core_property_node_t *parent_node, + const char *key, + float value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_double_create_t)( + const core_property_node_t *parent_node, + const char *key, + double value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_attr_create_t)( + const core_property_node_t *parent_node, + const char *key, + const char *value); +typedef core_property_node_result_t (*core_property_node_bool_create_t)( + const core_property_node_t *parent_node, + const char *key, + bool value, + core_property_node_t *node_out); +typedef core_property_node_result_t (*core_property_node_s8_read_t)( + const core_property_node_t *parent_node, int8_t *value); +typedef core_property_node_result_t (*core_property_node_u8_read_t)( + const core_property_node_t *parent_node, uint8_t *value); +typedef core_property_node_result_t (*core_property_node_s16_read_t)( + const core_property_node_t *parent_node, int16_t *value); +typedef core_property_node_result_t (*core_property_node_u16_read_t)( + const core_property_node_t *parent_node, uint16_t *value); +typedef core_property_node_result_t (*core_property_node_s32_read_t)( + const core_property_node_t *parent_node, int32_t *value); +typedef core_property_node_result_t (*core_property_node_u32_read_t)( + const core_property_node_t *parent_node, uint32_t *value); +typedef core_property_node_result_t (*core_property_node_s64_read_t)( + const core_property_node_t *parent_node, int64_t *value); +typedef core_property_node_result_t (*core_property_node_u64_read_t)( + const core_property_node_t *parent_node, uint64_t *value); +typedef core_property_node_result_t (*core_property_node_bin_read_t)( + const core_property_node_t *parent_node, void *value, size_t len); +typedef core_property_node_result_t (*core_property_node_str_read_t)( + const core_property_node_t *parent_node, char *value, size_t len); +typedef core_property_node_result_t (*core_property_node_ipv4_read_t)( + const core_property_node_t *parent_node, uint32_t *value); +typedef core_property_node_result_t (*core_property_node_float_read_t)( + const core_property_node_t *parent_node, float *value); +typedef core_property_node_result_t (*core_property_node_double_read_t)( + const core_property_node_t *parent_node, double *value); +typedef core_property_node_result_t (*core_property_node_attr_read_t)( + const core_property_node_t *parent_node, const char *key, char *value, size_t len); +typedef core_property_node_result_t (*core_property_node_bool_read_t)( + const core_property_node_t *parent_node, bool *value); +typedef core_property_node_result_t (*core_property_node_remove_t)( + const core_property_node_t *node); +typedef core_property_node_result_t (*core_property_node_attr_remove_t)( + const core_property_node_t *parent_node, const char *key); +typedef core_property_node_result_t (*core_property_node_copy_t)( + core_property_node_t *dst_node, const core_property_node_t *src_node); + +typedef struct core_property_node_api { + uint16_t version; + + struct { + core_property_node_name_get_t name_get; + core_property_node_size_t size; + core_property_node_search_t search; + core_property_node_next_result_search_t next_result_search; + core_property_node_child_get_t child_get; + core_property_node_next_sibling_get_t next_sibling_get; + core_property_node_void_create_t void_create; + core_property_node_s8_create_t s8_create; + core_property_node_u8_create_t u8_create; + core_property_node_s16_create_t s16_create; + core_property_node_u16_create_t u16_create; + core_property_node_s32_create_t s32_create; + core_property_node_u32_create_t u32_create; + core_property_node_s64_create_t s64_create; + core_property_node_u64_create_t u64_create; + core_property_node_bin_create_t bin_create; + core_property_node_str_create_t str_create; + core_property_node_ipv4_create_t ipv4_create; + core_property_node_float_create_t float_create; + core_property_node_double_create_t double_create; + core_property_node_attr_create_t attr_create; + core_property_node_bool_create_t bool_create; + core_property_node_s8_read_t s8_read; + core_property_node_u8_read_t u8_read; + core_property_node_s16_read_t s16_read; + core_property_node_u16_read_t u16_read; + core_property_node_s32_read_t s32_read; + core_property_node_u32_read_t u32_read; + core_property_node_s64_read_t s64_read; + core_property_node_u64_read_t u64_read; + core_property_node_bin_read_t bin_read; + core_property_node_str_read_t str_read; + core_property_node_ipv4_read_t ipv4_read; + core_property_node_float_read_t float_read; + core_property_node_double_read_t double_read; + core_property_node_attr_read_t attr_read; + core_property_node_bool_read_t bool_read; + core_property_node_remove_t remove; + core_property_node_attr_remove_t attr_remove; + core_property_node_copy_t copy; + } v1; +} core_property_node_api_t; + +void core_property_node_trace_log_enable(bool enable); +void core_property_node_api_set(const core_property_node_api_t *impl); +void core_property_node_api_get(core_property_node_api_t *impl); + +const char * +core_property_node_result_to_str(core_property_node_result_t result); + +core_property_node_result_t core_property_node_name_get( + const core_property_node_t *node, char *name, size_t len); +core_property_node_result_t +core_property_node_size(const core_property_node_t *node, size_t *size); +core_property_node_result_t core_property_node_search( + const core_property_node_t *node, + const char *path, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_next_result_search( + const core_property_node_t *node, core_property_node_t *node_out); +core_property_node_result_t core_property_node_child_get( + const core_property_node_t *node, core_property_node_t *node_out); +core_property_node_result_t core_property_node_next_sibling_get( + const core_property_node_t *node, core_property_node_t *node_out); +// Doc remark: node_out is optional here +core_property_node_result_t core_property_node_void_create( + const core_property_node_t *parent_node, + const char *key, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_s8_create( + const core_property_node_t *parent_node, + const char *key, + int8_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_u8_create( + const core_property_node_t *parent_node, + const char *key, + uint8_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_s16_create( + const core_property_node_t *parent_node, + const char *key, + int16_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_u16_create( + const core_property_node_t *parent_node, + const char *key, + uint16_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_s32_create( + const core_property_node_t *parent_node, + const char *key, + int32_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_u32_create( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_s64_create( + const core_property_node_t *parent_node, + const char *key, + int64_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_u64_create( + const core_property_node_t *parent_node, + const char *key, + uint64_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_bin_create( + const core_property_node_t *parent_node, + const char *key, + void *data, + size_t len, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_str_create( + const core_property_node_t *parent_node, + const char *key, + const char *value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_ipv4_create( + const core_property_node_t *parent_node, + const char *key, + uint32_t value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_float_create( + const core_property_node_t *parent_node, + const char *key, + float value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_double_create( + const core_property_node_t *parent_node, + const char *key, + double value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_attr_create( + const core_property_node_t *parent_node, + const char *key, + const char *value); +core_property_node_result_t core_property_node_bool_create( + const core_property_node_t *parent_node, + const char *key, + bool value, + core_property_node_t *node_out); +core_property_node_result_t core_property_node_s8_read( + const core_property_node_t *parent_node, int8_t *value); +core_property_node_result_t core_property_node_u8_read( + const core_property_node_t *parent_node, uint8_t *value); +core_property_node_result_t core_property_node_s16_read( + const core_property_node_t *parent_node, int16_t *value); +core_property_node_result_t core_property_node_u16_read( + const core_property_node_t *parent_node, uint16_t *value); +core_property_node_result_t core_property_node_s32_read( + const core_property_node_t *parent_node, int32_t *value); +core_property_node_result_t core_property_node_u32_read( + const core_property_node_t *parent_node, uint32_t *value); +core_property_node_result_t core_property_node_s64_read( + const core_property_node_t *parent_node, int64_t *value); +core_property_node_result_t core_property_node_u64_read( + const core_property_node_t *parent_node, uint64_t *value); +core_property_node_result_t core_property_node_bin_read( + const core_property_node_t *parent_node, void *value, size_t len); +core_property_node_result_t core_property_node_str_read( + const core_property_node_t *parent_node, char *value, size_t len); +core_property_node_result_t core_property_node_ipv4_read( + const core_property_node_t *parent_node, uint32_t *value); +core_property_node_result_t core_property_node_float_read( + const core_property_node_t *parent_node, float *value); +core_property_node_result_t core_property_node_double_read( + const core_property_node_t *parent_node, double *value); +core_property_node_result_t core_property_node_attr_read( + const core_property_node_t *parent_node, const char *key, char *value, size_t len); +core_property_node_result_t core_property_node_bool_read( + const core_property_node_t *parent_node, bool *value); +core_property_node_result_t +core_property_node_remove(const core_property_node_t *node); +core_property_node_result_t core_property_node_attr_remove( + const core_property_node_t *parent_node, const char *key); +core_property_node_result_t core_property_node_copy( + core_property_node_t *dst_node, const core_property_node_t *src_node); + +#endif \ No newline at end of file diff --git a/src/main/core/property-trace.c b/src/main/core/property-trace.c new file mode 100644 index 00000000..fd403c5c --- /dev/null +++ b/src/main/core/property-trace.c @@ -0,0 +1,172 @@ +#define LOG_MODULE "property-trace" + +#include + +#include "core/property.h" + +#include "iface-core/log.h" + +static core_property_api_t _core_property_trace_target_api; + +static core_property_result_t +_core_property_trace_create(size_t size, core_property_t **property) +{ + core_property_result_t result; + + log_misc(">>> create(%d)", size); + + result = _core_property_trace_target_api.v1.create(size, property); + + log_misc( + "<<< create(%d, %p): %s", + size, + *property, + core_property_result_to_str(result)); + + return result; +} + +static core_property_result_t +_core_property_trace_file_load(const char *path, core_property_t **property) +{ + core_property_result_t result; + + log_misc(">>> file_load(%s)", path); + + result = _core_property_trace_target_api.v1.file_load(path, property); + + log_misc( + "<<< file_load(%s, %p): %s", + path, + *property, + core_property_result_to_str(result)); + + return result; +} + +static core_property_result_t +_core_property_trace_str_load(const char *str, core_property_t **property) +{ + core_property_result_t result; + + log_misc(">>> str_load(%p)", str); + + result = _core_property_trace_target_api.v1.str_load(str, property); + + log_misc( + "<<< str_load(%p, %p): %s", + str, + *property, + core_property_result_to_str(result)); + + return result; +} + +static core_property_result_t +_core_property_trace_size(const core_property_t *property, size_t *size) +{ + core_property_result_t result; + + log_misc(">>> size(%p)", property); + + result = _core_property_trace_target_api.v1.size(property, size); + + log_misc( + "<<< size(%p, %d): %s", + property, + *size, + core_property_result_to_str(result)); + + return result; +} + +static core_property_result_t _core_property_trace_clone( + const core_property_t *property, core_property_t **property_cloned) +{ + core_property_result_t result; + + log_misc(">>> clone(%p)", property); + + result = + _core_property_trace_target_api.v1.clone(property, property_cloned); + + log_misc( + "<<< clone(%p, %p): %s", + property, + *property_cloned, + core_property_result_to_str(result)); + + return result; +} + +static core_property_result_t _core_property_trace_root_node_get( + const core_property_t *property, core_property_node_t *node) +{ + core_property_result_t result; + + log_misc(">>> root_node_get(%p)", property); + + result = _core_property_trace_target_api.v1.root_node_get(property, node); + + log_misc( + "<<< root_node_get(%p, %p): %s", + property, + node, + core_property_result_to_str(result)); + + return result; +} + +static core_property_result_t _core_property_trace_other_node_insert( + core_property_t *property, const core_property_node_t *node) +{ + core_property_result_t result; + + log_misc(">>> other_node_insert(%p, %p)", property, node); + + result = + _core_property_trace_target_api.v1.other_node_insert(property, node); + + log_misc( + "<<< other_node_insert(%p, %p): %s", + property, + node, + core_property_result_to_str(result)); + + return result; +} + +static void _core_property_trace_free(core_property_t **property) +{ + log_misc(">>> free(%p)", *property); + + _core_property_trace_target_api.v1.free(property); + + log_misc("<<< free(%p)", *property); +} + +void core_property_trace_target_api_set(const core_property_api_t *target_api) +{ + log_assert(target_api); + + memcpy( + &_core_property_trace_target_api, + target_api, + sizeof(core_property_api_t)); +} + +void core_property_trace_core_api_get(core_property_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.create = _core_property_trace_create; + api->v1.file_load = _core_property_trace_file_load; + api->v1.str_load = _core_property_trace_str_load; + api->v1.size = _core_property_trace_size; + api->v1.clone = _core_property_trace_clone; + api->v1.root_node_get = _core_property_trace_root_node_get; + api->v1.other_node_insert = _core_property_trace_other_node_insert; + api->v1.free = _core_property_trace_free; +} \ No newline at end of file diff --git a/src/main/core/property-trace.h b/src/main/core/property-trace.h new file mode 100644 index 00000000..3ce2bfb6 --- /dev/null +++ b/src/main/core/property-trace.h @@ -0,0 +1,10 @@ +#ifndef CORE_PROPERTY_TRACE_H +#define CORE_PROPERTY_TRACE_H + +#include "main/core/property.h" + +void core_property_trace_target_api_set(const core_property_api_t *target_api); + +void core_property_trace_core_api_get(core_property_api_t *api); + +#endif diff --git a/src/main/core/property.c b/src/main/core/property.c new file mode 100644 index 00000000..58649493 --- /dev/null +++ b/src/main/core/property.c @@ -0,0 +1,174 @@ +#define LOG_MODULE "core-property" + +#include + +#include "core/property-trace.h" +#include "core/property.h" + +#include "iface-core/log.h" + +#include "util/defs.h" + +#define CORE_PROPERTY_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bool _core_property_trace_log_enable; +static core_property_api_t _core_property_api; + +static bool _core_property_api_is_valid() +{ + return _core_property_api.version > 0; +} + +void core_property_trace_log_enable(bool enable) +{ + _core_property_trace_log_enable = enable; +} + +void core_property_api_set(const core_property_api_t *api) +{ + core_property_api_t trace_api; + + log_assert(api); + + if (_core_property_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.create, create); + CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.file_load, file_load); + CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.str_load, str_load); + CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.size, size); + CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.clone, clone); + CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.root_node_get, root_node_get); + CORE_PROPERTY_ASSERT_IMPLEMENTED( + api->v1.other_node_insert, other_node_insert); + CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.free, free); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } + + if (_core_property_trace_log_enable) { + log_info("API trace log enabled"); + + core_property_trace_target_api_set(api); + core_property_trace_core_api_get(&trace_api); + + memcpy(&_core_property_api, &trace_api, sizeof(core_property_api_t)); + } else { + memcpy(&_core_property_api, api, sizeof(core_property_api_t)); + } +} + +void core_property_api_get(core_property_api_t *api) +{ + log_assert(api); + log_assert(_core_property_api_is_valid()); + + memcpy(api, &_core_property_api, sizeof(core_property_api_t)); +} + +const char *core_property_result_to_str(core_property_result_t result) +{ + switch (result) { + case CORE_PROPERTY_RESULT_SUCCESS: + return "Success"; + case CORE_PROPERTY_RESULT_ERROR_INTERNAL: + return "Internal"; + case CORE_PROPERTY_RESULT_ERROR_ALLOC: + return "Allocating memory"; + case CORE_PROPERTY_RESULT_NOT_FOUND: + return "File or path not found"; + case CORE_PROPERTY_RESULT_ERROR_PERMISSIONS: + return "Permissions"; + case CORE_PROPERTY_RESULT_ERROR_READ: + return "Read error"; + case CORE_PROPERTY_RESULT_ERROR_WRITE: + return "Write error"; + default: + return "Undefined error"; + } +} + +core_property_result_t +core_property_create(size_t size, core_property_t **property) +{ + log_assert(_core_property_api_is_valid()); + log_assert(size > 0); + log_assert(property); + + return _core_property_api.v1.create(size, property); +} + +core_property_result_t +core_property_file_load(const char *path, core_property_t **property) +{ + log_assert(_core_property_api_is_valid()); + log_assert(path); + log_assert(property); + + return _core_property_api.v1.file_load(path, property); +} + +core_property_result_t +core_property_str_load(const char *str, core_property_t **property) +{ + log_assert(_core_property_api_is_valid()); + log_assert(str); + log_assert(property); + + return _core_property_api.v1.str_load(str, property); +} + +core_property_result_t +core_property_size(const core_property_t *property, size_t *size) +{ + log_assert(_core_property_api_is_valid()); + log_assert(property); + log_assert(size); + + return _core_property_api.v1.size(property, size); +} + +core_property_result_t core_property_clone( + const core_property_t *property, core_property_t **property_cloned) +{ + log_assert(_core_property_api_is_valid()); + log_assert(property); + log_assert(property_cloned); + + return _core_property_api.v1.clone(property, property_cloned); +} + +core_property_result_t core_property_root_node_get( + const core_property_t *property, core_property_node_t *node) +{ + log_assert(_core_property_api_is_valid()); + log_assert(property); + log_assert(node); + + return _core_property_api.v1.root_node_get(property, node); +} + +core_property_result_t core_property_other_node_insert( + core_property_t *property, const core_property_node_t *node) +{ + log_assert(_core_property_api_is_valid()); + log_assert(property); + log_assert(node); + + return _core_property_api.v1.other_node_insert(property, node); +} + +void core_property_free(core_property_t **property) +{ + log_assert(_core_property_api_is_valid()); + log_assert(property); + + _core_property_api.v1.free(property); +} diff --git a/src/main/core/property.h b/src/main/core/property.h new file mode 100644 index 00000000..b8361baa --- /dev/null +++ b/src/main/core/property.h @@ -0,0 +1,95 @@ +#ifndef CORE_PROPERTY_H +#define CORE_PROPERTY_H + +#include +#include +#include + +#define CORE_PROPERTY_RESULT_IS_ERROR(x) \ + (x != CORE_PROPERTY_RESULT_SUCCESS) + +// Macro to allow inlining of the caller function and line numbers +// to make debugging easier +#define core_property_fatal_on_error(result) \ + if (result != CORE_PROPERTY_RESULT_SUCCESS) { \ + log_fatal( \ + "Operation on property failed: %s", \ + core_property_result_to_str(result)); \ + } \ + +typedef struct core_property { + // Have size known, but not contents, to allow for stack allocations + void *v1; +} core_property_t; + +typedef struct core_property_node { + // Have size known, but not contents, to allow for stack allocations + void *v1; + void *v2; + void *v3; +} core_property_node_t; + +typedef enum core_property_result { + CORE_PROPERTY_RESULT_SUCCESS = 0, + CORE_PROPERTY_RESULT_ERROR_INTERNAL = 1, + CORE_PROPERTY_RESULT_ERROR_ALLOC = 2, + CORE_PROPERTY_RESULT_NOT_FOUND = 3, + CORE_PROPERTY_RESULT_ERROR_PERMISSIONS = 4, + CORE_PROPERTY_RESULT_ERROR_READ = 5, + CORE_PROPERTY_RESULT_ERROR_WRITE = 6, +} core_property_result_t; + +typedef core_property_result_t (*core_property_create_t)( + size_t size, core_property_t **result); +typedef core_property_result_t (*core_property_file_load_t)( + const char *path, core_property_t **result); +typedef core_property_result_t (*core_property_str_load_t)( + const char *str, core_property_t **result); +typedef core_property_result_t (*core_property_size_t)( + const core_property_t *property, size_t *size); +typedef core_property_result_t (*core_property_clone_t)( + const core_property_t *property, core_property_t **result); +typedef core_property_result_t (*core_property_root_node_get_t)( + const core_property_t *property, core_property_node_t *result); +typedef core_property_result_t (*core_property_other_node_insert_t)( + core_property_t *property, const core_property_node_t *node); +typedef void (*core_property_free_t)(core_property_t **property); + +typedef struct core_property_api { + uint16_t version; + + struct { + core_property_create_t create; + core_property_file_load_t file_load; + core_property_str_load_t str_load; + core_property_size_t size; + core_property_clone_t clone; + core_property_root_node_get_t root_node_get; + core_property_other_node_insert_t other_node_insert; + core_property_free_t free; + } v1; +} core_property_api_t; + +void core_property_trace_log_enable(bool enable); +void core_property_api_set(const core_property_api_t *api); +void core_property_api_get(core_property_api_t *api); + +const char *core_property_result_to_str(core_property_result_t result); + +core_property_result_t +core_property_create(size_t size, core_property_t **property); +core_property_result_t +core_property_file_load(const char *path, core_property_t **property); +core_property_result_t +core_property_str_load(const char *str, core_property_t **property); +core_property_result_t +core_property_size(const core_property_t *property, size_t *size); +core_property_result_t core_property_clone( + const core_property_t *property, core_property_t **property_cloned); +core_property_result_t core_property_root_node_get( + const core_property_t *property, core_property_node_t *node); +core_property_result_t core_property_other_node_insert( + core_property_t *property, const core_property_node_t *node); +void core_property_free(core_property_t **property); + +#endif \ No newline at end of file diff --git a/src/main/core/thread-crt.c b/src/main/core/thread-crt.c new file mode 100644 index 00000000..fc3196f8 --- /dev/null +++ b/src/main/core/thread-crt.c @@ -0,0 +1,97 @@ +#include +#include + +#include +#include + +#include "api/core/thread.h" + +#include "core/thread-crt.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "util/defs.h" + +struct core_thread_crt_shim_ctx { + HANDLE barrier; + int (*proc)(void *); + void *ctx; +}; + +static unsigned int STDCALL _core_thread_crt_thread_shim(void *outer_ctx) +{ + struct core_thread_crt_shim_ctx *sctx; + int (*proc)(void *); + void *inner_ctx; + + sctx = outer_ctx; + + proc = sctx->proc; + inner_ctx = sctx->ctx; + + SetEvent(sctx->barrier); + + return proc(inner_ctx); +} + +static bt_core_thread_result_t _core_thread_crt_create( + int (*proc)(void *), + void *ctx, + uint32_t stack_sz, + unsigned int priority, + bt_core_thread_id_t *thread_id) +{ + struct core_thread_crt_shim_ctx sctx; + + sctx.barrier = CreateEvent(NULL, TRUE, FALSE, NULL); + sctx.proc = proc; + sctx.ctx = ctx; + + *thread_id = _beginthreadex( + NULL, stack_sz, _core_thread_crt_thread_shim, &sctx, 0, NULL); + + WaitForSingleObject(sctx.barrier, INFINITE); + CloseHandle(sctx.barrier); + + return BT_CORE_THREAD_RESULT_SUCCESS; +} + +static bt_core_thread_result_t +_core_thread_crt_join(bt_core_thread_id_t thread_id, int *result) +{ + WaitForSingleObject((HANDLE) (uintptr_t) thread_id, INFINITE); + + if (result) { + GetExitCodeThread((HANDLE) (uintptr_t) thread_id, (DWORD *) result); + } + + return BT_CORE_THREAD_RESULT_SUCCESS; +} + +static bt_core_thread_result_t +_core_thread_crt_destroy(bt_core_thread_id_t thread_id) +{ + CloseHandle((HANDLE) (uintptr_t) thread_id); + + return BT_CORE_THREAD_RESULT_SUCCESS; +} + +static void _core_thread_crt_core_api_get(bt_core_thread_api_t *api) +{ + log_assert(api); + + api->version = 1; + + api->v1.create = _core_thread_crt_create; + api->v1.join = _core_thread_crt_join; + api->v1.destroy = _core_thread_crt_destroy; +} + +void core_thread_crt_core_api_set() +{ + bt_core_thread_api_t api; + + _core_thread_crt_core_api_get(&api); + bt_core_thread_api_set(&api); +} \ No newline at end of file diff --git a/src/main/core/thread-crt.h b/src/main/core/thread-crt.h new file mode 100644 index 00000000..32499401 --- /dev/null +++ b/src/main/core/thread-crt.h @@ -0,0 +1,8 @@ +#ifndef CORE_THREAD_CRT_H +#define CORE_THREAD_CRT_H + +#include "api/core/thread.h" + +void core_thread_crt_core_api_set(); + +#endif diff --git a/src/main/d3d9-util/dxerr.c b/src/main/d3d9-util/dxerr.c index fed1c624..301bf2ae 100644 --- a/src/main/d3d9-util/dxerr.c +++ b/src/main/d3d9-util/dxerr.c @@ -18,10 +18,7 @@ #ifndef DXERROR #define DXERROR(v, n, d) {v, TEXT(n), TEXT(d)}, -#define DXERRORLAST(v, n, d) \ - { \ - v, TEXT(n), TEXT(d) \ - } +#define DXERRORLAST(v, n, d) {v, TEXT(n), TEXT(d)} #endif #ifndef DXERROR8 #define DXERROR8(v, n, d) diff --git a/src/main/d3d9-util/dxerr9.c b/src/main/d3d9-util/dxerr9.c index 391c9f30..f27e0053 100644 --- a/src/main/d3d9-util/dxerr9.c +++ b/src/main/d3d9-util/dxerr9.c @@ -16,8 +16,5 @@ #define DXGetErrorDescription DXGetErrorDescription9A #define DXTrace DXTraceA #define DXERROR9(v, n, d) {v, n, d}, -#define DXERROR9LAST(v, n, d) \ - { \ - v, n, d \ - } +#define DXERROR9LAST(v, n, d) {v, n, d} #include "dxerr.c" diff --git a/src/main/d3d9exhook/config-gfx.c b/src/main/d3d9exhook/config-gfx.c index 6cf57af0..b051eb5d 100644 --- a/src/main/d3d9exhook/config-gfx.c +++ b/src/main/d3d9exhook/config-gfx.c @@ -2,268 +2,25 @@ #include -#include "cconfig/cconfig-util.h" - #include "d3d9exhook/config-gfx.h" -#include "util/log.h" - -#define D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY "gfx.framed" -#define D3D9EXHOOK_CONFIG_GFX_WINDOWED_KEY "gfx.windowed" -#define D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY "gfx.confined" -#define D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY "gfx.window_width" -#define D3D9EXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY "gfx.window_height" -#define D3D9EXHOOK_CONFIG_GFX_WINDOW_X_KEY "gfx.window_x" -#define D3D9EXHOOK_CONFIG_GFX_WINDOW_Y_KEY "gfx.window_y" -#define D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate" -#define D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY "gfx.device_adapter" -#define D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY "gfx.force_orientation" -#define D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY \ - "gfx.force_screen_res.width" -#define D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY \ - "gfx.force_screen_res.height" - -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE false -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_X_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_Y_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE -1 -#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE -1 - -void d3d9exhook_config_gfx_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE, - "Run the game in a framed window (requires windowed option)"); - - cconfig_util_set_bool( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOWED_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE, - "Run the game windowed"); - - cconfig_util_set_bool( - config, - D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE, - "Confine mouse cursor to window"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE, - "Windowed width, -1 for default size"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE, - "Windowed height, -1 for default size"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_X_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_X_VALUE, - "Windowed X, -1 for default X position"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_Y_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_Y_VALUE, - "Windowed Y, -1 for default Y position"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE, - "Forced refresh rate, -1 to not force any (try 59 or 60 if monitor " - "check fails to lock on high refresh rate monitors)"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE, - "D3D9ex device adapter (monitor), -1 to use default, " - "0, 1, 2 etc. to use specified adapter"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE, - "Orientation to force monitor into, -1 to use default, " - "0, 1, 2, 3 to do 0, 90, 180, 270 degrees"); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE, - "Force a screen resolution (width), -1 to disable. Use this if the " - "game does not auto " - "detect your monitor's resolution properly, e.g. 1368x768 instead of " - "1280x720."); - - cconfig_util_set_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE, - "Force a screen resolution (height), -1 to disable. Use this if the " - "game does not auto " - "detect your monitor's resolution properly, e.g. 1368x768 instead of " - "1280x720."); -} +#include "iface-core/log.h" void d3d9exhook_config_gfx_get( - struct d3d9exhook_config_gfx *config_gfx, struct cconfig *config) + const bt_core_config_t *config, + d3d9exhook_config_gfx_t *config_gfx) { - if (!cconfig_util_get_bool( - config, - D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY, - &config_gfx->framed, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE); - } - - if (!cconfig_util_get_bool( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOWED_KEY, - &config_gfx->windowed, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_WINDOWED_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE); - } - - if (!cconfig_util_get_bool( - config, - D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY, - &config_gfx->confined, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY, - &config_gfx->window_width, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY, - &config_gfx->window_height, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_X_KEY, - &config_gfx->window_x, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_X_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_WINDOW_X_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_X_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_WINDOW_Y_KEY, - &config_gfx->window_y, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_Y_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_WINDOW_Y_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_Y_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY, - &config_gfx->forced_refresh_rate, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY, - &config_gfx->device_adapter, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY, - &config_gfx->force_orientation, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY, - &config_gfx->force_screen_res.width, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE); - } - - if (!cconfig_util_get_int( - config, - D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY, - &config_gfx->force_screen_res.height, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY, - D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE); - } -} + bt_core_config_s32_get(config, "gfx/device/adapter", &config_gfx->device_adapter); + bt_core_config_s32_get(config, "gfx/device/forced_refresh_rate", &config_gfx->forced_refresh_rate); + bt_core_config_s32_get(config, "gfx/device/force_orientation", &config_gfx->force_orientation); + bt_core_config_s32_get(config, "gfx/device/force_screen_res/width", &config_gfx->force_screen_res.width); + bt_core_config_s32_get(config, "gfx/device/force_screen_res/height", &config_gfx->force_screen_res.height); + + bt_core_config_bool_get(config, "gfx/window/windowed", &config_gfx->windowed); + bt_core_config_bool_get(config, "gfx/window/framed", &config_gfx->framed); + bt_core_config_bool_get(config, "gfx/window/confined", &config_gfx->confined); + bt_core_config_s32_get(config, "gfx/window/width", &config_gfx->window_width); + bt_core_config_s32_get(config, "gfx/window/height", &config_gfx->window_height); + bt_core_config_s32_get(config, "gfx/window/x", &config_gfx->window_x); + bt_core_config_s32_get(config, "gfx/window/y", &config_gfx->window_y); +} \ No newline at end of file diff --git a/src/main/d3d9exhook/config-gfx.h b/src/main/d3d9exhook/config-gfx.h index e976079d..5e063557 100644 --- a/src/main/d3d9exhook/config-gfx.h +++ b/src/main/d3d9exhook/config-gfx.h @@ -1,7 +1,7 @@ #ifndef D3D9EXHOOK_CONFIG_GFX_H #define D3D9EXHOOK_CONFIG_GFX_H -#include "cconfig/cconfig.h" +#include "iface-core/config.h" /** * Config struct for d3d9exhook @@ -9,7 +9,7 @@ * Note: forced_refresh_rate sets the monitor's refresh rate * (it does not limit FPS or anything) */ -struct d3d9exhook_config_gfx { +typedef struct d3d9exhook_config_gfx { bool framed; bool windowed; bool confined; @@ -25,17 +25,10 @@ struct d3d9exhook_config_gfx { int32_t width; int32_t height; } force_screen_res; -}; +} d3d9exhook_config_gfx_t; -/** - * Add the gfx config set to the cconfig object - */ -void d3d9exhook_config_gfx_init(struct cconfig *config); - -/** - * Fill the actual config_gfx from the given config - */ void d3d9exhook_config_gfx_get( - struct d3d9exhook_config_gfx *config_gfx, struct cconfig *config); + const bt_core_config_t *config, + d3d9exhook_config_gfx_t *config_gfx); #endif diff --git a/src/main/d3d9exhook/d3d9ex.c b/src/main/d3d9exhook/d3d9ex.c index 88d95b00..dc5ba3a4 100644 --- a/src/main/d3d9exhook/d3d9ex.c +++ b/src/main/d3d9exhook/d3d9ex.c @@ -9,13 +9,14 @@ #include #include +#include "d3d9exhook/d3d9ex.h" + #include "hook/com-proxy.h" #include "hook/table.h" -#include "d3d9exhook/d3d9ex.h" +#include "iface-core/log.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #include "util/time.h" diff --git a/src/main/ddrhook-util/_com4.c b/src/main/ddrhook-util/_com4.c index 44e01784..a616effc 100644 --- a/src/main/ddrhook-util/_com4.c +++ b/src/main/ddrhook-util/_com4.c @@ -17,17 +17,17 @@ #include "acioemu/hdxs.h" #include "acioemu/icca.h" -#include "bemanitools/ddrio.h" - #include "ddrhook-util/_com4.h" #include "hook/iohook.h" +#include "iface-core/log.h" +#include "iface-io/ddr.h" + #include "p3ioemu/uart.h" #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" static struct ac_io_emu com4_ac_io_emu; static struct ac_io_emu_hdxs com4_hdxs; @@ -59,20 +59,24 @@ lights_dispatcher(struct ac_io_emu_hdxs *emu, const struct ac_io_message *req) const struct ac_io_hdxs_output *output = &req->cmd.hdxs_output; uint32_t lights = 0; - lights |= - check_panel_light(output, AC_IO_HDXS_OUT_P1_START, LIGHT_HD_P1_START); lights |= check_panel_light( - output, AC_IO_HDXS_OUT_P1_UP_DOWN, LIGHT_HD_P1_UP_DOWN); + output, AC_IO_HDXS_OUT_P1_START, BT_IO_DDR_HDXS_LIGHT_HD_P1_START); + lights |= check_panel_light( + output, AC_IO_HDXS_OUT_P1_UP_DOWN, BT_IO_DDR_HDXS_LIGHT_HD_P1_UP_DOWN); + lights |= check_panel_light( + output, + AC_IO_HDXS_OUT_P1_LEFT_RIGHT, + BT_IO_DDR_HDXS_LIGHT_HD_P1_LEFT_RIGHT); lights |= check_panel_light( - output, AC_IO_HDXS_OUT_P1_LEFT_RIGHT, LIGHT_HD_P1_LEFT_RIGHT); - lights |= - check_panel_light(output, AC_IO_HDXS_OUT_P2_START, LIGHT_HD_P2_START); + output, AC_IO_HDXS_OUT_P2_START, BT_IO_DDR_HDXS_LIGHT_HD_P2_START); lights |= check_panel_light( - output, AC_IO_HDXS_OUT_P2_UP_DOWN, LIGHT_HD_P2_UP_DOWN); + output, AC_IO_HDXS_OUT_P2_UP_DOWN, BT_IO_DDR_HDXS_LIGHT_HD_P2_UP_DOWN); lights |= check_panel_light( - output, AC_IO_HDXS_OUT_P2_LEFT_RIGHT, LIGHT_HD_P2_LEFT_RIGHT); + output, + AC_IO_HDXS_OUT_P2_LEFT_RIGHT, + BT_IO_DDR_HDXS_LIGHT_HD_P2_LEFT_RIGHT); - ddr_io_set_lights_hdxs_panel(lights); + bt_io_ddr_hdxs_lights_panel_set(lights); for (uint8_t i = 0; i < 4; ++i) { size_t light_idx = i * 3; @@ -85,7 +89,7 @@ lights_dispatcher(struct ac_io_emu_hdxs *emu, const struct ac_io_message *req) uint8_t b = upscale_light(output->lights[light_idx + AC_IO_HDXS_BLUE].analog); - ddr_io_set_lights_hdxs_rgb(i, r, g, b); + bt_io_ddr_hdxs_lights_rgb_set(i, r, g, b); } } diff --git a/src/main/ddrhook-util/dinput.c b/src/main/ddrhook-util/dinput.c index b0fdc663..08ce0265 100644 --- a/src/main/ddrhook-util/dinput.c +++ b/src/main/ddrhook-util/dinput.c @@ -9,8 +9,9 @@ #include "hook/pe.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" static HRESULT STDCALL my_DirectInput8Create( HINSTANCE hinst, diff --git a/src/main/ddrhook-util/extio.c b/src/main/ddrhook-util/extio.c index cd2dc84b..46afd1b4 100644 --- a/src/main/ddrhook-util/extio.c +++ b/src/main/ddrhook-util/extio.c @@ -12,12 +12,12 @@ #include #include -#include "bemanitools/ddrio.h" - #include "hook/iohook.h" +#include "iface-core/log.h" +#include "iface-io/ddr.h" + #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static HRESULT extio_open(struct irp *irp); @@ -108,7 +108,7 @@ static HRESULT extio_write(struct irp *irp) if (irp->write.nbytes >= sizeof(lights)) { lights_be = (const uint32_t *) irp->write.bytes; lights = _byteswap_ulong(*lights_be); - ddr_io_set_lights_extio(lights); + bt_io_ddr_extio_lights_set(lights); extio_pending = true; } else { diff --git a/src/main/ddrhook-util/gfx.c b/src/main/ddrhook-util/gfx.c index 3f5f7736..d88523c6 100644 --- a/src/main/ddrhook-util/gfx.c +++ b/src/main/ddrhook-util/gfx.c @@ -14,10 +14,11 @@ #include "hook/com-proxy.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "ddrhook-util/gfx.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #include "util/time.h" diff --git a/src/main/ddrhook-util/misc.c b/src/main/ddrhook-util/misc.c index b74c8de6..edf600c0 100644 --- a/src/main/ddrhook-util/misc.c +++ b/src/main/ddrhook-util/misc.c @@ -7,8 +7,9 @@ #include "hook/pe.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/str.h" static LRESULT(STDCALL *real_SendMessageW)( diff --git a/src/main/ddrhook-util/monitor.c b/src/main/ddrhook-util/monitor.c index 0dfce07f..a68b67ce 100644 --- a/src/main/ddrhook-util/monitor.c +++ b/src/main/ddrhook-util/monitor.c @@ -11,8 +11,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/str.h" /* Link pointers */ diff --git a/src/main/ddrhook-util/p3io.c b/src/main/ddrhook-util/p3io.c index 09b8c6f5..2fc92c14 100644 --- a/src/main/ddrhook-util/p3io.c +++ b/src/main/ddrhook-util/p3io.c @@ -3,15 +3,14 @@ #include #include -#include "bemanitools/ddrio.h" - #include "ddrhook-util/p3io.h" +#include "iface-core/log.h" +#include "iface-io/ddr.h" + #include "p3ioemu/emu.h" #include "p3ioemu/uart.h" -#include "util/log.h" - extern bool _15khz; extern bool standard_def; @@ -91,14 +90,14 @@ static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state) { log_assert(state != NULL); - *state = ddr_io_read_pad(); + *state = bt_io_ddr_pad_read(); return S_OK; } static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs) { - ddr_io_set_lights_p3io(outputs); + bt_io_ddr_p3io_lights_set(outputs); return S_OK; } diff --git a/src/main/ddrhook-util/spike.c b/src/main/ddrhook-util/spike.c index 0e383d20..b8178935 100644 --- a/src/main/ddrhook-util/spike.c +++ b/src/main/ddrhook-util/spike.c @@ -17,8 +17,9 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu spike_ac_io_emu; diff --git a/src/main/ddrhook-util/usbmem.c b/src/main/ddrhook-util/usbmem.c index f85363f3..08132c5d 100644 --- a/src/main/ddrhook-util/usbmem.c +++ b/src/main/ddrhook-util/usbmem.c @@ -9,15 +9,17 @@ // clang-format on #include +#include #include #include #include "hook/iohook.h" +#include "iface-core/log.h" + #include "util/crc.h" #include "util/fs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" #define USBMEM_DEVICE_COUNT 2 diff --git a/src/main/ddrhook1/Module.mk b/src/main/ddrhook1/Module.mk index 83782ae8..194075f5 100644 --- a/src/main/ddrhook1/Module.mk +++ b/src/main/ddrhook1/Module.mk @@ -2,29 +2,38 @@ avsdlls += ddrhook1 ldflags_ddrhook1 := \ -lws2_32 \ + -lshlwapi \ deplibs_ddrhook1 := \ avs \ +avslibs_ddrhook1 := \ + avs-ext \ + libs_ddrhook1 := \ + sdk-hook \ + core \ acioemu \ - cconfig \ ddrhook-util \ p3ioemu \ p3io \ hook \ hooklib \ util \ - eamio \ - ddrio \ security \ + iface \ + iface-core \ + iface-io \ + module \ + mxml \ src_ddrhook1 := \ avs-boot.c \ + ddrhook1.c \ dllmain.c \ config-ddrhook1.c \ config-eamuse.c \ config-gfx.c \ config-security.c \ - master.c \ filesystem.c \ + master.c \ diff --git a/src/main/ddrhook1/avs-boot.c b/src/main/ddrhook1/avs-boot.c index 1b7ad41a..69668561 100644 --- a/src/main/ddrhook1/avs-boot.c +++ b/src/main/ddrhook1/avs-boot.c @@ -5,15 +5,18 @@ #include #include +#include "core/log-bt.h" + #include "hook/iohook.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "ddrhook1/avs-boot.h" #include "ddrhook1/filesystem.h" -#include "util/log.h" #include "util/str.h" static void (*real_avs_boot)( @@ -50,6 +53,11 @@ static const struct hook_symbol ddrhook1_avs_ea3_hook_syms[] = { .link = (void **) &real_ea3_boot}, }; +static AVS_LOG_WRITER(_avs_boot_log_writer, chars, nchars, ctx) +{ + core_log_bt_direct_sink_write(chars, nchars); +} + static void avs_boot_replace_property_str( struct property_node *node, const char *name, const char *val) { @@ -115,7 +123,7 @@ static void my_avs_boot( sz_std_heap, avs_heap, sz_avs_heap, - log_writer_debug, + _avs_boot_log_writer, NULL); } diff --git a/src/main/ddrhook1/config-ddrhook1.c b/src/main/ddrhook1/config-ddrhook1.c index 154f3ae3..64a9649f 100644 --- a/src/main/ddrhook1/config-ddrhook1.c +++ b/src/main/ddrhook1/config-ddrhook1.c @@ -1,129 +1,17 @@ #include -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "ddrhook1/config-ddrhook1.h" -#include "util/log.h" - -#define DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY "ddrhook1.use_com4_emu" -#define DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY "ddrhook1.standard_def" -#define DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY "ddrhook1.use_15khz" -#define DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED "ddrhook1.usbmem_enabled" -#define DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1 "ddrhook1.usbmem_path_p1" -#define DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2 "ddrhook1.usbmem_path_p2" - -#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE true -#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE false -#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE false -#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED false -#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1 "usbmem_p1" -#define DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2 "usbmem_p2" - -void ddrhook1_config_ddrhook1_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE, - "Don't emulate P3IO COM4 and its downstream devices, use the Windows " - "COM4 port instead"); - cconfig_util_set_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE, - "SD cabinet mode"); - cconfig_util_set_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE, - "Use 15 kHz monitor mode"); - cconfig_util_set_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED, - "Enable USB memory data emulation"); - cconfig_util_set_str( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1, - "Specify path for P1 USB memory data"); - cconfig_util_set_str( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2, - "Specify path for P2 USB memory data"); -} - void ddrhook1_config_ddrhook1_get( - struct ddrhook1_config_ddrhook1 *config_ddrhook1, struct cconfig *config) + const bt_core_config_t *config, + ddrhook1_config_ddrhook1_t *config_ddrhook1) { - if (!cconfig_util_get_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY, - &config_ddrhook1->use_com4_emu, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - DDRHOOK1_CONFIG_DDRHOOK1_USE_COM4_EMU_KEY, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_COM4_EMU_VALUE); - } - if (!cconfig_util_get_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY, - &config_ddrhook1->standard_def, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - DDRHOOK1_CONFIG_DDRHOOK1_STANDARD_DEF_KEY, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_STANDARD_DEF_VALUE); - } - if (!cconfig_util_get_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY, - &config_ddrhook1->use_15khz, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - DDRHOOK1_CONFIG_DDRHOOK1_USE_15KHZ_KEY, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USE_15KHZ_VALUE); - } - if (!cconfig_util_get_bool( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED, - &config_ddrhook1->usbmem_enabled, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_ENABLED, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_ENABLED); - } - if (!cconfig_util_get_str( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1, - config_ddrhook1->usbmem_path_p1, - sizeof(config_ddrhook1->usbmem_path_p1) - 1, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P1, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P1); - } - if (!cconfig_util_get_str( - config, - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2, - config_ddrhook1->usbmem_path_p2, - sizeof(config_ddrhook1->usbmem_path_p2) - 1, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - DDRHOOK1_CONFIG_DDRHOOK1_USBMEM_PATH_P2, - DDRHOOK1_CONFIG_DDRHOOK1_DEFAULT_USBMEM_PATH_P2); - } + bt_core_config_ext_bool_get(config, "game/use_com4_emu", &config_ddrhook1->use_com4_emu); + bt_core_config_ext_bool_get(config, "game/standard_def", &config_ddrhook1->standard_def); + bt_core_config_ext_bool_get(config, "game/use_15khz", &config_ddrhook1->use_15khz); + bt_core_config_ext_bool_get(config, "game/usbmem/enabled", &config_ddrhook1->usbmem_enabled); + bt_core_config_ext_str_get(config, "game/usbmem/path_p1", config_ddrhook1->usbmem_path_p1, sizeof(config_ddrhook1->usbmem_path_p1)); + bt_core_config_ext_str_get(config, "game/usbmem/path_p2", config_ddrhook1->usbmem_path_p2, sizeof(config_ddrhook1->usbmem_path_p2)); } diff --git a/src/main/ddrhook1/config-ddrhook1.h b/src/main/ddrhook1/config-ddrhook1.h index fd590938..204c0a02 100644 --- a/src/main/ddrhook1/config-ddrhook1.h +++ b/src/main/ddrhook1/config-ddrhook1.h @@ -3,35 +3,21 @@ #include -#include "cconfig/cconfig.h" +#include -/** - * Struct holding configuration values for game-specific items. - */ -struct ddrhook1_config_ddrhook1 { +#include "api/core/config.h" + +typedef struct ddrhook1_config_ddrhook1 { bool use_com4_emu; bool standard_def; bool use_15khz; bool usbmem_enabled; char usbmem_path_p1[MAX_PATH]; char usbmem_path_p2[MAX_PATH]; -}; - -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void ddrhook1_config_ddrhook1_init(struct cconfig *config); +} ddrhook1_config_ddrhook1_t; -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_ddrhook1 Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void ddrhook1_config_ddrhook1_get( - struct ddrhook1_config_ddrhook1 *config_ddrhook1, struct cconfig *config); + const bt_core_config_t *config, + ddrhook1_config_ddrhook1_t *config_ddrhook1); #endif diff --git a/src/main/ddrhook1/config-eamuse.c b/src/main/ddrhook1/config-eamuse.c index 260791d3..74057c41 100644 --- a/src/main/ddrhook1/config-eamuse.c +++ b/src/main/ddrhook1/config-eamuse.c @@ -1,144 +1,13 @@ #include - -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "ddrhook1/config-eamuse.h" -#include "util/log.h" -#include "util/net.h" - -#define DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY "eamuse.server" -#define DDRHOOK1_CONFIG_EAMUSE_PCBID_KEY "eamuse.pcbid" -#define DDRHOOK1_CONFIG_EAMUSE_EAMID_KEY "eamuse.eamid" - -#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE "localhost:80" -#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE security_id_default -#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN \ - sizeof(security_id_default) -#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE security_id_default -#define DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN \ - sizeof(security_id_default) - -const struct net_addr ddrhook1_eamuse_default_server = { - .type = NET_ADDR_TYPE_HOSTNAME, - .hostname.host = "localhost", - .hostname.port = 80, -}; - -void ddrhook1_config_eamuse_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY, - DDRHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE, - "URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 " - "(e.g. 127.0.0.1:80) of the target eamuse server. The port is " - "optional " - "but defaults to 80."); - - cconfig_util_set_data( - config, - DDRHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, - DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - "PCBID"); - - cconfig_util_set_data( - config, - DDRHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, - DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - "EAMID"); -} - void ddrhook1_config_eamuse_get( - struct ddrhook1_config_eamuse *config_eamuse, struct cconfig *config) + const bt_core_config_t *config, + ddrhook1_config_eamuse_t *config_eamuse) { - char server_url[1024]; - char *tmp; - char *tmp2; - - memset(config_eamuse, 0, sizeof(struct ddrhook1_config_eamuse)); - - if (!cconfig_util_get_str( - config, - DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY, - server_url, - sizeof(server_url), - DDRHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - DDRHOOK1_CONFIG_EAMUSE_SERVER_KEY, - DDRHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE); - } - - if (!net_str_parse(server_url, &config_eamuse->server)) { - memcpy( - &config_eamuse->server, - &ddrhook1_eamuse_default_server, - sizeof(config_eamuse->server)); - tmp = net_addr_to_str(&config_eamuse->server); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!cconfig_util_get_data( - config, - DDRHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &config_eamuse->pcbid, - DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - (uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE)) { - tmp = security_id_to_str( - &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } - - if (!cconfig_util_get_data( - config, - DDRHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &config_eamuse->eamid, - DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - (uint8_t *) &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE)) { - tmp = security_id_to_str( - &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } + bt_core_config_ext_net_addr_get(config, "eamuse/server", &config_eamuse->server); + bt_core_config_ext_security_id_get(config, "eamuse/pcbid", &config_eamuse->pcbid); + bt_core_config_ext_security_id_get(config, "eamuse/eamid", &config_eamuse->eamid); } diff --git a/src/main/ddrhook1/config-eamuse.h b/src/main/ddrhook1/config-eamuse.h index c61ca5ae..91ff27c8 100644 --- a/src/main/ddrhook1/config-eamuse.h +++ b/src/main/ddrhook1/config-eamuse.h @@ -1,36 +1,20 @@ #ifndef DDRHOOK1_CONFIG_EAMUSE_H #define DDRHOOK1_CONFIG_EAMUSE_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/id.h" #include "util/net.h" -/** - * Struct holding configuration values for eamuse related items. - */ -struct ddrhook1_config_eamuse { +typedef struct ddrhook1_config_eamuse { struct net_addr server; struct security_id pcbid; struct security_id eamid; -}; +} ddrhook1_config_eamuse_t; -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void ddrhook1_config_eamuse_init(struct cconfig *config); - -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_eamuse Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void ddrhook1_config_eamuse_get( - struct ddrhook1_config_eamuse *config_eamuse, struct cconfig *config); + const bt_core_config_t *config, + ddrhook1_config_eamuse_t *config_eamuse); #endif \ No newline at end of file diff --git a/src/main/ddrhook1/config-gfx.c b/src/main/ddrhook1/config-gfx.c index 09ccc0c6..2d87baa1 100644 --- a/src/main/ddrhook1/config-gfx.c +++ b/src/main/ddrhook1/config-gfx.c @@ -1,36 +1,12 @@ #include -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "ddrhook1/config-gfx.h" -#include "util/log.h" - -#define DDRHOOK1_CONFIG_GFX_WINDOWED_KEY "gfx.windowed" - -#define DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE true - -void ddrhook1_config_gfx_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - DDRHOOK1_CONFIG_GFX_WINDOWED_KEY, - DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE, - "Run the game windowed"); -} - void ddrhook1_config_gfx_get( - struct ddrhook1_config_gfx *config_gfx, struct cconfig *config) + const bt_core_config_t *config, + ddrhook1_config_gfx_t *config_gfx) { - if (!cconfig_util_get_bool( - config, - DDRHOOK1_CONFIG_GFX_WINDOWED_KEY, - &config_gfx->windowed, - DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - DDRHOOK1_CONFIG_GFX_WINDOWED_KEY, - DDRHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE); - } + bt_core_config_ext_bool_get(config, "gfx/windowed", &config_gfx->windowed); } diff --git a/src/main/ddrhook1/config-gfx.h b/src/main/ddrhook1/config-gfx.h index 5281b7c6..97fc6b4e 100644 --- a/src/main/ddrhook1/config-gfx.h +++ b/src/main/ddrhook1/config-gfx.h @@ -1,30 +1,16 @@ #ifndef DDRHOOK1_CONFIG_GFX_H #define DDRHOOK1_CONFIG_GFX_H -#include "cconfig/cconfig.h" +#include -/** - * Struct holding configuration values for GFX related items. - */ -struct ddrhook1_config_gfx { - bool windowed; -}; +#include "api/core/config.h" -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void ddrhook1_config_gfx_init(struct cconfig *config); +typedef struct ddrhook1_config_gfx { + bool windowed; +} ddrhook1_config_gfx_t; -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_gfx Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void ddrhook1_config_gfx_get( - struct ddrhook1_config_gfx *config_gfx, struct cconfig *config); + const bt_core_config_t *config, + ddrhook1_config_gfx_t *config_gfx); #endif diff --git a/src/main/ddrhook1/config-security.c b/src/main/ddrhook1/config-security.c index 9489b0a6..4f3d2ffd 100644 --- a/src/main/ddrhook1/config-security.c +++ b/src/main/ddrhook1/config-security.c @@ -1,74 +1,10 @@ -#include - -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "ddrhook1/config-security.h" -#include "security/mcode.h" - -#include "util/log.h" -#include "util/net.h" - -#define DDRHOOK1_CONFIG_SECURITY_MCODE_KEY "security.mcode" - -static const struct security_mcode security_mcode_ddr_x = { - .header = SECURITY_MCODE_HEADER, - .unkn = SECURITY_MCODE_UNKN_Q, - .game = SECURITY_MCODE_GAME_DDR_X, - .region = SECURITY_MCODE_REGION_JAPAN, - .cabinet = SECURITY_MCODE_CABINET_A, - .revision = SECURITY_MCODE_REVISION_A, -}; - -void ddrhook1_config_security_init(struct cconfig *config) -{ - char *tmp; - - tmp = security_mcode_to_str(&security_mcode_ddr_x); - - cconfig_util_set_str( - config, - DDRHOOK1_CONFIG_SECURITY_MCODE_KEY, - tmp, - "Mcode of the game to run."); - - free(tmp); -} - void ddrhook1_config_security_get( - struct ddrhook1_config_security *config_security, struct cconfig *config) + const bt_core_config_t *config, + ddrhook1_config_security_t *config_security) { - char *tmp_default; - char mcode[9]; - - tmp_default = security_mcode_to_str(&security_mcode_ddr_x); - - if (!cconfig_util_get_str( - config, - DDRHOOK1_CONFIG_SECURITY_MCODE_KEY, - mcode, - sizeof(mcode) - 1, - tmp_default)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - DDRHOOK1_CONFIG_SECURITY_MCODE_KEY, - tmp_default); - } - - mcode[8] = '\0'; - - if (!security_mcode_parse(mcode, &config_security->mcode)) { - log_warning( - "Invalid mcode '%s' specified, fallback to default '%s'", - mcode, - tmp_default); - - memcpy( - &config_security->mcode, - &security_mcode_ddr_x, - sizeof(struct security_mcode)); - } - - free(tmp_default); -} + bt_core_config_ext_security_mcode_get(config, "security/mcode", &config_security->mcode); +} \ No newline at end of file diff --git a/src/main/ddrhook1/config-security.h b/src/main/ddrhook1/config-security.h index d0a4a5d5..3087ae31 100644 --- a/src/main/ddrhook1/config-security.h +++ b/src/main/ddrhook1/config-security.h @@ -1,34 +1,16 @@ #ifndef DDRHOOK1_CONFIG_SECURITY_H #define DDRHOOK1_CONFIG_SECURITY_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/mcode.h" -#include "util/net.h" - -/** - * Struct holding configuration values for security related items. - */ -struct ddrhook1_config_security { +typedef struct ddrhook1_config_security { struct security_mcode mcode; -}; - -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void ddrhook1_config_security_init(struct cconfig *config); +} ddrhook1_config_security_t; -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_security Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void ddrhook1_config_security_get( - struct ddrhook1_config_security *config_security, struct cconfig *config); + const bt_core_config_t *config, + ddrhook1_config_security_t *config_security); #endif \ No newline at end of file diff --git a/src/main/ddrhook1/ddrhook1.c b/src/main/ddrhook1/ddrhook1.c new file mode 100644 index 00000000..87c8b2ce --- /dev/null +++ b/src/main/ddrhook1/ddrhook1.c @@ -0,0 +1,192 @@ +#include + +#include + +#include "ddrhook-util/_com4.h" +#include "ddrhook-util/extio.h" +#include "ddrhook-util/p3io.h" +#include "ddrhook-util/spike.h" +#include "ddrhook-util/usbmem.h" + +#include "ddrhook1/avs-boot.h" +#include "ddrhook1/config-ddrhook1.h" +#include "ddrhook1/config-eamuse.h" +#include "ddrhook1/config-gfx.h" +#include "ddrhook1/config-security.h" +#include "ddrhook1/filesystem.h" +#include "ddrhook1/master.h" + +#include "ddrhook-util/gfx.h" + +#include "hook/iohook.h" + +#include "hooklib/rs232.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/ddr.h" +#include "iface-io/eam.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "p3ioemu/emu.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "security/rp-sign-key.h" + +bool standard_def; +bool _15khz; + +static const hook_d3d9_irp_handler_t ddrhook1_d3d9_handlers[] = { + gfx_d3d9_irp_handler, +}; + +static module_io_t *_ddrhook1_module_io_ddr; +static module_io_t *_ddrhook1_module_io_eam; + +static void _ddrhook1_io_ddr_init(module_io_t **module) +{ + bt_io_ddr_api_t api; + + module_io_ext_load_and_init( + "ddrio.dll", "bt_module_io_ddr_api_get", module); + module_io_api_get(*module, &api); + bt_io_ddr_api_set(&api); +} + +static void _ddrhook1_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_ddrhook1_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + bool ok; + ddrhook1_config_ddrhook1_t config_ddrhook1; + ddrhook1_config_eamuse_t config_eamuse; + ddrhook1_config_gfx_t config_gfx; + ddrhook1_config_security_t config_security; + + log_info("ddrhook1 for DDR X"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + ddrhook1_config_ddrhook1_get(config, &config_ddrhook1); + ddrhook1_config_eamuse_get(config, &config_eamuse); + ddrhook1_config_gfx_get(config, &config_gfx); + ddrhook1_config_security_get(config, &config_security); + + standard_def = config_ddrhook1.standard_def; + _15khz = config_ddrhook1.use_15khz; + + ddrhook1_master_insert_hooks(NULL); + ddrhook1_filesystem_hook_init(); + + hook_d3d9_init( + ddrhook1_d3d9_handlers, lengthof(ddrhook1_d3d9_handlers)); + + ddrhook1_filesystem_hook_init(); + + ddrhook1_avs_boot_init(); + ddrhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); + + iohook_push_handler(p3io_emu_dispatch_irp); + iohook_push_handler(extio_dispatch_irp); + iohook_push_handler(spike_dispatch_irp); + iohook_push_handler(usbmem_dispatch_irp); + + if (config_ddrhook1.use_com4_emu) { + /* See ddrhook-util/p3io.c for details. */ + iohook_push_handler(com4_dispatch_irp); + } + + if (config_gfx.windowed) { + gfx_set_windowed(); + } + + rs232_hook_init(); + + p3io_ddr_init_with_plugs( + &config_security.mcode, + &config_eamuse.pcbid, + &config_eamuse.eamid, +#if AVS_VERSION >= 1002 + &security_rp_sign_key_black_ddrx2, +#else + &security_rp_sign_key_black_ddrx, +#endif + &security_rp_sign_key_white_eamuse); + extio_init(); + usbmem_init( + config_ddrhook1.usbmem_path_p1, + config_ddrhook1.usbmem_path_p2, + config_ddrhook1.usbmem_enabled); + spike_init(); + com4_init(); + + log_info("Initializing DDR IO backend"); + + _ddrhook1_io_ddr_init(&_ddrhook1_module_io_ddr); + + ok = bt_io_ddr_init(); + + if (!ok) { + log_fatal("Couldn't initialize DDR IO backend"); + return false; + } + + if (config_ddrhook1.use_com4_emu) { + log_info("Initializing card reader backend"); + + _ddrhook1_io_eam_init(&_ddrhook1_module_io_eam); + + ok = bt_io_eam_init(); + + if (!ok) { + log_fatal("Couldn't initialize card reader backend"); + return false; + } + } + + return true; +} + +static void _ddrhook1_main_fini() +{ + // TODO cleanup +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _ddrhook1_main_init; + api->v1.main_fini = _ddrhook1_main_fini; +} \ No newline at end of file diff --git a/src/main/ddrhook1/ddrhook1.def b/src/main/ddrhook1/ddrhook1.def index 16b5248c..711a923a 100644 --- a/src/main/ddrhook1/ddrhook1.def +++ b/src/main/ddrhook1/ddrhook1.def @@ -2,3 +2,9 @@ LIBRARY ddrhook1 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/ddrhook1/ddrhook1.h b/src/main/ddrhook1/ddrhook1.h new file mode 100644 index 00000000..d6a89079 --- /dev/null +++ b/src/main/ddrhook1/ddrhook1.h @@ -0,0 +1,9 @@ +#ifndef DDRHOOK1_H +#define DDRHOOK1_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/ddrhook1/dllmain.c b/src/main/ddrhook1/dllmain.c index 3dcc6c94..5f9495c2 100644 --- a/src/main/ddrhook1/dllmain.c +++ b/src/main/ddrhook1/dllmain.c @@ -1,201 +1,72 @@ #include -#include - -#include "bemanitools/ddrio.h" -#include "bemanitools/eamio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ddrhook-util/_com4.h" -#include "ddrhook-util/extio.h" -#include "ddrhook-util/p3io.h" -#include "ddrhook-util/spike.h" -#include "ddrhook-util/usbmem.h" - -#include "ddrhook1/avs-boot.h" -#include "ddrhook1/config-ddrhook1.h" -#include "ddrhook1/config-eamuse.h" -#include "ddrhook1/config-gfx.h" -#include "ddrhook1/config-security.h" -#include "ddrhook1/filesystem.h" -#include "ddrhook1/master.h" - -#include "ddrhook-util/gfx.h" - -#include "hook/iohook.h" #include "hook/table.h" -#include "hooklib/app.h" -#include "hooklib/rs232.h" +#include "ddrhook1/ddrhook1.h" -#include "imports/avs.h" +#include "main/sdk-hook/dllentry.h" -#include "p3ioemu/emu.h" - -#include "security/rp-sign-key.h" - -#include "util/cmdline.h" #include "util/defs.h" -#include "util/log.h" -#include "util/thread.h" - -#define DDRHOOK1_INFO_HEADER \ - "ddrhook1 for DDR X" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define DDRHOOK1_CMD_USAGE \ - "Usage: inject.exe ddrhook1.dll [options...]" - -bool standard_def; -bool _15khz; - -static const hook_d3d9_irp_handler_t ddrhook1_d3d9_handlers[] = { - gfx_d3d9_irp_handler, -}; static DWORD STDCALL -my_GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize); -static DWORD(STDCALL *real_GetModuleFileNameA)( +_ddrhook1_dllmain_my_GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize); +static DWORD(STDCALL *_ddrhook1_dllmain_real_GetModuleFileNameA)( HMODULE hModule, LPSTR lpFilename, DWORD nSize); -static bool ddrhook1_init_check = false; +static bool _ddrhook1_dllmain_getmodulefilenamea_call_check; -static const struct hook_symbol init_hook_syms[] = { +static const struct hook_symbol _ddrhook1_dllmain_hook_syms[] = { { .name = "GetModuleFileNameA", - .patch = my_GetModuleFileNameA, - .link = (void **) &real_GetModuleFileNameA, + .patch = _ddrhook1_dllmain_my_GetModuleFileNameA, + .link = (void **) &_ddrhook1_dllmain_real_GetModuleFileNameA, }, }; static DWORD STDCALL -my_GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize) +_ddrhook1_dllmain_my_GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize) { - bool ok; - struct cconfig *config; - - struct ddrhook1_config_ddrhook1 config_ddrhook1; - struct ddrhook1_config_eamuse config_eamuse; - struct ddrhook1_config_gfx config_gfx; - struct ddrhook1_config_security config_security; - - if (ddrhook1_init_check) - goto skip; - - log_info("--- Begin ddrhook1 main ---"); - - ddrhook1_init_check = true; - - config = cconfig_init(); - - ddrhook1_config_ddrhook1_init(config); - ddrhook1_config_eamuse_init(config); - ddrhook1_config_gfx_init(config); - ddrhook1_config_security_init(config); - - if (!cconfig_hook_config_init( - config, - DDRHOOK1_INFO_HEADER "\n" DDRHOOK1_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - ddrhook1_config_ddrhook1_get(&config_ddrhook1, config); - ddrhook1_config_eamuse_get(&config_eamuse, config); - ddrhook1_config_gfx_get(&config_gfx, config); - ddrhook1_config_security_get(&config_security, config); - - cconfig_finit(config); - - standard_def = config_ddrhook1.standard_def; - _15khz = config_ddrhook1.use_15khz; - - log_info(DDRHOOK1_INFO_HEADER); - log_info("Initializing ddrhook1..."); - - ddrhook1_filesystem_hook_init(); - - ddrhook1_avs_boot_init(); - ddrhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); - - iohook_push_handler(p3io_emu_dispatch_irp); - iohook_push_handler(extio_dispatch_irp); - iohook_push_handler(spike_dispatch_irp); - iohook_push_handler(usbmem_dispatch_irp); - - if (config_ddrhook1.use_com4_emu) { - /* See ddrhook-util/p3io.c for details. */ - iohook_push_handler(com4_dispatch_irp); - } - - if (config_gfx.windowed) { - gfx_set_windowed(); - } - - rs232_hook_init(); - - p3io_ddr_init_with_plugs( - &config_security.mcode, - &config_eamuse.pcbid, - &config_eamuse.eamid, -#if AVS_VERSION >= 1002 - &security_rp_sign_key_black_ddrx2, -#else - &security_rp_sign_key_black_ddrx, -#endif - &security_rp_sign_key_white_eamuse); - extio_init(); - usbmem_init( - config_ddrhook1.usbmem_path_p1, - config_ddrhook1.usbmem_path_p2, - config_ddrhook1.usbmem_enabled); - spike_init(); - com4_init(); - - log_info("Initializing DDR IO backend"); - - ok = ddr_io_init(thread_create, thread_join, thread_destroy); - - if (!ok) { - log_fatal("Couldn't initialize DDR IO backend"); - return false; + if (_ddrhook1_dllmain_getmodulefilenamea_call_check) { + return _ddrhook1_dllmain_real_GetModuleFileNameA(hModule, lpFilename, nSize); } - if (config_ddrhook1.use_com4_emu) { - log_info("Initializing card reader backend"); + _ddrhook1_dllmain_getmodulefilenamea_call_check = true; - eam_io_set_loggers( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); + bt_hook_dllentry_main_init(); - ok = eam_io_init(thread_create, thread_join, thread_destroy); - - if (!ok) { - log_fatal("Couldn't initialize card reader backend"); - return false; - } - } - - log_info("--- End ddrhook1 main ---"); - -skip: - return real_GetModuleFileNameA(hModule, lpFilename, nSize); + return _ddrhook1_dllmain_real_GetModuleFileNameA(hModule, lpFilename, nSize); } -BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() + +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - log_to_writer(log_writer_debug, NULL); + bt_hook_dllentry_init( + mod, + "ddrhook1", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); + + _ddrhook1_dllmain_getmodulefilenamea_call_check = false; hook_table_apply( - NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms)); + NULL, "kernel32.dll", _ddrhook1_dllmain_hook_syms, lengthof(_ddrhook1_dllmain_hook_syms)); + + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "kernel32.dll", _ddrhook1_dllmain_hook_syms, lengthof(_ddrhook1_dllmain_hook_syms)); - ddrhook1_master_insert_hooks(NULL); - ddrhook1_filesystem_hook_init(); + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); - hook_d3d9_init( - ddrhook1_d3d9_handlers, lengthof(ddrhook1_d3d9_handlers)); + bt_hook_dllentry_fini(); + } } return TRUE; -} +} \ No newline at end of file diff --git a/src/main/ddrhook1/filesystem.c b/src/main/ddrhook1/filesystem.c index abec921e..5599dfb9 100644 --- a/src/main/ddrhook1/filesystem.c +++ b/src/main/ddrhook1/filesystem.c @@ -8,8 +8,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" diff --git a/src/main/ddrhook1/master.c b/src/main/ddrhook1/master.c index b30836a5..79beb871 100644 --- a/src/main/ddrhook1/master.c +++ b/src/main/ddrhook1/master.c @@ -6,10 +6,11 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "p3ioemu/devmgr.h" #include "util/defs.h" -#include "util/log.h" static HMODULE(STDCALL *real_LoadLibraryA)(const char *name); static BOOL(STDCALL *real_IsDebuggerPresent)(); diff --git a/src/main/ddrhook2/Module.mk b/src/main/ddrhook2/Module.mk index 0c9fd365..cb084dbb 100644 --- a/src/main/ddrhook2/Module.mk +++ b/src/main/ddrhook2/Module.mk @@ -3,7 +3,11 @@ avsdlls += ddrhook2 deplibs_ddrhook2 := \ avs \ +avslibs_ddrhook2 := \ + avs-ext \ + libs_ddrhook2 := \ + core \ acioemu \ ddrhook-util \ p3ioemu \ @@ -11,9 +15,10 @@ libs_ddrhook2 := \ hook \ hooklib \ util \ - eamio \ - ddrio \ security \ + iface-core \ + iface-io \ + module \ src_ddrhook2 := \ dllmain.c \ diff --git a/src/main/ddrhook2/ddrhook2.def b/src/main/ddrhook2/ddrhook2.def index e2628296..84f83d97 100644 --- a/src/main/ddrhook2/ddrhook2.def +++ b/src/main/ddrhook2/ddrhook2.def @@ -2,3 +2,8 @@ LIBRARY ddrhook2 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/ddrhook2/dllmain.c b/src/main/ddrhook2/dllmain.c index 90355519..693d5abd 100644 --- a/src/main/ddrhook2/dllmain.c +++ b/src/main/ddrhook2/dllmain.c @@ -2,9 +2,6 @@ #include -#include "bemanitools/ddrio.h" -#include "bemanitools/eamio.h" - #include "ddrhook-util/_com4.h" #include "ddrhook-util/extio.h" #include "ddrhook-util/gfx.h" @@ -16,24 +13,54 @@ #include "hook/iohook.h" -#include "hooklib/app.h" #include "hooklib/rs232.h" -#include "imports/avs.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/ddr.h" +#include "iface-io/eam.h" + +#include "module/io-ext.h" +#include "module/io.h" #include "p3ioemu/emu.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + #include "util/cmdline.h" #include "util/defs.h" -#include "util/log.h" - -static bool my_dll_entry_init(char *sidcode, struct property_node *param); -static bool my_dll_entry_main(void); bool standard_def; bool _15khz; -static bool my_dll_entry_init(char *sidcode, struct property_node *param) +static module_io_t *_ddrhook2_module_io_ddr; +static module_io_t *_ddrhook2_module_io_eam; + +static void _ddrhook2_io_ddr_init(module_io_t **module) +{ + bt_io_ddr_api_t api; + + module_io_ext_load_and_init( + "ddrio.dll", "bt_module_io_ddr_api_get", module); + module_io_api_get(*module, &api); + bt_io_ddr_api_set(&api); +} + +static void _ddrhook2_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_ddrhook2_main_init(HMODULE game_module, const bt_core_config_t *config_) { int argc; char **argv; @@ -119,10 +146,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("Initializing DDR IO backend"); - ddr_io_set_loggers( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); + _ddrhook2_io_ddr_init(&_ddrhook2_module_io_ddr); - ok = ddr_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + ok = bt_io_ddr_init(); if (!ok) { return false; @@ -131,11 +157,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) if (com4) { log_info("Initializing card reader backend"); - eam_io_set_loggers( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); + _ddrhook2_io_eam_init(&_ddrhook2_module_io_eam); - ok = - eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + ok = bt_io_eam_init(); if (!ok) { return false; @@ -144,41 +168,47 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("--- End ddrhook dll_entry_init ---"); - return app_hook_invoke_init(sidcode, param); + return true; } -static bool my_dll_entry_main(void) +static void _ddrhook2_main_fini() { - bool result; - - result = app_hook_invoke_main(); - log_misc("Shutting down card reader backend"); - eam_io_fini(); + bt_io_eam_fini(); + bt_io_eam_api_clear(); + module_io_free(&_ddrhook2_module_io_eam); log_misc("Shutting down DDR IO backend"); - ddr_io_fini(); + bt_io_ddr_fini(); + bt_io_ddr_api_clear(); + module_io_free(&_ddrhook2_module_io_ddr); com4_fini(); spike_fini(); usbmem_fini(); extio_fini(); p3io_emu_fini(); +} - return result; +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); } -BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } + bt_core_thread_api_set(api); +} - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; - app_hook_init(my_dll_entry_init, my_dll_entry_main); + api->v1.main_init = _ddrhook2_main_init; + api->v1.main_fini = _ddrhook2_main_fini; +} -end: +BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +{ return TRUE; } diff --git a/src/main/ddrhook2/master.c b/src/main/ddrhook2/master.c index 89f874ff..5df884cd 100644 --- a/src/main/ddrhook2/master.c +++ b/src/main/ddrhook2/master.c @@ -7,10 +7,11 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "p3ioemu/devmgr.h" #include "util/defs.h" -#include "util/log.h" static HMODULE(STDCALL *real_LoadLibraryA)(const char *name); diff --git a/src/main/ddrio-async/Module.mk b/src/main/ddrio-async/Module.mk index 62006cfe..4480ed18 100644 --- a/src/main/ddrio-async/Module.mk +++ b/src/main/ddrio-async/Module.mk @@ -3,7 +3,13 @@ dlls += ddrio-async ldflags_ddrio-async:= \ libs_ddrio-async := \ + core \ util \ + iface \ + iface-io \ + iface-core \ + util \ + module \ src_ddrio-async := \ ddrio.c \ diff --git a/src/main/ddrio-async/ddrio-async.def b/src/main/ddrio-async/ddrio-async.def index 9a399dd3..08f19164 100644 --- a/src/main/ddrio-async/ddrio-async.def +++ b/src/main/ddrio-async/ddrio-async.def @@ -1,11 +1,17 @@ LIBRARY ddrio-async EXPORTS - ddr_io_set_loggers - ddr_io_fini - ddr_io_init - ddr_io_read_pad - ddr_io_set_lights_extio - ddr_io_set_lights_p3io - ddr_io_set_lights_hdxs_panel - ddr_io_set_lights_hdxs_rgb + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_ddr_api_get + + ; Direct API + bt_io_ddr_init = bt_io_ddr_async_init + bt_io_ddr_fini = bt_io_ddr_async_fini + bt_io_ddr_pad_read = bt_io_ddr_async_pad_read + bt_io_ddr_extio_lights_set = bt_io_ddr_async_extio_lights_set + bt_io_ddr_p3io_lights_set = bt_io_ddr_async_p3io_lights_set + bt_io_ddr_hdxs_lights_panel_set = bt_io_ddr_async_hdxs_lights_panel_set + bt_io_ddr_hdxs_lights_rgb_set = bt_io_ddr_async_hdxs_lights_rgb_set + diff --git a/src/main/ddrio-async/ddrio.c b/src/main/ddrio-async/ddrio.c index fe81f68e..72d14874 100644 --- a/src/main/ddrio-async/ddrio.c +++ b/src/main/ddrio-async/ddrio.c @@ -9,45 +9,22 @@ #include -#include "bemanitools/ddrio.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface-io/ddr.h" + +#include "module/io-ext.h" +#include "module/io.h" -#include "util/log.h" -#include "util/thread.h" #include "util/time.h" -typedef void (*ddr_io_set_loggers_t)( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); -typedef bool (*ddr_io_init_t)( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy); -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_fini_t)(void); - -static HMODULE _child_ddr_io_module; - -static ddr_io_set_loggers_t _child_ddr_io_set_loggers; -static ddr_io_init_t _child_ddr_io_init; -static ddr_io_read_pad_t _child_ddr_io_read_pad; -static ddr_io_set_lights_extio_t _child_ddr_io_set_lights_extio; -static ddr_io_set_lights_p3io_t _child_ddr_io_set_lights_p3io; -static ddr_io_set_lights_hdxs_panel_t _child_ddr_io_set_lights_hdxs_panel; -static ddr_io_set_lights_hdxs_rgb_t _child_ddr_io_set_lights_hdxs_rgb; -static ddr_io_fini_t _child_ddr_io_fini; - -static log_formatter_t _log_formatter_misc; -static log_formatter_t _log_formatter_info; -static log_formatter_t _log_formatter_warning; -static log_formatter_t _log_formatter_fatal; +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/io/ddr.h" + +static module_io_t *_ddr_io_async_module_ddr_io; +static bt_core_thread_id_t _io_thread_id; static _Atomic(bool) _io_thread_proc_loop; static _Atomic(bool) _io_thread_proc_running; @@ -80,7 +57,7 @@ static int _io_thread_proc(void *ctx) loop_counter = 0; while (atomic_load_explicit(&_io_thread_proc_loop, memory_order_seq_cst)) { - local_tmp = _child_ddr_io_read_pad(); + local_tmp = bt_io_ddr_pad_read(); atomic_store_explicit( &_child_ddr_io_data_pad, local_tmp, memory_order_relaxed); @@ -95,7 +72,7 @@ static int _io_thread_proc(void *ctx) &_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); + bt_io_ddr_extio_lights_set(local_tmp); prev_child_ddr_io_data_extio_lights = local_tmp; } @@ -103,7 +80,7 @@ static int _io_thread_proc(void *ctx) &_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); + bt_io_ddr_p3io_lights_set(local_tmp); prev_child_ddr_io_data_p3io_lights = local_tmp; } @@ -130,84 +107,48 @@ static int _io_thread_proc(void *ctx) return 0; } -static void *_load_function(HMODULE module, const char *name) +static void _ddr_io_async_child_ddr_io_init(module_io_t **module) { - void *ptr; - - ptr = GetProcAddress(module, name); + bt_io_ddr_api_t api; - if (ptr == NULL) { - log_fatal("Could not find function %s in ddr3io child library", name); - } - - return ptr; + module_io_ext_load_and_init( + "ddrio-async-child.dll", "bt_module_io_ddr_api_get", module); + module_io_api_get(*module, &api); + bt_io_ddr_api_set(&api); } -void ddr_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +bool bt_io_ddr_async_init() { - _log_formatter_misc = misc; - _log_formatter_info = info; - _log_formatter_warning = warning; - _log_formatter_fatal = fatal; + bool result; + bt_core_thread_result_t result2; - log_to_external(misc, info, warning, fatal); -} - -bool ddr_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) -{ log_info("Loading ddrio-async-child.dll as child ddrio library..."); - _child_ddr_io_module = LoadLibraryA("ddrio-async-child.dll"); - - if (_child_ddr_io_module == NULL) { - log_warning("Loading ddrio-async-child.dll failed"); - return false; - } - - _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_fini = _load_function(_child_ddr_io_module, "ddr_io_fini"); - - _child_ddr_io_set_loggers( - _log_formatter_misc, - _log_formatter_info, - _log_formatter_warning, - _log_formatter_fatal); + _ddr_io_async_child_ddr_io_init(&_ddr_io_async_module_ddr_io); log_info("Calling child ddr_io_init..."); - if (!_child_ddr_io_init(thread_create, thread_join, thread_destroy)) { + result = bt_io_ddr_init(); + + if (!result) { log_warning("Child ddr_io_init failed"); - FreeLibrary(_child_ddr_io_module); + module_io_free(&_ddr_io_async_module_ddr_io); return false; } 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"); + result2 = + bt_core_thread_create(_io_thread_proc, NULL, 16384, 0, &_io_thread_id); + + if (result2 != BT_CORE_THREAD_RESULT_SUCCESS) { + log_warning( + "Creating IO thread failed: %s", + bt_core_thread_result_to_str(result2)); - _child_ddr_io_fini(); - FreeLibrary(_child_ddr_io_module); + bt_io_ddr_fini(); + module_io_free(&_ddr_io_async_module_ddr_io); return false; } @@ -215,47 +156,71 @@ bool ddr_io_init( return true; } -uint32_t ddr_io_read_pad(void) +void bt_io_ddr_async_fini(void) +{ + 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)) { + Sleep(1); + } + + log_info("IO thread finished"); + + bt_io_ddr_fini(); + + module_io_free(&_ddr_io_async_module_ddr_io); +} + +uint32_t bt_io_ddr_async_pad_read(void) { return atomic_load_explicit(&_child_ddr_io_data_pad, memory_order_relaxed); } -void ddr_io_set_lights_extio(uint32_t extio_lights) +void bt_io_ddr_async_extio_lights_set(uint32_t extio_lights) { atomic_store_explicit( &_child_ddr_io_data_extio_lights, extio_lights, memory_order_relaxed); } -void ddr_io_set_lights_p3io(uint32_t p3io_lights) +void bt_io_ddr_async_p3io_lights_set(uint32_t p3io_lights) { atomic_store_explicit( &_child_ddr_io_data_p3io_lights, p3io_lights, memory_order_relaxed); } -void ddr_io_set_lights_hdxs_panel(uint32_t lights) +void bt_io_ddr_async_hdxs_lights_panel_set(uint32_t lights) { // Not implemented for now } -void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +void bt_io_ddr_async_hdxs_lights_rgb_set( + uint8_t idx, uint8_t r, uint8_t g, uint8_t b) { // Not implemented for now } -void ddr_io_fini(void) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - 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)) { - Sleep(1); - } - - log_info("IO thread finished"); - - _child_ddr_io_fini(); + bt_core_log_api_set(api); +} - FreeLibrary(_child_ddr_io_module); +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); } + +void bt_module_io_ddr_api_get(bt_io_ddr_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_ddr_async_init; + api->v1.fini = bt_io_ddr_async_fini; + api->v1.pad_read = bt_io_ddr_async_pad_read; + api->v1.extio_lights_set = bt_io_ddr_async_extio_lights_set; + api->v1.p3io_lights_set = bt_io_ddr_async_p3io_lights_set; + api->v1.hdxs_lights_panel_set = bt_io_ddr_async_hdxs_lights_panel_set; + api->v1.hdxs_lights_rgb_set = bt_io_ddr_async_hdxs_lights_rgb_set; +} \ No newline at end of file diff --git a/src/main/ddrio-mm/Module.mk b/src/main/ddrio-mm/Module.mk index 9368a623..38621597 100644 --- a/src/main/ddrio-mm/Module.mk +++ b/src/main/ddrio-mm/Module.mk @@ -5,8 +5,10 @@ ldflags_ddrio-mm:= \ -lsetupapi \ libs_ddrio-mm := \ + core \ mm \ util \ + iface-core \ src_ddrio-mm := \ ddrio.c \ diff --git a/src/main/ddrio-mm/ddrio-mm.def b/src/main/ddrio-mm/ddrio-mm.def index 82df833d..546c7617 100644 --- a/src/main/ddrio-mm/ddrio-mm.def +++ b/src/main/ddrio-mm/ddrio-mm.def @@ -1,11 +1,15 @@ LIBRARY ddrio-mm EXPORTS - ddr_io_set_loggers - ddr_io_fini - ddr_io_init - ddr_io_read_pad - ddr_io_set_lights_extio - ddr_io_set_lights_p3io - ddr_io_set_lights_hdxs_panel - ddr_io_set_lights_hdxs_rgb + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_io_ddr_api_get + + ; Direct API + bt_io_ddr_init + bt_io_ddr_fini + bt_io_ddr_pad_read + bt_io_ddr_extio_lights_set + bt_io_ddr_p3io_lights_set + bt_io_ddr_hdxs_lights_panel_set + bt_io_ddr_hdxs_lights_rgb_set diff --git a/src/main/ddrio-mm/ddrio.c b/src/main/ddrio-mm/ddrio.c index 08bd1d29..30caddf2 100644 --- a/src/main/ddrio-mm/ddrio.c +++ b/src/main/ddrio-mm/ddrio.c @@ -1,3 +1,5 @@ +#define LOG_MODULE "ddrio-mm" + #include #include @@ -5,13 +7,17 @@ #include #include -#include "bemanitools/ddrio.h" +#include "api/core/log.h" + +#include "iface-core/log.h" #include "mm/mm.h" +#include "sdk/module/core/log.h" +#include "sdk/module/io/ddr.h" + #include "util/cmdline.h" #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" struct ddr_bittrans { @@ -20,49 +26,49 @@ struct ddr_bittrans { }; static const struct ddr_bittrans input_map[] = { - {0x00000001, 1 << DDR_SERVICE}, - {0x00000002, 1 << DDR_TEST}, - {0x00100000, 1 << DDR_P1_MENU_LEFT}, - {0x00400000, 1 << DDR_P1_MENU_RIGHT}, - {0x00000100, 1 << DDR_P1_START}, - {0x00200000, 1 << DDR_P2_MENU_LEFT}, - {0x00800000, 1 << DDR_P2_MENU_RIGHT}, - {0x00000200, 1 << DDR_P2_START}, - {0x00004000, 1 << DDR_P1_LEFT}, - {0x00010000, 1 << DDR_P1_RIGHT}, - {0x00000400, 1 << DDR_P1_UP}, - {0x00001000, 1 << DDR_P1_DOWN}, - {0x00008000, 1 << DDR_P2_LEFT}, - {0x00020000, 1 << DDR_P2_RIGHT}, - {0x00000800, 1 << DDR_P2_UP}, - {0x00002000, 1 << DDR_P2_DOWN}, + {0x00000001, 1 << BT_IO_DDR_SERVICE}, + {0x00000002, 1 << BT_IO_DDR_TEST}, + {0x00100000, 1 << BT_IO_DDR_P1_MENU_LEFT}, + {0x00400000, 1 << BT_IO_DDR_P1_MENU_RIGHT}, + {0x00000100, 1 << BT_IO_DDR_P1_START}, + {0x00200000, 1 << BT_IO_DDR_P2_MENU_LEFT}, + {0x00800000, 1 << BT_IO_DDR_P2_MENU_RIGHT}, + {0x00000200, 1 << BT_IO_DDR_P2_START}, + {0x00004000, 1 << BT_IO_DDR_P1_LEFT}, + {0x00010000, 1 << BT_IO_DDR_P1_RIGHT}, + {0x00000400, 1 << BT_IO_DDR_P1_UP}, + {0x00001000, 1 << BT_IO_DDR_P1_DOWN}, + {0x00008000, 1 << BT_IO_DDR_P2_LEFT}, + {0x00020000, 1 << BT_IO_DDR_P2_RIGHT}, + {0x00000800, 1 << BT_IO_DDR_P2_UP}, + {0x00002000, 1 << BT_IO_DDR_P2_DOWN}, /* Nonstandard */ - {0x01000000, 1 << DDR_P1_MENU_UP}, - {0x04000000, 1 << DDR_P1_MENU_DOWN}, - {0x02000000, 1 << DDR_P2_MENU_UP}, - {0x08000000, 1 << DDR_P2_MENU_DOWN}, + {0x01000000, 1 << BT_IO_DDR_P1_MENU_UP}, + {0x04000000, 1 << BT_IO_DDR_P1_MENU_DOWN}, + {0x02000000, 1 << BT_IO_DDR_P2_MENU_UP}, + {0x08000000, 1 << BT_IO_DDR_P2_MENU_DOWN}, }; static const struct ddr_bittrans extio_light_map[] = { - {0x00000100, 1 << LIGHT_P1_UP}, - {0x00000200, 1 << LIGHT_P1_DOWN}, - {0x00000400, 1 << LIGHT_P1_LEFT}, - {0x00000800, 1 << LIGHT_P1_RIGHT}, - {0x00010000, 1 << LIGHT_P2_UP}, - {0x00020000, 1 << LIGHT_P2_DOWN}, - {0x00040000, 1 << LIGHT_P2_LEFT}, - {0x00080000, 1 << LIGHT_P2_RIGHT}, - {0x01000000, 1 << LIGHT_NEONS}, + {0x00000100, 1 << BT_IO_DDR_EXTIO_LIGHT_P1_UP}, + {0x00000200, 1 << BT_IO_DDR_EXTIO_LIGHT_P1_DOWN}, + {0x00000400, 1 << BT_IO_DDR_EXTIO_LIGHT_P1_LEFT}, + {0x00000800, 1 << BT_IO_DDR_EXTIO_LIGHT_P1_RIGHT}, + {0x00010000, 1 << BT_IO_DDR_EXTIO_LIGHT_P2_UP}, + {0x00020000, 1 << BT_IO_DDR_EXTIO_LIGHT_P2_DOWN}, + {0x00040000, 1 << BT_IO_DDR_EXTIO_LIGHT_P2_LEFT}, + {0x00080000, 1 << BT_IO_DDR_EXTIO_LIGHT_P2_RIGHT}, + {0x01000000, 1 << BT_IO_DDR_EXTIO_LIGHT_NEONS}, }; static const struct ddr_bittrans p3io_light_map[] = { - {0x00000004, 1 << LIGHT_P1_MENU}, - {0x00000008, 1 << LIGHT_P2_MENU}, - {0x00000010, 1 << LIGHT_P2_LOWER_LAMP}, - {0x00000020, 1 << LIGHT_P2_UPPER_LAMP}, - {0x00000040, 1 << LIGHT_P1_LOWER_LAMP}, - {0x00000080, 1 << LIGHT_P1_UPPER_LAMP}, + {0x00000004, 1 << BT_IO_DDR_P3IO_LIGHT_P1_MENU}, + {0x00000008, 1 << BT_IO_DDR_P3IO_LIGHT_P2_MENU}, + {0x00000010, 1 << BT_IO_DDR_P3IO_LIGHT_P2_LOWER_LAMP}, + {0x00000020, 1 << BT_IO_DDR_P3IO_LIGHT_P2_UPPER_LAMP}, + {0x00000040, 1 << BT_IO_DDR_P3IO_LIGHT_P1_LOWER_LAMP}, + {0x00000080, 1 << BT_IO_DDR_P3IO_LIGHT_P1_UPPER_LAMP}, }; static bool initted; @@ -111,19 +117,7 @@ static int ddr_io_get_lag_param(void) return result; } -void ddr_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - log_to_external(misc, info, warning, fatal); -} - -bool ddr_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_ddr_init() { bool ok; @@ -143,7 +137,7 @@ bool ddr_io_init( return true; } -uint32_t ddr_io_read_pad(void) +uint32_t bt_io_ddr_pad_read(void) { struct mm_input in; uint32_t i; @@ -165,7 +159,7 @@ uint32_t ddr_io_read_pad(void) return pad; } -void ddr_io_set_lights_extio(uint32_t extio_lights) +void bt_io_ddr_extio_lights_set(uint32_t extio_lights) { uint32_t clr; uint32_t set; @@ -186,7 +180,7 @@ void ddr_io_set_lights_extio(uint32_t extio_lights) atomic_fetch_and(&out.lights, ~clr); } -void ddr_io_set_lights_p3io(uint32_t p3io_lights) +void bt_io_ddr_p3io_lights_set(uint32_t p3io_lights) { uint32_t clr; uint32_t set; @@ -207,13 +201,13 @@ void ddr_io_set_lights_p3io(uint32_t p3io_lights) atomic_fetch_and(&out.lights, ~clr); } -void ddr_io_set_lights_hdxs_panel(uint32_t lights) +void bt_io_ddr_hdxs_lights_panel_set(uint32_t lights) { (void) lights; // stubbed } -void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +void bt_io_ddr_hdxs_lights_rgb_set(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) { (void) idx; (void) r; @@ -222,7 +216,7 @@ void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) // stubbed } -void ddr_io_fini(void) +void bt_io_ddr_fini(void) { if (initted) { mm_fini(); @@ -230,3 +224,21 @@ void ddr_io_fini(void) initted = false; } } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_io_ddr_api_get(bt_io_ddr_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_ddr_init; + api->v1.fini = bt_io_ddr_fini; + api->v1.pad_read = bt_io_ddr_pad_read; + api->v1.extio_lights_set = bt_io_ddr_extio_lights_set; + api->v1.p3io_lights_set = bt_io_ddr_p3io_lights_set; + api->v1.hdxs_lights_panel_set = bt_io_ddr_hdxs_lights_panel_set; + api->v1.hdxs_lights_rgb_set = bt_io_ddr_hdxs_lights_rgb_set; +} \ No newline at end of file diff --git a/src/main/ddrio-p3io/Module.mk b/src/main/ddrio-p3io/Module.mk index 43e0fd06..8b10cad1 100644 --- a/src/main/ddrio-p3io/Module.mk +++ b/src/main/ddrio-p3io/Module.mk @@ -2,14 +2,17 @@ dlls += ddrio-p3io ldflags_ddrio-p3io:= \ -lsetupapi \ + -lws2_32 \ libs_ddrio-p3io := \ - cconfig \ + core \ extio \ extiodrv \ p3io \ p3iodrv \ util \ + iface-core \ + security \ src_ddrio-p3io := \ config.c \ diff --git a/src/main/ddrio-p3io/config.c b/src/main/ddrio-p3io/config.c index c45254e1..5a41027f 100644 --- a/src/main/ddrio-p3io/config.c +++ b/src/main/ddrio-p3io/config.c @@ -1,35 +1,32 @@ -#include "cconfig/cconfig-util.h" +#include -#include "util/log.h" +#include "core/config-ext.h" -#include "config.h" +#include "ddrio-p3io/config.h" -#define DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY "ddrio.p3io.extio_port" +#include "iface-core/log.h" -#define DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE "COM1" - -void ddrio_p3io_config_init(struct cconfig *config) +static void _ddrio_p3io_config_verify(const ddrio_p3io_config_t *config_ddrio_p3io) { - cconfig_util_set_str( - config, - DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY, - DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE, - "COM port the EXTIO is connected to, default COM1"); + char *num_part; + int num; + + if (strncmp(config_ddrio_p3io->extio_port, "COM", 3) != 0) { + log_fatal("Invalid COM port string: %s", config_ddrio_p3io->extio_port); + } + + num_part = ((char*) config_ddrio_p3io->extio_port) + 3; + + num = atoi(num_part); + + if (num < 1 || num > 99) { + log_fatal("Invalid COM port number in string: %s", config_ddrio_p3io->extio_port); + } } -void ddrio_p3io_config_get( - struct ddrio_p3io_config *config_ddrio_p3io, struct cconfig *config) +void ddrio_p3io_config_get(const bt_core_config_t *config, ddrio_p3io_config_t *config_ddrio_p3io) { - if (!cconfig_util_get_str( - config, - DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY, - config_ddrio_p3io->extio_port, - sizeof(config_ddrio_p3io->extio_port) - 1, - DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY, - DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE); - } + bt_core_config_ext_str_get(config, "extio_port", config_ddrio_p3io->extio_port, sizeof(config_ddrio_p3io->extio_port)); + + _ddrio_p3io_config_verify(config_ddrio_p3io); } diff --git a/src/main/ddrio-p3io/config.h b/src/main/ddrio-p3io/config.h index 784782f4..bbf37a8b 100644 --- a/src/main/ddrio-p3io/config.h +++ b/src/main/ddrio-p3io/config.h @@ -1,17 +1,12 @@ #ifndef DDRIO_P3IO_CONFIG_H #define DDRIO_P3IO_CONFIG_H -#include +#include "api/core/config.h" -#include "cconfig/cconfig.h" - -struct ddrio_p3io_config { +typedef struct ddrio_p3io_config { char extio_port[12]; -}; - -void ddrio_p3io_config_init(struct cconfig *config); +} ddrio_p3io_config_t; -void ddrio_p3io_config_get( - struct ddrio_p3io_config *config_ddrio_p3io, struct cconfig *config); +void ddrio_p3io_config_get(const bt_core_config_t *config, ddrio_p3io_config_t *config_ddrio_p3io); #endif \ No newline at end of file diff --git a/src/main/ddrio-p3io/ddrio-p3io.def b/src/main/ddrio-p3io/ddrio-p3io.def index f6e9fbbe..fd93c9d5 100644 --- a/src/main/ddrio-p3io/ddrio-p3io.def +++ b/src/main/ddrio-p3io/ddrio-p3io.def @@ -1,11 +1,17 @@ LIBRARY ddrio-p3io EXPORTS - ddr_io_set_loggers - ddr_io_fini - ddr_io_init - ddr_io_read_pad - ddr_io_set_lights_extio - ddr_io_set_lights_p3io - ddr_io_set_lights_hdxs_panel - ddr_io_set_lights_hdxs_rgb + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_configure_do + bt_module_io_ddr_api_get + + ; Direct API + bt_io_ddr_init + bt_io_ddr_fini + bt_io_ddr_pad_read + bt_io_ddr_extio_lights_set + bt_io_ddr_p3io_lights_set + bt_io_ddr_hdxs_lights_panel_set + bt_io_ddr_hdxs_lights_rgb_set diff --git a/src/main/ddrio-p3io/ddrio.c b/src/main/ddrio-p3io/ddrio.c index a38ce09d..87ebfd09 100644 --- a/src/main/ddrio-p3io/ddrio.c +++ b/src/main/ddrio-p3io/ddrio.c @@ -6,22 +6,22 @@ #include #include -#include "bemanitools/ddrio.h" - -#include "cconfig/cconfig-main.h" +#include "ddrio-p3io/config.h" #include "extiodrv/device.h" #include "extiodrv/extio.h" +#include "iface-core/config.h" +#include "iface-core/log.h" + #include "p3iodrv/ddr.h" #include "p3iodrv/device.h" -#include "util/log.h" -#include "util/thread.h" +#include "sdk/module/configure.h" +#include "sdk/module/core/log.h" +#include "sdk/module/io/ddr.h" -#include "config.h" - -static struct ddrio_p3io_config _ddr_io_p3io_config; +static ddrio_p3io_config_t _ddr_io_p3io_config; static HANDLE _ddr_io_p3io_handle; static HANDLE _ddr_io_extio_handle; @@ -249,49 +249,10 @@ static HRESULT _ddr_io_flush_and_reset(HANDLE p3io_handle, HANDLE extio_handle) return hr; } -void ddr_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - log_to_external(misc, info, warning, fatal); -} - -static void _ddr_io_config_init(struct ddrio_p3io_config *config_ddrio_p3io) -{ - struct cconfig *config; - - config = cconfig_init(); - - ddrio_p3io_config_init(config); - - if (!cconfig_main_config_init( - config, - "--ddrio-p3io-config", - "ddrio-p3io.conf", - "--help", - "-h", - "ddrio-p3io", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - ddrio_p3io_config_get(config_ddrio_p3io, config); - - cconfig_finit(config); -} - -bool ddr_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_ddr_init() { HRESULT hr; - _ddr_io_config_init(&_ddr_io_p3io_config); - hr = _ddr_io_p3io_init(&_ddr_io_p3io_handle); if (FAILED(hr)) { @@ -313,7 +274,7 @@ bool ddr_io_init( return true; } -uint32_t ddr_io_read_pad(void) +uint32_t bt_io_ddr_pad_read(void) { HRESULT hr; struct p3io_ddr_jamma jamma; @@ -328,23 +289,29 @@ uint32_t ddr_io_read_pad(void) return _byteswap_ulong(*((uint32_t *) &jamma)); } -void ddr_io_set_lights_extio(uint32_t extio_lights) +void bt_io_ddr_extio_lights_set(uint32_t extio_lights) { HRESULT hr; struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS]; bool neons; - pad_lights[0].up = (extio_lights & (1 << LIGHT_P1_UP)) > 0; - pad_lights[0].down = (extio_lights & (1 << LIGHT_P1_DOWN)) > 0; - pad_lights[0].left = (extio_lights & (1 << LIGHT_P1_LEFT)) > 0; - pad_lights[0].right = (extio_lights & (1 << LIGHT_P1_RIGHT)) > 0; + pad_lights[0].up = (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P1_UP)) > 0; + pad_lights[0].down = + (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P1_DOWN)) > 0; + pad_lights[0].left = + (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P1_LEFT)) > 0; + pad_lights[0].right = + (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P1_RIGHT)) > 0; - pad_lights[1].up = (extio_lights & (1 << LIGHT_P2_UP)) > 0; - pad_lights[1].down = (extio_lights & (1 << LIGHT_P2_DOWN)) > 0; - pad_lights[1].left = (extio_lights & (1 << LIGHT_P2_LEFT)) > 0; - pad_lights[1].right = (extio_lights & (1 << LIGHT_P2_RIGHT)) > 0; + pad_lights[1].up = (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P2_UP)) > 0; + pad_lights[1].down = + (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P2_DOWN)) > 0; + pad_lights[1].left = + (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P2_LEFT)) > 0; + pad_lights[1].right = + (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_P2_RIGHT)) > 0; - neons = (extio_lights & (1 << LIGHT_NEONS)) > 0; + neons = (extio_lights & (1 << BT_IO_DDR_EXTIO_LIGHT_NEONS)) > 0; hr = extiodrv_extio_transfer( _ddr_io_extio_handle, @@ -357,24 +324,24 @@ void ddr_io_set_lights_extio(uint32_t extio_lights) } } -void ddr_io_set_lights_p3io(uint32_t p3io_lights) +void bt_io_ddr_p3io_lights_set(uint32_t p3io_lights) { HRESULT hr; struct p3io_ddr_output output; output.cabinet.top_p1_lower = - (p3io_lights & (1 << LIGHT_P1_LOWER_LAMP)) > 0 ? 1 : 0; + (p3io_lights & (1 << BT_IO_DDR_P3IO_LIGHT_P1_LOWER_LAMP)) > 0 ? 1 : 0; output.cabinet.top_p1_upper = - (p3io_lights & (1 << LIGHT_P1_UPPER_LAMP)) > 0 ? 1 : 0; + (p3io_lights & (1 << BT_IO_DDR_P3IO_LIGHT_P1_UPPER_LAMP)) > 0 ? 1 : 0; output.cabinet.top_p2_lower = - (p3io_lights & (1 << LIGHT_P2_LOWER_LAMP)) > 0 ? 1 : 0; + (p3io_lights & (1 << BT_IO_DDR_P3IO_LIGHT_P2_LOWER_LAMP)) > 0 ? 1 : 0; output.cabinet.top_p2_upper = - (p3io_lights & (1 << LIGHT_P2_UPPER_LAMP)) > 0 ? 1 : 0; + (p3io_lights & (1 << BT_IO_DDR_P3IO_LIGHT_P2_UPPER_LAMP)) > 0 ? 1 : 0; output.cabinet.p1_menu_buttons = - (p3io_lights & (1 << LIGHT_P1_MENU)) > 0 ? 1 : 0; + (p3io_lights & (1 << BT_IO_DDR_P3IO_LIGHT_P1_MENU)) > 0 ? 1 : 0; output.cabinet.p2_menu_buttons = - (p3io_lights & (1 << LIGHT_P2_MENU)) > 0 ? 1 : 0; + (p3io_lights & (1 << BT_IO_DDR_P3IO_LIGHT_P2_MENU)) > 0 ? 1 : 0; hr = p3iodrv_ddr_set_outputs(_ddr_io_p3io_handle, &output); @@ -383,14 +350,14 @@ void ddr_io_set_lights_p3io(uint32_t p3io_lights) } } -void ddr_io_set_lights_hdxs_panel(uint32_t lights) +void bt_io_ddr_hdxs_lights_panel_set(uint32_t lights) { // Unused (void) lights; } -void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +void bt_io_ddr_hdxs_lights_rgb_set(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) { // Unused @@ -400,7 +367,7 @@ void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) (void) b; } -void ddr_io_fini(void) +void bt_io_ddr_fini(void) { HRESULT hr; @@ -425,3 +392,33 @@ void ddr_io_fini(void) // continue } } + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +bool bt_module_configure_do(const bt_core_config_t *config) +{ + ddrio_p3io_config_get(config, &_ddr_io_p3io_config); + + return true; +} + +void bt_module_io_ddr_api_get(bt_io_ddr_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_ddr_init; + api->v1.fini = bt_io_ddr_fini; + api->v1.pad_read = bt_io_ddr_pad_read; + api->v1.extio_lights_set = bt_io_ddr_extio_lights_set; + api->v1.p3io_lights_set = bt_io_ddr_p3io_lights_set; + api->v1.hdxs_lights_panel_set = bt_io_ddr_hdxs_lights_panel_set; + api->v1.hdxs_lights_rgb_set = bt_io_ddr_hdxs_lights_rgb_set; +} \ No newline at end of file diff --git a/src/main/ddrio-smx/Module.mk b/src/main/ddrio-smx/Module.mk index cc0563b2..ba779101 100644 --- a/src/main/ddrio-smx/Module.mk +++ b/src/main/ddrio-smx/Module.mk @@ -5,8 +5,12 @@ deplibs_ddrio-smx := \ SMX \ libs_ddrio-smx := \ + core \ geninput \ util \ + iface-core \ + iface \ + module \ src_ddrio-smx := \ ddrio.c \ diff --git a/src/main/ddrio-smx/ddrio-smx.def b/src/main/ddrio-smx/ddrio-smx.def index 49219de6..243faf40 100644 --- a/src/main/ddrio-smx/ddrio-smx.def +++ b/src/main/ddrio-smx/ddrio-smx.def @@ -1,11 +1,15 @@ LIBRARY ddrio-smx EXPORTS - ddr_io_set_loggers - ddr_io_fini - ddr_io_init - ddr_io_read_pad - ddr_io_set_lights_extio - ddr_io_set_lights_p3io - ddr_io_set_lights_hdxs_panel - ddr_io_set_lights_hdxs_rgb + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_io_ddr_api_get + + ; Direct API + bt_io_ddr_init + bt_io_ddr_fini + bt_io_ddr_pad_read + bt_io_ddr_extio_lights_set + bt_io_ddr_p3io_lights_set + bt_io_ddr_hdxs_lights_panel_set + bt_io_ddr_hdxs_lights_rgb_set diff --git a/src/main/ddrio-smx/ddrio.c b/src/main/ddrio-smx/ddrio.c index a7cda337..9fa46791 100644 --- a/src/main/ddrio-smx/ddrio.c +++ b/src/main/ddrio-smx/ddrio.c @@ -1,16 +1,29 @@ +#define LOG_MODULE "ddrio-smx" + #include #include #include -#include "bemanitools/ddrio.h" -#include "bemanitools/input.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/input.h" #include "imports/SMX.h" #include "imports/avs.h" +#include "main/module/input-ext.h" +#include "main/module/input.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/ddr.h" + #include "util/defs.h" -#include "util/log.h" struct ddr_io_smx_pad_map { int pad_no; @@ -30,15 +43,15 @@ static void ddr_io_smx_callback(int pad_no, enum SMXUpdateCallbackReason reason, void *ctx); static const struct ddr_io_smx_pad_map ddr_io_smx_pad_map[] = { - {0, 1 << 1, 1 << DDR_P1_UP}, - {0, 1 << 3, 1 << DDR_P1_LEFT}, - {0, 1 << 5, 1 << DDR_P1_RIGHT}, - {0, 1 << 7, 1 << DDR_P1_DOWN}, - - {1, 1 << 1, 1 << DDR_P2_UP}, - {1, 1 << 3, 1 << DDR_P2_LEFT}, - {1, 1 << 5, 1 << DDR_P2_RIGHT}, - {1, 1 << 7, 1 << DDR_P2_DOWN}, + {0, 1 << 1, 1 << BT_IO_DDR_P1_UP}, + {0, 1 << 3, 1 << BT_IO_DDR_P1_LEFT}, + {0, 1 << 5, 1 << BT_IO_DDR_P1_RIGHT}, + {0, 1 << 7, 1 << BT_IO_DDR_P1_DOWN}, + + {1, 1 << 1, 1 << BT_IO_DDR_P2_UP}, + {1, 1 << 3, 1 << BT_IO_DDR_P2_LEFT}, + {1, 1 << 5, 1 << BT_IO_DDR_P2_RIGHT}, + {1, 1 << 7, 1 << BT_IO_DDR_P2_DOWN}, }; #define DDR_IO_SMX_LIGHT_VALUES_PER_PANEL 75 @@ -49,39 +62,43 @@ static const struct ddr_io_smx_pad_map ddr_io_smx_pad_map[] = { static const struct ddr_io_smx_light_map ddr_io_smx_light_map[] = { /* Light L/R blue and U/D red to match DDR pad color scheme */ - {1 << LIGHT_P1_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 1, 0xFF, 0x00, 0x00}, - {1 << LIGHT_P1_LEFT, + {1 << BT_IO_DDR_EXTIO_LIGHT_P1_UP, + DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 1, + 0xFF, + 0x00, + 0x00}, + {1 << BT_IO_DDR_EXTIO_LIGHT_P1_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 3, 0x00, 0x00, 0xFF}, - {1 << LIGHT_P1_RIGHT, + {1 << BT_IO_DDR_EXTIO_LIGHT_P1_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 5, 0x00, 0x00, 0xFF}, - {1 << LIGHT_P1_DOWN, + {1 << BT_IO_DDR_EXTIO_LIGHT_P1_DOWN, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 7, 0xFF, 0x00, 0x00}, - {1 << LIGHT_P2_UP, + {1 << BT_IO_DDR_EXTIO_LIGHT_P2_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 10, 0xFF, 0x00, 0x00}, - {1 << LIGHT_P2_LEFT, + {1 << BT_IO_DDR_EXTIO_LIGHT_P2_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 12, 0x00, 0x00, 0xFF}, - {1 << LIGHT_P2_RIGHT, + {1 << BT_IO_DDR_EXTIO_LIGHT_P2_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 14, 0x00, 0x00, 0xFF}, - {1 << LIGHT_P2_DOWN, + {1 << BT_IO_DDR_EXTIO_LIGHT_P2_DOWN, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 16, 0xFF, 0x00, @@ -92,30 +109,24 @@ static _Atomic uint32_t ddr_io_smx_pad_state[2]; static CRITICAL_SECTION ddr_io_smx_lights_lock; static uint8_t ddr_io_smx_lights_counter; static char ddr_io_smx_lights[DDR_IO_SMX_TOTAL_LIGHT_VALUES]; +static module_input_t *_ddr_io_smx_module_input; -void ddr_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +bool bt_io_ddr_init() { - log_to_external(misc, info, warning, fatal); - input_set_loggers(misc, info, warning, fatal); + bool result; + bt_input_api_t input_api; - /* We would need a log server thread to accept log messages from SMX, since - it uses raw Win32 threads and not AVS threads (only AVS threads are - permitted to use the AVS logging API). So it's not really worth it. */ -} - -bool ddr_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) -{ /* Use geninput for menu/operator btns */ + module_input_ext_load_and_init("geninput.dll", &_ddr_io_smx_module_input); + module_input_api_get(_ddr_io_smx_module_input, &input_api); + bt_input_api_set(&input_api); + + result = bt_input_mapper_config_load("ddr"); - input_init(thread_create, thread_join, thread_destroy); - mapper_config_load("ddr"); + if (!result) { + log_warning("Failed loading input mapper config for ddr"); + return false; + } /* Start up SMX API */ @@ -129,7 +140,7 @@ bool ddr_io_init( return true; } -uint32_t ddr_io_read_pad(void) +uint32_t bt_io_ddr_pad_read(void) { /* SMX pads require a constant stream of lighting updates or they will quickly revert to autonomous lighting control. Here is a hacky way of @@ -160,11 +171,11 @@ uint32_t ddr_io_read_pad(void) /* We don't atomically read both pads, but they are separate USB devices so they don't update in lockstep anyway. */ - return mapper_update() | atomic_load(&ddr_io_smx_pad_state[0]) | + return bt_input_mapper_update() | atomic_load(&ddr_io_smx_pad_state[0]) | atomic_load(&ddr_io_smx_pad_state[1]); } -void ddr_io_set_lights_extio(uint32_t lights) +void bt_io_ddr_extio_lights_set(uint32_t lights) { const struct ddr_io_smx_light_map *map; size_t offset; @@ -193,42 +204,46 @@ void ddr_io_set_lights_extio(uint32_t lights) LeaveCriticalSection(&ddr_io_smx_lights_lock); } -void ddr_io_set_lights_p3io(uint32_t lights) +void bt_io_ddr_p3io_lights_set(uint32_t lights) { uint8_t i; for (i = 0x00; i <= 0x07; i++) { - mapper_write_light(i, lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(i, lights & (1 << i) ? 255 : 0); } } -void ddr_io_set_lights_hdxs_panel(uint32_t lights) +void bt_io_ddr_hdxs_lights_panel_set(uint32_t lights) { uint8_t i; for (i = 0x08; i <= 0x0D; i++) { - mapper_write_light(i, lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(i, lights & (1 << i) ? 255 : 0); } } -void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +void bt_io_ddr_hdxs_lights_rgb_set(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) { if (idx < 4) { uint8_t base = 0x20 + idx * 3; - mapper_write_light(base + 0, r); - mapper_write_light(base + 1, g); - mapper_write_light(base + 2, b); + bt_input_mapper_light_write(base + 0, r); + bt_input_mapper_light_write(base + 1, g); + bt_input_mapper_light_write(base + 2, b); } } -void ddr_io_fini(void) +void bt_io_ddr_fini(void) { log_info("Stopping SMX.DLL"); SMX_Stop(); log_info("Stopped SMX.DLL"); DeleteCriticalSection(&ddr_io_smx_lights_lock); - input_fini(); + + bt_input_fini(); + + bt_input_api_clear(); + module_input_free(&_ddr_io_smx_module_input); } static void @@ -256,3 +271,30 @@ ddr_io_smx_callback(int pad_no, enum SMXUpdateCallbackReason reason, void *ctx) atomic_store(&ddr_io_smx_pad_state[pad_no], ddr_state); } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); + + /* We would need a log server thread to accept log messages from SMX, since + it uses raw Win32 threads and not AVS threads (only AVS threads are + permitted to use the AVS logging API). So it's not really worth it. */ +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_ddr_api_get(bt_io_ddr_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_ddr_init; + api->v1.fini = bt_io_ddr_fini; + api->v1.pad_read = bt_io_ddr_pad_read; + api->v1.extio_lights_set = bt_io_ddr_extio_lights_set; + api->v1.p3io_lights_set = bt_io_ddr_p3io_lights_set; + api->v1.hdxs_lights_panel_set = bt_io_ddr_hdxs_lights_panel_set; + api->v1.hdxs_lights_rgb_set = bt_io_ddr_hdxs_lights_rgb_set; +} \ No newline at end of file diff --git a/src/main/ddrio/Module.mk b/src/main/ddrio/Module.mk index 6a25b77a..7b83c94b 100644 --- a/src/main/ddrio/Module.mk +++ b/src/main/ddrio/Module.mk @@ -1,7 +1,11 @@ dlls += ddrio libs_ddrio := \ - geninput \ + module \ + iface-core \ + core \ + iface \ + util \ src_ddrio := \ ddrio.c \ diff --git a/src/main/ddrio/ddrio.c b/src/main/ddrio/ddrio.c index 167b7c6e..9403ad2f 100644 --- a/src/main/ddrio/ddrio.c +++ b/src/main/ddrio/ddrio.c @@ -1,32 +1,53 @@ +#define LOG_MODULE "ddrio" + #include -#include "imports/avs.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/input.h" + +#include "module/input.h" + +#include "main/module/input-ext.h" +#include "main/module/input.h" -#include "bemanitools/input.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/ddr.h" -#include "util/log.h" +static module_input_t *_ddr_io_module_input; -void ddr_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +bool bt_io_ddr_init() { - input_set_loggers(misc, info, warning, fatal); + bool result; + bt_input_api_t input_api; + + module_input_ext_load_and_init("geninput.dll", &_ddr_io_module_input); + module_input_api_get(_ddr_io_module_input, &input_api); + bt_input_api_set(&input_api); + + result = bt_input_init(); + + if (!result) { + return false; + } + + return bt_input_mapper_config_load("ddr"); } -bool ddr_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +void bt_io_ddr_fini() { - input_init(thread_create, thread_join, thread_destroy); - mapper_config_load("ddr"); + bt_input_fini(); - return true; + bt_input_api_clear(); + module_input_free(&_ddr_io_module_input); } -uint32_t ddr_io_read_pad(void) +uint32_t bt_io_ddr_pad_read(void) { /* Sleep first: input is timestamped immediately AFTER the ioctl returns. @@ -36,47 +57,65 @@ uint32_t ddr_io_read_pad(void) Sleep(1); - return (uint32_t) mapper_update(); + return (uint32_t) bt_input_mapper_update(); } -void ddr_io_set_lights_extio(uint32_t lights) +void bt_io_ddr_extio_lights_set(uint32_t lights) { uint8_t i; for (i = 0x0E; i <= 0x1E; i++) { - mapper_write_light(i, lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(i, lights & (1 << i) ? 255 : 0); } } -void ddr_io_set_lights_p3io(uint32_t lights) +void bt_io_ddr_p3io_lights_set(uint32_t lights) { uint8_t i; for (i = 0x00; i <= 0x07; i++) { - mapper_write_light(i, lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(i, lights & (1 << i) ? 255 : 0); } } -void ddr_io_set_lights_hdxs_panel(uint32_t lights) +void bt_io_ddr_hdxs_lights_panel_set(uint32_t lights) { uint8_t i; for (i = 0x08; i <= 0x0D; i++) { - mapper_write_light(i, lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(i, lights & (1 << i) ? 255 : 0); } } -void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +void bt_io_ddr_hdxs_lights_rgb_set(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) { if (idx < 4) { uint8_t base = 0x20 + idx * 3; - mapper_write_light(base + 0, r); - mapper_write_light(base + 1, g); - mapper_write_light(base + 2, b); + bt_input_mapper_light_write(base + 0, r); + bt_input_mapper_light_write(base + 1, g); + bt_input_mapper_light_write(base + 2, b); } } -void ddr_io_fini(void) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - input_fini(); + bt_core_log_api_set(api); } + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_ddr_api_get(bt_io_ddr_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_ddr_init; + api->v1.fini = bt_io_ddr_fini; + api->v1.pad_read = bt_io_ddr_pad_read; + api->v1.extio_lights_set = bt_io_ddr_extio_lights_set; + api->v1.p3io_lights_set = bt_io_ddr_p3io_lights_set; + api->v1.hdxs_lights_panel_set = bt_io_ddr_hdxs_lights_panel_set; + api->v1.hdxs_lights_rgb_set = bt_io_ddr_hdxs_lights_rgb_set; +} \ No newline at end of file diff --git a/src/main/ddrio/ddrio.def b/src/main/ddrio/ddrio.def index bc2129dd..6be152d1 100644 --- a/src/main/ddrio/ddrio.def +++ b/src/main/ddrio/ddrio.def @@ -1,11 +1,16 @@ LIBRARY ddrio EXPORTS - ddr_io_set_loggers - ddr_io_fini - ddr_io_init - ddr_io_read_pad - ddr_io_set_lights_extio - ddr_io_set_lights_p3io - ddr_io_set_lights_hdxs_panel - ddr_io_set_lights_hdxs_rgb + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_ddr_api_get + + ; Direct API + bt_io_ddr_init + bt_io_ddr_fini + bt_io_ddr_pad_read + bt_io_ddr_extio_lights_set + bt_io_ddr_p3io_lights_set + bt_io_ddr_hdxs_lights_panel_set + bt_io_ddr_hdxs_lights_rgb_set diff --git a/src/main/ddriotest/Module.mk b/src/main/ddriotest/Module.mk index 569d9736..77006977 100644 --- a/src/main/ddriotest/Module.mk +++ b/src/main/ddriotest/Module.mk @@ -1,8 +1,11 @@ exes += ddriotest \ libs_ddriotest := \ - ddrio \ + core \ util \ + module \ + iface-core \ + iface-io \ src_ddriotest := \ main.c \ diff --git a/src/main/ddriotest/main.c b/src/main/ddriotest/main.c index e03bc0c4..17e5167c 100644 --- a/src/main/ddriotest/main.c +++ b/src/main/ddriotest/main.c @@ -5,35 +5,58 @@ #include -#include "bemanitools/ddrio.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" +#include "core/thread-crt.h" -#include "util/log.h" -#include "util/thread.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface-io/ddr.h" + +#include "module/io-ext.h" + +static void _ddriotest_io_ddr_init(module_io_t **module) +{ + bt_io_ddr_api_t api; + + module_io_ext_load_and_init( + "ddrio.dll", "bt_module_io_ddr_api_get", module); + module_io_api_get(*module, &api); + bt_io_ddr_api_set(&api); +} int main(int argc, char **argv) { - enum log_level log_level; + enum core_log_bt_log_level log_level; + module_io_t *module_io_ddr; - log_level = LOG_LEVEL_FATAL; + log_level = CORE_LOG_BT_LOG_LEVEL_FATAL; for (int i = 0; i < argc; i++) { if (!strcmp(argv[i], "-v")) { - log_level = LOG_LEVEL_WARNING; + log_level = CORE_LOG_BT_LOG_LEVEL_WARNING; } else if (!strcmp(argv[i], "-vv")) { - log_level = LOG_LEVEL_INFO; + log_level = CORE_LOG_BT_LOG_LEVEL_INFO; } else if (!strcmp(argv[i], "-vvv")) { - log_level = LOG_LEVEL_MISC; + log_level = CORE_LOG_BT_LOG_LEVEL_MISC; } } - log_to_writer(log_writer_stderr, NULL); - log_set_level(log_level); + core_log_bt_core_api_set(); + core_thread_crt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(log_level); - ddr_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _ddriotest_io_ddr_init(&module_io_ddr); - if (!ddr_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) { + if (!bt_io_ddr_init()) { fprintf(stderr, "Initializing ddrio failed\n"); + + bt_io_ddr_api_clear(); + module_io_free(&module_io_ddr); + return -1; } @@ -42,6 +65,11 @@ int main(int argc, char **argv) ">>> Initializing ddrio successful, press enter to continue <<<\n"); if (getchar() != '\n') { + bt_io_ddr_fini(); + + bt_io_ddr_api_clear(); + module_io_free(&module_io_ddr); + return 0; } @@ -56,10 +84,10 @@ int main(int argc, char **argv) uint8_t cnt = 0; while (loop) { - ddr_io_set_lights_extio(extio_lights); - ddr_io_set_lights_p3io(p3io_lights); + bt_io_ddr_extio_lights_set(extio_lights); + bt_io_ddr_p3io_lights_set(p3io_lights); - pad = ddr_io_read_pad(); + pad = bt_io_ddr_pad_read(); system("cls"); @@ -70,116 +98,116 @@ int main(int argc, char **argv) printf( "Up: %d Up: %d\n", - (pad & (1 << DDR_P1_UP)) > 0, - (pad & (1 << DDR_P2_UP)) > 0); + (pad & (1 << BT_IO_DDR_P1_UP)) > 0, + (pad & (1 << BT_IO_DDR_P2_UP)) > 0); printf( "Down: %d Down: %d\n", - (pad & (1 << DDR_P1_DOWN)) > 0, - (pad & (1 << DDR_P2_DOWN)) > 0); + (pad & (1 << BT_IO_DDR_P1_DOWN)) > 0, + (pad & (1 << BT_IO_DDR_P2_DOWN)) > 0); printf( "Left: %d Left: %d\n", - (pad & (1 << DDR_P1_LEFT)) > 0, - (pad & (1 << DDR_P2_LEFT)) > 0); + (pad & (1 << BT_IO_DDR_P1_LEFT)) > 0, + (pad & (1 << BT_IO_DDR_P2_LEFT)) > 0); printf( "Right: %d Right: %d\n", - (pad & (1 << DDR_P1_RIGHT)) > 0, - (pad & (1 << DDR_P2_RIGHT)) > 0); + (pad & (1 << BT_IO_DDR_P1_RIGHT)) > 0, + (pad & (1 << BT_IO_DDR_P2_RIGHT)) > 0); printf("\n"); printf("Menu\n"); printf( "Start: %d Start: %d\n", - (pad & (1 << DDR_P1_START)) > 0, - (pad & (1 << DDR_P2_START)) > 0); + (pad & (1 << BT_IO_DDR_P1_START)) > 0, + (pad & (1 << BT_IO_DDR_P2_START)) > 0); printf( "Up: %d Up: %d\n", - (pad & (1 << DDR_P1_MENU_UP)) > 0, - (pad & (1 << DDR_P2_MENU_UP)) > 0); + (pad & (1 << BT_IO_DDR_P1_MENU_UP)) > 0, + (pad & (1 << BT_IO_DDR_P2_MENU_UP)) > 0); printf( "Down: %d Down: %d\n", - (pad & (1 << DDR_P1_MENU_DOWN)) > 0, - (pad & (1 << DDR_P2_MENU_DOWN)) > 0); + (pad & (1 << BT_IO_DDR_P1_MENU_DOWN)) > 0, + (pad & (1 << BT_IO_DDR_P2_MENU_DOWN)) > 0); printf( "Left: %d Left: %d\n", - (pad & (1 << DDR_P1_MENU_LEFT)) > 0, - (pad & (1 << DDR_P2_MENU_LEFT)) > 0); + (pad & (1 << BT_IO_DDR_P1_MENU_LEFT)) > 0, + (pad & (1 << BT_IO_DDR_P2_MENU_LEFT)) > 0); printf( "Right: %d Right: %d\n", - (pad & (1 << DDR_P1_MENU_RIGHT)) > 0, - (pad & (1 << DDR_P2_MENU_RIGHT)) > 0); + (pad & (1 << BT_IO_DDR_P1_MENU_RIGHT)) > 0, + (pad & (1 << BT_IO_DDR_P2_MENU_RIGHT)) > 0); printf("\n"); printf("Operator\n"); printf( "Test: %d Service: %d Coin: %d\n", - (pad & (1 << DDR_TEST)) > 0, - (pad & (1 << DDR_SERVICE)) > 0, - (pad & (1 << DDR_COIN)) > 0); + (pad & (1 << BT_IO_DDR_TEST)) > 0, + (pad & (1 << BT_IO_DDR_SERVICE)) > 0, + (pad & (1 << BT_IO_DDR_COIN)) > 0); - if ((pad & (1 << DDR_P1_UP)) > 0) { - extio_lights |= (1 << LIGHT_P1_UP); + if ((pad & (1 << BT_IO_DDR_P1_UP)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P1_UP); } else { - extio_lights &= ~(1 << LIGHT_P1_UP); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P1_UP); } - if ((pad & (1 << DDR_P1_DOWN)) > 0) { - extio_lights |= (1 << LIGHT_P1_DOWN); + if ((pad & (1 << BT_IO_DDR_P1_DOWN)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P1_DOWN); } else { - extio_lights &= ~(1 << LIGHT_P1_DOWN); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P1_DOWN); } - if ((pad & (1 << DDR_P1_LEFT)) > 0) { - extio_lights |= (1 << LIGHT_P1_LEFT); + if ((pad & (1 << BT_IO_DDR_P1_LEFT)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P1_LEFT); } else { - extio_lights &= ~(1 << LIGHT_P1_LEFT); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P1_LEFT); } - if ((pad & (1 << DDR_P1_RIGHT)) > 0) { - extio_lights |= (1 << LIGHT_P1_RIGHT); + if ((pad & (1 << BT_IO_DDR_P1_RIGHT)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P1_RIGHT); } else { - extio_lights &= ~(1 << LIGHT_P1_RIGHT); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P1_RIGHT); } - if ((pad & (1 << DDR_P2_UP)) > 0) { - extio_lights |= (1 << LIGHT_P2_UP); + if ((pad & (1 << BT_IO_DDR_P2_UP)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P2_UP); } else { - extio_lights &= ~(1 << LIGHT_P2_UP); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P2_UP); } - if ((pad & (1 << DDR_P2_DOWN)) > 0) { - extio_lights |= (1 << LIGHT_P2_DOWN); + if ((pad & (1 << BT_IO_DDR_P2_DOWN)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P2_DOWN); } else { - extio_lights &= ~(1 << LIGHT_P2_DOWN); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P2_DOWN); } - if ((pad & (1 << DDR_P2_LEFT)) > 0) { - extio_lights |= (1 << LIGHT_P2_LEFT); + if ((pad & (1 << BT_IO_DDR_P2_LEFT)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P2_LEFT); } else { - extio_lights &= ~(1 << LIGHT_P2_LEFT); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P2_LEFT); } - if ((pad & (1 << DDR_P2_RIGHT)) > 0) { - extio_lights |= (1 << LIGHT_P2_RIGHT); + if ((pad & (1 << BT_IO_DDR_P2_RIGHT)) > 0) { + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_P2_RIGHT); } else { - extio_lights &= ~(1 << LIGHT_P2_RIGHT); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_P2_RIGHT); } - if ((pad & (1 << DDR_P1_START)) > 0 || - (pad & (1 << DDR_P1_MENU_UP)) > 0 || - (pad & (1 << DDR_P1_MENU_DOWN)) > 0 || - (pad & (1 << DDR_P1_MENU_LEFT)) > 0 || - (pad & (1 << DDR_P1_MENU_RIGHT)) > 0) { - p3io_lights |= (1 << LIGHT_P1_MENU); + if ((pad & (1 << BT_IO_DDR_P1_START)) > 0 || + (pad & (1 << BT_IO_DDR_P1_MENU_UP)) > 0 || + (pad & (1 << BT_IO_DDR_P1_MENU_DOWN)) > 0 || + (pad & (1 << BT_IO_DDR_P1_MENU_LEFT)) > 0 || + (pad & (1 << BT_IO_DDR_P1_MENU_RIGHT)) > 0) { + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P1_MENU); } else { - p3io_lights &= ~(1 << LIGHT_P1_MENU); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P1_MENU); } - if ((pad & (1 << DDR_P2_START)) > 0 || - (pad & (1 << DDR_P2_MENU_UP)) > 0 || - (pad & (1 << DDR_P2_MENU_DOWN)) > 0 || - (pad & (1 << DDR_P2_MENU_LEFT)) > 0 || - (pad & (1 << DDR_P2_MENU_RIGHT)) > 0) { - p3io_lights |= (1 << LIGHT_P2_MENU); + if ((pad & (1 << BT_IO_DDR_P2_START)) > 0 || + (pad & (1 << BT_IO_DDR_P2_MENU_UP)) > 0 || + (pad & (1 << BT_IO_DDR_P2_MENU_DOWN)) > 0 || + (pad & (1 << BT_IO_DDR_P2_MENU_LEFT)) > 0 || + (pad & (1 << BT_IO_DDR_P2_MENU_RIGHT)) > 0) { + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P2_MENU); } else { - p3io_lights &= ~(1 << LIGHT_P2_MENU); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P2_MENU); } /* avoid CPU banging */ @@ -217,9 +245,9 @@ int main(int argc, char **argv) n = scanf("%d", &state); if (n > 0) { - extio_lights |= (1 << LIGHT_NEONS); + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_NEONS); } else { - extio_lights &= ~(1 << LIGHT_NEONS); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_NEONS); } break; @@ -235,27 +263,35 @@ int main(int argc, char **argv) if (n > 0) { if (buf[0] == '1') { - p3io_lights |= (1 << LIGHT_P1_UPPER_LAMP); + p3io_lights |= + (1 << BT_IO_DDR_P3IO_LIGHT_P1_UPPER_LAMP); } else { - p3io_lights &= ~(1 << LIGHT_P1_UPPER_LAMP); + p3io_lights &= + ~(1 << BT_IO_DDR_P3IO_LIGHT_P1_UPPER_LAMP); } if (buf[1] == '1') { - p3io_lights |= (1 << LIGHT_P1_LOWER_LAMP); + p3io_lights |= + (1 << BT_IO_DDR_P3IO_LIGHT_P1_LOWER_LAMP); } else { - p3io_lights &= ~(1 << LIGHT_P1_LOWER_LAMP); + p3io_lights &= + ~(1 << BT_IO_DDR_P3IO_LIGHT_P1_LOWER_LAMP); } if (buf[2] == '1') { - p3io_lights |= (1 << LIGHT_P2_UPPER_LAMP); + p3io_lights |= + (1 << BT_IO_DDR_P3IO_LIGHT_P2_UPPER_LAMP); } else { - p3io_lights &= ~(1 << LIGHT_P2_UPPER_LAMP); + p3io_lights &= + ~(1 << BT_IO_DDR_P3IO_LIGHT_P2_UPPER_LAMP); } if (buf[3] == '1') { - p3io_lights |= (1 << LIGHT_P2_LOWER_LAMP); + p3io_lights |= + (1 << BT_IO_DDR_P3IO_LIGHT_P2_LOWER_LAMP); } else { - p3io_lights &= ~(1 << LIGHT_P2_LOWER_LAMP); + p3io_lights &= + ~(1 << BT_IO_DDR_P3IO_LIGHT_P2_LOWER_LAMP); } } @@ -263,27 +299,27 @@ int main(int argc, char **argv) } case '4': { - extio_lights |= (1 << LIGHT_NEONS); + extio_lights |= (1 << BT_IO_DDR_EXTIO_LIGHT_NEONS); - p3io_lights |= (1 << LIGHT_P1_MENU); - p3io_lights |= (1 << LIGHT_P2_MENU); - p3io_lights |= (1 << LIGHT_P1_UPPER_LAMP); - p3io_lights |= (1 << LIGHT_P1_LOWER_LAMP); - p3io_lights |= (1 << LIGHT_P2_UPPER_LAMP); - p3io_lights |= (1 << LIGHT_P2_LOWER_LAMP); + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P1_MENU); + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P2_MENU); + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P1_UPPER_LAMP); + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P1_LOWER_LAMP); + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P2_UPPER_LAMP); + p3io_lights |= (1 << BT_IO_DDR_P3IO_LIGHT_P2_LOWER_LAMP); break; } case '5': { - extio_lights &= ~(1 << LIGHT_NEONS); + extio_lights &= ~(1 << BT_IO_DDR_EXTIO_LIGHT_NEONS); - p3io_lights &= ~(1 << LIGHT_P1_MENU); - p3io_lights &= ~(1 << LIGHT_P2_MENU); - p3io_lights &= ~(1 << LIGHT_P1_UPPER_LAMP); - p3io_lights &= ~(1 << LIGHT_P1_LOWER_LAMP); - p3io_lights &= ~(1 << LIGHT_P2_UPPER_LAMP); - p3io_lights &= ~(1 << LIGHT_P2_LOWER_LAMP); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P1_MENU); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P2_MENU); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P1_UPPER_LAMP); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P1_LOWER_LAMP); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P2_UPPER_LAMP); + p3io_lights &= ~(1 << BT_IO_DDR_P3IO_LIGHT_P2_LOWER_LAMP); break; } @@ -297,7 +333,10 @@ int main(int argc, char **argv) system("cls"); - ddr_io_fini(); + bt_io_ddr_fini(); + + bt_io_ddr_api_clear(); + module_io_free(&module_io_ddr); return 0; } \ No newline at end of file diff --git a/src/main/dinput/dinput.c b/src/main/dinput/dinput.c index 248ead4a..5486a6bb 100644 --- a/src/main/dinput/dinput.c +++ b/src/main/dinput/dinput.c @@ -12,8 +12,9 @@ #include "hook/pe.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" static HRESULT STDCALL my_DirectInput8Create( HINSTANCE hinst, diff --git a/src/main/eamio-icca/Module.mk b/src/main/eamio-icca/Module.mk index 28c388e5..c53eaf3f 100644 --- a/src/main/eamio-icca/Module.mk +++ b/src/main/eamio-icca/Module.mk @@ -2,11 +2,13 @@ dlls += \ eamio-icca \ libs_eamio-icca := \ + core \ aciodrv \ - aciomgr \ - cconfig \ util \ + iface-core \ + iface-acio \ + module \ src_eamio-icca := \ - config-icc.c \ - eamio-icca.c \ + config.c \ + eamio.c \ diff --git a/src/main/eamio-icca/config-icc.c b/src/main/eamio-icca/config-icc.c deleted file mode 100644 index 660c0ee1..00000000 --- a/src/main/eamio-icca/config-icc.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "cconfig/cconfig-util.h" - -#include "eamio-icca/config-icc.h" - -#include "util/log.h" - -#define EAMIO_ICCA_CONFIG_ICC_PORT_KEY "icc.port" -#define EAMIO_ICCA_CONFIG_ICC_BAUD_KEY "icc.baud" - -#define EAMIO_ICCA_CONFIG_ICC_DEFAULT_PORT_VALUE "COM1" -#define EAMIO_ICCA_CONFIG_ICC_DEFAULT_BAUD_VALUE 57600 - -void eamio_icca_config_icc_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - EAMIO_ICCA_CONFIG_ICC_PORT_KEY, - EAMIO_ICCA_CONFIG_ICC_DEFAULT_PORT_VALUE, - "ICCA serial port"); - - cconfig_util_set_int( - config, - EAMIO_ICCA_CONFIG_ICC_BAUD_KEY, - EAMIO_ICCA_CONFIG_ICC_DEFAULT_BAUD_VALUE, - "ICCA bus baudrate (real devices expect 57600)"); -} - -void eamio_icca_config_icc_get( - struct icc_config *config_icc, struct cconfig *config) -{ - if (!cconfig_util_get_str( - config, - EAMIO_ICCA_CONFIG_ICC_PORT_KEY, - config_icc->port, - sizeof(config_icc->port) - 1, - EAMIO_ICCA_CONFIG_ICC_DEFAULT_PORT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - EAMIO_ICCA_CONFIG_ICC_PORT_KEY, - EAMIO_ICCA_CONFIG_ICC_DEFAULT_PORT_VALUE); - } - - if (!cconfig_util_get_int( - config, - EAMIO_ICCA_CONFIG_ICC_BAUD_KEY, - &config_icc->baud, - EAMIO_ICCA_CONFIG_ICC_DEFAULT_BAUD_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - EAMIO_ICCA_CONFIG_ICC_BAUD_KEY, - EAMIO_ICCA_CONFIG_ICC_DEFAULT_BAUD_VALUE); - } -} diff --git a/src/main/eamio-icca/config-icc.h b/src/main/eamio-icca/config-icc.h deleted file mode 100644 index c1219a46..00000000 --- a/src/main/eamio-icca/config-icc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef EAMIO_ICCA_CONFIG_ICC_H -#define EAMIO_ICCA_CONFIG_ICC_H - -#include - -#include "cconfig/cconfig.h" - -struct icc_config { - char port[64]; - int32_t baud; -}; - -void eamio_icca_config_icc_init(struct cconfig *config); - -void eamio_icca_config_icc_get( - struct icc_config *config_icc, struct cconfig *config); - -#endif diff --git a/src/main/eamio-icca/config.c b/src/main/eamio-icca/config.c new file mode 100644 index 00000000..f365d77c --- /dev/null +++ b/src/main/eamio-icca/config.c @@ -0,0 +1,10 @@ +#include "core/config-ext.h" + +#include "eamio-icca/config.h" + +void eamio_icca_config_icc_get( + const bt_core_config_t *config, icc_config_t *config_out) +{ + bt_core_config_str_get(config, "port", config_out->port, sizeof(config_out->port)); + bt_core_config_s32_get(config, "baud", &config_out->baud); +} \ No newline at end of file diff --git a/src/main/eamio-icca/config.h b/src/main/eamio-icca/config.h new file mode 100644 index 00000000..a1fff410 --- /dev/null +++ b/src/main/eamio-icca/config.h @@ -0,0 +1,14 @@ +#ifndef EAMIO_ICCA_CONFIG_ICC_H +#define EAMIO_ICCA_CONFIG_ICC_H + +#include "api/core/config.h" + +typedef struct icc_config { + char port[64]; + int32_t baud; +} icc_config_t; + +void eamio_icca_config_icc_get( + const bt_core_config_t *config, icc_config_t *config_out); + +#endif diff --git a/src/main/eamio-icca/eamio-icca.def b/src/main/eamio-icca/eamio-icca.def index 38a70304..208d9d58 100644 --- a/src/main/eamio-icca/eamio-icca.def +++ b/src/main/eamio-icca/eamio-icca.def @@ -1,12 +1,18 @@ LIBRARY eamio-icca EXPORTS - eam_io_fini - eam_io_init - eam_io_get_config_api - eam_io_get_keypad_state - eam_io_get_sensor_state - eam_io_read_card - eam_io_card_slot_cmd - eam_io_set_loggers - eam_io_poll + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_configure_do + bt_module_io_eam_api_get + + ; Direct API + bt_io_eam_init + bt_io_eam_fini + bt_io_eam_keypad_state_get + bt_io_eam_sensor_state_get + bt_io_eam_card_read + bt_io_eam_card_slot_cmd_send + bt_io_eam_poll + bt_io_eam_config_api_get diff --git a/src/main/eamio-icca/eamio-icca.c b/src/main/eamio-icca/eamio.c similarity index 59% rename from src/main/eamio-icca/eamio-icca.c rename to src/main/eamio-icca/eamio.c index c681610e..423ae3cf 100644 --- a/src/main/eamio-icca/eamio-icca.c +++ b/src/main/eamio-icca/eamio.c @@ -10,40 +10,49 @@ #include "aciodrv/device.h" #include "aciodrv/icca.h" -#include "aciomgr/manager.h" -#include "bemanitools/eamio.h" +#include "api/core/config.h" +#include "api/core/log.h" -#include "cconfig/cconfig-main.h" -#include "eamio-icca/config-icc.h" +#include "eamio-icca/config.h" -#include "util/log.h" +#include "iface-acio/mgr.h" +#include "iface-core/config.h" +#include "iface-core/log.h" + +#include "module/acio-mgr.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/io/eam.h" #define IDLE_RESPONSES_BETWEEN_FELICA_POLLS 5 #define NUMBER_OF_EMULATED_READERS 2 #define INVALID_NODE_ID -1 static const uint8_t eam_io_keypad_mappings[16] = { - EAM_IO_KEYPAD_DECIMAL, - EAM_IO_KEYPAD_3, - EAM_IO_KEYPAD_6, - EAM_IO_KEYPAD_9, + BT_IO_EAM_KEYPAD_SCAN_CODE_DECIMAL, + BT_IO_EAM_KEYPAD_SCAN_CODE_3, + BT_IO_EAM_KEYPAD_SCAN_CODE_6, + BT_IO_EAM_KEYPAD_SCAN_CODE_9, 0xFF, 0xFF, 0xFF, 0xFF, - EAM_IO_KEYPAD_0, - EAM_IO_KEYPAD_1, - EAM_IO_KEYPAD_4, - EAM_IO_KEYPAD_7, - EAM_IO_KEYPAD_00, - EAM_IO_KEYPAD_2, - EAM_IO_KEYPAD_5, - EAM_IO_KEYPAD_8}; + BT_IO_EAM_KEYPAD_SCAN_CODE_0, + BT_IO_EAM_KEYPAD_SCAN_CODE_1, + BT_IO_EAM_KEYPAD_SCAN_CODE_4, + BT_IO_EAM_KEYPAD_SCAN_CODE_7, + BT_IO_EAM_KEYPAD_SCAN_CODE_00, + BT_IO_EAM_KEYPAD_SCAN_CODE_2, + BT_IO_EAM_KEYPAD_SCAN_CODE_5, + BT_IO_EAM_KEYPAD_SCAN_CODE_8}; + +static icc_config_t _eamio_icca_config; static struct ac_io_icca_state eam_io_icca_state[NUMBER_OF_EMULATED_READERS]; -static struct aciomgr_port_dispatcher *acio_manager_ctx; +static bt_acio_mgr_port_dispatcher_t *acio_manager_ctx; static int32_t icca_node_id[NUMBER_OF_EMULATED_READERS]; @@ -52,75 +61,55 @@ static bool icca_is_slotted[NUMBER_OF_EMULATED_READERS]; static int32_t icca_poll_counter[NUMBER_OF_EMULATED_READERS]; static uint8_t icca_last_nonbusy_state[NUMBER_OF_EMULATED_READERS]; -void eam_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +static module_acio_mgr_t *_icca_module_acio_mgr; + +static void _bt_io_eam_icca_acio_mgr_init(module_acio_mgr_t **module) { - aciomgr_set_loggers(misc, info, warning, fatal); + bt_acio_mgr_api_t api; - log_to_external(misc, info, warning, fatal); + module_acio_mgr_load("acio-mgr.dll", module); + module_acio_mgr_api_get(*module, &api); + bt_acio_mgr_api_set(&api); } // all of these are referred to internally as ICCA static bool check_if_icca(int node_id) { - char product[ACIOMGR_NODE_PRODUCT_CODE_LEN]; - aciomgr_get_node_product_ident(acio_manager_ctx, node_id, product); + char product[BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN]; + bt_acio_mgr_node_product_ident_get(acio_manager_ctx, node_id, product); - if (!memcmp(product, "ICCA", ACIOMGR_NODE_PRODUCT_CODE_LEN)) { + if (!memcmp(product, "ICCA", BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN)) { return true; } - if (!memcmp(product, "ICCB", ACIOMGR_NODE_PRODUCT_CODE_LEN)) { + if (!memcmp(product, "ICCB", BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN)) { return true; } - if (!memcmp(product, "ICCC", ACIOMGR_NODE_PRODUCT_CODE_LEN)) { + if (!memcmp(product, "ICCC", BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN)) { return true; } return false; } -bool eam_io_init( - thread_create_t create, thread_join_t join, thread_destroy_t destroy) +bool bt_io_eam_init() { - struct cconfig *config; - struct icc_config config_icc; - - config = cconfig_init(); - - eamio_icca_config_icc_init(config); - - if (!cconfig_main_config_init( - config, - "--icc-config", - "eamio-icc.conf", - "--help", - "-h", - "eamio-icca", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } + _bt_io_eam_icca_acio_mgr_init(&_icca_module_acio_mgr); - eamio_icca_config_icc_get(&config_icc, config); - - cconfig_finit(config); - - acio_manager_ctx = aciomgr_port_init(config_icc.port, config_icc.baud); + acio_manager_ctx = bt_acio_mgr_port_init(_eamio_icca_config.port, _eamio_icca_config.baud); if (acio_manager_ctx == NULL) { - log_warning("Opening acio device on %s failed", config_icc.port); + log_warning("Opening acio device on %s failed", _eamio_icca_config.port); return false; } - struct aciodrv_device_ctx *device = aciomgr_port_checkout(acio_manager_ctx); + bt_acio_drv_device_ctx_t *device = + bt_acio_mgr_port_checkout(acio_manager_ctx); for (uint8_t i = 0; i < NUMBER_OF_EMULATED_READERS; i++) { icca_node_id[i] = INVALID_NODE_ID; - for (uint8_t nid = 0; nid < aciomgr_get_node_count(acio_manager_ctx); + for (uint8_t nid = 0; + nid < bt_acio_mgr_node_count_get(acio_manager_ctx); ++nid) { if (check_if_icca(nid)) { bool existing_reader = false; @@ -160,16 +149,19 @@ bool eam_io_init( return false; } - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkin(acio_manager_ctx); return true; } -void eam_io_fini(void) +void bt_io_eam_fini(void) { - aciomgr_port_fini(acio_manager_ctx); + bt_acio_mgr_port_fini(acio_manager_ctx); + + bt_acio_mgr_api_clear(); + module_acio_mgr_free(&_icca_module_acio_mgr); } -uint16_t eam_io_get_keypad_state(uint8_t unit_no) +uint16_t bt_io_eam_keypad_state_get(uint8_t unit_no) { uint16_t keypad_result = 0; @@ -184,18 +176,18 @@ uint16_t eam_io_get_keypad_state(uint8_t unit_no) return keypad_result; } -uint8_t eam_io_get_sensor_state(uint8_t unit_no) +uint8_t bt_io_eam_sensor_state_get(uint8_t unit_no) { uint8_t sensors = 0; if (icca_is_slotted[unit_no]) { if ((eam_io_icca_state[unit_no].sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) > 0) { - sensors |= (1 << EAM_IO_SENSOR_BACK); + sensors |= (1 << BT_IO_EAM_SENSOR_STATE_BACK); } if ((eam_io_icca_state[unit_no].sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON) > 0) { - sensors |= (1 << EAM_IO_SENSOR_FRONT); + sensors |= (1 << BT_IO_EAM_SENSOR_STATE_FRONT); } } else { // wavepass readers always report (EAM_IO_SENSOR_BACK + @@ -205,8 +197,8 @@ uint8_t eam_io_get_sensor_state(uint8_t unit_no) // reader so the emulation takes card of it if (eam_io_icca_state[unit_no].status_code == AC_IO_ICCA_STATUS_GOT_UID) { - sensors |= (1 << EAM_IO_SENSOR_BACK); - sensors |= (1 << EAM_IO_SENSOR_FRONT); + sensors |= (1 << BT_IO_EAM_SENSOR_STATE_BACK); + sensors |= (1 << BT_IO_EAM_SENSOR_STATE_FRONT); } // continue reporting last state during busy @@ -221,17 +213,17 @@ uint8_t eam_io_get_sensor_state(uint8_t unit_no) return sensors; } -uint8_t eam_io_read_card(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes) +uint8_t bt_io_eam_card_read(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes) { memcpy(card_id, eam_io_icca_state[unit_no].uid, nbytes); if (card_id[0] == 0xe0 && card_id[1] == 0x04) { - return EAM_IO_CARD_ISO15696; + return BT_IO_EAM_READ_CARD_RESULT_ISO15696; } else { - return EAM_IO_CARD_FELICA; + return BT_IO_EAM_READ_CARD_RESULT_FELICA; } } -bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd) +bool bt_io_eam_card_slot_cmd_send(uint8_t unit_no, uint8_t cmd) { // this node is not setup, just return "success"" if (icca_node_id[unit_no] == INVALID_NODE_ID) { @@ -243,32 +235,33 @@ bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd) return true; } - struct aciodrv_device_ctx *device = aciomgr_port_checkout(acio_manager_ctx); + struct aciodrv_device_ctx *device = + bt_acio_mgr_port_checkout(acio_manager_ctx); bool response = false; switch (cmd) { - case EAM_IO_CARD_SLOT_CMD_CLOSE: + case BT_IO_EAM_CARD_SLOT_CMD_CLOSE: response = aciodrv_icca_set_state( device, icca_node_id[unit_no], AC_IO_ICCA_SLOT_STATE_CLOSE, NULL); - case EAM_IO_CARD_SLOT_CMD_OPEN: + case BT_IO_EAM_CARD_SLOT_CMD_OPEN: response = aciodrv_icca_set_state( device, icca_node_id[unit_no], AC_IO_ICCA_SLOT_STATE_OPEN, NULL); - case EAM_IO_CARD_SLOT_CMD_EJECT: + case BT_IO_EAM_CARD_SLOT_CMD_EJECT: response = aciodrv_icca_set_state( device, icca_node_id[unit_no], AC_IO_ICCA_SLOT_STATE_EJECT, NULL); - case EAM_IO_CARD_SLOT_CMD_READ: + case BT_IO_EAM_CARD_SLOT_CMD_READ: response = aciodrv_icca_read_card(device, icca_node_id[unit_no], NULL) && aciodrv_icca_get_state( @@ -277,12 +270,12 @@ bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd) default: break; } - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkin(acio_manager_ctx); return response; } -bool eam_io_poll(uint8_t unit_no) +bool bt_io_eam_poll(uint8_t unit_no) { // this node is not setup, just return "success"" if (icca_node_id[unit_no] == INVALID_NODE_ID) { @@ -290,10 +283,10 @@ bool eam_io_poll(uint8_t unit_no) } bool response = aciodrv_icca_get_state( - aciomgr_port_checkout(acio_manager_ctx), + bt_acio_mgr_port_checkout(acio_manager_ctx), icca_node_id[unit_no], &eam_io_icca_state[unit_no]); - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkin(acio_manager_ctx); if (response && !icca_is_slotted[unit_no]) { // we handle wavepass a bit differently to handle polling felica @@ -308,8 +301,9 @@ bool eam_io_poll(uint8_t unit_no) // the last AC_IO_ICCA_STATUS_BUSY_NEW message if (icca_poll_counter[unit_no] >= IDLE_RESPONSES_BETWEEN_FELICA_POLLS) { response = aciodrv_icca_poll_felica( - aciomgr_port_checkout(acio_manager_ctx), icca_node_id[unit_no]); - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkout(acio_manager_ctx), + icca_node_id[unit_no]); + bt_acio_mgr_port_checkin(acio_manager_ctx); icca_poll_counter[unit_no] = 0; } @@ -318,12 +312,38 @@ bool eam_io_poll(uint8_t unit_no) return response; } -const struct eam_io_config_api *eam_io_get_config_api(void) +const bt_io_eam_config_api_t *bt_io_eam_config_api_get(void) { return NULL; } -BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *ctx) +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - return TRUE; + bt_core_log_api_set(api); } + +bool bt_module_configure_do(const bt_core_config_t *config) +{ + eamio_icca_config_icc_get(config, &_eamio_icca_config); + + return true; +} + +void bt_module_io_eam_api_get(bt_io_eam_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_eam_init; + api->v1.fini = bt_io_eam_fini; + api->v1.keypad_state_get = bt_io_eam_keypad_state_get; + api->v1.sensor_state_get = bt_io_eam_sensor_state_get; + api->v1.card_read = bt_io_eam_card_read; + api->v1.card_slot_cmd_send = bt_io_eam_card_slot_cmd_send; + api->v1.poll = bt_io_eam_poll; + api->v1.config_api_get = bt_io_eam_config_api_get; +} \ No newline at end of file diff --git a/src/main/eamio/Module.mk b/src/main/eamio/Module.mk index f7a7409c..89edd195 100644 --- a/src/main/eamio/Module.mk +++ b/src/main/eamio/Module.mk @@ -1,5 +1,5 @@ dlls += eamio -libs_eamio := geninput util +libs_eamio := iface-core iface core geninput util module src_eamio := \ eam-api.c \ eam-impl.c \ diff --git a/src/main/eamio/eam-api.c b/src/main/eamio/eam-api.c index 03203173..5ca6d068 100644 --- a/src/main/eamio/eam-api.c +++ b/src/main/eamio/eam-api.c @@ -8,17 +8,29 @@ #include #include -#include "bemanitools/eamio.h" -#include "bemanitools/input.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/input.h" + +#include "module/input.h" + +#include "main/module/input-ext.h" +#include "main/module/input.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/eam.h" #include "eamio/eam-config.h" #include "eamio/eam-impl.h" #include "eamio/eam-s11n.h" #include "util/fs.h" -#include "util/log.h" #include "util/msg-thread.h" -#include "util/thread.h" static void eam_handle_hotplug_msg(WPARAM wparam, const DEV_BROADCAST_HDR *hdr); static FILE *eam_io_config_open(const char *mode); @@ -33,10 +45,11 @@ static void eam_io_set_keypad_device(uint8_t unit_no, struct hid_stub *hid); static const char *eam_io_get_card_path(uint8_t unit_no); static void eam_io_set_card_path(uint8_t unit_no, const char *path); +static module_input_t *_eam_io_module_input; static HANDLE eam_hinst; static struct eam *eam_inst; -static const struct eam_io_config_api eam_io_config_api = { +static const struct bt_io_eam_config_api eam_io_config_api = { .config_save = eam_io_config_save, .get_autogen = eam_io_get_autogen, .set_autogen = eam_io_set_autogen, @@ -102,20 +115,21 @@ static FILE *eam_io_config_open(const char *mode) return fopen_appdata("DJHACKERS", "eam_v4_22.bin", mode); } -void eam_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +bool bt_io_eam_init() { - log_to_external(misc, info, warning, fatal); -} + bool result; + bt_input_api_t input_api; + + module_input_ext_load_and_init("geninput.dll", &_eam_io_module_input); + module_input_api_get(_eam_io_module_input, &input_api); + bt_input_api_set(&input_api); + + result = bt_input_init(); + + if (!result) { + return false; + } -bool eam_io_init( - thread_create_t create, thread_join_t join, thread_destroy_t destroy) -{ - input_init(create, join, destroy); - thread_api_init(create, join, destroy); eam_io_config_load(); msg_thread_init(eam_hinst); @@ -156,14 +170,16 @@ static void eam_io_config_load(void) eam_inst = eam_impl_create(); } -void eam_io_fini(void) +void bt_io_eam_fini(void) { msg_thread_fini(); eam_impl_destroy(eam_inst); - input_fini(); + + bt_input_api_clear(); + module_input_free(&_eam_io_module_input); } -const struct eam_io_config_api *eam_io_get_config_api(void) +const bt_io_eam_config_api_t *bt_io_eam_config_api_get(void) { return &eam_io_config_api; } @@ -222,37 +238,62 @@ static void eam_io_set_card_path(uint8_t unit_no, const char *path) eam_impl_set_card_path(eam_inst, unit_no, path); } -uint16_t eam_io_get_keypad_state(uint8_t unit_no) +uint16_t bt_io_eam_keypad_state_get(uint8_t unit_no) { return eam_impl_get_keypad_state(eam_inst, unit_no); } -uint8_t eam_io_get_sensor_state(uint8_t unit_no) +uint8_t bt_io_eam_sensor_state_get(uint8_t unit_no) { if (eam_impl_get_sensor_state(eam_inst, unit_no)) { - return (1 << EAM_IO_SENSOR_FRONT) | (1 << EAM_IO_SENSOR_BACK); + return (1 << BT_IO_EAM_SENSOR_STATE_FRONT) | + (1 << BT_IO_EAM_SENSOR_STATE_BACK); } else { return 0x00; } } -uint8_t eam_io_read_card(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes) +uint8_t bt_io_eam_card_read(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes) { return eam_impl_read_card(eam_inst, unit_no, card_id, nbytes); } -bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd) +bool bt_io_eam_card_slot_cmd_send(uint8_t unit_no, uint8_t cmd) { // ignored return true; } -bool eam_io_poll(uint8_t unit_no) +bool bt_io_eam_poll(uint8_t unit_no) { // ignored return true; } +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_eam_api_get(bt_io_eam_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_eam_init; + api->v1.fini = bt_io_eam_fini; + api->v1.keypad_state_get = bt_io_eam_keypad_state_get; + api->v1.sensor_state_get = bt_io_eam_sensor_state_get; + api->v1.card_read = bt_io_eam_card_read; + api->v1.card_slot_cmd_send = bt_io_eam_card_slot_cmd_send; + api->v1.poll = bt_io_eam_poll; + api->v1.config_api_get = bt_io_eam_config_api_get; +} + BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { diff --git a/src/main/eamio/eam-config.h b/src/main/eamio/eam-config.h index ebf4812c..ad7c5fee 100644 --- a/src/main/eamio/eam-config.h +++ b/src/main/eamio/eam-config.h @@ -1,9 +1,9 @@ #ifndef EAMIO_CONFIG_H #define EAMIO_CONFIG_H -#include "bemanitools/eamio.h" +#include "api/io/eam.h" -struct eam_io_config_api { +struct bt_io_eam_config_api { void (*config_save)(void); bool (*get_autogen)(void); void (*set_autogen)(bool autogen); diff --git a/src/main/eamio/eam-impl.c b/src/main/eamio/eam-impl.c index 0c417094..3e44a28e 100644 --- a/src/main/eamio/eam-impl.c +++ b/src/main/eamio/eam-impl.c @@ -7,16 +7,17 @@ #include #include -#include "bemanitools/eamio.h" +#include "api/io/eam.h" #include "eamio/eam-impl.h" #include "geninput/hid-mgr.h" +#include "iface-core/log.h" + #include "util/defs.h" #include "util/fs.h" #include "util/hex.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" @@ -25,7 +26,7 @@ struct eam_unit { char *card_path; struct hid_stub *hid; - size_t keypad_ctls[EAM_IO_KEYPAD_COUNT]; + size_t keypad_ctls[BT_IO_EAM_KEYPAD_COUNT]; size_t sensor_ctl; bool bound_ctls; uint8_t drive_no; @@ -45,7 +46,7 @@ struct eam { bool mux; }; -static const uint32_t eam_keypad_usages[EAM_IO_KEYPAD_COUNT + 1] = { +static const uint32_t eam_keypad_usages[BT_IO_EAM_KEYPAD_COUNT + 1] = { /* [EAM_KEYPAD_0] = */ 0x00070062, /* [EAM_KEYPAD_1] = */ 0x00070059, /* [EAM_KEYPAD_4] = */ 0x0007005C, @@ -60,7 +61,7 @@ static const uint32_t eam_keypad_usages[EAM_IO_KEYPAD_COUNT + 1] = { /* [EAM_KEYPAD_9] = */ 0x00070061, /* Sensor = */ 0x00070057}; -static const uint32_t eam_keypad_usages_alt[EAM_IO_KEYPAD_COUNT + 1] = { +static const uint32_t eam_keypad_usages_alt[BT_IO_EAM_KEYPAD_COUNT + 1] = { /* [EAM_KEYPAD_0] = */ 0x00070027, /* [EAM_KEYPAD_1] = */ 0x0007001E, /* [EAM_KEYPAD_4] = */ 0x00070021, @@ -270,13 +271,13 @@ static void eam_impl_bind_keypad(struct eam *eam, uint8_t unit_no) } for (control_no = 0; control_no < ncontrols; control_no++) { - for (btn_no = 0; btn_no < EAM_IO_KEYPAD_COUNT; btn_no++) { + for (btn_no = 0; btn_no < BT_IO_EAM_KEYPAD_COUNT; btn_no++) { if (controls[control_no].usage == usages[btn_no]) { unit->keypad_ctls[btn_no] = control_no; } } - if (controls[control_no].usage == usages[EAM_IO_KEYPAD_COUNT]) { + if (controls[control_no].usage == usages[BT_IO_EAM_KEYPAD_COUNT]) { unit->sensor_ctl = control_no; } } @@ -424,9 +425,9 @@ uint8_t eam_impl_read_card( fclose(f); if (card_id[0] == 0xe0 && card_id[1] == 0x04) { - return EAM_IO_CARD_ISO15696; + return BT_IO_EAM_READ_CARD_RESULT_ISO15696; } else { - return EAM_IO_CARD_FELICA; + return BT_IO_EAM_READ_CARD_RESULT_FELICA; } decode_fail: @@ -436,7 +437,7 @@ uint8_t eam_impl_read_card( fopen_fail: path_fail: - return EAM_IO_CARD_NONE; + return BT_IO_EAM_READ_CARD_RESULT_NONE; } static bool eam_impl_autogen(struct eam_unit *unit, uint8_t *card_id) diff --git a/src/main/eamio/eam-impl.h b/src/main/eamio/eam-impl.h index 486314d7..231935d1 100644 --- a/src/main/eamio/eam-impl.h +++ b/src/main/eamio/eam-impl.h @@ -5,7 +5,7 @@ #include #include -#include "bemanitools/eamio.h" +#include "api/io/eam.h" #include "geninput/hid-mgr.h" diff --git a/src/main/eamio/eamio.def b/src/main/eamio/eamio.def index 7bfca97f..3a7e3538 100644 --- a/src/main/eamio/eamio.def +++ b/src/main/eamio/eamio.def @@ -1,12 +1,17 @@ LIBRARY eamio EXPORTS - eam_io_fini - eam_io_init - eam_io_get_config_api - eam_io_get_keypad_state - eam_io_get_sensor_state - eam_io_read_card - eam_io_card_slot_cmd - eam_io_set_loggers - eam_io_poll + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_eam_api_get + + ; Direct API + bt_io_eam_init + bt_io_eam_fini + bt_io_eam_keypad_state_get + bt_io_eam_sensor_state_get + bt_io_eam_card_read + bt_io_eam_card_slot_cmd_send + bt_io_eam_poll + bt_io_eam_config_api_get diff --git a/src/main/eamiotest/Module.mk b/src/main/eamiotest/Module.mk index a54384b7..124fc950 100644 --- a/src/main/eamiotest/Module.mk +++ b/src/main/eamiotest/Module.mk @@ -1,8 +1,11 @@ exes += eamiotest libs_eamiotest := \ - eamio \ + core \ util \ + module \ + iface-core \ + iface-io \ src_eamiotest := \ main.c \ diff --git a/src/main/eamiotest/main.c b/src/main/eamiotest/main.c index 9880af4a..ce621abc 100644 --- a/src/main/eamiotest/main.c +++ b/src/main/eamiotest/main.c @@ -1,33 +1,60 @@ +#include + #include #include #include #include -#include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" -#include "bemanitools/eamio.h" +#include "iface-core/log.h" +#include "iface-io/eam.h" -#include "util/log.h" -#include "util/thread.h" +#include "module/io-ext.h" + +static void _eamiotest_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} /** * Tool to test your implementations of eamio. */ int main(int argc, char **argv) { - log_to_writer(log_writer_stdout, NULL); + module_io_t *module_io_eam; + + core_log_bt_core_api_set(); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); - if (!eam_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) { + _eamiotest_io_eam_init(&module_io_eam); + + if (!bt_io_eam_init()) { printf("Initializing eamio failed\n"); + + bt_io_eam_api_clear(); + module_io_free(&module_io_eam); + return -1; } printf(">>> Initializing eamio successful, press enter to continue <<<\n"); if (getchar() != '\n') { + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&module_io_eam); + return 0; } @@ -45,15 +72,15 @@ int main(int argc, char **argv) } for (uint8_t node = 0; node < 2; ++node) { - if (!eam_io_poll(node)) { + if (!bt_io_eam_poll(node)) { printf("ERROR: Polling node %d failed", node); return -2; } - uint16_t keypad = eam_io_get_keypad_state(node); + uint16_t keypad = bt_io_eam_keypad_state_get(node); uint16_t keypad_rise = ~keypad_prev[node] & keypad; - uint8_t sensors = eam_io_get_sensor_state(node); + uint8_t sensors = bt_io_eam_sensor_state_get(node); printf( "Press escape to quit\n" @@ -69,20 +96,20 @@ int main(int argc, char **argv) "|%02X%02X%02X%02X%02X%02X%02X%02X|\n" "------------------\n", node, - (keypad & (1 << EAM_IO_KEYPAD_7)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_8)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_9)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_4)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_5)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_6)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_1)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_2)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_3)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_0)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_00)) > 0, - (keypad & (1 << EAM_IO_KEYPAD_DECIMAL)) > 0, - (sensors & (1 << EAM_IO_SENSOR_FRONT)) > 0, - (sensors & (1 << EAM_IO_SENSOR_BACK)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_7)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_8)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_9)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_4)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_5)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_6)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_1)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_2)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_3)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_0)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_00)) > 0, + (keypad & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_DECIMAL)) > 0, + (sensors & (1 << BT_IO_EAM_SENSOR_STATE_FRONT)) > 0, + (sensors & (1 << BT_IO_EAM_SENSOR_STATE_BACK)) > 0, card[node][0], card[node][1], card[node][2], @@ -92,24 +119,29 @@ int main(int argc, char **argv) card[node][6], card[node][7]); - if (sensors & (1 << EAM_IO_SENSOR_BACK)) { - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_CLOSE); - eam_io_poll(node); - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_READ); - eam_io_poll(node); - eam_io_read_card(node, card[node], 8); + if (sensors & (1 << BT_IO_EAM_SENSOR_STATE_BACK)) { + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_CLOSE); + bt_io_eam_poll(node); + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_READ); + bt_io_eam_poll(node); + bt_io_eam_card_read(node, card[node], 8); } if (sensors == 0) { memset(card[node], 0, 8); - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_CLOSE); - eam_io_poll(node); - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_OPEN); + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_CLOSE); + bt_io_eam_poll(node); + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_OPEN); } - if (keypad_rise & (1 << EAM_IO_KEYPAD_DECIMAL)) { - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_EJECT); + if (keypad_rise & (1 << BT_IO_EAM_KEYPAD_SCAN_CODE_DECIMAL)) { + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_EJECT); } keypad_prev[node] = keypad; @@ -119,7 +151,10 @@ int main(int argc, char **argv) Sleep(5); } - eam_io_fini(); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&module_io_eam); return 0; } \ No newline at end of file diff --git a/src/main/exceptiontrace/Module.mk b/src/main/exceptiontrace/Module.mk new file mode 100644 index 00000000..6396594a --- /dev/null +++ b/src/main/exceptiontrace/Module.mk @@ -0,0 +1,9 @@ +dlls += exceptiontrace + +libs_exceptiontrace := \ + core \ + hook \ + util \ + +src_exceptiontrace := \ + dllmain.c \ diff --git a/src/main/exceptiontrace/dllmain.c b/src/main/exceptiontrace/dllmain.c new file mode 100644 index 00000000..71f1a587 --- /dev/null +++ b/src/main/exceptiontrace/dllmain.c @@ -0,0 +1,6 @@ +#include + +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ + return TRUE; +} diff --git a/src/main/exceptiontrace/exceptiontrace.c b/src/main/exceptiontrace/exceptiontrace.c new file mode 100644 index 00000000..84eb298a --- /dev/null +++ b/src/main/exceptiontrace/exceptiontrace.c @@ -0,0 +1,138 @@ +#define LOG_MODULE "exceptiontrace" + +#include + +#include + +#include "core/log.h" + +#include "imports/dwarfstack.h" + +#include "util/debug.h" + +#define log_exception(...) _debug_exception_msg("exception", __VA_ARGS__) + +static core_log_message_t _debug_exception_msg; + +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("base address: 0x%p (%s)", ptr, filename); + break; + + case DWST_NOT_FOUND: + case DWST_NO_DBG_SYM: + case DWST_NO_SRC_FILE: + log_exception( + " 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(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("=========================================================="); + log_exception("The application has crashed due to an unhandled exception!"); + + code = ep->ExceptionRecord->ExceptionCode; + desc = debug_exception_code_to_str(code); + + log_exception("code: 0x%08lX", code); + log_exception("desc: %s", desc); + + if (code == EXCEPTION_ACCESS_VIOLATION && + ep->ExceptionRecord->NumberParameters == 2) { + flag = ep->ExceptionRecord->ExceptionInformation[0]; + addr = ep->ExceptionRecord->ExceptionInformation[1]; + + log_exception( + "%s violation at 0x%p", + flag == 8 ? "data execution prevention" : + (flag ? "write access" : "read access"), + (void *) addr); + } + + log_exception("stacktrace:"); + + count = 0; + + dwstOfException(ep->ContextRecord, &_debug_stacktrace_printer, &count); + + log_exception("End of stacktrace"); + log_exception("=========================================================="); + + return EXCEPTION_EXECUTE_HANDLER; +} + +void debug_init(core_log_message_t exception_msg) +{ + _debug_exception_msg = exception_msg; + SetUnhandledExceptionFilter(_debug_unhandled_exception_filter); + + log_info("Initialized"); +} diff --git a/src/main/exceptiontrace/exceptiontrace.def b/src/main/exceptiontrace/exceptiontrace.def new file mode 100644 index 00000000..734cfc9e --- /dev/null +++ b/src/main/exceptiontrace/exceptiontrace.def @@ -0,0 +1,8 @@ +LIBRARY exceptiontrace + +EXPORTS + DllMain@12 @1 NONAME + btapi_hook_core_thread_impl_set + btapi_hook_core_log_impl_set + btapi_hook_main_init + btapi_hook_main_fini diff --git a/src/main/exceptiontrace/exceptiontrace.h b/src/main/exceptiontrace/exceptiontrace.h new file mode 100644 index 00000000..5718d63e --- /dev/null +++ b/src/main/exceptiontrace/exceptiontrace.h @@ -0,0 +1,8 @@ +#ifndef EXCEPTIONTRACE_EXCEPTIONTRACE_H +#define EXCEPTIONTRACE_EXCEPTIONTRACE_H + +#include "core/log.h" + +void exceptiontrace_init(core_log_message_t exception_msg); + +#endif \ No newline at end of file diff --git a/src/main/exceptiontrace/hook.c b/src/main/exceptiontrace/hook.c new file mode 100644 index 00000000..a810d8f5 --- /dev/null +++ b/src/main/exceptiontrace/hook.c @@ -0,0 +1,41 @@ +#define LOG_MODULE "exceptiontrance-hook" + +#include + +#include +#include + +#include "core/log.h" +#include "core/thread.h" + +#include "exceptiontrace/exceptiontrace.h" + +void btapi_hook_core_thread_impl_set( + btapi_thread_create_t create, + btapi_thread_join_t join, + btapi_thread_destroy_t destroy) +{ + core_thread_impl_set(create, join, destroy); +} + +void btapi_hook_core_log_impl_set( + btapi_log_formatter_t misc, + btapi_log_formatter_t info, + btapi_log_formatter_t warning, + btapi_log_formatter_t fatal) +{ + core_log_impl_set(misc, info, warning, fatal); +} + +bool btapi_hook_main_init( + HMODULE game_module, struct property_node *property_node_config) +{ + exceptiontrace_init(core_log_fatal_impl_get()); + + return true; +} + +void btapi_hook_main_fini() +{ + // noop +} \ No newline at end of file diff --git a/src/main/exceptiontrace/hook.h b/src/main/exceptiontrace/hook.h new file mode 100644 index 00000000..45f212ea --- /dev/null +++ b/src/main/exceptiontrace/hook.h @@ -0,0 +1,20 @@ +#ifndef EXCEPTIONTRACE_HOOK_H +#define EXCEPTIONTRACE_HOOK_H + +#include "btapi/hook-core.h" +#include "btapi/hook-main.h" + +void btapi_hook_core_thread_impl_set( + btapi_thread_create_t create, + btapi_thread_join_t join, + btapi_thread_destroy_t destroy); +void btapi_hook_core_log_impl_set( + btapi_log_formatter_t misc, + btapi_log_formatter_t info, + btapi_log_formatter_t warning, + btapi_log_formatter_t fatal); +bool btapi_hook_main_init( + HMODULE game_module, struct property_node *property_node_config); +void btapi_hook_main_fini(); + +#endif \ No newline at end of file diff --git a/src/main/extiodrv/device.c b/src/main/extiodrv/device.c index ba14fa7f..9f32f9d5 100644 --- a/src/main/extiodrv/device.c +++ b/src/main/extiodrv/device.c @@ -2,7 +2,7 @@ #include "device.h" -#include "util/log.h" +#include "iface-core/log.h" HRESULT extiodrv_device_open(const char *port, HANDLE *handle) { diff --git a/src/main/extiodrv/extio.c b/src/main/extiodrv/extio.c index 8c50de2f..ef01183a 100644 --- a/src/main/extiodrv/extio.c +++ b/src/main/extiodrv/extio.c @@ -2,7 +2,7 @@ #include "extio.h" -#include "util/log.h" +#include "iface-core/log.h" // static uint8_t _extiodrv_extio_sensor_read_mode_map[5] = { // 1, // all diff --git a/src/main/extiotest/Module.mk b/src/main/extiotest/Module.mk index 73ec1b07..e6515701 100644 --- a/src/main/extiotest/Module.mk +++ b/src/main/extiotest/Module.mk @@ -3,7 +3,10 @@ exes += extiotest \ libs_extiotest := \ extiodrv \ extio \ + core \ util \ + iface-core \ + mxml \ src_extiotest := \ main.c \ diff --git a/src/main/extiotest/main.c b/src/main/extiotest/main.c index 3be152b1..2cc9f874 100644 --- a/src/main/extiotest/main.c +++ b/src/main/extiotest/main.c @@ -5,9 +5,13 @@ #include -#include "extiodrv/extio.h" +#include "core/boot.h" +#include "core/log-bt.h" +#include "core/log-bt-ext.h" + +#include "iface-core/log.h" -#include "util/log.h" +#include "extiodrv/extio.h" int main(int argc, char **argv) { @@ -22,8 +26,11 @@ int main(int argc, char **argv) fprintf(stderr, " COM_PORT: For example COM1\n"); } - log_to_writer(log_writer_stderr, NULL); - log_set_level(LOG_LEVEL_MISC); + core_boot("extiotest"); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_core_api_set(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); port = argv[1]; diff --git a/src/main/ezusb-emu/device.c b/src/main/ezusb-emu/device.c index 9f1eca82..a2a7578c 100644 --- a/src/main/ezusb-emu/device.c +++ b/src/main/ezusb-emu/device.c @@ -20,12 +20,13 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "util/fs.h" #include "util/hex.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" // The max buffer size in iidx's ezusb client library is 4096 for the initial diff --git a/src/main/ezusb-emu/node-coin.c b/src/main/ezusb-emu/node-coin.c index 87e75037..6b392751 100644 --- a/src/main/ezusb-emu/node-coin.c +++ b/src/main/ezusb-emu/node-coin.c @@ -4,7 +4,7 @@ #include "ezusb-iidx/coin-cmd.h" -#include "util/log.h" +#include "iface-core/log.h" static uint8_t ezusb_iidx_emu_node_coin_mode = 0; diff --git a/src/main/ezusb-emu/node-eeprom.c b/src/main/ezusb-emu/node-eeprom.c index ea6a3fea..de066c2f 100644 --- a/src/main/ezusb-emu/node-eeprom.c +++ b/src/main/ezusb-emu/node-eeprom.c @@ -6,7 +6,7 @@ #include "ezusb-iidx/eeprom-cmd.h" -#include "util/log.h" +#include "iface-core/log.h" /* not verified, but we got calls with 3 pages only so far */ #define EEPROM_NPAGES 3 diff --git a/src/main/ezusb-emu/node-security-mem.c b/src/main/ezusb-emu/node-security-mem.c index 92422c82..d213d3c9 100644 --- a/src/main/ezusb-emu/node-security-mem.c +++ b/src/main/ezusb-emu/node-security-mem.c @@ -5,7 +5,7 @@ #include "ezusb-emu/node-security-mem.h" #include "ezusb-iidx/secmem-cmd.h" -#include "util/log.h" +#include "iface-core/log.h" #define SECURITY2_NPAGES 5 diff --git a/src/main/ezusb-emu/node-security-plug.c b/src/main/ezusb-emu/node-security-plug.c index 2b05a03a..4dde254b 100644 --- a/src/main/ezusb-emu/node-security-plug.c +++ b/src/main/ezusb-emu/node-security-plug.c @@ -7,12 +7,12 @@ #include "ezusb-emu/node-security-plug.h" #include "ezusb-iidx/secplug-cmd.h" +#include "iface-core/log.h" + #include "security/rp.h" #include "security/rp2.h" #include "security/util.h" -#include "util/log.h" - static struct security_mcode ezusb_iidx_emu_node_security_plug_boot_version; static uint32_t ezusb_iidx_emu_node_security_plug_boot_seeds[3]; diff --git a/src/main/ezusb-emu/node-sram.c b/src/main/ezusb-emu/node-sram.c index 200f1caf..c1e4cfae 100644 --- a/src/main/ezusb-emu/node-sram.c +++ b/src/main/ezusb-emu/node-sram.c @@ -6,8 +6,9 @@ #include "ezusb-emu/node-sram.h" #include "ezusb-iidx/sram-cmd.h" +#include "iface-core/log.h" + #include "util/fs.h" -#include "util/log.h" #define SRAM_NPAGES 12 diff --git a/src/main/ezusb-emu/node-wdt.c b/src/main/ezusb-emu/node-wdt.c index 9185bdde..971db1fd 100644 --- a/src/main/ezusb-emu/node-wdt.c +++ b/src/main/ezusb-emu/node-wdt.c @@ -3,7 +3,7 @@ #include "ezusb-emu/node-wdt.h" #include "ezusb-iidx/wdt-cmd.h" -#include "util/log.h" +#include "iface-core/log.h" uint8_t ezusb_iidx_emu_node_wdt_process_cmd( uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2) diff --git a/src/main/ezusb-emu/util.c b/src/main/ezusb-emu/util.c index 6e2798ae..a82d1a03 100644 --- a/src/main/ezusb-emu/util.c +++ b/src/main/ezusb-emu/util.c @@ -8,8 +8,9 @@ #include "ezusb-emu/util.h" +#include "iface-core/log.h" + #include "util/hex.h" -#include "util/log.h" enum ezusb_pipe { /* This is just the NT driver API. Add 1 to get the actual EP number. */ diff --git a/src/main/ezusb-iidx-16seg-emu/node-16seg.c b/src/main/ezusb-iidx-16seg-emu/node-16seg.c index 89bc5070..e823d471 100644 --- a/src/main/ezusb-iidx-16seg-emu/node-16seg.c +++ b/src/main/ezusb-iidx-16seg-emu/node-16seg.c @@ -4,12 +4,11 @@ #include -#include "bemanitools/iidxio.h" +#include "iface-core/log.h" +#include "iface-io/iidx.h" #include "ezusb-iidx/seg16-cmd.h" -#include "util/log.h" - uint8_t ezusb_iidx_emu_node_16seg_process_cmd( uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2) { @@ -38,5 +37,5 @@ bool ezusb_iidx_emu_node_16seg_write_packet( memcpy(_16seg, pkg->payload, 9); _16seg[9] = '\0'; - return iidx_io_ep3_write_16seg(_16seg); + return bt_io_iidx_ep3_16seg_send(_16seg); } \ No newline at end of file diff --git a/src/main/ezusb-iidx-emu/Module.mk b/src/main/ezusb-iidx-emu/Module.mk index d6253631..16f2c1dd 100644 --- a/src/main/ezusb-iidx-emu/Module.mk +++ b/src/main/ezusb-iidx-emu/Module.mk @@ -1,6 +1,7 @@ libs += ezusb-iidx-emu libs_ezusb-iidx-emu := \ + core \ ezusb-emu \ ezusb-iidx-16seg-emu \ diff --git a/src/main/ezusb-iidx-emu/card-mag.c b/src/main/ezusb-iidx-emu/card-mag.c index a210fd69..d87f2a02 100644 --- a/src/main/ezusb-iidx-emu/card-mag.c +++ b/src/main/ezusb-iidx-emu/card-mag.c @@ -2,10 +2,11 @@ #include +#include "iface-core/log.h" + #include "security/mcode.h" #include "util/crc.h" -#include "util/log.h" static const uint16_t ezusb_iidx_emu_card_mag_checksum_table_payload[256] = { 0x0, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, diff --git a/src/main/ezusb-iidx-emu/msg.c b/src/main/ezusb-iidx-emu/msg.c index bcab6566..88e8d202 100644 --- a/src/main/ezusb-iidx-emu/msg.c +++ b/src/main/ezusb-iidx-emu/msg.c @@ -4,10 +4,6 @@ #include #include -#include "bemanitools/iidxio.h" - -#include "hook/iohook.h" - #include "ezusb-emu/msg.h" #include "ezusb-emu/node-coin.h" #include "ezusb-emu/nodes.h" @@ -20,9 +16,12 @@ #include "ezusb-iidx-16seg-emu/nodes.h" -#include "util/hex.h" -#include "util/log.h" +#include "hook/iohook.h" + +#include "iface-core/log.h" +#include "iface-io/iidx.h" +#include "util/hex.h" /* ------------------------------------------------------------------------ */ static HRESULT ezusb_iidx_emu_msg_interrupt_read(struct iobuf *read); @@ -121,25 +120,25 @@ static HRESULT ezusb_iidx_emu_msg_interrupt_read(struct iobuf *read) struct ezusb_iidx_msg_interrupt_read_packet *msg_resp = (struct ezusb_iidx_msg_interrupt_read_packet *) read->bytes; - if (!iidx_io_ep2_recv()) { + if (!bt_io_iidx_ep2_recv()) { return E_FAIL; } - msg_resp->p1_turntable = iidx_io_ep2_get_turntable(0); - msg_resp->p2_turntable = iidx_io_ep2_get_turntable(1); + msg_resp->p1_turntable = bt_io_iidx_ep2_turntable_get(0); + msg_resp->p2_turntable = bt_io_iidx_ep2_turntable_get(1); msg_resp->sliders[0] = - iidx_io_ep2_get_slider(0) | (iidx_io_ep2_get_slider(1) << 4); + bt_io_iidx_ep2_slider_get(0) | (bt_io_iidx_ep2_slider_get(1) << 4); msg_resp->sliders[1] = - iidx_io_ep2_get_slider(2) | (iidx_io_ep2_get_slider(3) << 4); + bt_io_iidx_ep2_slider_get(2) | (bt_io_iidx_ep2_slider_get(3) << 4); - msg_resp->sliders[2] = iidx_io_ep2_get_slider(4); + msg_resp->sliders[2] = bt_io_iidx_ep2_slider_get(4); - msg_resp->inverted_pad = ((iidx_io_ep2_get_keys() & 0x3FFF) << 8) | - ((iidx_io_ep2_get_panel() & 0x0F) << 24) | - ((iidx_io_ep2_get_sys() & 0x07) << 28) | - (((iidx_io_ep2_get_sys() >> 2) & 0x01) << 22); + msg_resp->inverted_pad = ((bt_io_iidx_ep2_keys_get() & 0x3FFF) << 8) | + ((bt_io_iidx_ep2_panel_get() & 0x0F) << 24) | + ((bt_io_iidx_ep2_sys_get() & 0x07) << 28) | + (((bt_io_iidx_ep2_sys_get() >> 2) & 0x01) << 22); /* make sure to update the current coin mode state, otherwise the game will bang the IO and try to enforce the coin state it wants to @@ -208,12 +207,12 @@ static HRESULT ezusb_iidx_emu_msg_interrupt_write(struct const_iobuf *write) return E_INVALIDARG; } - iidx_io_ep1_set_deck_lights(msg_req->deck_lights); - iidx_io_ep1_set_panel_lights(msg_req->panel_lights); - iidx_io_ep1_set_top_lamps(msg_req->top_lamps); - iidx_io_ep1_set_top_neons(msg_req->top_neons); + bt_io_iidx_ep1_deck_lights_set(msg_req->deck_lights); + bt_io_iidx_ep1_panel_lights_set(msg_req->panel_lights); + bt_io_iidx_ep1_top_lamps_set(msg_req->top_lamps); + bt_io_iidx_ep1_top_neons_set(msg_req->top_neons); - if (!iidx_io_ep1_send()) { + if (!bt_io_iidx_ep1_send()) { return E_FAIL; } diff --git a/src/main/ezusb-iidx-emu/node-fpga.c b/src/main/ezusb-iidx-emu/node-fpga.c index d66c440c..a3ec6ac3 100644 --- a/src/main/ezusb-iidx-emu/node-fpga.c +++ b/src/main/ezusb-iidx-emu/node-fpga.c @@ -6,8 +6,9 @@ #include "ezusb-iidx-emu/node-fpga.h" #include "ezusb-iidx/fpga-cmd.h" +#include "iface-core/log.h" + #include "util/fs.h" -#include "util/log.h" static uint16_t ezusb_iidx_emu_node_fpga_write_ptr; static uint16_t ezusb_iidx_emu_node_fpga_prog_size; diff --git a/src/main/ezusb-iidx-emu/node-serial.c b/src/main/ezusb-iidx-emu/node-serial.c index 378ab02f..3b812201 100644 --- a/src/main/ezusb-iidx-emu/node-serial.c +++ b/src/main/ezusb-iidx-emu/node-serial.c @@ -2,18 +2,18 @@ #include -#include "bemanitools/eamio.h" - #include "ezusb-iidx-emu/card-mag.c" #include "ezusb-iidx-emu/node-serial.h" #include "ezusb-iidx/serial-cmd.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface-io/eam.h" + #include "security/mcode.h" #include "util/hex.h" -#include "util/log.h" #include "util/mem.h" -#include "util/thread.h" #define CARD_ID_LEN 8 @@ -227,7 +227,7 @@ struct ezusb_iidx_emu_node_serial_emulation_state { /* ------------------------------------------------------------------------- */ static const char - ezusb_iidx_emu_node_serial_eamio_mapping[EAM_IO_KEYPAD_COUNT] = { + ezusb_iidx_emu_node_serial_eamio_mapping[BT_IO_EAM_KEYPAD_COUNT] = { '0', '1', '4', '7', 'O', '2', '5', '8', 'E', '3', '6', '9'}; static const uint8_t HEADER_BYTE = 0xAA; @@ -267,6 +267,8 @@ static int ezusb_iidx_emu_node_serial_emu_thread_proc(void *ctx); void ezusb_iidx_emu_node_serial_init(void) { + bt_core_thread_result_t result; + ezusb_iidx_emu_node_serial_read_buf_busy = false; ezusb_iidx_emu_node_serial_write_buf_busy = false; memset( @@ -292,8 +294,13 @@ void ezusb_iidx_emu_node_serial_init(void) &ezusb_iidx_emu_node_serial_emulation_state[i].card_cs); } - ezusb_iidx_emu_node_serial_emu_thread = thread_create( - ezusb_iidx_emu_node_serial_emu_thread_proc, NULL, 0x4000, 0); + result = bt_core_thread_create( + ezusb_iidx_emu_node_serial_emu_thread_proc, + NULL, + 0x4000, + 0, + &ezusb_iidx_emu_node_serial_emu_thread); + bt_core_thread_fatal_on_error(result); } uint8_t ezusb_iidx_emu_node_serial_process_cmd( @@ -1252,15 +1259,15 @@ static int ezusb_iidx_emu_node_serial_emu_thread_proc(void *ctx) uint16_t keyboard_state_prev[2] = {0, 0}; while (true) { for (uint8_t node = 0; node < 2; node++) { - if (!eam_io_poll(node)) { + if (!bt_io_eam_poll(node)) { log_warning("Polling eamio, node %d failed", node); continue; } /* read card slot sensors */ - uint8_t sensors = eam_io_get_sensor_state(node); - if (sensors & (1 << EAM_IO_SENSOR_FRONT)) { + uint8_t sensors = bt_io_eam_sensor_state_get(node); + if (sensors & (1 << BT_IO_EAM_SENSOR_STATE_FRONT)) { ezusb_iidx_emu_node_serial_emulation_state[node] .card_slot_sensor_front = true; } else { @@ -1268,7 +1275,7 @@ static int ezusb_iidx_emu_node_serial_emu_thread_proc(void *ctx) .card_slot_sensor_front = false; } - if (sensors & (1 << EAM_IO_SENSOR_BACK)) { + if (sensors & (1 << BT_IO_EAM_SENSOR_STATE_BACK)) { ezusb_iidx_emu_node_serial_emulation_state[node] .card_slot_sensor_back = true; } else { @@ -1278,7 +1285,7 @@ static int ezusb_iidx_emu_node_serial_emu_thread_proc(void *ctx) /* handle keypad */ - uint16_t keypad = eam_io_get_keypad_state(node); + uint16_t keypad = bt_io_eam_keypad_state_get(node); uint16_t keypad_rise = ~keyboard_state_prev[node] & keypad; for (uint8_t i = 0; @@ -1296,11 +1303,13 @@ static int ezusb_iidx_emu_node_serial_emu_thread_proc(void *ctx) switch (ezusb_iidx_emu_node_serial_emulation_state[node] .ezusb_iidx_emu_node_serial_card_slot_state) { case EMU_CARD_SLOT_STATE_CLOSE: - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_CLOSE); + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_CLOSE); break; case EMU_CARD_SLOT_STATE_EJECT: - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_EJECT); + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_EJECT); EnterCriticalSection( &ezusb_iidx_emu_node_serial_emulation_state[node] @@ -1319,11 +1328,13 @@ static int ezusb_iidx_emu_node_serial_emu_thread_proc(void *ctx) break; case EMU_CARD_SLOT_STATE_OPEN: - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_OPEN); + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_OPEN); break; case EMU_CARD_SLOT_STATE_READ: - eam_io_card_slot_cmd(node, EAM_IO_CARD_SLOT_CMD_READ); + bt_io_eam_card_slot_cmd_send( + node, BT_IO_EAM_CARD_SLOT_CMD_READ); /* read once */ if (ezusb_iidx_emu_node_serial_emulation_state[node] @@ -1332,7 +1343,7 @@ static int ezusb_iidx_emu_node_serial_emu_thread_proc(void *ctx) &ezusb_iidx_emu_node_serial_emulation_state[node] .card_cs); - if (!eam_io_read_card( + if (!bt_io_eam_card_read( node, ezusb_iidx_emu_node_serial_emulation_state[node] .card_id, diff --git a/src/main/ezusb-iidx-fpga-flash/Module.mk b/src/main/ezusb-iidx-fpga-flash/Module.mk index c250b35b..ad7ee8c4 100644 --- a/src/main/ezusb-iidx-fpga-flash/Module.mk +++ b/src/main/ezusb-iidx-fpga-flash/Module.mk @@ -4,9 +4,11 @@ ldflags_ezusb-iidx-fpga-flash := \ -lsetupapi \ libs_ezusb-iidx-fpga-flash := \ + core \ ezusb \ ezusb-iidx \ util \ + iface-core \ src_ezusb-iidx-fpga-flash := \ main.c \ diff --git a/src/main/ezusb-iidx-fpga-flash/main.c b/src/main/ezusb-iidx-fpga-flash/main.c index a8fb6816..e153f186 100644 --- a/src/main/ezusb-iidx-fpga-flash/main.c +++ b/src/main/ezusb-iidx-fpga-flash/main.c @@ -3,11 +3,16 @@ #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + +#include "iface-core/log.h" + #include "ezusb-iidx/fpga.h" #include "ezusb/ezusb.h" #include "util/fs.h" -#include "util/log.h" int main(int argc, char **argv) { @@ -24,7 +29,10 @@ int main(int argc, char **argv) return -1; } - log_to_writer(log_writer_stderr, NULL); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); log_info("Opening ezusb '%s'...", EZUSB_DEVICE_PATH); diff --git a/src/main/ezusb-iidx-sram-flash/Module.mk b/src/main/ezusb-iidx-sram-flash/Module.mk index b6e6a73d..327841c0 100644 --- a/src/main/ezusb-iidx-sram-flash/Module.mk +++ b/src/main/ezusb-iidx-sram-flash/Module.mk @@ -4,9 +4,11 @@ ldflags_ezusb-iidx-sram-flash := \ -lsetupapi \ libs_ezusb-iidx-sram-flash := \ + core \ ezusb \ ezusb-iidx \ util \ + iface-core \ src_ezusb-iidx-sram-flash := \ main.c \ diff --git a/src/main/ezusb-iidx-sram-flash/main.c b/src/main/ezusb-iidx-sram-flash/main.c index d22464e0..5c71568a 100644 --- a/src/main/ezusb-iidx-sram-flash/main.c +++ b/src/main/ezusb-iidx-sram-flash/main.c @@ -1,13 +1,18 @@ +#include + #include #include -#include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + +#include "iface-core/log.h" #include "ezusb-iidx/sram.h" #include "ezusb/ezusb.h" #include "util/fs.h" -#include "util/log.h" int main(int argc, char **argv) { @@ -24,7 +29,10 @@ int main(int argc, char **argv) return -1; } - log_to_writer(log_writer_stdout, NULL); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); log_info("Opening ezusb '%s'...", argv[1]); diff --git a/src/main/ezusb-iidx/ezusb-iidx.c b/src/main/ezusb-iidx/ezusb-iidx.c index e82e2145..b9b4ae48 100644 --- a/src/main/ezusb-iidx/ezusb-iidx.c +++ b/src/main/ezusb-iidx/ezusb-iidx.c @@ -4,8 +4,9 @@ #include "ezusb/ezusbsys2.h" +#include "iface-core/log.h" + #include "util/hex.h" -#include "util/log.h" #include "util/time.h" #include "msg.h" diff --git a/src/main/ezusb-iidx/fpga.c b/src/main/ezusb-iidx/fpga.c index 23d5fd05..7eafa0c0 100644 --- a/src/main/ezusb-iidx/fpga.c +++ b/src/main/ezusb-iidx/fpga.c @@ -1,10 +1,10 @@ #define LOG_MODULE "ezusb-iidx-fpga" -#include "ezusb-iidx/fpga.h" - #include -#include "util/log.h" +#include "ezusb-iidx/fpga.h" + +#include "iface-core/log.h" #include "ezusb-iidx.h" #include "fpga-cmd.h" diff --git a/src/main/ezusb-iidx/sram.c b/src/main/ezusb-iidx/sram.c index f816b383..0ad056eb 100644 --- a/src/main/ezusb-iidx/sram.c +++ b/src/main/ezusb-iidx/sram.c @@ -2,7 +2,7 @@ #include "ezusb-iidx/sram.h" -#include "util/log.h" +#include "iface-core/log.h" #include "ezusb-iidx.h" #include "sram-cmd.h" diff --git a/src/main/ezusb-tool/Module.mk b/src/main/ezusb-tool/Module.mk index 349bc089..dd304ae6 100644 --- a/src/main/ezusb-tool/Module.mk +++ b/src/main/ezusb-tool/Module.mk @@ -4,8 +4,10 @@ ldflags_ezusb-tool := \ -lsetupapi \ libs_ezusb-tool := \ + core \ ezusb \ util \ + iface-core \ src_ezusb-tool := \ main.c \ diff --git a/src/main/ezusb-tool/main.c b/src/main/ezusb-tool/main.c index 115f79c5..9e96865d 100644 --- a/src/main/ezusb-tool/main.c +++ b/src/main/ezusb-tool/main.c @@ -3,11 +3,15 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + +#include "iface-core/log.h" + #include "ezusb/ezusb.h" #include "ezusb/util.h" -#include "util/log.h" - static int info() { HANDLE handle; @@ -103,7 +107,10 @@ int main(int argc, char **argv) arg_pos = 1; - log_to_writer(log_writer_stderr, NULL); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); if (!strcmp(argv[arg_pos], "info")) { return info(); diff --git a/src/main/ezusb/ezusb.c b/src/main/ezusb/ezusb.c index ce1b828e..95915b75 100644 --- a/src/main/ezusb/ezusb.c +++ b/src/main/ezusb/ezusb.c @@ -7,7 +7,8 @@ #include "ezusb/ezusb.h" #include "ezusb/ezusbsys2.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/str.h" static bool ezusb_reset(HANDLE handle, bool hold) diff --git a/src/main/ezusb/util.c b/src/main/ezusb/util.c index efc2cd10..e356166a 100644 --- a/src/main/ezusb/util.c +++ b/src/main/ezusb/util.c @@ -3,9 +3,10 @@ #include "ezusb/util.h" +#include "iface-core/log.h" + #include "util/crc.h" #include "util/fs.h" -#include "util/log.h" #include "util/mem.h" struct ezusb_firmware *ezusb_firmware_load(const char *file) diff --git a/src/main/ezusb2-dbg-hook/Module.mk b/src/main/ezusb2-dbg-hook/Module.mk index 4290f5cf..ab483ecc 100644 --- a/src/main/ezusb2-dbg-hook/Module.mk +++ b/src/main/ezusb2-dbg-hook/Module.mk @@ -1,8 +1,10 @@ dlls += ezusb2-dbg-hook libs_ezusb2-dbg-hook := \ + core \ hook \ util \ + iface-core \ src_ezusb2-dbg-hook := \ main.c \ diff --git a/src/main/ezusb2-dbg-hook/main.c b/src/main/ezusb2-dbg-hook/main.c index e90d3fb0..d4a66bb4 100644 --- a/src/main/ezusb2-dbg-hook/main.c +++ b/src/main/ezusb2-dbg-hook/main.c @@ -10,13 +10,18 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + #include "ezusb2/cyioctl.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "util/cmdline.h" #include "util/hex.h" -#include "util/log.h" #include "util/str.h" static HANDLE STDCALL my_CreateFileW( @@ -367,14 +372,16 @@ static void ezusb2_dbg_hook_terminate_process() BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - FILE *file; int argc; char **argv; wchar_t *buffer; uint32_t args_success; - file = fopen("ezusb2_dbg.log", "w+"); - log_to_writer(log_writer_file, file); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr_and_file( + "ezusb2_dbg.log", false, false, 0); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); hook_table_apply( NULL, diff --git a/src/main/ezusb2-emu/device.c b/src/main/ezusb2-emu/device.c index f4652798..df12232f 100644 --- a/src/main/ezusb2-emu/device.c +++ b/src/main/ezusb2-emu/device.c @@ -22,12 +22,13 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "util/fs.h" #include "util/hex.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" // The max buffer size in iidx's ezusb client library is 4096 for the initial diff --git a/src/main/ezusb2-emu/util.c b/src/main/ezusb2-emu/util.c index 2abd5134..ed4904fe 100644 --- a/src/main/ezusb2-emu/util.c +++ b/src/main/ezusb2-emu/util.c @@ -11,8 +11,9 @@ #include "ezusb-emu/util.h" +#include "iface-core/log.h" + #include "util/hex.h" -#include "util/log.h" void ezusb2_emu_util_log_usb_msg(const char *prefix, const struct irp *irp) { diff --git a/src/main/ezusb2-iidx-emu/msg.c b/src/main/ezusb2-iidx-emu/msg.c index 1279ea9b..12e8bedf 100644 --- a/src/main/ezusb2-iidx-emu/msg.c +++ b/src/main/ezusb2-iidx-emu/msg.c @@ -4,8 +4,6 @@ #include #include -#include "bemanitools/iidxio.h" - #include "hook/iohook.h" #include "ezusb-emu/msg.h" @@ -14,8 +12,10 @@ #include "ezusb2-iidx/msg.h" +#include "iface-core/log.h" +#include "iface-io/iidx.h" + #include "util/hex.h" -#include "util/log.h" /* ------------------------------------------------------------------------ */ @@ -66,27 +66,27 @@ static HRESULT ezusb2_iidx_emu_msg_interrupt_read(struct iobuf *read) { struct ezusb2_iidx_msg_interrupt_read_packet msg_resp; - if (!iidx_io_ep2_recv()) { + if (!bt_io_iidx_ep2_recv()) { return E_FAIL; } memset(&msg_resp, 0, sizeof(msg_resp)); - msg_resp.p1_turntable = iidx_io_ep2_get_turntable(0); - msg_resp.p2_turntable = iidx_io_ep2_get_turntable(1); + msg_resp.p1_turntable = bt_io_iidx_ep2_turntable_get(0); + msg_resp.p2_turntable = bt_io_iidx_ep2_turntable_get(1); msg_resp.sliders[0] = - iidx_io_ep2_get_slider(0) | (iidx_io_ep2_get_slider(1) << 4); + bt_io_iidx_ep2_slider_get(0) | (bt_io_iidx_ep2_slider_get(1) << 4); msg_resp.sliders[1] = - iidx_io_ep2_get_slider(2) | (iidx_io_ep2_get_slider(3) << 4); + bt_io_iidx_ep2_slider_get(2) | (bt_io_iidx_ep2_slider_get(3) << 4); - msg_resp.sliders[2] = iidx_io_ep2_get_slider(4); + msg_resp.sliders[2] = bt_io_iidx_ep2_slider_get(4); - msg_resp.inverted_pad = ((iidx_io_ep2_get_keys() & 0x3FFF) << 16) | - (iidx_io_ep2_get_panel() & 0x0F) | - ((iidx_io_ep2_get_sys() & 0x07) << 4) | - (((iidx_io_ep2_get_sys() >> 2) & 0x01) << 30); + msg_resp.inverted_pad = ((bt_io_iidx_ep2_keys_get() & 0x3FFF) << 16) | + (bt_io_iidx_ep2_panel_get() & 0x0F) | + ((bt_io_iidx_ep2_sys_get() & 0x07) << 4) | + (((bt_io_iidx_ep2_sys_get() >> 2) & 0x01) << 30); msg_resp.inverted_pad = ~msg_resp.inverted_pad; @@ -126,19 +126,19 @@ static HRESULT ezusb2_iidx_emu_msg_interrupt_write(struct const_iobuf *write) return E_INVALIDARG; } - iidx_io_ep1_set_deck_lights(msg_req.deck_lights); - iidx_io_ep1_set_panel_lights(msg_req.panel_lights); - iidx_io_ep1_set_top_lamps(msg_req.top_lamps); - iidx_io_ep1_set_top_neons(msg_req.top_neons); + bt_io_iidx_ep1_deck_lights_set(msg_req.deck_lights); + bt_io_iidx_ep1_panel_lights_set(msg_req.panel_lights); + bt_io_iidx_ep1_top_lamps_set(msg_req.top_lamps); + bt_io_iidx_ep1_top_neons_set(msg_req.top_neons); - if (!iidx_io_ep1_send()) { + if (!bt_io_iidx_ep1_send()) { return E_FAIL; } /* 16seg data is provided with the request and not handled using a separate bulk endpoint like on the C02 IO board */ - if (!iidx_io_ep3_write_16seg((const char *) msg_req.seg16)) { + if (!bt_io_iidx_ep3_16seg_send((const char *) msg_req.seg16)) { return E_FAIL; } diff --git a/src/main/ezusb2-popn-emu/msg.c b/src/main/ezusb2-popn-emu/msg.c index 6e83f7ac..7a2c357d 100644 --- a/src/main/ezusb2-popn-emu/msg.c +++ b/src/main/ezusb2-popn-emu/msg.c @@ -4,10 +4,6 @@ #include #include -#include "bemanitools/popnio.h" - -#include "hook/iohook.h" - #include "ezusb-emu/msg.h" #include "ezusb-emu/node-coin.h" @@ -18,8 +14,12 @@ #include "ezusb2-popn/msg.h" +#include "hook/iohook.h" + +#include "iface-core/log.h" +#include "iface-io/popn.h" + #include "util/hex.h" -#include "util/log.h" /* ------------------------------------------------------------------------ */ @@ -89,7 +89,7 @@ static HRESULT ezusb2_popn_emu_msg_interrupt_read(struct iobuf *read) msg_resp.coin_count = 0; msg_resp.unk4 = 0xfd; - msg_resp.io.inverted_pad = ~popn_io_get_buttons(); + msg_resp.io.inverted_pad = ~bt_io_popn_buttons_get(); msg_resp.unk5 = 0x00; msg_resp.unk6 = 0x7d; @@ -137,12 +137,12 @@ static HRESULT ezusb2_popn_emu_msg_interrupt_write(struct const_iobuf *write) return E_INVALIDARG; } - popn_io_set_top_lights(msg_req.lamp & 0x1f); - popn_io_set_side_lights((msg_req.lamp >> 8) & 0xf); - popn_io_set_button_lights((msg_req.lamp >> 20) & 0xfff); - popn_io_set_coin_counter_light( + bt_io_popn_top_lights_set(msg_req.lamp & 0x1f); + bt_io_popn_side_lights_set((msg_req.lamp >> 8) & 0xf); + bt_io_popn_button_lights_set((msg_req.lamp >> 20) & 0xfff); + bt_io_popn_coin_counter_light_set( ((msg_req.lamp >> 12) & 0xf) == 0); // Active low - popn_io_set_coin_blocker_light(((msg_req.lamp >> 16) & 0xf) == 0xf); + bt_io_popn_coin_blocker_light_set(((msg_req.lamp >> 16) & 0xf) == 0xf); /* Remember node for next bulk read */ diff --git a/src/main/ezusb2-popn-shim/Module.mk b/src/main/ezusb2-popn-shim/Module.mk index aefc2d40..64e348b6 100644 --- a/src/main/ezusb2-popn-shim/Module.mk +++ b/src/main/ezusb2-popn-shim/Module.mk @@ -4,10 +4,12 @@ ldflags_ezusb2-popn-shim := \ -lsetupapi \ libs_ezusb2-popn-shim := \ + core \ ezusb2-emu \ hook \ hooklib \ util \ + iface-core \ src_ezusb2-popn-shim := \ dllmain.c \ diff --git a/src/main/ezusb2-popn-shim/dllmain.c b/src/main/ezusb2-popn-shim/dllmain.c index c8e16fcf..1fd4efdd 100644 --- a/src/main/ezusb2-popn-shim/dllmain.c +++ b/src/main/ezusb2-popn-shim/dllmain.c @@ -11,9 +11,9 @@ #include "hooklib/setupapi.h" -#include "ezusb2-popn-shim/proxy.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "ezusb2-popn-shim/proxy.h" #define EZUSB_REAL_DLL_FILENAME "ezusb.dll" diff --git a/src/main/ezusb2-popn-shim/proxy.c b/src/main/ezusb2-popn-shim/proxy.c index fdf4f9f9..439fa91b 100644 --- a/src/main/ezusb2-popn-shim/proxy.c +++ b/src/main/ezusb2-popn-shim/proxy.c @@ -2,7 +2,7 @@ #include #include -#include "util/log.h" +#include "iface-core/log.h" struct CoinParam; struct EEP_HISTORY; diff --git a/src/main/ezusb2-tool/Module.mk b/src/main/ezusb2-tool/Module.mk index 06115652..dbed8d5e 100644 --- a/src/main/ezusb2-tool/Module.mk +++ b/src/main/ezusb2-tool/Module.mk @@ -4,9 +4,11 @@ ldflags_ezusb2-tool := \ -lsetupapi \ libs_ezusb2-tool := \ + core \ ezusb2 \ ezusb \ util \ + iface-core \ src_ezusb2-tool := \ main.c \ diff --git a/src/main/ezusb2-tool/main.c b/src/main/ezusb2-tool/main.c index cdfd179b..6f0f5e50 100644 --- a/src/main/ezusb2-tool/main.c +++ b/src/main/ezusb2-tool/main.c @@ -3,11 +3,15 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + +#include "iface-core/log.h" + #include "ezusb/util.h" #include "ezusb2/ezusb2.h" -#include "util/log.h" - static int scan() { char *path; @@ -122,7 +126,10 @@ int main(int argc, char **argv) arg_pos = 1; - log_to_writer(log_writer_stderr, NULL); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); if (!strcmp(argv[arg_pos], "scan")) { return scan(); diff --git a/src/main/ezusb2/ezusb2.c b/src/main/ezusb2/ezusb2.c index 61fabd73..1e0b952c 100644 --- a/src/main/ezusb2/ezusb2.c +++ b/src/main/ezusb2/ezusb2.c @@ -9,9 +9,10 @@ #include "ezusb2/cyioctl.h" #include "ezusb2/ezusb2.h" +#include "iface-core/log.h" + #include "util/crc.h" #include "util/fs.h" -#include "util/log.h" #include "util/str.h" #define REQ_TYPE_HOST_TO_DEV 0x40 diff --git a/src/main/geninput/Module.mk b/src/main/geninput/Module.mk index 1521d806..05f3755e 100644 --- a/src/main/geninput/Module.mk +++ b/src/main/geninput/Module.mk @@ -5,7 +5,10 @@ ldflags_geninput := \ -lsetupapi \ libs_geninput := \ + core \ util \ + iface-core \ + iface \ src_geninput := \ dev-list.c \ diff --git a/src/main/geninput/dev-list.c b/src/main/geninput/dev-list.c index 2bfcb4e8..da14b940 100644 --- a/src/main/geninput/dev-list.c +++ b/src/main/geninput/dev-list.c @@ -11,7 +11,8 @@ #include "geninput/dev-list.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" void dev_list_init(struct dev_list *devs, const GUID *class_guid) diff --git a/src/main/geninput/geninput.def b/src/main/geninput/geninput.def index 6ef4cf3e..e392cc84 100644 --- a/src/main/geninput/geninput.def +++ b/src/main/geninput/geninput.def @@ -1,6 +1,12 @@ LIBRARY geninput EXPORTS + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_input_api_get + + ; Direct API action_iter_get_mapping action_iter_get_action action_iter_get_page @@ -22,7 +28,6 @@ EXPORTS hid_stub_set_light input_fini input_init - input_set_loggers light_iter_get_mapping light_iter_get_game_light light_iter_is_valid @@ -49,6 +54,6 @@ EXPORTS mapper_set_light_map mapper_set_nanalogs mapper_set_nlights - mapper_read_analog + mapper_analog_read mapper_update - mapper_write_light + mapper_light_write diff --git a/src/main/geninput/hid-generic.c b/src/main/geninput/hid-generic.c index 41e73828..b6216425 100644 --- a/src/main/geninput/hid-generic.c +++ b/src/main/geninput/hid-generic.c @@ -18,8 +18,9 @@ #include "geninput/hid-meta-out.h" #include "geninput/hid.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" diff --git a/src/main/geninput/hid-meta-in.c b/src/main/geninput/hid-meta-in.c index bbaf44f1..8b8fa9f8 100644 --- a/src/main/geninput/hid-meta-in.c +++ b/src/main/geninput/hid-meta-in.c @@ -14,7 +14,8 @@ #include "geninput/hid-meta-in.h" #include "geninput/hid-report-in.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" static bool diff --git a/src/main/geninput/hid-meta-out.c b/src/main/geninput/hid-meta-out.c index 4f87602a..7aac137a 100644 --- a/src/main/geninput/hid-meta-out.c +++ b/src/main/geninput/hid-meta-out.c @@ -15,7 +15,8 @@ #include "geninput/hid-meta-out.h" #include "geninput/hid-report-out.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" static bool diff --git a/src/main/geninput/hid-mgr.c b/src/main/geninput/hid-mgr.c index f22d3a78..af8fb462 100644 --- a/src/main/geninput/hid-mgr.c +++ b/src/main/geninput/hid-mgr.c @@ -4,7 +4,8 @@ #include "geninput/hid-mgr.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" #include "util/str.h" diff --git a/src/main/geninput/hid-report-in.c b/src/main/geninput/hid-report-in.c index 721a721d..a35e7d1e 100644 --- a/src/main/geninput/hid-report-in.c +++ b/src/main/geninput/hid-report-in.c @@ -12,7 +12,8 @@ #include "geninput/hid-report-in.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" void hid_report_in_init( diff --git a/src/main/geninput/hid-report-out.c b/src/main/geninput/hid-report-out.c index 5469e3a3..ad84f669 100644 --- a/src/main/geninput/hid-report-out.c +++ b/src/main/geninput/hid-report-out.c @@ -13,7 +13,8 @@ #include "geninput/hid-report-out.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" bool hid_report_out_init( diff --git a/src/main/geninput/hid.c b/src/main/geninput/hid.c index 57685b02..58c65663 100644 --- a/src/main/geninput/hid.c +++ b/src/main/geninput/hid.c @@ -4,7 +4,8 @@ #include "geninput/dev-list.h" #include "geninput/hid.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/str.h" wchar_t *hid_ri_init_name(const GUID *class_guid, const char *dev_node) diff --git a/src/main/geninput/hotplug.c b/src/main/geninput/hotplug.c index 54dad425..bf8d77ec 100644 --- a/src/main/geninput/hotplug.c +++ b/src/main/geninput/hotplug.c @@ -11,7 +11,7 @@ #include "geninput/io-thread.h" #include "geninput/ri.h" -#include "util/log.h" +#include "iface-core/log.h" static HDEVNOTIFY hotplug_handle; diff --git a/src/main/geninput/input-config.h b/src/main/geninput/input-config.h index d7fe181a..6f33ecac 100644 --- a/src/main/geninput/input-config.h +++ b/src/main/geninput/input-config.h @@ -4,8 +4,6 @@ #include #include -#include "bemanitools/input.h" - #include "geninput/mapper.h" void mapper_config_save(const char *game_type); diff --git a/src/main/geninput/input.c b/src/main/geninput/input.c index 60c94c26..39ae1557 100644 --- a/src/main/geninput/input.c +++ b/src/main/geninput/input.c @@ -4,8 +4,13 @@ #include -#include "bemanitools/glue.h" -#include "bemanitools/input.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "api/input.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" #include "geninput/hid-mgr.h" #include "geninput/hid.h" @@ -14,10 +19,8 @@ #include "geninput/mapper.h" #include "util/fs.h" -#include "util/log.h" #include "util/msg-thread.h" #include "util/str.h" -#include "util/thread.h" static HINSTANCE input_hinst; static volatile long input_init_count; @@ -33,28 +36,19 @@ static FILE *mapper_config_open(const char *game_type, const char *mode) // Try to load the old save file only if we're loading if (f == NULL) { if (strchr(mode, 'r') != NULL) { + log_misc("Fallback to old save file"); str_format(path, sizeof(path), "%s_v5_00a07.bin", game_type); f = fopen_appdata("DJHACKERS", path, mode); } } - - return f; -} -void input_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - log_to_external(misc, info, warning, fatal); + return f; } -void input_init( - thread_create_t create, thread_join_t join, thread_destroy_t destroy) +bool input_init() { if (InterlockedIncrement(&input_init_count) != 1) { - return; + return true; } log_info("Generic input subsystem is starting up"); @@ -63,9 +57,10 @@ void input_init( mapper_inst = mapper_impl_create(); - thread_api_init(create, join, destroy); msg_thread_init(input_hinst); io_thread_init(); + + return true; } void input_fini(void) @@ -225,7 +220,7 @@ void mapper_set_nlights(uint8_t nlights) mapper_impl_set_nlights(mapper_inst, nlights); } -uint8_t mapper_read_analog(uint8_t analog) +uint8_t mapper_analog_read(uint8_t analog) { return mapper_impl_read_analog(mapper_inst, analog); } @@ -235,11 +230,33 @@ uint64_t mapper_update(void) return mapper_impl_update(mapper_inst); } -void mapper_write_light(uint8_t light, uint8_t intensity) +void mapper_light_write(uint8_t light, uint8_t intensity) { mapper_impl_write_light(mapper_inst, light, intensity); } +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_input_api_get(bt_input_api_t *api) +{ + api->version = 1; + + api->v1.init = input_init; + api->v1.fini = input_fini; + api->v1.mapper_config_load = mapper_config_load; + api->v1.mapper_analog_read = mapper_analog_read; + api->v1.mapper_update = mapper_update; + api->v1.mapper_light_write = mapper_light_write; +} + BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { diff --git a/src/main/geninput/io-thread.c b/src/main/geninput/io-thread.c index ca663ff3..cc064fbc 100644 --- a/src/main/geninput/io-thread.c +++ b/src/main/geninput/io-thread.c @@ -2,6 +2,9 @@ #include +#include "iface-core/log.h" +#include "iface-core/thread.h" + #include "geninput/dev-list.h" #include "geninput/hid-generic.h" #include "geninput/hid-mgr.h" @@ -10,9 +13,7 @@ #include "geninput/pacdrive.h" #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" -#include "util/thread.h" enum io_thread_cmd { IO_THREAD_CMD_STOP, @@ -26,7 +27,7 @@ struct io_thread_msg { }; static HANDLE io_thread_cp; -static int io_thread_id; +static bt_core_thread_id_t io_thread_id; static void io_thread_proc_add_device(const char *dev_node); static void io_thread_proc_init(void); @@ -169,10 +170,13 @@ static int io_thread_proc(void *param) void io_thread_init(void) { HANDLE barrier; + bt_core_thread_result_t result; barrier = CreateEvent(NULL, TRUE, FALSE, NULL); - io_thread_id = thread_create(io_thread_proc, barrier, 16384, 0); + result = + bt_core_thread_create(io_thread_proc, barrier, 16384, 0, &io_thread_id); + bt_core_thread_fatal_on_error(result); WaitForSingleObject(barrier, INFINITE); CloseHandle(barrier); @@ -195,11 +199,15 @@ void io_thread_add_device(const char *dev_node) void io_thread_fini(void) { struct io_thread_msg msg; + bt_core_thread_result_t result; msg.cmd = IO_THREAD_CMD_STOP; PostQueuedCompletionStatus(io_thread_cp, 0, (uintptr_t) &msg, NULL); - thread_join(io_thread_id, NULL); - thread_destroy(io_thread_id); + result = bt_core_thread_join(io_thread_id, NULL); + bt_core_thread_fatal_on_error(result); + + result = bt_core_thread_destroy(io_thread_id); + bt_core_thread_fatal_on_error(result); } diff --git a/src/main/geninput/kbd.c b/src/main/geninput/kbd.c index 9ae8e5ed..6e69ab35 100644 --- a/src/main/geninput/kbd.c +++ b/src/main/geninput/kbd.c @@ -15,8 +15,9 @@ #include "geninput/kbd-data.h" #include "geninput/kbd.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" diff --git a/src/main/geninput/mapper-s11n.c b/src/main/geninput/mapper-s11n.c index 3dba127a..b93b1258 100644 --- a/src/main/geninput/mapper-s11n.c +++ b/src/main/geninput/mapper-s11n.c @@ -22,9 +22,12 @@ enum mapper_config_version { static const uint32_t mapper_fourcc = FOURCC('B', 'T', 'M', 'D'); static uint32_t mapper_impl_config_load_version(FILE *f); -static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f, uint32_t version); -static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f, uint32_t version); -static bool mapper_impl_config_load_lights(struct mapper *m, FILE *f, uint32_t version); +static bool +mapper_impl_config_load_actions(struct mapper *m, FILE *f, uint32_t version); +static bool +mapper_impl_config_load_analogs(struct mapper *m, FILE *f, uint32_t version); +static bool +mapper_impl_config_load_lights(struct mapper *m, FILE *f, uint32_t version); static void mapper_impl_config_save_actions(struct mapper *m, FILE *f); static void mapper_impl_config_save_analogs(struct mapper *m, FILE *f); static void mapper_impl_config_save_lights(struct mapper *m, FILE *f); @@ -60,9 +63,9 @@ static uint32_t mapper_impl_config_load_version(FILE *f) if (!read_u32(f, &fourcc)) { return 0; } - + if (fourcc == mapper_fourcc) { - + if (!read_u32(f, &version)) { fseek(f, -4, SEEK_CUR); } @@ -74,7 +77,8 @@ static uint32_t mapper_impl_config_load_version(FILE *f) return version; } -static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f, uint32_t version) +static bool +mapper_impl_config_load_actions(struct mapper *m, FILE *f, uint32_t version) { char *dev_node; struct mapped_action ma; @@ -110,7 +114,8 @@ static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f, uint32_t return true; } -static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f, uint32_t version) +static bool +mapper_impl_config_load_analogs(struct mapper *m, FILE *f, uint32_t version) { char *dev_node; struct mapped_analog ma; @@ -164,7 +169,8 @@ static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f, uint32_t return true; } -static bool mapper_impl_config_load_lights(struct mapper *m, FILE *f, uint32_t version) +static bool +mapper_impl_config_load_lights(struct mapper *m, FILE *f, uint32_t version) { char *dev_node; struct mapped_light ml; diff --git a/src/main/geninput/mapper.c b/src/main/geninput/mapper.c index c3d02143..875f59bc 100644 --- a/src/main/geninput/mapper.c +++ b/src/main/geninput/mapper.c @@ -4,8 +4,9 @@ #include "geninput/hid-mgr.h" #include "geninput/mapper.h" +#include "iface-core/log.h" + #include "util/array.h" -#include "util/log.h" #include "util/mem.h" struct action_iter { @@ -173,7 +174,7 @@ static void analog_mapping_bind(struct analog_mapping *am) am->analog_min = ctl->value_min; am->analog_max = ctl->value_max; - am->inv_analog_range = 1.0 / ((int64_t)ctl->value_max - ctl->value_min); + am->inv_analog_range = 1.0 / ((int64_t) ctl->value_max - ctl->value_min); am->absolute = !(ctl->flags & HID_FLAG_RELATIVE); am->valid = true; @@ -424,7 +425,7 @@ int32_t mapper_impl_get_analog_sensitivity(struct mapper *m, uint8_t analog) return m->analogs[analog].sensitivity; } -bool mapper_impl_get_analog_invert(struct mapper* m, uint8_t analog) +bool mapper_impl_get_analog_invert(struct mapper *m, uint8_t analog) { if (analog >= m->nanalogs) { return 0; diff --git a/src/main/geninput/mouse.c b/src/main/geninput/mouse.c index 2b24d1c8..d1cb9f45 100644 --- a/src/main/geninput/mouse.c +++ b/src/main/geninput/mouse.c @@ -15,8 +15,9 @@ #include "geninput/hid.h" #include "geninput/mouse.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" diff --git a/src/main/geninput/msg-thread.c b/src/main/geninput/msg-thread.c index cc21ae06..89bbfd2a 100644 --- a/src/main/geninput/msg-thread.c +++ b/src/main/geninput/msg-thread.c @@ -9,7 +9,8 @@ #include "geninput/hotplug.h" #include "geninput/ri.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/msg-thread.h" void msg_window_setup(HWND hwnd) diff --git a/src/main/geninput/pacdrive.c b/src/main/geninput/pacdrive.c index 2a5ab36f..603860bc 100644 --- a/src/main/geninput/pacdrive.c +++ b/src/main/geninput/pacdrive.c @@ -15,8 +15,9 @@ #include "geninput/io-thread.h" #include "geninput/pacdrive.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" /* The PacDrive appears to have a malformed descriptor for its OUT report. diff --git a/src/main/geninput/ri.c b/src/main/geninput/ri.c index b3befee9..1415e272 100644 --- a/src/main/geninput/ri.c +++ b/src/main/geninput/ri.c @@ -6,8 +6,9 @@ #include "geninput/mouse.h" #include "geninput/ri.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" struct ri_handle { diff --git a/src/main/hook/com-proxy.h b/src/main/hook/com-proxy.h index 94671b7c..71d29538 100644 --- a/src/main/hook/com-proxy.h +++ b/src/main/hook/com-proxy.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include diff --git a/src/main/hook/d3d9.c b/src/main/hook/d3d9.c index 45e1fd14..89b8e073 100644 --- a/src/main/hook/d3d9.c +++ b/src/main/hook/d3d9.c @@ -1,11 +1,11 @@ #define LOG_MODULE "hook-d3d9" -#include "hook/d3d9.h" +#include "iface-core/log.h" + #include "hook/com-proxy.h" +#include "hook/d3d9.h" #include "hook/table.h" -#include "util/log.h" - /* ------------------------------------------------------------------------------------------------------------------ */ diff --git a/src/main/hook/table.c b/src/main/hook/table.c index 067ea75f..285a43d3 100644 --- a/src/main/hook/table.c +++ b/src/main/hook/table.c @@ -174,10 +174,11 @@ static void hook_table_revert_to_iid( sym = &syms[j]; if (hook_table_match_proc(&iate, sym)) { - // Only revert-able if the original pointer was stored previously + // Only revert-able if the original pointer was stored + // previously if (sym->link != NULL && *sym->link != NULL) { pe_patch(iate.ppointer, sym->link, sizeof(*sym->link)); - } + } } } } diff --git a/src/main/hooklib/acp.c b/src/main/hooklib/acp.c index 52675b2d..ecf4e40a 100644 --- a/src/main/hooklib/acp.c +++ b/src/main/hooklib/acp.c @@ -6,13 +6,14 @@ #include #include +#include "iface-core/log.h" + #include "hook/table.h" #include "hooklib/acp.h" #include "util/codepage.h" #include "util/defs.h" -#include "util/log.h" static NTSTATUS NTAPI my_RtlMultiByteToUnicodeN( wchar_t *dest, @@ -63,5 +64,11 @@ static NTSTATUS NTAPI my_RtlMultiByteToUnicodeN( void acp_hook_init(void) { hook_table_apply(NULL, "ntdll.dll", acp_hook_syms, lengthof(acp_hook_syms)); - log_info("ACP Hook enabled"); + log_info("Inserted ACP hook"); +} + +void acp_hook_fini() +{ + hook_table_revert(NULL, "ntdll.dll", acp_hook_syms, lengthof(acp_hook_syms)); + log_info("Removed ACP hook"); } diff --git a/src/main/hooklib/acp.h b/src/main/hooklib/acp.h index b4299965..85a993fa 100644 --- a/src/main/hooklib/acp.h +++ b/src/main/hooklib/acp.h @@ -3,4 +3,6 @@ void acp_hook_init(void); +void acp_hook_fini(); + #endif diff --git a/src/main/hooklib/adapter.c b/src/main/hooklib/adapter.c index 0b94c125..cfdeb40a 100644 --- a/src/main/hooklib/adapter.c +++ b/src/main/hooklib/adapter.c @@ -6,13 +6,14 @@ #include #include +#include "iface-core/log.h" + #include "hook/table.h" #include "hooklib/adapter.h" #include "util/codepage.h" #include "util/defs.h" -#include "util/log.h" static DWORD WINAPI my_GetAdaptersInfo(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len); @@ -116,6 +117,16 @@ void adapter_hook_init(void) { hook_table_apply( NULL, "iphlpapi.dll", adapter_hook_syms, lengthof(adapter_hook_syms)); + + log_info("Inserted adapter hooks"); +} + +void adapter_hook_fini() +{ + hook_table_revert( + NULL, "iphlpapi.dll", adapter_hook_syms, lengthof(adapter_hook_syms)); + + log_info("Removed adapter hooks"); } void adapter_hook_override(const char *adapter_address) diff --git a/src/main/hooklib/adapter.h b/src/main/hooklib/adapter.h index 3f5e5dab..23d78495 100644 --- a/src/main/hooklib/adapter.h +++ b/src/main/hooklib/adapter.h @@ -7,6 +7,8 @@ */ void adapter_hook_init(void); +void adapter_hook_fini(); + /** * Uses the provided address to try and match a network adapter. * This adapter is then returned as the only adapter. diff --git a/src/main/hooklib/app.c b/src/main/hooklib/app.c index 7ccd441d..4c545f00 100644 --- a/src/main/hooklib/app.c +++ b/src/main/hooklib/app.c @@ -1,5 +1,7 @@ #include +#include "iface-core/log.h" + #include "hook/table.h" #include "hooklib/app.h" @@ -7,7 +9,6 @@ #include "imports/avs.h" #include "imports/eapki.h" -#include "util/log.h" #include "util/str.h" static dll_entry_init_t hook_dll_entry_init; diff --git a/src/main/hooklib/config-adapter.c b/src/main/hooklib/config-adapter.c index 49c24505..89da7e69 100644 --- a/src/main/hooklib/config-adapter.c +++ b/src/main/hooklib/config-adapter.c @@ -1,35 +1,7 @@ -#include "cconfig/cconfig-util.h" - #include "hooklib/config-adapter.h" -#include "util/log.h" - -#define HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY "adapter.override_ip" - -#define HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE "" - -void hooklib_config_adapter_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY, - HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE, - "IP of adapter to force override with"); -} - void hooklib_config_adapter_get( - struct hooklib_config_adapter *config_adapter, struct cconfig *config) + const bt_core_config_t *config, hooklib_config_adapter_t *config_adapter) { - if (!cconfig_util_get_str( - config, - HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY, - config_adapter->override_ip, - sizeof(config_adapter->override_ip), - HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - HOOKLIB_CONFIG_ADAPTER_OVERRIDE_IP_KEY, - HOOKLIB_CONFIG_ADAPTER_DEFAULT_OVERRIDE_IP_VALUE); - } + bt_core_config_str_get(config, "adapter/override_ip", config_adapter->override_ip, sizeof(config_adapter->override_ip)); } diff --git a/src/main/hooklib/config-adapter.h b/src/main/hooklib/config-adapter.h index 621a0e35..0165d128 100644 --- a/src/main/hooklib/config-adapter.h +++ b/src/main/hooklib/config-adapter.h @@ -1,18 +1,14 @@ #ifndef HOOKLIB_CONFIG_ADAPTER_H #define HOOKLIB_CONFIG_ADAPTER_H -#include +#include "iface-core/config.h" -#include "cconfig/cconfig.h" - -struct hooklib_config_adapter { +typedef struct hooklib_config_adapter { // this is larger on purpose, in case ppl enter the wrong stuff here char override_ip[32]; -}; - -void hooklib_config_adapter_init(struct cconfig *config); +} hooklib_config_adapter_t; void hooklib_config_adapter_get( - struct hooklib_config_adapter *config_adapter, struct cconfig *config); + const bt_core_config_t *config, hooklib_config_adapter_t *config_adapter); #endif \ No newline at end of file diff --git a/src/main/hooklib/memfile.c b/src/main/hooklib/memfile.c index 08dbeba1..1b08efee 100644 --- a/src/main/hooklib/memfile.c +++ b/src/main/hooklib/memfile.c @@ -3,12 +3,13 @@ #include #include +#include "iface-core/log.h" + #include "hook/hr.h" #include "hook/iohook.h" #include "hook/table.h" #include "util/array.h" -#include "util/log.h" #include "util/str.h" struct file_entry { diff --git a/src/main/hooklib/rs232.c b/src/main/hooklib/rs232.c index 8d6d371f..5913fe72 100644 --- a/src/main/hooklib/rs232.c +++ b/src/main/hooklib/rs232.c @@ -14,12 +14,13 @@ #include #include +#include "iface-core/log.h" + #include "hook/hr.h" #include "hook/iohook.h" #include "hook/table.h" #include "util/array.h" -#include "util/log.h" /* RS232 API hooks */ diff --git a/src/main/hooklib/setupapi.c b/src/main/hooklib/setupapi.c index 07dc72cf..5aee2105 100644 --- a/src/main/hooklib/setupapi.c +++ b/src/main/hooklib/setupapi.c @@ -4,12 +4,13 @@ #include #include +#include "iface-core/log.h" + #include "hook/table.h" #include "hooklib/setupapi.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" /* my hooks */ @@ -360,3 +361,14 @@ void hook_setupapi_init(const struct hook_setupapi_data *data) log_info( "Hooked setupapi for %s, %s", data->device_path, data->device_desc); } + +void hook_setupapi_fini() +{ + hook_table_revert( + NULL, "setupapi.dll", setupapi_hook_syms, lengthof(setupapi_hook_syms)); + + log_info( + "Removed hooks setupapi for %s, %s", hook_setupapi_data->device_path, hook_setupapi_data->device_desc); + + hook_setupapi_data = NULL; +} \ No newline at end of file diff --git a/src/main/hooklib/setupapi.h b/src/main/hooklib/setupapi.h index 9ebc4fa2..4053d484 100644 --- a/src/main/hooklib/setupapi.h +++ b/src/main/hooklib/setupapi.h @@ -15,4 +15,6 @@ struct hook_setupapi_data { void hook_setupapi_init(const struct hook_setupapi_data *data); +void hook_setupapi_fini(); + #endif diff --git a/src/main/iface-acio/Module.mk b/src/main/iface-acio/Module.mk new file mode 100644 index 00000000..2ade27f1 --- /dev/null +++ b/src/main/iface-acio/Module.mk @@ -0,0 +1,8 @@ +libs += iface-acio + +libs_iface-acio := \ + iface-core \ + util \ + +src_iface-acio := \ + mgr.c \ diff --git a/src/main/iface-acio/mgr.c b/src/main/iface-acio/mgr.c new file mode 100644 index 00000000..bd1e8c5e --- /dev/null +++ b/src/main/iface-acio/mgr.c @@ -0,0 +1,135 @@ +#define LOG_MODULE "bt-acio-mgr" + +#include + +#include "api/acio/mgr.h" + +#include "iface-core/log.h" + +#define BT_ACIO_MGR_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_acio_mgr_api_t _bt_acio_mgr_api; + +static bool _bt_acio_mgr_api_is_valid() +{ + return _bt_acio_mgr_api.version > 0; +} + +void bt_acio_mgr_api_set(const bt_acio_mgr_api_t *api) +{ + log_assert(api); + + if (_bt_acio_mgr_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_ACIO_MGR_ASSERT_IMPLEMENTED( + api->v1.port_init, "bt_acio_mgr_port_init"); + BT_ACIO_MGR_ASSERT_IMPLEMENTED( + api->v1.port_fini, "bt_acio_mgr_port_fini"); + BT_ACIO_MGR_ASSERT_IMPLEMENTED( + api->v1.node_count_get, "bt_acio_mgr_node_count_get"); + BT_ACIO_MGR_ASSERT_IMPLEMENTED( + api->v1.node_product_ident_get, + "bt_acio_mgr_node_product_ident_get"); + BT_ACIO_MGR_ASSERT_IMPLEMENTED( + api->v1.port_packet_submit, "bt_acio_mgr_port_packet_submit"); + BT_ACIO_MGR_ASSERT_IMPLEMENTED( + api->v1.port_checkout, "bt_acio_mgr_port_checkout"); + BT_ACIO_MGR_ASSERT_IMPLEMENTED( + api->v1.port_checkin, "bt_acio_mgr_port_checkin"); + + memcpy(&_bt_acio_mgr_api, api, sizeof(bt_acio_mgr_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_acio_mgr_api_get(bt_acio_mgr_api_t *api) +{ + log_assert(api); + log_assert(_bt_acio_mgr_api_is_valid()); + + memcpy(api, &_bt_acio_mgr_api, sizeof(bt_acio_mgr_api_t)); +} + +void bt_acio_mgr_api_clear() +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + memset(&_bt_acio_mgr_api, 0, sizeof(bt_acio_mgr_api_t)); + + log_misc("api cleared"); +} + +bt_acio_mgr_port_dispatcher_t * +bt_acio_mgr_port_init(const char *path, uint32_t baud) +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + log_misc("port init: %s, %d", path, baud); + + return _bt_acio_mgr_api.v1.port_init(path, baud); +} + +void bt_acio_mgr_port_fini(bt_acio_mgr_port_dispatcher_t *dispatcher) +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + log_misc(">>> port fini"); + + _bt_acio_mgr_api.v1.port_fini(dispatcher); + + log_misc("<<< port fini"); +} + +uint8_t +bt_acio_mgr_node_count_get(const bt_acio_mgr_port_dispatcher_t *dispatcher) +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + return _bt_acio_mgr_api.v1.node_count_get(dispatcher); +} + +bool bt_acio_mgr_node_product_ident_get( + const bt_acio_mgr_port_dispatcher_t *dispatcher, + uint8_t node_id, + char product[BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN]) +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + return _bt_acio_mgr_api.v1.node_product_ident_get( + dispatcher, node_id, product); +} + +bool bt_acio_mgr_port_packet_submit( + bt_acio_mgr_port_dispatcher_t *dispatcher, + bt_acio_message_t *msg, + uint32_t max_resp_size) +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + return _bt_acio_mgr_api.v1.port_packet_submit( + dispatcher, msg, max_resp_size); +} + +bt_acio_drv_device_ctx_t * +bt_acio_mgr_port_checkout(bt_acio_mgr_port_dispatcher_t *dispatcher) +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + return _bt_acio_mgr_api.v1.port_checkout(dispatcher); +} + +void bt_acio_mgr_port_checkin(bt_acio_mgr_port_dispatcher_t *dispatcher) +{ + log_assert(_bt_acio_mgr_api_is_valid()); + + _bt_acio_mgr_api.v1.port_checkin(dispatcher); +} diff --git a/src/main/aciomgr/manager.h b/src/main/iface-acio/mgr.h similarity index 54% rename from src/main/aciomgr/manager.h rename to src/main/iface-acio/mgr.h index d2127a8a..f2354676 100644 --- a/src/main/aciomgr/manager.h +++ b/src/main/iface-acio/mgr.h @@ -1,26 +1,14 @@ -#ifndef ACIOMGR_MANAGER_H -#define ACIOMGR_MANAGER_H +#ifndef BT_ACIO_MGR_H +#define BT_ACIO_MGR_H #include +#include -#include "bemanitools/glue.h" +#include "api/acio/mgr.h" -#define ACIOMGR_NODE_PRODUCT_CODE_LEN 4 - -struct ac_io_message; -struct aciodrv_device_ctx; -struct aciomgr_port_dispatcher; - -/** - * The first function that will be called on your DLL. You will be supplied - * with four function pointers that may be used to log messages to the game's - * log file. See comments in glue.h for further information. - */ -void aciomgr_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); +void bt_acio_mgr_api_set(const bt_acio_mgr_api_t *api); +void bt_acio_mgr_api_get(bt_acio_mgr_api_t *api); +void bt_acio_mgr_api_clear(); /** * Init and open, or return the existing handle to an acio port @@ -28,9 +16,10 @@ void aciomgr_set_loggers( * @param path Port the device is connected to (e.g. "COM1") * @return opened port dispatcher context, NULL on error */ -struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud); +bt_acio_mgr_port_dispatcher_t * +bt_acio_mgr_port_init(const char *path, uint32_t baud); -void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher); +void bt_acio_mgr_port_fini(bt_acio_mgr_port_dispatcher_t *dispatcher); /** * Get the node count on the opened device. @@ -38,7 +27,8 @@ void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher); * @param dispatcher dispatcher context from aciomgr_port_init * @return Total num of nodes enumerated on the ACIO device. */ -uint8_t aciomgr_get_node_count(struct aciomgr_port_dispatcher *dispatcher); +uint8_t +bt_acio_mgr_node_count_get(const bt_acio_mgr_port_dispatcher_t *dispatcher); /** * Get the product identifier of an enumerated node. @@ -49,10 +39,10 @@ uint8_t aciomgr_get_node_count(struct aciomgr_port_dispatcher *dispatcher); * @return True on success, false on error. If True the variable product * contains the identifier of the queried node. */ -bool aciomgr_get_node_product_ident( - struct aciomgr_port_dispatcher *dispatcher, +bool bt_acio_mgr_node_product_ident_get( + const bt_acio_mgr_port_dispatcher_t *dispatcher, uint8_t node_id, - char product[ACIOMGR_NODE_PRODUCT_CODE_LEN]); + char product[BT_ACIO_MGR_NODE_PRODUCT_CODE_LEN]); /** * Submit and wait for the response of the specified packet @@ -62,10 +52,10 @@ bool aciomgr_get_node_product_ident( * @param max_resp_size pointer to the max size response we expect * @return false on error */ -bool aciomgr_port_submit_packet( - struct aciomgr_port_dispatcher *dispatcher, - struct ac_io_message *msg, - int max_resp_size); +bool bt_acio_mgr_port_packet_submit( + const bt_acio_mgr_port_dispatcher_t *dispatcher, + const bt_acio_message_t *msg, + uint32_t max_resp_size); /** * Checkout the device handler for this port dispatcher on this thread @@ -73,14 +63,14 @@ bool aciomgr_port_submit_packet( * @param dispatcher dispatcher context from aciomgr_port_init * @return the device context */ -struct aciodrv_device_ctx * -aciomgr_port_checkout(struct aciomgr_port_dispatcher *dispatcher); +bt_acio_drv_device_ctx_t * +bt_acio_mgr_port_checkout(const bt_acio_mgr_port_dispatcher_t *dispatcher); /** * Checkin the device handler that this thread holds * * @param dispatcher dispatcher context from aciomgr_port_init */ -void aciomgr_port_checkin(struct aciomgr_port_dispatcher *dispatcher); +void bt_acio_mgr_port_checkin(const bt_acio_mgr_port_dispatcher_t *dispatcher); -#endif +#endif \ No newline at end of file diff --git a/src/main/iface-core/Module.mk b/src/main/iface-core/Module.mk new file mode 100644 index 00000000..ddcbcd03 --- /dev/null +++ b/src/main/iface-core/Module.mk @@ -0,0 +1,9 @@ +libs += iface-core + +libs_iface-core := \ + util \ + +src_iface-core := \ + config.c \ + log.c \ + thread.c \ diff --git a/src/main/iface-core/config.c b/src/main/iface-core/config.c new file mode 100644 index 00000000..029ff902 --- /dev/null +++ b/src/main/iface-core/config.c @@ -0,0 +1,245 @@ +#define LOG_MODULE "bt-core-config" + +#include +#include +#include + +#include "api/core/config.h" + +#include "iface-core/log.h" + +#define BT_CORE_CONFIG_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_core_config_api_t _bt_core_config_api; + +static bool _bt_core_config_api_is_valid() +{ + return _bt_core_config_api.version > 0; +} + +void bt_core_config_api_set(const bt_core_config_api_t *api) +{ + log_assert(api); + + if (_bt_core_config_api_is_valid()) { + log_info("Re-initialize"); + } + + if (api->version == 1) { + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.s8_get, s8_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.u8_get, u8_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.s16_get, s16_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.u16_get, u16_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.s32_get, s32_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.u32_get, u32_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.s64_get, s64_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.u64_get, u64_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.float_get, float_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.double_get, double_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.bool_get, bool_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.bin_get, bin_get); + BT_CORE_CONFIG_ASSERT_IMPLEMENTED(api->v1.str_get, str_get); + + memcpy(&_bt_core_config_api, api, sizeof(bt_core_config_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_core_config_api_get(bt_core_config_api_t *api) +{ + log_assert(api); + log_assert(_bt_core_config_api_is_valid()); + + memcpy(api, &_bt_core_config_api, sizeof(bt_core_config_api_t)); +} + +void bt_core_config_api_clear() +{ + log_assert(_bt_core_config_api_is_valid()); + + memset(&_bt_core_config_api, 0, sizeof(bt_core_config_api_t)); + + log_misc("api cleared"); +} + +const char *bt_core_config_result_to_str(bt_core_config_result_t result) +{ + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return "Success"; + case BT_CORE_CONFIG_RESULT_ERROR_INTERNAL: + return "Internal"; + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + return "Value not found"; + case BT_CORE_CONFIG_RESULT_TYPE_MISMATCH: + return "Type mismatch"; + default: + return "Undefined error"; + } +} + +void bt_core_config_fatal_on_error(bt_core_config_result_t result, const char *path) +{ + switch (result) { + case BT_CORE_CONFIG_RESULT_SUCCESS: + return; + case BT_CORE_CONFIG_RESULT_ERROR_INTERNAL: + case BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND: + case BT_CORE_CONFIG_RESULT_TYPE_MISMATCH: + default: + log_fatal( + "Operation on config for path \"%s\" failed: %s", path, + bt_core_config_result_to_str(result)); + } +} + +bt_core_config_result_t bt_core_config_s8_get( + const bt_core_config_t *config, const char *path, int8_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.s8_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_u8_get( + const bt_core_config_t *config, const char *path, uint8_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.u8_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_s16_get( + const bt_core_config_t *config, const char *path, int16_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.s16_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_u16_get( + const bt_core_config_t *config, const char *path, uint16_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.u16_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_s32_get( + const bt_core_config_t *config, const char *path, int32_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.s32_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_u32_get( + const bt_core_config_t *config, const char *path, uint32_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.u32_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_s64_get( + const bt_core_config_t *config, const char *path, int64_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.s64_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_u64_get( + const bt_core_config_t *config, const char *path, uint64_t *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.u64_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_float_get( + const bt_core_config_t *config, const char *path, float *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.float_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_double_get( + const bt_core_config_t *config, const char *path, double *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.double_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_bool_get( + const bt_core_config_t *config, const char *path, bool *value) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + + return _bt_core_config_api.v1.bool_get(config, path, value); +} + +bt_core_config_result_t bt_core_config_bin_get( + const bt_core_config_t *config, const char *path, void *value, size_t len) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + log_assert(len > 0); + + return _bt_core_config_api.v1.bin_get(config, path, value, len); +} + +bt_core_config_result_t bt_core_config_str_get( + const bt_core_config_t *config, const char *path, char *value, size_t len) +{ + log_assert(_bt_core_config_api_is_valid()); + log_assert(config); + log_assert(path); + log_assert(value); + log_assert(len > 0); + + return _bt_core_config_api.v1.str_get(config, path, value, len); +} \ No newline at end of file diff --git a/src/main/iface-core/config.h b/src/main/iface-core/config.h new file mode 100644 index 00000000..8fd22cc3 --- /dev/null +++ b/src/main/iface-core/config.h @@ -0,0 +1,42 @@ +#ifndef BT_CORE_CONFIG_H +#define BT_CORE_CONFIG_H + +#include + +#include "api/core/config.h" + +void bt_core_config_api_set(const bt_core_config_api_t *api); +void bt_core_config_api_get(bt_core_config_api_t *api); +void bt_core_config_api_clear(); + +const char *bt_core_config_result_to_str(bt_core_config_result_t result); +void bt_core_config_fatal_on_error(bt_core_config_result_t result, const char *path); + +bt_core_config_result_t bt_core_config_s8_get( + const bt_core_config_t *config, const char *path, int8_t *value); +bt_core_config_result_t bt_core_config_u8_get( + const bt_core_config_t *config, const char *path, uint8_t *value); +bt_core_config_result_t bt_core_config_s16_get( + const bt_core_config_t *config, const char *path, int16_t *value); +bt_core_config_result_t bt_core_config_u16_get( + const bt_core_config_t *config, const char *path, uint16_t *value); +bt_core_config_result_t bt_core_config_s32_get( + const bt_core_config_t *config, const char *path, int32_t *value); +bt_core_config_result_t bt_core_config_u32_get( + const bt_core_config_t *config, const char *path, uint32_t *value); +bt_core_config_result_t bt_core_config_s64_get( + const bt_core_config_t *config, const char *path, int64_t *value); +bt_core_config_result_t bt_core_config_u64_get( + const bt_core_config_t *config, const char *path, uint64_t *value); +bt_core_config_result_t bt_core_config_float_get( + const bt_core_config_t *config, const char *path, float *value); +bt_core_config_result_t bt_core_config_double_get( + const bt_core_config_t *config, const char *path, double *value); +bt_core_config_result_t bt_core_config_bool_get( + const bt_core_config_t *config, const char *path, bool *value); +bt_core_config_result_t bt_core_config_bin_get( + const bt_core_config_t *config, const char *path, void *value, size_t len); +bt_core_config_result_t bt_core_config_str_get( + const bt_core_config_t *config, const char *path, char *value, size_t len); + +#endif \ No newline at end of file diff --git a/src/main/iface-core/log.c b/src/main/iface-core/log.c new file mode 100644 index 00000000..97a987bc --- /dev/null +++ b/src/main/iface-core/log.c @@ -0,0 +1,58 @@ +#define LOG_MODULE "bt-core-log" + +#include +#include +#include + +#include "iface-core/log.h" + +#define BT_CORE_LOG_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +bt_core_log_api_t _bt_core_log_api; + +static bool _bt_core_log_api_is_valid() +{ + return _bt_core_log_api.version > 0; +} + +void bt_core_log_api_set(const bt_core_log_api_t *api) +{ + log_assert(api); + + if (_bt_core_log_api_is_valid()) { + log_info("Re-initialize"); + } + + if (api->version == 1) { + BT_CORE_LOG_ASSERT_IMPLEMENTED(api->v1.misc, misc); + BT_CORE_LOG_ASSERT_IMPLEMENTED(api->v1.info, info); + BT_CORE_LOG_ASSERT_IMPLEMENTED(api->v1.warning, warning); + BT_CORE_LOG_ASSERT_IMPLEMENTED(api->v1.fatal, fatal); + + memcpy(&_bt_core_log_api, api, sizeof(bt_core_log_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_core_log_api_get(bt_core_log_api_t *api) +{ + log_assert(api); + log_assert(_bt_core_log_api_is_valid()); + + memcpy(api, &_bt_core_log_api, sizeof(bt_core_log_api_t)); +} + +void bt_core_log_api_clear() +{ + log_assert(_bt_core_log_api_is_valid()); + + memset(&_bt_core_log_api, 0, sizeof(bt_core_log_api_t)); + + log_misc("api cleared"); +} \ No newline at end of file diff --git a/src/main/iface-core/log.h b/src/main/iface-core/log.h new file mode 100644 index 00000000..a935e7ee --- /dev/null +++ b/src/main/iface-core/log.h @@ -0,0 +1,149 @@ +#ifndef BT_CORE_LOG_H +#define BT_CORE_LOG_H + +#include +#include +#include + +#include "util/defs.h" + +#include "api/core/log.h" + +/** + * The core log API of bemanitools. + * + * To a large extent, this reflects the AVS logging API and allows for swapping + * out the backends with different implementations. Most games should have some + * version of the AVS API available while some (legacy) games do not. These + * can use a bemanitools private logging implementation by configuring it + * in the bootstrapping process. + */ + +/* BUILD_MODULE is passed in as a command-line #define by the makefile */ + +#ifndef LOG_MODULE +#define LOG_MODULE STRINGIFY(BUILD_MODULE) +#endif + +/** + * Log a message on misc level + * + * Always use this interface in your application which hides the currently + * configured implementation. + * + * The macro is required to make things work with varargs. + * The log message is only printed if the log level is set to misc + * + * @param fmt printf format string + * @param ... Additional arguments according to the specified arguments in the + * printf format string + */ +#define log_misc_func _bt_core_log_api.v1.misc +#define log_misc(...) log_misc_func(LOG_MODULE, __VA_ARGS__) + +/** + * Log a message on info level + * + * Always use this interface in your application which hides the currently + * configured implementation. + * + * The macro is required to make things work with varargs. + * The log message is only printed if the log level is set to info or lower + * + * @param fmt printf format string + * @param ... Additional arguments according to the specified arguments in the + * printf format string + */ +#define log_info(...) _bt_core_log_api.v1.info(LOG_MODULE, __VA_ARGS__) + +/** + * Log a message on warning level + * + * Always use this interface in your application which hides the currently + * configured implementation. + * + * The macro is required to make things work with varargs. + * The log message is only printed if the log level is set to warning or lower + * + * @param fmt printf format string + * @param ... Additional arguments according to the specified arguments in the + * printf format string + */ +#define log_warning(...) _bt_core_log_api.v1.warning(LOG_MODULE, __VA_ARGS__) + +/** + * Log a message on fatal level + * + * Always use this interface in your application which hides the currently + * configured implementation. + * + * The macro is required to make things work with varargs. + * The log message is only printed if the log level is set to fatal. + * + * This call will also terminate the application. + * + * @param fmt printf format string + * @param ... Additional arguments according to the specified arguments in the + * printf format string + */ +// Additional empty log statement to trigger flush on some sinks. +// Otherwise, the last message might get lost +#define log_fatal(...) \ + do { \ + _bt_core_log_api.v1.fatal( \ + LOG_MODULE, \ + "%s:%d: function `%s'", \ + __FILE__, \ + __LINE__, \ + __FUNCTION__); \ + _bt_core_log_api.v1.fatal(LOG_MODULE, __VA_ARGS__); \ + _bt_core_log_api.v1.fatal(LOG_MODULE, ""); \ + abort(); \ + } while (0) + +/** + * Log a message and terminate the application if given condition fails + * + * Always use this interface in your application which hides the currently + * configured implementation. + * + * The macro is required to make things work with varargs. + * + * @param x Condition to evaluate. If false, the application terminates + */ +#define log_assert(x) \ + do { \ + if (!(x)) { \ + _bt_core_log_api.v1.fatal( \ + "assert", \ + "%s:%d: function `%s'", \ + __FILE__, \ + __LINE__, \ + __FUNCTION__); \ + abort(); \ + } \ + } while (0) + +/** + * Log a message in an exception handler + * + * Only use this function in an exception handler, e.g. for stack traces. It + * logs the message on fatal level but does not terminate. + * + * @param fmt printf format string + * @param ... Additional arguments according to the specified arguments in the + * printf format string + */ +#define log_exception_handler(...) \ + _bt_core_log_api.v1.fatal("exception", __VA_ARGS__) + +void bt_core_log_api_set(const bt_core_log_api_t *api); +void bt_core_log_api_get(bt_core_log_api_t *api); +void bt_core_log_api_clear(); + +// Do not use this directly. This is required to work around requiring the +// interface to use var args. Use the macros above to invoke the logging +// functions +extern bt_core_log_api_t _bt_core_log_api; + +#endif \ No newline at end of file diff --git a/src/main/iface-core/thread.c b/src/main/iface-core/thread.c new file mode 100644 index 00000000..093d77e0 --- /dev/null +++ b/src/main/iface-core/thread.c @@ -0,0 +1,115 @@ +#define LOG_MODULE "bt-core-thread" + +#include +#include +#include + +#include "api/core/thread.h" + +#include "iface-core/log.h" + +#define BT_CORE_THREAD_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_core_thread_api_t _bt_core_thread_api; + +static bool _bt_core_thread_api_is_valid() +{ + return _bt_core_thread_api.version > 0; +} + +void bt_core_thread_api_set(const bt_core_thread_api_t *api) +{ + log_assert(api); + + if (_bt_core_thread_api_is_valid()) { + log_info("Re-initialize"); + } + + if (api->version == 1) { + BT_CORE_THREAD_ASSERT_IMPLEMENTED(api->v1.create, create); + BT_CORE_THREAD_ASSERT_IMPLEMENTED(api->v1.join, join); + BT_CORE_THREAD_ASSERT_IMPLEMENTED(api->v1.destroy, destroy); + + memcpy(&_bt_core_thread_api, api, sizeof(bt_core_thread_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_core_thread_api_get(bt_core_thread_api_t *api) +{ + log_assert(api); + log_assert(_bt_core_thread_api_is_valid()); + + memcpy(api, &_bt_core_thread_api, sizeof(bt_core_thread_api_t)); +} + +void bt_core_thread_api_clear() +{ + log_assert(_bt_core_thread_api_is_valid()); + + memset(&_bt_core_thread_api, 0, sizeof(bt_core_thread_api_t)); + + log_misc("api cleared"); +} + +const char *bt_core_thread_result_to_str(bt_core_thread_result_t result) +{ + switch (result) { + case BT_CORE_THREAD_RESULT_SUCCESS: + return "Success"; + case BT_CORE_THREAD_RESULT_ERROR_INTERNAL: + return "Internal"; + default: + return "Undefined error"; + } +} + +void bt_core_thread_fatal_on_error(bt_core_thread_result_t result) +{ + switch (result) { + case BT_CORE_THREAD_RESULT_SUCCESS: + return; + case BT_CORE_THREAD_RESULT_ERROR_INTERNAL: + default: + log_fatal( + "Operation on thread failed: %s", + bt_core_thread_result_to_str(result)); + } +} + +bt_core_thread_result_t bt_core_thread_create( + int (*proc)(void *), + void *ctx, + uint32_t stack_sz, + unsigned int priority, + bt_core_thread_id_t *thread_id) +{ + log_assert(_bt_core_thread_api_is_valid()); + log_assert(proc); + log_assert(stack_sz > 0); + log_assert(thread_id); + + return _bt_core_thread_api.v1.create( + proc, ctx, stack_sz, priority, thread_id); +} + +bt_core_thread_result_t +bt_core_thread_join(bt_core_thread_id_t thread_id, int *result) +{ + log_assert(_bt_core_thread_api_is_valid()); + + return _bt_core_thread_api.v1.join(thread_id, result); +} + +bt_core_thread_result_t bt_core_thread_destroy(bt_core_thread_id_t thread_id) +{ + log_assert(_bt_core_thread_api_is_valid()); + + return _bt_core_thread_api.v1.destroy(thread_id); +} diff --git a/src/main/iface-core/thread.h b/src/main/iface-core/thread.h new file mode 100644 index 00000000..2bf1d46c --- /dev/null +++ b/src/main/iface-core/thread.h @@ -0,0 +1,25 @@ +#ifndef BT_CORE_THREAD_H +#define BT_CORE_THREAD_H + +#include + +#include "api/core/thread.h" + +void bt_core_thread_api_set(const bt_core_thread_api_t *api); +void bt_core_thread_api_get(bt_core_thread_api_t *api); +void bt_core_thread_api_clear(); + +const char *bt_core_thread_result_to_str(bt_core_thread_result_t result); +void bt_core_thread_fatal_on_error(bt_core_thread_result_t result); + +bt_core_thread_result_t bt_core_thread_create( + int (*proc)(void *), + void *ctx, + uint32_t stack_sz, + unsigned int priority, + bt_core_thread_id_t *thread_id); +bt_core_thread_result_t +bt_core_thread_join(bt_core_thread_id_t thread_id, int *result); +bt_core_thread_result_t bt_core_thread_destroy(bt_core_thread_id_t thread_id); + +#endif diff --git a/src/main/iface-io/Module.mk b/src/main/iface-io/Module.mk new file mode 100644 index 00000000..33f8122f --- /dev/null +++ b/src/main/iface-io/Module.mk @@ -0,0 +1,15 @@ +libs += iface-io + +libs_iface-io := \ + util \ + +src_iface-io := \ + bst.c \ + eam.c \ + ddr.c \ + eam.c \ + iidx.c \ + jb.c \ + popn.c \ + sdvx.c \ + vefx.c \ diff --git a/src/main/iface-io/bst.c b/src/main/iface-io/bst.c new file mode 100644 index 00000000..87c7be3a --- /dev/null +++ b/src/main/iface-io/bst.c @@ -0,0 +1,100 @@ +#define LOG_MODULE "bt-io-bst" + +#include + +#include "api/io/bst.h" + +#include "iface-core/log.h" + +#define BT_IO_BST_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_bst_api_t _bt_io_bst_api; + +static bool _bt_io_bst_api_is_valid() +{ + return _bt_io_bst_api.version > 0; +} + +void bt_io_bst_api_set(const bt_io_bst_api_t *api) +{ + log_assert(api); + + if (_bt_io_bst_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_BST_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_bst_init"); + BT_IO_BST_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_bst_fini"); + + BT_IO_BST_ASSERT_IMPLEMENTED( + api->v1.input_read, "bt_io_bst_input_read"); + BT_IO_BST_ASSERT_IMPLEMENTED(api->v1.input_get, "bt_io_bst_input_get"); + + memcpy(&_bt_io_bst_api, api, sizeof(bt_io_bst_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_bst_api_get(bt_io_bst_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_bst_api_is_valid()); + + memcpy(api, &_bt_io_bst_api, sizeof(bt_io_bst_api_t)); +} + +void bt_io_bst_api_clear() +{ + log_assert(_bt_io_bst_api_is_valid()); + + memset(&_bt_io_bst_api, 0, sizeof(bt_io_bst_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_bst_init() +{ + bool result; + + log_assert(_bt_io_bst_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_bst_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_bst_fini() +{ + log_assert(_bt_io_bst_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_bst_api.v1.fini(); + + log_misc("<<< fini"); +} + +bool bt_io_bst_input_read() +{ + log_assert(_bt_io_bst_api_is_valid()); + + return _bt_io_bst_api.v1.input_read(); +} + +uint8_t bt_io_bst_input_get() +{ + log_assert(_bt_io_bst_api_is_valid()); + + return _bt_io_bst_api.v1.input_get(); +} \ No newline at end of file diff --git a/src/main/iface-io/bst.h b/src/main/iface-io/bst.h new file mode 100644 index 00000000..41845fd0 --- /dev/null +++ b/src/main/iface-io/bst.h @@ -0,0 +1,19 @@ +#ifndef API_IO_BST_H +#define API_IO_BST_H + +#include +#include + +#include "api/io/bst.h" + +void bt_io_bst_api_set(const bt_io_bst_api_t *api); +void bt_io_bst_api_get(bt_io_bst_api_t *api); +void bt_io_bst_api_clear(); + +bool bt_io_bst_init(); +void bt_io_bst_fini(); + +bool bt_io_bst_input_read(); +uint8_t bt_io_bst_input_get(); + +#endif \ No newline at end of file diff --git a/src/main/iface-io/ddr.c b/src/main/iface-io/ddr.c new file mode 100644 index 00000000..f4486894 --- /dev/null +++ b/src/main/iface-io/ddr.c @@ -0,0 +1,142 @@ +#define LOG_MODULE "bt-io-ddr" + +#include + +#include "api/io/ddr.h" + +#include "iface-core/log.h" + +#define BT_IO_DDR_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_ddr_api_t _bt_io_ddr_api; + +static bool _bt_io_ddr_api_is_valid() +{ + return _bt_io_ddr_api.version > 0; +} + +void bt_io_ddr_api_set(const bt_io_ddr_api_t *api) +{ + log_assert(api); + + if (_bt_io_ddr_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_DDR_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_ddr_init"); + BT_IO_DDR_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_ddr_fini"); + + BT_IO_DDR_ASSERT_IMPLEMENTED(api->v1.pad_read, "bt_io_ddr_pad_read"); + BT_IO_DDR_ASSERT_IMPLEMENTED( + api->v1.extio_lights_set, "bt_io_ddr_extio_lights_set"); + BT_IO_DDR_ASSERT_IMPLEMENTED( + api->v1.p3io_lights_set, "bt_io_ddr_p3io_lights_set"); + BT_IO_DDR_ASSERT_IMPLEMENTED( + api->v1.hdxs_lights_panel_set, "bt_io_ddr_hdxs_lights_panel_set"); + BT_IO_DDR_ASSERT_IMPLEMENTED( + api->v1.hdxs_lights_rgb_set, "bt_io_ddr_hdxs_lights_rgb_set"); + + memcpy(&_bt_io_ddr_api, api, sizeof(bt_io_ddr_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_ddr_api_get(bt_io_ddr_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_ddr_api_is_valid()); + + memcpy(api, &_bt_io_ddr_api, sizeof(bt_io_ddr_api_t)); +} + +void bt_io_ddr_api_clear() +{ + log_assert(_bt_io_ddr_api_is_valid()); + + memset(&_bt_io_ddr_api, 0, sizeof(bt_io_ddr_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_ddr_init() +{ + bool result; + + log_assert(_bt_io_ddr_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_ddr_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_ddr_fini() +{ + log_assert(_bt_io_ddr_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_ddr_api.v1.fini(); + + log_misc("<<< fini"); +} + +uint32_t bt_io_ddr_pad_read() +{ + log_assert(_bt_io_ddr_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_ddr_api.v1.pad_read(); +} + +void bt_io_ddr_extio_lights_set(uint32_t extio_lights) +{ + log_assert(_bt_io_ddr_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_ddr_api.v1.extio_lights_set(extio_lights); +} + +void bt_io_ddr_p3io_lights_set(uint32_t p3io_lights) +{ + log_assert(_bt_io_ddr_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_ddr_api.v1.p3io_lights_set(p3io_lights); +} + +void bt_io_ddr_hdxs_lights_panel_set(uint32_t hdxs_lights) +{ + log_assert(_bt_io_ddr_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_ddr_api.v1.hdxs_lights_panel_set(hdxs_lights); +} + +void bt_io_ddr_hdxs_lights_rgb_set(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +{ + log_assert(_bt_io_ddr_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_ddr_api.v1.hdxs_lights_rgb_set(idx, r, g, b); +} diff --git a/src/main/iface-io/ddr.h b/src/main/iface-io/ddr.h new file mode 100644 index 00000000..f04ef11b --- /dev/null +++ b/src/main/iface-io/ddr.h @@ -0,0 +1,23 @@ +#ifndef API_IO_DDR_H +#define API_IO_DDR_H + +#include +#include + +#include "api/io/ddr.h" + +void bt_io_ddr_api_set(const bt_io_ddr_api_t *api); +void bt_io_ddr_api_get(bt_io_ddr_api_t *api); +void bt_io_ddr_api_clear(); + +bool bt_io_ddr_init(); +void bt_io_ddr_fini(); + +uint32_t bt_io_ddr_pad_read(); +void bt_io_ddr_extio_lights_set(uint32_t extio_lights); +void bt_io_ddr_p3io_lights_set(uint32_t p3io_lights); +void bt_io_ddr_hdxs_lights_panel_set(uint32_t hdxs_lights); +void bt_io_ddr_hdxs_lights_rgb_set( + uint8_t idx, uint8_t r, uint8_t g, uint8_t b); + +#endif \ No newline at end of file diff --git a/src/main/iface-io/eam.c b/src/main/iface-io/eam.c new file mode 100644 index 00000000..6abe5d49 --- /dev/null +++ b/src/main/iface-io/eam.c @@ -0,0 +1,137 @@ +#define LOG_MODULE "bt-io-eam" + +#include + +#include "api/io/eam.h" + +#include "iface-core/log.h" + +#define BT_IO_EAM_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_eam_api_t _bt_io_eam_api; + +static bool _bt_io_eam_api_is_valid() +{ + return _bt_io_eam_api.version > 0; +} + +void bt_io_eam_api_set(const bt_io_eam_api_t *api) +{ + log_assert(api); + + if (_bt_io_eam_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_EAM_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_eam_init"); + BT_IO_EAM_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_eam_fini"); + + BT_IO_EAM_ASSERT_IMPLEMENTED( + api->v1.keypad_state_get, "bt_io_eam_keypad_state_get"); + BT_IO_EAM_ASSERT_IMPLEMENTED( + api->v1.sensor_state_get, "bt_io_eam_sensor_state_get"); + BT_IO_EAM_ASSERT_IMPLEMENTED(api->v1.card_read, "bt_io_eam_card_read"); + BT_IO_EAM_ASSERT_IMPLEMENTED( + api->v1.card_slot_cmd_send, "bt_io_eam_card_slot_cmd_send"); + BT_IO_EAM_ASSERT_IMPLEMENTED(api->v1.poll, "bt_io_eam_poll"); + + BT_IO_EAM_ASSERT_IMPLEMENTED( + api->v1.config_api_get, "bt_io_eam_config_api_get"); + + memcpy(&_bt_io_eam_api, api, sizeof(bt_io_eam_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_eam_api_get(bt_io_eam_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_eam_api_is_valid()); + + memcpy(api, &_bt_io_eam_api, sizeof(bt_io_eam_api_t)); +} + +void bt_io_eam_api_clear() +{ + log_assert(_bt_io_eam_api_is_valid()); + + memset(&_bt_io_eam_api, 0, sizeof(bt_io_eam_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_eam_init() +{ + bool result; + + log_assert(_bt_io_eam_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_eam_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_eam_fini() +{ + log_assert(_bt_io_eam_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_eam_api.v1.fini(); + + log_misc("<<< fini"); +} + +uint16_t bt_io_eam_keypad_state_get(uint8_t unit_no) +{ + log_assert(_bt_io_eam_api_is_valid()); + + return _bt_io_eam_api.v1.keypad_state_get(unit_no); +} + +uint8_t bt_io_eam_sensor_state_get(uint8_t unit_no) +{ + log_assert(_bt_io_eam_api_is_valid()); + + return _bt_io_eam_api.v1.sensor_state_get(unit_no); +} + +uint8_t bt_io_eam_card_read(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes) +{ + log_assert(_bt_io_eam_api_is_valid()); + log_assert(card_id); + + return _bt_io_eam_api.v1.card_read(unit_no, card_id, nbytes); +} + +bool bt_io_eam_card_slot_cmd_send(uint8_t unit_no, uint8_t cmd) +{ + log_assert(_bt_io_eam_api_is_valid()); + + return _bt_io_eam_api.v1.card_slot_cmd_send(unit_no, cmd); +} + +bool bt_io_eam_poll(uint8_t unit_no) +{ + log_assert(_bt_io_eam_api_is_valid()); + + return _bt_io_eam_api.v1.poll(unit_no); +} + +const bt_io_eam_config_api_t *bt_io_eam_config_api_get() +{ + log_assert(_bt_io_eam_api_is_valid()); + + return _bt_io_eam_api.v1.config_api_get(); +} \ No newline at end of file diff --git a/src/main/iface-io/eam.h b/src/main/iface-io/eam.h new file mode 100644 index 00000000..0ebc8664 --- /dev/null +++ b/src/main/iface-io/eam.h @@ -0,0 +1,23 @@ +#ifndef API_IO_EAM_H +#define API_IO_EAM_H + +#include +#include + +#include "api/io/eam.h" + +void bt_io_eam_api_set(const bt_io_eam_api_t *api); +void bt_io_eam_api_get(bt_io_eam_api_t *api); +void bt_io_eam_api_clear(); + +bool bt_io_eam_init(); +void bt_io_eam_fini(); + +uint16_t bt_io_eam_keypad_state_get(uint8_t unit_no); +uint8_t bt_io_eam_sensor_state_get(uint8_t unit_no); +uint8_t bt_io_eam_card_read(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes); +bool bt_io_eam_card_slot_cmd_send(uint8_t unit_no, uint8_t cmd); +bool bt_io_eam_poll(uint8_t unit_no); +const bt_io_eam_config_api_t *bt_io_eam_config_api_get(); + +#endif \ No newline at end of file diff --git a/src/main/iface-io/iidx.c b/src/main/iface-io/iidx.c new file mode 100644 index 00000000..80b52ce2 --- /dev/null +++ b/src/main/iface-io/iidx.c @@ -0,0 +1,225 @@ +#define LOG_MODULE "bt-io-iidx" + +#include + +#include "api/io/iidx.h" + +#include "iface-core/log.h" + +#define BT_IO_IIDX_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_iidx_api_t _bt_io_iidx_api; + +static bool _bt_io_iidx_api_is_valid() +{ + return _bt_io_iidx_api.version > 0; +} + +void bt_io_iidx_api_set(const bt_io_iidx_api_t *api) +{ + log_assert(api); + + if (_bt_io_iidx_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_IIDX_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_iidx_init"); + BT_IO_IIDX_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_iidx_fini"); + + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep1_deck_lights_set, "bt_io_iidx_ep1_deck_lights_set"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep1_panel_lights_set, "bt_io_iidx_ep1_panel_lights_set"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep1_top_lamps_set, "bt_io_iidx_ep1_top_lamps_set"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep1_top_neons_set, "bt_io_iidx_ep1_top_neons_set"); + BT_IO_IIDX_ASSERT_IMPLEMENTED(api->v1.ep1_send, "bt_io_iidx_ep1_send"); + BT_IO_IIDX_ASSERT_IMPLEMENTED(api->v1.ep2_recv, "bt_io_iidx_ep2_recv"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep2_turntable_get, "bt_io_iidx_ep2_turntable_get"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep2_slider_get, "bt_io_iidx_ep2_slider_get"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep2_sys_get, "bt_io_iidx_ep2_sys_get"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep2_panel_get, "bt_io_iidx_ep2_panel_get"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep2_keys_get, "bt_io_iidx_ep2_keys_get"); + BT_IO_IIDX_ASSERT_IMPLEMENTED( + api->v1.ep3_16seg_send, "bt_io_iidx_ep3_16seg_send"); + + memcpy(&_bt_io_iidx_api, api, sizeof(bt_io_iidx_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_iidx_api_get(bt_io_iidx_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_iidx_api_is_valid()); + + memcpy(api, &_bt_io_iidx_api, sizeof(bt_io_iidx_api_t)); +} + +void bt_io_iidx_api_clear() +{ + log_assert(_bt_io_iidx_api_is_valid()); + + memset(&_bt_io_iidx_api, 0, sizeof(bt_io_iidx_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_iidx_init() +{ + bool result; + + log_assert(_bt_io_iidx_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_iidx_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_iidx_fini() +{ + log_assert(_bt_io_iidx_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_iidx_api.v1.fini(); + + log_misc("<<< fini"); +} + +void bt_io_iidx_ep1_deck_lights_set(uint16_t deck_lights) +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_iidx_api.v1.ep1_deck_lights_set(deck_lights); +} + +void bt_io_iidx_ep1_panel_lights_set(uint8_t panel_lights) +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_iidx_api.v1.ep1_panel_lights_set(panel_lights); +} + +void bt_io_iidx_ep1_top_lamps_set(uint8_t top_lamps) +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_iidx_api.v1.ep1_top_lamps_set(top_lamps); +} + +void bt_io_iidx_ep1_top_neons_set(bool top_neons) +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_iidx_api.v1.ep1_top_neons_set(top_neons); +} + +bool bt_io_iidx_ep1_send() +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep1_send(); +} + +bool bt_io_iidx_ep2_recv() +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep2_recv(); +} + +uint8_t bt_io_iidx_ep2_turntable_get(uint8_t player_no) +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep2_turntable_get(player_no); +} + +uint8_t bt_io_iidx_ep2_slider_get(uint8_t slider_no) +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep2_slider_get(slider_no); +} + +uint8_t bt_io_iidx_ep2_sys_get() +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep2_sys_get(); +} + +uint8_t bt_io_iidx_ep2_panel_get() +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep2_panel_get(); +} + +uint16_t bt_io_iidx_ep2_keys_get() +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep2_keys_get(); +} + +bool bt_io_iidx_ep3_16seg_send(const char *text) +{ + log_assert(_bt_io_iidx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_iidx_api.v1.ep3_16seg_send(text); +} diff --git a/src/main/iface-io/iidx.h b/src/main/iface-io/iidx.h new file mode 100644 index 00000000..a7ebbc00 --- /dev/null +++ b/src/main/iface-io/iidx.h @@ -0,0 +1,28 @@ +#ifndef API_IO_IIDX_H +#define API_IO_IIDX_H + +#include +#include + +#include "api/io/iidx.h" + +void bt_io_iidx_api_set(const bt_io_iidx_api_t *api); +void bt_io_iidx_api_get(bt_io_iidx_api_t *api); +void bt_io_iidx_api_clear(); + +bool bt_io_iidx_init(); +void bt_io_iidx_fini(); +void bt_io_iidx_ep1_deck_lights_set(uint16_t deck_lights); +void bt_io_iidx_ep1_panel_lights_set(uint8_t panel_lights); +void bt_io_iidx_ep1_top_lamps_set(uint8_t top_lamps); +void bt_io_iidx_ep1_top_neons_set(bool top_neons); +bool bt_io_iidx_ep1_send(); +bool bt_io_iidx_ep2_recv(); +uint8_t bt_io_iidx_ep2_turntable_get(uint8_t player_no); +uint8_t bt_io_iidx_ep2_slider_get(uint8_t slider_no); +uint8_t bt_io_iidx_ep2_sys_get(); +uint8_t bt_io_iidx_ep2_panel_get(); +uint16_t bt_io_iidx_ep2_keys_get(); +bool bt_io_iidx_ep3_16seg_send(const char *text); + +#endif \ No newline at end of file diff --git a/src/main/iface-io/jb.c b/src/main/iface-io/jb.c new file mode 100644 index 00000000..7ae18238 --- /dev/null +++ b/src/main/iface-io/jb.c @@ -0,0 +1,168 @@ +#define LOG_MODULE "bt-io-jb" + +#include + +#include "api/io/jb.h" + +#include "iface-core/log.h" + +#define BT_IO_JB_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_jb_api_t _bt_io_jb_api; + +static bool _bt_io_jb_api_is_valid() +{ + return _bt_io_jb_api.version > 0; +} + +void bt_io_jb_api_set(const bt_io_jb_api_t *api) +{ + log_assert(api); + + if (_bt_io_jb_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_JB_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_jb_init"); + BT_IO_JB_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_jb_fini"); + + BT_IO_JB_ASSERT_IMPLEMENTED( + api->v1.inputs_read, "bt_io_jb_inputs_read"); + BT_IO_JB_ASSERT_IMPLEMENTED( + api->v1.sys_inputs_get, "bt_io_jb_sys_inputs_get"); + BT_IO_JB_ASSERT_IMPLEMENTED( + api->v1.panel_inputs_get, "bt_io_jb_panel_inputs_get"); + BT_IO_JB_ASSERT_IMPLEMENTED( + api->v1.rgb_led_set, "bt_io_jb_rgb_led_set"); + BT_IO_JB_ASSERT_IMPLEMENTED( + api->v1.lights_write, "bt_io_jb_lights_write"); + BT_IO_JB_ASSERT_IMPLEMENTED( + api->v1.panel_mode_set, "bt_io_jb_panel_mode_set"); + BT_IO_JB_ASSERT_IMPLEMENTED( + api->v1.coin_blocker_set, "bt_io_jb_coin_blocker_set"); + + memcpy(&_bt_io_jb_api, api, sizeof(bt_io_jb_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_jb_api_get(bt_io_jb_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_jb_api_is_valid()); + + memcpy(api, &_bt_io_jb_api, sizeof(bt_io_jb_api_t)); +} + +void bt_io_jb_api_clear() +{ + log_assert(_bt_io_jb_api_is_valid()); + + memset(&_bt_io_jb_api, 0, sizeof(bt_io_jb_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_jb_init() +{ + bool result; + + log_assert(_bt_io_jb_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_jb_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_jb_fini() +{ + log_assert(_bt_io_jb_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_jb_api.v1.fini(); + + log_misc("<<< fini"); +} + +bool bt_io_jb_inputs_read() +{ + log_assert(_bt_io_jb_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_jb_api.v1.inputs_read(); +} + +uint8_t bt_io_jb_sys_inputs_get() +{ + log_assert(_bt_io_jb_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_jb_api.v1.sys_inputs_get(); +} + +uint16_t bt_io_jb_panel_inputs_get() +{ + log_assert(_bt_io_jb_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_jb_api.v1.panel_inputs_get(); +} + +void bt_io_jb_rgb_led_set( + bt_io_jb_rgb_led_t unit, uint8_t r, uint8_t g, uint8_t b) +{ + log_assert(_bt_io_jb_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_jb_api.v1.rgb_led_set(unit, r, g, b); +} + +bool bt_io_jb_lights_write() +{ + log_assert(_bt_io_jb_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_jb_api.v1.lights_write(); +} + +bool bt_io_jb_panel_mode_set(bt_io_jb_panel_mode_t mode) +{ + log_assert(_bt_io_jb_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_jb_api.v1.panel_mode_set(mode); +} + +bool bt_io_jb_coin_blocker_set(bool blocked) +{ + log_assert(_bt_io_jb_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_jb_api.v1.coin_blocker_set(blocked); +} diff --git a/src/main/iface-io/jb.h b/src/main/iface-io/jb.h new file mode 100644 index 00000000..a698353a --- /dev/null +++ b/src/main/iface-io/jb.h @@ -0,0 +1,24 @@ +#ifndef API_IO_JB_H +#define API_IO_JB_H + +#include +#include + +#include "api/io/jb.h" + +void bt_io_jb_api_set(const bt_io_jb_api_t *api); +void bt_io_jb_api_get(bt_io_jb_api_t *api); +void bt_io_jb_api_clear(); + +bool bt_io_jb_init(); +void bt_io_jb_fini(); +bool bt_io_jb_inputs_read(); +uint8_t bt_io_jb_sys_inputs_get(); +uint16_t bt_io_jb_panel_inputs_get(); +void bt_io_jb_rgb_led_set( + bt_io_jb_rgb_led_t unit, uint8_t r, uint8_t g, uint8_t b); +bool bt_io_jb_lights_write(); +bool bt_io_jb_panel_mode_set(bt_io_jb_panel_mode_t mode); +bool bt_io_jb_coin_blocker_set(bool blocked); + +#endif \ No newline at end of file diff --git a/src/main/iface-io/popn.c b/src/main/iface-io/popn.c new file mode 100644 index 00000000..9be62fdd --- /dev/null +++ b/src/main/iface-io/popn.c @@ -0,0 +1,157 @@ +#define LOG_MODULE "bt-io-popn" + +#include + +#include "api/io/popn.h" + +#include "iface-core/log.h" + +#define BT_IO_POPN_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_popn_api_t _bt_io_popn_api; + +static bool _bt_io_popn_api_is_valid() +{ + return _bt_io_popn_api.version > 0; +} + +void bt_io_popn_api_set(const bt_io_popn_api_t *api) +{ + log_assert(api); + + if (_bt_io_popn_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_POPN_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_popn_init"); + BT_IO_POPN_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_popn_fini"); + + BT_IO_POPN_ASSERT_IMPLEMENTED( + api->v1.buttons_get, "bt_io_popn_buttons_get"); + BT_IO_POPN_ASSERT_IMPLEMENTED( + api->v1.top_lights_set, "bt_io_popn_top_lights_set"); + BT_IO_POPN_ASSERT_IMPLEMENTED( + api->v1.side_lights_set, "bt_io_popn_side_lights_set"); + BT_IO_POPN_ASSERT_IMPLEMENTED( + api->v1.button_lights_set, "bt_io_popn_button_lights_set"); + BT_IO_POPN_ASSERT_IMPLEMENTED( + api->v1.coin_blocker_light_set, + "bt_io_popn_coin_blocker_light_set"); + BT_IO_POPN_ASSERT_IMPLEMENTED( + api->v1.coin_counter_light_set, + "bt_io_popn_coin_counter_light_set"); + + memcpy(&_bt_io_popn_api, api, sizeof(bt_io_popn_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_popn_api_get(bt_io_popn_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_popn_api_is_valid()); + + memcpy(api, &_bt_io_popn_api, sizeof(bt_io_popn_api_t)); +} + +void bt_io_popn_api_clear() +{ + log_assert(_bt_io_popn_api_is_valid()); + + memset(&_bt_io_popn_api, 0, sizeof(bt_io_popn_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_popn_init() +{ + bool result; + + log_assert(_bt_io_popn_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_popn_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_popn_fini() +{ + log_assert(_bt_io_popn_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_popn_api.v1.fini(); + + log_misc("<<< fini"); +} + +uint32_t bt_io_popn_buttons_get() +{ + log_assert(_bt_io_popn_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_popn_api.v1.buttons_get(); +} + +void bt_io_popn_top_lights_set(uint32_t lights) +{ + log_assert(_bt_io_popn_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_popn_api.v1.top_lights_set(lights); +} + +void bt_io_popn_side_lights_set(uint32_t lights) +{ + log_assert(_bt_io_popn_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_popn_api.v1.side_lights_set(lights); +} + +void bt_io_popn_button_lights_set(uint32_t lights) +{ + log_assert(_bt_io_popn_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_popn_api.v1.button_lights_set(lights); +} + +void bt_io_popn_coin_blocker_light_set(bool enabled) +{ + log_assert(_bt_io_popn_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_popn_api.v1.coin_blocker_light_set(enabled); +} + +void bt_io_popn_coin_counter_light_set(bool enabled) +{ + log_assert(_bt_io_popn_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_popn_api.v1.coin_counter_light_set(enabled); +} diff --git a/src/main/iface-io/popn.h b/src/main/iface-io/popn.h new file mode 100644 index 00000000..6256ec78 --- /dev/null +++ b/src/main/iface-io/popn.h @@ -0,0 +1,23 @@ +#ifndef API_IO_POPN_H +#define API_IO_POPN_H + +#include +#include + +#include "api/io/popn.h" + +void bt_io_popn_api_set(const bt_io_popn_api_t *api); +void bt_io_popn_api_get(bt_io_popn_api_t *api); +void bt_io_popn_api_clear(); + +bool bt_io_popn_init(); +void bt_io_popn_fini(); + +uint32_t bt_io_popn_buttons_get(); +void bt_io_popn_top_lights_set(uint32_t lights); +void bt_io_popn_side_lights_set(uint32_t lights); +void bt_io_popn_button_lights_set(uint32_t lights); +void bt_io_popn_coin_blocker_light_set(bool enabled); +void bt_io_popn_coin_counter_light_set(bool enabled); + +#endif \ No newline at end of file diff --git a/src/main/iface-io/sdvx.c b/src/main/iface-io/sdvx.c new file mode 100644 index 00000000..9d133e70 --- /dev/null +++ b/src/main/iface-io/sdvx.c @@ -0,0 +1,180 @@ +#define LOG_MODULE "bt-io-sdvx" + +#include + +#include "api/io/sdvx.h" + +#include "iface-core/log.h" + +#define BT_IO_SDVX_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_sdvx_api_t _bt_io_sdvx_api; + +static bool _bt_io_sdvx_api_is_valid() +{ + return _bt_io_sdvx_api.version > 0; +} + +void bt_io_sdvx_api_set(const bt_io_sdvx_api_t *api) +{ + log_assert(api); + + if (_bt_io_sdvx_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_SDVX_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_sdvx_init"); + BT_IO_SDVX_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_sdvx_fini"); + + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.gpio_lights_set, "bt_io_sdvx_gpio_lights_set"); + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.pwm_light_set, "bt_io_sdvx_pwm_light_set"); + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.output_write, "bt_io_sdvx_output_write"); + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.input_read, "bt_io_sdvx_input_read"); + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.input_gpio_sys_get, "bt_io_sdvx_input_gpio_sys_get"); + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.input_gpio_get, "bt_io_sdvx_input_gpio_get"); + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.spinner_pos_get, "bt_io_sdvx_spinner_pos_get"); + BT_IO_SDVX_ASSERT_IMPLEMENTED( + api->v1.amp_volume_set, "bt_io_sdvx_amp_volume_set"); + + memcpy(&_bt_io_sdvx_api, api, sizeof(bt_io_sdvx_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_sdvx_api_get(bt_io_sdvx_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_sdvx_api_is_valid()); + + memcpy(api, &_bt_io_sdvx_api, sizeof(bt_io_sdvx_api_t)); +} + +void bt_io_sdvx_api_clear() +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + memset(&_bt_io_sdvx_api, 0, sizeof(bt_io_sdvx_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_sdvx_init() +{ + bool result; + + log_assert(_bt_io_sdvx_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_sdvx_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_sdvx_fini() +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_sdvx_api.v1.fini(); + + log_misc("<<< fini"); +} + +void bt_io_sdvx_gpio_lights_set(uint32_t gpio_lights) +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_sdvx_api.v1.gpio_lights_set(gpio_lights); +} + +void bt_io_sdvx_pwm_light_set(uint8_t light_no, uint8_t intensity) +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + _bt_io_sdvx_api.v1.pwm_light_set(light_no, intensity); +} + +bool bt_io_sdvx_output_write() +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_sdvx_api.v1.output_write(); +} + +bool bt_io_sdvx_input_read() +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_sdvx_api.v1.input_read(); +} + +uint8_t bt_io_sdvx_input_gpio_sys_get() +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_sdvx_api.v1.input_gpio_sys_get(); +} + +uint16_t bt_io_sdvx_input_gpio_get(uint8_t gpio_bank) +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_sdvx_api.v1.input_gpio_get(gpio_bank); +} + +uint16_t bt_io_sdvx_spinner_pos_get(uint8_t spinner_no) +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_sdvx_api.v1.spinner_pos_get(spinner_no); +} + +bool bt_io_sdvx_amp_volume_set( + uint8_t primary, uint8_t headphone, uint8_t subwoofer) +{ + log_assert(_bt_io_sdvx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_sdvx_api.v1.amp_volume_set(primary, headphone, subwoofer); +} diff --git a/src/main/iface-io/sdvx.h b/src/main/iface-io/sdvx.h new file mode 100644 index 00000000..a803313b --- /dev/null +++ b/src/main/iface-io/sdvx.h @@ -0,0 +1,26 @@ +#ifndef API_IO_SDVX_H +#define API_IO_SDVX_H + +#include +#include + +#include "api/io/sdvx.h" + +void bt_io_sdvx_api_set(const bt_io_sdvx_api_t *api); +void bt_io_sdvx_api_get(bt_io_sdvx_api_t *api); +void bt_io_sdvx_api_clear(); + +bool bt_io_sdvx_init(); +void bt_io_sdvx_fini(); + +void bt_io_sdvx_gpio_lights_set(uint32_t gpio_lights); +void bt_io_sdvx_pwm_light_set(uint8_t light_no, uint8_t intensity); +bool bt_io_sdvx_output_write(); +bool bt_io_sdvx_input_read(); +uint8_t bt_io_sdvx_input_gpio_sys_get(); +uint16_t bt_io_sdvx_input_gpio_get(uint8_t gpio_bank); +uint16_t bt_io_sdvx_spinner_pos_get(uint8_t spinner_no); +bool bt_io_sdvx_amp_volume_set( + uint8_t primary, uint8_t headphone, uint8_t subwoofer); + +#endif \ No newline at end of file diff --git a/src/main/iface-io/vefx.c b/src/main/iface-io/vefx.c new file mode 100644 index 00000000..07834ef5 --- /dev/null +++ b/src/main/iface-io/vefx.c @@ -0,0 +1,118 @@ +#define LOG_MODULE "bt-io-vefx" + +#include + +#include "api/io/vefx.h" + +#include "iface-core/log.h" + +#define BT_IO_VEFX_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_io_vefx_api_t _bt_io_vefx_api; + +static bool _bt_io_vefx_api_is_valid() +{ + return _bt_io_vefx_api.version > 0; +} + +void bt_io_vefx_api_set(const bt_io_vefx_api_t *api) +{ + log_assert(api); + + if (_bt_io_vefx_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_IO_VEFX_ASSERT_IMPLEMENTED(api->v1.init, "bt_io_vefx_init"); + BT_IO_VEFX_ASSERT_IMPLEMENTED(api->v1.fini, "bt_io_vefx_fini"); + + BT_IO_VEFX_ASSERT_IMPLEMENTED(api->v1.recv, "bt_io_vefx_recv"); + BT_IO_VEFX_ASSERT_IMPLEMENTED( + api->v1.slider_get, "bt_io_vefx_slider_get"); + BT_IO_VEFX_ASSERT_IMPLEMENTED( + api->v1._16seg_send, "bt_io_vefx_16seg_send"); + + memcpy(&_bt_io_vefx_api, api, sizeof(bt_io_vefx_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_io_vefx_api_get(bt_io_vefx_api_t *api) +{ + log_assert(api); + log_assert(_bt_io_vefx_api_is_valid()); + + memcpy(api, &_bt_io_vefx_api, sizeof(bt_io_vefx_api_t)); +} + +void bt_io_vefx_api_clear() +{ + log_assert(_bt_io_vefx_api_is_valid()); + + memset(&_bt_io_vefx_api, 0, sizeof(bt_io_vefx_api_t)); + + log_misc("api cleared"); +} + +bool bt_io_vefx_init() +{ + bool result; + + log_assert(_bt_io_vefx_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_io_vefx_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_io_vefx_fini() +{ + log_assert(_bt_io_vefx_api_is_valid()); + + log_misc(">>> fini"); + + _bt_io_vefx_api.v1.fini(); + + log_misc("<<< fini"); +} + +bool bt_io_vefx_recv(uint64_t *ppad) +{ + log_assert(_bt_io_vefx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_vefx_api.v1.recv(ppad); +} + +uint8_t bt_io_vefx_slider_get(uint8_t slider_no) +{ + log_assert(_bt_io_vefx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_vefx_api.v1.slider_get(slider_no); +} + +bool bt_io_vefx_16seg_send(const char *text) +{ + log_assert(_bt_io_vefx_api_is_valid()); + + // Do not log on frequently invoked calls to avoid negative performance + // impact and log spam + + return _bt_io_vefx_api.v1._16seg_send(text); +} diff --git a/src/main/iface-io/vefx.h b/src/main/iface-io/vefx.h new file mode 100644 index 00000000..0444de41 --- /dev/null +++ b/src/main/iface-io/vefx.h @@ -0,0 +1,20 @@ +#ifndef API_IO_VEFX_H +#define API_IO_VEFX_H + +#include +#include + +#include "api/io/vefx.h" + +void bt_io_vefx_api_set(const bt_io_vefx_api_t *api); +void bt_io_vefx_api_get(bt_io_vefx_api_t *api); +void bt_io_vefx_api_clear(); + +bool bt_io_vefx_init(); +void bt_io_vefx_fini(); + +bool bt_io_vefx_recv(uint64_t *ppad); +uint8_t bt_io_vefx_slider_get(uint8_t slider_no); +bool bt_io_vefx_16seg_send(const char *text); + +#endif \ No newline at end of file diff --git a/src/main/iface/Module.mk b/src/main/iface/Module.mk new file mode 100644 index 00000000..4c64b3d7 --- /dev/null +++ b/src/main/iface/Module.mk @@ -0,0 +1,10 @@ +libs += iface + +libs_iface := \ + iface-core \ + iface-io \ + util \ + +src_iface := \ + hook.c \ + input.c \ diff --git a/src/main/iface/hook.c b/src/main/iface/hook.c new file mode 100644 index 00000000..51ae565c --- /dev/null +++ b/src/main/iface/hook.c @@ -0,0 +1,118 @@ +#define LOG_MODULE "bt-hook" + +#include + +#include "api/hook.h" + +#include "iface-core/log.h" +#include "iface/hook.h" + +#include "util/mem.h" +#include "util/str.h" + +struct bt_hook { + bt_hook_api_t api; + char name[512]; +}; + +void bt_hook_init(const bt_hook_api_t *api, const char *name, bt_hook_t **hook) +{ + log_assert(api); + log_assert(name); + log_assert(hook); + + if (api->version == 1) { + // all functions optional, no need for asserting them + + *hook = xmalloc(sizeof(bt_hook_t)); + + memcpy(&(*hook)->api, api, sizeof(bt_hook_api_t)); + str_cpy((*hook)->name, sizeof((*hook)->name), name); + + log_misc("[%s] api v1 detected", (*hook)->name); + } else { + log_fatal("[%s] Unsupported API version: %d", name, api->version); + } +} + +void bt_hook_fini(bt_hook_t **hook) +{ + log_assert(hook); + + free(*hook); + memset(*hook, 0, sizeof(bt_hook_t)); +} + +bool bt_hook_pre_avs_init(const bt_hook_t *hook, const bt_core_config_t *config) +{ + bool result; + + log_assert(hook); + log_assert(config); + log_assert(hook->api.version > 0); + + if (hook->api.v1.pre_avs_init) { + log_misc("[%s] >>> pre_avs_init", hook->name); + + result = hook->api.v1.pre_avs_init(config); + + log_misc("[%s] <<< pre_avs_init: %d", hook->name, result); + } else { + result = true; + } + + return result; +} + +void bt_hook_iat_dll_name_get(const bt_hook_t *hook, char *buffer, size_t size) +{ + log_assert(hook); + log_assert(hook->api.version > 0); + log_assert(buffer); + log_assert(size > 0); + + if (hook->api.v1.iat_dll_name_get) { + log_misc("[%s] >>> iat_dll_name_get", hook->name); + + hook->api.v1.iat_dll_name_get(buffer, size); + + log_misc("[%s] <<< iat_dll_name_get: %s", hook->name, buffer); + } +} + +bool bt_hook_main_init( + const bt_hook_t *hook, HMODULE game_module, const bt_core_config_t *config) +{ + bool result; + + log_assert(hook); + log_assert(game_module); + log_assert(hook->api.version > 0); + log_assert(config); + + if (hook->api.v1.main_init) { + log_misc("[%s] >>> main_init", hook->name); + + result = hook->api.v1.main_init(game_module, config); + + log_misc("[%s] <<< main_init: %d", hook->name, result); + } else { + result = true; + } + + return result; +} + +void bt_hook_main_fini(const bt_hook_t *hook) +{ + log_assert(hook); + log_assert(hook->api.version > 0); + + if (hook->api.v1.main_fini) { + log_misc("[%s] >>> main_fini", hook->name); + + hook->api.v1.main_fini(); + + log_misc("[%s] <<< main_fini", hook->name); + } +} diff --git a/src/main/iface/hook.h b/src/main/iface/hook.h new file mode 100644 index 00000000..30d13edb --- /dev/null +++ b/src/main/iface/hook.h @@ -0,0 +1,21 @@ +#ifndef BT_HOOK_H +#define BT_HOOK_H + +#include +#include + +#include "api/hook.h" + +typedef struct bt_hook bt_hook_t; + +void bt_hook_init(const bt_hook_api_t *api, const char *name, bt_hook_t **hook); +void bt_hook_fini(bt_hook_t **hook); + +bool bt_hook_pre_avs_init( + const bt_hook_t *hook, const bt_core_config_t *config); +void bt_hook_iat_dll_name_get(const bt_hook_t *hook, char *buffer, size_t size); +bool bt_hook_main_init( + const bt_hook_t *hook, HMODULE game_module, const bt_core_config_t *config); +void bt_hook_main_fini(const bt_hook_t *hook); + +#endif \ No newline at end of file diff --git a/src/main/iface/input.c b/src/main/iface/input.c new file mode 100644 index 00000000..61efeca5 --- /dev/null +++ b/src/main/iface/input.c @@ -0,0 +1,127 @@ +#define LOG_MODULE "bt-input" + +#include + +#include "api/input.h" + +#include "iface-core/log.h" + +#define BT_INPUT_ASSERT_IMPLEMENTED(func, name) \ + if (!func) { \ + log_fatal("Function %s not implemented", STRINGIFY(name)); \ + } + +static bt_input_api_t _bt_input_api; + +static bool _bt_input_api_is_valid() +{ + return _bt_input_api.version > 0; +} + +void bt_input_api_set(const bt_input_api_t *api) +{ + log_assert(api); + + if (_bt_input_api_is_valid()) { + log_warning("Re-initialize"); + } + + if (api->version == 1) { + BT_INPUT_ASSERT_IMPLEMENTED(api->v1.init, "bt_input_init"); + BT_INPUT_ASSERT_IMPLEMENTED(api->v1.fini, "bt_input_fini"); + + BT_INPUT_ASSERT_IMPLEMENTED( + api->v1.mapper_config_load, "bt_input_mapper_config_load"); + BT_INPUT_ASSERT_IMPLEMENTED( + api->v1.mapper_analog_read, "bt_input_mapper_analog_read"); + BT_INPUT_ASSERT_IMPLEMENTED( + api->v1.mapper_update, "bt_input_mapper_update"); + BT_INPUT_ASSERT_IMPLEMENTED( + api->v1.mapper_light_write, "bt_input_mapper_light_write"); + + memcpy(&_bt_input_api, api, sizeof(bt_input_api_t)); + + log_misc("api v1 set"); + } else { + log_fatal("Unsupported API version: %d", api->version); + } +} + +void bt_input_api_get(bt_input_api_t *api) +{ + log_assert(api); + log_assert(_bt_input_api_is_valid()); + + memcpy(api, &_bt_input_api, sizeof(bt_input_api_t)); +} + +void bt_input_api_clear() +{ + log_assert(_bt_input_api_is_valid()); + + memset(&_bt_input_api, 0, sizeof(bt_input_api_t)); + + log_misc("api cleared"); +} + +bool bt_input_init() +{ + bool result; + + log_assert(_bt_input_api_is_valid()); + + log_misc(">>> init"); + + result = _bt_input_api.v1.init(); + + log_misc("<<< init: %d", result); + + return result; +} + +void bt_input_fini() +{ + log_assert(_bt_input_api_is_valid()); + + log_misc(">>> fini"); + + _bt_input_api.v1.fini(); + + log_misc("<<< fini"); +} + +bool bt_input_mapper_config_load(const char *game_type) +{ + bool result; + + log_assert(_bt_input_api_is_valid()); + + log_misc(">>> mapper_config_load: %s", game_type); + + result = _bt_input_api.v1.mapper_config_load(game_type); + + log_misc("<<< mapper_config_load: %d", result); + + return result; +} + +uint8_t bt_input_mapper_analog_read(uint8_t analog) +{ + log_assert(_bt_input_api_is_valid()); + + return _bt_input_api.v1.mapper_analog_read(analog); +} + +uint64_t bt_input_mapper_update() +{ + log_assert(_bt_input_api_is_valid()); + + return _bt_input_api.v1.mapper_update(); +} + +void bt_input_mapper_light_write(uint8_t light, uint8_t intensity) +{ + log_assert(_bt_input_api_is_valid()); + + return _bt_input_api.v1.mapper_light_write(light, intensity); +} diff --git a/src/main/iface/input.h b/src/main/iface/input.h new file mode 100644 index 00000000..d6d5b452 --- /dev/null +++ b/src/main/iface/input.h @@ -0,0 +1,21 @@ +#ifndef BT_INPUT_H +#define BT_INPUT_H + +#include +#include + +#include "api/input.h" + +void bt_input_api_set(const bt_input_api_t *api); +void bt_input_api_get(bt_input_api_t *api); +void bt_input_api_clear(); + +bool bt_input_init(); +void bt_input_fini(); + +bool bt_input_mapper_config_load(const char *game_type); +uint8_t bt_input_mapper_analog_read(uint8_t analog); +uint64_t bt_input_mapper_update(); +void bt_input_mapper_light_write(uint8_t light, uint8_t intensity); + +#endif \ No newline at end of file diff --git a/src/main/iidx-bio2-exit-hook/Module.mk b/src/main/iidx-bio2-exit-hook/Module.mk index dcf7289b..701fa063 100644 --- a/src/main/iidx-bio2-exit-hook/Module.mk +++ b/src/main/iidx-bio2-exit-hook/Module.mk @@ -2,11 +2,14 @@ dlls += iidx-bio2-exit-hook ldflags_iidx-bio2-exit-hook := \ -lsetupapi \ + -lpsapi \ libs_iidx-bio2-exit-hook := \ + core \ bio2drv \ hook \ util \ + iface-core \ src_iidx-bio2-exit-hook := \ main.c \ diff --git a/src/main/iidx-bio2-exit-hook/main.c b/src/main/iidx-bio2-exit-hook/main.c index 13ac8251..4faf4ba6 100644 --- a/src/main/iidx-bio2-exit-hook/main.c +++ b/src/main/iidx-bio2-exit-hook/main.c @@ -11,10 +11,15 @@ #include "bio2/bi2a-iidx.h" #include "bio2drv/detect.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + #include "hook/iobuf.h" #include "hook/iohook.h" -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" #include "util/proc.h" #include "util/str.h" @@ -224,7 +229,10 @@ static HRESULT _iohook_handler(struct irp *irp) BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - log_to_writer(log_writer_stdout, NULL); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); if (reason != DLL_PROCESS_ATTACH) { return TRUE; diff --git a/src/main/iidx-ezusb-exit-hook/Module.mk b/src/main/iidx-ezusb-exit-hook/Module.mk index 4050ebe1..084841c4 100644 --- a/src/main/iidx-ezusb-exit-hook/Module.mk +++ b/src/main/iidx-ezusb-exit-hook/Module.mk @@ -1,9 +1,14 @@ dlls += iidx-ezusb-exit-hook +ldflags_iidx-ezusb-exit-hook := \ + -lpsapi \ + libs_iidx-ezusb-exit-hook := \ + core \ ezusb-iidx \ hook \ util \ + iface-core \ src_iidx-ezusb-exit-hook := \ main.c \ diff --git a/src/main/iidx-ezusb-exit-hook/main.c b/src/main/iidx-ezusb-exit-hook/main.c index 1c34d665..162664a1 100644 --- a/src/main/iidx-ezusb-exit-hook/main.c +++ b/src/main/iidx-ezusb-exit-hook/main.c @@ -7,6 +7,10 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + #include "ezusb/ezusbsys2.h" #include "ezusb-iidx/msg.h" @@ -176,6 +180,11 @@ static BOOL STDCALL my_DeviceIoControl( BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); + hook_table_apply( NULL, "kernel32.dll", iidxfx_hook_syms, lengthof(iidxfx_hook_syms)); } diff --git a/src/main/iidx-ezusb2-exit-hook/Module.mk b/src/main/iidx-ezusb2-exit-hook/Module.mk index 7828a97b..091939c2 100644 --- a/src/main/iidx-ezusb2-exit-hook/Module.mk +++ b/src/main/iidx-ezusb2-exit-hook/Module.mk @@ -1,8 +1,13 @@ dlls += iidx-ezusb2-exit-hook +ldflags_iidx-ezusb2-exit-hook := \ + -lpsapi \ + libs_iidx-ezusb2-exit-hook := \ + core \ hook \ util \ + iface-core \ src_iidx-ezusb2-exit-hook := \ main.c \ diff --git a/src/main/iidx-ezusb2-exit-hook/main.c b/src/main/iidx-ezusb2-exit-hook/main.c index 85b61bdb..4346c9ad 100644 --- a/src/main/iidx-ezusb2-exit-hook/main.c +++ b/src/main/iidx-ezusb2-exit-hook/main.c @@ -7,6 +7,10 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + #include "ezusb2/cyioctl.h" #include "ezusb2-iidx/msg.h" @@ -136,6 +140,11 @@ static BOOL STDCALL my_DeviceIoControl( BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); + hook_table_apply( NULL, "kernel32.dll", exit_hook_syms, lengthof(exit_hook_syms)); } diff --git a/src/main/iidx-irbeat-patch/Module.mk b/src/main/iidx-irbeat-patch/Module.mk index df42cd3d..62f9bb6e 100644 --- a/src/main/iidx-irbeat-patch/Module.mk +++ b/src/main/iidx-irbeat-patch/Module.mk @@ -2,6 +2,8 @@ exes += iidx-irbeat-patch libs_iidx-irbeat-patch := \ util \ + core \ + iface-core \ src_iidx-irbeat-patch := \ main.c \ diff --git a/src/main/iidx-irbeat-patch/main.c b/src/main/iidx-irbeat-patch/main.c index 9c2f58a9..da07956d 100644 --- a/src/main/iidx-irbeat-patch/main.c +++ b/src/main/iidx-irbeat-patch/main.c @@ -3,6 +3,11 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" + +#include "iface-core/log.h" + #include "util/fs.h" static const uint32_t offset_size_data_area = 4; @@ -170,6 +175,11 @@ int main(int argc, char **argv) return -1; } + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); + version = atoi(argv[1]); irbeat = atoi(argv[2]); settings = argv[3]; diff --git a/src/main/iidxhook-d3d9/bb-scale-hd.c b/src/main/iidxhook-d3d9/bb-scale-hd.c index 60dae6be..d41242a4 100644 --- a/src/main/iidxhook-d3d9/bb-scale-hd.c +++ b/src/main/iidxhook-d3d9/bb-scale-hd.c @@ -4,11 +4,11 @@ #include "d3d9-util/vertex.h" +#include "iface-core/log.h" + #include "bb-scale-hd.h" #include "util.h" -#include "util/log.h" - static bool iidxhook_d3d9_bb_scale_initialized; static uint16_t iidxhook_d3d9_bb_scale_hd_width; static uint16_t iidxhook_d3d9_bb_scale_hd_height; diff --git a/src/main/iidxhook-d3d9/util.h b/src/main/iidxhook-d3d9/util.h index 3a77e99b..f315e4b0 100644 --- a/src/main/iidxhook-d3d9/util.h +++ b/src/main/iidxhook-d3d9/util.h @@ -5,7 +5,7 @@ #include "d3d9-util/dxerr9.h" -#include "util/log.h" +#include "iface-core/log.h" inline void iidxhook_d3d9_util_check_and_handle_failure(HRESULT hr, const char *msg) diff --git a/src/main/iidxhook-util/Module.mk b/src/main/iidxhook-util/Module.mk index 92fe44d8..c549c2e1 100644 --- a/src/main/iidxhook-util/Module.mk +++ b/src/main/iidxhook-util/Module.mk @@ -1,6 +1,7 @@ libs += iidxhook-util libs_iidxhook-util := \ + core \ util \ src_iidxhook-util := \ @@ -16,5 +17,4 @@ src_iidxhook-util := \ d3d9.c \ eamuse.c \ effector.c \ - log-server.c \ settings.c \ diff --git a/src/main/iidxhook-util/acio.c b/src/main/iidxhook-util/acio.c index 62913361..fa26e0ce 100644 --- a/src/main/iidxhook-util/acio.c +++ b/src/main/iidxhook-util/acio.c @@ -18,13 +18,14 @@ #include "hook/iohook.h" #include "hooklib/rs232.h" +#include "iface-core/log.h" + #include "iidxhook-util/acio.h" #include "imports/avs.h" #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu iidxhook_util_acio_emu; diff --git a/src/main/iidxhook-util/chart-patch.c b/src/main/iidxhook-util/chart-patch.c index 4b2970ec..9b14dd00 100644 --- a/src/main/iidxhook-util/chart-patch.c +++ b/src/main/iidxhook-util/chart-patch.c @@ -6,10 +6,11 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "util/crc.h" #include "util/defs.h" #include "util/fs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" diff --git a/src/main/iidxhook-util/clock.c b/src/main/iidxhook-util/clock.c index 8c870fff..f3cec623 100644 --- a/src/main/iidxhook-util/clock.c +++ b/src/main/iidxhook-util/clock.c @@ -4,8 +4,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" static BOOL STDCALL my_SetLocalTime(const SYSTEMTIME *lpSystemTime); static BOOL(STDCALL *real_SetLocalTime)(const SYSTEMTIME *lpSystemTime); @@ -30,3 +31,11 @@ void iidxhook_util_clock_hook_init(void) log_info("Inserted clock hooks"); } + +void iidxhook_util_clock_hook_fini() +{ + hook_table_revert( + NULL, "kernel32.dll", clock_hook_syms, lengthof(clock_hook_syms)); + + log_info("Removed clock hooks"); +} diff --git a/src/main/iidxhook-util/clock.h b/src/main/iidxhook-util/clock.h index 28c08e5e..7e3c57a3 100644 --- a/src/main/iidxhook-util/clock.h +++ b/src/main/iidxhook-util/clock.h @@ -8,4 +8,6 @@ */ void iidxhook_util_clock_hook_init(void); +void iidxhook_util_clock_hook_fini(); + #endif diff --git a/src/main/iidxhook-util/config-eamuse.c b/src/main/iidxhook-util/config-eamuse.c index f59b03e8..33d6b814 100644 --- a/src/main/iidxhook-util/config-eamuse.c +++ b/src/main/iidxhook-util/config-eamuse.c @@ -1,169 +1,50 @@ #include -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "iidxhook-util/config-eamuse.h" -#include "security/mcode.h" - -#include "util/log.h" - -#define IIDXHOOK_CONFIG_EAMUSE_CARD_TYPE_KEY "eamuse.card_type" -#define IIDXHOOK_CONFIG_EAMUSE_SERVER_KEY "eamuse.server" -#define IIDXHOOK_CONFIG_EAMUSE_PCBID_KEY "eamuse.pcbid" -#define IIDXHOOK_CONFIG_EAMUSE_EAMID_KEY "eamuse.eamid" - -#define IIDXHOOK_CONFIG_EAMUSE_DEFAULT_CARD_TYPE_VALUE \ - SECURITY_MCODE_GAME_IIDX_9 -#define IIDXHOOK_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE "localhost:80" -#define IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE security_id_default -#define IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN \ - sizeof(security_id_default) -#define IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE security_id_default -#define IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN \ - sizeof(security_id_default) - -const struct net_addr iidxhook_eamuse_default_server = { - .type = NET_ADDR_TYPE_HOSTNAME, - .hostname.host = "localhost", - .hostname.port = 80, -}; - -void iidxhook_util_config_eamuse_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_EAMUSE_CARD_TYPE_KEY, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_CARD_TYPE_VALUE, - "Magnetic card type, format XXX, 3 digit string (supports: C02, " - "D01, " - "E11, ECO)"); +#include "iface-core/log.h" - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_EAMUSE_SERVER_KEY, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE, - "URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 " - "(e.g. 127.0.0.1:80) of the target eamuse server. The port is " - "optional " - "but defaults to 80."); - - cconfig_util_set_data( - config, - IIDXHOOK_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - "PCBID"); +#include "security/mcode.h" - cconfig_util_set_data( - config, - IIDXHOOK_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - "EAMID"); -} +#include "util/str.h" -void iidxhook_util_config_eamuse_get( - struct iidxhook_util_config_eamuse *config_eamuse, struct cconfig *config) +static void _iidxhook_util_config_eamuse_verify( + const iidxhook_util_config_eamuse_t *config) { - char server_url[1024]; char *tmp; - char *tmp2; - - memset(config_eamuse, 0, sizeof(struct iidxhook_util_config_eamuse)); - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_EAMUSE_CARD_TYPE_KEY, - config_eamuse->card_type, - sizeof(config_eamuse->card_type) - 1, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_CARD_TYPE_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_EAMUSE_CARD_TYPE_KEY, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_CARD_TYPE_VALUE); + if (!str_eq(config->card_type, "C02") && + !str_eq(config->card_type, "D01") && + !str_eq(config->card_type, "E11") && + !str_eq(config->card_type, "ECO")) { + log_fatal("Invalid card_type in eamuse configuration: %s", config->card_type); } - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_EAMUSE_SERVER_KEY, - server_url, - sizeof(server_url), - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_EAMUSE_SERVER_KEY, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE); - } - - if (!net_str_parse(server_url, &config_eamuse->server)) { - memcpy( - &config_eamuse->server, - &iidxhook_eamuse_default_server, - sizeof(config_eamuse->server)); - tmp = net_addr_to_str(&config_eamuse->server); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!cconfig_util_get_data( - config, - IIDXHOOK_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &config_eamuse->pcbid, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - (uint8_t *) &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE)) { - tmp = security_id_to_str( - &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); + if (!security_id_verify(&config->pcbid)) { + tmp = security_id_to_str(&config->pcbid, false); + log_fatal("Invalid pcbid in eamuse configuration: %s", tmp); free(tmp); - free(tmp2); } - if (!cconfig_util_get_data( - config, - IIDXHOOK_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &config_eamuse->eamid, - IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - (uint8_t *) &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE)) { - tmp = security_id_to_str( - &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); + if (!security_id_verify(&config->eamid)) { + tmp = security_id_to_str(&config->eamid, false); + log_fatal("Invalid eamid in eamuse configuration: %s", tmp); free(tmp); } +} - if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } +void iidxhook_util_config_eamuse_get( + const bt_core_config_t *config, + iidxhook_util_config_eamuse_t *config_eamuse) +{ + bt_core_config_ext_str_get(config, "eamuse/card_type", config_eamuse->card_type, sizeof(config_eamuse->card_type)); + bt_core_config_ext_net_addr_get(config, "eamuse/server", &config_eamuse->server); + bt_core_config_ext_bin_get(config, "eamuse/pcbid", + (uint8_t *) &config_eamuse->pcbid, sizeof(config_eamuse->pcbid)); + bt_core_config_ext_bin_get(config, "eamuse/eamid", + (uint8_t *) &config_eamuse->eamid, sizeof(config_eamuse->eamid)); + + _iidxhook_util_config_eamuse_verify(config_eamuse); } diff --git a/src/main/iidxhook-util/config-eamuse.h b/src/main/iidxhook-util/config-eamuse.h index b6b1d403..5e582a83 100644 --- a/src/main/iidxhook-util/config-eamuse.h +++ b/src/main/iidxhook-util/config-eamuse.h @@ -1,22 +1,21 @@ #ifndef IIDXHOOK_UTIL_CONFIG_EAMUSE_H #define IIDXHOOK_UTIL_CONFIG_EAMUSE_H -#include "cconfig/cconfig.h" +#include "iface-core/config.h" #include "security/id.h" #include "util/net.h" -struct iidxhook_util_config_eamuse { +typedef struct iidxhook_util_config_eamuse { char card_type[4]; struct net_addr server; struct security_id pcbid; struct security_id eamid; -}; - -void iidxhook_util_config_eamuse_init(struct cconfig *config); +} iidxhook_util_config_eamuse_t; void iidxhook_util_config_eamuse_get( - struct iidxhook_util_config_eamuse *config_eamuse, struct cconfig *config); + const bt_core_config_t *config, + iidxhook_util_config_eamuse_t *config_eamuse); #endif \ No newline at end of file diff --git a/src/main/iidxhook-util/config-ezusb.c b/src/main/iidxhook-util/config-ezusb.c index e860a1d5..d166089f 100644 --- a/src/main/iidxhook-util/config-ezusb.c +++ b/src/main/iidxhook-util/config-ezusb.c @@ -1,70 +1,33 @@ #include #include -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "iidxhook-util/config-ezusb.h" -#include "util/log.h" -#include "util/mem.h" +#include "iface-core/log.h" -#define IIDXHOOK_UTIL_CONFIG_EZUSB_API_CALL_MONITORING_KEY \ - "ezusb.api_call_monitoring" -#define IIDXHOOK_UTIL_CONFIG_EZUSB_IO_BOARD_TYPE_KEY "ezusb.io_board_type" +#include "util/str.h" -#define IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_API_CALL_MONITORING_VALUE false -#define IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_IO_BOARD_TYPE_VALUE 0 - -void iidxhook_util_config_ezusb_init(struct cconfig *config) +static void _iidxhook_util_config_ezusb_board_type_get(const bt_core_config_t *config, int32_t *board_type) { - cconfig_util_set_bool( - config, - IIDXHOOK_UTIL_CONFIG_EZUSB_API_CALL_MONITORING_KEY, - IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_API_CALL_MONITORING_VALUE, - "Enable monitoring of ezusb.dll calls by logging call traces. " - "Only works on 9th and 10th style!"); + char tmp[8]; + + bt_core_config_ext_str_get(config, "ezusb/type", tmp, sizeof(tmp)); - cconfig_util_set_int( - config, - IIDXHOOK_UTIL_CONFIG_EZUSB_IO_BOARD_TYPE_KEY, - IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_IO_BOARD_TYPE_VALUE, - "Set the type of ezusb IO board. 0 = C02, 1 = D01. " - "Note: Impacts security settings!"); + if (str_eq(tmp, "C02")) { + *board_type = 0; + } else if (str_eq(tmp, "D01")) { + *board_type = 1; + } else { + log_fatal("Invalid ezusb board type in configuration: %s", tmp); + } } void iidxhook_util_config_ezusb_get( - struct iidxhook_util_config_ezusb *config_ezusb, struct cconfig *config) + const bt_core_config_t *config, + iidxhook_util_config_ezusb_t *config_ezusb) { - if (!cconfig_util_get_bool( - config, - IIDXHOOK_UTIL_CONFIG_EZUSB_API_CALL_MONITORING_KEY, - &config_ezusb->api_call_monitoring, - IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_API_CALL_MONITORING_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_UTIL_CONFIG_EZUSB_API_CALL_MONITORING_KEY, - IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_API_CALL_MONITORING_VALUE); - } - - if (!cconfig_util_get_int( - config, - IIDXHOOK_UTIL_CONFIG_EZUSB_IO_BOARD_TYPE_KEY, - &config_ezusb->io_board_type, - IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_IO_BOARD_TYPE_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_UTIL_CONFIG_EZUSB_IO_BOARD_TYPE_KEY, - IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_IO_BOARD_TYPE_VALUE); - } - - if (config_ezusb->io_board_type != 0 && config_ezusb->io_board_type != 1) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_UTIL_CONFIG_EZUSB_IO_BOARD_TYPE_KEY, - IIDXHOOK_UTIL_CONFIG_EZUSB_DEFAULT_IO_BOARD_TYPE_VALUE); - config_ezusb->io_board_type = 0; - } -} + _iidxhook_util_config_ezusb_board_type_get(config, &config_ezusb->io_board_type); + bt_core_config_ext_bool_get(config, "ezusb/debug/api_call_monitoring", &config_ezusb->api_call_monitoring); +} \ No newline at end of file diff --git a/src/main/iidxhook-util/config-ezusb.h b/src/main/iidxhook-util/config-ezusb.h index 54d69fb8..9bdd2a99 100644 --- a/src/main/iidxhook-util/config-ezusb.h +++ b/src/main/iidxhook-util/config-ezusb.h @@ -1,18 +1,15 @@ #ifndef IIDXHOOK_UTIL_CONFIG_EZUSB_H #define IIDXHOOK_UTIL_CONFIG_EZUSB_H -#include "cconfig/cconfig.h" +#include "iface-core/config.h" -#include "security/mcode.h" - -struct iidxhook_util_config_ezusb { +typedef struct iidxhook_util_config_ezusb { bool api_call_monitoring; int32_t io_board_type; -}; - -void iidxhook_util_config_ezusb_init(struct cconfig *config); +} iidxhook_util_config_ezusb_t; void iidxhook_util_config_ezusb_get( - struct iidxhook_util_config_ezusb *config_ezusb, struct cconfig *config); + const bt_core_config_t *config, + iidxhook_util_config_ezusb_t *config_ezusb); #endif \ No newline at end of file diff --git a/src/main/iidxhook-util/config-gfx.c b/src/main/iidxhook-util/config-gfx.c index e591f480..7a9fd2d4 100644 --- a/src/main/iidxhook-util/config-gfx.c +++ b/src/main/iidxhook-util/config-gfx.c @@ -1,392 +1,92 @@ +#include #include -#include "cconfig/cconfig-util.h" +#include "iface-core/log.h" #include "iidxhook-util/config-gfx.h" -#include "util/log.h" +#include "util/str.h" -#define IIDXHOOK_CONFIG_GFX_BGVIDEO_UV_FIX_KEY "gfx.bgvideo_uv_fix" -#define IIDXHOOK_CONFIG_GFX_FRAMED_KEY "gfx.framed" -#define IIDXHOOK_CONFIG_GFX_FRAME_RATE_LIMIT_KEY "gfx.frame_rate_limit" -#define IIDXHOOK_CONFIG_GFX_MONITOR_CHECK_KEY "gfx.monitor_check" -#define IIDXHOOK_CONFIG_GFX_PCI_ID_KEY "gfx.pci_id" -#define IIDXHOOK_CONFIG_GFX_WINDOWED_KEY "gfx.windowed" -#define IIDXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY "gfx.window_width" -#define IIDXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY "gfx.window_height" -#define IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_WIDTH_KEY \ - "gfx.scale_back_buffer_width" -#define IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_HEIGHT_KEY \ - "gfx.scale_back_buffer_height" -#define IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_FILTER_KEY \ - "gfx.scale_back_buffer_filter" -#define IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate" -#define IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY "gfx.device_adapter" -#define IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY "gfx.diagonal_tearing_fix" - -#define IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE false -#define IIDXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false -#define IIDXHOOK_CONFIG_GFX_DEFAULT_FRAME_RATE_LIMIT_VALUE 0.0 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_MONITOR_CHECK_VALUE -1.0 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_PCI_ID_VALUE "1002:7146" -#define IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false -#define IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE -1 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE -1 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_WIDTH_VALUE 0 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_HEIGHT_VALUE 0 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE "none" -#define IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE -1 -#define IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE false - -void iidxhook_config_gfx_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_GFX_BGVIDEO_UV_FIX_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE, - "Fix stretched BG videos on newer GPUs. Might appear on SIRIUS " - "and older. On 9th and 10th style this issue may only affect " - "older BGAs (from 1st-3rd style)"); - - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_GFX_FRAMED_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE, - "Run the game in a framed window (requires windowed option)"); - - cconfig_util_set_float( - config, - IIDXHOOK_CONFIG_GFX_FRAME_RATE_LIMIT_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_FRAME_RATE_LIMIT_VALUE, - "Software limit the frame rate of the rendering loop in hz, e.g. " - "60 or 59.95 (0.0 = no software limit)"); - - cconfig_util_set_float( - config, - IIDXHOOK_CONFIG_GFX_MONITOR_CHECK_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_MONITOR_CHECK_VALUE, - "Enable/disable software monitor check/auto timebase or set " - "a pre-determined refresh value. -1 disables this feature. 0 " - "enables " - "auto detecting the current refresh rate on startup. Setting any " - "positive value > 0 allows you to set a pre-determined refresh " - "rate " - "(e.g. retrieved from the monitor check on newer IIDX games). " - "Either " - "the auto detected value or pre-determined value is used to patch " - "any " - "chart files in-memory to fix song synchronization issues. " - "Requires " - "constant refresh rate!!!"); - - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_GFX_PCI_ID_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_PCI_ID_VALUE, - "Patch the GPU device ID detection (leave empty to" - " disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid)." - " Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE," - " Radeon HD3450)"); - - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_GFX_WINDOWED_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE, - "Run the game windowed"); - - cconfig_util_set_int( - config, - IIDXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE, - "Windowed width, -1 for default size"); - - cconfig_util_set_int( - config, - IIDXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE, - "Windowed height, -1 for default size"); - - cconfig_util_set_int( - config, - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_WIDTH_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_WIDTH_VALUE, - "Up-/downscale the back buffer's width. This does not change the " - "game's rendering resolution but scales " - "the " - "final frame. Use this to target the native resolution of your " - "monitor/TV, e.g. to avoid over-/underscan, " - "bad " - "image quality or latency caused by the monitors internal " - "upscaler. 0 to disable this feature. Must be set " - "in " - "combination with the corresponding height parameter."); - - cconfig_util_set_int( - config, - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_HEIGHT_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_HEIGHT_VALUE, - "Up-/downscale the back buffer's height. This does not change the " - "game's rendering resolution but scales " - "the " - "final frame. Use this to target the native resolution of your " - "monitor/TV, e.g. to avoid over-/underscan, " - "bad " - "image quality or latency caused by the monitors internal " - "upscaler. 0 to disable this feature. Must be set " - "in " - "combination with the corresponding width parameter."); - - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_FILTER_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE, - "Filter type to use for up-/downscaling the back buffer. Only used " - "if scaling feature was enabled by " - "setting " - "the scaling width and height parameters. Available types: none, " - "linear, point (refer to " - "D3DTEXTUREFILTERTYPE " - " for explanation)."); - - cconfig_util_set_int( - config, - IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE, - "Forced refresh rate, -1 to not force any (try 59 or 60 if monitor " - "check fails to lock on high refresh rate monitors)"); - - cconfig_util_set_int( - config, - IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE, - "D3D9 device adapter (monitor), -1 to use default, " - "0, 1, 2 etc. to use specified adapter"); - - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE, - "Fix diagonal tearing with video cards " - "other than Radeon X1300 and HD3450"); -} - -void iidxhook_config_gfx_get( - struct iidxhook_config_gfx *config_gfx, struct cconfig *config) +static void _iidxhook_util_config_gfx_verify(const iidxhook_config_gfx_t *config) { - char tmp[10]; - char *vid; - char *pid; - int32_t tmp_int; - - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_GFX_BGVIDEO_UV_FIX_KEY, - &config_gfx->bgvideo_uv_fix, - IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_BGVIDEO_UV_FIX_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_BGVIDEO_UV_FIX_VALUE); + if (config->frame_rate_limit < 0.0 || config->frame_rate_limit > 500.0) { + log_fatal("Invalid frame_rate_limit value in gfx configuration: %f", config->frame_rate_limit); } - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_GFX_FRAMED_KEY, - &config_gfx->framed, - IIDXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_FRAMED_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE); + if (!(fabs(config->monitor_check - (-1.0)) < 0.001 || + fabs(config->monitor_check) < 0.001 || + config->monitor_check < 500.0)) { + log_fatal("Invalid monitor_check value in gfx configuration: %f", config->monitor_check); } - if (!cconfig_util_get_float( - config, - IIDXHOOK_CONFIG_GFX_FRAME_RATE_LIMIT_KEY, - &config_gfx->frame_rate_limit, - IIDXHOOK_CONFIG_GFX_DEFAULT_FRAME_RATE_LIMIT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%f'", - IIDXHOOK_CONFIG_GFX_FRAME_RATE_LIMIT_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_FRAME_RATE_LIMIT_VALUE); + if (config->window_width > 10000 || config->window_width < 0) { + log_fatal("Invalid window_width value in gfx configuration: %d", config->window_width); } - if (!cconfig_util_get_float( - config, - IIDXHOOK_CONFIG_GFX_MONITOR_CHECK_KEY, - &config_gfx->monitor_check, - IIDXHOOK_CONFIG_GFX_DEFAULT_MONITOR_CHECK_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%f'", - IIDXHOOK_CONFIG_GFX_MONITOR_CHECK_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_MONITOR_CHECK_VALUE); + if (config->window_height > 10000 || config->window_height < 0) { + log_fatal("Invalid window_height value in gfx configuration: %d", config->window_height); } - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_GFX_PCI_ID_KEY, - tmp, - sizeof(tmp) - 1, - IIDXHOOK_CONFIG_GFX_DEFAULT_PCI_ID_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_GFX_PCI_ID_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_PCI_ID_VALUE); + if (config->scale_back_buffer_width > 10000) { + log_fatal("Invalid scale_back_buffer_width value in gfx configuration: %d", config->scale_back_buffer_width); } - if (tmp[4] != ':') { - log_warning( - "Invalid format for value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_GFX_PCI_ID_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_PCI_ID_VALUE); - strcpy(tmp, IIDXHOOK_CONFIG_GFX_DEFAULT_PCI_ID_VALUE); + if (config->scale_back_buffer_height > 10000) { + log_fatal("Invalid scale_back_buffer_height value in gfx configuration: %d", config->scale_back_buffer_height); } - tmp[4] = '\0'; - vid = tmp; - pid = &tmp[5]; - config_gfx->pci_id_vid = strtol(vid, NULL, 16); - config_gfx->pci_id_pid = strtol(pid, NULL, 16); - - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_GFX_WINDOWED_KEY, - &config_gfx->windowed, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_WINDOWED_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE); + if (config->forced_refresh_rate < -1 || config->forced_refresh_rate > 500) { + log_fatal("Invalid forced_refresh_rate value in gfx configuration: %d", config->forced_refresh_rate); } - if (!cconfig_util_get_int( - config, - IIDXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY, - &config_gfx->window_width, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE); - } - - if (!cconfig_util_get_int( - config, - IIDXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY, - &config_gfx->window_height, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE); - } - - if (!cconfig_util_get_int( - config, - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_WIDTH_KEY, - &tmp_int, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_WIDTH_VALUE) || - tmp_int < 0 || tmp_int > 0xFFFF) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_WIDTH_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_WIDTH_VALUE); - } - - config_gfx->scale_back_buffer_width = (uint16_t) tmp_int; - - if (!cconfig_util_get_int( - config, - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_HEIGHT_KEY, - &tmp_int, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_HEIGHT_VALUE) || - tmp_int < 0 || tmp_int > 0xFFFF) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_HEIGHT_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_HEIGHT_VALUE); + if (config->device_adapter < -1 || config->device_adapter > 32) { + log_fatal("Invalid device_adapter value in gfx configuration: %d", config->device_adapter); } +} - config_gfx->scale_back_buffer_height = (uint16_t) tmp_int; +static void _iidxhook_util_config_gfx_back_buffer_scale_filter_get( + const bt_core_config_t *config, + enum iidxhook_util_d3d9_back_buffer_scale_filter *filter) +{ + char tmp[16]; - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_FILTER_KEY, - tmp, - sizeof(tmp) - 1, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_FILTER_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE); - } + bt_core_config_str_get(config, "gfx/back_buffer_scale/filter", tmp, sizeof(tmp)); - if (!strcmp(tmp, "none")) { - config_gfx->scale_back_buffer_filter = - IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_NONE; - } else if (!strcmp(tmp, "linear")) { - config_gfx->scale_back_buffer_filter = - IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_LINEAR; - } else if (!strcmp(tmp, "point")) { - config_gfx->scale_back_buffer_filter = - IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_POINT; + if (str_eq(tmp, "none")) { + *filter = IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_NONE; + } else if (str_eq(tmp, "linear")) { + *filter = IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_LINEAR; + } else if (str_eq(tmp, "point")) { + *filter = IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_POINT; } else { - config_gfx->scale_back_buffer_filter = - IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_NONE; - - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_GFX_SCALE_BACK_BUFFER_FILTER_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_SCALE_BACK_BUFFER_FILTER_VALUE); - } - - if (!cconfig_util_get_int( - config, - IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY, - &config_gfx->forced_refresh_rate, - IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE); - } - - if (!cconfig_util_get_int( - config, - IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY, - &config_gfx->device_adapter, - IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY, - &config_gfx->diagonal_tearing_fix, - IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_GFX_DIAGONAL_TEARING_FIX_KEY, - IIDXHOOK_CONFIG_GFX_DEFAULT_DIAGONAL_TEARING_FIX_VALUE); + log_fatal("Invalid value for back_buffer_scale/filter in gfx config: %s", tmp); } } + +void iidxhook_util_config_gfx_get( + const bt_core_config_t *config, + iidxhook_config_gfx_t *config_gfx) +{ + bt_core_config_s8_get(config, "gfx/device/adapter", &config_gfx->device_adapter); + bt_core_config_s16_get(config, "gfx/device/forced_refresh_rate", &config_gfx->forced_refresh_rate); + bt_core_config_float_get(config, "gfx/device/frame_rate_limit", &config_gfx->frame_rate_limit); + bt_core_config_u16_get(config, "gfx/device/pci_id_vid", &config_gfx->pci_id_vid); + bt_core_config_u16_get(config, "gfx/device/pci_id_pid", &config_gfx->pci_id_pid); + + bt_core_config_bool_get(config, "gfx/window/windowed", &config_gfx->windowed); + bt_core_config_bool_get(config, "gfx/window/framed", &config_gfx->framed); + bt_core_config_u16_get(config, "gfx/window/width", &config_gfx->window_width); + bt_core_config_u16_get(config, "gfx/window/height", &config_gfx->window_height); + + bt_core_config_u16_get(config, "gfx/back_buffer_scale/width", &config_gfx->scale_back_buffer_width); + bt_core_config_u16_get(config, "gfx/back_buffer_scale/height", &config_gfx->scale_back_buffer_height); + _iidxhook_util_config_gfx_back_buffer_scale_filter_get(config, &config_gfx->scale_back_buffer_filter); + + bt_core_config_bool_get(config, "gfx/game/bgvideo_uv_fix", &config_gfx->bgvideo_uv_fix); + bt_core_config_float_get(config, "gfx/game/monitor_check", &config_gfx->monitor_check); + bt_core_config_bool_get(config, "gfx/game/diagonal_tearing_fix", &config_gfx->diagonal_tearing_fix); + bt_core_config_bool_get(config, "gfx/game/happy_sky_ms_bg_fix", &config_gfx->happy_sky_ms_bg_fix); + bt_core_config_bool_get(config, "gfx/game/distorted_ms_bg_fix", &config_gfx->distorted_ms_bg_fix); + + _iidxhook_util_config_gfx_verify(config_gfx); +} \ No newline at end of file diff --git a/src/main/iidxhook-util/config-gfx.h b/src/main/iidxhook-util/config-gfx.h index 6a73e62e..7da23f9d 100644 --- a/src/main/iidxhook-util/config-gfx.h +++ b/src/main/iidxhook-util/config-gfx.h @@ -1,12 +1,12 @@ #ifndef IIDXHOOK_CONFIG_GFX_H #define IIDXHOOK_CONFIG_GFX_H -#include "cconfig/cconfig.h" +#include "iface-core/config.h" #include "iidxhook-util/d3d9.h" // see struct iidxhook_util_d3d9_config for more info -struct iidxhook_config_gfx { +typedef struct iidxhook_config_gfx { bool bgvideo_uv_fix; bool framed; float frame_rate_limit; @@ -14,19 +14,20 @@ struct iidxhook_config_gfx { uint16_t pci_id_vid; uint16_t pci_id_pid; bool windowed; - int32_t window_width; - int32_t window_height; + uint16_t window_width; + uint16_t window_height; uint16_t scale_back_buffer_width; uint16_t scale_back_buffer_height; enum iidxhook_util_d3d9_back_buffer_scale_filter scale_back_buffer_filter; - int32_t forced_refresh_rate; - int32_t device_adapter; + int16_t forced_refresh_rate; + int8_t device_adapter; bool diagonal_tearing_fix; -}; + bool happy_sky_ms_bg_fix; + bool distorted_ms_bg_fix; +} iidxhook_config_gfx_t; -void iidxhook_config_gfx_init(struct cconfig *config); - -void iidxhook_config_gfx_get( - struct iidxhook_config_gfx *config_gfx, struct cconfig *config); +void iidxhook_util_config_gfx_get( + const bt_core_config_t *config, + iidxhook_config_gfx_t *config_gfx); #endif \ No newline at end of file diff --git a/src/main/iidxhook-util/config-io.c b/src/main/iidxhook-util/config-io.c index 3055ac6e..e8bbc863 100644 --- a/src/main/iidxhook-util/config-io.c +++ b/src/main/iidxhook-util/config-io.c @@ -1,57 +1,13 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" -#include "iidxhook-util/config-io.h" - -#include "util/log.h" - -#define IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY \ - "io.disable_card_reader_emu" -#define IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY "io.disable_io_emu" - -#define IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false -#define IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE false +#include "iface-core/log.h" -void iidxhook_config_io_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE, - "Disable card reader emulation and enable usage of real card reader " - "hardware on COM1 (for games supporting slotted/wavepass readers)"); - - cconfig_util_set_bool( - config, - IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY, - IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE, - "Disable ezusb IO emulation and enable usage of real ezusb1/2 IO " - "hardware"); -} +#include "iidxhook-util/config-io.h" -void iidxhook_config_io_get( - struct iidxhook_config_io *config_io, struct cconfig *config) +void iidxhook_util_config_io_get( + const bt_core_config_t *config, + iidxhook_config_io_t *config_io) { - if (!cconfig_util_get_bool( - config, - IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - &config_io->disable_card_reader_emu, - IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY, - &config_io->disable_io_emu, - IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY, - IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE); - } -} + bt_core_config_ext_bool_get(config, "io/disable_card_reader_emu", &config_io->disable_card_reader_emu); + bt_core_config_ext_bool_get(config, "io/disable_io_emu", &config_io->disable_io_emu); +} \ No newline at end of file diff --git a/src/main/iidxhook-util/config-io.h b/src/main/iidxhook-util/config-io.h index 0f63750d..e18b1ebd 100644 --- a/src/main/iidxhook-util/config-io.h +++ b/src/main/iidxhook-util/config-io.h @@ -3,16 +3,15 @@ #include -#include "cconfig/cconfig.h" +#include "iface-core/config.h" -struct iidxhook_config_io { +typedef struct iidxhook_config_io { bool disable_card_reader_emu; bool disable_io_emu; -}; +} iidxhook_config_io_t; -void iidxhook_config_io_init(struct cconfig *config); - -void iidxhook_config_io_get( - struct iidxhook_config_io *config_io, struct cconfig *config); +void iidxhook_util_config_io_get( + const bt_core_config_t *config, + iidxhook_config_io_t *config_io); #endif \ No newline at end of file diff --git a/src/main/iidxhook-util/config-misc.c b/src/main/iidxhook-util/config-misc.c index 7a18499e..65f6f205 100644 --- a/src/main/iidxhook-util/config-misc.c +++ b/src/main/iidxhook-util/config-misc.c @@ -1,76 +1,12 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "iidxhook-util/config-misc.h" -#include "util/log.h" - -#define IIDXHOOK_CONFIG_MISC_DISABLE_CLOCK_SET_KEY "misc.disable_clock_set" -#define IIDXHOOK_CONFIG_MISC_RTEFFECT_STUB_KEY "misc.rteffect_stub" -#define IIDXHOOK_CONFIG_MISC_SETTINGS_PATH_STUB_KEY "misc.settings_path" - -#define IIDXHOOK_CONFIG_MISC_DEFAULT_DISABLE_CLOCK_SET_VALUE false -#define IIDXHOOK_CONFIG_MISC_DEFAULT_RTEFFECT_STUB_VALUE false -#define IIDXHOOK_CONFIG_MISC_DEFAULT_SETTINGS_PATH_STUB_VALUE ".\\" - -void iidxhook_config_misc_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_MISC_DISABLE_CLOCK_SET_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_DISABLE_CLOCK_SET_VALUE, - "Disable operator clock setting system clock time"); - - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_MISC_RTEFFECT_STUB_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_RTEFFECT_STUB_VALUE, - "Stub calls to rteffect.dll (10th to DistorteD)"); - - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_MISC_SETTINGS_PATH_STUB_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_SETTINGS_PATH_STUB_VALUE, - "Path to store the settings, e.g. bookkeeping, operator settings. d:, " - "e: and f: drive configuration/settings data"); -} - -void iidxhook_config_misc_get( - struct iidxhook_config_misc *config_misc, struct cconfig *config) +void iidxhook_util_config_misc_get( + const bt_core_config_t *config, + iidxhook_config_misc_t *config_misc) { - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_MISC_DISABLE_CLOCK_SET_KEY, - &config_misc->disable_clock_set, - IIDXHOOK_CONFIG_MISC_DEFAULT_DISABLE_CLOCK_SET_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_MISC_DISABLE_CLOCK_SET_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_DISABLE_CLOCK_SET_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_MISC_RTEFFECT_STUB_KEY, - &config_misc->rteffect_stub, - IIDXHOOK_CONFIG_MISC_DEFAULT_RTEFFECT_STUB_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_MISC_RTEFFECT_STUB_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_RTEFFECT_STUB_VALUE); - } - - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_MISC_SETTINGS_PATH_STUB_KEY, - config_misc->settings_path, - sizeof(config_misc->settings_path), - IIDXHOOK_CONFIG_MISC_DEFAULT_SETTINGS_PATH_STUB_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_MISC_SETTINGS_PATH_STUB_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_SETTINGS_PATH_STUB_VALUE); - } + bt_core_config_ext_bool_get(config, "misc/disable_clock_set", &config_misc->disable_clock_set); + bt_core_config_ext_bool_get(config, "misc/rteffect_stub", &config_misc->rteffect_stub); + bt_core_config_ext_str_get(config, "misc/settings_path", config_misc->settings_path, sizeof(config_misc->settings_path)); } diff --git a/src/main/iidxhook-util/config-misc.h b/src/main/iidxhook-util/config-misc.h index 743e83d4..f553069b 100644 --- a/src/main/iidxhook-util/config-misc.h +++ b/src/main/iidxhook-util/config-misc.h @@ -3,17 +3,16 @@ #include -#include "cconfig/cconfig.h" +#include "iface-core/config.h" -struct iidxhook_config_misc { +typedef struct iidxhook_config_misc { bool disable_clock_set; bool rteffect_stub; char settings_path[MAX_PATH]; -}; +} iidxhook_config_misc_t; -void iidxhook_config_misc_init(struct cconfig *config); - -void iidxhook_config_misc_get( - struct iidxhook_config_misc *config_misc, struct cconfig *config); +void iidxhook_util_config_misc_get( + const bt_core_config_t *config, + iidxhook_config_misc_t *config_misc); #endif \ No newline at end of file diff --git a/src/main/iidxhook-util/config-sec.c b/src/main/iidxhook-util/config-sec.c index 54cb0eea..07cb1d11 100644 --- a/src/main/iidxhook-util/config-sec.c +++ b/src/main/iidxhook-util/config-sec.c @@ -1,64 +1,17 @@ #include #include -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" + +#include "iface-core/log.h" #include "iidxhook-util/config-sec.h" #include "security/mcode.h" #include "security/rp.h" -#include "util/log.h" #include "util/mem.h" -#define IIDXHOOK_CONFIG_SEC_BOOT_VERSION_KEY "sec.boot_version" -#define IIDXHOOK_CONFIG_SEC_BOOT_SEEDS_KEY "sec.boot_seeds" -#define IIDXHOOK_CONFIG_SEC_BLACK_PLUG_MCODE_KEY "sec.black_plug_mcode" - -/* Use C02 defaults */ -#define IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_VERSION_VALUE \ - iidxhook_security_default_boot_version -#define IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_SEEDS_VALUE \ - iidxhook_security_default_boot_seeds -#define IIDXHOOK_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE \ - iidxhook_security_default_black_plug_mcode - -/* IIDX 09 default */ -static const struct security_mcode iidxhook_security_default_boot_version = { - .header = SECURITY_MCODE_HEADER, - .unkn = SECURITY_MCODE_UNKN_E, - .game = SECURITY_MCODE_GAME_IIDX_9, - .region = SECURITY_MCODE_FIELD_BLANK, - .cabinet = SECURITY_MCODE_FIELD_BLANK, - .revision = SECURITY_MCODE_FIELD_BLANK, -}; - -/* IIDX 09 default */ -static const uint32_t iidxhook_security_default_boot_seeds[3] = {0, 0, 0}; - -/* IIDX 09 default */ -static const struct security_mcode iidxhook_security_default_black_plug_mcode = - { - .header = SECURITY_MCODE_HEADER, - .unkn = SECURITY_MCODE_UNKN_Q, - .game = SECURITY_MCODE_GAME_IIDX_9, - .region = SECURITY_MCODE_REGION_JAPAN, - .cabinet = SECURITY_MCODE_CABINET_A, - .revision = SECURITY_MCODE_REVISION_A, -}; - -static char *iidxhook_config_boot_seeds_to_str(const uint32_t *seeds) -{ - char *res; - size_t len; - - len = snprintf(NULL, 0, "%d:%d:%d", seeds[0], seeds[1], seeds[2]); - res = xmalloc(len + 1); - sprintf(res, "%d:%d:%d", seeds[0], seeds[1], seeds[2]); - - return res; -} - static bool iidxhook_config_boot_seeds_parse(const char *str, uint32_t *seeds) { if (strlen(str) < 5) { @@ -75,140 +28,33 @@ static bool iidxhook_config_boot_seeds_parse(const char *str, uint32_t *seeds) } } -void iidxhook_config_sec_init(struct cconfig *config) +static void _iidxhook_util_config_sec_security_mcode_get(const bt_core_config_t *config, const char *path, struct security_mcode *mcode) { - char *tmp; - - tmp = - security_mcode_to_str(&IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_VERSION_VALUE); - - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_SEC_BOOT_VERSION_KEY, - tmp, - "Security boot version (e.g. GEC02)."); - - free(tmp); - - tmp = iidxhook_config_boot_seeds_to_str( - IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_SEEDS_VALUE); - - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_SEC_BOOT_SEEDS_KEY, - tmp, - "Security boot seeds for ezusb, format: X:X:X where X is a number " - "of " - "0-9 (e.g. 0:0:0)."); - - free(tmp); - - tmp = security_mcode_to_str( - &IIDXHOOK_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE); + char tmp[sizeof(struct security_mcode) + 1]; - cconfig_util_set_str( - config, - IIDXHOOK_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp, - "Security black plug mcode id string (e.g. GQC02JAA)."); + bt_core_config_ext_str_get(config, path, tmp, sizeof(tmp)); - free(tmp); + if (!security_mcode_parse(tmp, mcode)) { + log_fatal("Parsing mcode failed: %s", tmp); + } } -void iidxhook_config_sec_get( - struct iidxhook_config_sec *config_sec, struct cconfig *config) +static void _iidxhook_util_config_sec_boot_seeds_get(const bt_core_config_t *config, uint32_t *boot_seeds) { - char tmp_seeds[6]; - char tmp_mcode[sizeof(struct security_mcode) + 1]; - char *tmp_str; - - tmp_str = - security_mcode_to_str(&IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_VERSION_VALUE); + char tmp[8]; - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_SEC_BOOT_VERSION_KEY, - tmp_mcode, - sizeof(tmp_mcode) - 1, - tmp_str)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_SEC_BOOT_VERSION_KEY, - tmp_str); - } - - if (!security_mcode_parse(tmp_mcode, &config_sec->boot_version)) { - log_warning( - "Invalid format for value of key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_SEC_BOOT_VERSION_KEY, - tmp_str); - memcpy( - &config_sec->boot_version, - &IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_VERSION_VALUE, - sizeof(IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_VERSION_VALUE)); - } - - free(tmp_str); - - tmp_str = iidxhook_config_boot_seeds_to_str( - IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_SEEDS_VALUE); - - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_SEC_BOOT_SEEDS_KEY, - tmp_seeds, - sizeof(tmp_seeds) - 1, - tmp_str)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_SEC_BOOT_SEEDS_KEY, - tmp_str); - } + bt_core_config_ext_str_get(config, "ezusb/security/boot/seed", tmp, sizeof(tmp)); - if (!iidxhook_config_boot_seeds_parse(tmp_seeds, config_sec->boot_seeds)) { - log_warning( - "Invalid format for value of key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_SEC_BOOT_SEEDS_KEY, - tmp_str); - memcpy( - config_sec->boot_seeds, - IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_SEEDS_VALUE, - sizeof(IIDXHOOK_CONFIG_SEC_DEFAULT_BOOT_SEEDS_VALUE)); - } - - free(tmp_str); - - tmp_str = security_mcode_to_str( - &IIDXHOOK_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE); - - if (!cconfig_util_get_str( - config, - IIDXHOOK_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp_mcode, - sizeof(tmp_mcode) - 1, - tmp_str)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp_str); - } - - if (!security_mcode_parse(tmp_mcode, &config_sec->black_plug_mcode)) { - log_warning( - "Invalid format for value of key '%s' specified, fallback " - "to default '%s'", - IIDXHOOK_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp_str); - memcpy( - &config_sec->black_plug_mcode, - &IIDXHOOK_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE, - sizeof(IIDXHOOK_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE)); + if (!iidxhook_config_boot_seeds_parse(tmp, boot_seeds)) { + log_fatal("Parsing security boot seeds failed: %s", tmp); } +} - free(tmp_str); +void iidxhook_util_config_sec_get( + const bt_core_config_t *config, + iidxhook_config_sec_t *config_sec) +{ + _iidxhook_util_config_sec_security_mcode_get(config, "ezusb/security/boot/version", &config_sec->boot_version); + _iidxhook_util_config_sec_boot_seeds_get(config, config_sec->boot_seeds); + _iidxhook_util_config_sec_security_mcode_get(config, "ezusb/security/plug_black_mcode", &config_sec->black_plug_mcode); } diff --git a/src/main/iidxhook-util/config-sec.h b/src/main/iidxhook-util/config-sec.h index 314940d6..1e58a007 100644 --- a/src/main/iidxhook-util/config-sec.h +++ b/src/main/iidxhook-util/config-sec.h @@ -1,19 +1,18 @@ #ifndef IIDXHOOK_CONFIG_SEC_H #define IIDXHOOK_CONFIG_SEC_H -#include "cconfig/cconfig.h" +#include "iface-core/config.h" #include "security/mcode.h" -struct iidxhook_config_sec { +typedef struct iidxhook_config_sec { struct security_mcode boot_version; uint32_t boot_seeds[3]; struct security_mcode black_plug_mcode; -}; +} iidxhook_config_sec_t; -void iidxhook_config_sec_init(struct cconfig *config); - -void iidxhook_config_sec_get( - struct iidxhook_config_sec *config_sec, struct cconfig *config); +void iidxhook_util_config_sec_get( + const bt_core_config_t *config, + iidxhook_config_sec_t *config_sec); #endif \ No newline at end of file diff --git a/src/main/iidxhook-util/d3d9.c b/src/main/iidxhook-util/d3d9.c index 9c877199..77a24b43 100644 --- a/src/main/iidxhook-util/d3d9.c +++ b/src/main/iidxhook-util/d3d9.c @@ -12,11 +12,12 @@ #include "hook/com-proxy.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "iidxhook-util/d3d9.h" #include "iidxhook-util/vertex-shader.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #include "util/time.h" diff --git a/src/main/iidxhook-util/eamuse.c b/src/main/iidxhook-util/eamuse.c index bd56c775..7b58c8d5 100644 --- a/src/main/iidxhook-util/eamuse.c +++ b/src/main/iidxhook-util/eamuse.c @@ -10,10 +10,11 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "iidxhook-util/eamuse.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" /* ------------------------------------------------------------------------- */ @@ -119,6 +120,14 @@ void eamuse_hook_init(void) log_info("Inserted eamuse hooks"); } +void eamuse_hook_fini() +{ + hook_table_revert( + NULL, "ws2_32.dll", eamuse_hook_syms, lengthof(eamuse_hook_syms)); + + log_info("Removed eamuse hooks"); +} + void eamuse_set_addr(const struct net_addr *addr) { char *tmp_str; diff --git a/src/main/iidxhook-util/eamuse.h b/src/main/iidxhook-util/eamuse.h index 111ffe34..3bbec855 100644 --- a/src/main/iidxhook-util/eamuse.h +++ b/src/main/iidxhook-util/eamuse.h @@ -9,6 +9,8 @@ */ void eamuse_hook_init(void); +void eamuse_hook_fini(); + /** * Set a net_addr to a eamuse server for the game to connect to. * diff --git a/src/main/iidxhook-util/effector.c b/src/main/iidxhook-util/effector.c index 4f30e279..a6e41795 100644 --- a/src/main/iidxhook-util/effector.c +++ b/src/main/iidxhook-util/effector.c @@ -4,10 +4,11 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "iidxhook-util/effector.h" #include "util/defs.h" -#include "util/log.h" static BOOL my_EnableEqualizer(int a1); static BOOL my_GetEqualizerStatus(LPVOID buffer); @@ -80,3 +81,11 @@ void effector_hook_init(void) log_info("Inserted rteffect hooks"); } + +void effector_hook_fini() +{ + hook_table_revert( + NULL, "rteffect.dll", effector_hook_syms, lengthof(effector_hook_syms)); + + log_info("Removed rteffect hooks"); +} \ No newline at end of file diff --git a/src/main/iidxhook-util/effector.h b/src/main/iidxhook-util/effector.h index 4a9592e6..473f3446 100644 --- a/src/main/iidxhook-util/effector.h +++ b/src/main/iidxhook-util/effector.h @@ -8,4 +8,6 @@ */ void effector_hook_init(void); +void effector_hook_fini(); + #endif diff --git a/src/main/iidxhook-util/log-server.c b/src/main/iidxhook-util/log-server.c deleted file mode 100644 index 1a7f687c..00000000 --- a/src/main/iidxhook-util/log-server.c +++ /dev/null @@ -1,163 +0,0 @@ -#include - -#include -#include -#include -#include - -#include "hook/table.h" - -#include "iidxhook-util/log-server.h" - -#include "imports/avs.h" - -#include "util/defs.h" -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -static int log_thread_proc(void *ctx); -static void -log_post(char level, const char *module, const char *fmt, va_list ap); -static void log_post_misc(const char *module, const char *fmt, ...); -static void log_post_info(const char *module, const char *fmt, ...); -static void log_post_warning(const char *module, const char *fmt, ...); -static void log_post_fatal(const char *module, const char *fmt, ...); - -static int log_thread_id; -static HANDLE log_rv_producer; -static HANDLE log_rv_consumer; -static char log_rv_level; -static const char *log_rv_module; -static char log_rv_buffer[8192]; - -void log_server_init(void) -{ - HANDLE ready; - - log_rv_producer = CreateSemaphore(NULL, 1, 1, NULL); - log_rv_consumer = CreateSemaphore(NULL, 0, 1, NULL); - ready = CreateEvent(NULL, TRUE, FALSE, NULL); - - log_to_external( - log_post_misc, log_post_info, log_post_warning, log_post_fatal); - - log_thread_id = avs_thread_create(log_thread_proc, ready, 16384, 0); - - if (WaitForSingleObject(ready, INFINITE)) { - // can't do any logging here, yet. - fprintf( - stderr, - "ERROR log_server_init: WaitForSingleObject failed: %08x", - (unsigned int) GetLastError()); - return; - } - - CloseHandle(ready); - - log_misc("Started log server thread"); -} - -static int log_thread_proc(void *ctx) -{ - bool run; - - SetEvent((HANDLE) ctx); - - run = true; - - log_body_misc(LOG_MODULE, "Log server thread is running"); - - while (run) { - if (WaitForSingleObject(log_rv_consumer, INFINITE)) { - log_fatal( - "WaitForSingleObject failed: %08x", - (unsigned int) GetLastError()); - } - - switch (log_rv_level) { - case '\0': - run = false; - - break; - - case 'M': - log_body_misc(log_rv_module, "%s", log_rv_buffer); - - break; - - case 'I': - log_body_info(log_rv_module, "%s", log_rv_buffer); - - break; - - case 'W': - log_body_warning(log_rv_module, "%s", log_rv_buffer); - - break; - - case 'F': - log_body_fatal(log_rv_module, "%s", log_rv_buffer); - - break; - } - - if (!ReleaseSemaphore(log_rv_producer, 1, NULL)) { - log_fatal( - "ReleaseSemaphore failed: %08x", (unsigned int) GetLastError()); - } - } - - log_body_misc(LOG_MODULE, "Log server thread is exiting"); - - return 0; -} - -static void -log_post(char level, const char *module, const char *fmt, va_list ap) -{ - if (WaitForSingleObject(log_rv_producer, INFINITE)) { - return; - } - - log_rv_level = level; - log_rv_module = module; - str_vformat(log_rv_buffer, sizeof(log_rv_buffer), fmt, ap); - - ReleaseSemaphore(log_rv_consumer, 1, NULL); -} - -#define LOG_POST_IMPL(name, level) \ - static void name(const char *module, const char *fmt, ...) \ - { \ - va_list ap; \ - \ - va_start(ap, fmt); \ - log_post(level, module, fmt, ap); \ - va_end(ap); \ - } - -LOG_POST_IMPL(log_post_misc, 'M') -LOG_POST_IMPL(log_post_info, 'I') -LOG_POST_IMPL(log_post_warning, 'W') -LOG_POST_IMPL(log_post_fatal, 'F') - -void log_server_fini(void) -{ - int thread_result; - - log_misc("Stopping log server thread"); - - WaitForSingleObject(log_rv_producer, INFINITE); - log_rv_level = '\0'; - ReleaseSemaphore(log_rv_consumer, 1, NULL); - - avs_thread_join(log_thread_id, &thread_result); - avs_thread_destroy(log_thread_id); - - CloseHandle(log_rv_producer); - CloseHandle(log_rv_consumer); - - log_rv_producer = NULL; - log_rv_consumer = NULL; -} diff --git a/src/main/iidxhook-util/log-server.h b/src/main/iidxhook-util/log-server.h deleted file mode 100644 index 5984baa3..00000000 --- a/src/main/iidxhook-util/log-server.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef IIDXHOOK_LOG_SERVER_H -#define IIDXHOOK_LOG_SERVER_H - -/** - * Initialize the log server which creates a dedicated thread and a log message - * queue. - * - * Log messages are posted to the queue by the application and the background - * thread writes them to the target output. Required for newer iidx and pop'n - * games using the avs log api (e.g. iidxhook4 to 7) due to a quirk of the ezusb - * driver. For a full breakdown about the logging on avs (and non avs) based - * konami games, see doc/logging-breadkdown-avs.md. - */ -void log_server_init(void); - -/** - * Shut down the log server. - */ -void log_server_fini(void); - -#endif diff --git a/src/main/iidxhook-util/settings.c b/src/main/iidxhook-util/settings.c index b4f2ce3f..9dab10d1 100644 --- a/src/main/iidxhook-util/settings.c +++ b/src/main/iidxhook-util/settings.c @@ -10,9 +10,10 @@ #include "hook/iohook.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" #include "util/fs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" @@ -99,6 +100,14 @@ void settings_hook_init(void) log_info("Inserted settings hooks, settings path: %s", settings_path); } +void settings_hook_fini() +{ + hook_table_revert( + NULL, "kernel32.dll", settings_hook_syms, lengthof(settings_hook_syms)); + + log_info("Removed settings hooks for settings path: %s", settings_path); +} + void settings_hook_set_path(const char *path) { size_t len; diff --git a/src/main/iidxhook-util/settings.h b/src/main/iidxhook-util/settings.h index d95d0902..0f713911 100644 --- a/src/main/iidxhook-util/settings.h +++ b/src/main/iidxhook-util/settings.h @@ -12,6 +12,8 @@ */ void settings_hook_init(void); +void settings_hook_fini(); + /** * Change the path where settings file are stored. * diff --git a/src/main/iidxhook1/Module.mk b/src/main/iidxhook1/Module.mk index fcfad98b..5d3cede2 100644 --- a/src/main/iidxhook1/Module.mk +++ b/src/main/iidxhook1/Module.mk @@ -3,24 +3,30 @@ dlls += iidxhook1 ldflags_iidxhook1 := \ -lws2_32 \ -liphlpapi \ + -lpsapi \ + -lshlwapi \ libs_iidxhook1 := \ + sdk-hook \ + core \ iidxhook-util \ ezusb-emu \ ezusb-iidx-16seg-emu \ ezusb-iidx-emu \ security \ - eamio \ acioemu \ hook \ hooklib \ - iidxio \ - cconfig \ - util \ + module \ ezusb \ + iface \ + iface-io \ + iface-core \ + util \ + mxml \ src_iidxhook1 := \ - config-iidxhook1.c \ dllmain.c \ + iidxhook1.c \ ezusb-mon.c \ log-ezusb.c \ diff --git a/src/main/iidxhook1/config-iidxhook1.c b/src/main/iidxhook1/config-iidxhook1.c deleted file mode 100644 index 5a02c95c..00000000 --- a/src/main/iidxhook1/config-iidxhook1.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "cconfig/cconfig-util.h" - -#include "iidxhook1/config-iidxhook1.h" - -#include "util/log.h" - -#define IIDXHOOK_CONFIG_MISC_HAPPY_SKY_MS_BG_FIX_KEY "misc.happy_sky_ms_bg_fix" - -#define IIDXHOOK_CONFIG_MISC_DEFAULT_HAPPY_SKY_MS_BG_FIX_VALUE false - -void iidxhook_config_iidxhook1_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_MISC_HAPPY_SKY_MS_BG_FIX_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_HAPPY_SKY_MS_BG_FIX_VALUE, - "Fix broken 3D background on Happy Sky's music select (if " - "appearing " - "completely white)"); -} - -void iidxhook_config_iidxhook1_get( - struct iidxhook_config_iidxhook1 *config_iidxhook1, struct cconfig *config) -{ - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_MISC_HAPPY_SKY_MS_BG_FIX_KEY, - &config_iidxhook1->happy_sky_ms_bg_fix, - IIDXHOOK_CONFIG_MISC_DEFAULT_HAPPY_SKY_MS_BG_FIX_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_MISC_HAPPY_SKY_MS_BG_FIX_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_HAPPY_SKY_MS_BG_FIX_VALUE); - } -} \ No newline at end of file diff --git a/src/main/iidxhook1/config-iidxhook1.h b/src/main/iidxhook1/config-iidxhook1.h deleted file mode 100644 index bec1e487..00000000 --- a/src/main/iidxhook1/config-iidxhook1.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef IIDXHOOK_CONFIG_IIDXHOOK1_H -#define IIDXHOOK_CONFIG_IIDXHOOK1_H - -#include "cconfig/cconfig.h" - -struct iidxhook_config_iidxhook1 { - bool happy_sky_ms_bg_fix; -}; - -void iidxhook_config_iidxhook1_init(struct cconfig *config); - -void iidxhook_config_iidxhook1_get( - struct iidxhook_config_iidxhook1 *config_iidxhook1, struct cconfig *config); - -#endif \ No newline at end of file diff --git a/src/main/iidxhook1/dllmain.c b/src/main/iidxhook1/dllmain.c index a3a4a357..5b0742b3 100644 --- a/src/main/iidxhook1/dllmain.c +++ b/src/main/iidxhook1/dllmain.c @@ -1,280 +1,70 @@ #include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-emu/desc.h" -#include "ezusb-emu/device.h" -#include "ezusb-emu/node-security-plug.h" - -#include "ezusb-iidx-emu/msg.h" -#include "ezusb-iidx-emu/node-serial.h" -#include "ezusb-iidx-emu/nodes.h" - -#include "hook/d3d9.h" -#include "hook/iohook.h" #include "hook/table.h" -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-util/chart-patch.h" -#include "iidxhook-util/clock.h" -#include "iidxhook-util/config-eamuse.h" -#include "iidxhook-util/config-ezusb.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-misc.h" -#include "iidxhook-util/config-sec.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/eamuse.h" -#include "iidxhook-util/effector.h" -#include "iidxhook-util/settings.h" +#include "iidxhook1/iidxhook1.h" -#include "iidxhook1/config-iidxhook1.h" -#include "iidxhook1/ezusb-mon.h" -#include "iidxhook1/log-ezusb.h" +#include "main/sdk-hook/dllentry.h" #include "util/defs.h" -#include "util/log.h" -#include "util/thread.h" - -#define IIDXHOOK1_INFO_HEADER \ - "iidxhook for 9th Style, 10th Style, RED and HAPPY SKY" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK1_CMD_USAGE \ - "Usage: inject.exe iidxhook1.dll [options...]" - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_util_d3d9_irp_handler, -}; -static HANDLE STDCALL my_OpenProcess(DWORD, BOOL, DWORD); -static HANDLE(STDCALL *real_OpenProcess)(DWORD, BOOL, DWORD); +static HANDLE STDCALL _iidxhook1_dllmain_my_OpenProcess(DWORD, BOOL, DWORD); +static HANDLE(STDCALL *_iidxhook1_dllmain_real_OpenProcess)(DWORD, BOOL, DWORD); -static bool iidxhook_init_check; +static bool _iidxhook1_dllmain_openprocess_call_check; -static const struct hook_symbol init_hook_syms[] = { +static const struct hook_symbol _iidxhook1_dllmain_hook_syms[] = { { .name = "OpenProcess", - .patch = my_OpenProcess, - .link = (void **) &real_OpenProcess, + .patch = _iidxhook1_dllmain_my_OpenProcess, + .link = (void **) &_iidxhook1_dllmain_real_OpenProcess, }, }; -static void iidxhook1_setup_d3d9_hooks( - const struct iidxhook_config_gfx *config_gfx, - const struct iidxhook_config_iidxhook1 *config_iidxhook1) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - log_warning( - "d3d8 hook module deprecated, using d3d9 hook modules requiring " - "d3d8to9 to work!"); - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.iidx12_fix_song_select_bg = - config_iidxhook1->happy_sky_ms_bg_fix; - d3d9_config.iidx09_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix; - d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; - d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; - d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - - if (config_gfx->monitor_check == 0) { - log_info("Auto monitor check enabled"); - - d3d9_config.iidx09_to_19_monitor_check_cb = - iidxhook_util_chart_patch_set_refresh_rate; - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); - } else if (config_gfx->monitor_check > 0) { - log_info( - "Manual monitor check, resulting refresh rate: %f", - config_gfx->monitor_check); - - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); - iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); - } - - iidxhook_util_d3d9_configure(&d3d9_config); - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -/** - * This seems to be a good entry point to intercept - * before the game calls anything important - */ static HANDLE STDCALL -my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) +_iidxhook1_dllmain_my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) { - struct cconfig *config; - - struct iidxhook_util_config_ezusb config_ezusb; - struct iidxhook_util_config_eamuse config_eamuse; - struct iidxhook_config_gfx config_gfx; - struct iidxhook_config_iidxhook1 config_iidxhook1; - struct iidxhook_config_misc config_misc; - struct iidxhook_config_sec config_sec; - - if (iidxhook_init_check) { - goto skip; - } - - iidxhook_init_check = true; - - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook my_OpenProcess ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_util_config_ezusb_init(config); - iidxhook_util_config_eamuse_init(config); - iidxhook_config_gfx_init(config); - iidxhook_config_iidxhook1_init(config); - iidxhook_config_misc_init(config); - iidxhook_config_sec_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK1_INFO_HEADER "\n" IIDXHOOK1_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); + if (_iidxhook1_dllmain_openprocess_call_check) { + return _iidxhook1_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); } - iidxhook_util_config_ezusb_get(&config_ezusb, config); - iidxhook_util_config_eamuse_get(&config_eamuse, config); - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_iidxhook1_get(&config_iidxhook1, config); - iidxhook_config_misc_get(&config_misc, config); - iidxhook_config_sec_get(&config_sec, config); - - cconfig_finit(config); - - log_info(IIDXHOOK1_INFO_HEADER); - log_info("Initializing iidxhook..."); - - /* Round plug security */ + _iidxhook1_dllmain_openprocess_call_check = true; - ezusb_iidx_emu_node_security_plug_set_boot_version( - &config_sec.boot_version); - ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); - ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( - &config_sec.black_plug_mcode); - ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + bt_hook_dllentry_main_init(); - /* Magnetic card reader (9th to HS) */ - - ezusb_iidx_emu_node_serial_set_card_attributes( - 0, true, config_eamuse.card_type); - - /* eAmusement server IP */ - - eamuse_set_addr(&config_eamuse.server); - eamuse_check_connection(); - - /* Patch rteffect.dll calls */ - - if (config_misc.rteffect_stub) { - effector_hook_init(); - } - - /* Settings paths */ - - if (strlen(config_misc.settings_path) > 0) { - settings_hook_set_path(config_misc.settings_path); - } - - /* Direct3D and USER32 hooks */ - - iidxhook1_setup_d3d9_hooks(&config_gfx, &config_iidxhook1); - - /* Disable operator menu clock setting system clock time */ - - if (config_misc.disable_clock_set) { - iidxhook_util_clock_hook_init(); - } - - /* Start up IIDXIO.DLL */ - - log_info("Starting IIDX IO backend"); - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - - /* Start up EAMIO.DLL */ - - log_misc("Initializing card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); - iohook_push_handler(settings_hook_dispatch_irp); - - hook_setupapi_init(&ezusb_emu_desc_device.setupapi); - ezusb_emu_device_hook_init( - ezusb_iidx_emu_msg_init(config_ezusb.io_board_type)); - - if (config_ezusb.api_call_monitoring) { - ezusb_log_hook_init(); - ezusb_mon_hook_init(); - } - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook my_OpenProcess ----------------"); - log_info("-------------------------------------------------------------"); - -skip: - return real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); + return _iidxhook1_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); } -/** - * Hook library for 9th to Happy Sky - */ +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() + BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - log_to_writer(log_writer_debug, NULL); + bt_hook_dllentry_init( + mod, + "iidxhook1", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); - /* Bootstrap hook for further init tasks (see above) */ + _iidxhook1_dllmain_openprocess_call_check = false; hook_table_apply( - NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms)); + NULL, "kernel32.dll", _iidxhook1_dllmain_hook_syms, lengthof(_iidxhook1_dllmain_hook_syms)); + + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "kernel32.dll", _iidxhook1_dllmain_hook_syms, lengthof(_iidxhook1_dllmain_hook_syms)); - /* Actual hooks for game specific stuff */ + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); - acp_hook_init(); - adapter_hook_init(); - eamuse_hook_init(); - settings_hook_init(); + bt_hook_dllentry_fini(); + } } return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook1/ezusb-mon.c b/src/main/iidxhook1/ezusb-mon.c index b76418a6..d13f1502 100644 --- a/src/main/iidxhook1/ezusb-mon.c +++ b/src/main/iidxhook1/ezusb-mon.c @@ -8,10 +8,11 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "iidxhook1/ezusb-mon.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" /* ------------------------------------------------------------------------- */ @@ -231,3 +232,10 @@ void ezusb_mon_hook_init(void) log_info("Inserted ezusb mon hooks"); } + +void ezusb_mon_hook_fini() +{ + hook_table_revert(NULL, "ezusb.dll", ezusb_mon_hook_syms, lengthof(ezusb_mon_hook_syms)); + + log_info("Removed ezusb mon hooks"); +} \ No newline at end of file diff --git a/src/main/iidxhook1/ezusb-mon.h b/src/main/iidxhook1/ezusb-mon.h index 31a3340a..be052ebf 100644 --- a/src/main/iidxhook1/ezusb-mon.h +++ b/src/main/iidxhook1/ezusb-mon.h @@ -9,4 +9,6 @@ */ void ezusb_mon_hook_init(void); +void ezusb_mon_hook_fini(); + #endif diff --git a/src/main/iidxhook1/iidxhook1.c b/src/main/iidxhook1/iidxhook1.c new file mode 100644 index 00000000..640652b8 --- /dev/null +++ b/src/main/iidxhook1/iidxhook1.c @@ -0,0 +1,306 @@ +#define LOG_MODULE "iidxhook1" + +#include + +#include +#include +#include + +#include "ezusb-emu/desc.h" +#include "ezusb-emu/device.h" +#include "ezusb-emu/node-security-plug.h" + +#include "ezusb-iidx-emu/msg.h" +#include "ezusb-iidx-emu/node-serial.h" +#include "ezusb-iidx-emu/nodes.h" + +#include "hook/d3d9.h" +#include "hook/iohook.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-util/chart-patch.h" +#include "iidxhook-util/clock.h" +#include "iidxhook-util/config-eamuse.h" +#include "iidxhook-util/config-ezusb.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-misc.h" +#include "iidxhook-util/config-sec.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/eamuse.h" +#include "iidxhook-util/effector.h" +#include "iidxhook-util/settings.h" + +#include "iidxhook1/ezusb-mon.h" +#include "iidxhook1/log-ezusb.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/proc.h" + +static const hook_d3d9_irp_handler_t _iidxhook1_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static module_io_t *_iidxhook1_module_io_iidx; +static module_io_t *_iidxhook1_module_io_eam; + +static void _iidxhook1_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook1_io_iidx_fini(module_io_t **module) +{ + bt_io_iidx_api_clear(); + module_io_free(module); +} + +static void _iidxhook1_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void _iidxhook1_io_eam_fini(module_io_t **module) +{ + bt_io_eam_api_clear(); + module_io_free(module); +} + +static void iidxhook1_setup_d3d9_hooks( + const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + if (!proc_is_module_loaded("d3d9.dll")) { + log_fatal( + "d3d8 hook module deprecated, using d3d9 hook modules requires " + "d3d8to9 to work! Could not detect loaded d3d9.dll"); + } + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.iidx12_fix_song_select_bg = + config_gfx->happy_sky_ms_bg_fix; + d3d9_config.iidx09_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix; + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + + if (config_gfx->monitor_check == 0) { + log_info("Auto monitor check enabled"); + + d3d9_config.iidx09_to_19_monitor_check_cb = + iidxhook_util_chart_patch_set_refresh_rate; + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); + } else if (config_gfx->monitor_check > 0) { + log_info( + "Manual monitor check, resulting refresh rate: %f", + config_gfx->monitor_check); + + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); + iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); + } + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(_iidxhook1_d3d9_handlers, lengthof(_iidxhook1_d3d9_handlers)); +} + +static bool +_iidxhook1_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_util_config_ezusb_t config_ezusb; + iidxhook_util_config_eamuse_t config_eamuse; + iidxhook_config_gfx_t config_gfx; + iidxhook_config_misc_t config_misc; + iidxhook_config_sec_t config_sec; + + log_info("iidxhook for 9th Style, 10th Style, RED and HAPPY SKY"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_ezusb_get(config, &config_ezusb); + iidxhook_util_config_eamuse_get(config, &config_eamuse); + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_misc_get(config, &config_misc); + iidxhook_util_config_sec_get(config, &config_sec); + + acp_hook_init(); + adapter_hook_init(); + eamuse_hook_init(); + settings_hook_init(); + + /* Round plug security */ + + ezusb_iidx_emu_node_security_plug_set_boot_version( + &config_sec.boot_version); + ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); + ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( + &config_sec.black_plug_mcode); + ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + + /* Magnetic card reader (9th to HS) */ + + ezusb_iidx_emu_node_serial_set_card_attributes( + 0, true, config_eamuse.card_type); + + /* eAmusement server IP */ + + eamuse_set_addr(&config_eamuse.server); + eamuse_check_connection(); + + /* Patch rteffect.dll calls */ + + // TODO this doesn't work, because it's too late to apply this here + // this needs to be launched before bm2dx.exe even loads the rteffect.dll + // and runs DllMain of it (see also how this is done with the proxy + // ezusb.dll) + + // TODO the default should also be off and the config should ask for enabling it + if (config_misc.rteffect_stub) { + effector_hook_init(); + } + + /* Settings paths */ + + if (strlen(config_misc.settings_path) > 0) { + settings_hook_set_path(config_misc.settings_path); + } + + /* Direct3D and USER32 hooks */ + + iidxhook1_setup_d3d9_hooks(&config_gfx); + + /* Disable operator menu clock setting system clock time */ + + // TODO this should be inverted as the default is probably to not want it to be set + if (config_misc.disable_clock_set) { + iidxhook_util_clock_hook_init(); + } + + /* Start up IIDXIO.DLL */ + + log_info("Starting IIDX IO backend"); + + _iidxhook1_io_iidx_init(&_iidxhook1_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + + /* Start up EAMIO.DLL */ + + log_misc("Initializing card reader backend"); + + _iidxhook1_io_eam_init(&_iidxhook1_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + hook_setupapi_init(&ezusb_emu_desc_device.setupapi); + ezusb_emu_device_hook_init( + ezusb_iidx_emu_msg_init(config_ezusb.io_board_type)); + + if (config_ezusb.api_call_monitoring) { + ezusb_log_hook_init(); + ezusb_mon_hook_init(); + } + + return true; +} +static void _iidxhook1_main_fini() +{ + // TODO guard these as they are config driven + ezusb_mon_hook_fini(); + ezusb_log_hook_fini(); + + ezusb_emu_device_hook_fini(); + hook_setupapi_fini(); + + // TODO how to cleanup iohook_push_handler? + + bt_io_eam_fini(); + + _iidxhook1_io_eam_fini(&_iidxhook1_module_io_eam); + + bt_io_iidx_fini(); + + _iidxhook1_io_iidx_fini(&_iidxhook1_module_io_iidx); + + // TODO guard because config driven + iidxhook_util_clock_hook_fini(); + + // TODO how to cleanup hook_d3d9_init? + + // TODO guard because config driven + effector_hook_fini(); + + settings_hook_fini(); + eamuse_hook_fini(); + adapter_hook_fini(); + acp_hook_fini(); +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook1_main_init; + api->v1.main_fini = _iidxhook1_main_fini; +} diff --git a/src/main/iidxhook1/iidxhook1.def b/src/main/iidxhook1/iidxhook1.def index eb7b5ff8..b844b19c 100644 --- a/src/main/iidxhook1/iidxhook1.def +++ b/src/main/iidxhook1/iidxhook1.def @@ -2,4 +2,9 @@ LIBRARY iidxhook1 EXPORTS DllMain@12 @1 NONAME - \ No newline at end of file + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook1/iidxhook1.h b/src/main/iidxhook1/iidxhook1.h new file mode 100644 index 00000000..7edbd433 --- /dev/null +++ b/src/main/iidxhook1/iidxhook1.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK1_H +#define IIDXHOOK1_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook1/log-ezusb.c b/src/main/iidxhook1/log-ezusb.c index ac71907b..9f0b052e 100644 --- a/src/main/iidxhook1/log-ezusb.c +++ b/src/main/iidxhook1/log-ezusb.c @@ -8,10 +8,11 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "iidxhook1/log-ezusb.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" /* ------------------------------------------------------------------------- */ @@ -48,3 +49,11 @@ void ezusb_log_hook_init(void) log_info("Inserted ezusb log hooks"); } + +void ezusb_log_hook_fini() +{ + hook_table_revert( + NULL, "user32.dll", ezusb_log_hook_syms, lengthof(ezusb_log_hook_syms)); + + log_info("Removed ezusb log hooks"); +} \ No newline at end of file diff --git a/src/main/iidxhook1/log-ezusb.h b/src/main/iidxhook1/log-ezusb.h index 1aa5ec6c..565bf73d 100644 --- a/src/main/iidxhook1/log-ezusb.h +++ b/src/main/iidxhook1/log-ezusb.h @@ -7,4 +7,6 @@ */ void ezusb_log_hook_init(void); +void ezusb_log_hook_fini(); + #endif diff --git a/src/main/iidxhook2/Module.mk b/src/main/iidxhook2/Module.mk index c9fd4389..c171df82 100644 --- a/src/main/iidxhook2/Module.mk +++ b/src/main/iidxhook2/Module.mk @@ -3,22 +3,28 @@ avsdlls += iidxhook2 ldflags_iidxhook2 := \ -lws2_32 \ -liphlpapi \ + -lpsapi \ + -lshlwapi \ libs_iidxhook2 := \ + core \ iidxhook-util \ ezusb-emu \ ezusb-iidx-16seg-emu \ ezusb-iidx-emu \ security \ - eamio \ acioemu \ hook \ hooklib \ - iidxio \ - cconfig \ - util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ + mxml \ + sdk-hook \ src_iidxhook2 := \ - config-iidxhook2.c \ dllmain.c \ + iidxhook2.c \ diff --git a/src/main/iidxhook2/config-iidxhook2.c b/src/main/iidxhook2/config-iidxhook2.c deleted file mode 100644 index 6e3ac6bd..00000000 --- a/src/main/iidxhook2/config-iidxhook2.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "cconfig/cconfig-util.h" - -#include "iidxhook2/config-iidxhook2.h" - -#include "util/log.h" - -#define IIDXHOOK_CONFIG_MISC_DISTORTED_MS_BG_FIX_KEY "misc.distorted_ms_bg_fix" - -#define IIDXHOOK_CONFIG_MISC_DEFAULT_DISTORTED_MS_BG_FIX_VALUE false - -void iidxhook_config_iidxhook2_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - IIDXHOOK_CONFIG_MISC_DISTORTED_MS_BG_FIX_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_DISTORTED_MS_BG_FIX_VALUE, - "Fix broken 3D background on DistorteD's music select (if " - "appearing " - "completely black)"); -} - -void iidxhook_config_iidxhook2_get( - struct iidxhook_config_iidxhook2 *config_iidxhook2, struct cconfig *config) -{ - if (!cconfig_util_get_bool( - config, - IIDXHOOK_CONFIG_MISC_DISTORTED_MS_BG_FIX_KEY, - &config_iidxhook2->distorted_ms_bg_fix, - IIDXHOOK_CONFIG_MISC_DEFAULT_DISTORTED_MS_BG_FIX_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK_CONFIG_MISC_DISTORTED_MS_BG_FIX_KEY, - IIDXHOOK_CONFIG_MISC_DEFAULT_DISTORTED_MS_BG_FIX_VALUE); - } -} \ No newline at end of file diff --git a/src/main/iidxhook2/config-iidxhook2.h b/src/main/iidxhook2/config-iidxhook2.h deleted file mode 100644 index 50c85e1b..00000000 --- a/src/main/iidxhook2/config-iidxhook2.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef IIDXHOOK_CONFIG_IIDXHOOK2_H -#define IIDXHOOK_CONFIG_IIDXHOOK2_H - -#include "cconfig/cconfig.h" - -struct iidxhook_config_iidxhook2 { - bool distorted_ms_bg_fix; -}; - -void iidxhook_config_iidxhook2_init(struct cconfig *config); - -void iidxhook_config_iidxhook2_get( - struct iidxhook_config_iidxhook2 *config_iidxhook2, struct cconfig *config); - -#endif \ No newline at end of file diff --git a/src/main/iidxhook2/dllmain.c b/src/main/iidxhook2/dllmain.c index 25a76ed9..4a2b4787 100644 --- a/src/main/iidxhook2/dllmain.c +++ b/src/main/iidxhook2/dllmain.c @@ -1,273 +1,70 @@ #include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-emu/desc.h" -#include "ezusb-emu/device.h" -#include "ezusb-emu/node-security-plug.h" - -#include "ezusb-iidx-emu/msg.h" -#include "ezusb-iidx-emu/node-serial.h" -#include "ezusb-iidx-emu/nodes.h" - -#include "hook/d3d9.h" -#include "hook/iohook.h" #include "hook/table.h" -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-util/acio.h" -#include "iidxhook-util/chart-patch.h" -#include "iidxhook-util/clock.h" -#include "iidxhook-util/config-eamuse.h" -#include "iidxhook-util/config-ezusb.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-misc.h" -#include "iidxhook-util/config-sec.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/eamuse.h" -#include "iidxhook-util/effector.h" -#include "iidxhook-util/settings.h" - -#include "iidxhook2/config-iidxhook2.h" - -#include "util/log.h" -#include "util/thread.h" +#include "iidxhook2/iidxhook2.h" -#define IIDXHOOK2_INFO_HEADER \ - "iidxhook for DistorteD" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK2_CMD_USAGE \ - "Usage: inject.exe iidxhook2.dll [options...]" +#include "main/sdk-hook/dllentry.h" -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_util_d3d9_irp_handler, -}; +#include "util/defs.h" -static HANDLE STDCALL my_OpenProcess(DWORD, BOOL, DWORD); -static HANDLE(STDCALL *real_OpenProcess)(DWORD, BOOL, DWORD); +static HANDLE STDCALL _iidxhook2_dllmain_my_OpenProcess(DWORD, BOOL, DWORD); +static HANDLE(STDCALL *_iidxhook2_dllmain_real_OpenProcess)(DWORD, BOOL, DWORD); -static bool iidxhook_init_check; +static bool _iidxhook2_dllmain_openprocess_call_check; -static const struct hook_symbol init_hook_syms[] = { - {.name = "OpenProcess", - .patch = my_OpenProcess, - .link = (void **) &real_OpenProcess}, +static const struct hook_symbol _iidxhook2_dllmain_hook_syms[] = { + { + .name = "OpenProcess", + .patch = _iidxhook2_dllmain_my_OpenProcess, + .link = (void **) &_iidxhook2_dllmain_real_OpenProcess, + }, }; -static void iidxhook2_setup_d3d9_hooks( - const struct iidxhook_config_gfx *config_gfx, - const struct iidxhook_config_iidxhook2 *config_iidxhook2) +static HANDLE STDCALL +_iidxhook2_dllmain_my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) { - struct iidxhook_util_d3d9_config d3d9_config; - - log_warning( - "d3d8 hook module deprecated, using d3d9 hook modules requiring " - "d3d8to9 to work!"); - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.iidx13_fix_song_select_bg = - config_iidxhook2->distorted_ms_bg_fix; - d3d9_config.iidx09_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix; - d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; - d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; - d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - - if (config_gfx->monitor_check == 0) { - log_info("Auto monitor check enabled"); - - d3d9_config.iidx09_to_19_monitor_check_cb = - iidxhook_util_chart_patch_set_refresh_rate; - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); - } else if (config_gfx->monitor_check > 0) { - log_info( - "Manual monitor check, resulting refresh rate: %f", - config_gfx->monitor_check); - - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); - iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); + if (_iidxhook2_dllmain_openprocess_call_check) { + return _iidxhook2_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); } - iidxhook_util_d3d9_configure(&d3d9_config); - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -/** - * This seems to be a good entry point to intercept - * before the game calls anything important - */ -HANDLE STDCALL -my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) -{ - struct cconfig *config; - - struct iidxhook_util_config_ezusb config_ezusb; - struct iidxhook_util_config_eamuse config_eamuse; - struct iidxhook_config_gfx config_gfx; - struct iidxhook_config_iidxhook2 config_iidxhook2; - struct iidxhook_config_misc config_misc; - struct iidxhook_config_sec config_sec; - - if (iidxhook_init_check) { - goto skip; - } - - iidxhook_init_check = true; - - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook my_OpenProcess ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_util_config_ezusb_init(config); - iidxhook_util_config_eamuse_init(config); - iidxhook_config_gfx_init(config); - iidxhook_config_iidxhook2_init(config); - iidxhook_config_misc_init(config); - iidxhook_config_sec_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK2_INFO_HEADER "\n" IIDXHOOK2_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - iidxhook_util_config_ezusb_get(&config_ezusb, config); - iidxhook_util_config_eamuse_get(&config_eamuse, config); - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_iidxhook2_get(&config_iidxhook2, config); - iidxhook_config_misc_get(&config_misc, config); - iidxhook_config_sec_get(&config_sec, config); - - cconfig_finit(config); - - log_info(IIDXHOOK2_INFO_HEADER); - log_info("Initializing iidxhook..."); + _iidxhook2_dllmain_openprocess_call_check = true; - /* Round plug security */ + bt_hook_dllentry_main_init(); - ezusb_iidx_emu_node_security_plug_set_boot_version( - &config_sec.boot_version); - ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); - ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( - &config_sec.black_plug_mcode); - ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); - - /* eAmusement server IP */ - - eamuse_set_addr(&config_eamuse.server); - eamuse_check_connection(); - - /* Patch rteffect.dll calls */ - - if (config_misc.rteffect_stub) { - effector_hook_init(); - } - - /* Settings paths */ - - if (strlen(config_misc.settings_path) > 0) { - settings_hook_set_path(config_misc.settings_path); - } - - /* Direct3D and USER32 hooks */ - - iidxhook2_setup_d3d9_hooks(&config_gfx, &config_iidxhook2); - - /* Disable operator menu clock setting system clock time */ - - if (config_misc.disable_clock_set) { - iidxhook_util_clock_hook_init(); - } - - /* Start up IIDXIO.DLL */ - - log_info("Starting IIDX IO backend"); - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - - /* Start up EAMIO.DLL */ - - log_misc("Initializing card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); - iohook_push_handler(settings_hook_dispatch_irp); - - hook_setupapi_init(&ezusb_emu_desc_device.setupapi); - ezusb_emu_device_hook_init( - ezusb_iidx_emu_msg_init(config_ezusb.io_board_type)); - - /* Card reader emulation, same issue with hooking as IO emulation */ - rs232_hook_init(); - - iidxhook_util_acio_init(true); - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook my_OpenProcess ----------------"); - log_info("-------------------------------------------------------------"); - -skip: - return real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); + return _iidxhook2_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); } -/** - * Hook library for DistorteD - */ +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() + BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - log_to_writer(log_writer_debug, NULL); + bt_hook_dllentry_init( + mod, + "iidxhook2", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); - /* Bootstrap hook for further init tasks (see above) */ + _iidxhook2_dllmain_openprocess_call_check = false; hook_table_apply( - NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms)); + NULL, "kernel32.dll", _iidxhook2_dllmain_hook_syms, lengthof(_iidxhook2_dllmain_hook_syms)); + + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "kernel32.dll", _iidxhook2_dllmain_hook_syms, lengthof(_iidxhook2_dllmain_hook_syms)); - /* Actual hooks for game specific stuff */ + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); - acp_hook_init(); - adapter_hook_init(); - eamuse_hook_init(); - settings_hook_init(); + bt_hook_dllentry_fini(); + } } return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook2/iidxhook2.c b/src/main/iidxhook2/iidxhook2.c new file mode 100644 index 00000000..56452014 --- /dev/null +++ b/src/main/iidxhook2/iidxhook2.c @@ -0,0 +1,258 @@ +#define LOG_MODULE "iidxhook2" + +#include + +#include +#include +#include + +#include "ezusb-emu/desc.h" +#include "ezusb-emu/device.h" +#include "ezusb-emu/node-security-plug.h" + +#include "ezusb-iidx-emu/msg.h" +#include "ezusb-iidx-emu/node-serial.h" +#include "ezusb-iidx-emu/nodes.h" + +#include "hook/d3d9.h" +#include "hook/iohook.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/chart-patch.h" +#include "iidxhook-util/clock.h" +#include "iidxhook-util/config-eamuse.h" +#include "iidxhook-util/config-ezusb.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-misc.h" +#include "iidxhook-util/config-sec.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/eamuse.h" +#include "iidxhook-util/effector.h" +#include "iidxhook-util/settings.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/proc.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static module_io_t *_iidxhook2_module_io_iidx; +static module_io_t *_iidxhook2_module_io_eam; + +static void _iidxhook2_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook2_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void iidxhook2_setup_d3d9_hooks( + const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + if (!proc_is_module_loaded("d3d9.dll")) { + log_fatal( + "d3d8 hook module deprecated, using d3d9 hook modules requires " + "d3d8to9 to work! Could not detect loaded d3d9.dll"); + } + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.iidx09_to_17_fix_uvs_bg_videos = config_gfx->bgvideo_uv_fix; + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + d3d9_config.iidx13_fix_song_select_bg = config_gfx->distorted_ms_bg_fix; + + if (config_gfx->monitor_check == 0) { + log_info("Auto monitor check enabled"); + + d3d9_config.iidx09_to_19_monitor_check_cb = + iidxhook_util_chart_patch_set_refresh_rate; + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); + } else if (config_gfx->monitor_check > 0) { + log_info( + "Manual monitor check, resulting refresh rate: %f", + config_gfx->monitor_check); + + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_9_TO_13); + iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); + } + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook2_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_util_config_ezusb_t config_ezusb; + iidxhook_util_config_eamuse_t config_eamuse; + iidxhook_config_gfx_t config_gfx; + iidxhook_config_misc_t config_misc; + iidxhook_config_sec_t config_sec; + + log_info("iidxhook for DistorteD"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_ezusb_get(config, &config_ezusb); + iidxhook_util_config_eamuse_get(config, &config_eamuse); + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_misc_get(config, &config_misc); + iidxhook_util_config_sec_get(config, &config_sec); + + acp_hook_init(); + adapter_hook_init(); + eamuse_hook_init(); + settings_hook_init(); + + /* Round plug security */ + + ezusb_iidx_emu_node_security_plug_set_boot_version( + &config_sec.boot_version); + ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); + ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( + &config_sec.black_plug_mcode); + ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + + /* eAmusement server IP */ + + eamuse_set_addr(&config_eamuse.server); + eamuse_check_connection(); + + /* Patch rteffect.dll calls */ + + // TODO this doesn't work, because it's too late to apply this here + // this needs to be launched before bm2dx.exe even loads the rteffect.dll + // and runs DllMain of it (see also how this is done with the proxy + // ezusb.dll) + if (config_misc.rteffect_stub) { + effector_hook_init(); + } + + /* Settings paths */ + + if (strlen(config_misc.settings_path) > 0) { + settings_hook_set_path(config_misc.settings_path); + } + + /* Direct3D and USER32 hooks */ + + iidxhook2_setup_d3d9_hooks(&config_gfx); + + /* Disable operator menu clock setting system clock time */ + + if (config_misc.disable_clock_set) { + iidxhook_util_clock_hook_init(); + } + + /* Start up IIDXIO.DLL */ + + log_info("Starting IIDX IO backend"); + + _iidxhook2_io_iidx_init(&_iidxhook2_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + + /* Start up EAMIO.DLL */ + + log_misc("Initializing card reader backend"); + + _iidxhook2_io_eam_init(&_iidxhook2_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + hook_setupapi_init(&ezusb_emu_desc_device.setupapi); + ezusb_emu_device_hook_init( + ezusb_iidx_emu_msg_init(config_ezusb.io_board_type)); + + /* Card reader emulation, same issue with hooking as IO emulation */ + rs232_hook_init(); + + iidxhook_util_acio_init(true); + + return true; +} + +static void _iidxhook2_main_fini() +{ + // TODO cleanup +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook2_main_init; + api->v1.main_fini = _iidxhook2_main_fini; +} \ No newline at end of file diff --git a/src/main/iidxhook2/iidxhook2.def b/src/main/iidxhook2/iidxhook2.def index 76b59eca..df59a813 100644 --- a/src/main/iidxhook2/iidxhook2.def +++ b/src/main/iidxhook2/iidxhook2.def @@ -2,4 +2,9 @@ LIBRARY iidxhook2 EXPORTS DllMain@12 @1 NONAME - \ No newline at end of file + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook2/iidxhook2.h b/src/main/iidxhook2/iidxhook2.h new file mode 100644 index 00000000..7f3a5abf --- /dev/null +++ b/src/main/iidxhook2/iidxhook2.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK2_H +#define IIDXHOOK2_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook3/Module.mk b/src/main/iidxhook3/Module.mk index a575a13b..f9277ef1 100644 --- a/src/main/iidxhook3/Module.mk +++ b/src/main/iidxhook3/Module.mk @@ -3,11 +3,13 @@ avsdlls += iidxhook3 ldflags_iidxhook3 := \ -lws2_32 \ -liphlpapi \ + -lshlwapi \ deplibs_iidxhook3 := \ avs \ libs_iidxhook3 := \ + core \ iidxhook-util \ ezusb-emu \ ezusb-iidx-16seg-emu \ @@ -16,14 +18,18 @@ libs_iidxhook3 := \ ezusb-iidx-emu \ security \ acioemu \ - eamio \ hook \ hooklib \ - iidxio \ - cconfig \ - util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ + mxml \ + sdk-hook \ src_iidxhook3 := \ avs-boot.c \ dllmain.c \ + iidxhook3.c \ diff --git a/src/main/iidxhook3/avs-boot.c b/src/main/iidxhook3/avs-boot.c index 196439fe..77ab800e 100644 --- a/src/main/iidxhook3/avs-boot.c +++ b/src/main/iidxhook3/avs-boot.c @@ -3,14 +3,16 @@ #include #include +#include "core/log-bt.h" + #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "iidxhook3/avs-boot.h" -#include "util/log.h" - static void (*real_avs_boot)( struct property_node *config, void *std_heap, @@ -50,6 +52,11 @@ static const struct hook_symbol iidxhook3_ea3_hook_syms[] = { .link = (void **) &real_ea3_boot}, }; +static AVS_LOG_WRITER(_avs_boot_log_writer, chars, nchars, ctx) +{ + core_log_bt_direct_sink_write(chars, nchars); +} + static void avs_boot_replace_property_uint32( struct property_node *node, const char *name, uint32_t val) { @@ -103,7 +110,7 @@ static void my_avs_boot( sz_std_heap, avs_heap, sz_avs_heap, - log_writer_debug, + _avs_boot_log_writer, NULL); } diff --git a/src/main/iidxhook3/dllmain.c b/src/main/iidxhook3/dllmain.c index 49882b85..811f8f19 100644 --- a/src/main/iidxhook3/dllmain.c +++ b/src/main/iidxhook3/dllmain.c @@ -1,265 +1,70 @@ #include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-emu/node-security-plug.h" -#include "ezusb-iidx-emu/node-serial.h" -#include "ezusb-iidx-emu/nodes.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "ezusb2-iidx-emu/msg.h" - -#include "hook/d3d9.h" -#include "hook/iohook.h" #include "hook/table.h" -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" +#include "iidxhook3/iidxhook3.h" -#include "iidxhook3/avs-boot.h" +#include "main/sdk-hook/dllentry.h" -#include "iidxhook-util/acio.h" -#include "iidxhook-util/chart-patch.h" -#include "iidxhook-util/clock.h" -#include "iidxhook-util/config-eamuse.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-misc.h" -#include "iidxhook-util/config-sec.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/settings.h" +#include "util/defs.h" -#include "security/rp-sign-key.h" +static HANDLE STDCALL _iidxhook3_dllmain_my_OpenProcess(DWORD, BOOL, DWORD); +static HANDLE(STDCALL *_iidxhook3_dllmain_real_OpenProcess)(DWORD, BOOL, DWORD); -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" +static bool _iidxhook3_dllmain_openprocess_call_check; -#define IIDXHOOK3_INFO_HEADER \ - "iidxhook for Gold, DJTroopers, Empress and Sirius" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK3_CMD_USAGE \ - "Usage: inject.exe iidxhook3.dll [options...]" - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_util_d3d9_irp_handler, +static const struct hook_symbol _iidxhook3_dllmain_hook_syms[] = { + { + .name = "OpenProcess", + .patch = _iidxhook3_dllmain_my_OpenProcess, + .link = (void **) &_iidxhook3_dllmain_real_OpenProcess, + }, }; -static HANDLE STDCALL my_OpenProcess(DWORD, BOOL, DWORD); -static HANDLE(STDCALL *real_OpenProcess)(DWORD, BOOL, DWORD); -static bool iidxhook_init_check; - -static const struct hook_symbol init_hook_syms[] = { - {.name = "OpenProcess", - .patch = my_OpenProcess, - .link = (void **) &real_OpenProcess}, -}; - -static void -iidxhook3_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - - /* Required for GOLD (and newer?) to not crash with NVIDIA cards */ - d3d9_config.iidx09_to_17_fix_uvs_bg_videos = true; - d3d9_config.iidx14_to_19_nvidia_fix = true; - - d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; - d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; - d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - - if (config_gfx->monitor_check == 0) { - log_info("Auto monitor check enabled"); - - d3d9_config.iidx09_to_19_monitor_check_cb = - iidxhook_util_chart_patch_set_refresh_rate; - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - } else if (config_gfx->monitor_check > 0) { - log_info( - "Manual monitor check, resulting refresh rate: %f", - config_gfx->monitor_check); - - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); - } - - iidxhook_util_d3d9_configure(&d3d9_config); - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -/** - * This seems to be a good entry point to intercept - * before the game calls anything important - */ -HANDLE STDCALL -my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) +static HANDLE STDCALL +_iidxhook3_dllmain_my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) { - struct cconfig *config; - - struct iidxhook_util_config_eamuse config_eamuse; - struct iidxhook_config_gfx config_gfx; - struct iidxhook_config_misc config_misc; - struct iidxhook_config_sec config_sec; - - if (iidxhook_init_check) { - goto skip; + if (_iidxhook3_dllmain_openprocess_call_check) { + return _iidxhook3_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); } - iidxhook_init_check = true; - - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook my_OpenProcess ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_util_config_eamuse_init(config); - iidxhook_config_gfx_init(config); - iidxhook_config_misc_init(config); - iidxhook_config_sec_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK3_INFO_HEADER "\n" IIDXHOOK3_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } + _iidxhook3_dllmain_openprocess_call_check = true; - iidxhook_util_config_eamuse_get(&config_eamuse, config); - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_misc_get(&config_misc, config); - iidxhook_config_sec_get(&config_sec, config); + bt_hook_dllentry_main_init(); - cconfig_finit(config); - - log_info(IIDXHOOK3_INFO_HEADER); - log_info("Initializing iidxhook..."); - - /* Round plug security */ - - ezusb_iidx_emu_node_security_plug_set_boot_version( - &config_sec.boot_version); - ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); - ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( - &security_rp_sign_key_black_iidx); - ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key( - &security_rp_sign_key_white_eamuse); - ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( - &config_sec.black_plug_mcode); - ezusb_iidx_emu_node_security_plug_set_plug_white_mcode( - &security_mcode_eamuse); - ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); - ezusb_iidx_emu_node_security_plug_set_eamid(&config_eamuse.eamid); - - iidxhook3_avs_boot_init(); - iidxhook3_avs_boot_set_eamuse_addr(&config_eamuse.server); - - /* Settings paths */ - - if (strlen(config_misc.settings_path) > 0) { - settings_hook_set_path(config_misc.settings_path); - } - - /* Direct3D and USER32 hooks */ - - iidxhook3_setup_d3d9_hooks(&config_gfx); - - /* Disable operator menu clock setting system clock time */ - - if (config_misc.disable_clock_set) { - iidxhook_util_clock_hook_init(); - } - - /* Start up IIDXIO.DLL */ - - log_info("Starting IIDX IO backend"); - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - - /* Start up EAMIO.DLL */ - - log_misc("Initializing card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); - iohook_push_handler(settings_hook_dispatch_irp); - - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); - - /* Card reader emulation, same issue with hooking as IO emulation */ - rs232_hook_init(); - - iidxhook_util_acio_init(true); - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook my_OpenProcess ----------------"); - log_info("-------------------------------------------------------------"); - -skip: - return real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); + return _iidxhook3_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); } -/** - * Hook library for Gold to Sirius - */ +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() + BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - log_to_writer(log_writer_debug, NULL); + bt_hook_dllentry_init( + mod, + "iidxhook3", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); - /* Bootstrap hook for further init tasks (see above) */ + _iidxhook3_dllmain_openprocess_call_check = false; hook_table_apply( - NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms)); + NULL, "kernel32.dll", _iidxhook3_dllmain_hook_syms, lengthof(_iidxhook3_dllmain_hook_syms)); + + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "kernel32.dll", _iidxhook3_dllmain_hook_syms, lengthof(_iidxhook3_dllmain_hook_syms)); - /* Actual hooks for game specific stuff */ - /* Some hooks are setting dependent and can only be applied later in - the bootstrap hook */ + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); - acp_hook_init(); - adapter_hook_init(); - settings_hook_init(); + bt_hook_dllentry_fini(); + } } return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook3/iidxhook3.c b/src/main/iidxhook3/iidxhook3.c new file mode 100644 index 00000000..50898c50 --- /dev/null +++ b/src/main/iidxhook3/iidxhook3.c @@ -0,0 +1,249 @@ +#define LOG_MODULE "iidxhook3" + +#include + +#include +#include +#include + +#include "ezusb-emu/node-security-plug.h" +#include "ezusb-iidx-emu/nodes.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/d3d9.h" +#include "hook/iohook.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook3/avs-boot.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/chart-patch.h" +#include "iidxhook-util/clock.h" +#include "iidxhook-util/config-eamuse.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-misc.h" +#include "iidxhook-util/config-sec.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/settings.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "security/rp-sign-key.h" + +#include "util/str.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static module_io_t *_iidxhook3_module_io_iidx; +static module_io_t *_iidxhook3_module_io_eam; + +static void _iidxhook3_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook3_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void iidxhook3_setup_d3d9_hooks( + const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + + /* Required for GOLD (and newer?) to not crash with NVIDIA cards */ + d3d9_config.iidx09_to_17_fix_uvs_bg_videos = true; + d3d9_config.iidx14_to_19_nvidia_fix = true; + + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + + if (config_gfx->monitor_check == 0) { + log_info("Auto monitor check enabled"); + + d3d9_config.iidx09_to_19_monitor_check_cb = + iidxhook_util_chart_patch_set_refresh_rate; + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + } else if (config_gfx->monitor_check > 0) { + log_info( + "Manual monitor check, resulting refresh rate: %f", + config_gfx->monitor_check); + + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); + } + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook3_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_util_config_eamuse_t config_eamuse; + iidxhook_config_gfx_t config_gfx; + iidxhook_config_misc_t config_misc; + iidxhook_config_sec_t config_sec; + + log_info("iidxhook for Gold, DJTroopers, Empress and Sirius"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_eamuse_get(config, &config_eamuse); + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_misc_get(config, &config_misc); + iidxhook_util_config_sec_get(config, &config_sec); + + acp_hook_init(); + adapter_hook_init(); + settings_hook_init(); + + /* Round plug security */ + + ezusb_iidx_emu_node_security_plug_set_boot_version( + &config_sec.boot_version); + ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); + ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( + &security_rp_sign_key_black_iidx); + ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key( + &security_rp_sign_key_white_eamuse); + ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( + &config_sec.black_plug_mcode); + ezusb_iidx_emu_node_security_plug_set_plug_white_mcode( + &security_mcode_eamuse); + ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + ezusb_iidx_emu_node_security_plug_set_eamid(&config_eamuse.eamid); + + iidxhook3_avs_boot_init(); + iidxhook3_avs_boot_set_eamuse_addr(&config_eamuse.server); + + /* Settings paths */ + + if (strlen(config_misc.settings_path) > 0) { + settings_hook_set_path(config_misc.settings_path); + } + + /* Direct3D and USER32 hooks */ + + iidxhook3_setup_d3d9_hooks(&config_gfx); + + /* Disable operator menu clock setting system clock time */ + + if (config_misc.disable_clock_set) { + iidxhook_util_clock_hook_init(); + } + + /* Start up IIDXIO.DLL */ + + log_info("Starting IIDX IO backend"); + + _iidxhook3_io_iidx_init(&_iidxhook3_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + + /* Start up EAMIO.DLL */ + + log_misc("Initializing card reader backend"); + + _iidxhook3_io_eam_init(&_iidxhook3_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + + /* Card reader emulation, same issue with hooking as IO emulation */ + rs232_hook_init(); + + iidxhook_util_acio_init(true); + + return true; +} + +static void _iidxhook3_main_fini() +{ + // TODO cleanup +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook3_main_init; + api->v1.main_fini = _iidxhook3_main_fini; +} \ No newline at end of file diff --git a/src/main/iidxhook3/iidxhook3.def b/src/main/iidxhook3/iidxhook3.def index f687ba1b..d25148d3 100644 --- a/src/main/iidxhook3/iidxhook3.def +++ b/src/main/iidxhook3/iidxhook3.def @@ -2,4 +2,9 @@ LIBRARY iidxhook3 EXPORTS DllMain@12 @1 NONAME - \ No newline at end of file + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook3/iidxhook3.h b/src/main/iidxhook3/iidxhook3.h new file mode 100644 index 00000000..51249acd --- /dev/null +++ b/src/main/iidxhook3/iidxhook3.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK3_H +#define IIDXHOOK3_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook4-cn/Module.mk b/src/main/iidxhook4-cn/Module.mk index 0f7bceea..6ec4e48e 100644 --- a/src/main/iidxhook4-cn/Module.mk +++ b/src/main/iidxhook4-cn/Module.mk @@ -3,11 +3,16 @@ avsdlls += iidxhook4-cn ldflags_iidxhook4-cn := \ -liphlpapi \ -lws2_32 \ + -lshlwapi \ deplibs_iidxhook4-cn := \ avs \ +avslibs_iidxhook4-cn := \ + avs-ext \ + libs_iidxhook4-cn := \ + core \ iidxhook-util \ ezusb-emu \ ezusb-iidx-16seg-emu \ @@ -16,12 +21,18 @@ libs_iidxhook4-cn := \ security \ hook \ hooklib \ - iidxio \ - cconfig \ util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ + mxml \ + sdk-hook \ src_iidxhook4-cn := \ avs-boot.c \ - path.c \ dllmain.c \ + iidxhook4-cn.c \ + path.c \ diff --git a/src/main/iidxhook4-cn/avs-boot.c b/src/main/iidxhook4-cn/avs-boot.c index 378d80cf..be94783f 100644 --- a/src/main/iidxhook4-cn/avs-boot.c +++ b/src/main/iidxhook4-cn/avs-boot.c @@ -3,14 +3,16 @@ #include #include +#include "core/log-bt.h" + #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "iidxhook4-cn/avs-boot.h" -#include "util/log.h" - static void (*real_avs_boot)( struct property_node *config, void *std_heap, @@ -35,6 +37,11 @@ static const struct hook_symbol iidxhook4_cn_log_hook_syms[] = { .link = (void **) &real_avs_boot}, }; +static AVS_LOG_WRITER(_avs_boot_log_writer, chars, nchars, ctx) +{ + core_log_bt_direct_sink_write(chars, nchars); +} + static void avs_boot_replace_property_uint32( struct property_node *node, const char *name, uint32_t val) { @@ -87,7 +94,7 @@ static void my_avs_boot( sz_std_heap, avs_heap, sz_avs_heap, - log_writer_debug, + _avs_boot_log_writer, NULL); } diff --git a/src/main/iidxhook4-cn/dllmain.c b/src/main/iidxhook4-cn/dllmain.c index ea2f42ab..e824e943 100644 --- a/src/main/iidxhook4-cn/dllmain.c +++ b/src/main/iidxhook4-cn/dllmain.c @@ -1,235 +1,70 @@ #include -#include -#include -#include -#include - -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-emu/node-security-plug.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "ezusb2-iidx-emu/msg.h" - #include "hook/table.h" -#include "hooklib/acp.h" -#include "hooklib/setupapi.h" - -#include "iidxhook4-cn/avs-boot.h" -#include "iidxhook4-cn/path.h" - -#include "iidxhook-util/chart-patch.h" -#include "iidxhook-util/config-eamuse.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-io.h" -#include "iidxhook-util/config-misc.h" -#include "iidxhook-util/config-sec.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/settings.h" - -#include "security/rp-sign-key.h" - -#include "imports/avs.h" +#include "iidxhook4-cn/iidxhook4-cn.h" -#include "util/log.h" +#include "main/sdk-hook/dllentry.h" -#define IIDXHOOK4_CN_INFO_HEADER \ - "iidxhook for Resort Anthem CN" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK4_CN_CMD_USAGE \ - "Usage: inject.exe iidxhook4-cn.dll [options...]" +#include "util/defs.h" -static HANDLE STDCALL my_OpenProcess(DWORD, BOOL, DWORD); -static HANDLE(STDCALL *real_OpenProcess)(DWORD, BOOL, DWORD); -static bool iidxhook_init_check; +static HANDLE STDCALL _iidxhook4_cn_dllmain_my_OpenProcess(DWORD, BOOL, DWORD); +static HANDLE(STDCALL *_iidxhook4_cn_dllmain_real_OpenProcess)(DWORD, BOOL, DWORD); -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_util_d3d9_irp_handler, -}; +static bool _iidxhook4_cn_dllmain_openprocess_call_check; -static const struct hook_symbol init_hook_syms[] = { - {.name = "OpenProcess", - .patch = my_OpenProcess, - .link = (void **) &real_OpenProcess}, +static const struct hook_symbol _iidxhook4_cn_dllmain_hook_syms[] = { + { + .name = "OpenProcess", + .patch = _iidxhook4_cn_dllmain_my_OpenProcess, + .link = (void **) &_iidxhook4_cn_dllmain_real_OpenProcess, + }, }; -static struct iidxhook_config_io config_io; - -static void -iidxhook4_cn_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; - d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; - d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - d3d9_config.iidx18_and_19_diagonal_tearing_fix = - config_gfx->diagonal_tearing_fix; - d3d9_config.iidx14_to_19_nvidia_fix = true; - d3d9_config.iidx18_and_19_diagonal_tearing_fix = - config_gfx->diagonal_tearing_fix; - - if (config_gfx->monitor_check == 0) { - log_info("Auto monitor check enabled"); - - d3d9_config.iidx09_to_19_monitor_check_cb = - iidxhook_util_chart_patch_set_refresh_rate; - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - } else if (config_gfx->monitor_check > 0) { - log_info( - "Manual monitor check, resulting refresh rate: %f", - config_gfx->monitor_check); - - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); - } - - iidxhook_util_d3d9_configure(&d3d9_config); - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -/** - * This seems to be a good entry point to intercept - * before the game calls anything important - */ static HANDLE STDCALL -my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) +_iidxhook4_cn_dllmain_my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) { - struct cconfig *config; - - struct iidxhook_util_config_eamuse config_eamuse; - struct iidxhook_config_gfx config_gfx; - struct iidxhook_config_sec config_sec; - struct iidxhook_config_misc config_misc; - - if (iidxhook_init_check) { - return real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); + if (_iidxhook4_cn_dllmain_openprocess_call_check) { + return _iidxhook4_cn_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); } - iidxhook_init_check = true; + _iidxhook4_cn_dllmain_openprocess_call_check = true; - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook my_OpenProcess ---------------"); - log_info("-------------------------------------------------------------"); + bt_hook_dllentry_main_init(); - config = cconfig_init(); - - iidxhook_util_config_eamuse_init(config); - iidxhook_config_gfx_init(config); - iidxhook_config_io_init(config); - iidxhook_config_sec_init(config); - iidxhook_config_misc_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK4_CN_INFO_HEADER "\n" IIDXHOOK4_CN_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - iidxhook_util_config_eamuse_get(&config_eamuse, config); - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_io_get(&config_io, config); - iidxhook_config_sec_get(&config_sec, config); - iidxhook_config_misc_get(&config_misc, config); - - cconfig_finit(config); - - log_info(IIDXHOOK4_CN_INFO_HEADER); - log_info("Initializing iidxhook..."); - - /** - * This game is using a black round plug for game license management instead - * of a black usb dongle. No white dongle hooks applies since the game does - * not have network functionality. Also, card readers are not used/checked; - * no card reader hooks required. - */ - ezusb_iidx_emu_node_security_plug_set_boot_version( - &config_sec.boot_version); - ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); - ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( - &security_rp_sign_key_black_iidx); - ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( - &config_sec.black_plug_mcode); - ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); - - iidxhook4_cn_setup_d3d9_hooks(&config_gfx); - - if (strlen(config_misc.settings_path) > 0) { - settings_hook_set_path(config_misc.settings_path); - } - - if (!config_io.disable_io_emu) { - log_info("Starting IIDX IO backend"); + return _iidxhook4_cn_dllmain_real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); +} - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } else { - log_info("IIDX IO emulation backend disabled"); - } +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ + if (reason == DLL_PROCESS_ATTACH) { + bt_hook_dllentry_init( + mod, + "iidxhook4-cn", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); - iohook_push_handler(settings_hook_dispatch_irp); + _iidxhook4_cn_dllmain_openprocess_call_check = false; - if (!config_io.disable_io_emu) { - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); - } + hook_table_apply( + NULL, "kernel32.dll", _iidxhook4_cn_dllmain_hook_syms, lengthof(_iidxhook4_cn_dllmain_hook_syms)); - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook my_OpenProcess ----------------"); - log_info("-------------------------------------------------------------"); + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "kernel32.dll", _iidxhook4_cn_dllmain_hook_syms, lengthof(_iidxhook4_cn_dllmain_hook_syms)); - return real_OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); -} + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); -/** - * Hook library for Resort Anthem CN - */ -BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) -{ - if (reason != DLL_PROCESS_ATTACH) { - return TRUE; + bt_hook_dllentry_fini(); + } } - log_to_writer(log_writer_debug, NULL); - - hook_table_apply( - NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms)); - - iidxhook4_cn_path_init(); - iidxhook4_cn_avs_boot_init(); - acp_hook_init(); - settings_hook_init(); - return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook4-cn/iidxhook4-cn.c b/src/main/iidxhook4-cn/iidxhook4-cn.c new file mode 100644 index 00000000..8e09b7b0 --- /dev/null +++ b/src/main/iidxhook4-cn/iidxhook4-cn.c @@ -0,0 +1,209 @@ +#define LOG_MODULE "iidxhook4-cn" + +#include + +#include +#include +#include +#include + +#include "ezusb-emu/node-security-plug.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/table.h" + +#include "hooklib/acp.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/iidx.h" + +#include "iidxhook4-cn/avs-boot.h" +#include "iidxhook4-cn/path.h" + +#include "iidxhook-util/chart-patch.h" +#include "iidxhook-util/config-eamuse.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-io.h" +#include "iidxhook-util/config-misc.h" +#include "iidxhook-util/config-sec.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/settings.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "security/rp-sign-key.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static module_io_t *iidxhook_module_io_iidx; + +static void _iidxhook4_cn_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void +iidxhook4_cn_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + d3d9_config.iidx18_and_19_diagonal_tearing_fix = + config_gfx->diagonal_tearing_fix; + d3d9_config.iidx14_to_19_nvidia_fix = true; + d3d9_config.iidx18_and_19_diagonal_tearing_fix = + config_gfx->diagonal_tearing_fix; + + if (config_gfx->monitor_check == 0) { + log_info("Auto monitor check enabled"); + + d3d9_config.iidx09_to_19_monitor_check_cb = + iidxhook_util_chart_patch_set_refresh_rate; + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + } else if (config_gfx->monitor_check > 0) { + log_info( + "Manual monitor check, resulting refresh rate: %f", + config_gfx->monitor_check); + + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); + } + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook4_cn_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_util_config_eamuse_t config_eamuse; + iidxhook_config_gfx_t config_gfx; + iidxhook_config_sec_t config_sec; + iidxhook_config_misc_t config_misc; + iidxhook_config_io_t config_io; + + log_info("iidxhook for Resort Anthem CN"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_eamuse_get(config, &config_eamuse); + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_sec_get(config, &config_sec); + iidxhook_util_config_misc_get(config, &config_misc); + iidxhook_util_config_io_get(config, &config_io); + + iidxhook4_cn_path_init(); + iidxhook4_cn_avs_boot_init(); + acp_hook_init(); + settings_hook_init(); + + /** + * This game is using a black round plug for game license management instead + * of a black usb dongle. No white dongle hooks applies since the game does + * not have network functionality. Also, card readers are not used/checked; + * no card reader hooks required. + */ + ezusb_iidx_emu_node_security_plug_set_boot_version( + &config_sec.boot_version); + ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); + ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( + &security_rp_sign_key_black_iidx); + ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( + &config_sec.black_plug_mcode); + ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + + iidxhook4_cn_setup_d3d9_hooks(&config_gfx); + + if (strlen(config_misc.settings_path) > 0) { + settings_hook_set_path(config_misc.settings_path); + } + + if (!config_io.disable_io_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook4_cn_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } else { + log_info("IIDX IO emulation backend disabled"); + } + + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + if (!config_io.disable_io_emu) { + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + } + + return true; +} + +static void _iidxhook4_cn_main_fini() +{ + // TODO cleanup initialized stuff +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook4_cn_main_init; + api->v1.main_fini = _iidxhook4_cn_main_fini; +} diff --git a/src/main/iidxhook4-cn/iidxhook4-cn.def b/src/main/iidxhook4-cn/iidxhook4-cn.def index 55cc115d..fa45dd2b 100644 --- a/src/main/iidxhook4-cn/iidxhook4-cn.def +++ b/src/main/iidxhook4-cn/iidxhook4-cn.def @@ -2,3 +2,9 @@ LIBRARY iidxhook4-cn EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook4-cn/iidxhook4-cn.h b/src/main/iidxhook4-cn/iidxhook4-cn.h new file mode 100644 index 00000000..6f58004e --- /dev/null +++ b/src/main/iidxhook4-cn/iidxhook4-cn.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK4_CN_H +#define IIDXHOOK4_CN_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook4-cn/path.c b/src/main/iidxhook4-cn/path.c index 4ab6c5a3..c9bf4746 100644 --- a/src/main/iidxhook4-cn/path.c +++ b/src/main/iidxhook4-cn/path.c @@ -6,9 +6,10 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "iidxhook4-cn/path.h" -#include "util/log.h" #include "util/str.h" #define PATH_A "D:/JDZ-001/contents/" diff --git a/src/main/iidxhook4/Module.mk b/src/main/iidxhook4/Module.mk index 40f40b02..23e9cd97 100644 --- a/src/main/iidxhook4/Module.mk +++ b/src/main/iidxhook4/Module.mk @@ -6,7 +6,11 @@ ldflags_iidxhook4 := \ deplibs_iidxhook4 := \ avs \ +avslibs_iidxhook4 := \ + avs-ext \ + libs_iidxhook4 := \ + core \ iidxhook-util \ ezusb-emu \ ezusb-iidx-16seg-emu \ @@ -14,14 +18,17 @@ libs_iidxhook4 := \ ezusb2-iidx-emu \ ezusb-iidx-emu \ security \ - eamio \ acioemu \ hook \ hooklib \ - iidxio \ - cconfig \ - util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ + mxml \ src_iidxhook4 := \ dllmain.c \ + iidxhook4.c \ diff --git a/src/main/iidxhook4/dllmain.c b/src/main/iidxhook4/dllmain.c index d7993dd7..f8f6588d 100644 --- a/src/main/iidxhook4/dllmain.c +++ b/src/main/iidxhook4/dllmain.c @@ -1,241 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-iidx-emu/nodes.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "ezusb2-iidx-emu/msg.h" - -#include "hook/d3d9.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-util/acio.h" -#include "iidxhook-util/chart-patch.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-io.h" -#include "iidxhook-util/config-misc.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/log-server.h" -#include "iidxhook-util/settings.h" - -#include "imports/avs.h" - -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#define IIDXHOOK4_INFO_HEADER \ - "iidxhook for Resort Anthem" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK4_CMD_USAGE \ - "Usage: launcher.exe -K iidxhook4.dll [options...]" - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_util_d3d9_irp_handler, -}; - -static struct iidxhook_config_io config_io; - -static void -iidxhook4_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; - d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; - d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - d3d9_config.iidx14_to_19_nvidia_fix = true; - d3d9_config.iidx18_and_19_diagonal_tearing_fix = - config_gfx->diagonal_tearing_fix; - - if (config_gfx->monitor_check == 0) { - log_info("Auto monitor check enabled"); - - d3d9_config.iidx09_to_19_monitor_check_cb = - iidxhook_util_chart_patch_set_refresh_rate; - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - } else if (config_gfx->monitor_check > 0) { - log_info( - "Manual monitor check, resulting refresh rate: %f", - config_gfx->monitor_check); - - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); - } - - iidxhook_util_d3d9_configure(&d3d9_config); - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - struct cconfig *config; - - struct iidxhook_config_gfx config_gfx; - struct iidxhook_config_misc config_misc; - - log_server_init(); - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook dll_entry_init ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - iidxhook_config_io_init(config); - iidxhook_config_misc_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK4_INFO_HEADER "\n" IIDXHOOK4_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - log_server_fini(); - exit(EXIT_FAILURE); - } - - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_io_get(&config_io, config); - iidxhook_config_misc_get(&config_misc, config); - - cconfig_finit(config); - - log_info(IIDXHOOK4_INFO_HEADER); - log_info("Initializing iidxhook..."); - - iidxhook4_setup_d3d9_hooks(&config_gfx); - - if (strlen(config_misc.settings_path) > 0) { - settings_hook_set_path(config_misc.settings_path); - } - - if (!config_io.disable_io_emu) { - log_info("Starting IIDX IO backend"); - - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } else { - log_info("IIDX IO emulation backend disabled"); - } - - if (!config_io.disable_card_reader_emu) { - log_misc("Initializing card reader backend"); - - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - } else { - log_info("Card reader emulation backend disabled"); - } - - /* iohooks are okay, even if emu is diabled since the fake handlers won't be - * used */ - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); - iohook_push_handler(settings_hook_dispatch_irp); - - if (!config_io.disable_io_emu) { - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); - } - - /* Card reader emulation, same issue with hooking as IO emulation */ - rs232_hook_init(); - - if (!config_io.disable_card_reader_emu) { - iidxhook_util_acio_init(true); - } - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook dll_entry_init ----------------"); - log_info("-------------------------------------------------------------"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - iidxhook_util_chart_patch_fini(); - - if (!config_io.disable_card_reader_emu) { - log_misc("Shutting down card reader backend"); - eam_io_fini(); - } - - if (!config_io.disable_io_emu) { - log_misc("Shutting down IIDX IO backend"); - iidx_io_fini(); - } - - log_server_fini(); - - return result; -} - -/** - * Hook library for Resort Anthem - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - acp_hook_init(); - adapter_hook_init(); - settings_hook_init(); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook4/iidxhook4.c b/src/main/iidxhook4/iidxhook4.c new file mode 100644 index 00000000..a6e19d24 --- /dev/null +++ b/src/main/iidxhook4/iidxhook4.c @@ -0,0 +1,235 @@ +#define LOG_MODULE "iidxhook4" + +#include + +#include +#include +#include +#include + +#include "ezusb-iidx-emu/nodes.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/d3d9.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/chart-patch.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-io.h" +#include "iidxhook-util/config-misc.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/settings.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/str.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static struct iidxhook_config_io config_io; +static module_io_t *iidxhook_module_io_iidx; +static module_io_t *iidxhook_module_io_eam; + +static void _iidxhook4_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook4_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void +iidxhook4_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + d3d9_config.iidx14_to_19_nvidia_fix = true; + d3d9_config.iidx18_and_19_diagonal_tearing_fix = + config_gfx->diagonal_tearing_fix; + + if (config_gfx->monitor_check == 0) { + log_info("Auto monitor check enabled"); + + d3d9_config.iidx09_to_19_monitor_check_cb = + iidxhook_util_chart_patch_set_refresh_rate; + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + } else if (config_gfx->monitor_check > 0) { + log_info( + "Manual monitor check, resulting refresh rate: %f", + config_gfx->monitor_check); + + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); + } + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook4_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_config_gfx_t config_gfx; + iidxhook_config_misc_t config_misc; + iidxhook_config_io_t config_io; + + log_info("iidxhook for Resort Anthem"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_misc_get(config, &config_misc); + iidxhook_util_config_io_get(config, &config_io); + + acp_hook_init(); + adapter_hook_init(); + settings_hook_init(); + + iidxhook4_setup_d3d9_hooks(&config_gfx); + + if (strlen(config_misc.settings_path) > 0) { + settings_hook_set_path(config_misc.settings_path); + } + + if (!config_io.disable_io_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook4_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } else { + log_info("IIDX IO emulation backend disabled"); + } + + if (!config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + _iidxhook4_io_eam_init(&iidxhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + } else { + log_info("Card reader emulation backend disabled"); + } + + /* iohooks are okay, even if emu is diabled since the fake handlers won't be + * used */ + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + if (!config_io.disable_io_emu) { + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + } + + /* Card reader emulation, same issue with hooking as IO emulation */ + rs232_hook_init(); + + if (!config_io.disable_card_reader_emu) { + iidxhook_util_acio_init(true); + } + + return true; +} + +static void _iidxhook4_main_fini() +{ + iidxhook_util_chart_patch_fini(); + + if (!config_io.disable_card_reader_emu) { + log_misc("Shutting down card reader backend"); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&iidxhook_module_io_eam); + } + + if (!config_io.disable_io_emu) { + log_misc("Shutting down IIDX IO backend"); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&iidxhook_module_io_iidx); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook4_main_init; + api->v1.main_fini = _iidxhook4_main_fini; +} \ No newline at end of file diff --git a/src/main/iidxhook4/iidxhook4.def b/src/main/iidxhook4/iidxhook4.def index f4b03bde..5632a86b 100644 --- a/src/main/iidxhook4/iidxhook4.def +++ b/src/main/iidxhook4/iidxhook4.def @@ -2,4 +2,9 @@ LIBRARY iidxhook4 EXPORTS DllMain@12 @1 NONAME - \ No newline at end of file + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook4/iidxhook4.h b/src/main/iidxhook4/iidxhook4.h new file mode 100644 index 00000000..a6ea7c72 --- /dev/null +++ b/src/main/iidxhook4/iidxhook4.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK4_H +#define IIDXHOOK4_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook5-cn/Module.mk b/src/main/iidxhook5-cn/Module.mk index feea3d48..ef1544fd 100644 --- a/src/main/iidxhook5-cn/Module.mk +++ b/src/main/iidxhook5-cn/Module.mk @@ -3,11 +3,16 @@ avsdlls += iidxhook5-cn ldflags_iidxhook5-cn := \ -liphlpapi \ -lws2_32 \ + -lshlwapi \ deplibs_iidxhook5-cn := \ avs \ +avslibs_iidxhook5-cn := \ + avs-ext \ + libs_iidxhook5-cn := \ + core \ iidxhook-util \ ezusb-emu \ ezusb-iidx-16seg-emu \ @@ -16,12 +21,17 @@ libs_iidxhook5-cn := \ security \ hook \ hooklib \ - iidxio \ - cconfig \ - util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ + mxml \ + sdk-hook \ src_iidxhook5-cn := \ avs-boot.c \ - path.c \ dllmain.c \ + iidxhook5-cn.c \ + path.c \ diff --git a/src/main/iidxhook5-cn/avs-boot.c b/src/main/iidxhook5-cn/avs-boot.c index 772832ab..13cca830 100644 --- a/src/main/iidxhook5-cn/avs-boot.c +++ b/src/main/iidxhook5-cn/avs-boot.c @@ -3,14 +3,16 @@ #include #include +#include "core/log-bt.h" + #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "iidxhook5-cn/avs-boot.h" -#include "util/log.h" - static void (*real_avs_boot)( struct property_node *config, void *std_heap, @@ -35,6 +37,11 @@ static const struct hook_symbol iidxhook5_cn_log_hook_syms[] = { .link = (void **) &real_avs_boot}, }; +static AVS_LOG_WRITER(_avs_boot_log_writer, chars, nchars, ctx) +{ + core_log_bt_direct_sink_write(chars, nchars); +} + static void avs_boot_replace_property_uint32( struct property_node *node, const char *name, uint32_t val) { @@ -87,7 +94,7 @@ static void my_avs_boot( sz_std_heap, avs_heap, sz_avs_heap, - log_writer_debug, + _avs_boot_log_writer, NULL); } diff --git a/src/main/iidxhook5-cn/dllmain.c b/src/main/iidxhook5-cn/dllmain.c index 711c906f..76872514 100644 --- a/src/main/iidxhook5-cn/dllmain.c +++ b/src/main/iidxhook5-cn/dllmain.c @@ -1,217 +1,69 @@ #include -#include -#include -#include -#include - -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-emu/node-security-plug.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "ezusb2-iidx-emu/msg.h" - -#include "hook/d3d9.h" #include "hook/table.h" -#include "hooklib/acp.h" -#include "hooklib/setupapi.h" - -#include "iidxhook5-cn/avs-boot.h" -#include "iidxhook5-cn/path.h" - -#include "iidxhook-util/config-eamuse.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-io.h" -#include "iidxhook-util/config-misc.h" -#include "iidxhook-util/config-sec.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/settings.h" +#include "iidxhook5-cn/iidxhook5-cn.h" -#include "security/rp-sign-key.h" +#include "main/sdk-hook/dllentry.h" -#include "imports/avs.h" +#include "util/defs.h" -#include "util/log.h" +static ATOM WINAPI _iidxhook5_cn_dllmain_my_RegisterClassA(const WNDCLASSA *lpWndClass); +static ATOM(WINAPI *_iidxhook5_cn_dllmain_real_RegisterClassA)(const WNDCLASSA *lpWndClass); -#define IIDXHOOK5_CN_INFO_HEADER \ - "iidxhook for tricoro CN" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK5_CN_CMD_USAGE \ - "Usage: inject.exe iidxhook5-cn.dll [options...]" +static bool _iidxhook5_cn_dllmain_registerclassa_call_check; -static ATOM WINAPI my_RegisterClassA(const WNDCLASSA *lpWndClass); -static ATOM(WINAPI *real_RegisterClassA)(const WNDCLASSA *lpWndClass); -static bool iidxhook_init_check; - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_util_d3d9_irp_handler, +static const struct hook_symbol _iidxhook5_cn_dllmain_hook_syms[] = { + { + .name = "RegisterClassA", + .patch = _iidxhook5_cn_dllmain_my_RegisterClassA, + .link = (void **) &_iidxhook5_cn_dllmain_real_RegisterClassA + }, }; -static const struct hook_symbol init_hook_user32_syms[] = { - {.name = "RegisterClassA", - .patch = my_RegisterClassA, - .link = (void **) &real_RegisterClassA}, -}; - -static struct iidxhook_config_io config_io; - -static void -iidxhook5_cn_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; - d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; - d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - d3d9_config.iidx14_to_19_nvidia_fix = true; - d3d9_config.iidx18_and_19_diagonal_tearing_fix = - config_gfx->diagonal_tearing_fix; - - iidxhook_util_d3d9_configure(&d3d9_config); - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -/** - * OpenProcess is basically used for hooks in exe games, - * but since it does not exist in this game, RegisterClassA is used instead. - */ -static ATOM WINAPI my_RegisterClassA(const WNDCLASSA *lpWndClass) +static ATOM WINAPI _iidxhook5_cn_dllmain_my_RegisterClassA(const WNDCLASSA *lpWndClass) { - struct cconfig *config; - - struct iidxhook_util_config_eamuse config_eamuse; - struct iidxhook_config_gfx config_gfx; - struct iidxhook_config_sec config_sec; - struct iidxhook_config_misc config_misc; - - if (iidxhook_init_check) { - return real_RegisterClassA(lpWndClass); + if (_iidxhook5_cn_dllmain_registerclassa_call_check) { + return _iidxhook5_cn_dllmain_real_RegisterClassA(lpWndClass); } - iidxhook_init_check = true; - - log_info("-------------------------------------------------------------"); - log_info("------------- Begin iidxhook my_RegisterClassA --------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); + _iidxhook5_cn_dllmain_registerclassa_call_check = true; - iidxhook_util_config_eamuse_init(config); - iidxhook_config_gfx_init(config); - iidxhook_config_io_init(config); - iidxhook_config_sec_init(config); - iidxhook_config_misc_init(config); + bt_hook_dllentry_main_init(); - if (!cconfig_hook_config_init( - config, - IIDXHOOK5_CN_INFO_HEADER "\n" IIDXHOOK5_CN_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - iidxhook_util_config_eamuse_get(&config_eamuse, config); - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_io_get(&config_io, config); - iidxhook_config_sec_get(&config_sec, config); - iidxhook_config_misc_get(&config_misc, config); - - cconfig_finit(config); - - log_info(IIDXHOOK5_CN_INFO_HEADER); - log_info("Initializing iidxhook..."); - - /** - * This game is using a black round plug for game license management instead - * of a black usb dongle. No white dongle hooks applies since the game does - * not have network functionality. Also, card readers are not used/checked; - * no card reader hooks required. - */ - ezusb_iidx_emu_node_security_plug_set_boot_version( - &config_sec.boot_version); - ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); - ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( - &security_rp_sign_key_black_iidx); - ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( - &config_sec.black_plug_mcode); - ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); - - iidxhook5_cn_setup_d3d9_hooks(&config_gfx); - - if (strlen(config_misc.settings_path) > 0) { - settings_hook_set_path(config_misc.settings_path); - } - - if (!config_io.disable_io_emu) { - log_info("Starting IIDX IO backend"); + return _iidxhook5_cn_dllmain_real_RegisterClassA(lpWndClass); +} - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } else { - log_info("IIDX IO emulation backend disabled"); - } +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ + if (reason == DLL_PROCESS_ATTACH) { + bt_hook_dllentry_init( + mod, + "iidxhook5-cn", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(settings_hook_dispatch_irp); + _iidxhook5_cn_dllmain_registerclassa_call_check = false; - if (!config_io.disable_io_emu) { - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); - } + hook_table_apply( + NULL, "kernel32.dll", _iidxhook5_cn_dllmain_hook_syms, lengthof(_iidxhook5_cn_dllmain_hook_syms)); - log_info("-------------------------------------------------------------"); - log_info("-------------- End iidxhook my_RegisterClassA ---------------"); - log_info("-------------------------------------------------------------"); + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "kernel32.dll", _iidxhook5_cn_dllmain_hook_syms, lengthof(_iidxhook5_cn_dllmain_hook_syms)); - return real_RegisterClassA(lpWndClass); -} + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); -/** - * Hook library for tricoro CN - */ -BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) -{ - if (reason != DLL_PROCESS_ATTACH) { - return TRUE; + bt_hook_dllentry_fini(); + } } - log_to_writer(log_writer_debug, NULL); - - hook_table_apply( - NULL, - "user32.dll", - init_hook_user32_syms, - lengthof(init_hook_user32_syms)); - - iidxhook5_cn_path_init(); - iidxhook5_cn_avs_boot_init(); - acp_hook_init(); - settings_hook_init(); - return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook5-cn/iidxhook5-cn.c b/src/main/iidxhook5-cn/iidxhook5-cn.c new file mode 100644 index 00000000..cda11b0d --- /dev/null +++ b/src/main/iidxhook5-cn/iidxhook5-cn.c @@ -0,0 +1,187 @@ +#include + +#include +#include +#include +#include + +#include "ezusb-emu/node-security-plug.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/d3d9.h" +#include "hook/table.h" + +#include "hooklib/acp.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/iidx.h" + +#include "iidxhook5-cn/avs-boot.h" +#include "iidxhook5-cn/path.h" + +#include "iidxhook-util/config-eamuse.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-io.h" +#include "iidxhook-util/config-misc.h" +#include "iidxhook-util/config-sec.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/settings.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "security/rp-sign-key.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static module_io_t *iidxhook_module_io_iidx; + +static void _iidxhook5_cn_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void +iidxhook5_cn_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + d3d9_config.iidx14_to_19_nvidia_fix = true; + d3d9_config.iidx18_and_19_diagonal_tearing_fix = + config_gfx->diagonal_tearing_fix; + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook5_cn_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_util_config_eamuse_t config_eamuse; + iidxhook_config_gfx_t config_gfx; + iidxhook_config_sec_t config_sec; + iidxhook_config_misc_t config_misc; + iidxhook_config_io_t config_io; + + log_info("iidxhook for tricoro CN"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_eamuse_get(config, &config_eamuse); + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_sec_get(config, &config_sec); + iidxhook_util_config_misc_get(config, &config_misc); + iidxhook_util_config_io_get(config, &config_io); + + iidxhook5_cn_path_init(); + iidxhook5_cn_avs_boot_init(); + acp_hook_init(); + settings_hook_init(); + + /** + * This game is using a black round plug for game license management instead + * of a black usb dongle. No white dongle hooks applies since the game does + * not have network functionality. Also, card readers are not used/checked; + * no card reader hooks required. + */ + ezusb_iidx_emu_node_security_plug_set_boot_version( + &config_sec.boot_version); + ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); + ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( + &security_rp_sign_key_black_iidx); + ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( + &config_sec.black_plug_mcode); + ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + + iidxhook5_cn_setup_d3d9_hooks(&config_gfx); + + if (strlen(config_misc.settings_path) > 0) { + settings_hook_set_path(config_misc.settings_path); + } + + if (!config_io.disable_io_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook5_cn_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } else { + log_info("IIDX IO emulation backend disabled"); + } + + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + if (!config_io.disable_io_emu) { + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + } + + return true; +} + +static void _iidxhook5_cn_main_fini() +{ + // TODO cleanup +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook5_cn_main_init; + api->v1.main_fini = _iidxhook5_cn_main_fini; +} diff --git a/src/main/iidxhook5-cn/iidxhook5-cn.def b/src/main/iidxhook5-cn/iidxhook5-cn.def index 3ef04542..2fb7cbf1 100644 --- a/src/main/iidxhook5-cn/iidxhook5-cn.def +++ b/src/main/iidxhook5-cn/iidxhook5-cn.def @@ -2,3 +2,9 @@ LIBRARY iidxhook5-cn EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook5-cn/iidxhook5-cn.h b/src/main/iidxhook5-cn/iidxhook5-cn.h new file mode 100644 index 00000000..12afd478 --- /dev/null +++ b/src/main/iidxhook5-cn/iidxhook5-cn.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK5_CN_H +#define IIDXHOOK5_CN_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook5-cn/path.c b/src/main/iidxhook5-cn/path.c index d45bf227..2357e925 100644 --- a/src/main/iidxhook5-cn/path.c +++ b/src/main/iidxhook5-cn/path.c @@ -6,9 +6,10 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "iidxhook5-cn/path.h" -#include "util/log.h" #include "util/str.h" #define PATH_A "D:/JDZ-001/contents/" diff --git a/src/main/iidxhook5/Module.mk b/src/main/iidxhook5/Module.mk index 78ea3077..bd2a0c3f 100644 --- a/src/main/iidxhook5/Module.mk +++ b/src/main/iidxhook5/Module.mk @@ -6,7 +6,11 @@ ldflags_iidxhook5 := \ deplibs_iidxhook5 := \ avs \ +avslibs_iidxhook5 := \ + avs-ext \ + libs_iidxhook5 := \ + core \ iidxhook-util \ ezusb-emu \ ezusb-iidx-16seg-emu \ @@ -14,15 +18,18 @@ libs_iidxhook5 := \ ezusb2-iidx-emu \ ezusb-iidx-emu \ security \ - eamio \ acioemu \ hook \ hooklib \ - iidxio \ - cconfig \ - util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ + mxml \ src_iidxhook5 := \ dllmain.c \ + iidxhook5.c \ ifs-snd-redir.c \ diff --git a/src/main/iidxhook5/dllmain.c b/src/main/iidxhook5/dllmain.c index 268bf395..f8f6588d 100644 --- a/src/main/iidxhook5/dllmain.c +++ b/src/main/iidxhook5/dllmain.c @@ -1,242 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-iidx-emu/nodes.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "ezusb2-iidx-emu/msg.h" - -#include "hook/d3d9.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-util/acio.h" -#include "iidxhook-util/chart-patch.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-io.h" -#include "iidxhook-util/config-misc.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/log-server.h" -#include "iidxhook-util/settings.h" - -#include "imports/avs.h" - -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#include "ifs-snd-redir.h" - -#define IIDXHOOK5_INFO_HEADER \ - "iidxhook for Lincle" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK5_CMD_USAGE \ - "Usage: launcher.exe -K iidxhook5.dll [options...]" - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_util_d3d9_irp_handler, -}; - -static struct iidxhook_config_io config_io; - -static void -iidxhook5_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; - d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; - d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - d3d9_config.iidx14_to_19_nvidia_fix = true; - d3d9_config.iidx18_and_19_diagonal_tearing_fix = - config_gfx->diagonal_tearing_fix; - - if (config_gfx->monitor_check == 0) { - log_info("Auto monitor check enabled"); - - d3d9_config.iidx09_to_19_monitor_check_cb = - iidxhook_util_chart_patch_set_refresh_rate; - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - } else if (config_gfx->monitor_check > 0) { - log_info( - "Manual monitor check, resulting refresh rate: %f", - config_gfx->monitor_check); - - iidxhook_util_chart_patch_init( - IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); - iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); - } - - iidxhook_util_d3d9_configure(&d3d9_config); - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - struct cconfig *config; - - struct iidxhook_config_gfx config_gfx; - struct iidxhook_config_misc config_misc; - - log_server_init(); - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook dll_entry_init ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - iidxhook_config_io_init(config); - iidxhook_config_misc_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK5_INFO_HEADER "\n" IIDXHOOK5_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - log_server_fini(); - exit(EXIT_FAILURE); - } - - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_io_get(&config_io, config); - iidxhook_config_misc_get(&config_misc, config); - - cconfig_finit(config); - - log_info(IIDXHOOK5_INFO_HEADER); - log_info("Initializing iidxhook..."); - - iidxhook5_setup_d3d9_hooks(&config_gfx); - - if (strlen(config_misc.settings_path) > 0) { - settings_hook_set_path(config_misc.settings_path); - } - - if (!config_io.disable_io_emu) { - log_info("Starting IIDX IO backend"); - - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } else { - log_info("IIDX IO emulation backend disabled"); - } - - if (!config_io.disable_card_reader_emu) { - log_misc("Initializing card reader backend"); - - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - } else { - log_info("Card reader emulation backend disabled"); - } - - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); - iohook_push_handler(settings_hook_dispatch_irp); - - if (!config_io.disable_io_emu) { - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); - } - - iidxhook5_ifs_snd_redir_init(); - - /* Card reader emulation, same issue with hooking as IO emulation */ - rs232_hook_init(); - - if (!config_io.disable_card_reader_emu) { - /* Do not use legacy mode, first version with wave pass readers */ - iidxhook_util_acio_init(false); - } - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook dll_entry_init ----------------"); - log_info("-------------------------------------------------------------"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - if (!config_io.disable_card_reader_emu) { - log_misc("Shutting down card reader backend"); - eam_io_fini(); - } - - if (!config_io.disable_io_emu) { - log_misc("Shutting down IIDX IO backend"); - iidx_io_fini(); - } - - log_server_fini(); - - return result; -} - -/** - * Hook library for Lincle - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - acp_hook_init(); - adapter_hook_init(); - settings_hook_init(); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook5/ifs-snd-redir.c b/src/main/iidxhook5/ifs-snd-redir.c index e73dd5ca..64fff9d3 100644 --- a/src/main/iidxhook5/ifs-snd-redir.c +++ b/src/main/iidxhook5/ifs-snd-redir.c @@ -7,9 +7,10 @@ #include "imports/avs.h" +#include "iface-core/log.h" + #include "iidxhook5/ifs-snd-redir.h" -#include "util/log.h" #include "util/str.h" static void *(*real_avs_fs_open)(const char *path, int mode, int flags); diff --git a/src/main/iidxhook5/iidxhook5.c b/src/main/iidxhook5/iidxhook5.c new file mode 100644 index 00000000..0ba4870e --- /dev/null +++ b/src/main/iidxhook5/iidxhook5.c @@ -0,0 +1,236 @@ +#define LOG_MODULE "iidxhook5" + +#include + +#include +#include +#include +#include + +#include "ezusb-iidx-emu/nodes.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/d3d9.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/chart-patch.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-io.h" +#include "iidxhook-util/config-misc.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/settings.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/str.h" + +#include "ifs-snd-redir.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static struct iidxhook_config_io config_io; +static module_io_t *iidxhook_module_io_iidx; +static module_io_t *iidxhook_module_io_eam; + +static void _iidxhook5_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook5_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void +iidxhook5_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + d3d9_config.iidx14_to_19_nvidia_fix = true; + d3d9_config.iidx18_and_19_diagonal_tearing_fix = + config_gfx->diagonal_tearing_fix; + + if (config_gfx->monitor_check == 0) { + log_info("Auto monitor check enabled"); + + d3d9_config.iidx09_to_19_monitor_check_cb = + iidxhook_util_chart_patch_set_refresh_rate; + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + } else if (config_gfx->monitor_check > 0) { + log_info( + "Manual monitor check, resulting refresh rate: %f", + config_gfx->monitor_check); + + iidxhook_util_chart_patch_init( + IIDXHOOK_UTIL_CHART_PATCH_TIMEBASE_14_TO_19_VGA); + iidxhook_util_chart_patch_set_refresh_rate(config_gfx->monitor_check); + } + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook5_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_config_gfx_t config_gfx; + iidxhook_config_misc_t config_misc; + + log_info("iidxhook for Lincle"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_misc_get(config, &config_misc); + iidxhook_util_config_io_get(config, &config_io); + + acp_hook_init(); + adapter_hook_init(); + settings_hook_init(); + + iidxhook5_setup_d3d9_hooks(&config_gfx); + + if (strlen(config_misc.settings_path) > 0) { + settings_hook_set_path(config_misc.settings_path); + } + + if (!config_io.disable_io_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook5_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } else { + log_info("IIDX IO emulation backend disabled"); + } + + if (!config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + _iidxhook5_io_eam_init(&iidxhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + } else { + log_info("Card reader emulation backend disabled"); + } + + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + if (!config_io.disable_io_emu) { + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + } + + iidxhook5_ifs_snd_redir_init(); + + /* Card reader emulation, same issue with hooking as IO emulation */ + rs232_hook_init(); + + if (!config_io.disable_card_reader_emu) { + /* Do not use legacy mode, first version with wave pass readers */ + iidxhook_util_acio_init(false); + } + + return true; +} + +static void _iidxhook5_main_fini() +{ + if (!config_io.disable_card_reader_emu) { + log_misc("Shutting down card reader backend"); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&iidxhook_module_io_eam); + } + + if (!config_io.disable_io_emu) { + log_misc("Shutting down IIDX IO backend"); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&iidxhook_module_io_iidx); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook5_main_init; + api->v1.main_fini = _iidxhook5_main_fini; +} diff --git a/src/main/iidxhook5/iidxhook5.def b/src/main/iidxhook5/iidxhook5.def index 7235fdbc..0a325a8d 100644 --- a/src/main/iidxhook5/iidxhook5.def +++ b/src/main/iidxhook5/iidxhook5.def @@ -2,4 +2,9 @@ LIBRARY iidxhook5 EXPORTS DllMain@12 @1 NONAME - \ No newline at end of file + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook5/iidxhook5.h b/src/main/iidxhook5/iidxhook5.h new file mode 100644 index 00000000..1c0b7764 --- /dev/null +++ b/src/main/iidxhook5/iidxhook5.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK5_H +#define IIDXHOOK5_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook6/Module.mk b/src/main/iidxhook6/Module.mk index 7fda87b1..6c77ebe6 100644 --- a/src/main/iidxhook6/Module.mk +++ b/src/main/iidxhook6/Module.mk @@ -6,7 +6,11 @@ ldflags_iidxhook6 := \ deplibs_iidxhook6 := \ avs \ +avslibs_iidxhook6 := \ + avs-ext \ + libs_iidxhook6 := \ + core \ iidxhook-d3d9 \ iidxhook-util \ ezusb-emu \ @@ -15,14 +19,16 @@ libs_iidxhook6 := \ ezusb2-iidx-emu \ ezusb-iidx-emu \ security \ - eamio \ acioemu \ hook \ hooklib \ - iidxio \ - cconfig \ - util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ src_iidxhook6 := \ dllmain.c \ + iidxhook6.c \ diff --git a/src/main/iidxhook6/dllmain.c b/src/main/iidxhook6/dllmain.c index b4ca65aa..f8f6588d 100644 --- a/src/main/iidxhook6/dllmain.c +++ b/src/main/iidxhook6/dllmain.c @@ -1,216 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-iidx-emu/nodes.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "ezusb2-iidx-emu/msg.h" - -#include "hook/d3d9.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-d3d9/bb-scale-hd.h" - -#include "iidxhook-util/acio.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-io.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/log-server.h" - -#include "imports/avs.h" - -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#define IIDXHOOK6_INFO_HEADER \ - "iidxhook for Tricoro" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK6_CMD_USAGE \ - "Usage: launcher.exe -K iidxhook6.dll [options...]" - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler, - iidxhook_util_d3d9_irp_handler, -}; - -static struct iidxhook_config_io config_io; - -static void -iidxhook6_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - - iidxhook_util_d3d9_configure(&d3d9_config); - - // The "old"/current scaling feature does not work with 20-26 because - // the render engine changed and provides its own built-in scaling feature - if (config_gfx->scale_back_buffer_width > 0 && - config_gfx->scale_back_buffer_height > 0) { - iidxhook_d3d9_bb_scale_hd_init( - config_gfx->scale_back_buffer_width, - config_gfx->scale_back_buffer_height); - } - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - struct cconfig *config; - - struct iidxhook_config_gfx config_gfx; - - log_server_init(); - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook dll_entry_init ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - iidxhook_config_io_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK6_INFO_HEADER "\n" IIDXHOOK6_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - log_server_fini(); - exit(EXIT_FAILURE); - } - - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_io_get(&config_io, config); - - cconfig_finit(config); - - log_info(IIDXHOOK6_INFO_HEADER); - log_info("Initializing iidxhook..."); - - iidxhook6_setup_d3d9_hooks(&config_gfx); - - if (!config_io.disable_io_emu) { - log_info("Starting IIDX IO backend"); - - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } else { - log_info("IIDX IO emulation backend disabled"); - } - - if (!config_io.disable_card_reader_emu) { - log_misc("Initializing card reader backend"); - - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - } else { - log_info("Card reader emulation backend disabled"); - } - - /* iohooks are okay, even if emu is diabled since the fake handlers won't be - * used */ - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - - if (!config_io.disable_io_emu) { - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); - } - - /* Card reader emulation, same issue with hooking as IO emulation */ - rs232_hook_init(); - - if (!config_io.disable_card_reader_emu) { - /* Do not use legacy mode, wave pass readers */ - iidxhook_util_acio_init(false); - } - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook dll_entry_init ----------------"); - log_info("-------------------------------------------------------------"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - if (!config_io.disable_card_reader_emu) { - log_misc("Shutting down card reader backend"); - eam_io_fini(); - } - - if (!config_io.disable_io_emu) { - log_misc("Shutting down IIDX IO backend"); - iidx_io_fini(); - } - - log_server_fini(); - - return result; -} - -/** - * Hook library for Tricoro - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - acp_hook_init(); - adapter_hook_init(); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook6/iidxhook6.c b/src/main/iidxhook6/iidxhook6.c new file mode 100644 index 00000000..ec7a0aba --- /dev/null +++ b/src/main/iidxhook6/iidxhook6.c @@ -0,0 +1,211 @@ +#define LOG_MODULE "iidxhook6" + +#include + +#include +#include +#include +#include + +#include "ezusb-iidx-emu/nodes.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/d3d9.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-d3d9/bb-scale-hd.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-io.h" +#include "iidxhook-util/d3d9.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/str.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler, + iidxhook_util_d3d9_irp_handler, +}; + +static struct iidxhook_config_io config_io; +static module_io_t *iidxhook_module_io_iidx; +static module_io_t *iidxhook_module_io_eam; + +static void _iidxhook6_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook6_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void +iidxhook6_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + + iidxhook_util_d3d9_configure(&d3d9_config); + + // The "old"/current scaling feature does not work with 20-26 because + // the render engine changed and provides its own built-in scaling feature + if (config_gfx->scale_back_buffer_width > 0 && + config_gfx->scale_back_buffer_height > 0) { + iidxhook_d3d9_bb_scale_hd_init( + config_gfx->scale_back_buffer_width, + config_gfx->scale_back_buffer_height); + } + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook6_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_config_gfx_t config_gfx; + + log_info("iidxhook for Tricoro"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_io_get(config, &config_io); + + acp_hook_init(); + adapter_hook_init(); + + iidxhook6_setup_d3d9_hooks(&config_gfx); + + if (!config_io.disable_io_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook6_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } else { + log_info("IIDX IO emulation backend disabled"); + } + + if (!config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + _iidxhook6_io_eam_init(&iidxhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + } else { + log_info("Card reader emulation backend disabled"); + } + + /* iohooks are okay, even if emu is diabled since the fake handlers won't be + * used */ + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + + if (!config_io.disable_io_emu) { + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + } + + /* Card reader emulation, same issue with hooking as IO emulation */ + rs232_hook_init(); + + if (!config_io.disable_card_reader_emu) { + /* Do not use legacy mode, wave pass readers */ + iidxhook_util_acio_init(false); + } + + return true; +} + +static void _iidxhook6_main_fini() +{ + if (!config_io.disable_card_reader_emu) { + log_misc("Shutting down card reader backend"); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&iidxhook_module_io_eam); + } + + if (!config_io.disable_io_emu) { + log_misc("Shutting down IIDX IO backend"); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&iidxhook_module_io_iidx); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook6_main_init; + api->v1.main_fini = _iidxhook6_main_fini; +} diff --git a/src/main/iidxhook6/iidxhook6.def b/src/main/iidxhook6/iidxhook6.def index a0da401d..52c17db3 100644 --- a/src/main/iidxhook6/iidxhook6.def +++ b/src/main/iidxhook6/iidxhook6.def @@ -2,4 +2,9 @@ LIBRARY iidxhook6 EXPORTS DllMain@12 @1 NONAME - \ No newline at end of file + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook6/iidxhook6.h b/src/main/iidxhook6/iidxhook6.h new file mode 100644 index 00000000..14cf7486 --- /dev/null +++ b/src/main/iidxhook6/iidxhook6.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK6_H +#define IIDXHOOK6_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook7/Module.mk b/src/main/iidxhook7/Module.mk index a40366af..71b2c519 100644 --- a/src/main/iidxhook7/Module.mk +++ b/src/main/iidxhook7/Module.mk @@ -7,23 +7,29 @@ ldflags_iidxhook7 := \ deplibs_iidxhook7 := \ avs \ +avslibs_iidxhook7 := \ + avs-ext \ + libs_iidxhook7 := \ + core \ iidxhook-d3d9 \ iidxhook-util \ - cconfig \ ezusb-emu \ ezusb-iidx-16seg-emu \ ezusb2-emu \ ezusb2-iidx-emu \ ezusb-iidx-emu \ security \ - eamio \ acioemu \ hook \ hooklib \ - iidxio \ - util \ ezusb \ + iface \ + iface-io \ + iface-core \ + module \ + util \ src_iidxhook7 := \ dllmain.c \ + iidxhook7.c \ diff --git a/src/main/iidxhook7/dllmain.c b/src/main/iidxhook7/dllmain.c index af948f61..f8f6588d 100644 --- a/src/main/iidxhook7/dllmain.c +++ b/src/main/iidxhook7/dllmain.c @@ -1,216 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-iidx-emu/nodes.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "ezusb2-iidx-emu/msg.h" - -#include "hook/d3d9.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-d3d9/bb-scale-hd.h" - -#include "iidxhook-util/acio.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/config-io.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/log-server.h" - -#include "imports/avs.h" - -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#define IIDXHOOK7_INFO_HEADER \ - "iidxhook for SPADA, PENDUAL, copula and SINOBUZ" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define IIDXHOOK7_CMD_USAGE \ - "Usage: launcher.exe -K iidxhook7.dll [options...]" - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler, - iidxhook_util_d3d9_irp_handler, -}; - -static struct iidxhook_config_io config_io; - -static void -iidxhook7_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - - iidxhook_util_d3d9_configure(&d3d9_config); - - // The "old"/current scaling feature does not work with 20-26 because - // the render engine changed and provides its own built-in scaling feature - if (config_gfx->scale_back_buffer_width > 0 && - config_gfx->scale_back_buffer_height > 0) { - iidxhook_d3d9_bb_scale_hd_init( - config_gfx->scale_back_buffer_width, - config_gfx->scale_back_buffer_height); - } - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - struct cconfig *config; - - struct iidxhook_config_gfx config_gfx; - - log_server_init(); - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook dll_entry_init ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - iidxhook_config_io_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK7_INFO_HEADER "\n" IIDXHOOK7_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - log_server_fini(); - exit(EXIT_FAILURE); - } - - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook_config_io_get(&config_io, config); - - cconfig_finit(config); - - log_info(IIDXHOOK7_INFO_HEADER); - log_info("Initializing iidxhook..."); - - iidxhook7_setup_d3d9_hooks(&config_gfx); - - if (!config_io.disable_io_emu) { - log_info("Starting IIDX IO backend"); - - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } else { - log_info("IIDX IO emulation backend disabled"); - } - - if (!config_io.disable_card_reader_emu) { - log_misc("Initializing card reader backend"); - - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - } else { - log_info("Card reader emulation backend disabled"); - } - - /* iohooks are okay, even if emu is diabled since the fake handlers won't be - * used */ - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - - if (!config_io.disable_io_emu) { - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); - } - - /* Card reader emulation, same issue with hooking as IO emulation */ - rs232_hook_init(); - - if (!config_io.disable_card_reader_emu) { - /* Do not use legacy mode, wave pass readers */ - iidxhook_util_acio_init(false); - } - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook dll_entry_init ----------------"); - log_info("-------------------------------------------------------------"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - if (!config_io.disable_card_reader_emu) { - log_misc("Shutting down card reader backend"); - eam_io_fini(); - } - - if (!config_io.disable_io_emu) { - log_misc("Shutting down IIDX IO backend"); - iidx_io_fini(); - } - - log_server_fini(); - - return result; -} - -/** - * Hook library for SPADA, PENDUAL, copula and SINOBUZ - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - acp_hook_init(); - adapter_hook_init(); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook7/iidxhook7.c b/src/main/iidxhook7/iidxhook7.c new file mode 100644 index 00000000..e45093fd --- /dev/null +++ b/src/main/iidxhook7/iidxhook7.c @@ -0,0 +1,211 @@ +#define LOG_MODULE "iidxhook7" + +#include + +#include +#include +#include +#include + +#include "ezusb-iidx-emu/nodes.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/d3d9.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-d3d9/bb-scale-hd.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-io.h" +#include "iidxhook-util/d3d9.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/str.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler, + iidxhook_util_d3d9_irp_handler, +}; + +static struct iidxhook_config_io config_io; +static module_io_t *iidxhook_module_io_iidx; +static module_io_t *iidxhook_module_io_eam; + +static void _iidxhook7_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook7_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void +iidxhook7_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + + iidxhook_util_d3d9_configure(&d3d9_config); + + // The "old"/current scaling feature does not work with 20-26 because + // the render engine changed and provides its own built-in scaling feature + if (config_gfx->scale_back_buffer_width > 0 && + config_gfx->scale_back_buffer_height > 0) { + iidxhook_d3d9_bb_scale_hd_init( + config_gfx->scale_back_buffer_width, + config_gfx->scale_back_buffer_height); + } + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +static bool +_iidxhook7_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_config_gfx_t config_gfx; + + log_info("iidxhook for SPADA, PENDUAL, copula and SINOBUZ"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook_util_config_io_get(config, &config_io); + + acp_hook_init(); + adapter_hook_init(); + + iidxhook7_setup_d3d9_hooks(&config_gfx); + + if (!config_io.disable_io_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook7_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } else { + log_info("IIDX IO emulation backend disabled"); + } + + if (!config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + _iidxhook7_io_eam_init(&iidxhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + } else { + log_info("Card reader emulation backend disabled"); + } + + /* iohooks are okay, even if emu is diabled since the fake handlers won't be + * used */ + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + + if (!config_io.disable_io_emu) { + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + } + + /* Card reader emulation, same issue with hooking as IO emulation */ + rs232_hook_init(); + + if (!config_io.disable_card_reader_emu) { + /* Do not use legacy mode, wave pass readers */ + iidxhook_util_acio_init(false); + } + + return true; +} + +static void _iidxhook7_main_fini() +{ + if (!config_io.disable_card_reader_emu) { + log_misc("Shutting down card reader backend"); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&iidxhook_module_io_eam); + } + + if (!config_io.disable_io_emu) { + log_misc("Shutting down IIDX IO backend"); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&iidxhook_module_io_iidx); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook7_main_init; + api->v1.main_fini = _iidxhook7_main_fini; +} diff --git a/src/main/iidxhook7/iidxhook7.def b/src/main/iidxhook7/iidxhook7.def index 39872f21..40ce412e 100644 --- a/src/main/iidxhook7/iidxhook7.def +++ b/src/main/iidxhook7/iidxhook7.def @@ -2,3 +2,9 @@ LIBRARY iidxhook7 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook7/iidxhook7.h b/src/main/iidxhook7/iidxhook7.h new file mode 100644 index 00000000..34377d80 --- /dev/null +++ b/src/main/iidxhook7/iidxhook7.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK7_H +#define IIDXHOOK7_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook8/Module.mk b/src/main/iidxhook8/Module.mk index e71c8c25..1bd1d311 100644 --- a/src/main/iidxhook8/Module.mk +++ b/src/main/iidxhook8/Module.mk @@ -7,24 +7,32 @@ ldflags_iidxhook8 := \ -lmf \ -lmfplat \ -lole32 \ + -lws2_32 \ deplibs_iidxhook8 := \ avs \ +avslibs_iidxhook8 := \ + avs-ext \ + libs_iidxhook8 := \ + core \ iidxhook-d3d9 \ iidxhook-util \ acioemu \ bio2emu \ bio2emu-iidx \ camhook \ - iidxio \ hook \ hooklib \ - cconfig \ + iface \ + iface-io \ + iface-core \ + module \ util \ - eamio \ + security \ src_iidxhook8 := \ config-io.c \ dllmain.c \ + iidxhook8.c \ diff --git a/src/main/iidxhook8/config-io.c b/src/main/iidxhook8/config-io.c index 8cbb9b24..731ee432 100644 --- a/src/main/iidxhook8/config-io.c +++ b/src/main/iidxhook8/config-io.c @@ -1,77 +1,12 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "iidxhook8/config-io.h" -#include "util/log.h" - -#define IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY \ - "io.disable_card_reader_emu" -#define IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY "io.disable_bio2_emu" -#define IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter" - -#define IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false -#define IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false -#define IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false - -void iidxhook8_config_io_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE, - "Disable card reader emulation and enable usage of real card " - "reader " - "hardware on COM1 (for games supporting slotted readers)"); - - cconfig_util_set_bool( - config, - IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE, - "Disable BIO2 emulation and enable usage of real BIO2 hardware"); - - cconfig_util_set_bool( - config, - IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE, - "Disables the poll limiter, warning very high CPU usage may arise"); -} - void iidxhook8_config_io_get( - struct iidxhook8_config_io *config_io, struct cconfig *config) + const bt_core_config_t *config, + struct iidxhook8_config_io *config_io) { - if (!cconfig_util_get_bool( - config, - IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - &config_io->disable_card_reader_emu, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK8_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - &config_io->disable_bio2_emu, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK8_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - &config_io->disable_poll_limiter, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK8_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - IIDXHOOK8_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE); - } -} + bt_core_config_ext_bool_get(config, "io/disable_card_reader_emu", &config_io->disable_card_reader_emu); + bt_core_config_ext_bool_get(config, "io/disable_bio2_emu", &config_io->disable_bio2_emu); + bt_core_config_ext_bool_get(config, "io/disable_poll_limiter", &config_io->disable_poll_limiter); +} \ No newline at end of file diff --git a/src/main/iidxhook8/config-io.h b/src/main/iidxhook8/config-io.h index beaf6e4c..0c1daabd 100644 --- a/src/main/iidxhook8/config-io.h +++ b/src/main/iidxhook8/config-io.h @@ -1,9 +1,7 @@ #ifndef IIDXHOOK8_CONFIG_IO_H #define IIDXHOOK8_CONFIG_IO_H -#include - -#include "cconfig/cconfig.h" +#include "iface-core/config.h" struct iidxhook8_config_io { bool disable_card_reader_emu; @@ -11,9 +9,8 @@ struct iidxhook8_config_io { bool disable_poll_limiter; }; -void iidxhook8_config_io_init(struct cconfig *config); - void iidxhook8_config_io_get( - struct iidxhook8_config_io *config_io, struct cconfig *config); + const bt_core_config_t *config, + struct iidxhook8_config_io *config_io); #endif \ No newline at end of file diff --git a/src/main/iidxhook8/dllmain.c b/src/main/iidxhook8/dllmain.c index 7bf7e98c..f8f6588d 100644 --- a/src/main/iidxhook8/dllmain.c +++ b/src/main/iidxhook8/dllmain.c @@ -1,230 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "hook/d3d9.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-d3d9/bb-scale-hd.h" - -#include "iidxhook-util/acio.h" -#include "iidxhook-util/config-gfx.h" -#include "iidxhook-util/d3d9.h" -#include "iidxhook-util/log-server.h" - -#include "bio2emu-iidx/bi2a.h" -#include "bio2emu/emu.h" - -#include "camhook/cam.h" -#include "camhook/config-cam.h" -#include "iidxhook8/config-io.h" - -#include "imports/avs.h" - -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#define IIDXHOOK8_INFO_HEADER \ - "iidxhook for Cannon Ballers/Rootage" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n" -#define IIDXHOOK8_CMD_USAGE \ - "Usage: launcher.exe -K iidxhook8.dll [options...]" - -static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { - iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler, - iidxhook_util_d3d9_irp_handler, -}; - -static void -iidxhook8_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) -{ - struct iidxhook_util_d3d9_config d3d9_config; - - iidxhook_util_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.framerate_limit = config_gfx->frame_rate_limit; - d3d9_config.pci_vid = config_gfx->pci_id_vid; - d3d9_config.pci_pid = config_gfx->pci_id_pid; - d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; - d3d9_config.device_adapter = config_gfx->device_adapter; - - iidxhook_util_d3d9_configure(&d3d9_config); - - // The "old"/current scaling feature does not work with 20-26 because - // the render engine changed and provides its own built-in scaling feature - if (config_gfx->scale_back_buffer_width > 0 && - config_gfx->scale_back_buffer_height > 0) { - iidxhook_d3d9_bb_scale_hd_init( - config_gfx->scale_back_buffer_width, - config_gfx->scale_back_buffer_height); - } - - hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); -} - -struct iidxhook8_config_io iidxhook8_config_io; -struct camhook_config_cam config_cam; - -static struct bio2emu_port bio2_emu = { - .port = "COM4", - .wport = L"COM4", - .dispatcher = bio2_emu_bi2a_dispatch_request, -}; - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - struct cconfig *config; - - struct iidxhook_config_gfx config_gfx; - - // log_server_init is required due to IO occuring in a non avs_thread - log_server_init(); - - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook dll_entry_init ---------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - iidxhook8_config_io_init(config); - camhook_config_cam_init(config, 2, false); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK8_INFO_HEADER "\n" IIDXHOOK8_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - log_server_fini(); - exit(EXIT_FAILURE); - } - - iidxhook_config_gfx_get(&config_gfx, config); - iidxhook8_config_io_get(&iidxhook8_config_io, config); - camhook_config_cam_get(&config_cam, config, 2, false); - - cconfig_finit(config); - - log_info(IIDXHOOK8_INFO_HEADER); - log_info("Initializing iidxhook..."); - - iidxhook8_setup_d3d9_hooks(&config_gfx); - - /* Start up IIDXIO.DLL */ - if (!iidxhook8_config_io.disable_bio2_emu) { - log_info("Starting IIDX IO backend"); - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } - - /* Start up EAMIO.DLL */ - if (!iidxhook8_config_io.disable_card_reader_emu) { - log_misc("Initializing card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - } - - /* iohooks are okay, even if emu is diabled since the fake handlers won't be - * used */ - /* Set up IO emulation hooks _after_ IO API setup to allow - API implementations with real IO devices */ - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - iohook_push_handler(bio2emu_port_dispatch_irp); - - rs232_hook_init(); - rs232_hook_limit_hooks(); - - if (!iidxhook8_config_io.disable_bio2_emu) { - bio2emu_init(); - bio2_emu_bi2a_init(&bio2_emu, iidxhook8_config_io.disable_poll_limiter); - } - - if (!iidxhook8_config_io.disable_card_reader_emu) { - iidxhook_util_acio_init(false); - } - - // camera hooks - if (!config_cam.disable_emu) { - camhook_init(&config_cam); - } - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook dll_entry_init ----------------"); - log_info("-------------------------------------------------------------"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - if (!config_cam.disable_emu) { - camhook_fini(); - } - - if (!iidxhook8_config_io.disable_card_reader_emu) { - log_misc("Shutting down card reader backend"); - eam_io_fini(); - } - - if (!iidxhook8_config_io.disable_bio2_emu) { - log_misc("Shutting down IIDX IO backend"); - iidx_io_fini(); - } - - log_server_fini(); - - return result; -} - -/** - * Hook library CB/Rootage - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - acp_hook_init(); - adapter_hook_init(); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook8/iidxhook8.c b/src/main/iidxhook8/iidxhook8.c new file mode 100644 index 00000000..effd7820 --- /dev/null +++ b/src/main/iidxhook8/iidxhook8.c @@ -0,0 +1,225 @@ +#define LOG_MODULE "iidxhook8" + +#include + +#include +#include +#include +#include + +#include "hook/d3d9.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-d3d9/bb-scale-hd.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/d3d9.h" + +#include "bio2emu-iidx/bi2a.h" +#include "bio2emu/emu.h" + +#include "camhook/cam.h" +#include "camhook/config-cam.h" +#include "iidxhook8/config-io.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/str.h" + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler, + iidxhook_util_d3d9_irp_handler, +}; + +static module_io_t *iidxhook_module_io_iidx; +static module_io_t *iidxhook_module_io_eam; + +static void _iidxhook8_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook8_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void +iidxhook8_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + + iidxhook_util_d3d9_configure(&d3d9_config); + + // The "old"/current scaling feature does not work with 20-26 because + // the render engine changed and provides its own built-in scaling feature + if (config_gfx->scale_back_buffer_width > 0 && + config_gfx->scale_back_buffer_height > 0) { + iidxhook_d3d9_bb_scale_hd_init( + config_gfx->scale_back_buffer_width, + config_gfx->scale_back_buffer_height); + } + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +struct iidxhook8_config_io iidxhook8_config_io; +struct camhook_config_cam config_cam; + +static struct bio2emu_port bio2_emu = { + .port = "COM4", + .wport = L"COM4", + .dispatcher = bio2_emu_bi2a_dispatch_request, +}; + +static bool +_iidxhook8_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + iidxhook_config_gfx_t config_gfx; + + log_info("iidxhook for Cannon Ballers and Rootage"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + iidxhook_util_config_gfx_get(config, &config_gfx); + iidxhook8_config_io_get(config, &iidxhook8_config_io); + camhook_config_cam_get(config, &config_cam, 2, false); + + acp_hook_init(); + adapter_hook_init(); + + iidxhook8_setup_d3d9_hooks(&config_gfx); + + /* Start up IIDXIO.DLL */ + if (!iidxhook8_config_io.disable_bio2_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook8_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } + + /* Start up EAMIO.DLL */ + if (!iidxhook8_config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + _iidxhook8_io_eam_init(&iidxhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + } + + /* iohooks are okay, even if emu is diabled since the fake handlers won't be + * used */ + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + iohook_push_handler(bio2emu_port_dispatch_irp); + + rs232_hook_init(); + rs232_hook_limit_hooks(); + + if (!iidxhook8_config_io.disable_bio2_emu) { + bio2emu_init(); + bio2_emu_bi2a_init(&bio2_emu, iidxhook8_config_io.disable_poll_limiter); + } + + if (!iidxhook8_config_io.disable_card_reader_emu) { + iidxhook_util_acio_init(false); + } + + // camera hooks + if (!config_cam.disable_emu) { + camhook_init(&config_cam); + } + + return true; +} + +static void _iidxhook8_main_fini() +{ + if (!config_cam.disable_emu) { + camhook_fini(); + } + + if (!iidxhook8_config_io.disable_card_reader_emu) { + log_misc("Shutting down card reader backend"); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&iidxhook_module_io_eam); + } + + if (!iidxhook8_config_io.disable_bio2_emu) { + log_misc("Shutting down IIDX IO backend"); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&iidxhook_module_io_iidx); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _iidxhook8_main_init; + api->v1.main_fini = _iidxhook8_main_fini; +} diff --git a/src/main/iidxhook8/iidxhook8.def b/src/main/iidxhook8/iidxhook8.def index 8451e8ae..77cb42c9 100644 --- a/src/main/iidxhook8/iidxhook8.def +++ b/src/main/iidxhook8/iidxhook8.def @@ -2,3 +2,9 @@ LIBRARY iidxhook8 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook8/iidxhook8.h b/src/main/iidxhook8/iidxhook8.h new file mode 100644 index 00000000..17e833cd --- /dev/null +++ b/src/main/iidxhook8/iidxhook8.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK8_H +#define IIDXHOOK8_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxhook9/Module.mk b/src/main/iidxhook9/Module.mk index 09e56a8c..a3dddc88 100644 --- a/src/main/iidxhook9/Module.mk +++ b/src/main/iidxhook9/Module.mk @@ -7,11 +7,16 @@ ldflags_iidxhook9 := \ -lmf \ -lmfplat \ -lole32 \ + -lws2_32 \ deplibs_iidxhook9 := \ avs \ +avslibs_iidxhook9 := \ + avs-ext \ + libs_iidxhook9 := \ + core \ iidxhook-util \ acioemu \ asio \ @@ -20,14 +25,17 @@ libs_iidxhook9 := \ camhook \ d3d9exhook \ dinput \ - iidxio \ hook \ hooklib \ - cconfig \ + iface \ + iface-io \ + iface-core \ + module \ util \ - eamio \ + security \ src_iidxhook9 := \ config-io.c \ - fs-hook.c \ dllmain.c \ + fs-hook.c \ + iidxhook9.c \ diff --git a/src/main/iidxhook9/config-io.c b/src/main/iidxhook9/config-io.c index ba7ff45a..65de9192 100644 --- a/src/main/iidxhook9/config-io.c +++ b/src/main/iidxhook9/config-io.c @@ -1,156 +1,17 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" -#include "iidxhook9/config-io.h" - -#include "util/log.h" - -#define IIDXHOOK9_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY \ - "io.disable_card_reader_emu" -#define IIDXHOOK9_CONFIG_IO_DISABLE_BIO2_EMU_KEY "io.disable_bio2_emu" -#define IIDXHOOK9_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter" -#define IIDXHOOK9_CONFIG_IO_LIGHTNING_MODE_KEY "io.lightning_mode" -#define IIDXHOOK9_CONFIG_IO_DISABLE_CAMS_KEY "io.disable_cams" -#define IIDXHOOK9_CONFIG_IO_DISABLE_FILE_HOOKS_KEY "io.disable_file_hooks" -#define IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY "io.tt_multiplier" - -#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false -#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false -#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false -#define IIDXHOOK9_CONFIG_IO_DEFAULT_LIGHTNING_MODE_VALUE false -#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CAMS_VALUE false -#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE false -#define IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE 1.0 - -void iidxhook9_config_io_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE, - "Disable card reader emulation and enable usage of real card reader " - "hardware on COM1 (for games supporting slotted readers)"); - - cconfig_util_set_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE, - "Disable BIO2 emulation and enable usage of real BIO2 hardware"); - - cconfig_util_set_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE, - "Disables the poll limiter, warning very high CPU usage may arise"); - - cconfig_util_set_bool( - config, - IIDXHOOK9_CONFIG_IO_LIGHTNING_MODE_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_LIGHTNING_MODE_VALUE, - "Lightning cab mode (requires additional IO emulation)"); +#include "iface-core/log.h" - cconfig_util_set_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_CAMS_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CAMS_VALUE, - "Disable camera connection"); - - cconfig_util_set_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE, - "Disables the built in file hooks, requiring manual file creation"); - - cconfig_util_set_float( - config, - IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE, - "Turntable sensitivity multiplier (1.0 is default)"); -} +#include "iidxhook9/config-io.h" void iidxhook9_config_io_get( - struct iidxhook9_config_io *config_io, struct cconfig *config) + const bt_core_config_t *config, + struct iidxhook9_config_io *config_io) { - if (!cconfig_util_get_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - &config_io->disable_card_reader_emu, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK9_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - &config_io->disable_bio2_emu, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK9_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - &config_io->disable_poll_limiter, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK9_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK9_CONFIG_IO_LIGHTNING_MODE_KEY, - &config_io->lightning_mode, - IIDXHOOK9_CONFIG_IO_DEFAULT_LIGHTNING_MODE_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK9_CONFIG_IO_LIGHTNING_MODE_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_LIGHTNING_MODE_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_CAMS_KEY, - &config_io->disable_cams, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CAMS_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK9_CONFIG_IO_DISABLE_CAMS_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CAMS_VALUE); - } - - if (!cconfig_util_get_bool( - config, - IIDXHOOK9_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, - &config_io->disable_file_hooks, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - IIDXHOOK9_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE); - } - - if (!cconfig_util_get_float( - config, - IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY, - &config_io->tt_multiplier, - IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%f'", - IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY, - IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE); - } -} + bt_core_config_ext_bool_get(config, "io/disable_card_reader_emu", &config_io->disable_card_reader_emu); + bt_core_config_ext_bool_get(config, "io/disable_bio2_emu", &config_io->disable_bio2_emu); + bt_core_config_ext_bool_get(config, "io/disable_poll_limiter", &config_io->disable_poll_limiter); + bt_core_config_ext_bool_get(config, "io/disable_cams", &config_io->disable_cams); + bt_core_config_ext_bool_get(config, "io/disable_file_hooks", &config_io->disable_file_hooks); + bt_core_config_ext_float_get(config, "io/tt_multiplier", &config_io->tt_multiplier); +} \ No newline at end of file diff --git a/src/main/iidxhook9/config-io.h b/src/main/iidxhook9/config-io.h index 6bc30914..ad302886 100644 --- a/src/main/iidxhook9/config-io.h +++ b/src/main/iidxhook9/config-io.h @@ -1,9 +1,7 @@ #ifndef IIDXHOOK9_CONFIG_IO_H #define IIDXHOOK9_CONFIG_IO_H -#include - -#include "cconfig/cconfig.h" +#include struct iidxhook9_config_io { bool disable_card_reader_emu; @@ -15,9 +13,8 @@ struct iidxhook9_config_io { float tt_multiplier; }; -void iidxhook9_config_io_init(struct cconfig *config); - void iidxhook9_config_io_get( - struct iidxhook9_config_io *config_io, struct cconfig *config); + const bt_core_config_t *config, + struct iidxhook9_config_io *config_io); #endif \ No newline at end of file diff --git a/src/main/iidxhook9/dllmain.c b/src/main/iidxhook9/dllmain.c index 7044d215..f8f6588d 100644 --- a/src/main/iidxhook9/dllmain.c +++ b/src/main/iidxhook9/dllmain.c @@ -1,297 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/iidxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/config-adapter.h" -#include "hooklib/memfile.h" -#include "hooklib/rs232.h" -#include "hooklib/setupapi.h" - -#include "iidxhook-util/acio.h" -#include "iidxhook-util/log-server.h" - -#include "bio2emu/emu.h" - -#include "bio2emu-iidx/bi2a.h" - -#include "iidxhook9/config-io.h" -#include "iidxhook9/fs-hook.h" - -#include "camhook/cam.h" -#include "camhook/config-cam.h" - -#include "asio/asio-reghook.h" -#include "asio/config-asio.h" -#include "d3d9exhook/d3d9ex.h" -#include "dinput/dinput.h" - -#include "imports/avs.h" - -#include "util/cmdline.h" -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#define IIDXHOOK9_INFO_HEADER \ - "iidxhook for Heroic Verse" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n" -#define IIDXHOOK9_CMD_USAGE \ - "Usage: launcher.exe -B iidxhook9-prehook.dll -K iidxhook9.dll " \ - " [options...]" - -static struct iidxhook9_config_io iidxhook9_config_io; -static struct camhook_config_cam config_cam; -static struct asiohook_config_asio config_asio; -static struct hooklib_config_adapter config_adapter; -static struct d3d9exhook_config_gfx config_gfx; - -static struct bio2emu_port bio2_emu = { - .port = "COM4", - .wport = L"COM4", - .dispatcher = bio2_emu_bi2a_dispatch_request, -}; - -static bool load_configs() -{ - struct cconfig *config; - config = cconfig_init(); - - iidxhook9_config_io_init(config); - camhook_config_cam_init(config, 2, true); - - d3d9exhook_config_gfx_init(config); - - hooklib_config_adapter_init(config); - asiohook_config_init(config); - - if (!cconfig_hook_config_init( - config, - IIDXHOOK9_INFO_HEADER "\n" IIDXHOOK9_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - return false; - } - - iidxhook9_config_io_get(&iidxhook9_config_io, config); - camhook_config_cam_get(&config_cam, config, 2, true); - - d3d9exhook_config_gfx_get(&config_gfx, config); - - hooklib_config_adapter_get(&config_adapter, config); - asiohook_config_asio_get(&config_asio, config); - - cconfig_finit(config); - - return true; -} - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - // log_server_init is required due to IO occuring in a non avs_thread - log_server_init(); - - log_info("-------------------------------------------------------------"); - log_info("--------------- Begin iidxhook dll_entry_init ---------------"); - log_info("-------------------------------------------------------------"); - - log_info(IIDXHOOK9_INFO_HEADER); - log_info("Initializing iidxhook..."); - - // reload configs again so they get logged through avs as well - // (so we get a copy of them in the -Y logfile) - if (!load_configs()) { - log_server_fini(); - exit(EXIT_FAILURE); - } - - d3d9ex_configure(&config_gfx); - d3d9ex_hook_init(); - - acp_hook_init(); - adapter_hook_init(); - dinput_init(); - - /* Start up IIDXIO.DLL */ - if (!iidxhook9_config_io.disable_bio2_emu) { - log_info("Starting IIDX IO backend"); - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!iidx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing IIDX IO backend failed"); - } - } - - /* Start up EAMIO.DLL */ - if (!iidxhook9_config_io.disable_card_reader_emu) { - log_misc("Initializing card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - } - - iohook_push_handler(iidxhook_util_acio_dispatch_irp); - iohook_push_handler(bio2emu_port_dispatch_irp); - - if (!iidxhook9_config_io.disable_file_hooks) { - memfile_hook_init(); - iohook_push_handler(memfile_hook_dispatch_irp); - - // game uses this file to determine what mode to put the cab in - // the default depends on a value embedded in the dll - if (iidxhook9_config_io.lightning_mode) { - memfile_hook_add_fd("d:\\\\001rom.txt", ABSOLUTE_MATCH, "TDJ", 3); - } else { - memfile_hook_add_fd("d:\\\\001rom.txt", ABSOLUTE_MATCH, "LDJ", 3); - } - - // redirect F:\ drive to vfs (used for video recording) - iidxhook9_fs_hooks_init(); - } - - rs232_hook_init(); - rs232_hook_limit_hooks(); - - if (!iidxhook9_config_io.disable_bio2_emu) { - if (!iidxhook9_config_io.lightning_mode) { - bio2emu_init(); - bio2_emu_bi2a_set_tt_multiplier(iidxhook9_config_io.tt_multiplier); - bio2_emu_bi2a_init( - &bio2_emu, iidxhook9_config_io.disable_poll_limiter); - } - } - - if (!iidxhook9_config_io.disable_card_reader_emu) { - if (iidxhook9_config_io.lightning_mode) { - // TDJ mode expects 1.7.0 readers - iidxhook_util_acio_override_version(v170); - } - - iidxhook_util_acio_init(false); - } - - // camera hooks - if (!config_cam.disable_emu) { - camhook_set_version(CAMHOOK_VERSION_NEW); - camhook_init(&config_cam); - } - - adapter_hook_override(config_adapter.override_ip); - - // asio hooks - if (config_asio.force_asio) { - asio_reghook_init("XONAR SOUND CARD(64)", config_asio.replacement_name); - } - - log_info("-------------------------------------------------------------"); - log_info("---------------- End iidxhook dll_entry_init ----------------"); - log_info("-------------------------------------------------------------"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - if (!config_cam.disable_emu) { - camhook_fini(); - } - - if (!iidxhook9_config_io.disable_card_reader_emu) { - log_misc("Shutting down card reader backend"); - eam_io_fini(); - } - - if (!iidxhook9_config_io.disable_bio2_emu) { - log_misc("Shutting down IIDX IO backend"); - iidx_io_fini(); - } - - if (!iidxhook9_config_io.disable_file_hooks) { - memfile_hook_fini(); - } - - log_server_fini(); - - return result; -} - -static void pre_hook() -{ - log_info("-------------------------------------------------------------"); - log_info("------------------ Begin iidxhook pre_hook ------------------"); - log_info("-------------------------------------------------------------"); - - if (!load_configs()) { - exit(EXIT_FAILURE); - } - - // asio hooks - if (config_asio.force_asio) { - SetEnvironmentVariable("SOUND_OUTPUT_DEVICE", "asio"); - } else if (config_asio.force_wasapi) { - SetEnvironmentVariable("SOUND_OUTPUT_DEVICE", "wasapi"); - } - - if (iidxhook9_config_io.disable_cams) { - // this disables the entire camera subsystem - // useful for skipping the camera error entierly - SetEnvironmentVariable("CONNECT_CAMERA", "0"); - } - - log_info("-------------------------------------------------------------"); - log_info("------------------- End iidxhook pre_hook -------------------"); - log_info("-------------------------------------------------------------"); -} - -/** - * Hook library HV+ - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - if (avs_is_active()) { - // if AVS is loaded, we're likely too late to be a prehook - // so we warn the user - // and switch the current logging context to AVS so it shows up in logs - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - log_warning("iidxhook9 is designed to be used as a prehook"); - log_warning("please ensure that it is being loaded with -B"); - log_fatal("cya l8r in the prehook :3"); - } else { - // we can't log to external in DllMain (AVS) as we're a prehook - // later during my_dll_entry_init, log_server_init is called - // which sets swaps the main log write to that instead - log_to_writer(log_writer_file, stdout); - } - - pre_hook(); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/iidxhook9/fs-hook.c b/src/main/iidxhook9/fs-hook.c index b7e0df2d..cca7a7c8 100644 --- a/src/main/iidxhook9/fs-hook.c +++ b/src/main/iidxhook9/fs-hook.c @@ -5,11 +5,12 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "iidxhook9/fs-hook.h" -#include "util/log.h" #include "util/str.h" static void *(*real_avs_fs_mount)(const char *dest, const char *src, const char *fs_type, const char *options); diff --git a/src/main/iidxhook9/iidxhook9.c b/src/main/iidxhook9/iidxhook9.c new file mode 100644 index 00000000..0f488845 --- /dev/null +++ b/src/main/iidxhook9/iidxhook9.c @@ -0,0 +1,263 @@ +#define LOG_MODULE "iidxhook9" + +#include + +#include +#include +#include +#include + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/config-adapter.h" +#include "hooklib/memfile.h" +#include "hooklib/rs232.h" +#include "hooklib/setupapi.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/iidx.h" + +#include "iidxhook-util/acio.h" + +#include "bio2emu/emu.h" + +#include "bio2emu-iidx/bi2a.h" + +#include "iidxhook9/config-io.h" +#include "iidxhook9/fs-hook.h" + +#include "camhook/cam.h" +#include "camhook/config-cam.h" + +#include "asio/asio-reghook.h" +#include "asio/config-asio.h" +#include "d3d9exhook/d3d9ex.h" +#include "dinput/dinput.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/cmdline.h" +#include "util/str.h" + +static struct iidxhook9_config_io iidxhook9_config_io; +static struct camhook_config_cam config_cam; +static struct asiohook_config_asio config_asio; +static struct hooklib_config_adapter config_adapter; +static struct d3d9exhook_config_gfx config_gfx; + +static struct bio2emu_port bio2_emu = { + .port = "COM4", + .wport = L"COM4", + .dispatcher = bio2_emu_bi2a_dispatch_request, +}; + +static module_io_t *iidxhook_module_io_iidx; +static module_io_t *iidxhook_module_io_eam; + +static void _iidxhook9_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _iidxhook9_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void load_configs(const bt_core_config_t *config) +{ + iidxhook9_config_io_get(config, &iidxhook9_config_io); + + camhook_config_cam_get(config, &config_cam, 2, true); + + d3d9exhook_config_gfx_get(config, &config_gfx); + + hooklib_config_adapter_get(config, &config_adapter); + asiohook_config_asio_get(config, &config_asio); +} + +static bool _iidxhook9_pre_avs_init(const bt_core_config_t *config) +{ + load_configs(config); + + // asio hooks + if (config_asio.force_asio) { + SetEnvironmentVariable("SOUND_OUTPUT_DEVICE", "asio"); + } else if (config_asio.force_wasapi) { + SetEnvironmentVariable("SOUND_OUTPUT_DEVICE", "wasapi"); + } + + if (iidxhook9_config_io.disable_cams) { + // this disables the entire camera subsystem + // useful for skipping the camera error entierly + SetEnvironmentVariable("CONNECT_CAMERA", "0"); + } + + return true; +} + +static bool +_iidxhook9_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + log_info("iidxhook for Heroic Verse, Bistrover, Cast Hour and Resident"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + // reload configs again so they get logged through avs as well + // (so we get a copy of them in the -Y logfile) + load_configs(config); + + d3d9ex_configure(&config_gfx); + d3d9ex_hook_init(); + + acp_hook_init(); + adapter_hook_init(); + dinput_init(); + + /* Start up IIDXIO.DLL */ + if (!iidxhook9_config_io.disable_bio2_emu) { + log_info("Starting IIDX IO backend"); + + _iidxhook9_io_iidx_init(&iidxhook_module_io_iidx); + + if (!bt_io_iidx_init()) { + log_fatal("Initializing IIDX IO backend failed"); + } + } + + /* Start up EAMIO.DLL */ + if (!iidxhook9_config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + _iidxhook9_io_eam_init(&iidxhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + } + + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + iohook_push_handler(bio2emu_port_dispatch_irp); + + if (!iidxhook9_config_io.disable_file_hooks) { + memfile_hook_init(); + iohook_push_handler(memfile_hook_dispatch_irp); + + // game uses this file to determine what mode to put the cab in + // the default depends on a value embedded in the dll + if (iidxhook9_config_io.lightning_mode) { + memfile_hook_add_fd("d:\\\\001rom.txt", ABSOLUTE_MATCH, "TDJ", 3); + } else { + memfile_hook_add_fd("d:\\\\001rom.txt", ABSOLUTE_MATCH, "LDJ", 3); + } + + // redirect F:\ drive to vfs (used for video recording) + iidxhook9_fs_hooks_init(); + } + + rs232_hook_init(); + rs232_hook_limit_hooks(); + + if (!iidxhook9_config_io.disable_bio2_emu) { + if (!iidxhook9_config_io.lightning_mode) { + bio2emu_init(); + bio2_emu_bi2a_set_tt_multiplier(iidxhook9_config_io.tt_multiplier); + bio2_emu_bi2a_init( + &bio2_emu, iidxhook9_config_io.disable_poll_limiter); + } + } + + if (!iidxhook9_config_io.disable_card_reader_emu) { + if (iidxhook9_config_io.lightning_mode) { + // TDJ mode expects 1.7.0 readers + iidxhook_util_acio_override_version(v170); + } + + iidxhook_util_acio_init(false); + } + + // camera hooks + if (!config_cam.disable_emu) { + camhook_set_version(CAMHOOK_VERSION_NEW); + camhook_init(&config_cam); + } + + adapter_hook_override(config_adapter.override_ip); + + // asio hooks + if (config_asio.force_asio) { + asio_reghook_init("XONAR SOUND CARD(64)", config_asio.replacement_name); + } + + return true; +} + +static void _iidxhook9_main_fini() +{ + if (!config_cam.disable_emu) { + camhook_fini(); + } + + if (!iidxhook9_config_io.disable_card_reader_emu) { + log_misc("Shutting down card reader backend"); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&iidxhook_module_io_eam); + } + + if (!iidxhook9_config_io.disable_bio2_emu) { + log_misc("Shutting down IIDX IO backend"); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&iidxhook_module_io_iidx); + } + + if (!iidxhook9_config_io.disable_file_hooks) { + memfile_hook_fini(); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.pre_avs_init = _iidxhook9_pre_avs_init; + api->v1.main_init = _iidxhook9_main_init; + api->v1.main_fini = _iidxhook9_main_fini; +} \ No newline at end of file diff --git a/src/main/iidxhook9/iidxhook9.def b/src/main/iidxhook9/iidxhook9.def index 32f7f78a..d0343c6f 100644 --- a/src/main/iidxhook9/iidxhook9.def +++ b/src/main/iidxhook9/iidxhook9.def @@ -2,3 +2,9 @@ LIBRARY iidxhook9 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/iidxhook9/iidxhook9.h b/src/main/iidxhook9/iidxhook9.h new file mode 100644 index 00000000..539d2398 --- /dev/null +++ b/src/main/iidxhook9/iidxhook9.h @@ -0,0 +1,9 @@ +#ifndef IIDXHOOK9_H +#define IIDXHOOK9_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/iidxio-bio2/Module.mk b/src/main/iidxio-bio2/Module.mk index 09632c21..e03d04b5 100644 --- a/src/main/iidxio-bio2/Module.mk +++ b/src/main/iidxio-bio2/Module.mk @@ -2,12 +2,18 @@ dlls += iidxio-bio2 ldflags_iidxio-bio2 := \ -lsetupapi \ + -lws2_32 \ libs_iidxio-bio2 := \ + core \ aciodrv \ bio2drv \ - cconfig \ util \ + iface \ + module \ + iface-io \ + iface-core \ + security \ src_iidxio-bio2 := \ iidxio.c \ diff --git a/src/main/iidxio-bio2/iidxio-bio2.def b/src/main/iidxio-bio2/iidxio-bio2.def index 403900d7..c34605ff 100644 --- a/src/main/iidxio-bio2/iidxio-bio2.def +++ b/src/main/iidxio-bio2/iidxio-bio2.def @@ -1,18 +1,24 @@ LIBRARY iidxio EXPORTS - iidx_io_ep1_send - iidx_io_ep1_set_deck_lights - iidx_io_ep1_set_panel_lights - iidx_io_ep1_set_top_lamps - iidx_io_ep1_set_top_neons - iidx_io_ep2_get_keys - iidx_io_ep2_get_panel - iidx_io_ep2_get_sys - iidx_io_ep2_get_slider - iidx_io_ep2_get_turntable - iidx_io_ep2_recv - iidx_io_ep3_write_16seg - iidx_io_fini - iidx_io_init - iidx_io_set_loggers + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_configure_do + bt_module_io_iidx_api_get + + ; Direct API + bt_io_iidx_init + bt_io_iidx_fini + bt_io_iidx_ep1_deck_lights_set + bt_io_iidx_ep1_panel_lights_set + bt_io_iidx_ep1_top_lamps_set + bt_io_iidx_ep1_top_neons_set + bt_io_iidx_ep1_send + bt_io_iidx_ep2_recv + bt_io_iidx_ep2_turntable_get + bt_io_iidx_ep2_slider_get + bt_io_iidx_ep2_sys_get + bt_io_iidx_ep2_panel_get + bt_io_iidx_ep2_keys_get + bt_io_iidx_ep3_16seg_send diff --git a/src/main/iidxio-bio2/iidxio.c b/src/main/iidxio-bio2/iidxio.c index 2bca0dcd..e885c0d5 100644 --- a/src/main/iidxio-bio2/iidxio.c +++ b/src/main/iidxio-bio2/iidxio.c @@ -1,32 +1,34 @@ -#include - #define LOG_MODULE "iidxio-bio2" +#include + #include #include #include #include #include -#include "bemanitools/glue.h" -#include "bemanitools/iidxio.h" +#include "aciodrv/device.h" -#include "cconfig/cconfig-main.h" +#include "api/core/config.h" +#include "api/core/log.h" +#include "api/core/thread.h" -#include "aciodrv/device.h" #include "bio2drv/bi2a-iidx.h" -#include "bio2drv/config-bio2.h" +#include "bio2drv/config.h" #include "bio2drv/detect.h" -#define log_misc(...) iidx_io_log_misc(LOG_MODULE, __VA_ARGS__) -#define log_info(...) iidx_io_log_info(LOG_MODULE, __VA_ARGS__) -#define log_warning(...) iidx_io_log_warning(LOG_MODULE, __VA_ARGS__) -#define log_fatal(...) iidx_io_log_fatal(LOG_MODULE, __VA_ARGS__) +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/configure.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/io/iidx.h" -static log_formatter_t iidx_io_log_misc; -static log_formatter_t iidx_io_log_info; -static log_formatter_t iidx_io_log_warning; -static log_formatter_t iidx_io_log_fatal; +static bio2drv_config_t _iidxio_bio2_config; static char autodetect_buffer[512]; @@ -40,6 +42,9 @@ static struct bi2a_iidx_state_out pout_ready; static struct aciodrv_device_ctx *bio2_device_ctx; +bool bt_io_iidx_ep1_send(void); +bool bt_io_iidx_ep2_recv(void); + static bool _bio2_iidx_io_poll( const struct bi2a_iidx_state_out *pout, struct bi2a_iidx_state_in *pin) { @@ -58,51 +63,11 @@ static bool _bio2_iidx_io_poll( return true; } -void iidx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +bool bt_io_iidx_init() { - iidx_io_log_misc = misc; - iidx_io_log_info = info; - iidx_io_log_warning = warning; - iidx_io_log_fatal = fatal; + const char *selected_port = _iidxio_bio2_config.port; - bio2drv_set_loggers(misc, info, warning, fatal); -} - -bool iidx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) -{ - struct cconfig *config; - struct bio2drv_config_bio2 config_bio2; - - config = cconfig_init(); - - bio2drv_config_bio2_init(config); - - if (!cconfig_main_config_init( - config, - "--bio2-config", - "iidxio-bio2.conf", - "--help", - "-h", - "iidxio-bio2", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - bio2drv_config_bio2_get(&config_bio2, config); - - cconfig_finit(config); - - const char *selected_port = config_bio2.port; - - if (config_bio2.autodetect) { + if (_iidxio_bio2_config.autodetect) { log_info("Attempting autodetect"); if (bio2drv_detect( @@ -117,7 +82,7 @@ bool iidx_io_init( } // BIO2's cannot share a bus with anything else, so use device directly - bio2_device_ctx = aciodrv_device_open_path(selected_port, config_bio2.baud); + bio2_device_ctx = aciodrv_device_open_path(selected_port, _iidxio_bio2_config.baud); if (bio2_device_ctx == NULL) { log_info("Opening BIO2 device on [%s] failed", selected_port); @@ -169,14 +134,14 @@ bool iidx_io_init( return running; } -void iidx_io_fini(void) +void bt_io_iidx_fini(void) { // Pushing some final state before closing the IO to the actual outputs, // e.g. lights on/off can be a bit finicky. Do a few polls to // "enforce"/flush this final state for (uint8_t i = 0; i < 3; i++) { - iidx_io_ep1_send(); - iidx_io_ep2_recv(); + bt_io_iidx_ep1_send(); + bt_io_iidx_ep2_recv(); Sleep(10); } @@ -191,59 +156,59 @@ void iidx_io_fini(void) aciodrv_device_close(bio2_device_ctx); } -void iidx_io_ep1_set_deck_lights(uint16_t deck_lights) +void bt_io_iidx_ep1_deck_lights_set(uint16_t deck_lights) { for (uint8_t i = 0; i < sizeof(pout_staging.DECKSW); i++) { pout_staging.DECKSW[i].l_state = (deck_lights & (1 << i)) > 0; } } -void iidx_io_ep1_set_panel_lights(uint8_t panel_lights) +void bt_io_iidx_ep1_panel_lights_set(uint8_t panel_lights) { pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_START_P1].l_state = - (panel_lights & (1 << IIDX_IO_PANEL_P1_START)) > 0; + (panel_lights & (1 << BT_IO_IIDX_PANEL_P1_START)) > 0; pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_START_P2].l_state = - (panel_lights & (1 << IIDX_IO_PANEL_P2_START)) > 0; + (panel_lights & (1 << BT_IO_IIDX_PANEL_P2_START)) > 0; pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_VEFX].l_state = - (panel_lights & (1 << IIDX_IO_PANEL_VEFX)) > 0; + (panel_lights & (1 << BT_IO_IIDX_PANEL_VEFX)) > 0; pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_EFFECT].l_state = - (panel_lights & (1 << IIDX_IO_PANEL_EFFECT)) > 0; + (panel_lights & (1 << BT_IO_IIDX_PANEL_EFFECT)) > 0; } -void iidx_io_ep1_set_top_lamps(uint8_t top_lamps) +void bt_io_iidx_ep1_top_lamps_set(uint8_t top_lamps) { pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_RED].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_RED)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_RED)) > 0; pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_YELLOW].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_YELLOW)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_YELLOW)) > 0; pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_GREEN].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_GREEN)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_GREEN)) > 0; pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_BLUE].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_BLUE)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_BLUE)) > 0; pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_RED].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_RED)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_LEFT_RED)) > 0; pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_YELLOW].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_YELLOW)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_LEFT_YELLOW)) > 0; pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_GREEN].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_GREEN)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_LEFT_GREEN)) > 0; pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_BLUE].l_state = - (top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_BLUE)) > 0; + (top_lamps & (1 << BT_IO_IIDX_TOP_LAMP_LEFT_BLUE)) > 0; } -void iidx_io_ep1_set_top_neons(bool top_neons) +void bt_io_iidx_ep1_top_neons_set(bool top_neons) { pout_staging.NEONLAMP.l_state = top_neons; } -bool iidx_io_ep1_send(void) +bool bt_io_iidx_ep1_send(void) { memcpy(&pout_ready, &pout_staging, sizeof(struct bi2a_iidx_state_out)); return true; } -bool iidx_io_ep2_recv(void) +bool bt_io_iidx_ep2_recv(void) { if (!_bio2_iidx_io_poll(&pout_ready, &pin_cur)) { return false; @@ -252,7 +217,7 @@ bool iidx_io_ep2_recv(void) return true; } -uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) +uint8_t bt_io_iidx_ep2_turntable_get(uint8_t player_no) { switch (player_no) { case 0: @@ -264,7 +229,7 @@ uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) } } -uint8_t iidx_io_ep2_get_slider(uint8_t slider_no) +uint8_t bt_io_iidx_ep2_slider_get(uint8_t slider_no) { switch (slider_no) { case 0: @@ -282,80 +247,122 @@ uint8_t iidx_io_ep2_get_slider(uint8_t slider_no) } } -uint8_t iidx_io_ep2_get_sys(void) +uint8_t bt_io_iidx_ep2_sys_get(void) { uint8_t state; state = 0; if (pin_cur.SYSTEM.v_test) { - state |= (1 << IIDX_IO_SYS_TEST); + state |= (1 << BT_IO_IIDX_SYS_TEST); } if (pin_cur.SYSTEM.v_service) { - state |= (1 << IIDX_IO_SYS_SERVICE); + state |= (1 << BT_IO_IIDX_SYS_SERVICE); } if (pin_cur.SYSTEM.v_coin) { - state |= (1 << IIDX_IO_SYS_COIN); + state |= (1 << BT_IO_IIDX_SYS_COIN); } return state; } -uint8_t iidx_io_ep2_get_panel(void) +uint8_t bt_io_iidx_ep2_panel_get(void) { uint8_t state; state = 0; if (pin_cur.PANEL.y_start1) { - state |= (1 << IIDX_IO_PANEL_P1_START); + state |= (1 << BT_IO_IIDX_PANEL_P1_START); } if (pin_cur.PANEL.y_start2) { - state |= (1 << IIDX_IO_PANEL_P2_START); + state |= (1 << BT_IO_IIDX_PANEL_P2_START); } if (pin_cur.PANEL.y_vefx) { - state |= (1 << IIDX_IO_PANEL_VEFX); + state |= (1 << BT_IO_IIDX_PANEL_VEFX); } if (pin_cur.PANEL.y_effect) { - state |= (1 << IIDX_IO_PANEL_EFFECT); + state |= (1 << BT_IO_IIDX_PANEL_EFFECT); } return state; } -uint16_t iidx_io_ep2_get_keys(void) +uint16_t bt_io_iidx_ep2_keys_get(void) { uint16_t state; state = 0; - state |= ((pin_cur.P1SW1.b_val > 0) << IIDX_IO_KEY_P1_1); - state |= ((pin_cur.P1SW2.b_val > 0) << IIDX_IO_KEY_P1_2); - state |= ((pin_cur.P1SW3.b_val > 0) << IIDX_IO_KEY_P1_3); - state |= ((pin_cur.P1SW4.b_val > 0) << IIDX_IO_KEY_P1_4); - state |= ((pin_cur.P1SW5.b_val > 0) << IIDX_IO_KEY_P1_5); - state |= ((pin_cur.P1SW6.b_val > 0) << IIDX_IO_KEY_P1_6); - state |= ((pin_cur.P1SW7.b_val > 0) << IIDX_IO_KEY_P1_7); - - state |= ((pin_cur.P2SW1.b_val > 0) << IIDX_IO_KEY_P2_1); - state |= ((pin_cur.P2SW2.b_val > 0) << IIDX_IO_KEY_P2_2); - state |= ((pin_cur.P2SW3.b_val > 0) << IIDX_IO_KEY_P2_3); - state |= ((pin_cur.P2SW4.b_val > 0) << IIDX_IO_KEY_P2_4); - state |= ((pin_cur.P2SW5.b_val > 0) << IIDX_IO_KEY_P2_5); - state |= ((pin_cur.P2SW6.b_val > 0) << IIDX_IO_KEY_P2_6); - state |= ((pin_cur.P2SW7.b_val > 0) << IIDX_IO_KEY_P2_7); + state |= ((pin_cur.P1SW1.b_val > 0) << BT_IO_IIDX_KEY_P1_1); + state |= ((pin_cur.P1SW2.b_val > 0) << BT_IO_IIDX_KEY_P1_2); + state |= ((pin_cur.P1SW3.b_val > 0) << BT_IO_IIDX_KEY_P1_3); + state |= ((pin_cur.P1SW4.b_val > 0) << BT_IO_IIDX_KEY_P1_4); + state |= ((pin_cur.P1SW5.b_val > 0) << BT_IO_IIDX_KEY_P1_5); + state |= ((pin_cur.P1SW6.b_val > 0) << BT_IO_IIDX_KEY_P1_6); + state |= ((pin_cur.P1SW7.b_val > 0) << BT_IO_IIDX_KEY_P1_7); + + state |= ((pin_cur.P2SW1.b_val > 0) << BT_IO_IIDX_KEY_P2_1); + state |= ((pin_cur.P2SW2.b_val > 0) << BT_IO_IIDX_KEY_P2_2); + state |= ((pin_cur.P2SW3.b_val > 0) << BT_IO_IIDX_KEY_P2_3); + state |= ((pin_cur.P2SW4.b_val > 0) << BT_IO_IIDX_KEY_P2_4); + state |= ((pin_cur.P2SW5.b_val > 0) << BT_IO_IIDX_KEY_P2_5); + state |= ((pin_cur.P2SW6.b_val > 0) << BT_IO_IIDX_KEY_P2_6); + state |= ((pin_cur.P2SW7.b_val > 0) << BT_IO_IIDX_KEY_P2_7); return state; } -bool iidx_io_ep3_write_16seg(const char *text) +bool bt_io_iidx_ep3_16seg_send(const char *text) { memcpy(pout_staging.SEG16, text, sizeof(pout_staging.SEG16)); return true; } + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +bool bt_module_configure_do(const bt_core_config_t *config) +{ + bio2drv_config_bio2_get(config, &_iidxio_bio2_config); + + return true; +} + +void bt_module_io_iidx_api_get(bt_io_iidx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_iidx_init; + api->v1.fini = bt_io_iidx_fini; + api->v1.ep1_deck_lights_set = bt_io_iidx_ep1_deck_lights_set; + api->v1.ep1_panel_lights_set = bt_io_iidx_ep1_panel_lights_set; + api->v1.ep1_top_lamps_set = bt_io_iidx_ep1_top_lamps_set; + api->v1.ep1_top_neons_set = bt_io_iidx_ep1_top_neons_set; + api->v1.ep1_send = bt_io_iidx_ep1_send; + api->v1.ep2_recv = bt_io_iidx_ep2_recv; + api->v1.ep2_turntable_get = bt_io_iidx_ep2_turntable_get; + api->v1.ep2_slider_get = bt_io_iidx_ep2_slider_get; + api->v1.ep2_sys_get = bt_io_iidx_ep2_sys_get; + api->v1.ep2_panel_get = bt_io_iidx_ep2_panel_get; + api->v1.ep2_keys_get = bt_io_iidx_ep2_keys_get; + api->v1.ep3_16seg_send = bt_io_iidx_ep3_16seg_send; +} diff --git a/src/main/iidxio-ezusb/Module.mk b/src/main/iidxio-ezusb/Module.mk index ce9982c2..7f69a144 100644 --- a/src/main/iidxio-ezusb/Module.mk +++ b/src/main/iidxio-ezusb/Module.mk @@ -5,10 +5,15 @@ ldflags_iidxio-ezusb := \ -lsetupapi \ libs_iidxio-ezusb := \ + core \ ezusb \ ezusb2 \ ezusb-iidx \ util \ + iface \ + module \ + iface-io \ + iface-core \ src_iidxio-ezusb := \ iidxio.c \ diff --git a/src/main/iidxio-ezusb/iidxio-ezusb.def b/src/main/iidxio-ezusb/iidxio-ezusb.def index 403900d7..848c5747 100644 --- a/src/main/iidxio-ezusb/iidxio-ezusb.def +++ b/src/main/iidxio-ezusb/iidxio-ezusb.def @@ -1,18 +1,23 @@ LIBRARY iidxio EXPORTS - iidx_io_ep1_send - iidx_io_ep1_set_deck_lights - iidx_io_ep1_set_panel_lights - iidx_io_ep1_set_top_lamps - iidx_io_ep1_set_top_neons - iidx_io_ep2_get_keys - iidx_io_ep2_get_panel - iidx_io_ep2_get_sys - iidx_io_ep2_get_slider - iidx_io_ep2_get_turntable - iidx_io_ep2_recv - iidx_io_ep3_write_16seg - iidx_io_fini - iidx_io_init - iidx_io_set_loggers + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_iidx_api_get + + ; Direct API + bt_io_iidx_init + bt_io_iidx_fini + bt_io_iidx_ep1_deck_lights_set + bt_io_iidx_ep1_panel_lights_set + bt_io_iidx_ep1_top_lamps_set + bt_io_iidx_ep1_top_neons_set + bt_io_iidx_ep1_send + bt_io_iidx_ep2_recv + bt_io_iidx_ep2_turntable_get + bt_io_iidx_ep2_slider_get + bt_io_iidx_ep2_sys_get + bt_io_iidx_ep2_panel_get + bt_io_iidx_ep2_keys_get + bt_io_iidx_ep3_16seg_send diff --git a/src/main/iidxio-ezusb/iidxio.c b/src/main/iidxio-ezusb/iidxio.c index a6a20590..e1e91957 100644 --- a/src/main/iidxio-ezusb/iidxio.c +++ b/src/main/iidxio-ezusb/iidxio.c @@ -1,3 +1,5 @@ +#define LOG_MODULE "iidxio-ezusb" + // clang-format off // Don't format because the order is important here #include @@ -8,7 +10,8 @@ #include #include -#include "bemanitools/iidxio.h" +#include "api/core/log.h" +#include "api/core/thread.h" #include "ezusb/ezusb.h" #include "ezusb/ezusbsys2.h" @@ -17,18 +20,15 @@ #include "ezusb-iidx/fpga.h" #include "ezusb-iidx/seg16-cmd.h" -#include "util/fs.h" -#include "util/time.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" -#define log_misc(...) iidx_io_log_misc("iidxio-ezusb", __VA_ARGS__) -#define log_info(...) iidx_io_log_info("iidxio-ezusb", __VA_ARGS__) -#define log_warning(...) iidx_io_log_warning("iidxio-ezusb", __VA_ARGS__) -#define log_fatal(...) iidx_io_log_fatal("iidxio-ezusb", __VA_ARGS__) +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/io/iidx.h" -static log_formatter_t iidx_io_log_misc; -static log_formatter_t iidx_io_log_info; -static log_formatter_t iidx_io_log_warning; -static log_formatter_t iidx_io_log_fatal; +#include "util/fs.h" +#include "util/time.h" static HANDLE iidx_io_ezusb_handle; @@ -36,22 +36,10 @@ static struct ezusb_iidx_msg_interrupt_read_packet iidx_io_ezusb_read_packet; static struct ezusb_iidx_msg_interrupt_write_packet iidx_io_ezusb_write_packet; static bool iidxio_io_ezusb_16seg_rts; -void iidx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - iidx_io_log_misc = misc; - iidx_io_log_info = info; - iidx_io_log_warning = warning; - iidx_io_log_fatal = fatal; -} +bool bt_io_iidx_ep1_send(void); +bool bt_io_iidx_ep2_recv(void); -bool iidx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_iidx_init() { struct ezusb_ident ident; @@ -81,20 +69,20 @@ bool iidx_io_init( // Random data returned by device, likely not properly initalized on device // side Triggers random inputs and lights Flush that by execute a few polls for (int i = 0; i < 10; i++) { - iidx_io_ep2_recv(); + bt_io_iidx_ep2_recv(); } return true; } -void iidx_io_fini(void) +void bt_io_iidx_fini(void) { // Pushing some final state before closing the IO to the actual outputs, // e.g. lights on/off can be a bit finicky. Do a few polls to // "enforce"/flush this final state for (uint8_t i = 0; i < 5; i++) { - iidx_io_ep1_send(); - iidx_io_ep2_recv(); + bt_io_iidx_ep1_send(); + bt_io_iidx_ep2_recv(); Sleep(10); } @@ -107,27 +95,27 @@ void iidx_io_fini(void) the neons bit into an unused start btns light. The entire 32-bit word is then sent to geninput for output light mapping. */ -void iidx_io_ep1_set_deck_lights(uint16_t deck_lights) +void bt_io_iidx_ep1_deck_lights_set(uint16_t deck_lights) { iidx_io_ezusb_write_packet.deck_lights = deck_lights; } -void iidx_io_ep1_set_panel_lights(uint8_t panel_lights) +void bt_io_iidx_ep1_panel_lights_set(uint8_t panel_lights) { iidx_io_ezusb_write_packet.panel_lights = panel_lights; } -void iidx_io_ep1_set_top_lamps(uint8_t top_lamps) +void bt_io_iidx_ep1_top_lamps_set(uint8_t top_lamps) { iidx_io_ezusb_write_packet.top_lamps = top_lamps; } -void iidx_io_ep1_set_top_neons(bool top_neons) +void bt_io_iidx_ep1_top_neons_set(bool top_neons) { iidx_io_ezusb_write_packet.top_neons = top_neons ? 1 : 0; } -bool iidx_io_ep1_send(void) +bool bt_io_iidx_ep1_send(void) { BULK_TRANSFER_CONTROL transfer; uint32_t outpkt; @@ -154,7 +142,7 @@ bool iidx_io_ep1_send(void) } } -bool iidx_io_ep2_recv(void) +bool bt_io_iidx_ep2_recv(void) { if (!ezusb_iidx_interrupt_read( iidx_io_ezusb_handle, &iidx_io_ezusb_read_packet)) { @@ -177,7 +165,7 @@ bool iidx_io_ep2_recv(void) return true; } -uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) +uint8_t bt_io_iidx_ep2_turntable_get(uint8_t player_no) { switch (player_no) { case 0: @@ -189,7 +177,7 @@ uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) } } -uint8_t iidx_io_ep2_get_slider(uint8_t slider_no) +uint8_t bt_io_iidx_ep2_slider_get(uint8_t slider_no) { switch (slider_no) { case 0: @@ -207,23 +195,23 @@ uint8_t iidx_io_ep2_get_slider(uint8_t slider_no) } } -uint8_t iidx_io_ep2_get_sys(void) +uint8_t bt_io_iidx_ep2_sys_get(void) { return (((~iidx_io_ezusb_read_packet.inverted_pad) >> 28) & 0x03) | ((((~iidx_io_ezusb_read_packet.inverted_pad) >> 22) & 0x01) << 2); } -uint8_t iidx_io_ep2_get_panel(void) +uint8_t bt_io_iidx_ep2_panel_get(void) { return ((~iidx_io_ezusb_read_packet.inverted_pad) >> 24) & 0x0F; } -uint16_t iidx_io_ep2_get_keys(void) +uint16_t bt_io_iidx_ep2_keys_get(void) { return ((~iidx_io_ezusb_read_packet.inverted_pad) >> 8) & 0x3FFF; } -bool iidx_io_ep3_write_16seg(const char *text) +bool bt_io_iidx_ep3_16seg_send(const char *text) { struct ezusb_iidx_msg_bulk_packet pkg; @@ -245,3 +233,33 @@ bool iidx_io_ep3_write_16seg(const char *text) return true; } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_iidx_api_get(bt_io_iidx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_iidx_init; + api->v1.fini = bt_io_iidx_fini; + api->v1.ep1_deck_lights_set = bt_io_iidx_ep1_deck_lights_set; + api->v1.ep1_panel_lights_set = bt_io_iidx_ep1_panel_lights_set; + api->v1.ep1_top_lamps_set = bt_io_iidx_ep1_top_lamps_set; + api->v1.ep1_top_neons_set = bt_io_iidx_ep1_top_neons_set; + api->v1.ep1_send = bt_io_iidx_ep1_send; + api->v1.ep2_recv = bt_io_iidx_ep2_recv; + api->v1.ep2_turntable_get = bt_io_iidx_ep2_turntable_get; + api->v1.ep2_slider_get = bt_io_iidx_ep2_slider_get; + api->v1.ep2_sys_get = bt_io_iidx_ep2_sys_get; + api->v1.ep2_panel_get = bt_io_iidx_ep2_panel_get; + api->v1.ep2_keys_get = bt_io_iidx_ep2_keys_get; + api->v1.ep3_16seg_send = bt_io_iidx_ep3_16seg_send; +} diff --git a/src/main/iidxio-ezusb2/Module.mk b/src/main/iidxio-ezusb2/Module.mk index f1f19631..15c79e82 100644 --- a/src/main/iidxio-ezusb2/Module.mk +++ b/src/main/iidxio-ezusb2/Module.mk @@ -5,10 +5,15 @@ ldflags_iidxio-ezusb2 := \ -lsetupapi \ libs_iidxio-ezusb2 := \ + core \ ezusb2 \ ezusb \ ezusb2-iidx \ util \ + iface \ + module \ + iface-io \ + iface-core \ src_iidxio-ezusb2 := \ iidxio.c \ diff --git a/src/main/iidxio-ezusb2/iidxio-ezusb2.def b/src/main/iidxio-ezusb2/iidxio-ezusb2.def index 403900d7..848c5747 100644 --- a/src/main/iidxio-ezusb2/iidxio-ezusb2.def +++ b/src/main/iidxio-ezusb2/iidxio-ezusb2.def @@ -1,18 +1,23 @@ LIBRARY iidxio EXPORTS - iidx_io_ep1_send - iidx_io_ep1_set_deck_lights - iidx_io_ep1_set_panel_lights - iidx_io_ep1_set_top_lamps - iidx_io_ep1_set_top_neons - iidx_io_ep2_get_keys - iidx_io_ep2_get_panel - iidx_io_ep2_get_sys - iidx_io_ep2_get_slider - iidx_io_ep2_get_turntable - iidx_io_ep2_recv - iidx_io_ep3_write_16seg - iidx_io_fini - iidx_io_init - iidx_io_set_loggers + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_iidx_api_get + + ; Direct API + bt_io_iidx_init + bt_io_iidx_fini + bt_io_iidx_ep1_deck_lights_set + bt_io_iidx_ep1_panel_lights_set + bt_io_iidx_ep1_top_lamps_set + bt_io_iidx_ep1_top_neons_set + bt_io_iidx_ep1_send + bt_io_iidx_ep2_recv + bt_io_iidx_ep2_turntable_get + bt_io_iidx_ep2_slider_get + bt_io_iidx_ep2_sys_get + bt_io_iidx_ep2_panel_get + bt_io_iidx_ep2_keys_get + bt_io_iidx_ep3_16seg_send diff --git a/src/main/iidxio-ezusb2/iidxio.c b/src/main/iidxio-ezusb2/iidxio.c index e6292721..a2ff7297 100644 --- a/src/main/iidxio-ezusb2/iidxio.c +++ b/src/main/iidxio-ezusb2/iidxio.c @@ -1,51 +1,36 @@ +#define LOG_MODULE "iidxio-ezusb2" + #include #include #include -#include "bemanitools/iidxio.h" +#include "api/core/log.h" +#include "api/core/thread.h" #include "ezusb/util.h" #include "ezusb2/ezusb2.h" #include "ezusb2-iidx/ezusb2-iidx.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/io/iidx.h" + #include "util/fs.h" #include "util/time.h" #define EZUSB2_FIND_TIMEOUT_MS 10000 -#define log_misc(...) iidx_io_log_misc("iidxio-ezusb2", __VA_ARGS__) -#define log_info(...) iidx_io_log_info("iidxio-ezusb2", __VA_ARGS__) -#define log_warning(...) iidx_io_log_warning("iidxio-ezusb2", __VA_ARGS__) -#define log_fatal(...) iidx_io_log_fatal("iidxio-ezusb2", __VA_ARGS__) - -static log_formatter_t iidx_io_log_misc; -static log_formatter_t iidx_io_log_info; -static log_formatter_t iidx_io_log_warning; -static log_formatter_t iidx_io_log_fatal; - static HANDLE iidx_io_ezusb2_handle; static struct ezusb2_iidx_msg_interrupt_read_packet iidx_io_ezusb2_read_packet; static struct ezusb2_iidx_msg_interrupt_write_packet iidx_io_ezusb2_write_packet; -void iidx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - iidx_io_log_misc = misc; - iidx_io_log_info = info; - iidx_io_log_warning = warning; - iidx_io_log_fatal = fatal; -} - -bool iidx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_iidx_init() { struct ezusb_ident ident; char *device_path; @@ -100,37 +85,33 @@ bool iidx_io_init( } } -void iidx_io_fini(void) +void bt_io_iidx_fini(void) { ezusb2_close(iidx_io_ezusb2_handle); iidx_io_ezusb2_handle = INVALID_HANDLE_VALUE; } -/* Total number of light bits is 33. That's slightly annoying. So, we pack - the neons bit into an unused start btns light. The entire 32-bit word is - then sent to geninput for output light mapping. */ - -void iidx_io_ep1_set_deck_lights(uint16_t deck_lights) +void bt_io_iidx_ep1_deck_lights_set(uint16_t deck_lights) { iidx_io_ezusb2_write_packet.deck_lights = deck_lights; } -void iidx_io_ep1_set_panel_lights(uint8_t panel_lights) +void bt_io_iidx_ep1_panel_lights_set(uint8_t panel_lights) { iidx_io_ezusb2_write_packet.panel_lights = panel_lights; } -void iidx_io_ep1_set_top_lamps(uint8_t top_lamps) +void bt_io_iidx_ep1_top_lamps_set(uint8_t top_lamps) { iidx_io_ezusb2_write_packet.top_lamps = top_lamps; } -void iidx_io_ep1_set_top_neons(bool top_neons) +void bt_io_iidx_ep1_top_neons_set(bool top_neons) { iidx_io_ezusb2_write_packet.top_neons = top_neons ? 1 : 0; } -bool iidx_io_ep1_send(void) +bool bt_io_iidx_ep1_send(void) { if (!ezusb2_iidx_interrupt_write( iidx_io_ezusb2_handle, &iidx_io_ezusb2_write_packet)) { @@ -141,7 +122,7 @@ bool iidx_io_ep1_send(void) } } -bool iidx_io_ep2_recv(void) +bool bt_io_iidx_ep2_recv(void) { if (!ezusb2_iidx_interrupt_read( iidx_io_ezusb2_handle, &iidx_io_ezusb2_read_packet)) { @@ -152,7 +133,7 @@ bool iidx_io_ep2_recv(void) } } -uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) +uint8_t bt_io_iidx_ep2_turntable_get(uint8_t player_no) { switch (player_no) { case 0: @@ -164,7 +145,7 @@ uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) } } -uint8_t iidx_io_ep2_get_slider(uint8_t slider_no) +uint8_t bt_io_iidx_ep2_slider_get(uint8_t slider_no) { switch (slider_no) { case 0: @@ -182,25 +163,55 @@ uint8_t iidx_io_ep2_get_slider(uint8_t slider_no) } } -uint8_t iidx_io_ep2_get_sys(void) +uint8_t bt_io_iidx_ep2_sys_get(void) { return (((~iidx_io_ezusb2_read_packet.inverted_pad) >> 4) & 0x03) | ((((~iidx_io_ezusb2_read_packet.inverted_pad) >> 30) & 1) << 2); } -uint8_t iidx_io_ep2_get_panel(void) +uint8_t bt_io_iidx_ep2_panel_get(void) { return ((~iidx_io_ezusb2_read_packet.inverted_pad) >> 0) & 0x0F; } -uint16_t iidx_io_ep2_get_keys(void) +uint16_t bt_io_iidx_ep2_keys_get(void) { return ((~iidx_io_ezusb2_read_packet.inverted_pad) >> 16) & 0x3FFF; } -bool iidx_io_ep3_write_16seg(const char *text) +bool bt_io_iidx_ep3_16seg_send(const char *text) { /* 16seg writing to device done in ep2 */ memcpy(iidx_io_ezusb2_write_packet.seg16, text, 9); return true; } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_iidx_api_get(bt_io_iidx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_iidx_init; + api->v1.fini = bt_io_iidx_fini; + api->v1.ep1_deck_lights_set = bt_io_iidx_ep1_deck_lights_set; + api->v1.ep1_panel_lights_set = bt_io_iidx_ep1_panel_lights_set; + api->v1.ep1_top_lamps_set = bt_io_iidx_ep1_top_lamps_set; + api->v1.ep1_top_neons_set = bt_io_iidx_ep1_top_neons_set; + api->v1.ep1_send = bt_io_iidx_ep1_send; + api->v1.ep2_recv = bt_io_iidx_ep2_recv; + api->v1.ep2_turntable_get = bt_io_iidx_ep2_turntable_get; + api->v1.ep2_slider_get = bt_io_iidx_ep2_slider_get; + api->v1.ep2_sys_get = bt_io_iidx_ep2_sys_get; + api->v1.ep2_panel_get = bt_io_iidx_ep2_panel_get; + api->v1.ep2_keys_get = bt_io_iidx_ep2_keys_get; + api->v1.ep3_16seg_send = bt_io_iidx_ep3_16seg_send; +} diff --git a/src/main/iidxio/Module.mk b/src/main/iidxio/Module.mk index 33aa7e21..8e66b145 100644 --- a/src/main/iidxio/Module.mk +++ b/src/main/iidxio/Module.mk @@ -4,8 +4,11 @@ ldflags_iidxio := \ -lwinmm libs_iidxio := \ - geninput \ - vefxio \ + iface \ + module \ + iface-io \ + iface-core \ + util \ src_iidxio := \ iidxio.c \ diff --git a/src/main/iidxio/iidxio.c b/src/main/iidxio/iidxio.c index 901c1ba6..71bd11c4 100644 --- a/src/main/iidxio/iidxio.c +++ b/src/main/iidxio/iidxio.c @@ -1,12 +1,4 @@ -/* This is the source code for the IIDXIO.DLL that ships with Bemanitools 5. - - If you want to add on some minor functionality like a custom 16seg display - or a customer slider board then see vefxio. - - If you want to make a completely custom IO board that handles all input and - lighting then you'd be better off writing your own from scratch. Consult - the "bemanitools" header files included by this source file for detailed - information about the API you'll need to implement. */ +#define LOG_MODULE "iidxio" // clang-format off // Don't format because the order is important here @@ -17,9 +9,23 @@ #include #include -#include "bemanitools/iidxio.h" -#include "bemanitools/input.h" -#include "bemanitools/vefxio.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface-io/vefx.h" +#include "iface/input.h" + +#include "main/module/input-ext.h" +#include "main/module/input.h" +#include "main/module/io-ext.h" +#include "main/module/io.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/iidx.h" #define MSEC_PER_NOTCH 8 @@ -92,126 +98,114 @@ static const struct iidx_io_tt_inputs iidx_io_tt_inputs[2] = { IIDX_IO_P2_START}, }; +static module_input_t *_iidx_io_module_input; +static module_io_t *_iidx_io_module_vefx; + static struct iidx_io_tt iidx_io_tt[2]; static uint8_t iidx_io_sys; static uint8_t iidx_io_panel; static uint16_t iidx_io_keys; -/* Uncomment these if you need them. */ +static void _bt_io_iidx_module_input_init(module_input_t **module) +{ + bt_input_api_t api; -#if 0 -static log_formatter_t iidx_io_log_misc; -static log_formatter_t iidx_io_log_info; -static log_formatter_t iidx_io_log_warning; -static log_formatter_t iidx_io_log_fatal; -#endif + module_input_ext_load_and_init("geninput.dll", module); + module_input_api_get(*module, &api); + bt_input_api_set(&api); +} -void iidx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +static void _bt_io_iidx_module_vefx_init(module_io_t **module) { - /* Pass logger functions on to geninput so that it has somewhere to write - its own log output. */ + bt_io_vefx_api_t api; - input_set_loggers(misc, info, warning, fatal); - - /* Pass logger functions on to vefx_io so that it has somewhere to write - its own log output. */ + module_io_ext_load_and_init( + "vefxio.dll", "bt_module_io_vefx_api_get", module); + module_io_api_get(*module, &api); + bt_io_vefx_api_set(&api); +} - vefx_io_set_loggers(misc, info, warning, fatal); +bool bt_io_iidx_init() +{ + bool result; - /* Uncomment this block if you have something you'd like to log. + _bt_io_iidx_module_input_init(&_iidx_io_module_input); + _bt_io_iidx_module_vefx_init(&_iidx_io_module_vefx); - You should probably return false from the appropriate function instead - of calling the fatal logger yourself though. */ + result = bt_io_vefx_init(); -#if 0 - iidx_io_log_misc = misc; - iidx_io_log_info = info; - iidx_io_log_warning = warning; - iidx_io_log_fatal = fatal; -#endif -} + if (!result) { + log_warning("Initializing vefx failed"); + return false; + } -bool iidx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) -{ - vefx_io_init(thread_create, thread_join, thread_destroy); timeBeginPeriod(1); - input_init(thread_create, thread_join, thread_destroy); - mapper_config_load("iidx"); + result = bt_input_init(); + + if (!result) { + log_warning("Initializing input failed"); + return false; + } iidx_io_tt[0].stab_dir = +1; iidx_io_tt[1].stab_dir = +1; - /* Initialize your own IO devices here. Log something and then return - false if the initialization fails. */ - - return true; + return bt_input_mapper_config_load("iidx"); } -void iidx_io_fini(void) +void bt_io_iidx_fini(void) { - /* This function gets called as IIDX shuts down after an Alt-F4. Close your - connections to your IO devices here. */ + bt_input_fini(); + bt_input_api_clear(); + module_input_free(&_iidx_io_module_input); + + bt_io_vefx_fini(); + bt_io_vefx_api_clear(); + module_io_free(&_iidx_io_module_vefx); - input_fini(); - vefx_io_fini(); timeEndPeriod(1); } -/* Total number of light bits is 33. That's slightly annoying. So, we pack - the neons bit into an unused start btns light. The entire 32-bit word is - then sent to geninput for output light mapping. */ - -void iidx_io_ep1_set_deck_lights(uint16_t deck_lights) +void bt_io_iidx_ep1_deck_lights_set(uint16_t deck_lights) { uint8_t i; for (i = 0x00; i < 0x0E; i++) { - mapper_write_light(i, deck_lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(i, deck_lights & (1 << i) ? 255 : 0); } } -void iidx_io_ep1_set_panel_lights(uint8_t panel_lights) +void bt_io_iidx_ep1_panel_lights_set(uint8_t panel_lights) { uint8_t i; for (i = 0x00; i < 0x04; i++) { - mapper_write_light(0x18 + i, panel_lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write( + 0x18 + i, panel_lights & (1 << i) ? 255 : 0); } } -void iidx_io_ep1_set_top_lamps(uint8_t top_lamps) +void bt_io_iidx_ep1_top_lamps_set(uint8_t top_lamps) { uint8_t i; for (i = 0x00; i < 0x08; i++) { - mapper_write_light(0x10 + i, top_lamps & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(0x10 + i, top_lamps & (1 << i) ? 255 : 0); } } -void iidx_io_ep1_set_top_neons(bool top_neons) +void bt_io_iidx_ep1_top_neons_set(bool top_neons) { - mapper_write_light(0x1F, top_neons ? 255 : 0); + bt_input_mapper_light_write(0x1F, top_neons ? 255 : 0); } -bool iidx_io_ep1_send(void) +bool bt_io_iidx_ep1_send(void) { - /* The generic input stack currently initiates lighting sends and input - reads simultaneously, though this might change later. Perform all of our - I/O immediately before reading out the inputs so that the input state is - as fresh as possible. */ - return true; } -bool iidx_io_ep2_recv(void) +bool bt_io_iidx_ep2_recv(void) { uint32_t now; uint64_t pad; @@ -220,8 +214,8 @@ bool iidx_io_ep2_recv(void) /* Update all of our input state here. */ now = timeGetTime(); - pad = (uint64_t) mapper_update(); - vefx_io_recv(&pad); + pad = (uint64_t) bt_input_mapper_update(); + bt_io_vefx_recv(&pad); for (i = 0; i < 2; i++) { iidx_io_tt_update(now, pad, i); @@ -292,10 +286,10 @@ static void iidx_io_tt_update(uint32_t now, uint64_t pad, int i) /* Snapshot analog spinner state as well. */ - iidx_io_tt[i].analog_pos = mapper_read_analog(i); + iidx_io_tt[i].analog_pos = bt_input_mapper_analog_read(i); } -uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) +uint8_t bt_io_iidx_ep2_turntable_get(uint8_t player_no) { if (player_no > 1) { return 0; @@ -304,27 +298,57 @@ uint8_t iidx_io_ep2_get_turntable(uint8_t player_no) return iidx_io_tt[player_no].pos + iidx_io_tt[player_no].analog_pos; } -uint8_t iidx_io_ep2_get_slider(uint8_t slider_no) +uint8_t bt_io_iidx_ep2_slider_get(uint8_t slider_no) { - return vefx_io_get_slider(slider_no); + return bt_io_vefx_slider_get(slider_no); } -uint8_t iidx_io_ep2_get_sys(void) +uint8_t bt_io_iidx_ep2_sys_get(void) { return iidx_io_sys; } -uint8_t iidx_io_ep2_get_panel(void) +uint8_t bt_io_iidx_ep2_panel_get(void) { return iidx_io_panel; } -uint16_t iidx_io_ep2_get_keys(void) +uint16_t bt_io_iidx_ep2_keys_get(void) { return iidx_io_keys; } -bool iidx_io_ep3_write_16seg(const char *text) +bool bt_io_iidx_ep3_16seg_send(const char *text) +{ + return bt_io_vefx_16seg_send(text); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - return vefx_io_write_16seg(text); + bt_core_log_api_set(api); } + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_iidx_api_get(bt_io_iidx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_iidx_init; + api->v1.fini = bt_io_iidx_fini; + api->v1.ep1_deck_lights_set = bt_io_iidx_ep1_deck_lights_set; + api->v1.ep1_panel_lights_set = bt_io_iidx_ep1_panel_lights_set; + api->v1.ep1_top_lamps_set = bt_io_iidx_ep1_top_lamps_set; + api->v1.ep1_top_neons_set = bt_io_iidx_ep1_top_neons_set; + api->v1.ep1_send = bt_io_iidx_ep1_send; + api->v1.ep2_recv = bt_io_iidx_ep2_recv; + api->v1.ep2_turntable_get = bt_io_iidx_ep2_turntable_get; + api->v1.ep2_slider_get = bt_io_iidx_ep2_slider_get; + api->v1.ep2_sys_get = bt_io_iidx_ep2_sys_get; + api->v1.ep2_panel_get = bt_io_iidx_ep2_panel_get; + api->v1.ep2_keys_get = bt_io_iidx_ep2_keys_get; + api->v1.ep3_16seg_send = bt_io_iidx_ep3_16seg_send; +} \ No newline at end of file diff --git a/src/main/iidxio/iidxio.def b/src/main/iidxio/iidxio.def index 403900d7..848c5747 100644 --- a/src/main/iidxio/iidxio.def +++ b/src/main/iidxio/iidxio.def @@ -1,18 +1,23 @@ LIBRARY iidxio EXPORTS - iidx_io_ep1_send - iidx_io_ep1_set_deck_lights - iidx_io_ep1_set_panel_lights - iidx_io_ep1_set_top_lamps - iidx_io_ep1_set_top_neons - iidx_io_ep2_get_keys - iidx_io_ep2_get_panel - iidx_io_ep2_get_sys - iidx_io_ep2_get_slider - iidx_io_ep2_get_turntable - iidx_io_ep2_recv - iidx_io_ep3_write_16seg - iidx_io_fini - iidx_io_init - iidx_io_set_loggers + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_iidx_api_get + + ; Direct API + bt_io_iidx_init + bt_io_iidx_fini + bt_io_iidx_ep1_deck_lights_set + bt_io_iidx_ep1_panel_lights_set + bt_io_iidx_ep1_top_lamps_set + bt_io_iidx_ep1_top_neons_set + bt_io_iidx_ep1_send + bt_io_iidx_ep2_recv + bt_io_iidx_ep2_turntable_get + bt_io_iidx_ep2_slider_get + bt_io_iidx_ep2_sys_get + bt_io_iidx_ep2_panel_get + bt_io_iidx_ep2_keys_get + bt_io_iidx_ep3_16seg_send diff --git a/src/main/iidxiotest/Module.mk b/src/main/iidxiotest/Module.mk index ce0536cf..74870e50 100644 --- a/src/main/iidxiotest/Module.mk +++ b/src/main/iidxiotest/Module.mk @@ -1,8 +1,11 @@ exes += iidxiotest \ libs_iidxiotest := \ - iidxio \ + core \ util \ + module \ + iface-core \ + iface-io \ src_iidxiotest := \ main.c \ diff --git a/src/main/iidxiotest/main.c b/src/main/iidxiotest/main.c index ddd57cf4..d37ddd64 100644 --- a/src/main/iidxiotest/main.c +++ b/src/main/iidxiotest/main.c @@ -1,14 +1,18 @@ +#include + #include #include #include #include -#include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" -#include "bemanitools/iidxio.h" +#include "iface-core/log.h" +#include "iface-io/iidx.h" -#include "util/log.h" -#include "util/thread.h" +#include "module/io-ext.h" static uint8_t _fix_top_lamps_order(uint8_t top_lamps) { @@ -16,58 +20,88 @@ static uint8_t _fix_top_lamps_order(uint8_t top_lamps) out = 0; - out |= ((1 << 0) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_RED) : 0; - out |= ((1 << 1) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_YELLOW) : 0; - out |= ((1 << 2) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_GREEN) : 0; - out |= ((1 << 3) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_BLUE) : 0; + out |= ((1 << 0) & top_lamps) > 0 ? (1 << BT_IO_IIDX_TOP_LAMP_LEFT_RED) : 0; + out |= + ((1 << 1) & top_lamps) > 0 ? (1 << BT_IO_IIDX_TOP_LAMP_LEFT_YELLOW) : 0; + out |= + ((1 << 2) & top_lamps) > 0 ? (1 << BT_IO_IIDX_TOP_LAMP_LEFT_GREEN) : 0; + out |= + ((1 << 3) & top_lamps) > 0 ? (1 << BT_IO_IIDX_TOP_LAMP_LEFT_BLUE) : 0; - out |= ((1 << 4) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_BLUE) : 0; - out |= ((1 << 5) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_GREEN) : 0; out |= - ((1 << 6) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_YELLOW) : 0; - out |= ((1 << 7) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_RED) : 0; + ((1 << 4) & top_lamps) > 0 ? (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_BLUE) : 0; + out |= + ((1 << 5) & top_lamps) > 0 ? (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_GREEN) : 0; + out |= ((1 << 6) & top_lamps) > 0 ? + (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_YELLOW) : + 0; + out |= + ((1 << 7) & top_lamps) > 0 ? (1 << BT_IO_IIDX_TOP_LAMP_RIGHT_RED) : 0; return out; } static void _all_lights_off_shutdown() { - iidx_io_ep1_set_deck_lights(0); - iidx_io_ep1_set_panel_lights(0); - iidx_io_ep1_set_top_lamps(0); - iidx_io_ep1_set_top_neons(false); + bt_io_iidx_ep1_deck_lights_set(0); + bt_io_iidx_ep1_panel_lights_set(0); + bt_io_iidx_ep1_top_lamps_set(0); + bt_io_iidx_ep1_top_neons_set(false); // Depending on the IO, pushing the state to the actual outputs, e.g. lights // on/off can be a bit finicky. Do a few times to "enforce" the state for (uint8_t i = 0; i < 3; i++) { - iidx_io_ep1_send(); + bt_io_iidx_ep1_send(); // Required to handle iidxio-ezusb specific quirks with flushing 16seg // text - iidx_io_ep2_recv(); - iidx_io_ep3_write_16seg(" "); + bt_io_iidx_ep2_recv(); + bt_io_iidx_ep3_16seg_send(" "); Sleep(10); } } +static void _iidxiotest_io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + /** * Tool to test your implementations of iidxio. */ int main(int argc, char **argv) { - log_to_writer(log_writer_stdout, NULL); + module_io_t *module_io_iidx; + + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _iidxiotest_io_iidx_init(&module_io_iidx); - if (!iidx_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) { + if (!bt_io_iidx_init()) { printf("Initializing iidxio failed\n"); + + bt_io_iidx_api_clear(); + module_io_free(&module_io_iidx); + return -1; } printf(">>> Initializing iidxio successful, press enter to continue <<<\n"); if (getchar() != '\n') { + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&module_io_iidx); + return 0; } @@ -89,19 +123,25 @@ int main(int argc, char **argv) uint8_t cnt = 0; bool all_on = false; while (loop) { - if (!iidx_io_ep2_recv()) { + if (!bt_io_iidx_ep2_recv()) { printf("ERROR: Receive ep2 failed\n"); + + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&module_io_iidx); + return -2; } /* get inputs */ - input_sys = iidx_io_ep2_get_sys(); - input_panel = iidx_io_ep2_get_panel(); - input_keys = iidx_io_ep2_get_keys(); - turn_table[0] = iidx_io_ep2_get_turntable(0); - turn_table[1] = iidx_io_ep2_get_turntable(1); + input_sys = bt_io_iidx_ep2_sys_get(); + input_panel = bt_io_iidx_ep2_panel_get(); + input_keys = bt_io_iidx_ep2_keys_get(); + turn_table[0] = bt_io_iidx_ep2_turntable_get(0); + turn_table[1] = bt_io_iidx_ep2_turntable_get(1); for (uint8_t i = 0; i < 5; ++i) { - slider[i] = iidx_io_ep2_get_slider(i); + slider[i] = bt_io_iidx_ep2_slider_get(i); } system("cls"); @@ -146,38 +186,38 @@ int main(int argc, char **argv) text_16seg[6], text_16seg[7], text_16seg[8], - (input_panel >> IIDX_IO_PANEL_EFFECT) & 1, - (input_sys >> IIDX_IO_SYS_TEST) & 1, + (input_panel >> BT_IO_IIDX_PANEL_EFFECT) & 1, + (input_sys >> BT_IO_IIDX_SYS_TEST) & 1, - (input_panel >> IIDX_IO_PANEL_P1_START) & 1, + (input_panel >> BT_IO_IIDX_PANEL_P1_START) & 1, slider[0], slider[1], slider[2], slider[3], slider[4], - (input_panel >> IIDX_IO_PANEL_P2_START) & 1, + (input_panel >> BT_IO_IIDX_PANEL_P2_START) & 1, - (input_panel >> IIDX_IO_PANEL_VEFX) & 1, - (input_sys >> IIDX_IO_SYS_SERVICE) & 1, + (input_panel >> BT_IO_IIDX_PANEL_VEFX) & 1, + (input_sys >> BT_IO_IIDX_SYS_SERVICE) & 1, turn_table[0], - (input_keys >> IIDX_IO_KEY_P1_2) & 1, - (input_keys >> IIDX_IO_KEY_P1_4) & 1, - (input_keys >> IIDX_IO_KEY_P1_6) & 1, - (input_sys >> IIDX_IO_SYS_COIN), - (input_keys >> IIDX_IO_KEY_P2_2) & 1, - (input_keys >> IIDX_IO_KEY_P2_4) & 1, - (input_keys >> IIDX_IO_KEY_P2_6) & 1, + (input_keys >> BT_IO_IIDX_KEY_P1_2) & 1, + (input_keys >> BT_IO_IIDX_KEY_P1_4) & 1, + (input_keys >> BT_IO_IIDX_KEY_P1_6) & 1, + (input_sys >> BT_IO_IIDX_SYS_COIN), + (input_keys >> BT_IO_IIDX_KEY_P2_2) & 1, + (input_keys >> BT_IO_IIDX_KEY_P2_4) & 1, + (input_keys >> BT_IO_IIDX_KEY_P2_6) & 1, turn_table[1], - (input_keys >> IIDX_IO_KEY_P1_1) & 1, - (input_keys >> IIDX_IO_KEY_P1_3) & 1, - (input_keys >> IIDX_IO_KEY_P1_5) & 1, - (input_keys >> IIDX_IO_KEY_P1_7) & 1, + (input_keys >> BT_IO_IIDX_KEY_P1_1) & 1, + (input_keys >> BT_IO_IIDX_KEY_P1_3) & 1, + (input_keys >> BT_IO_IIDX_KEY_P1_5) & 1, + (input_keys >> BT_IO_IIDX_KEY_P1_7) & 1, - (input_keys >> IIDX_IO_KEY_P2_1) & 1, - (input_keys >> IIDX_IO_KEY_P2_3) & 1, - (input_keys >> IIDX_IO_KEY_P2_5) & 1, - (input_keys >> IIDX_IO_KEY_P2_7) & 1); + (input_keys >> BT_IO_IIDX_KEY_P2_1) & 1, + (input_keys >> BT_IO_IIDX_KEY_P2_3) & 1, + (input_keys >> BT_IO_IIDX_KEY_P2_5) & 1, + (input_keys >> BT_IO_IIDX_KEY_P2_7) & 1); /* set outputs */ if (all_on) { @@ -188,10 +228,10 @@ int main(int argc, char **argv) memset(text_16seg, '*', 9); } - iidx_io_ep1_set_deck_lights(deck_lights); - iidx_io_ep1_set_panel_lights(panel_lights); - iidx_io_ep1_set_top_lamps(_fix_top_lamps_order(top_lamps)); - iidx_io_ep1_set_top_neons(top_neons); + bt_io_iidx_ep1_deck_lights_set(deck_lights); + bt_io_iidx_ep1_panel_lights_set(panel_lights); + bt_io_iidx_ep1_top_lamps_set(_fix_top_lamps_order(top_lamps)); + bt_io_iidx_ep1_top_neons_set(top_neons); /* light up keys when pressed */ if (!all_on) { @@ -209,13 +249,25 @@ int main(int argc, char **argv) } } - if (!iidx_io_ep1_send()) { + if (!bt_io_iidx_ep1_send()) { printf("ERROR: Sending ep1 failed\n"); + + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&module_io_iidx); + return -4; } - if (!iidx_io_ep3_write_16seg(text_16seg)) { + if (!bt_io_iidx_ep3_16seg_send(text_16seg)) { printf("ERROR: Sending ep3 failed\n"); + + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&module_io_iidx); + return -3; } @@ -315,7 +367,10 @@ int main(int argc, char **argv) _all_lights_off_shutdown(); - iidx_io_fini(); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&module_io_iidx); return 0; } \ No newline at end of file diff --git a/src/main/inject/Module.mk b/src/main/inject/Module.mk index 549f1792..819c64ca 100644 --- a/src/main/inject/Module.mk +++ b/src/main/inject/Module.mk @@ -1,16 +1,28 @@ exes += inject +imps += dwarfstack ldflags_inject := \ -mconsole \ -lpsapi \ + -ldbghelp \ libs_inject := \ + core \ util \ + dwarfstack \ + iface-core \ + mxml \ src_inject := \ - main.c \ + debug-config.c \ + debugger-config.c \ debugger.c \ + hooks-config.c \ + inject-config.c \ + inject.c \ + logger-config.c \ logger.c \ + main.c \ options.c \ version.c \ diff --git a/src/main/inject/debug-config.c b/src/main/inject/debug-config.c new file mode 100644 index 00000000..4ae5e340 --- /dev/null +++ b/src/main/inject/debug-config.c @@ -0,0 +1,29 @@ +#define LOG_MODULE "inject-debug-config" + +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "inject/debug-config.h" + +void debug_config_init(debug_config_t *config) +{ + log_assert(config); + + config->property_configs_log = false; +} + +void debug_config_load( + const core_property_node_t *node, debug_config_t *config) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(config); + + result = core_property_node_ext_bool_read(node, "property_configs_log", &config->property_configs_log); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read(node, "property_api_trace_log", &config->property_configs_log); + core_property_node_fatal_on_error(result); +} \ No newline at end of file diff --git a/src/main/inject/debug-config.h b/src/main/inject/debug-config.h new file mode 100644 index 00000000..5966d20d --- /dev/null +++ b/src/main/inject/debug-config.h @@ -0,0 +1,18 @@ +#ifndef INJECT_DEBUG_CONFIG_H +#define INJECT_DEBUG_CONFIG_H + +#include + +#include "core/property-node.h" + +typedef struct debug_config { + bool property_configs_log; + bool property_api_trace_log; +} debug_config_t; + +void debug_config_init(debug_config_t *config); + +void debug_config_load( + const core_property_node_t *node, debug_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/inject/debugger-config.c b/src/main/inject/debugger-config.c new file mode 100644 index 00000000..eb35aa46 --- /dev/null +++ b/src/main/inject/debugger-config.c @@ -0,0 +1,52 @@ +#define LOG_MODULE "inject-debugger-config" + +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "inject/debugger-config.h" + +#include "util/str.h" + +static debugger_attach_type_t _debugger_config_str_to_attachtype(const char *str) +{ + log_assert(str); + + if (str_eq(str, "none")) { + return DEBUGGER_ATTACH_TYPE_NONE; + } else if (str_eq(str, "inject")) { + return DEBUGGER_ATTACH_TYPE_INJECT; + } else if (str_eq(str, "external")) { + return DEBUGGER_ATTACH_TYPE_EXTERNAL; + } else { + log_fatal("Invalid debugger attach type for debugger config: %s", str); + } +} + +void debugger_config_init(debugger_config_t *config) +{ + log_assert(config); + + memset(config, 0, sizeof(debugger_config_t)); +} + +void debugger_config_load( + const core_property_node_t *node, debugger_config_t *config) +{ + core_property_node_result_t result; + char buffer[16]; + + log_assert(node); + log_assert(config); + + result = core_property_node_ext_str_read(node, "app/path", config->app.path, sizeof(config->app.path)); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + node, "app/args", config->app.args, sizeof(config->app.args), ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(node, "attach_type", buffer, sizeof(buffer)); + core_property_node_fatal_on_error(result); + config->attach_type = _debugger_config_str_to_attachtype(buffer); +} \ No newline at end of file diff --git a/src/main/inject/debugger-config.h b/src/main/inject/debugger-config.h new file mode 100644 index 00000000..7e92ade1 --- /dev/null +++ b/src/main/inject/debugger-config.h @@ -0,0 +1,29 @@ +#ifndef INJECT_DEBUGGER_CONFIG_H +#define INJECT_DEBUGGER_CONFIG_H + +#include + +#include + +#include "core/property-node.h" + +#include "inject/debugger.h" + +// https://learn.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/command-line-string-limitation +#define WINDOWS_CMD_LINE_ARGS_MAX_LEN 8192 + +typedef struct debugger_config { + struct debugger_app_config { + char path[MAX_PATH]; + char args[WINDOWS_CMD_LINE_ARGS_MAX_LEN]; + } app; + + debugger_attach_type_t attach_type; +} debugger_config_t; + +void debugger_config_init(debugger_config_t *config); + +void debugger_config_load( + const core_property_node_t *node, debugger_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/inject/debugger.c b/src/main/inject/debugger.c index 724ed9ba..3b378afa 100644 --- a/src/main/inject/debugger.c +++ b/src/main/inject/debugger.c @@ -8,23 +8,27 @@ #include #include +#include "core/log-bt.h" +#include "core/log-ext.h" + +#include "iface-core/log.h" + #include "inject/debugger.h" -#include "inject/logger.h" -#include "util/log.h" +#include "util/debug.h" #include "util/mem.h" #include "util/proc.h" -#include "util/signal.h" #include "util/str.h" #define MM_ALLOCATION_GRANULARITY 0x10000 struct debugger_thread_params { const char *app_name; - char *cmd_line; - bool local_debugger; + const char *cmd_line; }; +static debugger_attach_type_t debugger_attach_type; + static HANDLE debugger_thread_handle; static HANDLE debugger_ready_event; @@ -132,7 +136,7 @@ read_debug_str(HANDLE process, const OUTPUT_DEBUG_STRING_INFO *odsi) free(str); log_warning( - "ERROR: ReadProcessMemory for debug string failed: %08x", + "ReadProcessMemory for debug string failed: %08x", (unsigned int) GetLastError()); str = NULL; } @@ -158,12 +162,12 @@ read_debug_wstr(HANDLE process, const OUTPUT_DEBUG_STRING_INFO *odsi) if (wstr_narrow(wstr, &str)) { str[odsi->nDebugStringLength - 1] = '\0'; } else { - log_warning("ERROR: OutputDebugStringW: UTF-16 conversion failed"); + log_warning("OutputDebugStringW: UTF-16 conversion failed"); str = NULL; } } else { log_warning( - "ERROR: ReadProcessMemory for debug string failed: %08x", + "ReadProcessMemory for debug string failed: %08x", (unsigned int) GetLastError()); str = NULL; } @@ -178,6 +182,7 @@ static bool log_debug_str(HANDLE process, const OUTPUT_DEBUG_STRING_INFO *odsi) log_assert(odsi); char *debug_str; + size_t debug_str_len; if (odsi->fUnicode) { debug_str = read_debug_wstr(process, odsi); @@ -186,7 +191,15 @@ static bool log_debug_str(HANDLE process, const OUTPUT_DEBUG_STRING_INFO *odsi) } if (debug_str) { - logger_log(debug_str); + debug_str_len = strlen(debug_str); + + // Important performance remark: If any sink in the chain has costly + // IO (e.g. blocking) or synchronization that can lead to blocking + // the caller here, the performance penalty propagates all the way up + // to the thread calling OutputDebugStr. This can lead to various + // symptoms such as stuttering or slowdowns in a game loop to laggy + // IO or music de-sync (depending on how logging is applied) + core_log_bt_direct_sink_write(debug_str, debug_str_len); free(debug_str); return true; @@ -195,9 +208,10 @@ static bool log_debug_str(HANDLE process, const OUTPUT_DEBUG_STRING_INFO *odsi) } } -static bool debugger_create_process( - bool local_debugger, const char *app_name, char *cmd_line) +static bool debugger_create_process(const char *app_name, const char *cmd_line) { + char cmd_line_cpy[8192]; + log_assert(app_name); log_assert(cmd_line); @@ -211,42 +225,44 @@ static bool debugger_create_process( flags = 0; // CREATE_SUSPENDED that we have plenty of time to set up the debugger and - // theemote process environment with hook dlls. + // the remote process environment with hook dlls. flags |= CREATE_SUSPENDED; - if (local_debugger) { + if (debugger_attach_type == DEBUGGER_ATTACH_TYPE_INJECT) { // DEBUG_PROCESS is required to make this work properly. Otherwise, // weird things like random remote process crashing are happening. Also, // DEBUG_ONLY_THIS_PROCESS is NOT sufficient/ correct here. Maybe I // didn't understand the documentation properly or it and various blog // posts I read are not explaining things well enough or are even wrong. flags |= DEBUG_PROCESS; + + log_info("Local debugger enabled"); + } else { + log_info("Local debugger disabled, no log output from remote process"); } log_misc("Creating remote process %s...", app_name); log_misc("Remote process cmd_line: %s", cmd_line); + str_cpy(cmd_line_cpy, sizeof(cmd_line_cpy), cmd_line); + ok = CreateProcess( - app_name, cmd_line, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi); + app_name, cmd_line_cpy, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi); if (!ok) { log_warning( - "ERROR: Failed to launch hooked EXE: %08x", + "Failed to launch hooked EXE: %08x", (unsigned int) GetLastError()); - free(cmd_line); - return false; } - free(cmd_line); - log_info("Remote process created, pid: %ld", pi.dwProcessId); return true; } -static uint32_t debugger_loop() +static uint32_t _debugger_thread_loop() { DEBUG_EVENT de; DWORD continue_status; @@ -257,7 +273,7 @@ static uint32_t debugger_loop() for (;;) { if (!WaitForDebugEvent(&de, INFINITE)) { log_warning( - "ERROR: WaitForDebugEvent failed: %08x", + "WaitForDebugEvent failed: %08x", (unsigned int) GetLastError()); return 1; } @@ -271,7 +287,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); @@ -376,14 +392,14 @@ static uint32_t debugger_loop() if (!ContinueDebugEvent( de.dwProcessId, de.dwThreadId, continue_status)) { log_warning( - "ERROR: ContinueDebugEvent failed: %08x", + "ContinueDebugEvent failed: %08x", (unsigned int) GetLastError()); return 1; } } } -static DWORD WINAPI debugger_proc(LPVOID param) +static DWORD WINAPI _debugger_thread_proc(LPVOID param) { uint32_t debugger_loop_exit_code; @@ -391,11 +407,9 @@ static DWORD WINAPI debugger_proc(LPVOID param) params = (struct debugger_thread_params *) param; - log_misc( - "Debugger thread start (local debugger: %d)", params->local_debugger); + log_misc("Debugger thread start"); - if (!debugger_create_process( - params->local_debugger, params->app_name, params->cmd_line)) { + if (!debugger_create_process(params->app_name, params->cmd_line)) { return 0; } @@ -403,8 +417,8 @@ static DWORD WINAPI debugger_proc(LPVOID param) // Don't run our local debugger loop if the user wants to attach a remote // debugger or debugger is disabled - if (params->local_debugger) { - debugger_loop_exit_code = debugger_loop(); + if (debugger_attach_type == DEBUGGER_ATTACH_TYPE_INJECT) { + debugger_loop_exit_code = _debugger_thread_loop(); free(params); @@ -424,19 +438,73 @@ static DWORD WINAPI debugger_proc(LPVOID param) } } -bool debugger_init(bool local_debugger, const char *app_name, char *cmd_line) +void _debugger_wait_for_remote_debugger() +{ + BOOL res; + + log_warning("Waiting until remote debugger attaches to remote process..."); + + while (true) { + res = FALSE; + + if (!CheckRemoteDebuggerPresent(pi.hProcess, &res)) { + log_fatal( + "CheckRemoteDebuggerPresent failed: %08x", + (unsigned int) GetLastError()); + return; + } + + if (res) { + log_info("Remote debugger attached, resuming"); + break; + } + + Sleep(1000); + } +} + +void _debugger_resume_process() +{ + log_info("Resuming remote process..."); + + if (ResumeThread(pi.hThread) == -1) { + log_fatal( + "Resuming remote process failed: %08x", + (unsigned int) GetLastError()); + } + + CloseHandle(pi.hThread); +} + +void _debugger_wait_process_exit() +{ + log_misc("Waiting for remote process to exit..."); + + // Wait for the process as we might have a remote debugger attached, so our + // debugger thread exits after creating the process + WaitForSingleObject(pi.hProcess, INFINITE); + + // When the process exits, the debugger gets notified and the thread ends + WaitForSingleObject(debugger_thread_handle, INFINITE); + + log_misc("Remote process exit'd"); +} + +void debugger_init(debugger_attach_type_t attach_type, const char *app_name, const char *cmd_line) { struct debugger_thread_params *thread_params; + log_assert(app_name); + log_assert(cmd_line); + + debugger_attach_type = attach_type; + debugger_ready_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!debugger_ready_event) { - free(cmd_line); - - log_warning( - "ERROR: Creating event object failed: %08x", + log_fatal( + "Creating event object failed: %08x", (unsigned int) GetLastError()); - return false; } // free'd by thread if created successfully @@ -444,53 +512,21 @@ bool debugger_init(bool local_debugger, const char *app_name, char *cmd_line) thread_params->app_name = app_name; thread_params->cmd_line = cmd_line; - thread_params->local_debugger = local_debugger; debugger_thread_handle = - CreateThread(NULL, 0, debugger_proc, thread_params, 0, 0); + CreateThread(NULL, 0, _debugger_thread_proc, thread_params, 0, 0); if (!debugger_thread_handle) { - free(cmd_line); free(thread_params); - log_warning( - "ERROR: Creating debugger thread failed: %08x", + log_fatal( + "Creating debugger thread failed: %08x", (unsigned int) GetLastError()); - return false; } WaitForSingleObject(debugger_ready_event, INFINITE); - log_misc("Debugger initialized"); - - return true; -} - -bool debugger_wait_for_remote_debugger() -{ - BOOL res; - - log_warning("Waiting until remote debugger attaches to remote process..."); - - while (true) { - res = FALSE; - - if (!CheckRemoteDebuggerPresent(pi.hProcess, &res)) { - log_warning( - "ERROR: CheckRemoteDebuggerPresent failed: %08x", - (unsigned int) GetLastError()); - return false; - } - - if (res) { - log_info("Remote debugger attached, resuming"); - break; - } - - Sleep(1000); - } - - return true; + log_misc("Initialized, attach type: %d", debugger_attach_type); } bool debugger_inject_dll(const char *path_dll) @@ -508,6 +544,10 @@ bool debugger_inject_dll(const char *path_dll) dll_path_length = SearchPath(NULL, path_dll, NULL, MAX_PATH, dll_path, NULL); + if (dll_path_length == 0) { + log_fatal_on_win_last_error("Determining path for dll %s failed", path_dll); + } + dll_path_length++; remote_addr = VirtualAllocEx( @@ -519,7 +559,7 @@ bool debugger_inject_dll(const char *path_dll) if (!remote_addr) { log_warning( - "ERROR: VirtualAllocEx failed: %08x", + "VirtualAllocEx failed: %08x", (unsigned int) GetLastError()); goto alloc_fail; @@ -530,7 +570,7 @@ bool debugger_inject_dll(const char *path_dll) if (!ok) { log_warning( - "ERROR: WriteProcessMemory failed: %08x", + "WriteProcessMemory failed: %08x", (unsigned int) GetLastError()); goto write_fail; @@ -547,7 +587,7 @@ bool debugger_inject_dll(const char *path_dll) if (remote_thread == NULL) { log_warning( - "ERROR: CreateRemoteThread failed: %08x", + "CreateRemoteThread failed: %08x", (unsigned int) GetLastError()); goto inject_fail; @@ -561,9 +601,11 @@ bool debugger_inject_dll(const char *path_dll) if (!ok) { log_warning( - "ERROR: VirtualFreeEx failed: %08x", (unsigned int) GetLastError()); + "VirtualFreeEx failed: %08x", (unsigned int) GetLastError()); } + log_misc("Injecting success: %s", path_dll); + return true; inject_fail: @@ -746,34 +788,19 @@ bool debugger_replace_dll_iat( return false; } -bool debugger_resume_process() +void debugger_run() { - log_info("Resuming remote process..."); - - if (ResumeThread(pi.hThread) == -1) { - log_warning( - "ERROR: Resuming remote process: %08x", - (unsigned int) GetLastError()); - return false; + // Execute this after injecting the DLLs. Some debuggers seem to crash if we + // attach the process before DLL injection (inject's local one doesn't + // crash). However, this means the remote debugger is missing out on all + // injected DLL loads, e.g. calls to DllMain + if (debugger_attach_type == DEBUGGER_ATTACH_TYPE_EXTERNAL) { + _debugger_wait_for_remote_debugger(); } - CloseHandle(pi.hThread); - - return true; -} - -void debugger_wait_process_exit() -{ - log_misc("Waiting for remote process to exit..."); - - // Wait for the process as we might have a remote debugger attached, so our - // debugger thread exits after creating the process - WaitForSingleObject(pi.hProcess, INFINITE); + _debugger_resume_process(); - // When the process exits, the debugger gets notified and the thread ends - WaitForSingleObject(debugger_thread_handle, INFINITE); - - log_misc("Remote process exit'd"); + _debugger_wait_process_exit(); } void debugger_finit(bool failure) diff --git a/src/main/inject/debugger.h b/src/main/inject/debugger.h index 76075f1c..b1c82b34 100644 --- a/src/main/inject/debugger.h +++ b/src/main/inject/debugger.h @@ -2,16 +2,11 @@ #include -/** - * Initialize inject's logger backend. - * - * This takes care of hooking and merging the different log - * streams, e.g. inject's local logging and inject's debugger - * receiving remote logging events. - * - * @param log_file_path Path to the file to log to or NULL to - * disable. - */ +typedef enum debugger_attach_type { + DEBUGGER_ATTACH_TYPE_NONE = 0, + DEBUGGER_ATTACH_TYPE_INJECT = 1, + DEBUGGER_ATTACH_TYPE_EXTERNAL = 2, +} debugger_attach_type_t; /** * Initialize the debugger. @@ -30,15 +25,11 @@ * set the parameter local_debugger to false. Then, the debugger * will only create the remote process and monitor it. * - * @param local_debugger True to attach inject's local debugger, - * false to allow attaching a remote - * debugger with enhanced features. + * @param attach_type Setup the debugger to attach with the given type of debugger * @param app_name Name of the application to spawn and debug. * @param cmd_line Command line string to pass to application. - * @return true on success, false on error. On error, no remote - * application and local debugger is started. */ -bool debugger_init(bool local_debugger, const char *app_name, char *cmd_line); +void debugger_init(debugger_attach_type_t attach_type, const char *app_name, const char *cmd_line); /** * Inject a DLL into the remote process. @@ -48,6 +39,8 @@ bool debugger_init(bool local_debugger, const char *app_name, char *cmd_line); */ bool debugger_inject_dll(const char *path_dll); +void debugger_run(); + /** * Inject a DLL into the remote process by replacing its reference in * the import table. diff --git a/src/main/inject/hooks-config.c b/src/main/inject/hooks-config.c new file mode 100644 index 00000000..7328b91a --- /dev/null +++ b/src/main/inject/hooks-config.c @@ -0,0 +1,226 @@ +#define LOG_MODULE "inject-hooks-config" + +#include "core/property-ext.h" +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "inject/hooks-config.h" + +#define HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES 8 + +static core_property_t * +_hooks_config_layered_config_nodes_load(const core_property_node_t *node) +{ + char kind[64]; + char file[MAX_PATH]; + int cnt; + + core_property_node_t cur; + core_property_node_t tmp; + core_property_t *config_property[HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES]; + core_property_t *merged_property; + core_property_node_result_t result; + core_property_result_t prop_result; + + log_assert(node); + + cnt = 0; + result = core_property_node_search(node, "config", &cur); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (cnt >= HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES) { + log_fatal( + "Exceeding max supported config nodes for layering, max is %d", + HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES); + } + + result = + core_property_node_attr_read(&cur, "kind", kind, sizeof(kind)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal("Failed reading 'kind' attribute value of config node"); + } + + if (!strcmp(kind, "file")) { + core_property_node_str_read(&cur, file, sizeof(file)); + + prop_result = core_property_file_load(file, &config_property[cnt]); + core_property_fatal_on_error(prop_result); + } else if (!strcmp(kind, "inline")) { + // The nested child is the actual root of the inline, not the outer + // node + result = core_property_node_child_get(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + result = + core_property_node_ext_extract(&cur, &config_property[cnt]); + core_property_node_fatal_on_error(result); + } else { + log_fatal( + "Unsupported 'kind' attribute value '%s' of config node", kind); + } + + cnt++; + result = core_property_node_next_result_search(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + + if (cnt == 0) { + prop_result = core_property_str_load("", &merged_property); + core_property_fatal_on_error(prop_result); + } else { + prop_result = + core_property_ext_many_merge(config_property, cnt, &merged_property); + core_property_fatal_on_error(prop_result); + + for (int i = 0; i < cnt; i++) { + core_property_free(&config_property[i]); + } + } + + return merged_property; +} + +static void _hooks_config_hooks_load( + const core_property_node_t *node, + struct hooks_hook_config *configs) +{ + core_property_node_result_t result; + core_property_node_t child; + core_property_node_t tmp; + uint8_t processed_hooks; + + processed_hooks = 0; + + result = core_property_node_search(node, "hook", &child); + + do { + if (processed_hooks >= HOOKS_CONFIG_MAX_HOOKS) { + log_fatal("Cannot load more hooks, max supported capacity reached"); + } + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + return; + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_ext_bool_read(&child, "enable", &configs[processed_hooks].enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(&child, "path", configs[processed_hooks].path, sizeof(configs[processed_hooks].path)); + core_property_node_fatal_on_error(result); + + configs[processed_hooks].config = _hooks_config_layered_config_nodes_load(&child); + + result = core_property_node_next_result_search(&child, &tmp); + memcpy(&child, &tmp, sizeof(core_property_node_t)); + + processed_hooks++; + } while (true); +} + +static void _hooks_config_iats_load( + const core_property_node_t *node, + struct hooks_iat_config *configs) +{ + core_property_node_result_t result; + core_property_node_t child; + core_property_node_t tmp; + uint8_t processed_hooks; + + processed_hooks = 0; + + result = core_property_node_search(node, "iat", &child); + + do { + if (processed_hooks >= HOOKS_CONFIG_MAX_HOOKS) { + log_fatal("Cannot load more hooks, max supported capacity reached"); + } + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + return; + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_ext_bool_read(&child, "enable", &configs[processed_hooks].enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(&child, "source_name", configs[processed_hooks].source_name, sizeof(configs[processed_hooks].source_name)); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(&child, "path", configs[processed_hooks].path, sizeof(configs[processed_hooks].path)); + core_property_node_fatal_on_error(result); + + configs[processed_hooks].config = _hooks_config_layered_config_nodes_load(&child); + + result = core_property_node_next_result_search(&child, &tmp); + memcpy(&child, &tmp, sizeof(core_property_node_t)); + + processed_hooks++; + } while (true); +} + +void hooks_config_init(hooks_config_t *config) +{ + log_assert(config); + + memset(config, 0, sizeof(hooks_config_t)); +} + +void hooks_config_load( + const core_property_node_t *node, hooks_config_t *config) +{ + log_assert(node); + log_assert(config); + + _hooks_config_hooks_load(node, config->hooks); + _hooks_config_iats_load(node, config->iats); +} + +bool hooks_config_hook_is_valid(const struct hooks_hook_config *hook) +{ + log_assert(hook); + + return strlen(hook->path) > 0; +} + +bool hooks_config_iat_is_valid(const struct hooks_iat_config *hook) +{ + log_assert(hook); + + return strlen(hook->path) > 0; +} + +void hooks_config_fini(hooks_config_t *config) +{ + uint32_t i; + + log_assert(config); + + for (i = 0; i < HOOKS_CONFIG_MAX_HOOKS; i++) { + if (hooks_config_hook_is_valid(&config->hooks[i])) { + core_property_free(&config->hooks[i].config); + } + } + + for (i = 0; i < HOOKS_CONFIG_MAX_HOOKS; i++) { + if (hooks_config_iat_is_valid(&config->iats[i])) { + core_property_free(&config->iats[i].config); + } + } +} \ No newline at end of file diff --git a/src/main/inject/hooks-config.h b/src/main/inject/hooks-config.h new file mode 100644 index 00000000..87441cde --- /dev/null +++ b/src/main/inject/hooks-config.h @@ -0,0 +1,39 @@ +#ifndef INJECT_HOOKS_CONFIG_H +#define INJECT_HOOKS_CONFIG_H + +#include + +#include + +#include "core/property.h" +#include "core/property-node.h" + +#define HOOKS_CONFIG_MAX_HOOKS 16 + +typedef struct hooks_config { + struct hooks_hook_config { + bool enable; + char path[MAX_PATH]; + core_property_t *config; + } hooks[HOOKS_CONFIG_MAX_HOOKS]; + + struct hooks_iat_config { + bool enable; + char source_name[MAX_PATH]; + char path[MAX_PATH]; + core_property_t *config; + } iats[HOOKS_CONFIG_MAX_HOOKS]; +} hooks_config_t; + +void hooks_config_init(hooks_config_t *config); + +void hooks_config_load( + const core_property_node_t *node, hooks_config_t *config); + +bool hooks_config_hook_is_valid(const struct hooks_hook_config *hook); + +bool hooks_config_iat_is_valid(const struct hooks_iat_config *hook); + +void hooks_config_fini(hooks_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/inject/inject-config.c b/src/main/inject/inject-config.c new file mode 100644 index 00000000..9f9e8d48 --- /dev/null +++ b/src/main/inject/inject-config.c @@ -0,0 +1,77 @@ +#define LOG_MODULE "inject-config" + +#include "core/property-ext.h" +#include "core/property-node.h" +#include "core/property.h" + +#include "core/property-mxml-internal.h" +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "inject/debug-config.h" +#include "inject/debugger-config.h" +#include "inject/hooks-config.h" +#include "inject/inject-config.h" +#include "inject/logger-config.h" + +void inject_config_init(struct inject_config *config) +{ + log_assert(config); + + config->version = 1; + + debug_config_init(&config->debug); + debugger_config_init(&config->debugger); + hooks_config_init(&config->hooks); + logger_config_init(&config->logger); +} + +void inject_config_file_load(const char *path, inject_config_t *config) +{ + core_property_result_t result_prop; + core_property_node_result_t result; + core_property_t *property; + core_property_node_t root_node; + core_property_node_t child_node; + + log_info("Loading configuration file: %s", path); + + result_prop = core_property_file_load(path, &property); + core_property_fatal_on_error(result_prop); + + result = core_property_root_node_get(property, &root_node); + core_property_node_fatal_on_error(result); + + result = core_property_node_search(&root_node, "debug", &child_node); + core_property_node_fatal_on_error(result); + debug_config_load(&child_node, &config->debug); + + result = core_property_node_search(&root_node, "debugger", &child_node); + core_property_node_fatal_on_error(result); + debugger_config_load(&child_node, &config->debugger); + + result = core_property_node_search(&root_node, "hooks", &child_node); + core_property_node_fatal_on_error(result); + hooks_config_load(&child_node, &config->hooks); + + result = core_property_node_search(&root_node, "logger", &child_node); + core_property_node_fatal_on_error(result); + logger_config_load(&child_node, &config->logger); + + if (config->debug.property_configs_log) { + core_property_ext_log(property, log_misc_func); + } + + core_property_free(&property); + + log_misc("Loading done"); +} + +void inject_config_fini(inject_config_t *config) +{ + log_assert(config); + + // Other configs don't have a fini + hooks_config_fini(&config->hooks); +} \ No newline at end of file diff --git a/src/main/inject/inject-config.h b/src/main/inject/inject-config.h new file mode 100644 index 00000000..3b1747d2 --- /dev/null +++ b/src/main/inject/inject-config.h @@ -0,0 +1,26 @@ +#ifndef INJECT_CONFIG_H +#define INJECT_CONFIG_H + +#include + +#include "inject/debug-config.h" +#include "inject/debugger-config.h" +#include "inject/hooks-config.h" +#include "inject/logger-config.h" + +typedef struct inject_config { + uint32_t version; + + hooks_config_t hooks; + logger_config_t logger; + debugger_config_t debugger; + debug_config_t debug; +} inject_config_t; + +void inject_config_init(struct inject_config *config); + +void inject_config_file_load(const char *path, inject_config_t *config); + +void inject_config_fini(inject_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/inject/inject.c b/src/main/inject/inject.c new file mode 100644 index 00000000..8a156120 --- /dev/null +++ b/src/main/inject/inject.c @@ -0,0 +1,135 @@ +#define LOG_MODULE "inject" + +#include "iface-core/log.h" + +#include "inject/debugger.h" +#include "inject/inject-config.h" +#include "inject/logger.h" +#include "inject/version.h" + +#include "util/os.h" +#include "util/signal.h" + +static void _inject_fini(); + +static void _inject_signal_handler_shutdown() +{ + _inject_fini(); + exit(0); +} + +static void _inject_header_log() +{ + log_info( + "\n" + " _ _ _ \n" + " (_)_ __ (_) ___ ___| |_ \n" + " | | '_ \\ | |/ _ \\/ __| __|\n" + " | | | | || | __/ (__| |_ \n" + " |_|_| |_|/ |\\___|\\___|\\__|\n" + " |__/ "); + + log_info( + "build date %s, gitrev %s", inject_build_date, inject_gitrev); +} + +static void _inject_iat_hook_dlls(const struct hooks_iat_config *configs) +{ + uint32_t i; + + log_assert(configs); + + log_info("Injecting IAT hook DLLs..."); + + for (i = 0; i < HOOKS_CONFIG_MAX_HOOKS; i++) { + if (hooks_config_iat_is_valid(&configs[i])) { + if (configs[i].enable) { + if (!debugger_replace_dll_iat(configs[i].source_name, configs[i].path)) { + log_fatal("Injecting iat hook failed: %s=%s", configs[i].source_name, configs[i].path); + } + } else { + log_warning("iat hook disabled: %s=%s", configs[i].source_name, configs[i].path); + } + } + } +} + +static void _inject_hook_dlls(const struct hooks_hook_config *configs) +{ + uint32_t i; + + log_assert(configs); + + log_info("Injecting hook DLLs..."); + + for (i = 0; i < HOOKS_CONFIG_MAX_HOOKS; i++) { + if (hooks_config_hook_is_valid(&configs[i])) { + if (configs[i].enable) { + if (!debugger_inject_dll(configs[i].path)) { + log_fatal("Injecting hook failed: %s", configs[i].path); + } + } else { + log_warning("Hook disabled: %s", configs[i].path); + } + } + } +} + +static void _inject_init(const inject_config_t *config) +{ + log_assert(config); + + logger_init(&config->logger); + + _inject_header_log(); + os_version_log(); + + signal_exception_handler_init(); + // Cleanup remote process on CTRL+C + signal_register_shutdown_handler(_inject_signal_handler_shutdown); + + debugger_init( + config->debugger.attach_type, + config->debugger.app.path, + config->debugger.app.args); + + log_misc("<<< init"); +} + +static void _inject_run(const inject_config_t *config) +{ + log_assert(config); + + log_misc(">>> run"); + + _inject_hook_dlls(config->hooks.hooks); + _inject_iat_hook_dlls(config->hooks.iats); + + debugger_run(); + + log_misc("<<< run"); +} + +static void _inject_fini() +{ + log_misc(">>> fini"); + + debugger_finit(false); + + logger_fini(); +} + +// TODO run inject module only with inject configuration +// config must be bootstrapped using an early env +// in main with a early logger setup etc. +// apply the same to launcher +void inject_main(const inject_config_t *config) +{ + log_assert(config); + + log_misc(">>> main"); + + _inject_init(config); + _inject_run(config); + _inject_fini(); +} \ No newline at end of file diff --git a/src/main/inject/inject.h b/src/main/inject/inject.h new file mode 100644 index 00000000..187f28b4 --- /dev/null +++ b/src/main/inject/inject.h @@ -0,0 +1,8 @@ +#ifndef INJECT_INJECT_H +#define INJECT_INJECT_H + +#include "inject/inject-config.h" + +void inject_main(const inject_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/inject/logger-config.c b/src/main/inject/logger-config.c new file mode 100644 index 00000000..cd0b1511 --- /dev/null +++ b/src/main/inject/logger-config.c @@ -0,0 +1,140 @@ +#define LOG_MODULE "inject-logger-config" + +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "inject/logger-config.h" + +#include "util/str.h" + +static enum core_log_bt_log_level _logger_config_str_to_loglevel(const char *str) +{ + log_assert(str); + + if (str_eq(str, "off")) { + return CORE_LOG_BT_LOG_LEVEL_OFF; + } else if (str_eq(str, "fatal")) { + return CORE_LOG_BT_LOG_LEVEL_FATAL; + } else if (str_eq(str, "warning")) { + return CORE_LOG_BT_LOG_LEVEL_WARNING; + } else if (str_eq(str, "info")) { + return CORE_LOG_BT_LOG_LEVEL_INFO; + } else if (str_eq(str, "misc")) { + return CORE_LOG_BT_LOG_LEVEL_MISC; + } else { + log_fatal("Invalid log level string in config: %s", str); + } +} + +static enum core_log_sink_async_overflow_policy _logger_config_str_to_overflowpolicy(const char *str) +{ + log_assert(str); + + if (str_eq(str, "discard_new")) { + return CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_DISCARD_NEW; + } else if (str_eq(str, "block")) { + return CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_BLOCK; + } else { + log_fatal("Invalid overflow policy string in config: %s", str); + } +} + +static void _logger_config_sink_async_load(const core_property_node_t *node, struct logger_sink_async_config *config) +{ + core_property_node_result_t result; + core_property_node_t child; + char buffer[16]; + + log_assert(node); + log_assert(config); + + result = core_property_node_search(node, "sinks/async", &child); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read(&child, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_u8_read(&child, "queue_length", &config->queue_length); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(&child, "overflow_policy", buffer, sizeof(buffer)); + core_property_node_fatal_on_error(result); + config->overflow_policy = _logger_config_str_to_overflowpolicy(buffer); +} + +static void _logger_config_sink_console_load(const core_property_node_t *node, struct logger_sink_console_config *config) +{ + core_property_node_result_t result; + core_property_node_t child; + + log_assert(node); + log_assert(config); + + result = core_property_node_search(node, "sinks/console", &child); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read(&child, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read(&child, "color", &config->color); + core_property_node_fatal_on_error(result); +} + +static void _logger_config_sink_file_load(const core_property_node_t *node, struct logger_sink_file_config *config) +{ + core_property_node_result_t result; + core_property_node_t child; + + log_assert(node); + log_assert(config); + + result = core_property_node_search(node, "sinks/file", &child); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read(&child, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(&child, "path", config->path, sizeof(config->path)); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read(&child, "append", &config->append); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read(&child, "rotate", &config->rotate); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_u8_read(&child, "max_rotations", &config->max_rotations); + core_property_node_fatal_on_error(result); +} + +void logger_config_init(logger_config_t *config) +{ + log_assert(config); + + memset(config, 0, sizeof(logger_config_t)); +} + +void logger_config_load( + const core_property_node_t *node, logger_config_t *config) +{ + core_property_node_result_t result; + char buffer[16]; + + log_assert(node); + log_assert(config); + + result = core_property_node_ext_bool_read(node, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(node, "level", buffer, sizeof(buffer)); + core_property_node_fatal_on_error(result); + config->level = _logger_config_str_to_loglevel(buffer); + + result = core_property_node_ext_u32_read(node, "msg_buffer_size_bytes", &config->msg_buffer_size_bytes); + core_property_node_fatal_on_error(result); + + _logger_config_sink_async_load(node, &config->sink_async); + _logger_config_sink_console_load(node, &config->sink_console); + _logger_config_sink_file_load(node, &config->sink_file); +} diff --git a/src/main/inject/logger-config.h b/src/main/inject/logger-config.h new file mode 100644 index 00000000..66ae1b8d --- /dev/null +++ b/src/main/inject/logger-config.h @@ -0,0 +1,43 @@ +#ifndef INJECT_LOGGER_CONFIG_H +#define INJECT_LOGGER_CONFIG_H + +#include +#include + +#include + +#include "core/log-bt.h" +#include "core/log-sink-async.h" +#include "core/property-node.h" + +typedef struct logger_config { + bool enable; + enum core_log_bt_log_level level; + uint32_t msg_buffer_size_bytes; + + struct logger_sink_async_config { + bool enable; + uint8_t queue_length; + enum core_log_sink_async_overflow_policy overflow_policy; + } sink_async; + + struct logger_sink_console_config { + bool enable; + bool color; + } sink_console; + + struct logger_sink_file_config { + bool enable; + char path[MAX_PATH]; + bool append; + bool rotate; + uint8_t max_rotations; + } sink_file; +} logger_config_t; + +void logger_config_init(logger_config_t *config); + +void logger_config_load( + const core_property_node_t *node, logger_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/inject/logger.c b/src/main/inject/logger.c index 8f63aa9c..3393b328 100644 --- a/src/main/inject/logger.c +++ b/src/main/inject/logger.c @@ -1,217 +1,123 @@ #define LOG_MODULE "inject-logger" -#include -#include -#include -#include -#include -#include +#include "core/log-bt.h" +#include "core/log-sink-async.h" +#include "core/log-sink-file.h" +#include "core/log-sink-list.h" +#include "core/log-sink-null.h" +#include "core/log-sink-std.h" -#include "inject/logger.h" -#include "inject/version.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "inject/logger-config.h" -static FILE *log_file; -static HANDLE log_mutex; - -static const char *logger_get_formatted_timestamp(void) +static void _logger_null_sink_init() { - static char buffer[64]; - time_t cur = 0; - struct tm *tm = NULL; - - cur = time(NULL); - tm = localtime(&cur); + core_log_sink_t sink; - strftime(buffer, sizeof(buffer), "[%Y/%m/%d %H:%M:%S] ", tm); + core_log_sink_null_open(&sink); - return buffer; + // Size doesn't matter (but must be valid) + // logger is entirely disabled + core_log_bt_init(1024, &sink); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_OFF); } -static char logger_console_determine_color(const char *str) +static bool _logger_sinks_create( + const logger_config_t *config, + core_log_sink_t *root_sink) { - log_assert(str); + core_log_sink_t target_sinks[2]; + core_log_sink_t list_sink; + uint8_t target_sink_count; - /* Add some color to make spotting warnings/errors easier. - Based on debug output level identifier. */ + log_assert(config); + log_assert(root_sink); - /* Avoids colored output on strings like "Windows" */ - if (str[1] != ':') { - return 15; - } + target_sink_count = 0; - 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; - } -} + // Fixed order to ensure logger's first sink to write to is + // async and async sinks to console and file -static size_t logger_msg_coloring_len(const char *str) -{ - // Expected format example: "I:boot: my log message" + if (config->sink_console.enable) { + core_log_sink_std_err_open( + config->sink_console.color, + &target_sinks[target_sink_count]); - const char *ptr; - size_t len; - int colon_count; - - ptr = str; - len = 0; - colon_count = 0; + target_sink_count++; + } - while (true) { - // End of string = invalid log format - if (*ptr == '\0') { - return 0; - } + if (config->sink_file.enable) { + core_log_sink_file_open( + config->sink_file.path, + config->sink_file.append, + config->sink_file.rotate, + config->sink_file.max_rotations, + &target_sinks[target_sink_count]); - if (*ptr == ':') { - colon_count++; - } + target_sink_count++; + } - if (colon_count == 2) { - // Skip current colon, next char is a space - return len + 1; + if (target_sink_count > 0) { + // Compose to single sink + core_log_sink_list_open( + target_sinks, + target_sink_count, + &list_sink); + + // Async sink only makes sense if at least one other + // sink is enabled + if (config->sink_async.enable) { + core_log_sink_async_open( + config->msg_buffer_size_bytes, + config->sink_async.queue_length, + config->sink_async.overflow_policy, + &list_sink, + root_sink); + } else { + // "Sync" with list of sinks + memcpy(root_sink, &list_sink, sizeof(core_log_sink_t)); } - len++; - ptr++; + return true; + } else { + memset(root_sink, 0, sizeof(core_log_sink_t)); + return false; } - - return 0; } -static void logger_console( - void *ctx, const char *chars, size_t nchars, const char *timestamp_str) +static void _logger_with_sinks_init(const logger_config_t *config) { - 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); + core_log_sink_t sink; + bool has_sinks; - // 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); + log_assert(config); - strcpy(buffer, chars); + has_sinks = _logger_sinks_create(config, &sink); - // 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); + if (has_sinks) { + core_log_bt_init(config->msg_buffer_size_bytes, &sink); + core_log_bt_level_set(config->level); } else { - printf("%s", chars); + // Consider this equivalent to disabling logging entirely + _logger_null_sink_init(); } } -static void logger_file( - void *ctx, const char *chars, size_t nchars, const char *timestamp_str) +void logger_init(const logger_config_t *config) { - if (ctx) { - fwrite(timestamp_str, 1, strlen(timestamp_str), (FILE *) ctx); - fwrite(chars, 1, nchars, (FILE *) ctx); - fflush((FILE *) ctx); - } -} - -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); + log_assert(config); - 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" - " | | | | || | __/ (__| |_ \n" - " |_|_| |_|/ |\\___|\\___|\\__|\n" - " |__/ "); - - log_info( - "Inject build date %s, gitrev %s", inject_build_date, inject_gitrev); -} - -bool logger_init(const char *log_file_path) -{ - if (log_file_path) { - log_file = fopen(log_file_path, "w+"); + if (!config->enable) { + _logger_null_sink_init(); } else { - log_file = NULL; + _logger_with_sinks_init(config); } - 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_warning( - "ERROR: Opening log file %s failed: %s", - log_file_path, - strerror(errno)); - return false; - } - } - - log_mutex = CreateMutex(NULL, FALSE, NULL); - - return true; -} - -void logger_log(const char *str) -{ - logger_writer(log_file, str, strlen(str)); + core_log_bt_core_api_set(); } -void logger_finit() +void logger_fini() { - log_misc("Logger finit"); - - if (log_file) { - fclose(log_file); - } - - CloseHandle(log_mutex); + core_log_bt_fini(); } \ No newline at end of file diff --git a/src/main/inject/logger.h b/src/main/inject/logger.h index 45a8b770..fcec2616 100644 --- a/src/main/inject/logger.h +++ b/src/main/inject/logger.h @@ -1,28 +1,10 @@ -#include +#ifndef INJECT_LOGGER_H +#define INJECT_LOGGER_H -/** - * Initialize inject's logger backend. - * - * This takes care of hooking and merging the different log - * streams, e.g. inject's local logging and inject's debugger - * receiving remote logging events. - * - * @param log_file_path Path to the file to log to or NULL to - * disable. - */ -bool logger_init(const char *log_file_path); +#include "inject/logger-config.h" -/** - * Write a message to the logging backend. - * - * This is used by inject's debugger to redirect log messages - * recevied from the remote process. - * - * @param str String to log - */ -void logger_log(const char *str); +void logger_init(const logger_config_t *config); -/** - * Shutdown and cleanup the logging backend. - */ -void logger_finit(); \ No newline at end of file +void logger_fini(); + +#endif \ No newline at end of file diff --git a/src/main/inject/main.c b/src/main/inject/main.c index bfb6c1be..1d280698 100644 --- a/src/main/inject/main.c +++ b/src/main/inject/main.c @@ -1,234 +1,68 @@ -#include +#define LOG_MODULE "main" -#include -#include -#include #include -#include -#include -#include "cconfig/cconfig-util.h" -#include "cconfig/cmd.h" +#include "core/boot.h" -#include "inject/debugger.h" -#include "inject/logger.h" -#include "inject/options.h" -#include "inject/version.h" +#include "inject/inject-config.h" +#include "inject/inject.h" -#include "util/cmdline.h" -#include "util/log.h" -#include "util/mem.h" -#include "util/os.h" -#include "util/signal.h" -#include "util/str.h" - -static bool init_options(int argc, char **argv, struct options *options) -{ - options_init(options); - - if (argc < 3 || !options_read_cmdline(options, argc, argv)) { - options_print_usage(); - return false; - } - - return true; -} - -static bool verify_hook_dll_and_exec_args_and_count_hooks( - int argc, char **argv, uint32_t *hooks, uint32_t *exec_arg_pos) -{ - log_assert(argc >= 0); - log_assert(argv); - log_assert(hooks); - log_assert(exec_arg_pos); - - *hooks = 0; - *exec_arg_pos = 0; - - for (int i = 1; i < argc; i++) { - if (str_ends_with(argv[i], "dll")) { - (*hooks)++; - } else if (str_ends_with(argv[i], "exe")) { - *exec_arg_pos = i; - break; - } - } - - if (!(*hooks)) { - log_warning("ERROR: No Hook DLL(s) specified before executable"); - return false; - } - - if (!*exec_arg_pos) { - log_warning("ERROR: No executable specified"); - return false; - } - - log_misc("%d hook(s) dll detected", *hooks); - log_misc("Executable: %s", argv[*exec_arg_pos]); - - return true; -} - -static bool -verify_hook_dlls_exist(int argc, char **argv, uint32_t hook_dll_count) +static void _bootstrap_options(int argc, char **argv) { - log_assert(argc >= 0); - log_assert(argv); - - char dll_path[MAX_PATH]; - DWORD dll_path_length; - - for (uint32_t i = 0; i < hook_dll_count; i++) { - char *iat_hook = strstr(argv[i + 1], "="); - - if (iat_hook) { - dll_path_length = - SearchPath(NULL, iat_hook + 1, NULL, MAX_PATH, dll_path, NULL); - } else { - dll_path_length = - SearchPath(NULL, argv[i + 1], NULL, MAX_PATH, dll_path, NULL); - } - - if (dll_path_length == 0) { - log_warning( - "ERROR: Hook DLL not found: %08x", - (unsigned int) GetLastError()); - - return false; - } + // TODO use options here + if (argc < 2) { + printf("Not enough args\n"); + exit(1); } - - return true; } -static bool inject_iat_hook_dlls(uint32_t hooks, char **argv) +static void _bootstrap_config(const char *path, inject_config_t *config) { - log_assert(argv); - - log_info("Injecting IAT hook DLLs..."); - - for (int i = 0; i < hooks; i++) { - char *iat_hook = strstr(argv[i + 1], "="); - - if (!iat_hook) - continue; - - *iat_hook = '\0'; - debugger_replace_dll_iat(argv[i + 1], iat_hook + 1); - *iat_hook = '='; - } - - return true; -} - -static bool inject_hook_dlls(uint32_t hooks, char **argv) -{ - log_assert(argv); - - log_info("Injecting hook DLLs..."); - - for (int i = 0; i < hooks; i++) { - char *iat_hook = strstr(argv[i + 1], "="); - - if (iat_hook) - continue; - - if (!debugger_inject_dll(argv[i + 1])) { - return false; - } - } - - return true; -} - -static void signal_shutdown_handler() -{ - debugger_finit(true); - logger_finit(); + inject_config_init(config); + inject_config_file_load(path, config); } int main(int argc, char **argv) { - struct options options; - uint32_t hooks; - uint32_t exec_arg_pos; - char *cmd_line; - bool local_debugger; - - if (!init_options(argc, argv, &options)) { - goto init_options_fail; - } + const char *config_path; + inject_config_t config; - if (!logger_init(strlen(options.log_file) > 0 ? options.log_file : NULL)) { - goto init_logger_fail; - } + core_boot("inject"); - os_version_log(); + config_path = argv[1]; - signal_exception_handler_init(); - // Cleanup remote process on CTRL+C - signal_register_shutdown_handler(signal_shutdown_handler); + // Duct-tape to allow access to config path and load config in hook dlls + SetEnvironmentVariable("INJECT_CONFIG_PATH", config_path); - if (!verify_hook_dll_and_exec_args_and_count_hooks( - argc, argv, &hooks, &exec_arg_pos)) { - goto verify_fail; - } + // TODO make configurable + // core_property_trace_log_enable(true); + // core_property_node_trace_log_enable(true); - if (!verify_hook_dlls_exist(argc, argv, hooks)) { - goto verify_2_fail; - } + _bootstrap_options(argc, argv); + _bootstrap_config(config_path, &config); - // buffer consumed by debugger_init - cmd_line = args_join(argc - exec_arg_pos, argv + exec_arg_pos); + inject_main(&config); - local_debugger = options.debug && !options.remote_debugger; + return 0; - if (!debugger_init(local_debugger, argv[exec_arg_pos], cmd_line)) { - goto debugger_init_fail; - } - if (!inject_iat_hook_dlls(hooks, argv)) { - goto inject_hook_dlls_fail; - } + // inject + // general configuration stuff + // --config (-c) inject-09.xml + // override any parameters with key-value params + // --param (-p) logger.level=asdf + + // some shortcuts for params commonly used + // --loglevel (-l) + // --logfile (-y) + // --remotedebugger (-r) + // --debugger (-d) + // --configslog (-s) + + // -- hook.dll... app.exe [hooks options...] - if (!inject_hook_dlls(hooks, argv)) { - goto inject_hook_dlls_fail; - } - - // Execute this after injecting the DLLs. Some debuggers seem to crash if we - // attach the process before DLL injection (inject's local one doesn't - // crash). However, this means the remote debugger is missing out on all - // injected DLL loads, e.g. calls to DllMain - if (options.remote_debugger) { - if (!debugger_wait_for_remote_debugger()) { - goto debugger_wait_for_remote_debugger_fail; - } - } - - if (!debugger_resume_process()) { - goto debugger_resume_process_fail; - } - - debugger_wait_process_exit(); - - debugger_finit(false); - - logger_finit(); - - return EXIT_SUCCESS; - -debugger_resume_process_fail: -debugger_wait_for_remote_debugger_fail: -inject_hook_dlls_fail: - debugger_finit(true); - -debugger_init_fail: -verify_2_fail: -verify_fail: - logger_finit(); - -init_logger_fail: -init_options_fail: - return EXIT_FAILURE; -} + // TODO + // - options + // - load config + // - apply overrides to config, hook dlls are added +} \ No newline at end of file diff --git a/src/main/jbhook-util-p3io/gfx.c b/src/main/jbhook-util-p3io/gfx.c index 63607fd8..4772eabc 100644 --- a/src/main/jbhook-util-p3io/gfx.c +++ b/src/main/jbhook-util-p3io/gfx.c @@ -12,12 +12,13 @@ #include "hook/com-proxy.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/glhelper.h" #include "jbhook-util-p3io/gfx.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #include "util/time.h" diff --git a/src/main/jbhook-util-p3io/mixer.c b/src/main/jbhook-util-p3io/mixer.c index 30dcace9..89c48d5b 100644 --- a/src/main/jbhook-util-p3io/mixer.c +++ b/src/main/jbhook-util-p3io/mixer.c @@ -8,8 +8,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" MMRESULT STDCALL hook_mixerGetLineControlsA( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls); diff --git a/src/main/jbhook-util-p3io/p3io.c b/src/main/jbhook-util-p3io/p3io.c index 25b3364f..cfded20a 100644 --- a/src/main/jbhook-util-p3io/p3io.c +++ b/src/main/jbhook-util-p3io/p3io.c @@ -3,7 +3,8 @@ #include #include -#include "bemanitools/jbio.h" +#include "iface-core/log.h" +#include "iface-io/jb.h" #include "jbhook-util-p3io/p3io.h" @@ -13,8 +14,6 @@ #include "security/rp-sign-key.h" #include "security/rp3.h" -#include "util/log.h" - static HRESULT jbhook_p3io_read_jamma(void *ctx, uint32_t *state); static HRESULT jbhook_p3io_get_roundplug( void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom); @@ -119,13 +118,13 @@ static HRESULT jbhook_p3io_read_jamma(void *ctx, uint32_t *state) state_tmp = 0; - if (!jb_io_read_inputs()) { + if (!bt_io_jb_inputs_read()) { log_warning("Reading inputs from jbio failed"); return E_FAIL; } - panels = jb_io_get_panel_inputs(); - buttons = jb_io_get_sys_inputs(); + panels = bt_io_jb_panel_inputs_get(); + buttons = bt_io_jb_sys_inputs_get(); for (uint8_t i = 0; i < 16; i++) { // panels are active-low @@ -189,30 +188,30 @@ static HRESULT jbhook_p3io_set_outputs(void *ctx, uint32_t state) uint8_t p3io_panel = (state & 0x00FF00) >> 8; uint8_t p3io_coinblocker = (state & 0xFF0000) >> 16; - enum jb_io_panel_mode panel_mode; + bt_io_jb_panel_mode_t panel_mode; switch (p3io_panel) { case 5: - panel_mode = JB_IO_PANEL_MODE_TOP_LEFT; + panel_mode = BT_IO_JB_PANEL_MODE_TOP_LEFT; break; case 4: - panel_mode = JB_IO_PANEL_MODE_TOP_RIGHT; + panel_mode = BT_IO_JB_PANEL_MODE_TOP_RIGHT; break; case 6: - panel_mode = JB_IO_PANEL_MODE_BOTTOM_RIGHT; + panel_mode = BT_IO_JB_PANEL_MODE_BOTTOM_RIGHT; break; case 7: - panel_mode = JB_IO_PANEL_MODE_BOTTOM_LEFT; + panel_mode = BT_IO_JB_PANEL_MODE_BOTTOM_LEFT; break; default: - panel_mode = JB_IO_PANEL_MODE_ALL; + panel_mode = BT_IO_JB_PANEL_MODE_ALL; break; } - jb_io_set_panel_mode(panel_mode); + bt_io_jb_panel_mode_set(panel_mode); // 0x40 has been seen to unblock, no other values observed - jb_io_set_coin_blocker(p3io_coinblocker == 0x00); + bt_io_jb_coin_blocker_set(p3io_coinblocker == 0x00); return S_OK; } diff --git a/src/main/jbhook-util/acio.c b/src/main/jbhook-util/acio.c index a1f5492e..197d32e2 100644 --- a/src/main/jbhook-util/acio.c +++ b/src/main/jbhook-util/acio.c @@ -18,6 +18,8 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "jbhook-util/acio.h" #include "imports/avs.h" @@ -25,7 +27,6 @@ #include "util/defs.h" #include "util/hex.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu ac_io_emu; diff --git a/src/main/jbhook-util/eamuse.c b/src/main/jbhook-util/eamuse.c index 0a796259..364c151a 100644 --- a/src/main/jbhook-util/eamuse.c +++ b/src/main/jbhook-util/eamuse.c @@ -11,8 +11,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/net.h" #include "util/str.h" diff --git a/src/main/jbhook-util/locale.c b/src/main/jbhook-util/locale.c index 272bbc64..5c6255f0 100644 --- a/src/main/jbhook-util/locale.c +++ b/src/main/jbhook-util/locale.c @@ -4,8 +4,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" // ANSI/OEM Japanese; Japanese (Shift-JIS) #define CODEPAGE_SHIFT_JIS 932 diff --git a/src/main/jbhook-util/p4io.c b/src/main/jbhook-util/p4io.c index ab77d5dc..6a7b7659 100644 --- a/src/main/jbhook-util/p4io.c +++ b/src/main/jbhook-util/p4io.c @@ -2,7 +2,8 @@ #include -#include "bemanitools/jbio.h" +#include "iface-core/log.h" +#include "iface-io/jb.h" #include "imports/avs.h" @@ -10,8 +11,6 @@ #include "p4io/cmd.h" -#include "util/log.h" - static void jbhook_io_jamma2_read(void *resp, uint32_t nbytes); static uint32_t jbhook_command_handle( uint8_t cmd, @@ -97,13 +96,13 @@ static void jbhook_io_jamma2_read(void *resp, uint32_t nbytes) /* lower three bytes low active, highest byte high active */ inputs_out = 0x00FFFFFF; - if (!jb_io_read_inputs()) { + if (!bt_io_jb_inputs_read()) { log_warning("Reading inputs from jbio failed"); return; } - panels = jb_io_get_panel_inputs(); - buttons = jb_io_get_sys_inputs(); + panels = bt_io_jb_panel_inputs_get(); + buttons = bt_io_jb_sys_inputs_get(); for (uint8_t i = 0; i < 16; i++) { if (panels & (1 << i)) { @@ -134,7 +133,7 @@ static uint32_t jbhook_command_handle( // on is 0x00, off is either 0x10 or 0x20 depending on whether it's // during gameplay (0x10) or test menu (0x20). Both seem to have the // same effect - jb_io_set_coin_blocker(*(uint8_t *) payload == 0x00); + bt_io_jb_coin_blocker_set(*(uint8_t *) payload == 0x00); // this actually returns the coinstock, don't care for it memset(resp, 0, 4); @@ -147,33 +146,33 @@ static uint32_t jbhook_command_handle( (const struct p4io_req_panel_mode *) payload; // always fallback to ALL if input is unknown - enum jb_io_panel_mode mode = JB_IO_PANEL_MODE_ALL; + bt_io_jb_panel_mode_t mode = BT_IO_JB_PANEL_MODE_ALL; if (req->is_single) { switch (req->mode) { case 0x0001: - mode = JB_IO_PANEL_MODE_TOP_LEFT; + mode = BT_IO_JB_PANEL_MODE_TOP_LEFT; break; case 0x0000: - mode = JB_IO_PANEL_MODE_TOP_RIGHT; + mode = BT_IO_JB_PANEL_MODE_TOP_RIGHT; break; case 0x0101: - mode = JB_IO_PANEL_MODE_BOTTOM_LEFT; + mode = BT_IO_JB_PANEL_MODE_BOTTOM_LEFT; break; case 0x0100: - mode = JB_IO_PANEL_MODE_BOTTOM_RIGHT; + mode = BT_IO_JB_PANEL_MODE_BOTTOM_RIGHT; break; default: - mode = JB_IO_PANEL_MODE_ALL; + mode = BT_IO_JB_PANEL_MODE_ALL; break; } } - jb_io_set_panel_mode(mode); + bt_io_jb_panel_mode_set(mode); memset(resp, 0, 1); diff --git a/src/main/jbhook1/Module.mk b/src/main/jbhook1/Module.mk index b5e47776..7de78b34 100644 --- a/src/main/jbhook1/Module.mk +++ b/src/main/jbhook1/Module.mk @@ -9,12 +9,11 @@ ldflags_jbhook1 := \ -lws2_32 \ -liphlpapi \ -lopengl32 \ + -lshlwapi \ libs_jbhook1 := \ + core \ acioemu \ - cconfig \ - eamio \ - jbio \ jbhook-util \ jbhook-util-p3io \ p3ioemu \ @@ -23,6 +22,12 @@ libs_jbhook1 := \ hooklib \ security \ util \ + iface \ + iface-io \ + iface-core \ + module \ + sdk-hook \ + mxml \ src_jbhook1 := \ avs-boot.c \ @@ -30,4 +35,6 @@ src_jbhook1 := \ config-eamuse.c \ config-security.c \ dllmain.c \ + gfx.c \ + jbhook1.c \ log-gftools.c \ diff --git a/src/main/jbhook1/avs-boot.c b/src/main/jbhook1/avs-boot.c index dccba692..0dc3c246 100644 --- a/src/main/jbhook1/avs-boot.c +++ b/src/main/jbhook1/avs-boot.c @@ -5,14 +5,16 @@ #include #include +#include "core/log-bt.h" + #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "jbhook1/avs-boot.h" -#include "util/log.h" - static void (*real_avs_boot)( struct property_node *config, void *std_heap, @@ -52,6 +54,11 @@ static const struct hook_symbol jbhook1_log_gftools_hook_syms2[] = { .link = (void **) &real_ea3_boot}, }; +static AVS_LOG_WRITER(_avs_boot_log_writer, chars, nchars, ctx) +{ + core_log_bt_direct_sink_write(chars, nchars); +} + static void avs_boot_create_property_str( struct property *config, const char *name, const char *val) { @@ -139,7 +146,7 @@ static void my_avs_boot( sz_std_heap, avs_heap, sz_avs_heap, - log_writer_debug, + _avs_boot_log_writer, NULL); } diff --git a/src/main/jbhook1/config-eamuse.c b/src/main/jbhook1/config-eamuse.c index dba512eb..d3a570b9 100644 --- a/src/main/jbhook1/config-eamuse.c +++ b/src/main/jbhook1/config-eamuse.c @@ -1,144 +1,12 @@ -#include - -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "jbhook1/config-eamuse.h" -#include "util/log.h" -#include "util/net.h" - -#define JBHOOK1_CONFIG_EAMUSE_SERVER_KEY "eamuse.server" -#define JBHOOK1_CONFIG_EAMUSE_PCBID_KEY "eamuse.pcbid" -#define JBHOOK1_CONFIG_EAMUSE_EAMID_KEY "eamuse.eamid" - -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE "localhost:80" -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE security_id_default -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN \ - sizeof(security_id_default) -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE security_id_default -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN \ - sizeof(security_id_default) - -const struct net_addr jbhook1_eamuse_default_server = { - .type = NET_ADDR_TYPE_HOSTNAME, - .hostname.host = "localhost", - .hostname.port = 80, -}; - -void jbhook1_config_eamuse_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - JBHOOK1_CONFIG_EAMUSE_SERVER_KEY, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE, - "URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 " - "(e.g. 127.0.0.1:80) of the target eamuse server. The port is " - "optional " - "but defaults to 80."); - - cconfig_util_set_data( - config, - JBHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - "PCBID"); - - cconfig_util_set_data( - config, - JBHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - "EAMID"); -} - void jbhook1_config_eamuse_get( - struct jbhook1_config_eamuse *config_eamuse, struct cconfig *config) + const bt_core_config_t *config, + jbhook1_config_eamuse_t *config_out) { - char server_url[1024]; - char *tmp; - char *tmp2; - - memset(config_eamuse, 0, sizeof(struct jbhook1_config_eamuse)); - - if (!cconfig_util_get_str( - config, - JBHOOK1_CONFIG_EAMUSE_SERVER_KEY, - server_url, - sizeof(server_url), - JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - JBHOOK1_CONFIG_EAMUSE_SERVER_KEY, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE); - } - - if (!net_str_parse(server_url, &config_eamuse->server)) { - memcpy( - &config_eamuse->server, - &jbhook1_eamuse_default_server, - sizeof(config_eamuse->server)); - tmp = net_addr_to_str(&config_eamuse->server); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!cconfig_util_get_data( - config, - JBHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &config_eamuse->pcbid, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } - - if (!cconfig_util_get_data( - config, - JBHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &config_eamuse->eamid, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } -} + bt_core_config_ext_net_addr_get(config, "eamuse/server", &config_out->server); + bt_core_config_ext_security_id_get(config, "eamuse/pcbid", &config_out->pcbid); + bt_core_config_ext_security_id_get(config, "eamuse/eamid", &config_out->eamid); +} \ No newline at end of file diff --git a/src/main/jbhook1/config-eamuse.h b/src/main/jbhook1/config-eamuse.h index 63df2750..f54c6d81 100644 --- a/src/main/jbhook1/config-eamuse.h +++ b/src/main/jbhook1/config-eamuse.h @@ -1,7 +1,7 @@ #ifndef JBHOOK1_CONFIG_EAMUSE_H #define JBHOOK1_CONFIG_EAMUSE_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/id.h" @@ -10,27 +10,14 @@ /** * Struct holding configuration values for eamuse related items. */ -struct jbhook1_config_eamuse { +typedef struct jbhook1_config_eamuse { struct net_addr server; struct security_id pcbid; struct security_id eamid; -}; +} jbhook1_config_eamuse_t; -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void jbhook1_config_eamuse_init(struct cconfig *config); - -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_eamuse Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void jbhook1_config_eamuse_get( - struct jbhook1_config_eamuse *config_eamuse, struct cconfig *config); + const bt_core_config_t *config, + jbhook1_config_eamuse_t *config_out); #endif \ No newline at end of file diff --git a/src/main/jbhook1/config-gfx.c b/src/main/jbhook1/config-gfx.c index 5215659c..5d512ebd 100644 --- a/src/main/jbhook1/config-gfx.c +++ b/src/main/jbhook1/config-gfx.c @@ -1,54 +1,13 @@ #include -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "jbhook1/config-gfx.h" -#include "util/log.h" - -#define JBHOOK1_CONFIG_GFX_WINDOWED_KEY "gfx.windowed" -#define JBHOOK1_CONFIG_GFX_VERTICAL_KEY "gfx.vertical" - -#define JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false -#define JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE true - -void jbhook1_config_gfx_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - JBHOOK1_CONFIG_GFX_WINDOWED_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE, - "Run the game windowed"); - cconfig_util_set_bool( - config, - JBHOOK1_CONFIG_GFX_VERTICAL_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE, - "Adjust the rotation of the game window so it runs vertically"); -} - void jbhook1_config_gfx_get( - struct jbhook1_config_gfx *config_gfx, struct cconfig *config) + const bt_core_config_t *config, + jbhook1_config_gfx_t *config_out) { - if (!cconfig_util_get_bool( - config, - JBHOOK1_CONFIG_GFX_WINDOWED_KEY, - &config_gfx->windowed, - JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - JBHOOK1_CONFIG_GFX_WINDOWED_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE); - } - if (!cconfig_util_get_bool( - config, - JBHOOK1_CONFIG_GFX_VERTICAL_KEY, - &config_gfx->vertical, - JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - JBHOOK1_CONFIG_GFX_VERTICAL_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE); - } + bt_core_config_ext_bool_get(config, "gfx/windowed", &config_out->windowed); + bt_core_config_ext_bool_get(config, "gfx/vertical", &config_out->vertical); } diff --git a/src/main/jbhook1/config-gfx.h b/src/main/jbhook1/config-gfx.h index e39aecef..cc2c7ced 100644 --- a/src/main/jbhook1/config-gfx.h +++ b/src/main/jbhook1/config-gfx.h @@ -1,31 +1,18 @@ #ifndef JBHOOK1_CONFIG_GFX_H #define JBHOOK1_CONFIG_GFX_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" /** * Struct holding configuration values for GFX related items. */ -struct jbhook1_config_gfx { +typedef struct jbhook1_config_gfx { bool windowed; bool vertical; -}; +} jbhook1_config_gfx_t; -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void jbhook1_config_gfx_init(struct cconfig *config); - -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_gfx Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void jbhook1_config_gfx_get( - struct jbhook1_config_gfx *config_gfx, struct cconfig *config); + const bt_core_config_t *config, + jbhook1_config_gfx_t *config_out); #endif diff --git a/src/main/jbhook1/config-security.c b/src/main/jbhook1/config-security.c index 565081e4..1246b34b 100644 --- a/src/main/jbhook1/config-security.c +++ b/src/main/jbhook1/config-security.c @@ -1,74 +1,10 @@ -#include - -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "jbhook1/config-security.h" -#include "security/mcode.h" - -#include "util/log.h" -#include "util/net.h" - -#define JBHOOK1_CONFIG_SECURITY_MCODE_KEY "security.mcode" - -static const struct security_mcode security_mcode_h44 = { - .header = SECURITY_MCODE_HEADER, - .unkn = SECURITY_MCODE_UNKN_C, - .game = SECURITY_MCODE_GAME_JB_1, - .region = SECURITY_MCODE_REGION_JAPAN, - .cabinet = SECURITY_MCODE_CABINET_A, - .revision = SECURITY_MCODE_REVISION_B, -}; - -void jbhook1_config_security_init(struct cconfig *config) -{ - char *tmp; - - tmp = security_mcode_to_str(&security_mcode_h44); - - cconfig_util_set_str( - config, - JBHOOK1_CONFIG_SECURITY_MCODE_KEY, - tmp, - "Mcode of the game to run."); - - free(tmp); -} - void jbhook1_config_security_get( - struct jbhook1_config_security *config_security, struct cconfig *config) + const bt_core_config_t *config, + jbhook1_config_security_t *config_out) { - char *tmp_default; - char mcode[9]; - - tmp_default = security_mcode_to_str(&security_mcode_h44); - - if (!cconfig_util_get_str( - config, - JBHOOK1_CONFIG_SECURITY_MCODE_KEY, - mcode, - sizeof(mcode) - 1, - tmp_default)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - JBHOOK1_CONFIG_SECURITY_MCODE_KEY, - tmp_default); - } - - mcode[8] = '\0'; - - if (!security_mcode_parse(mcode, &config_security->mcode)) { - log_warning( - "Invalid mcode '%s' specified, fallback to default '%s'", - mcode, - tmp_default); - - memcpy( - &config_security->mcode, - &security_mcode_h44, - sizeof(struct security_mcode)); - } - - free(tmp_default); -} + bt_core_config_ext_security_mcode_get(config, "security/mcode", &config_out->mcode); +} \ No newline at end of file diff --git a/src/main/jbhook1/config-security.h b/src/main/jbhook1/config-security.h index 37e1b126..615e3bb5 100644 --- a/src/main/jbhook1/config-security.h +++ b/src/main/jbhook1/config-security.h @@ -1,34 +1,19 @@ #ifndef JBHOOK1_CONFIG_SECURITY_H #define JBHOOK1_CONFIG_SECURITY_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/mcode.h" -#include "util/net.h" - /** * Struct holding configuration values for security related items. */ -struct jbhook1_config_security { +typedef struct jbhook1_config_security { struct security_mcode mcode; -}; - -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void jbhook1_config_security_init(struct cconfig *config); +} jbhook1_config_security_t; -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_security Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void jbhook1_config_security_get( - struct jbhook1_config_security *config_security, struct cconfig *config); + const bt_core_config_t *config, + jbhook1_config_security_t *config_out); #endif \ No newline at end of file diff --git a/src/main/jbhook1/dllmain.c b/src/main/jbhook1/dllmain.c index 42f8dc9d..245e61b6 100644 --- a/src/main/jbhook1/dllmain.c +++ b/src/main/jbhook1/dllmain.c @@ -1,99 +1,31 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/jbio.h" - -#include "cconfig/cconfig-hook.h" - #include "hook/table.h" -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/rs232.h" - -#include "jbhook1/avs-boot.h" -#include "jbhook1/config-eamuse.h" -#include "jbhook1/config-gfx.h" -#include "jbhook1/config-security.h" -#include "jbhook1/log-gftools.h" +#include "jbhook1/jbhook1.h" -#include "jbhook-util/acio.h" -#include "jbhook-util/eamuse.h" - -#include "jbhook-util-p3io/gfx.h" -#include "jbhook-util-p3io/mixer.h" -#include "jbhook-util-p3io/p3io.h" - -#include "p3ioemu/devmgr.h" -#include "p3ioemu/emu.h" +#include "main/sdk-hook/dllentry.h" #include "util/defs.h" -#include "util/log.h" -#include "util/thread.h" - -#define JBHOOK1_INFO_HEADER \ - "jbhook1 for jubeat" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define JBHOOK1_CMD_USAGE \ - "Usage: inject.exe jbhook1.dll [options...]" static HWND CDECL -my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); -static HWND(CDECL *real_mwindow_create)( +_jbhook1_dllmain_my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); +static HWND(CDECL *_jbhook1_dllmain_real_mwindow_create)( HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); -static BOOL STDCALL my_CreateProcessA( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation); -static BOOL(STDCALL *real_CreateProcessA)( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation); - -static const struct hook_symbol init_hook_syms[] = { +static const struct hook_symbol _jbhook1_dllmain_hook_syms[] = { { .name = "mwindow_create", - .patch = my_mwindow_create, - .link = (void **) &real_mwindow_create, + .patch = _jbhook1_dllmain_my_mwindow_create, + .link = (void **) &_jbhook1_dllmain_real_mwindow_create, }, }; -static const struct hook_symbol kernel32_hook_syms[] = { - { - .name = "CreateProcessA", - .patch = my_CreateProcessA, - .link = (void **) &real_CreateProcessA, - }, -}; - -// so our CreateProcessA hook can check -static bool vertical; - /** * This seems to be a good entry point to intercept before the game calls * anything important (very close to the start of WinMain). */ -static HWND CDECL my_mwindow_create( +static HWND CDECL _jbhook1_dllmain_my_mwindow_create( HINSTANCE hinstance, void *callback, const char *window_title, @@ -101,92 +33,9 @@ static HWND CDECL my_mwindow_create( DWORD window_height, BOOL fullscreen) { - struct cconfig *config; - - struct jbhook1_config_gfx config_gfx; - struct jbhook1_config_eamuse config_eamuse; - struct jbhook1_config_security config_security; - - log_info("-------------------------------------------------------------"); - log_info("---------------- Begin jbhook mwindow_create ----------------"); - log_info("-------------------------------------------------------------"); - - jbhook_util_mixer_hook_init(); - - config = cconfig_init(); - - jbhook1_config_gfx_init(config); - jbhook1_config_eamuse_init(config); - jbhook1_config_security_init(config); - - if (!cconfig_hook_config_init( - config, - JBHOOK1_INFO_HEADER "\n" JBHOOK1_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - jbhook1_config_gfx_get(&config_gfx, config); - jbhook1_config_eamuse_get(&config_eamuse, config); - jbhook1_config_security_get(&config_security, config); - - cconfig_finit(config); - - log_info(JBHOOK1_INFO_HEADER); - log_info("Initializing jbhook..."); - - jbhook1_avs_boot_init(); - jbhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); - jbhook1_log_gftools_init(); - - fullscreen = !config_gfx.windowed; - vertical = config_gfx.vertical; - - if (config_gfx.vertical) { - DWORD tmp = window_width; - window_width = window_height; - window_height = tmp; - - jbhook_util_gfx_install_vertical_hooks(); - } + bt_hook_dllentry_main_init(); - log_info("Starting up jubeat IO backend"); - - jb_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!jb_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing jb IO backend failed"); - } - - log_info("Starting up card reader backend"); - - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - - jbhook_util_eamuse_hook_init(); - - iohook_push_handler(p3io_emu_dispatch_irp); - iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp); - - rs232_hook_init(); - jbhook_util_ac_io_port_init(L"COM1"); - jbhook_util_ac_io_set_iccb(); - - p3io_setupapi_insert_hooks(NULL); - jbhook_util_p3io_init( - &config_security.mcode, &config_eamuse.pcbid, &config_eamuse.eamid); - - log_info("-------------------------------------------------------------"); - log_info("----------------- End jbhook mwindow_create -----------------"); - log_info("-------------------------------------------------------------"); - - return real_mwindow_create( + return _jbhook1_dllmain_real_mwindow_create( hinstance, callback, window_title, @@ -195,68 +44,34 @@ static HWND CDECL my_mwindow_create( fullscreen); } -/** - * Hook library for jubeat (1) - */ +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() + BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - log_to_writer(log_writer_debug, NULL); - - /* Bootstrap hook for further init tasks (see above) */ + bt_hook_dllentry_init( + mod, + "jbhook1", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); hook_table_apply( - NULL, "mwindow.dll", init_hook_syms, lengthof(init_hook_syms)); + NULL, "mwindow.dll", _jbhook1_dllmain_hook_syms, lengthof(_jbhook1_dllmain_hook_syms)); - /* Actual hooks for game specific stuff */ + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "mwindow.dll", _jbhook1_dllmain_hook_syms, lengthof(_jbhook1_dllmain_hook_syms)); - hook_table_apply( - NULL, - "kernel32.dll", - kernel32_hook_syms, - lengthof(kernel32_hook_syms)); + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); - acp_hook_init(); - adapter_hook_init(); - } - - return TRUE; -} - -static BOOL STDCALL my_CreateProcessA( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation) -{ - LPSTR rot_arg; - - // de-rotate the error window if needed. In theory this should parse the - // commandline properly, in practice this works on all the .exe jubeats. - if (vertical && lpCommandLine) { - if ((rot_arg = strstr(lpCommandLine, " -R90 "))) { // jubeat 01 - memcpy(rot_arg, " -R0 ", strlen(" -R0 ")); - } else if ((rot_arg = - strstr(lpCommandLine, " -rot:90 "))) { // jubeat 02 - memcpy(rot_arg, " -rot:0 ", strlen(" -rot:0 ")); + bt_hook_dllentry_fini(); } } - return real_CreateProcessA( - lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation); -} + return TRUE; +} \ No newline at end of file diff --git a/src/main/jbhook1/gfx.c b/src/main/jbhook1/gfx.c new file mode 100644 index 00000000..74ab4cf7 --- /dev/null +++ b/src/main/jbhook1/gfx.c @@ -0,0 +1,158 @@ +#define LOG_MODULE "jbhook1-gfx" + +#include + +#include + +#include "hook/table.h" + +#include "iface-core/log.h" + +#include "jbhook1/config-gfx.h" + +#include "jbhook-util-p3io/gfx.h" + +#include "util/defs.h" + +static jbhook1_config_gfx_t _jbhook1_gfx_config; + +static HWND CDECL +my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); +static HWND(CDECL *real_mwindow_create)( + HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); + +static BOOL STDCALL my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); +static BOOL(STDCALL *real_CreateProcessA)( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); + +static const struct hook_symbol mwindow_hook_syms[] = { + { + .name = "mwindow_create", + .patch = my_mwindow_create, + .link = (void **) &real_mwindow_create, + }, +}; + +static const struct hook_symbol kernel32_hook_syms[] = { + { + .name = "CreateProcessA", + .patch = my_CreateProcessA, + .link = (void **) &real_CreateProcessA, + }, +}; + +static HWND CDECL my_mwindow_create( + HINSTANCE hinstance, + void *callback, + const char *window_title, + DWORD window_width, + DWORD window_height, + BOOL fullscreen) +{ + DWORD tmp; + + fullscreen = !_jbhook1_gfx_config.windowed; + + if (_jbhook1_gfx_config.vertical) { + tmp = window_width; + window_width = window_height; + window_height = tmp; + } + + return real_mwindow_create( + hinstance, + callback, + window_title, + window_width, + window_height, + fullscreen); +} + +static BOOL STDCALL my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +{ + LPSTR rot_arg; + + // de-rotate the error window if needed. In theory this should parse the + // commandline properly, in practice this works on all the .exe jubeats. + if (_jbhook1_gfx_config.vertical && lpCommandLine) { + if ((rot_arg = strstr(lpCommandLine, " -R90 "))) { // jubeat 01 + memcpy(rot_arg, " -R0 ", strlen(" -R0 ")); + } else if ((rot_arg = + strstr(lpCommandLine, " -rot:90 "))) { // jubeat 02 + memcpy(rot_arg, " -rot:0 ", strlen(" -rot:0 ")); + } + } + + return real_CreateProcessA( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation); +} + +void jbhook1_gfx_init(const jbhook1_config_gfx_t *config) +{ + memcpy(&_jbhook1_gfx_config, config, sizeof(_jbhook1_gfx_config)); + + hook_table_apply( + NULL, "mwindow.dll", mwindow_hook_syms, lengthof(mwindow_hook_syms)); + hook_table_apply( + NULL, + "kernel32.dll", + kernel32_hook_syms, + lengthof(kernel32_hook_syms)); + + log_info("Inserted gfx hooks"); + + if (_jbhook1_gfx_config.vertical) { + jbhook_util_gfx_install_vertical_hooks(); + } +} + +void jbhook1_gfx_fini() +{ + hook_table_revert( + NULL, "mwindow.dll", mwindow_hook_syms, lengthof(mwindow_hook_syms)); + hook_table_revert( + NULL, + "kernel32.dll", + kernel32_hook_syms, + lengthof(kernel32_hook_syms)); + + log_info("Removed gfx hooks"); +} \ No newline at end of file diff --git a/src/main/jbhook1/gfx.h b/src/main/jbhook1/gfx.h new file mode 100644 index 00000000..5768f8b7 --- /dev/null +++ b/src/main/jbhook1/gfx.h @@ -0,0 +1,10 @@ +#ifndef JBHOOK1_GFX_H +#define JBHOOK1_GFX_H + +#include "jbhook1/config-gfx.h" + +void jbhook1_gfx_init(const jbhook1_config_gfx_t *config); + +void jbhook1_gfx_fini(); + +#endif \ No newline at end of file diff --git a/src/main/jbhook1/jbhook1.c b/src/main/jbhook1/jbhook1.c new file mode 100644 index 00000000..738de2b2 --- /dev/null +++ b/src/main/jbhook1/jbhook1.c @@ -0,0 +1,153 @@ +#include + +#include +#include +#include +#include + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/jb.h" + +#include "jbhook1/avs-boot.h" +#include "jbhook1/config-eamuse.h" +#include "jbhook1/config-gfx.h" +#include "jbhook1/config-security.h" +#include "jbhook1/gfx.h" +#include "jbhook1/log-gftools.h" + +#include "jbhook-util/acio.h" +#include "jbhook-util/eamuse.h" + +#include "jbhook-util-p3io/mixer.h" +#include "jbhook-util-p3io/p3io.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "p3ioemu/devmgr.h" +#include "p3ioemu/emu.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +static module_io_t *jbhook_module_io_jb; +static module_io_t *jbhook_module_io_eam; + +static void _jbhook1_io_jb_init(module_io_t **module) +{ + bt_io_jb_api_t api; + + module_io_ext_load_and_init("jbio.dll", "bt_module_io_jb_api_get", module); + module_io_api_get(*module, &api); + bt_io_jb_api_set(&api); +} + +static void _jbhook1_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_jbhook1_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + jbhook1_config_gfx_t config_gfx; + jbhook1_config_eamuse_t config_eamuse; + jbhook1_config_security_t config_security; + + log_info("jbhook for jubeat and jubeat ripples"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + jbhook1_config_gfx_get(config, &config_gfx); + jbhook1_config_eamuse_get(config, &config_eamuse); + jbhook1_config_security_get(config, &config_security); + + acp_hook_init(); + adapter_hook_init(); + + // TODO this won't work because it modifies the parameters of the mwindow_create + // call which is also used for bootstrapping this function (_jbhook1_main_init) + // Introducing the additional abstraction and glue code to further separate + // concerns, a different function before mwindow_create must be used in + // dllmain to bootstrap the main hooking code here, so the mwindow_create + // hook can be set up in advance and then be invoked by the game + jbhook1_gfx_init(&config_gfx); + + jbhook1_avs_boot_init(); + jbhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); + jbhook1_log_gftools_init(); + jbhook_util_mixer_hook_init(); + + log_info("Starting up jubeat IO backend"); + + _jbhook1_io_jb_init(&jbhook_module_io_jb); + + if (!bt_io_jb_init()) { + log_fatal("Initializing jb IO backend failed"); + } + + log_info("Starting up card reader backend"); + + _jbhook1_io_eam_init(&jbhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + + jbhook_util_eamuse_hook_init(); + + iohook_push_handler(p3io_emu_dispatch_irp); + iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp); + + rs232_hook_init(); + jbhook_util_ac_io_port_init(L"COM1"); + jbhook_util_ac_io_set_iccb(); + + p3io_setupapi_insert_hooks(NULL); + jbhook_util_p3io_init( + &config_security.mcode, &config_eamuse.pcbid, &config_eamuse.eamid); + + return true; +} + +static void _jbhook1_main_fini() +{ + // TODO cleanup +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _jbhook1_main_init; + api->v1.main_fini = _jbhook1_main_fini; +} \ No newline at end of file diff --git a/src/main/jbhook1/jbhook1.def b/src/main/jbhook1/jbhook1.def index 3f6d499a..6d5812cc 100644 --- a/src/main/jbhook1/jbhook1.def +++ b/src/main/jbhook1/jbhook1.def @@ -2,3 +2,9 @@ LIBRARY jbhook1 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/jbhook1/jbhook1.h b/src/main/jbhook1/jbhook1.h new file mode 100644 index 00000000..3f747b18 --- /dev/null +++ b/src/main/jbhook1/jbhook1.h @@ -0,0 +1,9 @@ +#ifndef JBHOOK1_H +#define JBHOOK1_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/jbhook1/log-gftools.c b/src/main/jbhook1/log-gftools.c index 97721736..dd5622bf 100644 --- a/src/main/jbhook1/log-gftools.c +++ b/src/main/jbhook1/log-gftools.c @@ -5,9 +5,9 @@ #include #include -#include "hook/table.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "hook/table.h" static int CDECL my_GFReportPuts( int level, diff --git a/src/main/jbhook2/Module.mk b/src/main/jbhook2/Module.mk index 2573867f..4a88a307 100644 --- a/src/main/jbhook2/Module.mk +++ b/src/main/jbhook2/Module.mk @@ -9,10 +9,12 @@ ldflags_jbhook2 := \ -liphlpapi \ -lopengl32 \ +avslibs_jbhook2 := \ + avs-ext \ + libs_jbhook2 := \ + core \ acioemu \ - eamio \ - jbio \ jbhook-util \ jbhook-util-p3io \ p3ioemu \ @@ -22,6 +24,10 @@ libs_jbhook2 := \ hooklib \ security \ util \ + iface \ + iface-io \ + iface-core \ + module \ src_jbhook2 := \ dllmain.c \ diff --git a/src/main/jbhook2/dllmain.c b/src/main/jbhook2/dllmain.c index a8523ad9..98f99272 100644 --- a/src/main/jbhook2/dllmain.c +++ b/src/main/jbhook2/dllmain.c @@ -5,18 +5,18 @@ #include #include -#include "bemanitools/eamio.h" -#include "bemanitools/jbio.h" - #include "hook/iohook.h" #include "hook/table.h" #include "hooklib/adapter.h" -#include "hooklib/app.h" #include "hooklib/rs232.h" #include "hooklib/setupapi.h" -#include "imports/avs.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/jb.h" #include "jbhook2/options.h" @@ -26,6 +26,9 @@ #include "jbhook-util-p3io/gfx.h" #include "jbhook-util-p3io/p3io.h" +#include "module/io-ext.h" +#include "module/io.h" + #include "p3ioemu/devmgr.h" #include "p3ioemu/emu.h" @@ -35,13 +38,83 @@ #include "security/id.h" #include "security/mcode.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + #include "util/defs.h" -#include "util/log.h" -#include "util/thread.h" static struct options options; +static module_io_t *jbhook_module_io_jb; +static module_io_t *jbhook_module_io_eam; + +static HWND CDECL +my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); +static HWND(CDECL *real_mwindow_create)( + HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); -static bool my_dll_entry_init(char *sidcode, struct property_node *param) +static const struct hook_symbol init_hook_syms[] = { + { + .name = "mwindow_create", + .patch = my_mwindow_create, + .link = (void **) &real_mwindow_create, + }, +}; + +static HWND CDECL my_mwindow_create( + HINSTANCE hinstance, + void *callback, + const char *window_title, + DWORD window_width, + DWORD window_height, + BOOL fullscreen) +{ + log_info("-------------------------------------------------------------"); + log_info("---------------- Begin jbhook mwindow_create ----------------"); + log_info("-------------------------------------------------------------"); + + if (options.vertical) { + DWORD tmp = window_width; + window_width = window_height; + window_height = tmp; + } + + if (options.show_cursor) { + ShowCursor(TRUE); + } + + fullscreen = !options.windowed; + + return real_mwindow_create( + hinstance, + callback, + window_title, + window_width, + window_height, + fullscreen); +} + +static void _jbhook2_io_jb_init(module_io_t **module) +{ + bt_io_jb_api_t api; + + module_io_ext_load_and_init("jbio.dll", "bt_module_io_jb_api_get", module); + module_io_api_get(*module, &api); + bt_io_jb_api_set(&api); +} + +static void _jbhook2_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_jbhook2_main_init(HMODULE game_module, const bt_core_config_t *config_) { bool eam_io_ok; bool jb_io_ok; @@ -51,8 +124,21 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("--- Begin jbhook dll_entry_init ---"); + char *sidcode = NULL; // TODO this isn't propagated with the new api anymore, what to do? + log_assert(sidcode != NULL); + options_init_from_cmdline(&options); + + hook_table_apply( + NULL, "mwindow.dll", init_hook_syms, lengthof(init_hook_syms)); + + if (!options.disable_adapteremu) { + adapter_hook_init(); + } + + jbhook_util_eamuse_hook_init(); + if (options.vertical) { jbhook_util_gfx_install_vertical_hooks(); } @@ -80,11 +166,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("Starting up jubeat IO backend"); - jb_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _jbhook2_io_jb_init(&jbhook_module_io_jb); - jb_io_ok = - jb_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + jb_io_ok = bt_io_jb_init(); if (!jb_io_ok) { goto fail; @@ -99,11 +183,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("Starting up card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _jbhook2_io_eam_init(&jbhook_module_io_eam); - eam_io_ok = - eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + eam_io_ok = bt_io_eam_init(); if (!eam_io_ok) { goto fail; @@ -114,7 +196,8 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) char *sidcode_in_ea3_config = strdup(sidcode); - bool ret = app_hook_invoke_init(sidcode, param); + // TODO the following needs the sidcode back-propagation, figure something out + // bool ret = app_hook_invoke_init(sidcode, param); // If the game is append, the mcode `cabinet` is forced to C. This is bad if // p3io was configured to respond as A! Help the user help themsevles... @@ -133,112 +216,71 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) free(sidcode_in_ea3_config); - return ret; + return true; fail: if (eam_io_ok) { - eam_io_fini(); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&jbhook_module_io_eam); } if (jb_io_ok) { - jb_io_fini(); + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&jbhook_module_io_jb); } return false; } -static bool my_dll_entry_main(void) +static void _jbhook2_main_fini() { - bool result; - - result = app_hook_invoke_main(); - - log_info("Shutting down card reader backend"); - eam_io_fini(); - - log_info("Shutting down Jubeat IO backend"); - jb_io_fini(); - if (!options.disable_cardemu) { + log_info("Shutting down card reader backend"); + jbhook_util_ac_io_port_fini(); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&jbhook_module_io_eam); } if (!options.disable_p3ioemu) { + log_info("Shutting down Jubeat IO backend"); + jbhook_util_p3io_fini(); + + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&jbhook_module_io_jb); } options_fini(&options); - - return result; } -static HWND CDECL -my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); -static HWND(CDECL *real_mwindow_create)( - HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); - -static const struct hook_symbol init_hook_syms[] = { - { - .name = "mwindow_create", - .patch = my_mwindow_create, - .link = (void **) &real_mwindow_create, - }, -}; - -static HWND CDECL my_mwindow_create( - HINSTANCE hinstance, - void *callback, - const char *window_title, - DWORD window_width, - DWORD window_height, - BOOL fullscreen) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - log_info("-------------------------------------------------------------"); - log_info("---------------- Begin jbhook mwindow_create ----------------"); - log_info("-------------------------------------------------------------"); - - if (options.vertical) { - DWORD tmp = window_width; - window_width = window_height; - window_height = tmp; - } + bt_core_log_api_set(api); +} - if (options.show_cursor) { - ShowCursor(TRUE); - } +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} - fullscreen = !options.windowed; +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; - return real_mwindow_create( - hinstance, - callback, - window_title, - window_width, - window_height, - fullscreen); + api->v1.main_init = _jbhook2_main_init; + api->v1.main_fini = _jbhook2_main_fini; } BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - return TRUE; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - options_init_from_cmdline(&options); - - hook_table_apply( - NULL, "mwindow.dll", init_hook_syms, lengthof(init_hook_syms)); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - if (!options.disable_adapteremu) { - adapter_hook_init(); - } - - jbhook_util_eamuse_hook_init(); - return TRUE; } diff --git a/src/main/jbhook2/jbhook2.def b/src/main/jbhook2/jbhook2.def index cccec244..c1f12f38 100644 --- a/src/main/jbhook2/jbhook2.def +++ b/src/main/jbhook2/jbhook2.def @@ -2,3 +2,8 @@ LIBRARY jbhook2 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/jbhook2/options.c b/src/main/jbhook2/options.c index 9e1987e4..63ee6d45 100644 --- a/src/main/jbhook2/options.c +++ b/src/main/jbhook2/options.c @@ -9,7 +9,7 @@ #include "util/cmdline.h" #include "util/defs.h" #include "util/hex.h" -#include "util/log.h" + #include "util/str.h" void options_init_from_cmdline(struct options *options) diff --git a/src/main/jbhook3/Module.mk b/src/main/jbhook3/Module.mk index a82c4cc9..51330d0e 100644 --- a/src/main/jbhook3/Module.mk +++ b/src/main/jbhook3/Module.mk @@ -7,10 +7,12 @@ ldflags_jbhook3 := \ -lws2_32 \ -liphlpapi \ +avslibs_jbhook3 := \ + avs-ext \ + libs_jbhook3 := \ + core \ acioemu \ - eamio \ - jbio \ jbhook-util \ p3ioemu \ p3io \ @@ -19,6 +21,10 @@ libs_jbhook3 := \ hooklib \ security \ util \ + iface \ + iface-io \ + iface-core \ + module \ src_jbhook3 := \ dllmain.c \ diff --git a/src/main/jbhook3/dllmain.c b/src/main/jbhook3/dllmain.c index b4eada83..18e7ef37 100644 --- a/src/main/jbhook3/dllmain.c +++ b/src/main/jbhook3/dllmain.c @@ -5,18 +5,18 @@ #include #include -#include "bemanitools/eamio.h" -#include "bemanitools/jbio.h" - #include "hook/iohook.h" #include "hook/table.h" #include "hooklib/adapter.h" -#include "hooklib/app.h" #include "hooklib/rs232.h" #include "hooklib/setupapi.h" -#include "imports/avs.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/jb.h" #include "jbhook3/gfx.h" #include "jbhook3/options.h" @@ -25,18 +25,45 @@ #include "jbhook-util/eamuse.h" #include "jbhook-util/p4io.h" +#include "module/io-ext.h" +#include "module/io.h" + #include "p4ioemu/device.h" #include "p4ioemu/setupapi.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + #include "security/id.h" #include "util/defs.h" -#include "util/log.h" -#include "util/thread.h" static struct options options; +static module_io_t *jbhook_module_io_jb; +static module_io_t *jbhook_module_io_eam; -static bool my_dll_entry_init(char *sidcode, struct property_node *param) +static void _jbhook3_io_jb_init(module_io_t **module) +{ + bt_io_jb_api_t api; + + module_io_ext_load_and_init("jbio.dll", "bt_module_io_jb_api_get", module); + module_io_api_get(*module, &api); + bt_io_jb_api_set(&api); +} + +static void _jbhook3_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_jbhook3_main_init(HMODULE game_module, const bt_core_config_t *config_) { bool eam_io_ok; bool jb_io_ok; @@ -46,6 +73,14 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("--- Begin jbhook dll_entry_init ---"); + options_init_from_cmdline(&options); + + if (!options.disable_adapteremu) { + adapter_hook_init(); + } + + jbhook_util_eamuse_hook_init(); + iohook_push_handler(p4ioemu_dispatch_irp); iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp); @@ -62,11 +97,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) if (!options.disable_p4ioemu) { log_info("Starting up jubeat IO backend"); - jb_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _jbhook3_io_jb_init(&jbhook_module_io_jb); - jb_io_ok = - jb_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + jb_io_ok = bt_io_jb_init(); if (!jb_io_ok) { goto fail; @@ -79,11 +112,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) if (!options.disable_cardemu) { log_info("Starting up card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _jbhook3_io_eam_init(&jbhook_module_io_eam); - eam_io_ok = - eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + eam_io_ok = bt_io_eam_init(); if (!eam_io_ok) { goto fail; @@ -96,65 +127,71 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("--- End jbhook dll_entry_init ---"); - bool ret = app_hook_invoke_init(sidcode, param); - - return ret; + return true; fail: if (eam_io_ok) { - eam_io_fini(); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&jbhook_module_io_eam); } if (jb_io_ok) { - jb_io_fini(); + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&jbhook_module_io_jb); } return false; } -static bool my_dll_entry_main(void) +static void _jbhook3_main_fini() { - bool result; - - result = app_hook_invoke_main(); - - log_info("Shutting down card reader backend"); - eam_io_fini(); - - log_info("Shutting down Jubeat IO backend"); - jb_io_fini(); - if (!options.disable_cardemu) { + log_info("Shutting down card reader backend"); + jbhook_util_ac_io_port_fini(); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&jbhook_module_io_eam); } if (!options.disable_p4ioemu) { + log_info("Shutting down Jubeat IO backend"); + p4ioemu_fini(); + + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&jbhook_module_io_jb); } options_fini(&options); - - return result; } -BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - if (reason != DLL_PROCESS_ATTACH) { - return TRUE; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - options_init_from_cmdline(&options); + bt_core_log_api_set(api); +} - app_hook_init(my_dll_entry_init, my_dll_entry_main); +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} - if (!options.disable_adapteremu) { - adapter_hook_init(); - } +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; - jbhook_util_eamuse_hook_init(); + api->v1.main_init = _jbhook3_main_init; + api->v1.main_fini = _jbhook3_main_fini; +} +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ return TRUE; } diff --git a/src/main/jbhook3/gfx.c b/src/main/jbhook3/gfx.c index ee3b5ff5..055a8c05 100644 --- a/src/main/jbhook3/gfx.c +++ b/src/main/jbhook3/gfx.c @@ -7,9 +7,9 @@ #include "hook/table.h" -#include "jbhook3/options.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "jbhook3/options.h" static bool jbhook3_gfx_windowed; static bool jbhook3_gfx_show_cursor; diff --git a/src/main/jbhook3/jbhook3.def b/src/main/jbhook3/jbhook3.def index a1b99b72..fbfcff6c 100644 --- a/src/main/jbhook3/jbhook3.def +++ b/src/main/jbhook3/jbhook3.def @@ -2,3 +2,8 @@ LIBRARY jbhook3 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/jbhook3/options.c b/src/main/jbhook3/options.c index 59ffc1eb..bab5f276 100644 --- a/src/main/jbhook3/options.c +++ b/src/main/jbhook3/options.c @@ -6,10 +6,11 @@ #include #include +#include "iface-core/log.h" + #include "util/cmdline.h" #include "util/defs.h" #include "util/hex.h" -#include "util/log.h" #include "util/str.h" void options_init_from_cmdline(struct options *options) diff --git a/src/main/jbio-magicbox/Module.mk b/src/main/jbio-magicbox/Module.mk index 1d24eb43..fcdd6488 100644 --- a/src/main/jbio-magicbox/Module.mk +++ b/src/main/jbio-magicbox/Module.mk @@ -3,6 +3,10 @@ imps += ch341 deplibs_jbio-magicbox := \ ch341 \ + iface \ + module \ + iface-core \ + util \ src_jbio-magicbox := \ jbio.c \ diff --git a/src/main/jbio-magicbox/jbio-magicbox.def b/src/main/jbio-magicbox/jbio-magicbox.def index 4920f405..c665b51b 100644 --- a/src/main/jbio-magicbox/jbio-magicbox.def +++ b/src/main/jbio-magicbox/jbio-magicbox.def @@ -1,13 +1,17 @@ LIBRARY jbio EXPORTS - jb_io_fini - jb_io_get_panel_inputs - jb_io_get_sys_inputs - jb_io_init - jb_io_read_inputs - jb_io_set_loggers - jb_io_set_rgb_led - jb_io_set_coin_blocker - jb_io_set_panel_mode - jb_io_write_lights + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_io_jb_api_get + + ; Direct API + bt_io_jb_init + bt_io_jb_fini + bt_io_jb_inputs_read + bt_io_jb_sys_inputs_get + bt_io_jb_panel_inputs_get + bt_io_jb_rgb_led_set + bt_io_jb_lights_write + bt_io_jb_panel_mode_set + bt_io_jb_coin_blocker_set diff --git a/src/main/jbio-magicbox/jbio.c b/src/main/jbio-magicbox/jbio.c index 3aa02be1..a265ffba 100644 --- a/src/main/jbio-magicbox/jbio.c +++ b/src/main/jbio-magicbox/jbio.c @@ -1,10 +1,19 @@ +#define LOG_MODULE "jbio-magicbox" + // This implementation is ported from the device.dll source graciously // provided by zyp #include -#include "bemanitools/jbio.h" +#include "api/core/log.h" + +#include "iface-core/log.h" + #include "imports/ch341.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/io/jb.h" + #include "util/defs.h" static uint16_t jb_io_panels; @@ -12,35 +21,15 @@ static uint8_t jb_io_sys_buttons; static bool is_initialized = false; -static log_formatter_t jb_io_log_misc; -static log_formatter_t jb_io_log_info; -static log_formatter_t jb_io_log_warning; -static log_formatter_t jb_io_log_fatal; - union magicbox_input { uint32_t dword; uint8_t bytes[4]; }; -void jb_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - jb_io_log_misc = misc; - jb_io_log_info = info; - jb_io_log_warning = warning; - jb_io_log_fatal = fatal; -} - -bool jb_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_jb_init() { if (CH341OpenDevice(0) < 0) { - jb_io_log_warning("jbio", "Can't open CH341 device.\n"); + log_warning("jbio", "Can't open CH341 device.\n"); return false; } @@ -49,7 +38,7 @@ bool jb_io_init( return true; } -void jb_io_fini(void) +void bt_io_jb_fini() { CH341CloseDevice(0); } @@ -79,7 +68,7 @@ static const uint32_t magic_sys_mappings[] = { (1 << 0x13), // COIN }; -bool jb_io_read_inputs(void) +bool bt_io_jb_inputs_read() { // Read IO board unsigned long size; @@ -119,34 +108,55 @@ bool jb_io_read_inputs(void) return true; } -bool jb_io_write_lights(void) +bool bt_io_jb_lights_write() { return true; } -uint8_t jb_io_get_sys_inputs(void) +uint8_t bt_io_jb_sys_inputs_get() { return jb_io_sys_buttons; } -uint16_t jb_io_get_panel_inputs(void) +uint16_t bt_io_jb_panel_inputs_get() { return jb_io_panels; } -void jb_io_set_rgb_led(enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b) +void bt_io_jb_rgb_led_set( + bt_io_jb_rgb_led_t unit, uint8_t r, uint8_t g, uint8_t b) { // I mean I guess there's reactive LEDs on the sides? I'm not going to the // effort to work out if they're controllable or not } -bool jb_io_set_panel_mode(enum jb_io_panel_mode mode) +bool bt_io_jb_panel_mode_set(bt_io_jb_panel_mode_t mode) { // panel always returns merged input state, no corner support return true; } -bool jb_io_set_coin_blocker(bool blocked) +bool bt_io_jb_coin_blocker_set(bool blocked) { return true; } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_io_jb_api_get(bt_io_jb_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_jb_init; + api->v1.fini = bt_io_jb_fini; + api->v1.inputs_read = bt_io_jb_inputs_read; + api->v1.sys_inputs_get = bt_io_jb_sys_inputs_get; + api->v1.panel_inputs_get = bt_io_jb_panel_inputs_get; + api->v1.rgb_led_set = bt_io_jb_rgb_led_set; + api->v1.lights_write = bt_io_jb_lights_write; + api->v1.panel_mode_set = bt_io_jb_panel_mode_set; + api->v1.coin_blocker_set = bt_io_jb_coin_blocker_set; +} \ No newline at end of file diff --git a/src/main/jbio-p4io/Module.mk b/src/main/jbio-p4io/Module.mk index b31604df..2ccda69b 100644 --- a/src/main/jbio-p4io/Module.mk +++ b/src/main/jbio-p4io/Module.mk @@ -1,16 +1,21 @@ dlls += jbio-p4io ldflags_jbio-p4io := \ - -lsetupapi - -src_jbio-p4io := \ - config-h44b.c \ - h44b.c \ - jbio.c \ + -lsetupapi \ + -lws2_32 \ libs_jbio-p4io := \ + core \ aciodrv \ - aciomgr \ - cconfig \ p4iodrv \ util \ + iface \ + module \ + iface-core \ + iface-acio \ + security \ + +src_jbio-p4io := \ + config-h44b.c \ + h44b.c \ + jbio.c \ diff --git a/src/main/jbio-p4io/config-h44b.c b/src/main/jbio-p4io/config-h44b.c index 91d37cb8..88d2ce0c 100644 --- a/src/main/jbio-p4io/config-h44b.c +++ b/src/main/jbio-p4io/config-h44b.c @@ -1,55 +1,11 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "jbio-p4io/config-h44b.h" -#include "util/log.h" - -#define JBIO_CONFIG_H44B_PORT_KEY "h44b.port" -#define JBIO_CONFIG_H44B_BAUD_KEY "h44b.baud" - -#define JBIO_CONFIG_H44B_DEFAULT_PORT_VALUE "COM2" -#define JBIO_CONFIG_H44B_DEFAULT_BAUD_VALUE 57600 - -void jbio_config_h44b_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - JBIO_CONFIG_H44B_PORT_KEY, - JBIO_CONFIG_H44B_DEFAULT_PORT_VALUE, - "H44B serial port"); - - cconfig_util_set_int( - config, - JBIO_CONFIG_H44B_BAUD_KEY, - JBIO_CONFIG_H44B_DEFAULT_BAUD_VALUE, - "H44B bus baudrate (real devices expect 57600)"); -} - void jbio_config_h44b_get( - struct h44b_config *config_h44b, struct cconfig *config) + const bt_core_config_t *config, + h44b_config_t *config_out) { - if (!cconfig_util_get_str( - config, - JBIO_CONFIG_H44B_PORT_KEY, - config_h44b->port, - sizeof(config_h44b->port) - 1, - JBIO_CONFIG_H44B_DEFAULT_PORT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - JBIO_CONFIG_H44B_PORT_KEY, - JBIO_CONFIG_H44B_DEFAULT_PORT_VALUE); - } - - if (!cconfig_util_get_int( - config, - JBIO_CONFIG_H44B_BAUD_KEY, - &config_h44b->baud, - JBIO_CONFIG_H44B_DEFAULT_BAUD_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - JBIO_CONFIG_H44B_BAUD_KEY, - JBIO_CONFIG_H44B_DEFAULT_BAUD_VALUE); - } + bt_core_config_str_get(config, "h44b/port", config_out->port, sizeof(config_out->port)); + bt_core_config_s32_get(config, "h44b/baud", &config_out->baud); } diff --git a/src/main/jbio-p4io/config-h44b.h b/src/main/jbio-p4io/config-h44b.h index cdc33f97..69195474 100644 --- a/src/main/jbio-p4io/config-h44b.h +++ b/src/main/jbio-p4io/config-h44b.h @@ -1,18 +1,15 @@ #ifndef JBIO_CONFIG_H44B_H #define JBIO_CONFIG_H44B_H -#include +#include "api/core/config.h" -#include "cconfig/cconfig.h" - -struct h44b_config { +typedef struct h44b_config { char port[64]; int32_t baud; -}; - -void jbio_config_h44b_init(struct cconfig *config); +} h44b_config_t; void jbio_config_h44b_get( - struct h44b_config *config_h44b, struct cconfig *config); + const bt_core_config_t *config, + h44b_config_t *config_out); #endif diff --git a/src/main/jbio-p4io/h44b.c b/src/main/jbio-p4io/h44b.c index 1d9b77a0..585f13d4 100644 --- a/src/main/jbio-p4io/h44b.c +++ b/src/main/jbio-p4io/h44b.c @@ -8,19 +8,18 @@ #include "aciodrv/h44b.h" -#include "aciomgr/manager.h" - -#include "util/log.h" +#include "iface-acio/mgr.h" +#include "iface-core/log.h" static int16_t h44b_node_id; static atomic_bool running; -static struct aciomgr_port_dispatcher *acio_manager_ctx; +static bt_acio_mgr_port_dispatcher_t *acio_manager_ctx; bool jb_io_h44b_init(const char *port, int32_t baud) { - acio_manager_ctx = aciomgr_port_init(port, baud); + acio_manager_ctx = bt_acio_mgr_port_init(port, baud); if (acio_manager_ctx == NULL) { log_info("Opening acio device on [%s] failed", port); @@ -29,14 +28,14 @@ bool jb_io_h44b_init(const char *port, int32_t baud) log_info("Opening acio device successful"); - uint8_t node_count = aciomgr_get_node_count(acio_manager_ctx); + uint8_t node_count = bt_acio_mgr_node_count_get(acio_manager_ctx); log_info("Enumerated %d nodes", node_count); h44b_node_id = -1; for (uint8_t i = 0; i < node_count; i++) { char product[4]; - aciomgr_get_node_product_ident(acio_manager_ctx, i, product); + bt_acio_mgr_node_product_ident_get(acio_manager_ctx, i, product); log_info( "> %d: %c%c%c%c", i, @@ -57,8 +56,8 @@ bool jb_io_h44b_init(const char *port, int32_t baud) log_warning("Using H44B on node: %d", h44b_node_id); bool init_result = aciodrv_h44b_init( - aciomgr_port_checkout(acio_manager_ctx), h44b_node_id); - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkout(acio_manager_ctx), h44b_node_id); + bt_acio_mgr_port_checkin(acio_manager_ctx); if (!init_result) { log_warning("Unable to start H44B on node: %d", h44b_node_id); @@ -76,7 +75,7 @@ bool jb_io_h44b_init(const char *port, int32_t baud) bool jb_io_h44b_fini(void) { - aciomgr_port_fini(acio_manager_ctx); + bt_acio_mgr_port_fini(acio_manager_ctx); return true; } @@ -88,8 +87,8 @@ bool jb_io_h44b_write_lights(struct ac_io_h44b_output *lights) } bool amp_result = aciodrv_h44b_lights( - aciomgr_port_checkout(acio_manager_ctx), h44b_node_id, lights); - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkout(acio_manager_ctx), h44b_node_id, lights); + bt_acio_mgr_port_checkin(acio_manager_ctx); if (!amp_result) { return false; diff --git a/src/main/jbio-p4io/jbio-p4io.def b/src/main/jbio-p4io/jbio-p4io.def index e923ef7c..cd7c2969 100644 --- a/src/main/jbio-p4io/jbio-p4io.def +++ b/src/main/jbio-p4io/jbio-p4io.def @@ -1,13 +1,19 @@ LIBRARY jbio EXPORTS - jb_io_fini - jb_io_get_panel_inputs - jb_io_get_sys_inputs - jb_io_init - jb_io_read_inputs - jb_io_set_loggers - jb_io_set_rgb_led - jb_io_set_panel_mode - jb_io_set_coin_blocker - jb_io_write_lights + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_configure_do + bt_module_io_jb_api_get + + ; Direct API + bt_io_jb_init + bt_io_jb_fini + bt_io_jb_inputs_read + bt_io_jb_sys_inputs_get + bt_io_jb_panel_inputs_get + bt_io_jb_rgb_led_set + bt_io_jb_lights_write + bt_io_jb_panel_mode_set + bt_io_jb_coin_blocker_set diff --git a/src/main/jbio-p4io/jbio.c b/src/main/jbio-p4io/jbio.c index 202187fe..a8bf3740 100644 --- a/src/main/jbio-p4io/jbio.c +++ b/src/main/jbio-p4io/jbio.c @@ -1,3 +1,5 @@ +#define LOG_MODULE "jbio-p4io" + // clang-format off // Don't format because the order is important here #include @@ -5,18 +7,25 @@ #include // clang-format on -#include "aciomgr/manager.h" - -#include "cconfig/cconfig-main.h" +#include "api/core/log.h" -#include "bemanitools/jbio.h" +#include "iface-acio/mgr.h" +#include "iface-core/config.h" +#include "iface-core/log.h" #include "jbio-p4io/config-h44b.h" #include "jbio-p4io/h44b.h" +#include "main/module/acio-mgr-ext.h" + #include "p4iodrv/device.h" -#include "util/log.h" +#include "sdk/module/core/config.h" +#include "sdk/module/configure.h" +#include "sdk/module/core/log.h" +#include "sdk/module/io/jb.h" + +static h44b_config_t _jbio_p4io_config_h44b; static struct p4iodrv_ctx *p4io_ctx; static uint16_t jb_io_panels; @@ -28,53 +37,29 @@ static struct ac_io_h44b_output jb_io_new_lights; static bool coin_blocked; -void jb_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +static module_acio_mgr_t *acio_mgr_module; + +static void _bt_io_jb_module_acio_mgr_init(module_acio_mgr_t **module) { - aciomgr_set_loggers(misc, info, warning, fatal); + bt_acio_mgr_api_t api; - log_to_external(misc, info, warning, fatal); + module_acio_mgr_ext_load_and_init("acio-mgr.dll", module); + module_acio_mgr_api_get(*module, &api); + bt_acio_mgr_api_set(&api); } -bool jb_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_jb_init() { - struct cconfig *config; - struct h44b_config config_h44b; - - config = cconfig_init(); - - jbio_config_h44b_init(config); - - if (!cconfig_main_config_init( - config, - "--h44b-config", - "jbio-h44b.conf", - "--help", - "-h", - "jbio-h44b", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - jbio_config_h44b_get(&config_h44b, config); - - cconfig_finit(config); + _bt_io_jb_module_acio_mgr_init(&acio_mgr_module); p4io_ctx = p4iodrv_open(); if (!p4io_ctx) { return false; } - // some people use p4io just for inputs and have no lights. Soft fail when - // h44b is not able to be connected instead of returning false - lights_present = jb_io_h44b_init(config_h44b.port, config_h44b.baud); + // some people use p4io just for acio_mgrs and have no lights. Soft fail + // when h44b is not able to be connected instead of returning false + lights_present = jb_io_h44b_init(_jbio_p4io_config_h44b.port, _jbio_p4io_config_h44b.baud); if (!lights_present) { log_warning("Could not connect to H44B, lights disabled"); } @@ -82,9 +67,12 @@ bool jb_io_init( return true; } -void jb_io_fini(void) +void bt_io_jb_fini() { p4iodrv_close(p4io_ctx); + + bt_acio_mgr_api_clear(); + module_acio_mgr_free(&acio_mgr_module); } static const uint32_t jb_io_panel_mappings[] = { @@ -111,7 +99,7 @@ static const uint32_t jb_io_sys_button_mappings[] = { (1 << 25), }; -bool jb_io_read_inputs(void) +bool bt_io_jb_inputs_read() { uint32_t jamma[4]; if (!p4iodrv_read_jamma(p4io_ctx, jamma)) { @@ -140,7 +128,7 @@ bool jb_io_read_inputs(void) return true; } -bool jb_io_write_lights(void) +bool bt_io_jb_lights_write() { if (lights_present && memcmp(&jb_io_lights, &jb_io_new_lights, sizeof(jb_io_lights))) { @@ -151,37 +139,37 @@ bool jb_io_write_lights(void) return true; } -uint8_t jb_io_get_sys_inputs(void) +uint8_t bt_io_jb_sys_inputs_get() { return jb_io_sys_buttons; } -uint16_t jb_io_get_panel_inputs(void) +uint16_t bt_io_jb_panel_inputs_get() { return jb_io_panels; } -bool jb_io_set_panel_mode(enum jb_io_panel_mode mode) +bool bt_io_jb_panel_mode_set(bt_io_jb_panel_mode_t mode) { struct p4io_req_panel_mode panel_mode = {0}; panel_mode.is_single = 1; switch (mode) { - case JB_IO_PANEL_MODE_ALL: + case BT_IO_JB_PANEL_MODE_ALL: panel_mode.is_single = 0; panel_mode.mode = 0; break; - case JB_IO_PANEL_MODE_TOP_LEFT: + case BT_IO_JB_PANEL_MODE_TOP_LEFT: panel_mode.mode = 0x0001; break; - case JB_IO_PANEL_MODE_TOP_RIGHT: + case BT_IO_JB_PANEL_MODE_TOP_RIGHT: panel_mode.mode = 0x0000; break; - case JB_IO_PANEL_MODE_BOTTOM_LEFT: + case BT_IO_JB_PANEL_MODE_BOTTOM_LEFT: panel_mode.mode = 0x0101; break; - case JB_IO_PANEL_MODE_BOTTOM_RIGHT: + case BT_IO_JB_PANEL_MODE_BOTTOM_RIGHT: panel_mode.mode = 0x0100; break; } @@ -189,27 +177,28 @@ bool jb_io_set_panel_mode(enum jb_io_panel_mode mode) return p4iodrv_cmd_portout(p4io_ctx, (uint8_t *) &panel_mode); } -void jb_io_set_rgb_led(enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b) +void bt_io_jb_rgb_led_set( + bt_io_jb_rgb_led_t unit, uint8_t r, uint8_t g, uint8_t b) { uint8_t *light; switch (unit) { - case JB_IO_RGB_LED_FRONT: + case BT_IO_JB_RGB_LED_FRONT: light = jb_io_new_lights.front_rgb; break; - case JB_IO_RGB_LED_TOP: + case BT_IO_JB_RGB_LED_TOP: light = jb_io_new_lights.top_rgb; break; - case JB_IO_RGB_LED_LEFT: + case BT_IO_JB_RGB_LED_LEFT: light = jb_io_new_lights.left_rgb; break; - case JB_IO_RGB_LED_RIGHT: + case BT_IO_JB_RGB_LED_RIGHT: light = jb_io_new_lights.right_rgb; break; - case JB_IO_RGB_LED_TITLE: + case BT_IO_JB_RGB_LED_TITLE: light = jb_io_new_lights.title_rgb; break; - case JB_IO_RGB_LED_WOOFER: + case BT_IO_JB_RGB_LED_WOOFER: light = jb_io_new_lights.woofer_rgb; break; default: @@ -221,7 +210,7 @@ void jb_io_set_rgb_led(enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b) light[2] = b; } -bool jb_io_set_coin_blocker(bool blocked) +bool bt_io_jb_coin_blocker_set(bool blocked) { coin_blocked = blocked; @@ -229,3 +218,35 @@ bool jb_io_set_coin_blocker(bool blocked) coin[0] = coin_blocked ? 0x00 : 0x20; return p4iodrv_cmd_coinstock(p4io_ctx, coin); } + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +bool bt_module_configure_do(const bt_core_config_t *config) +{ + jbio_config_h44b_get(config, &_jbio_p4io_config_h44b); + + return true; +} + +void bt_module_io_jb_api_get(bt_io_jb_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_jb_init; + api->v1.fini = bt_io_jb_fini; + api->v1.inputs_read = bt_io_jb_inputs_read; + api->v1.sys_inputs_get = bt_io_jb_sys_inputs_get; + api->v1.panel_inputs_get = bt_io_jb_panel_inputs_get; + api->v1.rgb_led_set = bt_io_jb_rgb_led_set; + api->v1.lights_write = bt_io_jb_lights_write; + api->v1.panel_mode_set = bt_io_jb_panel_mode_set; + api->v1.coin_blocker_set = bt_io_jb_coin_blocker_set; +} diff --git a/src/main/jbio/Module.mk b/src/main/jbio/Module.mk index e859879a..57db809c 100644 --- a/src/main/jbio/Module.mk +++ b/src/main/jbio/Module.mk @@ -4,8 +4,12 @@ ldflags_jbio := \ -lwinmm libs_jbio := \ - geninput - + iface \ + module \ + iface-io \ + iface-core \ + util \ + src_jbio := \ jbio.c \ diff --git a/src/main/jbio/jbio.c b/src/main/jbio/jbio.c index 96a90497..8a05d224 100644 --- a/src/main/jbio/jbio.c +++ b/src/main/jbio/jbio.c @@ -1,12 +1,4 @@ -/* This is the source code for the JBIO.DLL that ships with Bemanitools 5. - - If you want to add on some minor functionality like a custom RGB LED setup - then feel free to extend this code with support for your custom device. - - If you want to make a completely custom IO board that handles all input and - lighting then you'd be better off writing your own from scratch. Consult - the "bemanitools" header files included by this source file for detailed - information about the API you'll need to implement. */ +#define LOG_MODULE "jbio" // clang-format off // Don't format because the order is important here @@ -14,71 +6,65 @@ #include // clang-format on -#include "bemanitools/jbio.h" -#include "bemanitools/input.h" - -static uint16_t jb_io_panels; -static uint8_t jb_io_sys_buttons; +#include "api/core/log.h" +#include "api/core/thread.h" -/* Uncomment these if you need them. */ +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/input.h" -#if 0 -static log_formatter_t jb_io_log_misc; -static log_formatter_t jb_io_log_info; -static log_formatter_t jb_io_log_warning; -static log_formatter_t jb_io_log_fatal; -#endif +#include "main/module/input-ext.h" +#include "main/module/input.h" +#include "main/module/io-ext.h" +#include "main/module/io.h" -void jb_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - /* Pass logger functions on to geninput so that it has somewhere to write - its own log output. */ +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/jb.h" - input_set_loggers(misc, info, warning, fatal); +static module_input_t *_jb_io_module_input; - /* Uncomment this block if you have something you'd like to log. +static uint16_t jb_io_panels; +static uint8_t jb_io_sys_buttons; - You should probably return false from the appropriate function instead - of calling the fatal logger yourself though. */ +static void _bt_io_jb_module_input_init(module_input_t **module) +{ + bt_input_api_t api; -#if 0 - jb_io_log_misc = misc; - jb_io_log_info = info; - jb_io_log_warning = warning; - jb_io_log_fatal = fatal; -#endif + module_input_ext_load_and_init("geninput.dll", module); + module_input_api_get(*module, &api); + bt_input_api_set(&api); } -bool jb_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_jb_init() { + bool result; + timeBeginPeriod(1); - input_init(thread_create, thread_join, thread_destroy); - mapper_config_load("jb"); + _bt_io_jb_module_input_init(&_jb_io_module_input); - /* Initialize your own IO devices here. Log something and then return - false if the initialization fails. */ + result = bt_input_init(); - return true; + if (!result) { + log_warning("Initializing input failed"); + return false; + } + + return bt_input_mapper_config_load("jb"); } -void jb_io_fini(void) +void bt_io_jb_fini() { - /* This function gets called as JB shuts down after an Alt-F4. Close your - connections to your IO devices here. */ + bt_input_fini(); + bt_input_api_clear(); + module_input_free(&_jb_io_module_input); - input_fini(); timeEndPeriod(1); } -bool jb_io_read_inputs(void) +bool bt_io_jb_inputs_read() { uint32_t buttons; /* Sleep first: input is timestamped immediately AFTER the ioctl returns. @@ -91,7 +77,7 @@ bool jb_io_read_inputs(void) /* Update all of our input state here. */ - buttons = (uint32_t) mapper_update(); + buttons = (uint32_t) bt_input_mapper_update(); /* Mask out the stuff provided by geninput and store the panel/button state for later retrieval via jb_io_get_buttons() */ @@ -102,7 +88,7 @@ bool jb_io_read_inputs(void) return true; } -bool jb_io_write_lights(void) +bool bt_io_jb_lights_write() { /* The generic input stack currently initiates lighting sends and input reads simultaneously, though this might change later. Perform all of our @@ -112,30 +98,56 @@ bool jb_io_write_lights(void) return true; } -uint8_t jb_io_get_sys_inputs(void) +uint8_t bt_io_jb_sys_inputs_get() { return jb_io_sys_buttons; } -uint16_t jb_io_get_panel_inputs(void) +uint16_t bt_io_jb_panel_inputs_get() { return jb_io_panels; } -bool jb_io_set_panel_mode(enum jb_io_panel_mode mode) +bool bt_io_jb_panel_mode_set(bt_io_jb_panel_mode_t mode) { // geninput only uses 1 switch per panel, so ignore alternate modes return true; } -bool jb_io_set_coin_blocker(bool blocked) +bool bt_io_jb_coin_blocker_set(bool blocked) { return true; } -void jb_io_set_rgb_led(enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b) +void bt_io_jb_rgb_led_set( + bt_io_jb_rgb_led_t unit, uint8_t r, uint8_t g, uint8_t b) +{ + bt_input_mapper_light_write(unit * 3, r); + bt_input_mapper_light_write(unit * 3 + 1, g); + bt_input_mapper_light_write(unit * 3 + 2, b); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - mapper_write_light(unit * 3, r); - mapper_write_light(unit * 3 + 1, g); - mapper_write_light(unit * 3 + 2, b); + bt_core_log_api_set(api); } + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_jb_api_get(bt_io_jb_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_jb_init; + api->v1.fini = bt_io_jb_fini; + api->v1.inputs_read = bt_io_jb_inputs_read; + api->v1.sys_inputs_get = bt_io_jb_sys_inputs_get; + api->v1.panel_inputs_get = bt_io_jb_panel_inputs_get; + api->v1.rgb_led_set = bt_io_jb_rgb_led_set; + api->v1.lights_write = bt_io_jb_lights_write; + api->v1.panel_mode_set = bt_io_jb_panel_mode_set; + api->v1.coin_blocker_set = bt_io_jb_coin_blocker_set; +} \ No newline at end of file diff --git a/src/main/jbio/jbio.def b/src/main/jbio/jbio.def index aecc2289..09d9d499 100644 --- a/src/main/jbio/jbio.def +++ b/src/main/jbio/jbio.def @@ -1,13 +1,18 @@ LIBRARY jbio EXPORTS - jb_io_fini - jb_io_get_panel_inputs - jb_io_get_sys_inputs - jb_io_init - jb_io_read_inputs - jb_io_set_loggers - jb_io_set_panel_mode - jb_io_set_rgb_led - jb_io_set_coin_blocker - jb_io_write_lights + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_jb_api_get + + ; Direct API + bt_io_jb_init + bt_io_jb_fini + bt_io_jb_inputs_read + bt_io_jb_sys_inputs_get + bt_io_jb_panel_inputs_get + bt_io_jb_rgb_led_set + bt_io_jb_lights_write + bt_io_jb_panel_mode_set + bt_io_jb_coin_blocker_set diff --git a/src/main/jbiotest/Module.mk b/src/main/jbiotest/Module.mk index f2cf618b..b55298e6 100644 --- a/src/main/jbiotest/Module.mk +++ b/src/main/jbiotest/Module.mk @@ -1,8 +1,11 @@ exes += jbiotest \ libs_jbiotest := \ - jbio \ + core \ util \ + module \ + iface-core \ + iface-io \ src_jbiotest := \ main.c \ diff --git a/src/main/jbiotest/main.c b/src/main/jbiotest/main.c index 416b3251..43ec913b 100644 --- a/src/main/jbiotest/main.c +++ b/src/main/jbiotest/main.c @@ -1,14 +1,18 @@ +#include + #include #include #include #include -#include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" -#include "bemanitools/jbio.h" +#include "iface-core/log.h" +#include "iface-io/jb.h" -#include "util/log.h" -#include "util/thread.h" +#include "module/io-ext.h" typedef struct { uint8_t r, g, b; @@ -18,24 +22,46 @@ enum jbio_light_mode { LIGHTS_OFF, LIGHTS_ON, LIGHTS_INPUT }; #define IS_BIT_SET(var, bit) ((((var) >> (bit)) & 1) > 0) +static void _jbiotest_io_jb_init(module_io_t **module) +{ + bt_io_jb_api_t api; + + module_io_ext_load_and_init("jbio.dll", "bt_module_io_jb_api_get", module); + module_io_api_get(*module, &api); + bt_io_jb_api_set(&api); +} + /** * Tool to test your implementations of jbio. */ int main(int argc, char **argv) { - log_to_writer(log_writer_stdout, NULL); + module_io_t *module_io_jb; + + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); - jb_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _jbiotest_io_jb_init(&module_io_jb); - if (!jb_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) { + if (!bt_io_jb_init()) { printf("Initializing jbio failed\n"); + + bt_io_jb_api_clear(); + module_io_free(&module_io_jb); + return -1; } printf(">>> Initializing jbio successful, press enter to continue <<<\n"); if (getchar() != '\n') { + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&module_io_jb); + return 0; } @@ -49,15 +75,21 @@ int main(int argc, char **argv) bool loop = true; uint16_t cnt = 0; enum jbio_light_mode light_mode = LIGHTS_OFF; - enum jb_io_panel_mode panel_mode = JB_IO_PANEL_MODE_ALL; + bt_io_jb_panel_mode_t panel_mode = BT_IO_JB_PANEL_MODE_ALL; bool panel_corners_animate = false; char *all_text; char top_left, top_right, bottom_left, bottom_right; while (loop) { - if (!jb_io_read_inputs()) { + if (!bt_io_jb_inputs_read()) { printf("ERROR: Input read fail\n"); + + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&module_io_jb); + return -2; } @@ -66,37 +98,37 @@ int main(int argc, char **argv) panel_mode %= 5; // skip the all state - if (panel_mode == JB_IO_PANEL_MODE_ALL) { + if (panel_mode == BT_IO_JB_PANEL_MODE_ALL) { panel_mode++; } - jb_io_set_panel_mode(panel_mode); + bt_io_jb_panel_mode_set(panel_mode); } all_text = " "; top_left = top_right = bottom_left = bottom_right = ' '; switch (panel_mode) { - case JB_IO_PANEL_MODE_ALL: + case BT_IO_JB_PANEL_MODE_ALL: all_text = "ALL"; top_left = top_right = bottom_left = bottom_right = '*'; break; - case JB_IO_PANEL_MODE_TOP_LEFT: + case BT_IO_JB_PANEL_MODE_TOP_LEFT: top_left = '*'; break; - case JB_IO_PANEL_MODE_TOP_RIGHT: + case BT_IO_JB_PANEL_MODE_TOP_RIGHT: top_right = '*'; break; - case JB_IO_PANEL_MODE_BOTTOM_LEFT: + case BT_IO_JB_PANEL_MODE_BOTTOM_LEFT: bottom_left = '*'; break; - case JB_IO_PANEL_MODE_BOTTOM_RIGHT: + case BT_IO_JB_PANEL_MODE_BOTTOM_RIGHT: bottom_right = '*'; break; } /* get inputs */ - input_sys = jb_io_get_sys_inputs(); - input_panel = jb_io_get_panel_inputs(); + input_sys = bt_io_jb_sys_inputs_get(); + input_panel = bt_io_jb_panel_inputs_get(); system("cls"); printf( @@ -129,54 +161,54 @@ int main(int argc, char **argv) " `---`---`---`---`\n", cnt, - lights[JB_IO_RGB_LED_TOP].r, - lights[JB_IO_RGB_LED_TOP].g, - lights[JB_IO_RGB_LED_TOP].b, - lights[JB_IO_RGB_LED_FRONT].r, - lights[JB_IO_RGB_LED_FRONT].g, - lights[JB_IO_RGB_LED_FRONT].b, - lights[JB_IO_RGB_LED_LEFT].r, - lights[JB_IO_RGB_LED_RIGHT].r, - lights[JB_IO_RGB_LED_LEFT].g, - lights[JB_IO_RGB_LED_RIGHT].g, - lights[JB_IO_RGB_LED_LEFT].b, - lights[JB_IO_RGB_LED_TITLE].r, - lights[JB_IO_RGB_LED_TITLE].g, - lights[JB_IO_RGB_LED_TITLE].b, - lights[JB_IO_RGB_LED_RIGHT].b, - lights[JB_IO_RGB_LED_WOOFER].r, - lights[JB_IO_RGB_LED_WOOFER].g, - lights[JB_IO_RGB_LED_WOOFER].b, - - IS_BIT_SET(input_sys, JB_IO_SYS_TEST), - IS_BIT_SET(input_sys, JB_IO_SYS_SERVICE), - IS_BIT_SET(input_sys, JB_IO_SYS_COIN), - - IS_BIT_SET(input_panel, JB_IO_PANEL_01), - IS_BIT_SET(input_panel, JB_IO_PANEL_02), - IS_BIT_SET(input_panel, JB_IO_PANEL_03), - IS_BIT_SET(input_panel, JB_IO_PANEL_04), - IS_BIT_SET(input_panel, JB_IO_PANEL_05), - IS_BIT_SET(input_panel, JB_IO_PANEL_06), - IS_BIT_SET(input_panel, JB_IO_PANEL_07), - IS_BIT_SET(input_panel, JB_IO_PANEL_08), + lights[BT_IO_JB_RGB_LED_TOP].r, + lights[BT_IO_JB_RGB_LED_TOP].g, + lights[BT_IO_JB_RGB_LED_TOP].b, + lights[BT_IO_JB_RGB_LED_FRONT].r, + lights[BT_IO_JB_RGB_LED_FRONT].g, + lights[BT_IO_JB_RGB_LED_FRONT].b, + lights[BT_IO_JB_RGB_LED_LEFT].r, + lights[BT_IO_JB_RGB_LED_RIGHT].r, + lights[BT_IO_JB_RGB_LED_LEFT].g, + lights[BT_IO_JB_RGB_LED_RIGHT].g, + lights[BT_IO_JB_RGB_LED_LEFT].b, + lights[BT_IO_JB_RGB_LED_TITLE].r, + lights[BT_IO_JB_RGB_LED_TITLE].g, + lights[BT_IO_JB_RGB_LED_TITLE].b, + lights[BT_IO_JB_RGB_LED_RIGHT].b, + lights[BT_IO_JB_RGB_LED_WOOFER].r, + lights[BT_IO_JB_RGB_LED_WOOFER].g, + lights[BT_IO_JB_RGB_LED_WOOFER].b, + + IS_BIT_SET(input_sys, BT_IO_JB_SYS_TEST), + IS_BIT_SET(input_sys, BT_IO_JB_SYS_SERVICE), + IS_BIT_SET(input_sys, BT_IO_JB_SYS_COIN), + + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_01), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_02), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_03), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_04), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_05), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_06), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_07), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_08), top_left, top_right, all_text, - IS_BIT_SET(input_panel, JB_IO_PANEL_09), - IS_BIT_SET(input_panel, JB_IO_PANEL_10), - IS_BIT_SET(input_panel, JB_IO_PANEL_11), - IS_BIT_SET(input_panel, JB_IO_PANEL_12), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_09), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_10), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_11), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_12), bottom_left, bottom_right, - IS_BIT_SET(input_panel, JB_IO_PANEL_13), - IS_BIT_SET(input_panel, JB_IO_PANEL_14), - IS_BIT_SET(input_panel, JB_IO_PANEL_15), - IS_BIT_SET(input_panel, JB_IO_PANEL_16)); + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_13), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_14), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_15), + IS_BIT_SET(input_panel, BT_IO_JB_PANEL_16)); /* set outputs */ switch (light_mode) { @@ -205,11 +237,17 @@ int main(int argc, char **argv) } for (int i = 0; i < 6; i++) { - jb_io_set_rgb_led(i, lights[i].r, lights[i].g, lights[i].b); + bt_io_jb_rgb_led_set(i, lights[i].r, lights[i].g, lights[i].b); } - if (!jb_io_write_lights()) { + if (!bt_io_jb_lights_write()) { printf("ERROR: Writing outputs failed\n"); + + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&module_io_jb); + return -4; } @@ -236,10 +274,10 @@ int main(int argc, char **argv) case '1': { /* one last update to turn off the lights */ for (int i = 0; i < 6; i++) { - jb_io_set_rgb_led(i, 0, 0, 0); + bt_io_jb_rgb_led_set(i, 0, 0, 0); } - if (!jb_io_write_lights()) { + if (!bt_io_jb_lights_write()) { printf("ERROR: Writing outputs failed\n"); return -4; } @@ -266,8 +304,8 @@ int main(int argc, char **argv) case '5': { panel_corners_animate = !panel_corners_animate; if (!panel_corners_animate) { - panel_mode = JB_IO_PANEL_MODE_ALL; - jb_io_set_panel_mode(panel_mode); + panel_mode = BT_IO_JB_PANEL_MODE_ALL; + bt_io_jb_panel_mode_set(panel_mode); } break; } @@ -280,7 +318,11 @@ int main(int argc, char **argv) } system("cls"); - jb_io_fini(); + + bt_io_jb_fini(); + + bt_io_jb_api_clear(); + module_io_free(&module_io_jb); return 0; } diff --git a/src/main/launcher/Module.mk b/src/main/launcher/Module.mk index c9dfd078..432db2b3 100644 --- a/src/main/launcher/Module.mk +++ b/src/main/launcher/Module.mk @@ -3,22 +3,40 @@ rc_launcher := launcher.rc ldflags_launcher := \ -mconsole \ + -ldbghelp \ + -lpsapi \ deplibs_launcher := \ avs \ avs-ea3 \ +avslibs_launcher := \ + avs-ext \ + libs_launcher := \ hook \ util \ + iface-core \ + iface \ + module \ + core \ + mxml \ src_launcher := \ - avs-context.c \ - ea3-config.c \ + app.c \ + avs-config.c \ + avs.c \ + bootstrap-config.c \ + bootstrap.c \ + debug.c \ + ea3-ident-config.c \ + eamuse-config.c \ + eamuse.c \ + hooks.c \ + launcher-config.c \ + launcher.c \ main.c \ - module.c \ options.c \ - property.c \ stubs.c \ version.c \ diff --git a/src/main/launcher/app.c b/src/main/launcher/app.c new file mode 100644 index 00000000..b1d9db5d --- /dev/null +++ b/src/main/launcher/app.c @@ -0,0 +1,312 @@ +#define LOG_MODULE "app" + +#include + +#include "avs-ext/property-node.h" + +#include "hook/pe.h" + +#include "iface-core/log.h" + +#include "launcher/app.h" + +#include "util/str.h" + +static bool _app_dependency_available(const char *lib) +{ + HMODULE module; + + module = LoadLibraryA(lib); + + if (module == NULL) { + return false; + } else { + FreeLibrary(module); + return true; + } +} + +HMODULE _app_load(const char *path, bool resolve_references) +{ + HMODULE module; + LPSTR buffer; + DWORD err; + + log_misc("Loading app module: %s", path); + + if (resolve_references) { + module = LoadLibraryA(path); + } else { + module = LoadLibraryExA(path, NULL, DONT_RESOLVE_DLL_REFERENCES); + } + + if (module == NULL) { + err = GetLastError(); + + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR) &buffer, + 0, + NULL); + + if (err == ERROR_MOD_NOT_FOUND) { + log_warning("%s is likely missing dependencies", path); + log_warning("Do you have vcredist/directx runtimes installed?"); + log_warning( + "Ensure the installed dependencies match the architecture, " + "32-bit/64-bit, of the game"); + log_warning( + "Running heuristic for commonly used libraries (actual " + "requirements depend on game)..."); + + if (_app_dependency_available("d3d9.dll")) { + log_warning("Could not find directx9 runtime"); + } + + if (_app_dependency_available("msvcr100.dll")) { + log_warning("Could not find vcredist 2010 runtime"); + } + + if (_app_dependency_available("msvcr120.dll")) { + log_warning("Could not find vcredist 2013 runtime"); + } + + if (_app_dependency_available("msvcp140.dll")) { + log_warning("Could not find vcredist 2015 runtime"); + } + } + + log_fatal("%s: Failed to load app module: %s", path, buffer); + + LocalFree(buffer); + } + + log_misc("Loading app module done"); + + return module; +} + +static void _app_api_resolve(app_t *app) +{ + log_assert(app); + + app->init = + (dll_entry_init_t) GetProcAddress(app->module, "dll_entry_init"); + + if (!app->init) { + log_fatal( + "%s (%p): 'dll_entry_init' not found. Is this a game DLL?", + app->path, + app->module); + } + + app->main = + (dll_entry_main_t) GetProcAddress(app->module, "dll_entry_main"); + + if (!app->main) { + log_fatal( + "%s (%p): dll_entry_main not found. Is this a game DLL?", + app->path, + app->module); + } +} + +void app_load(const char *path, app_t *app) +{ + log_assert(path != NULL); + log_assert(app != NULL); + + log_info("%s: load", path); + + str_cpy(app->path, sizeof(app->path), path); + app->module = _app_load(path, true); + + _app_api_resolve(app); + + log_misc("%s (%p): loaded", app->path, app->module); +} + +void app_unresolved_load(const char *path, app_t *app) +{ + log_assert(path != NULL); + log_assert(app != NULL); + + log_info("%s: unresolved load", path); + + str_cpy(app->path, sizeof(app->path), path); + app->module = _app_load(path, false); + _app_api_resolve(app); + + log_misc("%s (%p): unresolved loaded", app->path, app->module); +} + +HMODULE app_module_handle_get(const app_t *app) +{ + log_assert(app); + + return app->module; +} + +void app_resolve(const app_t *app) +{ + log_assert(app); + + log_info("%s (%p) resolving", app->path, app->module); + // Resolve all imports like a normally loaded DLL + pe_resolve_imports(app->module); + + dll_entry_t orig_entry = pe_get_entry_point(app->module); + + log_misc("%s (%p): >>> DllMain"); + + orig_entry(app->module, DLL_PROCESS_ATTACH, NULL); + + log_misc("%s (%p): <<< DllMain"); + + log_misc("%s (%p) resolved", app->path, app->module); +} + +void app_init_invoke( + const app_t *app, + struct ea3_ident_config *ea3_ident_config, + const core_property_node_t *app_params_node) +{ + char sidcode_short[17]; + char sidcode_long[21]; + char security_code[9]; + struct property_node *app_params_node_avs; + bool ok; + + log_info("%s (%p): init invoke", app->path, app->module); + + /* 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); + + log_info("Invoking game init..."); + + log_misc("%s (%p) >>> init", app->path, app->module); + + app_params_node_avs = + avs_ext_property_node_avs_property_node_get(app_params_node); + + ok = app->init(sidcode_short, app_params_node_avs); + + log_misc("%s (%p) <<< init: %d", app->path, app->module, ok); + + if (!ok) { + log_fatal("%s: dll_entry_init_t() returned failure", app->path); + } + + /* 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("%s (%p): init invoked", app->path, app->module); +} + +bool app_main_invoke(const app_t *app) +{ + bool result; + + log_assert(app != NULL); + + log_info("%s (%p): main invoke", app->path, app->module); + + log_misc("%s (%p) >>> main", app->path, app->module); + + result = app->main(); + + log_misc("%s (%p) <<< main: %d", app->path, app->module, result); + + return result; +} + +void app_free(app_t *app) +{ + log_assert(app); + + log_misc("%s (%p): free", app->path, app->module); + + FreeLibrary(app->module); + memset(app, 0, sizeof(app_t)); +} diff --git a/src/main/launcher/app.h b/src/main/launcher/app.h new file mode 100644 index 00000000..c97fee7c --- /dev/null +++ b/src/main/launcher/app.h @@ -0,0 +1,30 @@ +#ifndef LAUNCHER_APP_H +#define LAUNCHER_APP_H + +#include + +#include "core/property-node.h" + +#include "imports/eapki.h" + +#include "launcher/ea3-ident-config.h" + +typedef struct app { + char path[MAX_PATH]; + HMODULE module; + dll_entry_init_t init; + dll_entry_main_t main; +} app_t; + +void app_load(const char *path, app_t *app); +void app_unresolved_load(const char *path, app_t *app); +HMODULE app_module_handle_get(const app_t *app); +void app_resolve(const app_t *app); +void app_init_invoke( + const app_t *app, + struct ea3_ident_config *ea3_ident_config, + const core_property_node_t *app_params_node); +bool app_main_invoke(const app_t *app); +void app_free(app_t *app); + +#endif diff --git a/src/main/launcher/avs-config.c b/src/main/launcher/avs-config.c new file mode 100644 index 00000000..eaa2eee1 --- /dev/null +++ b/src/main/launcher/avs-config.c @@ -0,0 +1,949 @@ +#define LOG_MODULE "avs-config" + +#include + +#include "avs-ext/error.h" + +#include "iface-core/log.h" + +#include "core/property-node-ext.h" +#include "core/property-node.h" +#include "core/property.h" + +#include "launcher/avs-config.h" + +#include "util/str.h" + +#define AVS_CONFIG_ROOT_NODE "/config" + +static const char *_avs_config_property_mounttable_path = + "/config/fs/mounttable"; + +static void _avs_config_node_vfs_copy( + core_property_node_t *parent, const core_property_node_t *source) +{ + // Use max path size to fit dst and src fs paths + char data[MAX_PATH]; + + // Remark: Using property_node_clone doesn't work here + // Cloning non-deep only clones the vfs node. Cloning deep doesn't seem + // to work with arbitrary attributes that don't follow the general + // design of a property structure. This seems to require clear typing for + // nodes in order to allow property_node_clone to work + + // Ignore errors and default to empty + memset(data, 0, sizeof(data)); + core_property_node_attr_read(source, "name", data, sizeof(data)); + core_property_node_ext_attr_replace(parent, "name", data); + + memset(data, 0, sizeof(data)); + core_property_node_attr_read(source, "fstype", data, sizeof(data)); + core_property_node_ext_attr_replace(parent, "fstype", data); + + memset(data, 0, sizeof(data)); + core_property_node_attr_read(source, "src", data, sizeof(data)); + core_property_node_ext_attr_replace(parent, "src", data); + + memset(data, 0, sizeof(data)); + core_property_node_attr_read(source, "dst", data, sizeof(data)); + core_property_node_ext_attr_replace(parent, "dst", data); + + memset(data, 0, sizeof(data)); + core_property_node_attr_read(source, "opt", data, sizeof(data)); + core_property_node_ext_attr_replace(parent, "opt", data); +} + +static core_property_node_result_t +_avs_config_mounttable_vfs_nodes_merge_strategy_do( + core_property_node_t *parent, + const core_property_node_t *source, + void *ctx, + bool *consumed, + core_property_node_ext_merge_recursion_do_t node_merge_recursion_do) +{ + core_property_node_t parent_child; + core_property_node_t tmp; + core_property_node_t source_child; + core_property_node_result_t result; + + char parent_child_name[CORE_PROPERTY_NODE_NAME_SIZE_MAX]; + char name_parent[CORE_PROPERTY_NODE_ATTR_NAME_SIZE_MAX]; + char dst_parent[CORE_PROPERTY_NODE_ATTR_NAME_SIZE_MAX]; + + char source_child_name[CORE_PROPERTY_NODE_NAME_SIZE_MAX]; + char name_source[CORE_PROPERTY_NODE_ATTR_NAME_SIZE_MAX]; + char dst_source[CORE_PROPERTY_NODE_ATTR_NAME_SIZE_MAX]; + + bool found_parent; + + result = core_property_node_child_get(source, &source_child); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + return CORE_PROPERTY_NODE_RESULT_SUCCESS; + } + + if (result != CORE_PROPERTY_NODE_RESULT_SUCCESS) { + core_property_node_fatal_on_error(result); + } + + *consumed = false; + + while (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + result = core_property_node_name_get( + &source_child, source_child_name, sizeof(source_child_name)); + core_property_node_fatal_on_error(result); + + if (str_eq(source_child_name, "vfs")) { + *consumed = true; + + result = core_property_node_child_get(parent, &parent_child); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND || + result != CORE_PROPERTY_NODE_RESULT_SUCCESS) { + core_property_node_fatal_on_error(result); + } + + found_parent = false; + + while (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + result = core_property_node_name_get( + &parent_child, + parent_child_name, + sizeof(parent_child_name)); + core_property_node_fatal_on_error(result); + + if (str_eq(parent_child_name, "vfs")) { + result = core_property_node_attr_read( + &source_child, + "name", + name_source, + sizeof(name_source)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal( + "Missing 'name' attribute on avs config mounttable " + "vfs source node"); + } + + result = core_property_node_attr_read( + &source_child, "dst", dst_source, sizeof(dst_source)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal( + "Missing 'dst' attribute on avs config mounttable " + "vfs source node"); + } + + result = core_property_node_attr_read( + &parent_child, + "name", + name_parent, + sizeof(name_parent)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal( + "Missing 'name' attribute on avs config mounttable " + "vfs parent node"); + } + + result = core_property_node_attr_read( + &parent_child, "dst", dst_parent, sizeof(dst_parent)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal( + "Missing 'dst' attribute on avs config mounttable " + "vfs parent node"); + } + + // Found existing matching node on parent, replace it + if (str_eq(name_source, name_parent) && + str_eq(dst_source, dst_parent)) { + _avs_config_node_vfs_copy(&parent_child, &source_child); + + found_parent = true; + break; + } + } + + result = + core_property_node_next_sibling_get(&parent_child, &tmp); + memcpy(&parent_child, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + + // Not found an existing node that got replaced, insert/merge new + // data + if (!found_parent) { + result = core_property_node_void_create( + parent, "vfs", &parent_child); + core_property_node_fatal_on_error(result); + + _avs_config_node_vfs_copy(&parent_child, &source_child); + } + } + + result = core_property_node_next_sibling_get(&source_child, &tmp); + memcpy(&source_child, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + + return CORE_PROPERTY_NODE_RESULT_SUCCESS; +} + +core_property_t *avs_config_load(const char *filepath) +{ + core_property_t *property; + core_property_result_t result; + core_property_node_t node; + + log_assert(filepath); + + log_info("Loading from file path: %s", filepath); + + result = core_property_file_load(filepath, &property); + core_property_fatal_on_error(result); + + // Check if root node exists, call already errors if not + avs_config_root_get(property, &node); + + return property; +} + +void avs_config_root_get( + const core_property_t *property, core_property_node_t *node) +{ + core_property_node_result_t result; + char node_name[128]; + + log_assert(property); + log_assert(node); + + result = core_property_root_node_get(property, node); + core_property_node_fatal_on_error(result); + + result = core_property_node_name_get(node, node_name, sizeof(node_name)); + core_property_node_fatal_on_error(result); + + if (!str_eq(node_name, "config")) { + log_fatal("Root node " AVS_CONFIG_ROOT_NODE " in AVS config missing"); + } else { + core_property_node_fatal_on_error(result); + } +} + +core_property_t *avs_config_property_merge( + const core_property_t *parent, const core_property_t *source) +{ + core_property_node_ext_merge_strategies_t strategies; + core_property_t *merged; + core_property_node_result_t result; + + log_assert(parent); + log_assert(source); + + strategies.num = 2; + + strategies.entry[0].path = _avs_config_property_mounttable_path; + strategies.entry[0].merge_strategy_do = + _avs_config_mounttable_vfs_nodes_merge_strategy_do; + + strategies.entry[1].path = ""; + strategies.entry[1].merge_strategy_do = + core_property_node_ext_merge_strategy_default_do; + + result = core_property_node_ext_merge_with_strategies_do( + parent, source, &strategies, &merged); + core_property_node_fatal_on_error(result); + + return merged; +} + +void avs_config_fs_root_device_get( + const core_property_node_t *node, char *buffer, size_t size) +{ + core_property_node_t device_node; + core_property_node_result_t result; + + log_assert(node); + log_assert(buffer); + log_assert(size > 0); + + result = core_property_node_search(node, "fs/root/device", &device_node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal("Could not find node fs/root/device AVS config"); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_str_read(&device_node, buffer, size); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal( + "fs/root/device, property read failed: %s", + core_property_node_result_to_str(result)); + } +} + +void avs_config_mode_product_set(core_property_node_t *node, bool enable) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = + core_property_node_ext_u8_replace(node, "mode/product", enable ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = core_property_node_ext_bool_replace(node, "mode/product", enable); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_net_raw_set(core_property_node_t *node, bool enable) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = core_property_node_ext_u8_replace( + node, "net/enable_raw", enable ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = + core_property_node_ext_bool_replace(node, "net/enable_raw", enable); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_net_eaudp_set(core_property_node_t *node, bool enable) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = core_property_node_ext_u8_replace( + node, "net/eaudp/enable", enable ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = + core_property_node_ext_bool_replace(node, "net/eaudp/enable", enable); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_sntp_ea_set(core_property_node_t *node, bool on) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = core_property_node_ext_u8_replace(node, "sntp/ea_on", on ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = core_property_node_ext_bool_replace(node, "sntp/ea_on", on); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_level_set(core_property_node_t *node, const char *level) +{ + core_property_node_result_t result; + + 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); + } + + result = core_property_node_ext_u32_replace(node, "log/level", level_value); + core_property_node_fatal_on_error(result); +#else + result = core_property_node_ext_str_replace(node, "log/level", level); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_name_set(core_property_node_t *node, const char *name) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(name); + + result = core_property_node_ext_str_replace(node, "log/name", name); + core_property_node_fatal_on_error(result); +} + +void avs_config_log_file_set(core_property_node_t *node, const char *file) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(file); + + result = core_property_node_ext_str_replace(node, "log/file", file); + core_property_node_fatal_on_error(result); +} + +void avs_config_log_buffer_size_set(core_property_node_t *node, uint32_t size) +{ + core_property_node_result_t result; + + log_assert(node); + + result = core_property_node_ext_u32_replace(node, "log/sz_buf", size); + core_property_node_fatal_on_error(result); +} + +void avs_config_log_output_delay_set( + core_property_node_t *node, uint16_t delay_ms) +{ + core_property_node_result_t result; + + log_assert(node); + + result = + core_property_node_ext_u16_replace(node, "log/output_delay", delay_ms); + core_property_node_fatal_on_error(result); +} + +void avs_config_log_enable_console_set(core_property_node_t *node, bool enable) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = core_property_node_ext_u8_replace( + node, "log/enable_console", enable ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = + core_property_node_ext_bool_replace(node, "log/enable_console", enable); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_enable_sci_set(core_property_node_t *node, bool enable) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = core_property_node_ext_u8_replace( + node, "log/enable_netsci", enable ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = + core_property_node_ext_bool_replace(node, "log/enable_netsci", enable); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_enable_net_set(core_property_node_t *node, bool enable) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = core_property_node_ext_u8_replace( + node, "log/enable_netlog", enable ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = + core_property_node_ext_bool_replace(node, "log/enable_netlog", enable); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_enable_file_set(core_property_node_t *node, bool enable) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = core_property_node_ext_u8_replace( + node, "log/enable_file", enable ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = + core_property_node_ext_bool_replace(node, "log/enable_file", enable); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_rotate_set(core_property_node_t *node, bool rotate) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = + core_property_node_ext_u8_replace(node, "log/rotate", rotate ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = core_property_node_ext_bool_replace(node, "log/rotate", rotate); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_append_set(core_property_node_t *node, bool append) +{ + core_property_node_result_t result; + + log_assert(node); + +#if AVS_VERSION <= 1306 + result = + core_property_node_ext_u8_replace(node, "log/append", append ? 1 : 0); + core_property_node_fatal_on_error(result); +#else + result = core_property_node_ext_bool_replace(node, "log/append", append); + core_property_node_fatal_on_error(result); +#endif +} + +void avs_config_log_count_set(core_property_node_t *node, uint16_t count) +{ + core_property_node_result_t result; + + log_assert(node); + + result = core_property_node_ext_u16_replace(node, "log/gen", count); + core_property_node_fatal_on_error(result); +} + +void avs_config_set_log_level( + core_property_node_t *node, enum core_log_bt_log_level loglevel) +{ + const char *str; + + log_assert(node); + + switch (loglevel) { + case CORE_LOG_BT_LOG_LEVEL_OFF: + str = "disable"; + break; + + case CORE_LOG_BT_LOG_LEVEL_FATAL: + str = "fatal"; + break; + + case CORE_LOG_BT_LOG_LEVEL_WARNING: + str = "warn"; + break; + + case CORE_LOG_BT_LOG_LEVEL_INFO: + str = "info"; + break; + + case CORE_LOG_BT_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( + core_property_node_t *node, const char *dev_nvram_raw_path) +{ + char path_dev_raw[MAX_PATH]; + char path_dev_nvram[MAX_PATH]; + + core_property_node_t fs_node; + core_property_node_t mounttable_node; + core_property_node_t vfs_node; + core_property_node_result_t result; + + 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"); + + result = core_property_node_search(node, "fs", &fs_node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal("Cannot find 'fs' node in avs config"); + } else { + core_property_node_fatal_on_error(result); + } + + // Check if "new" mounttable config is used for dev/nvram and dev/raw or + // legacy config + result = + core_property_node_search(&fs_node, "mounttable", &mounttable_node); + + if (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + result = core_property_node_remove(&mounttable_node); + core_property_node_fatal_on_error(result); + + result = core_property_node_void_create( + &fs_node, "mounttable", &mounttable_node); + core_property_node_fatal_on_error(result); + + result = + core_property_node_void_create(&mounttable_node, "vfs", &vfs_node); + core_property_node_fatal_on_error(result); + + result = core_property_node_attr_create( + &vfs_node, "name", "boot"); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "fstype", "fs"); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "src", path_dev_raw); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "dest", "/dev/raw"); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "opt", "vf=1,posix=1"); + core_property_node_fatal_on_error(result); + + result = + core_property_node_void_create(&mounttable_node, "vfs", &vfs_node); + core_property_node_fatal_on_error(result); + + result = core_property_node_attr_create( + &vfs_node, "name", "boot"); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "fstype", "fs"); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "src", path_dev_nvram); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "dest", "/dev/nvram"); + core_property_node_fatal_on_error(result); + result = core_property_node_attr_create( + &vfs_node, "opt", "vf=1,posix=1"); + core_property_node_fatal_on_error(result); + } else if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + result = core_property_node_ext_str_replace( + &fs_node, "nvram/device", path_dev_nvram); + core_property_node_fatal_on_error(result); + result = + core_property_node_ext_str_replace(&fs_node, "nvram/fstype", "fs"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_replace( + &fs_node, "nvram/option", "vf=1,posix=1"); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_replace( + &fs_node, "raw/device", path_dev_raw); + core_property_node_fatal_on_error(result); + result = + core_property_node_ext_str_replace(&fs_node, "raw/fstype", "fs"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_replace( + &fs_node, "raw/option", "vf=1,posix=1"); + core_property_node_fatal_on_error(result); + } else { + core_property_node_fatal_on_error(result); + } +} + +void avs_config_vfs_mounttable_get( + const core_property_node_t *node, + struct avs_config_vfs_mounttable *mounttable) +{ + core_property_node_t fs_node; + core_property_node_t mounttable_node; + core_property_node_t cur; + core_property_node_t tmp; + core_property_node_result_t result; + + char mounttable_selector[128]; + char name[128]; + uint8_t pos; + + log_assert(node); + log_assert(mounttable); + + result = core_property_node_search(node, "fs", &fs_node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal("Cannot find 'fs' node in avs config"); + } else { + core_property_node_fatal_on_error(result); + } + + // Check if new mounttable config is used for dev/nvram and dev/raw or + // legacy config + result = + core_property_node_search(&fs_node, "mounttable", &mounttable_node); + + memset(mounttable, 0, sizeof(*mounttable)); + pos = 0; + + if (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + result = + core_property_node_search(&fs_node, "mounttable_selector", &cur); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal("Missing 'mounttable_selector' on mounttable"); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_str_read( + &cur, mounttable_selector, sizeof(mounttable_selector)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal("Reading 'mounttable_selector' failed"); + } + + log_misc("Mounttable selector: %s", mounttable_selector); + + result = core_property_node_child_get(&mounttable_node, &cur); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + result = core_property_node_name_get(&cur, name, sizeof(name)); + core_property_node_fatal_on_error(result); + + if (str_eq(name, "vfs")) { + if (pos >= AVS_CONFIG_MOUNTTABLE_MAX_ENTRIES) { + log_warning( + "Exceeding max number of supported mounttable entries " + "(%d), ignoring remaining", + pos); + break; + } + + result = core_property_node_attr_read( + &cur, "name", name, sizeof(name)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal("Missing 'name' attribute on vfs node"); + } else { + core_property_node_fatal_on_error(result); + } + + if (str_eq(name, mounttable_selector)) { + result = core_property_node_attr_read( + &cur, + "fstype", + mounttable->entry[pos].fstype, + sizeof(mounttable->entry[pos].fstype)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // default + str_cpy( + mounttable->entry[pos].fstype, + sizeof(mounttable->entry[pos].fstype), + "fs"); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_attr_read( + &cur, + "src", + mounttable->entry[pos].src, + sizeof(mounttable->entry[pos].src)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal( + "Missing 'src' attribute on vfs node, name: %s", + name); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_attr_read( + &cur, + "dst", + mounttable->entry[pos].dst, + sizeof(mounttable->entry[pos].dst)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal( + "Missing 'dst' attribute on vfs node, name: %s", + name); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_attr_read( + &cur, + "opt", + mounttable->entry[pos].opt, + sizeof(mounttable->entry[pos].opt)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // optional + } else { + core_property_node_fatal_on_error(result); + } + + pos++; + } + } + + result = core_property_node_next_sibling_get(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + } else if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + result = core_property_node_search(&fs_node, "nvram", &cur); + + if (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + result = core_property_node_ext_str_read( + &cur, + "fstype", + mounttable->entry[pos].fstype, + sizeof(mounttable->entry[pos].fstype)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // default + str_cpy( + mounttable->entry[pos].fstype, + sizeof(mounttable->entry[pos].fstype), + "fs"); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_ext_str_read( + &cur, + "device", + mounttable->entry[pos].src, + sizeof(mounttable->entry[pos].src)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal("Missing 'device' attribute on nvram node"); + } else { + core_property_node_fatal_on_error(result); + } + + str_cpy( + mounttable->entry[pos].dst, + sizeof(mounttable->entry[pos].dst), + "/dev/nvram"); + + result = core_property_node_ext_str_read( + &cur, + "opt", + mounttable->entry[pos].opt, + sizeof(mounttable->entry[pos].opt)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // optional + } else { + core_property_node_fatal_on_error(result); + } + + pos++; + } else if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_search(&fs_node, "raw", &cur); + + if (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + result = core_property_node_ext_str_read( + &cur, + "fstype", + mounttable->entry[pos].fstype, + sizeof(mounttable->entry[pos].fstype)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // default + str_cpy( + mounttable->entry[pos].fstype, + sizeof(mounttable->entry[pos].fstype), + "fs"); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_ext_str_read( + &cur, + "device", + mounttable->entry[pos].src, + sizeof(mounttable->entry[pos].src)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal("Missing 'device' attribute on raw node"); + } else { + core_property_node_fatal_on_error(result); + } + + str_cpy( + mounttable->entry[pos].dst, + sizeof(mounttable->entry[pos].dst), + "/dev/raw"); + + result = core_property_node_ext_str_read( + &cur, + "opt", + mounttable->entry[pos].opt, + sizeof(mounttable->entry[pos].opt)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + // optional + } else { + core_property_node_fatal_on_error(result); + } + + pos++; + } else if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } else { + core_property_node_fatal_on_error(result); + } + + mounttable->num_entries = pos; +} \ 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..4916fa64 --- /dev/null +++ b/src/main/launcher/avs-config.h @@ -0,0 +1,60 @@ +#ifndef LAUNCHER_AVS_CONFIG_H +#define LAUNCHER_AVS_CONFIG_H + +#include "core/log-bt.h" + +#include "core/property-node.h" +#include "core/property.h" + +#include "launcher/bootstrap-config.h" + +#define AVS_CONFIG_MOUNTTABLE_MAX_ENTRIES 16 + +struct avs_config_vfs_mounttable { + struct { + char fstype[64]; + char src[512]; + char dst[512]; + char opt[256]; + } entry[AVS_CONFIG_MOUNTTABLE_MAX_ENTRIES]; + + uint8_t num_entries; +}; + +core_property_t *avs_config_load(const char *filepath); +void avs_config_root_get( + const core_property_t *property, core_property_node_t *node); +core_property_t *avs_config_property_merge( + const core_property_t *parent, const core_property_t *source); + +void avs_config_fs_root_device_get( + const core_property_node_t *node, char *buffer, size_t size); + +void avs_config_mode_product_set(core_property_node_t *node, bool enable); +void avs_config_net_raw_set(core_property_node_t *node, bool enable); +void avs_config_net_eaudp_set(core_property_node_t *node, bool enable); +void avs_config_sntp_ea_set(core_property_node_t *node, bool on); +void avs_config_log_level_set(core_property_node_t *node, const char *level); +void avs_config_log_name_set(core_property_node_t *node, const char *name); +void avs_config_log_file_set(core_property_node_t *node, const char *file); +void avs_config_log_buffer_size_set(core_property_node_t *node, uint32_t size); +void avs_config_log_output_delay_set( + core_property_node_t *node, uint16_t delay_ms); +void avs_config_log_enable_console_set(core_property_node_t *node, bool enable); +void avs_config_log_enable_sci_set(core_property_node_t *node, bool enable); +void avs_config_log_enable_net_set(core_property_node_t *node, bool enable); +void avs_config_log_enable_file_set(core_property_node_t *node, bool enable); +void avs_config_log_rotate_set(core_property_node_t *node, bool rotate); +void avs_config_log_append_set(core_property_node_t *node, bool append); +void avs_config_log_count_set(core_property_node_t *node, uint16_t count); + +void avs_config_set_log_level( + core_property_node_t *node, enum core_log_bt_log_level loglevel); +void avs_config_local_fs_path_dev_nvram_and_raw_set( + core_property_node_t *node, const char *dev_nvram_raw_path); + +void avs_config_vfs_mounttable_get( + const core_property_node_t *node, + struct avs_config_vfs_mounttable *mounttable); + +#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..023f58fb --- /dev/null +++ b/src/main/launcher/avs.c @@ -0,0 +1,282 @@ +#define LOG_MODULE "avs" + +#include + +#include +#include +#include + +#include "avs-ext/error.h" +#include "avs-ext/property-node.h" + +#include "core/log-bt.h" +#include "core/property-node.h" + +#include "iface-core/log.h" + +#include "imports/avs.h" + +#include "launcher/avs-config.h" +#include "launcher/avs.h" + +#include "util/codepage.h" +#include "util/fs.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 + core_log_bt_direct_sink_write(utf8, utf8_len); + + /* Clean up */ + + free(utf8); + free(utf16); +} + +void avs_fs_assert_root_device_exists(const core_property_node_t *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_mountpoints_fs_dirs_create(const core_property_node_t *node) +{ + struct avs_config_vfs_mounttable mounttable; + uint8_t i; + + avs_config_vfs_mounttable_get(node, &mounttable); + + if (mounttable.num_entries == 0) { + log_warning("No mountpoints found in mounttable"); + } + + for (i = 0; i < mounttable.num_entries; i++) { + if (str_eq(mounttable.entry[i].fstype, "fs")) { + log_misc( + "Creating avs fs directory '%s' for destination/device '%s'...", + mounttable.entry[i].src, + mounttable.entry[i].dst); + + if (!path_exists(mounttable.entry[i].src)) { + if (!path_mkdir(mounttable.entry[i].src)) { + log_fatal( + "Creating fs directory %s failed", + mounttable.entry[i].src); + } + } + } + } +} + +void avs_init( + const core_property_node_t *node, + uint32_t avs_heap_size, + uint32_t std_heap_size) +{ + struct property_node *avs_node; + + log_assert(node); + log_assert(avs_heap_size > 0); + // Modern games don't have a separate std heap anymore + log_assert(std_heap_size >= 0); + + log_info("init"); + + log_misc("Allocating avs heap: %d", avs_heap_size); + + 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 + log_misc("Allocating std heap: %d", std_heap_size); + + 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"); + + avs_node = avs_ext_property_node_avs_property_node_get(node); + +#ifdef AVS_HAS_STD_HEAP + avs_boot( + avs_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( + avs_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; + avs_error error; + + log_assert(src); + log_assert(dst); + + log_misc("Copying %s to %s...", src, dst); + + error = avs_fs_lstat(src, &st); + + if (AVS_IS_ERROR(error)) { + log_fatal( + "File source %s does not exist or is not accessible: %s", + src, + avs_ext_error_str(error)); + } + + error = avs_fs_copy(src, dst); + + if (AVS_IS_ERROR(error)) { + log_fatal( + "Failed copying file %s to %s: %s", + src, + dst, + avs_ext_error_str(error)); + } +} + +void avs_fs_dir_log(const char *path) +{ + const char *name; + avs_desc dir; + + log_assert(path); + + dir = avs_fs_opendir(path); + + if (AVS_IS_ERROR(dir)) { + log_warning( + "Opening avs dir %s failed, skipping logging contents: %s", + path, + avs_ext_error_str(dir)); + } + + 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..7d2fc2e6 --- /dev/null +++ b/src/main/launcher/avs.h @@ -0,0 +1,18 @@ +#ifndef LAUNCHER_AVS_H +#define LAUNCHER_AVS_H + +#include + +#include "core/property-node.h" + +void avs_fs_assert_root_device_exists(const core_property_node_t *node); +void avs_fs_mountpoints_fs_dirs_create(const core_property_node_t *node); +void avs_init( + const core_property_node_t *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..fef4f7a4 --- /dev/null +++ b/src/main/launcher/bootstrap-config.c @@ -0,0 +1,675 @@ +#define LOG_MODULE "bootstrap-config" + +#include + +#include "core/property-node-ext.h" +#include "core/property-node.h" + +#include "iface-core/log.h" + +#include "imports/avs.h" + +#include "launcher/avs-config.h" +#include "launcher/bootstrap-config.h" + +#include "util/defs.h" +#include "util/hex.h" +#include "util/str.h" + +#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( + const core_property_node_t *node, const char *profile) +{ + core_property_node_t profile_node; + core_property_node_result_t result; + + log_assert(node); + log_assert(profile); + + result = core_property_node_search(node, profile, &profile_node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + NODE_STARTUP_MISSING_FATAL(profile); + } else { + core_property_node_fatal_on_error(result); + } +} + +static void _bootstrap_config_root_node_get( + const core_property_t *property, core_property_node_t *node) +{ + core_property_node_result_t result; + char node_name[128]; + + log_assert(property); + log_assert(node); + + result = core_property_root_node_get(property, node); + core_property_node_fatal_on_error(result); + + result = core_property_node_name_get(node, node_name, sizeof(node_name)); + core_property_node_fatal_on_error(result); + + if (!str_eq(node_name, "config")) { + NODE_MISSING_FATAL(""); + } else { + core_property_node_fatal_on_error(result); + } +} + +static void _bootstrap_config_startup_node_get( + const core_property_node_t *node, core_property_node_t *node_out) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(node_out); + + result = core_property_node_search(node, "startup", node_out); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + NODE_MISSING_FATAL("startup"); + } else { + core_property_node_fatal_on_error(result); + } +} + +static void _bootstrap_config_inheritance_resolve( + const core_property_node_t *startup_node, const char *profile_name) +{ + core_property_node_t startup_parent_node; + core_property_node_t startup_profile_node; + core_property_node_t tmp_node; + core_property_node_result_t result; + + char inherit_name[64]; + int i; + + result = core_property_node_search( + startup_node, profile_name, &startup_profile_node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal(ROOT_NODE "/startup/%s: missing", profile_name); + } else { + core_property_node_fatal_on_error(result); + } + + memcpy( + &startup_parent_node, + &startup_profile_node, + sizeof(core_property_node_t)); + + while (true) { + result = core_property_node_attr_read( + &startup_parent_node, + "inherit", + inherit_name, + sizeof(inherit_name)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + break; + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_search( + startup_node, inherit_name, &startup_parent_node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + NODE_STARTUP_MISSING_FATAL(inherit_name); + } else { + core_property_node_fatal_on_error(result); + } + + for (i = 0; i < _countof(inherited_nodes); i++) { + result = core_property_node_search( + startup_node, inherited_nodes[i], &tmp_node); + + // if found, then continue; if not found, skip this, any other + // errors go fatal + if (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + continue; + } else if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_search( + &startup_parent_node, inherited_nodes[i], &tmp_node); + + if (result == CORE_PROPERTY_NODE_RESULT_SUCCESS) { + log_misc( + ROOT_NODE "/startup/%s: merging %s...", + inherit_name, + inherited_nodes[i]); + + result = + core_property_node_copy(&startup_profile_node, &tmp_node); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal( + "Merging '%s' into '%s' failed", + inherited_nodes[i], + inherit_name); + } + } else if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + } +} + +static void _bootstrap_config_load_bootstrap_module_app_config( + const core_property_node_t *profile_node, + struct bootstrap_module_config *config) +{ + core_property_node_t app_node; + core_property_node_result_t result; + + log_assert(profile_node); + log_assert(config); + + result = + core_property_node_search(profile_node, "component/param", &app_node); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_extract(&app_node, &config->app_config); + core_property_node_fatal_on_error(result); +} + +static void _bootstrap_config_load_bootstrap_default_files_config( + const char *profile_name, + const core_property_node_t *profile_node, + struct bootstrap_default_file_config *config) +{ + int i; + core_property_node_t tmp; + core_property_node_t child; + core_property_node_result_t result; + + log_assert(profile_node); + log_assert(config); + + result = core_property_node_search(profile_node, "default/file", &child); + i = 0; + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (i >= DEFAULT_FILE_MAX) { + log_warning( + "Currently not supporting more than %d default files, skipping " + "remaining", + i); + break; + } + + result = core_property_node_attr_read( + &child, "src", config->file[i].src, sizeof(config->file[i].src)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal( + "Missing src attribute on default file node of profile %s", + profile_name); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_attr_read( + &child, "dst", config->file[i].dst, sizeof(config->file[i].dst)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + log_fatal( + "Missing dst attribute on default file node of profile %s", + profile_name); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_next_result_search(&child, &tmp); + memcpy(&child, &tmp, sizeof(core_property_node_t)); + i++; + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } +} + +static void _bootstrap_config_load_bootstrap( + const core_property_node_t *startup_node, + const char *profile, + struct bootstrap_startup_config *config) +{ + core_property_node_t profile_node; + core_property_node_result_t result; + + result = core_property_node_search(startup_node, profile, &profile_node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + NODE_PROFILE_LOADING_FATAL(profile, ""); + } else { + core_property_node_fatal_on_error(result); + } + + _bootstrap_config_load_bootstrap_default_files_config( + profile, &profile_node, &config->default_file); + + result = core_property_node_ext_str_read( + &profile_node, + "boot/file", + config->boot.config_file, + sizeof(config->boot.config_file)); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read( + &profile_node, "boot/heap_avs", &config->boot.avs_heap_size); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "boot/heap_std", &config->boot.std_heap_size, 0); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "boot/mounttable_selector", + config->boot.mount_table_selector, + sizeof(config->boot.mount_table_selector), + "boot"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "boot/watcher", &config->boot.watcher_enable, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, + "boot/timemachine", + &config->boot.timemachine_enable, + false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "boot/launch_path", + config->boot.launch_config_file, + sizeof(config->boot.launch_config_file), + "/dev/raw/launch.xml"); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &profile_node, + "log/level", + config->log.level, + sizeof(config->log.level), + "all"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "log/name", + config->log.name, + sizeof(config->log.name), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "log/file", + config->log.file, + sizeof(config->log.file), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "log/sz_buf", &config->log.bufsz, 4096); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u16_read_or_default( + &profile_node, "log/output_delay", &config->log.output_delay_ms, 10); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "log/enable_console", &config->log.enable_console, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "log/enable_netsci", &config->log.enable_sci, false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "log/enable_netlog", &config->log.enable_net, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "log/enable_file", &config->log.enable_file, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "log/rotate", &config->log.rotate, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "log/append", &config->log.append, false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u16_read_or_default( + &profile_node, "log/gen", &config->log.count, 10); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_u8_read_or_default( + &profile_node, "minidump/gen", &config->minidump.count, 10); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, + "minidump/cont_debug", + &config->minidump.continue_, + false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "minidump/echo_log", &config->minidump.log, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u8_read_or_default( + &profile_node, "minidump/dump_type", &config->minidump.type, 2); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "minidump/path", + config->minidump.path, + sizeof(config->minidump.path), + "/dev/raw/minidump"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "minidump/sz_symbuf", &config->minidump.symbufsz, 32768); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "minidump/search", + config->minidump.search_path, + sizeof(config->minidump.search_path), + "."); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read( + &profile_node, + "component/file", + config->module.file, + sizeof(config->module.file)); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "component/load_type", + config->module.load_type, + sizeof(config->module.load_type), + "MEMORY"); + core_property_node_fatal_on_error(result); + + _bootstrap_config_load_bootstrap_module_app_config( + &profile_node, &config->module); + + /* disabled until we implement PSMAP_TYPE_BIN + PSMAP_OPTIONAL(PSMAP_TYPE_STR, struct bootstrap_startup_config, + ntdll_digest, "dlml/ntdll/hash", "") + */ + result = core_property_node_ext_u32_read_or_default( + &profile_node, "dlml/ntdll/size", &config->dlm_ntdll.size, 0); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "dlml/ntdll/ift_table", &config->dlm_ntdll.ift_table, 0); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, + "dlml/ntdll/insert_ift", + &config->dlm_ntdll.ift_insert, + 0); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, + "dlml/ntdll/remove_ift", + &config->dlm_ntdll.ift_remove, + 0); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read_or_default( + &profile_node, "shield/enable", &config->shield.enable, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "shield/verbose", &config->shield.verbose, false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, + "shield/use_loadlibrary", + &config->shield.use_loadlibrary, + false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "shield/use_loadlibrary", + config->shield.logger, + sizeof(config->shield.logger), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "shield/sleepmin", &config->shield.sleep_min, 10); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "shield/sleepblur", &config->shield.sleep_blur, 90); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "shield/whitelist", + config->shield.whitelist_file, + sizeof(config->shield.whitelist_file), + "prop/whitelist.csv"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "shield/ticksleep", &config->shield.tick_sleep, 100); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "shield/tickerror", &config->shield.tick_error, 1000); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u8_read_or_default( + &profile_node, + "shield/overwork_threshold", + &config->shield.overwork_threshold, + 50); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, + "shield/overwork_delay", + &config->shield.overwork_delay, + 100); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, "shield/pause_delay", &config->shield.pause_delay, 1000); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "shield/unlimited_key", + config->shield.unlimited_key, + sizeof(config->shield.unlimited_key), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u16_read_or_default( + &profile_node, "shield_killer/port", &config->shield.killer_port, 5001); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &profile_node, + "dongle/license", + config->dongle.license_cn, + sizeof(config->dongle.license_cn), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "dongle/account", + config->dongle.account_cn, + sizeof(config->dongle.account_cn), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "dongle/pkcs11_driver", + config->dongle.driver_dll, + sizeof(config->dongle.driver_dll), + "eTPKCS11.dll"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "dongle/disable_gc", &config->dongle.disable_gc, false); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &profile_node, "drm/dll", config->drm.dll, sizeof(config->drm.dll), ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "drm/fstype", + config->drm.fstype, + sizeof(config->drm.fstype), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "drm/device", + config->drm.device, + sizeof(config->drm.device), + ""); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "drm/dst", + config->drm.mount, + sizeof(config->drm.mount), + "/"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "drm/option", + config->drm.options, + sizeof(config->drm.options), + ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read_or_default( + &profile_node, "lte/enable", &config->lte.enable, false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "lte/file", + config->lte.config_file, + sizeof(config->lte.config_file), + "/dev/nvram/lte-config.xml"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "lte/unlimited_key", + config->lte.unlimited_key, + sizeof(config->lte.unlimited_key), + ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &profile_node, + "ssl/option", + config->ssl.options, + sizeof(config->ssl.options), + ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read_or_default( + &profile_node, "esign/enable", &config->esign.enable, false); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read_or_default( + &profile_node, "eamuse/enable", &config->eamuse.enable, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, "eamuse/sync", &config->eamuse.sync, true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, + "eamuse/enable_model", + &config->eamuse.enable_model, + false); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_str_read_or_default( + &profile_node, + "eamuse/file", + config->eamuse.config_file, + sizeof(config->eamuse.config_file), + "/dev/nvram/ea3-config.xml"); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_bool_read_or_default( + &profile_node, + "eamuse/updatecert_enable", + &config->eamuse.updatecert_enable, + true); + core_property_node_fatal_on_error(result); + result = core_property_node_ext_u32_read_or_default( + &profile_node, + "eamuse/updatecert_interval", + &config->eamuse.updatecert_interval, + 0); + core_property_node_fatal_on_error(result); +} + +void bootstrap_config_init(struct bootstrap_config *config) +{ + log_assert(config); + + memset(config, 0, sizeof(*config)); +} + +void bootstrap_config_load( + const core_property_t *property, + const char *profile, + struct bootstrap_config *config) +{ + core_property_node_t root_node; + core_property_node_t startup_node; + core_property_node_result_t result; + + log_assert(property); + log_assert(profile); + log_assert(config); + + log_info(ROOT_NODE ": loading..."); + + _bootstrap_config_root_node_get(property, &root_node); + + result = core_property_node_ext_str_read_or_default( + &root_node, + "/release_code", + config->release_code, + sizeof(config->release_code), + ""); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal(ROOT_NODE ": loading failed"); + } + + _bootstrap_config_startup_node_get(&root_node, &startup_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); + + _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..b9117652 --- /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 "core/property.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]; + core_property_t *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( + const core_property_t *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..0edff901 --- /dev/null +++ b/src/main/launcher/bootstrap.c @@ -0,0 +1,353 @@ +#define LOG_MODULE "bootstrap" + +#include "core/log-bt.h" +#include "core/log-sink-async.h" +#include "core/log-sink-file.h" +#include "core/log-sink-list.h" +#include "core/log-sink-null.h" +#include "core/log-sink-std.h" + +#include "core/property-ext.h" +#include "core/property-node-ext.h" +#include "core/property-node.h" +#include "core/property.h" + +#include "iface-core/log.h" + +#include "launcher/app.h" +#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 "util/str.h" + +static bool _bootstrap_log_property_configs; +static app_t _bootstrap_app; + +static void _bootstrap_eamuse_ea3_ident_config_inject( + core_property_node_t *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(core_property_node_t *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( + core_property_node_t *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 core_log_bt_log_level _bootstrap_log_map_level(const char *level) +{ + if (str_eq(level, "fatal")) { + return CORE_LOG_BT_LOG_LEVEL_FATAL; + } else if (str_eq(level, "warning")) { + return CORE_LOG_BT_LOG_LEVEL_WARNING; + } else if (str_eq(level, "info")) { + return CORE_LOG_BT_LOG_LEVEL_INFO; + } else if (str_eq(level, "misc")) { + return CORE_LOG_BT_LOG_LEVEL_MISC; + } else if (str_eq(level, "all")) { + return CORE_LOG_BT_LOG_LEVEL_MISC; + } else if (str_eq(level, "disable")) { + return CORE_LOG_BT_LOG_LEVEL_OFF; + } else if (str_eq(level, "default")) { + return CORE_LOG_BT_LOG_LEVEL_WARNING; + } 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) +{ + core_log_sink_t sinks[2]; + core_log_sink_t sink_composed; + core_log_sink_t sink_async; + enum core_log_bt_log_level level; + + log_assert(config); + + log_info("log init"); + + if (config->enable_file && strlen(config->file) > 0 && + config->enable_console) { + core_log_sink_std_out_open(true, &sinks[0]); + core_log_sink_file_open( + config->file, + config->append, + config->rotate, + config->count, + &sinks[1]); + core_log_sink_list_open(sinks, 2, &sink_composed); + } else if (config->enable_file && strlen(config->file) > 0) { + core_log_sink_file_open( + config->file, + config->append, + config->rotate, + config->count, + &sink_composed); + } else if (config->enable_console) { + core_log_sink_std_out_open(true, &sink_composed); + } else { + core_log_sink_null_open(&sink_composed); + } + + // TODO have configurable parameters for these + // TODO Allow for configuration of async logger on/off, default on + core_log_sink_async_open(64 * 1024, 64, CORE_LOG_SINK_ASYNC_OVERFLOW_POLICY_DISCARD_NEW, &sink_composed, &sink_async); + + // TODO have configurable parameters for these + core_log_bt_reinit(64 * 1024, &sink_async); + + level = _bootstrap_log_map_level(config->level); + core_log_bt_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, + const core_property_t *override_property) +{ + core_property_t *file_property; + core_property_t *merged_property; + core_property_node_t root_node; + + log_assert(config); + log_assert(log_config); + log_assert(override_property); + + log_info("avs init"); + + file_property = avs_config_load(config->config_file); + + if (_bootstrap_log_property_configs) { + log_misc("avs-config from file: %s", config->config_file); + core_property_ext_log(file_property, log_misc_func); + } + + merged_property = + avs_config_property_merge(file_property, override_property); + + core_property_free(&file_property); + + if (_bootstrap_log_property_configs) { + log_misc("avs-config merged with overrides"); + core_property_ext_log(merged_property, log_misc_func); + } + + avs_config_root_get(merged_property, &root_node); + + _bootstrap_avs_config_force_overrides_apply(&root_node); + _bootstrap_avs_config_log_overrides_apply(&root_node, log_config); + + if (_bootstrap_log_property_configs) { + log_misc("avs-config final"); + core_property_ext_log(merged_property, log_misc_func); + } + + avs_fs_assert_root_device_exists(&root_node); + + log_misc("Creating AVS file system directories..."); + + avs_fs_mountpoints_fs_dirs_create(&root_node); + + avs_init(&root_node, config->avs_heap_size, config->std_heap_size); + + core_property_free(&merged_property); + + log_misc("avs init done"); +} + +void bootstrap_eamuse_init( + const struct bootstrap_eamuse_config *config, + const struct ea3_ident_config *ea3_ident_config, + const core_property_t *override_property) +{ + core_property_t *file_property; + core_property_t *merged_property; + core_property_node_t root_node; + core_property_result_t prop_result; + + log_assert(config); + log_assert(ea3_ident_config); + log_assert(override_property); + + log_info("eamuse init"); + + if (config->enable) { + file_property = eamuse_config_avs_load(config->config_file); + + if (_bootstrap_log_property_configs) { + log_misc("eamuse-config from file: %s", config->config_file); + core_property_ext_log(file_property, log_misc_func); + } + + prop_result = core_property_ext_merge( + file_property, override_property, &merged_property); + core_property_fatal_on_error(prop_result); + + core_property_free(&file_property); + + if (_bootstrap_log_property_configs) { + log_misc("eamuse-config merged with overrides"); + core_property_ext_log(merged_property, log_misc_func); + } + + eamuse_config_root_get(merged_property, &root_node); + + _bootstrap_eamuse_ea3_ident_config_inject(&root_node, ea3_ident_config); + + if (_bootstrap_log_property_configs) { + log_misc("eamuse-config final"); + core_property_ext_log(merged_property, log_misc_func); + } + + eamuse_init(&root_node); + + core_property_free(&merged_property); + } else { + log_warning("Eamuse disabled"); + } + + log_misc("eamuse init done"); +} + +HMODULE bootstrap_app_unresolved_init( + const struct bootstrap_module_config *module_config) +{ + log_assert(module_config); + + app_unresolved_load(module_config->file, &_bootstrap_app); + + return app_module_handle_get(&_bootstrap_app); +} + +void bootstrap_app_resolve_init() +{ + app_resolve(&_bootstrap_app); +} + +void bootstrap_app_init( + const struct bootstrap_module_config *module_config, + struct ea3_ident_config *ea3_ident_config) +{ + core_property_node_t node; + core_property_result_t prop_result; + core_property_node_result_t result; + char node_name[128]; + + log_assert(module_config); + log_assert(ea3_ident_config); + + log_info("app init"); + + prop_result = core_property_root_node_get(module_config->app_config, &node); + core_property_fatal_on_error(prop_result); + + result = core_property_node_name_get(&node, node_name, sizeof(node_name)); + core_property_node_fatal_on_error(result); + + if (!str_eq(node_name, "param")) { + log_fatal("Missing param node on app-config"); + } else { + core_property_node_fatal_on_error(result); + } + + if (_bootstrap_log_property_configs) { + log_misc("app-config"); + core_property_node_ext_log(&node, log_misc_func); + } + + app_init_invoke(&_bootstrap_app, ea3_ident_config, &node); + + log_misc("app init done"); +} + +void bootstrap_app_run() +{ + app_main_invoke(&_bootstrap_app); +} + +void bootstrap_app_fini() +{ + app_free(&_bootstrap_app); +} + +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..4285366e --- /dev/null +++ b/src/main/launcher/bootstrap.h @@ -0,0 +1,34 @@ +#ifndef LAUNCHER_BOOTSTRAP_H +#define LAUNCHER_BOOTSTRAP_H + +#include "core/property.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, + const core_property_t *override_property); +void bootstrap_eamuse_init( + const struct bootstrap_eamuse_config *config, + const struct ea3_ident_config *ea3_ident_config, + const core_property_t *override_property); +HMODULE bootstrap_app_unresolved_init( + const struct bootstrap_module_config *module_config); +void bootstrap_app_resolve_init(); +void bootstrap_app_init( + const struct bootstrap_module_config *module_config, + struct ea3_ident_config *ea3_ident_config); +void bootstrap_app_run(); +void bootstrap_app_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..8f28121d --- /dev/null +++ b/src/main/launcher/debug.c @@ -0,0 +1,33 @@ + +#define LOG_MODULE "debug" + +#include +#include + +#include "iface-core/log.h" + +#include "launcher/debug.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..d27e62de --- /dev/null +++ b/src/main/launcher/ea3-ident-config.c @@ -0,0 +1,137 @@ +#define LOG_MODULE "ea3-ident-config" + +#include + +#include "core/property-node-ext.h" +#include "core/property-node.h" + +#include "iface-core/log.h" + +#include "imports/avs.h" + +#include "launcher/ea3-ident-config.h" + +#include "util/defs.h" +#include "util/hex.h" +#include "util/str.h" + +#define ROOT_NODE "/ea3_conf" + +static void _ea3_ident_config_root_get( + const core_property_t *property, core_property_node_t *node) +{ + core_property_node_result_t result; + char node_name[128]; + + log_assert(property); + log_assert(node); + + result = core_property_root_node_get(property, node); + core_property_node_fatal_on_error(result); + + result = core_property_node_name_get(node, node_name, sizeof(node_name)); + core_property_node_fatal_on_error(result); + + if (!str_eq(node_name, "ea3_conf")) { + log_fatal("Root node " ROOT_NODE " in ea3-ident config missing"); + } else { + core_property_node_fatal_on_error(result); + } +} + +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) +{ + core_property_t *property; + core_property_result_t result; + + log_assert(path); + log_assert(config); + + log_info("Loading from file path: %s", path); + + result = core_property_file_load(path, &property); + core_property_fatal_on_error(result); + + ea3_ident_config_load(property, config); + + core_property_free(&property); +} + +void ea3_ident_config_load( + const core_property_t *property, struct ea3_ident_config *config) +{ + core_property_node_t node; + core_property_node_result_t result; + + log_assert(property); + log_assert(config); + + _ea3_ident_config_root_get(property, &node); + + result = core_property_node_ext_str_read_or_default( + &node, "id/softid", config->softid, sizeof(config->softid), ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &node, "id/pcbid", config->pcbid, sizeof(config->pcbid), ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &node, "soft/model", config->model, sizeof(config->model), ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &node, "soft/dest", config->dest, sizeof(config->dest), ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &node, "soft/spec", config->spec, sizeof(config->spec), ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &node, "soft/rev", config->rev, sizeof(config->rev), ""); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read_or_default( + &node, "soft/ext", config->ext, sizeof(config->ext), ""); + core_property_node_fatal_on_error(result); +} + +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..44d3d92f --- /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 "core/property.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( + const core_property_t *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..9a10aef7 --- /dev/null +++ b/src/main/launcher/eamuse-config.c @@ -0,0 +1,136 @@ +#define LOG_MODULE "eamuse-config" + +#include + +#include "avs-ext/property-ext.h" + +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "launcher/ea3-ident-config.h" +#include "launcher/eamuse-config.h" + +#include "util/str.h" + +#define EAMUSE_CONFIG_ROOT_NODE "/ea3" + +core_property_t *eamuse_config_avs_load(const char *path) +{ + core_property_t *property; + core_property_node_t node; + + log_assert(path); + + log_misc("Loading from avs path: %s", path); + + avs_ext_property_ext_avs_file_load(path, &property); + + // Check if root node exists, call already errors if not + eamuse_config_root_get(property, &node); + + return property; +} + +void eamuse_config_root_get( + core_property_t *property, core_property_node_t *node) +{ + core_property_node_result_t result; + char node_name[128]; + + log_assert(property); + log_assert(node); + + result = core_property_root_node_get(property, node); + core_property_node_fatal_on_error(result); + + result = core_property_node_name_get(node, node_name, sizeof(node_name)); + core_property_node_fatal_on_error(result); + + if (!str_eq(node_name, "ea3")) { + log_fatal("Root node " EAMUSE_CONFIG_ROOT_NODE + " in eamuse config missing"); + } else { + core_property_node_fatal_on_error(result); + } +} + +void eamuse_config_id_softid_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "id/softid", value); +} + +void eamuse_config_id_hardid_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "id/hardid", value); +} + +void eamuse_config_id_pcbid_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "id/pcbid", value); +} + +void eamuse_config_soft_model_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "soft/model", value); +} + +void eamuse_config_soft_dest_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "soft/dest", value); +} + +void eamuse_config_soft_spec_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "soft/spec", value); +} + +void eamuse_config_soft_rev_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "soft/rev", value); +} + +void eamuse_config_soft_ext_set(core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(node, "soft/ext", value); +} + +void eamuse_config_network_url_slash_set(core_property_node_t *node, bool value) +{ + log_assert(node); + + core_property_node_ext_bool_replace(node, "network/url_slash", value); +} + +void eamuse_config_network_service_url_set( + core_property_node_t *node, const char *value) +{ + log_assert(node); + log_assert(value); + + core_property_node_ext_str_replace(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..d5e45ab3 --- /dev/null +++ b/src/main/launcher/eamuse-config.h @@ -0,0 +1,25 @@ +#ifndef LAUNCHER_EAMUSE_CONFIG_H +#define LAUNCHER_EAMUSE_CONFIG_H + +#include "core/property-node.h" +#include "core/property.h" + +core_property_t *eamuse_config_avs_load(const char *path); +void eamuse_config_root_get( + core_property_t *property, core_property_node_t *node); + +void eamuse_config_id_softid_set(core_property_node_t *node, const char *value); +void eamuse_config_id_hardid_set(core_property_node_t *node, const char *value); +void eamuse_config_id_pcbid_set(core_property_node_t *node, const char *value); +void eamuse_config_soft_model_set( + core_property_node_t *node, const char *value); +void eamuse_config_soft_dest_set(core_property_node_t *node, const char *value); +void eamuse_config_soft_spec_set(core_property_node_t *node, const char *value); +void eamuse_config_soft_rev_set(core_property_node_t *node, const char *value); +void eamuse_config_soft_ext_set(core_property_node_t *node, const char *value); +void eamuse_config_network_url_slash_set( + core_property_node_t *node, bool value); +void eamuse_config_network_service_url_set( + core_property_node_t *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..b71cf6c8 --- /dev/null +++ b/src/main/launcher/eamuse.c @@ -0,0 +1,31 @@ +#define LOG_MODULE "eamuse" + +#include "avs-ext/property-node.h" + +#include "iface-core/log.h" + +#include "imports/avs-ea3.h" + +void eamuse_init(const core_property_node_t *node) +{ + struct property_node *node_avs; + + log_assert(node); + + log_info("init"); + + node_avs = avs_ext_property_node_avs_property_node_get(node); + + ea3_boot(node_avs); + + 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..eb5eb475 --- /dev/null +++ b/src/main/launcher/eamuse.h @@ -0,0 +1,9 @@ +#ifndef LAUNCHER_EAMUSE_H +#define LAUNCHER_EAMUSE_H + +#include "core/property-node.h" + +void eamuse_init(const core_property_node_t *node); +void eamuse_fini(); + +#endif \ No newline at end of file diff --git a/src/main/launcher/hooks.c b/src/main/launcher/hooks.c new file mode 100644 index 00000000..cbc9d8e6 --- /dev/null +++ b/src/main/launcher/hooks.c @@ -0,0 +1,211 @@ +#define LOG_MODULE "hooks" + +#include "core/config-property-node.h" +#include "core/property-node.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/hook.h" + +#include "module/hook.h" + +#define MAX_HOOKS 64 + +typedef struct hooks_hook { + module_hook_t *module; + bt_hook_t *hook; + const core_property_node_t *node; +} hooks_hook_t; + +static hooks_hook_t _module_hooks[MAX_HOOKS]; +static uint32_t _hooks_count; + +void hooks_init() +{ + log_info("init"); + + memset(_module_hooks, 0, sizeof(_module_hooks)); + _hooks_count = 0; + + log_misc("init done"); +} + +void hooks_hook_load(const char *path, const core_property_node_t *node) +{ + module_hook_t *module; + bt_hook_api_t api; + bt_hook_t *hook; + + log_assert(path); + log_assert(node); + + log_misc("load: %s", path); + + if (_hooks_count >= MAX_HOOKS) { + log_fatal("Cannot load more hooks, max supported capacity reached"); + } + + module_hook_load(path, &module); + module_hook_api_get(module, &api); + bt_hook_init(&api, path, &hook); + + _module_hooks[_hooks_count].module = module; + _module_hooks[_hooks_count].hook = hook; + _module_hooks[_hooks_count].node = node; + _hooks_count++; +} + +void hooks_core_config_api_set() +{ + bt_core_config_api_t api; + uint32_t i; + + bt_core_config_api_get(&api); + + log_info("core_config_api_set"); + + for (i = 0; i < _hooks_count; i++) { + module_hook_core_config_api_set(_module_hooks[i].module, &api); + } + + log_misc("core_config_api_set done"); +} + +void hooks_core_log_api_set() +{ + bt_core_log_api_t api; + uint32_t i; + + bt_core_log_api_get(&api); + + log_info("core_log_api_set"); + + for (i = 0; i < _hooks_count; i++) { + module_hook_core_log_api_set(_module_hooks[i].module, &api); + } + + log_misc("core_log_api_set done"); +} + +void hooks_core_thread_api_set() +{ + bt_core_thread_api_t api; + uint32_t i; + + bt_core_thread_api_get(&api); + + log_info("core_thread_api_set"); + + for (i = 0; i < _hooks_count; i++) { + module_hook_core_thread_api_set(_module_hooks[i].module, &api); + } + + log_misc("core_thread_api_set done"); +} + +void hooks_pre_avs_init() +{ + uint32_t i; + bt_core_config_t *config; + bool result; + + log_info("pre_avs_init"); + + for (i = 0; i < _hooks_count; i++) { + core_config_property_node_init(_module_hooks[i].node, &config); + + result = bt_hook_pre_avs_init(_module_hooks[i].hook, config); + + core_config_property_node_free(&config); + + if (!result) { + log_fatal( + "%s: pre avs initializing hook failed", + module_hook_path_get(_module_hooks[i].module)); + } + } + + log_misc("pre_avs_init done"); +} + +void hooks_iat_apply(HMODULE game_module) +{ + uint32_t i; + char iat_dll_name[PATH_MAX]; + + log_info("iat_apply"); + + for (i = 0; i < _hooks_count; i++) { + bt_hook_iat_dll_name_get( + _module_hooks[i].hook, iat_dll_name, sizeof(iat_dll_name)); + + // TODO fix iat hooking + // module_hook_iat_apply(game_module, "source_dll?", iat_dll_name); + + // static void _module_hook_dll_iat( + // HMODULE hModule, const char *source_dll, const char *iat_hook) + + // (&, game_module); + } + + log_misc("iat_apply done"); +} + +void hooks_main_init(HMODULE game_module) +{ + uint32_t i; + bt_core_config_t *config; + bool result; + + log_assert(game_module); + + log_info("main_init"); + + for (i = 0; i < _hooks_count; i++) { + core_config_property_node_init(_module_hooks[i].node, &config); + + result = bt_hook_main_init(_module_hooks[i].hook, game_module, config); + + core_config_property_node_free(&config); + + if (!result) { + log_fatal( + "%s: Initializing hook failed", + module_hook_path_get(_module_hooks[i].module)); + } + } + + log_misc("main_init done"); +} + +void hooks_main_fini() +{ + uint32_t i; + + log_info("main_fini"); + + for (i = 0; i < _hooks_count; i++) { + bt_hook_main_fini(_module_hooks[i].hook); + } + + log_misc("main_fini done"); +} + +void hooks_fini() +{ + uint32_t i; + + log_info("fini"); + + for (i = 0; i < _hooks_count; i++) { + bt_hook_fini(&_module_hooks[i].hook); + module_hook_free(&_module_hooks[i].module); + } + + // node is just a reference to the property which is managed externally + + memset(_module_hooks, 0, sizeof(_module_hooks)); + + log_misc("fini done"); +} \ No newline at end of file diff --git a/src/main/launcher/hooks.h b/src/main/launcher/hooks.h new file mode 100644 index 00000000..5623513f --- /dev/null +++ b/src/main/launcher/hooks.h @@ -0,0 +1,28 @@ +#ifndef LAUNCHER_HOOKS_H +#define LAUNCHER_HOOKS_H + +#include + +#include "core/property-node.h" + +void hooks_init(); + +void hooks_hook_load(const char *path, const core_property_node_t *node); + +void hooks_core_config_api_set(); + +void hooks_core_log_api_set(); + +void hooks_core_thread_api_set(); + +void hooks_pre_avs_init(); + +void hooks_iat_apply(HMODULE game_module); + +void hooks_main_init(HMODULE game_module); + +void hooks_main_fini(); + +void hooks_fini(); + +#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..d24daf27 --- /dev/null +++ b/src/main/launcher/launcher-config.c @@ -0,0 +1,572 @@ +#define LOG_MODULE "launcher-config" + +#include + +#include "core/property-ext.h" +#include "core/property-node-ext.h" +#include "core/property-node.h" +#include "core/property.h" + +#include "iface-core/log.h" + +#include "launcher/launcher-config.h" + +#include "util/mem.h" +#include "util/str.h" + +#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 core_property_t * +_launcher_config_layered_config_nodes_load(const core_property_node_t *node) +{ + char kind[64]; + char file[MAX_PATH]; + int cnt; + + core_property_node_t cur; + core_property_node_t tmp; + core_property_t *config_property[MAX_LAYER_CONFIG_NODES]; + core_property_t *merged_property; + core_property_node_result_t result; + core_property_result_t prop_result; + + log_assert(node); + + cnt = 0; + result = core_property_node_search(node, "config", &cur); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (cnt >= MAX_LAYER_CONFIG_NODES) { + log_fatal( + "Exceeding max supported config nodes for layering, max is %d", + MAX_LAYER_CONFIG_NODES); + } + + result = + core_property_node_attr_read(&cur, "kind", kind, sizeof(kind)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal("Failed reading 'kind' attribute value of config node"); + } + + if (!strcmp(kind, "file")) { + core_property_node_str_read(&cur, file, sizeof(file)); + + prop_result = core_property_file_load(file, &config_property[cnt]); + core_property_fatal_on_error(prop_result); + } else if (!strcmp(kind, "inline")) { + // The nested child is the actual root of the inline, not the outer + // node + result = core_property_node_child_get(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + result = + core_property_node_ext_extract(&cur, &config_property[cnt]); + core_property_node_fatal_on_error(result); + } else { + log_fatal( + "Unsupported 'kind' attribute value '%s' of config node", kind); + } + + cnt++; + result = core_property_node_next_result_search(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + + if (cnt == 0) { + return NULL; + } + + prop_result = + core_property_ext_many_merge(config_property, cnt, &merged_property); + core_property_fatal_on_error(prop_result); + + for (int i = 0; i < cnt; i++) { + core_property_free(&config_property[i]); + } + + return merged_property; +} + +static void _launcher_config_bootstrap_load( + const core_property_node_t *node, struct launcher_bootstrap_config *config) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(config); + + result = core_property_node_ext_str_read( + node, "selector", config->selector, sizeof(config->selector)); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + NODE_MISSING_FATAL("bootstrap/selector"); + } else { + core_property_node_fatal_on_error(result); + } + + config->property = _launcher_config_layered_config_nodes_load(node); + + if (config->property == NULL) { + NODE_MISSING_FATAL("bootstrap/config"); + } +} + +static void _launcher_config_hook_hook_load( + const core_property_node_t *node, struct launcher_hook_config_hook *config) +{ + core_property_node_result_t result; + core_property_result_t prop_result; + + result = core_property_node_ext_bool_read(node, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read( + node, "path", config->path, sizeof(config->path)); + core_property_node_fatal_on_error(result); + + config->property = _launcher_config_layered_config_nodes_load(node); + + // Default empty config + if (!config->property) { + prop_result = core_property_str_load( + "1", + &config->property); + core_property_fatal_on_error(prop_result); + } +} + +static void _launcher_config_hook_pre_avs_load( + const core_property_node_t *node, + struct launcher_hook_config_pre_avs *config) +{ + core_property_node_result_t result; + core_property_result_t prop_result; + + result = core_property_node_ext_bool_read(node, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read( + node, "path", config->path, sizeof(config->path)); + core_property_node_fatal_on_error(result); + + config->property = _launcher_config_layered_config_nodes_load(node); + + // Default empty config + if (!config->property) { + prop_result = core_property_str_load( + "1", + &config->property); + core_property_fatal_on_error(prop_result); + } +} + +static void _launcher_config_hook_iat_load( + const core_property_node_t *node, struct launcher_hook_config_iat *config) +{ + core_property_node_result_t result; + core_property_result_t prop_result; + + result = core_property_node_ext_bool_read(node, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read( + node, "source_name", config->source_name, sizeof(config->source_name)); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read( + node, "path", config->path, sizeof(config->path)); + core_property_node_fatal_on_error(result); + + config->property = _launcher_config_layered_config_nodes_load(node); + + // Default empty config + if (!config->property) { + prop_result = core_property_str_load( + "1", + &config->property); + core_property_fatal_on_error(prop_result); + } +} + +static void _launcher_config_hooks_hook_load( + const core_property_node_t *node, struct launcher_hook_config *config) +{ + int cnt; + core_property_node_t tmp; + core_property_node_t cur; + core_property_node_result_t result; + + log_assert(node); + log_assert(config); + + cnt = 0; + result = core_property_node_search(node, "hook", &cur); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (cnt >= LAUNCHER_CONFIG_MAX_HOOKS) { + log_warning( + "Currently not supporting more than %d hooks, skipping " + "remaining", + cnt); + break; + } + + _launcher_config_hook_hook_load(&cur, &config->hook[cnt]); + + cnt++; + result = core_property_node_next_result_search(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } +} + +static void _launcher_config_hooks_pre_avs_load( + const core_property_node_t *node, struct launcher_hook_config *config) +{ + int cnt; + core_property_node_t tmp; + core_property_node_t cur; + core_property_node_result_t result; + + log_assert(node); + log_assert(config); + + cnt = 0; + result = core_property_node_search(node, "pre_avs", &cur); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (cnt >= LAUNCHER_CONFIG_MAX_HOOKS) { + log_warning( + "Currently not supporting more than %d hooks, skipping " + "remaining", + cnt); + break; + } + + _launcher_config_hook_pre_avs_load(&cur, &config->pre_avs[cnt]); + + cnt++; + result = core_property_node_next_result_search(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } +} + +static void _launcher_config_hooks_iat_load( + const core_property_node_t *node, struct launcher_hook_config *config) +{ + int cnt; + core_property_node_t tmp; + core_property_node_t cur; + core_property_node_result_t result; + + log_assert(node); + log_assert(config); + + cnt = 0; + result = core_property_node_search(node, "iat", &cur); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (cnt >= LAUNCHER_CONFIG_MAX_HOOKS) { + log_warning( + "Currently not supporting more than %d hooks, skipping " + "remaining", + cnt); + break; + } + + _launcher_config_hook_iat_load(&cur, &config->iat[cnt]); + + cnt++; + result = core_property_node_next_result_search(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } +} + +static void _launcher_config_hooks_load( + const core_property_node_t *node, struct launcher_hook_config *config) +{ + log_assert(node); + log_assert(config); + + _launcher_config_hooks_hook_load(node, config); + _launcher_config_hooks_pre_avs_load(node, config); + _launcher_config_hooks_iat_load(node, config); +} + +static void _launcher_config_debug_load( + const core_property_node_t *node, struct launcher_debug_config *config) +{ + core_property_node_result_t result; + + log_assert(node); + log_assert(config); + + result = core_property_node_ext_bool_read_or_default( + node, "debug/remote_debugger", &config->remote_debugger, false); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_bool_read_or_default( + node, + "debug/log_property_configs", + &config->log_property_configs, + false); + core_property_node_fatal_on_error(result); +} + +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, 0, sizeof(config->hook)); + + config->debug.remote_debugger = false; + config->debug.log_property_configs = false; +} + +void launcher_config_load( + const core_property_t *property, struct launcher_config *config) +{ + core_property_node_t root_node; + core_property_node_t node; + core_property_node_result_t result; + core_property_result_t result_prop; + + log_assert(property); + log_assert(config); + + result_prop = core_property_root_node_get(property, &root_node); + core_property_fatal_on_error(result_prop); + + result = core_property_node_search(&root_node, "version", &node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + NODE_MISSING_FATAL("version"); + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_u32_read(&node, &config->version); + + core_property_node_fatal_on_error(result); + + if (config->version != 1) { + log_fatal( + "Unsupported version of launcher configuration: %d", + config->version); + } + + result = core_property_node_search(&root_node, "bootstrap", &node); + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + NODE_MISSING_FATAL("bootstrap"); + } else { + core_property_node_fatal_on_error(result); + } + + _launcher_config_bootstrap_load(&node, &config->bootstrap); + + result = core_property_node_search(&root_node, "avs", &node); + + if (!CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + config->avs.property = + _launcher_config_layered_config_nodes_load(&node); + } else { + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + result_prop = core_property_str_load( + "", &config->avs.property); + core_property_fatal_on_error(result_prop); + } else { + core_property_node_fatal_on_error(result); + } + } + + result = core_property_node_search(&root_node, "ea3_ident", &node); + + if (!CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + config->ea3_ident.property = + _launcher_config_layered_config_nodes_load(&node); + } else { + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + result_prop = core_property_str_load( + "", &config->ea3_ident.property); + core_property_fatal_on_error(result_prop); + } else { + core_property_node_fatal_on_error(result); + } + } + + result = core_property_node_search(&root_node, "eamuse", &node); + + if (!CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + config->eamuse.property = + _launcher_config_layered_config_nodes_load(&node); + } else { + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + result_prop = + core_property_str_load("", &config->eamuse.property); + core_property_fatal_on_error(result_prop); + } else { + core_property_node_fatal_on_error(result); + } + } + + result = core_property_node_search(&root_node, "hook", &node); + + if (!CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + _launcher_config_hooks_load(&node, &config->hook); + } else { + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + // No defaults + + _launcher_config_debug_load(&root_node, &config->debug); +} + +bool launcher_config_hooks_hook_add( + struct launcher_config *config, const char *path) +{ + int i; + core_property_result_t result; + + log_assert(config); + log_assert(path); + + i = 0; + + while (i < LAUNCHER_CONFIG_MAX_HOOKS) { + if (!launcher_config_hooks_hook_available(&config->hook.hook[i])) { + break; + } + + i++; + } + + if (i >= LAUNCHER_CONFIG_MAX_HOOKS) { + return false; + } + + config->hook.hook[i].enable = true; + str_cpy(config->hook.hook[i].path, sizeof(config->hook.hook[i].path), path); + result = core_property_str_load( + "1", + &config->hook.hook[i].property); + core_property_fatal_on_error(result); + + return true; +} + +bool launcher_config_hooks_hook_available( + const struct launcher_hook_config_hook *config) +{ + log_assert(config); + + return strlen(config->path) > 0; +} + +bool launcher_config_hooks_pre_avs_hook_available( + const struct launcher_hook_config_pre_avs *config) +{ + log_assert(config); + + return strlen(config->path) > 0; +} + +bool launcher_config_hooks_iat_hook_available( + const struct launcher_hook_config_iat *config) +{ + log_assert(config); + + return strlen(config->path) > 0; +} + +void launcher_config_fini(struct launcher_config *config) +{ + int i; + + log_assert(config); + + core_property_free(&config->bootstrap.property); + + if (config->avs.property) { + core_property_free(&config->avs.property); + } + + if (config->ea3_ident.property) { + core_property_free(&config->ea3_ident.property); + } + + if (config->eamuse.property) { + core_property_free(&config->eamuse.property); + } + + for (i = 0; i < LAUNCHER_CONFIG_MAX_HOOKS; i++) { + if (config->hook.hook[i].property) { + core_property_free(&config->hook.hook[i].property); + } + } + + for (i = 0; i < LAUNCHER_CONFIG_MAX_HOOKS; i++) { + if (config->hook.pre_avs[i].property) { + core_property_free(&config->hook.pre_avs[i].property); + } + } + + for (i = 0; i < LAUNCHER_CONFIG_MAX_HOOKS; i++) { + if (config->hook.iat[i].property) { + core_property_free(&config->hook.iat[i].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..11bdb62c --- /dev/null +++ b/src/main/launcher/launcher-config.h @@ -0,0 +1,79 @@ +#ifndef LAUNCHER_CONFIG_H +#define LAUNCHER_CONFIG_H + +#include + +#include "core/property.h" + +#define LAUNCHER_CONFIG_MAX_HOOKS 16 + +struct launcher_config { + uint32_t version; + + struct launcher_bootstrap_config { + char selector[128]; + core_property_t *property; + } bootstrap; + + struct launcher_avs_config { + core_property_t *property; + } avs; + + struct launcher_ea3_ident_config { + core_property_t *property; + } ea3_ident; + + struct launcher_eamuse_config { + core_property_t *property; + } eamuse; + + struct launcher_hook_config { + struct launcher_hook_config_hook { + bool enable; + char path[MAX_PATH]; + core_property_t *property; + } hook[LAUNCHER_CONFIG_MAX_HOOKS]; + + struct launcher_hook_config_pre_avs { + bool enable; + char path[MAX_PATH]; + core_property_t *property; + } pre_avs[LAUNCHER_CONFIG_MAX_HOOKS]; + + struct launcher_hook_config_iat { + bool enable; + char source_name[MAX_PATH]; + char path[MAX_PATH]; + core_property_t *property; + } iat[LAUNCHER_CONFIG_MAX_HOOKS]; + } hook; + + struct launcher_debug_config { + bool remote_debugger; + bool log_property_configs; + bool procmon_file; + bool procmon_module; + bool procmon_thread; + } debug; +}; + +void launcher_config_init(struct launcher_config *config); + +void launcher_config_load( + const core_property_t *property, struct launcher_config *config); + +bool launcher_config_hooks_hook_add( + struct launcher_config *config, const char *path); + +bool launcher_config_hooks_hook_available( + const struct launcher_hook_config_hook *config); + +bool launcher_config_hooks_pre_avs_hook_available( + const struct launcher_hook_config_pre_avs *config); + +bool launcher_config_hooks_iat_hook_available( + const struct launcher_hook_config_iat *config); + +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..7a36b8df --- /dev/null +++ b/src/main/launcher/launcher.c @@ -0,0 +1,584 @@ +#define LOG_MODULE "launcher" + +#include + +#include +#include +#include +#include + +#include "avs-ext/property-node.h" +#include "avs-ext/property.h" + +#include "core/boot.h" +#include "core/config-property-node.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-file.h" +#include "core/log-sink-list.h" +#include "core/log-sink-std.h" +#include "core/property-ext.h" +#include "core/thread-crt.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "imports/avs-ea3.h" +#include "imports/avs.h" + +#include "launcher/app.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/hooks.h" +#include "launcher/launcher-config.h" +#include "launcher/options.h" +#include "launcher/stubs.h" +#include "launcher/version.h" + +#include "util/debug.h" +#include "util/defs.h" +#include "util/fs.h" +#include "util/os.h" +#include "util/proc.h" +#include "util/signal.h" +#include "util/str.h" + +static void _launcher_log_header() +{ + log_info( + "\n" + " .__ .__ \n" + " | | _____ __ __ ____ ____ | |__ ___________ \n" + " | | \\__ \\ | | \\/ \\_/ ___\\| | \\_/ __ \\_ __ \\ \n" + " | |__/ __ \\| | / | \\ \\___| Y \\ ___/| | \\/ \n" + " |____(____ /____/|___| /\\___ >___| /\\___ >__| \n" + " \\/ \\/ \\/ \\/ \\/ "); + + log_info( + "launcher build date %s, gitrev %s", + launcher_build_date, + launcher_gitrev); + log_info("Linked AVS version %s", launcher_linked_avs_version); +} + +void _launcher_log_init( + const char *log_file_path, enum core_log_bt_log_level level) +{ + if (log_file_path) { + core_log_bt_ext_init_async_with_stderr_and_file(log_file_path, false, true, 10); + } else { + core_log_bt_ext_init_async_with_stderr(); + } + + core_log_bt_core_api_set(); + + core_log_bt_level_set(level); +} + +static void _launcher_signal_shutdown_handler() +{ + core_log_bt_fini(); + ExitProcess(EXIT_FAILURE); +} + +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) +{ + core_property_result_t result; + + log_assert(config); + log_assert(options); + + if (options->config_path) { + log_misc( + "Command line override bootstrap configuration from file: %s", + options->config_path); + + core_property_free(&config->property); + result = + core_property_file_load(options->config_path, &config->property); + core_property_fatal_on_error(result); + } + + 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_hooks *options) +{ + size_t i; + const char *path; + + log_assert(config); + log_assert(options); + + for (i = 0; i < options->paths.nitems; i++) { + path = *array_item(const char *, &options->paths, i); + + if (!launcher_config_hooks_hook_add(config, path)) { + log_warning( + "Adding override hook dll '%s' failed (max supported limit " + "exceeded), ignored", + path); + } + } +} + +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->hooks); + _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"); + core_property_ext_log(config->bootstrap.property, log_misc_func); + + log_misc("avs-config"); + core_property_ext_log(config->avs.property, log_misc_func); + + log_misc("ea3-ident-config"); + core_property_ext_log(config->ea3_ident.property, log_misc_func); + + log_misc("eamuse-config"); + core_property_ext_log(config->eamuse.property, log_misc_func); + } +} + +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 CORE_LOG_BT_LOG_LEVEL_OFF: + str_cpy(config->level, sizeof(config->level), "disable"); + break; + + case CORE_LOG_BT_LOG_LEVEL_FATAL: + str_cpy(config->level, sizeof(config->level), "fatal"); + break; + + case CORE_LOG_BT_LOG_LEVEL_WARNING: + str_cpy(config->level, sizeof(config->level), "warn"); + break; + + case CORE_LOG_BT_LOG_LEVEL_INFO: + str_cpy(config->level, sizeof(config->level), "info"); + break; + + case CORE_LOG_BT_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); + } + } +} + +void _launcher_hooks_load( + const struct launcher_hook_config *config, bool debug_log_property_configs) +{ + int i; + core_property_node_t root_node; + core_property_result_t result_prop; + + log_assert(config); + + for (i = 0; i < LAUNCHER_CONFIG_MAX_HOOKS; i++) { + if (launcher_config_hooks_hook_available(&config->hook[i])) { + if (config->hook[i].enable) { + if (debug_log_property_configs) { + log_misc("Property hook config: %s", config->hook[i].path); + + core_property_ext_log(config->hook[i].property, log_misc_func); + } + + result_prop = core_property_root_node_get( + config->hook[i].property, &root_node); + core_property_fatal_on_error(result_prop); + + hooks_hook_load(config->hook[i].path, &root_node); + } else { + log_misc("Hook disabled: %s", config->hook[i].path); + } + } + } +} + +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"); + + core_property_ext_log(launcher_config->property, log_misc_func); + } + + 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_dongle_stubs_init() +{ + stubs_init(); +} + +static void _launcher_debugger_break() +{ + /* Opportunity for breakpoint setup etc */ + if (IsDebuggerPresent()) { + DebugBreak(); + } +} + +void _launcher_log_reinit() +{ + core_log_bt_core_api_set(); +} + +void _launcher_init( + const struct options *options, + struct launcher_config *launcher_config, + struct bootstrap_config *bootstrap_config, + struct ea3_ident_config *ea3_ident_config) +{ + core_property_t *launcher_property; + core_property_result_t result; + + log_assert(options); + log_assert(launcher_config); + log_assert(bootstrap_config); + log_assert(ea3_ident_config); + + core_thread_crt_core_api_set(); + + // Early logging pre AVS setup depend entirely on command args + // We don't even have the bootstrap configuration loaded at this point + _launcher_log_init(options->log.file_path, options->log.level); + _launcher_log_header(); + + // TODO make this configurable, e.g. command line args/env vars? + core_property_trace_log_enable(true); + core_property_node_trace_log_enable(true); + + // This is already available without AVS being actually booted + // and we need this to read our configuration files + avs_ext_property_core_api_set(); + avs_ext_property_node_core_api_set(); + + // Run our configuration API always through the property API + core_config_property_node_core_api_set(); + + 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); + + result = core_property_file_load( + options->launcher.config_path, &launcher_property); + core_property_fatal_on_error(result); + + 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"); + core_property_ext_log(launcher_property, log_misc_func); + } + + core_property_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); + + hooks_init(); + _launcher_hooks_load( + &launcher_config->hook, launcher_config->debug.log_property_configs); + + hooks_core_log_api_set(); + hooks_core_thread_api_set(); + hooks_core_config_api_set(); + + hooks_pre_avs_init(); + + bootstrap_avs_init( + &bootstrap_config->startup.boot, + &bootstrap_config->startup.log, + 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) +{ + HMODULE game_module; + + log_assert(launcher_config); + log_assert(bootstrap_config); + log_assert(ea3_ident_config); + + game_module = + bootstrap_app_unresolved_init(&bootstrap_config->startup.module); + + hooks_iat_apply(game_module); + + bootstrap_app_resolve_init(); + + _launcher_dongle_stubs_init(); + + _launcher_debugger_break(); + + hooks_main_init(game_module); + + bootstrap_app_init(&bootstrap_config->startup.module, ea3_ident_config); + + bootstrap_eamuse_init( + &bootstrap_config->startup.eamuse, + ea3_ident_config, + launcher_config->eamuse.property); + + bootstrap_app_run(); + + hooks_main_fini(); +} + +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_app_fini(); + + hooks_fini(); + + bootstrap_avs_fini(); + + _launcher_log_reinit(); + + launcher_config_fini(launcher_config); + + log_info("Shutdown complete"); + + core_log_bt_fini(); +} + +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/main.c b/src/main/launcher/main.c index 70c5184d..cdae112c 100644 --- a/src/main/launcher/main.c +++ b/src/main/launcher/main.c @@ -1,338 +1,27 @@ -#include - -#include -#include -#include #include -#include "imports/avs-ea3.h" -#include "imports/avs.h" +#include "core/boot.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 */ + core_boot("launcher"); 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); + exit(EXIT_FAILURE); } - 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); - } - - /* 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 deleted file mode 100644 index b3beff26..00000000 --- a/src/main/launcher/module.c +++ /dev/null @@ -1,263 +0,0 @@ -#include - -#include "hook/pe.h" - -#include "imports/avs.h" -#include "imports/eapki.h" - -#include "launcher/module.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) -{ - log_assert(hModule); - log_assert(iat_hook_dlls); - - if (iat_hook_dlls->nitems == 0) - return true; - - PBYTE pbModule = (PBYTE) hModule; - - // Find EXE base in process memory - IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *) pbModule; - IMAGE_NT_HEADERS *inh = (IMAGE_NT_HEADERS *) (pbModule + idh->e_lfanew); - - // Search through import table if it exists and replace the target DLL with - // our DLL filename - PIMAGE_SECTION_HEADER pRemoteSectionHeaders = - (PIMAGE_SECTION_HEADER) ((PBYTE) pbModule + sizeof(inh->Signature) + - sizeof(inh->FileHeader) + - inh->FileHeader.SizeOfOptionalHeader); - size_t total_size = inh->OptionalHeader.SizeOfHeaders; - - for (DWORD n = 0; n < inh->FileHeader.NumberOfSections; ++n) { - IMAGE_SECTION_HEADER *header = - (IMAGE_SECTION_HEADER *) (pRemoteSectionHeaders + n); - size_t new_total_size = - header->VirtualAddress + header->Misc.VirtualSize; - if (new_total_size > total_size) - total_size = new_total_size; - } - - void *remote_addr = NULL; - size_t remote_addr_ptr = 0; - - for (size_t i = 0; i < 10000 && remote_addr == NULL; i++) { - remote_addr = VirtualAlloc( - pbModule + total_size + (MM_ALLOCATION_GRANULARITY * (i + 1)), - (MAX_PATH + 1) * iat_hook_dlls->nitems, - MEM_RESERVE | MEM_COMMIT, - PAGE_READWRITE); - } - - log_assert(remote_addr != NULL); - - if (inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] - .VirtualAddress != 0) { - PIMAGE_IMPORT_DESCRIPTOR pImageImport = - (PIMAGE_IMPORT_DESCRIPTOR) (pbModule + - inh->OptionalHeader - .DataDirectory - [IMAGE_DIRECTORY_ENTRY_IMPORT] - .VirtualAddress); - - DWORD size = 0; - while (inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] - .Size == 0 || - size < inh->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] - .Size) { - IMAGE_IMPORT_DESCRIPTOR *ImageImport = - (IMAGE_IMPORT_DESCRIPTOR *) pImageImport; - - if (ImageImport->Name == 0) { - break; - } - - const char *name = (const char *) (pbModule + ImageImport->Name); - - for (size_t i = 0; i < iat_hook_dlls->nitems; i++) { - const char *iat_hook_dll = - *array_item(char *, iat_hook_dlls, i); - - char *iat_hook_replacement = strstr(iat_hook_dll, "="); - - if (!iat_hook_replacement) - continue; - - *iat_hook_replacement = '\0'; - - const char *expected_dll = iat_hook_dll; - const char *replacement_path_dll = iat_hook_replacement + 1; - - if (strcmp(name, expected_dll) == 0) { - pe_patch( - (PBYTE) remote_addr + remote_addr_ptr, - replacement_path_dll, - strlen(replacement_path_dll)); - - log_misc( - "Replacing %s with %s", name, replacement_path_dll); - - DWORD val = (DWORD) ((PBYTE) remote_addr - pbModule); - pe_patch(&ImageImport->Name, &val, sizeof(DWORD)); - pe_patch(pImageImport, &ImageImport, sizeof(ImageImport)); - - remote_addr_ptr += strlen(replacement_path_dll) + 1; - } - - *iat_hook_replacement = '='; - } - - pImageImport++; - size += sizeof(IMAGE_IMPORT_DESCRIPTOR); - } - } else { - log_misc("Couldn't find import table, can't hook DLL\n"); - goto inject_fail; - } - - return true; - -inject_fail: - return false; -} - -void module_context_init(struct module_context *module, const char *path) -{ - log_assert(module != NULL); - log_assert(path != NULL); - - module->dll = LoadLibrary(path); - - if (module->dll == NULL) { - LPSTR buffer; - DWORD err = GetLastError(); - - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR) &buffer, - 0, - NULL); - - if (err == ERROR_MOD_NOT_FOUND) { - log_warning("%s is likely missing dependencies", path); - log_warning("Do you have vcredist/directx runtimes installed?"); - } - - log_fatal("%s: Failed to load game DLL: %s", path, buffer); - - LocalFree(buffer); - } - - module->path = str_dup(path); -} - -void module_context_init_with_iat_hooks( - struct module_context *module, - const char *path, - struct array *iat_hook_dlls) -{ - log_assert(module != NULL); - log_assert(path != NULL); - - module->dll = LoadLibraryExA(path, NULL, DONT_RESOLVE_DLL_REFERENCES); - - if (module->dll == NULL) { - LPSTR buffer; - DWORD err = GetLastError(); - - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR) &buffer, - 0, - NULL); - - if (err == ERROR_MOD_NOT_FOUND) { - log_warning("%s is likely missing dependencies", path); - log_warning("Do you have vcredist/directx runtimes installed?"); - } - - log_fatal("%s: Failed to load game DLL: %s", path, buffer); - - LocalFree(buffer); - } - - // Add IAT hooks - module_replace_dll_iat(module->dll, iat_hook_dlls); - - log_misc("Finished processing IAT hooks"); - - // Resolve all imports like a normally loaded DLL - pe_resolve_imports(module->dll); - - dll_entry_t orig_entry = pe_get_entry_point(module->dll); - orig_entry(module->dll, DLL_PROCESS_ATTACH, NULL); - - log_misc("Finished resolving imports"); - - module->path = str_dup(path); -} - -bool module_context_invoke_init( - const struct module_context *module, - char *sidcode, - struct property_node *app_config) -{ - dll_entry_init_t init; - - log_assert(module != NULL); - log_assert(sidcode != NULL); - log_assert(app_config != NULL); - - init = (void *) GetProcAddress(module->dll, "dll_entry_init"); - - if (init == NULL) { - log_fatal( - "%s: dll_entry_init not found. Is this a game DLL?", module->path); - } - - return init(sidcode, app_config); -} - -bool module_context_invoke_main(const struct module_context *module) -{ - /* GCC warns if you call a variable "main" */ - dll_entry_main_t main_; - - log_assert(module != NULL); - - main_ = (void *) GetProcAddress(module->dll, "dll_entry_main"); - - if (main_ == NULL) { - log_fatal( - "%s: dll_entry_main not found. Is this a game DLL?", module->path); - } - - return main_(); -} - -void module_context_fini(struct module_context *module) -{ - if (module == NULL) { - return; - } - - free(module->path); - - if (module->dll != NULL) { - FreeLibrary(module->dll); - } -} diff --git a/src/main/launcher/module.h b/src/main/launcher/module.h deleted file mode 100644 index f2a851eb..00000000 --- a/src/main/launcher/module.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef LAUNCHER_MODULE_H -#define LAUNCHER_MODULE_H - -#include - -#include "imports/avs.h" - -#include "util/array.h" - -struct module_context { - HMODULE dll; - char *path; -}; - -void module_context_init(struct module_context *module, const char *path); -void module_context_init_with_iat_hooks( - struct module_context *module, - const char *path, - struct array *iat_hook_dlls); -bool module_context_invoke_init( - 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); - -#endif diff --git a/src/main/launcher/options.c b/src/main/launcher/options.c index 757555ec..a9d42121 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->hooks.paths); + + options->log.level = CORE_LOG_BT_LOG_LEVEL_INFO; } 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 'B': 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,38 @@ 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; - } - - break; - -#ifdef AVS_HAS_STD_HEAP - case 'T': - 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->hooks.paths) = + argv[++i]; break; -#endif - case 'K': + case 'L': if (i + 1 >= argc) { return false; } - *array_append(const char *, &options->hook_dlls) = - argv[++i]; - - break; + long tmp = strtol(argv[++i], NULL, 0); - case 'B': - if (i + 1 >= argc) { + if (tmp < CORE_LOG_BT_LOG_LEVEL_OFF || + tmp > CORE_LOG_BT_LOG_LEVEL_MISC) { return false; } - *array_append(const char *, &options->before_hook_dlls) = - argv[++i]; + options->log.level = (enum core_log_bt_log_level) tmp; break; - case 'I': { + case 'Y': if (i + 1 >= argc) { return false; } - const char *dll = argv[++i]; - log_assert(strstr(dll, "=") != NULL); - - *array_append(const char *, &options->iat_hook_dlls) = dll; + options->log.file_path = argv[++i]; break; - } - - case 'Y': - if (i + 1 >= argc) { - return false; - } - options->logfile = argv[++i]; + case 'C': + options->debug.log_property_configs = true; break; @@ -160,7 +110,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 +119,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 +143,60 @@ 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 " - "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" + " Bootstrap\n" + " -B [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 " + "\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->hooks.paths); + + if (options->eamuse.urlslash) { + free(options->eamuse.urlslash); + } } diff --git a/src/main/launcher/options.h b/src/main/launcher/options.h index 13f1c0fb..3d23b0d0 100644 --- a/src/main/launcher/options.h +++ b/src/main/launcher/options.h @@ -4,25 +4,50 @@ #include #include +#include "core/log-bt.h" + +#include "launcher/bootstrap-config.h" + #include "util/array.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 core_log_bt_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_hooks { + struct array paths; + } hooks; + + struct options_debug { + bool remote_debugger; + bool log_property_configs; + } debug; }; void options_init(struct options *options); 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..81acdf1b 100644 --- a/src/main/launcher/stubs.c +++ b/src/main/launcher/stubs.c @@ -1,3 +1,5 @@ +#define LOG_MODULE "stubs" + #include #include @@ -7,10 +9,11 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "launcher/stubs.h" #include "util/defs.h" -#include "util/log.h" struct ikey_status { uint32_t field_0; @@ -27,7 +30,7 @@ struct stub { void *proc; }; -typedef void (*bt_get_fucked_t)(uint32_t /* even in 64-bit */ context); +typedef void(__cdecl *bt_get_fucked_t)(void *context); static HMODULE STDCALL my_GetModuleHandleA(const char *name); static HMODULE STDCALL my_GetModuleHandleW(const wchar_t *name); @@ -36,7 +39,7 @@ static void *STDCALL my_GetProcAddress(HMODULE dll, const char *name); static void bt_get_ikey_status(struct ikey_status *ik); #if AVS_VERSION >= 1509 -static void bt_get_fucked(bt_get_fucked_t callback, uint32_t ctx); +static void bt_get_fucked(bt_get_fucked_t callback, void *ctx); #endif static void bt_fcheck_init(void); @@ -116,6 +119,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)); } @@ -135,10 +140,15 @@ static void bt_get_ikey_status(struct ikey_status *ik) } #if AVS_VERSION >= 1509 -static void bt_get_fucked(bt_get_fucked_t callback, uint32_t ctx) +static void bt_get_fucked(bt_get_fucked_t callback, void *ctx) { log_info(">>> k_bt0002"); - callback(ctx); + + if (callback != NULL) { + log_misc("callback(%p): %p", callback, ctx); + callback(ctx); + } + log_info("<<< k_bt0002"); } #endif diff --git a/src/main/launcher/version.c b/src/main/launcher/version.c index c71d5ff6..f2b2f228 100644 --- a/src/main/launcher/version.c +++ b/src/main/launcher/version.c @@ -2,3 +2,4 @@ const char *launcher_build_date = __DATE__ " " __TIME__; const char *launcher_gitrev = STRINGIFY(GITREV); +const char *launcher_linked_avs_version = STRINGIFY(AVS_VERSION); \ No newline at end of file diff --git a/src/main/launcher/version.h b/src/main/launcher/version.h index fe7f0d3f..9764563f 100644 --- a/src/main/launcher/version.h +++ b/src/main/launcher/version.h @@ -2,3 +2,4 @@ extern const char *launcher_build_date; extern const char *launcher_gitrev; +extern const char *launcher_linked_avs_version; diff --git a/src/main/mempatch-hook/Module.mk b/src/main/mempatch-hook/Module.mk index 9785efa9..6f58ff68 100644 --- a/src/main/mempatch-hook/Module.mk +++ b/src/main/mempatch-hook/Module.mk @@ -2,6 +2,8 @@ dlls += mempatch-hook libs_mempatch-hook := \ util \ + core \ + iface-core \ src_mempatch-hook := \ main.c \ diff --git a/src/main/mempatch-hook/main.c b/src/main/mempatch-hook/main.c index 43c1dcd9..2d6d4f4b 100644 --- a/src/main/mempatch-hook/main.c +++ b/src/main/mempatch-hook/main.c @@ -4,10 +4,15 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + +#include "iface-core/log.h" + #include "util/cmdline.h" #include "util/fs.h" #include "util/hex.h" -#include "util/log.h" static bool patch_memory_check_data( uintptr_t base_address, @@ -283,12 +288,15 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) int argc; char **argv; char *filepath; - FILE *logfile; bool patched; patched = false; - logfile = fopen("mempatch.log", "w+"); - log_to_writer(log_writer_file, logfile); + + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr_and_file( + "mempatch.log", false, false, 0); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); args_recover(&argc, &argv); @@ -319,8 +327,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) log_info("Patching done"); } - fflush(logfile); - fclose(logfile); + core_log_bt_fini(); } return TRUE; diff --git a/src/main/mm/Module.mk b/src/main/mm/Module.mk index 5ffd4062..877007ca 100644 --- a/src/main/mm/Module.mk +++ b/src/main/mm/Module.mk @@ -6,6 +6,7 @@ ldflags_mm := \ libs_mm := \ util \ + iface-core \ src_mm := \ mm.c \ diff --git a/src/main/mm/Sources b/src/main/mm/Sources deleted file mode 100644 index 7062a2f6..00000000 --- a/src/main/mm/Sources +++ /dev/null @@ -1,6 +0,0 @@ -!include ../Common.inc - -TARGETNAME = libmm -TARGETTYPE = LIBRARY -SOURCES = mm.c - diff --git a/src/main/mm/mm.c b/src/main/mm/mm.c index db543a62..1518904e 100644 --- a/src/main/mm/mm.c +++ b/src/main/mm/mm.c @@ -9,11 +9,12 @@ #include #include +#include "iface-core/log.h" + #include "mm/mm.h" #include "util/cmdline.h" #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" DEFINE_GUID( diff --git a/src/main/module/Module.mk b/src/main/module/Module.mk new file mode 100644 index 00000000..b2a5f5ce --- /dev/null +++ b/src/main/module/Module.mk @@ -0,0 +1,16 @@ +libs += module + +libs_module := \ + core \ + hook \ + util \ + +src_module := \ + acio-mgr-ext.c \ + acio-mgr.c \ + hook.c \ + input-ext.c \ + input.c \ + io-ext.c \ + io.c \ + module.c \ diff --git a/src/main/module/acio-mgr-ext.c b/src/main/module/acio-mgr-ext.c new file mode 100644 index 00000000..f213f579 --- /dev/null +++ b/src/main/module/acio-mgr-ext.c @@ -0,0 +1,15 @@ +#include "iface-core/log.h" + +#include "module/acio-mgr.h" + +void module_acio_mgr_ext_load_and_init( + const char *path, module_acio_mgr_t **module) +{ + bt_core_log_api_t core_log_api; + + module_acio_mgr_load(path, module); + + bt_core_log_api_get(&core_log_api); + + module_acio_mgr_core_log_api_set(*module, &core_log_api); +} \ No newline at end of file diff --git a/src/main/module/acio-mgr-ext.h b/src/main/module/acio-mgr-ext.h new file mode 100644 index 00000000..b8e08032 --- /dev/null +++ b/src/main/module/acio-mgr-ext.h @@ -0,0 +1,9 @@ +#ifndef MODULE_ACIO_MGR_EXT_H +#define MODULE_ACIO_MGR_EXT_H + +#include "module/acio-mgr.h" + +void module_acio_mgr_ext_load_and_init( + const char *path, module_acio_mgr_t **module); + +#endif \ No newline at end of file diff --git a/src/main/module/acio-mgr.c b/src/main/module/acio-mgr.c new file mode 100644 index 00000000..08f55dd1 --- /dev/null +++ b/src/main/module/acio-mgr.c @@ -0,0 +1,83 @@ +#define LOG_MODULE "module-acio_mgr" + +#include "api/acio/mgr.h" +#include "api/core/log.h" + +#include "iface-core/log.h" + +#include "main/module/acio-mgr.h" +#include "main/module/core.h" +#include "main/module/module.h" + +#include "util/mem.h" + +typedef void (*module_acio_mgr_api_get_t)(bt_acio_mgr_api_t *api); + +struct module_acio_mgr { + module_t *module; + + bt_module_core_log_api_set_t core_log_api_set; + + module_acio_mgr_api_get_t api_get; +}; + +static void _module_acio_mgr_resolve(module_acio_mgr_t *module) +{ + module->core_log_api_set = + (bt_module_core_log_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_log_api_set"); + + module->api_get = (module_acio_mgr_api_get_t) module_func_required_resolve( + module->module, "bt_acio_mgr_api_get"); +} + +void module_acio_mgr_load(const char *path, module_acio_mgr_t **module) +{ + log_assert(path); + log_assert(module); + + *module = xmalloc(sizeof(module_acio_mgr_t)); + memset(*module, 0, sizeof(module_acio_mgr_t)); + + module_load(path, &(*module)->module); + + _module_acio_mgr_resolve(*module); +} + +void module_acio_mgr_free(module_acio_mgr_t **module) +{ + log_assert(module); + + module_free(&(*module)->module); + memset(*module, 0, sizeof(module_acio_mgr_t)); +} + +void module_acio_mgr_core_log_api_set( + const module_acio_mgr_t *module, const bt_core_log_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_log_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_log_api_set"); + + module->core_log_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_log_api_set"); + } +} + +void module_acio_mgr_api_get( + const module_acio_mgr_t *module, bt_acio_mgr_api_t *api) +{ + log_assert(module); + log_assert(api); + + module_func_pre_invoke_log(module->module, "bt_acio_mgr_api_get"); + + module->api_get(api); + + module_func_post_invoke_log(module->module, "bt_acio_mgr_api_get"); +} \ No newline at end of file diff --git a/src/main/module/acio-mgr.h b/src/main/module/acio-mgr.h new file mode 100644 index 00000000..be930670 --- /dev/null +++ b/src/main/module/acio-mgr.h @@ -0,0 +1,21 @@ +#ifndef MODULE_ACIO_MGR_H +#define MODULE_ACIO_MGR_H + +#include +#include + +#include "api/acio/mgr.h" +#include "api/core/log.h" + +typedef struct module_acio_mgr module_acio_mgr_t; + +void module_acio_mgr_load(const char *path, module_acio_mgr_t **module); +void module_acio_mgr_free(module_acio_mgr_t **module); + +void module_acio_mgr_core_log_api_set( + const module_acio_mgr_t *module, const bt_core_log_api_t *api); + +void module_acio_mgr_api_get( + const module_acio_mgr_t *module, bt_acio_mgr_api_t *api); + +#endif \ No newline at end of file diff --git a/src/main/module/configure.h b/src/main/module/configure.h new file mode 100644 index 00000000..2ac7896d --- /dev/null +++ b/src/main/module/configure.h @@ -0,0 +1,8 @@ +#ifndef MODULE_CONFIGURE_H +#define MODULE_CONFIGURE_H + +#include "api/core/config.h" + +typedef bool (*bt_module_configure_do_t)(const bt_core_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/module/core.h b/src/main/module/core.h new file mode 100644 index 00000000..936e0a25 --- /dev/null +++ b/src/main/module/core.h @@ -0,0 +1,14 @@ +#ifndef MODULE_CORE_H +#define MODULE_CORE_H + +#include "api/core/config.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +typedef void (*bt_module_core_config_api_set_t)( + const bt_core_config_api_t *api); +typedef void (*bt_module_core_log_api_set_t)(const bt_core_log_api_t *api); +typedef void (*bt_module_core_thread_api_set_t)( + const bt_core_thread_api_t *api); + +#endif \ No newline at end of file diff --git a/src/main/module/hook.c b/src/main/module/hook.c new file mode 100644 index 00000000..5d659d2e --- /dev/null +++ b/src/main/module/hook.c @@ -0,0 +1,140 @@ +#define LOG_MODULE "module-hook" + +#include + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "main/module/core.h" +#include "main/module/hook.h" +#include "main/module/module.h" + +#include "util/mem.h" +#include "util/str.h" + +struct module_hook { + module_t *module; + + bt_module_core_config_api_set_t core_config_api_set; + bt_module_core_log_api_set_t core_log_api_set; + bt_module_core_thread_api_set_t core_thread_api_set; + + bt_module_hook_api_get_t api_get; +}; + +static void _module_hook_resolve(module_hook_t *module) +{ + module->core_config_api_set = + (bt_module_core_config_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_config_api_set"); + module->core_log_api_set = + (bt_module_core_log_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_log_api_set"); + module->core_thread_api_set = + (bt_module_core_thread_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_thread_api_set"); + + module->api_get = (bt_module_hook_api_get_t) module_func_optional_resolve( + module->module, "bt_module_hook_api_get"); +} + +void module_hook_load(const char *path, module_hook_t **module) +{ + log_assert(path); + log_assert(module); + + *module = xmalloc(sizeof(module_hook_t)); + memset(*module, 0, sizeof(module_hook_t)); + + module_load(path, &(*module)->module); + + _module_hook_resolve(*module); +} + +const char *module_hook_path_get(const module_hook_t *module) +{ + log_assert(module); + + return module_path_get(module->module); +} + +void module_hook_free(module_hook_t **module) +{ + log_assert(module); + + module_free(&(*module)->module); + memset(*module, 0, sizeof(module_hook_t)); +} + +void module_hook_core_config_api_set( + const module_hook_t *module, const bt_core_config_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_config_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_config_api_set"); + + module->core_config_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_config_api_set"); + } +} + +void module_hook_core_log_api_set( + const module_hook_t *module, const bt_core_log_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_log_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_log_api_set"); + + module->core_log_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_log_api_set"); + } +} + +void module_hook_core_thread_api_set( + const module_hook_t *module, const bt_core_thread_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_thread_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_thread_api_set"); + + module->core_thread_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_thread_api_set"); + } +} + +void module_hook_api_get(const module_hook_t *module, bt_hook_api_t *api) +{ + log_assert(module); + log_assert(api); + + memset(api, 0, sizeof(bt_hook_api_t)); + + if (module->api_get) { + module_func_pre_invoke_log(module->module, "bt_hook_api_get"); + + module->api_get(api); + + module_func_post_invoke_log(module->module, "bt_hook_api_get"); + } else { + // Consider this still v1 as all functions are optional + // This allows for creating rather simple and even bemanitools + // independent hook libraries that only use DllMain + api->version = 1; + } +} diff --git a/src/main/module/hook.h b/src/main/module/hook.h new file mode 100644 index 00000000..a4f7c5aa --- /dev/null +++ b/src/main/module/hook.h @@ -0,0 +1,28 @@ +#ifndef MODULE_HOOK_H +#define MODULE_HOOK_H + +#include + +#include +#include + +#include "api/hook.h" + +typedef void (*bt_module_hook_api_get_t)(bt_hook_api_t *api); + +typedef struct module_hook module_hook_t; + +void module_hook_load(const char *path, module_hook_t **module); +const char *module_hook_path_get(const module_hook_t *module); +void module_hook_free(module_hook_t **module); + +void module_hook_core_config_api_set( + const module_hook_t *module, const bt_core_config_api_t *api); +void module_hook_core_log_api_set( + const module_hook_t *module, const bt_core_log_api_t *api); +void module_hook_core_thread_api_set( + const module_hook_t *module, const bt_core_thread_api_t *api); + +void module_hook_api_get(const module_hook_t *module, bt_hook_api_t *api); + +#endif \ No newline at end of file diff --git a/src/main/module/input-ext.c b/src/main/module/input-ext.c new file mode 100644 index 00000000..5022faa1 --- /dev/null +++ b/src/main/module/input-ext.c @@ -0,0 +1,18 @@ +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "module/input.h" + +void module_input_ext_load_and_init(const char *path, module_input_t **module) +{ + bt_core_log_api_t core_log_api; + bt_core_thread_api_t core_thread_api; + + module_input_load(path, module); + + bt_core_log_api_get(&core_log_api); + bt_core_thread_api_get(&core_thread_api); + + module_input_core_log_api_set(*module, &core_log_api); + module_input_core_thread_api_set(*module, &core_thread_api); +} \ No newline at end of file diff --git a/src/main/module/input-ext.h b/src/main/module/input-ext.h new file mode 100644 index 00000000..0967b450 --- /dev/null +++ b/src/main/module/input-ext.h @@ -0,0 +1,8 @@ +#ifndef MODULE_INPUT_EXT_H +#define MODULE_INPUT_EXT_H + +#include "module/input.h" + +void module_input_ext_load_and_init(const char *path, module_input_t **module); + +#endif \ No newline at end of file diff --git a/src/main/module/input.c b/src/main/module/input.c new file mode 100644 index 00000000..cde728a2 --- /dev/null +++ b/src/main/module/input.c @@ -0,0 +1,104 @@ +#define LOG_MODULE "module-input" + +#include "api/input.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" + +#include "main/module/core.h" +#include "main/module/input.h" +#include "main/module/module.h" + +#include "util/mem.h" + +typedef void (*module_input_api_get_t)(bt_input_api_t *api); + +struct module_input { + module_t *module; + + bt_module_core_log_api_set_t core_log_api_set; + bt_module_core_thread_api_set_t core_thread_api_set; + + module_input_api_get_t api_get; +}; + +static void _module_input_resolve(module_input_t *module) +{ + module->core_log_api_set = + (bt_module_core_log_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_log_api_set"); + module->core_thread_api_set = + (bt_module_core_thread_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_thread_api_set"); + + module->api_get = (module_input_api_get_t) module_func_required_resolve( + module->module, "bt_module_input_api_get"); +} + +void module_input_load(const char *path, module_input_t **module) +{ + log_assert(path); + log_assert(module); + + *module = xmalloc(sizeof(module_input_t)); + memset(*module, 0, sizeof(module_input_t)); + + module_load(path, &(*module)->module); + + _module_input_resolve(*module); +} + +void module_input_free(module_input_t **module) +{ + log_assert(module); + + module_free(&(*module)->module); + memset(*module, 0, sizeof(module_input_t)); +} + +void module_input_core_log_api_set( + const module_input_t *module, const bt_core_log_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_log_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_log_api_set"); + + module->core_log_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_log_api_set"); + } +} + +void module_input_core_thread_api_set( + const module_input_t *module, const bt_core_thread_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_thread_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_thread_api_set"); + + module->core_thread_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_thread_api_set"); + } +} + +void module_input_api_get(const module_input_t *module, bt_input_api_t *api) +{ + log_assert(module); + log_assert(api); + + module_func_pre_invoke_log(module->module, "bt_module_input_api_get"); + + module->api_get(api); + + module_func_post_invoke_log(module->module, "bt_module_input_api_get"); +} \ No newline at end of file diff --git a/src/main/module/input.h b/src/main/module/input.h new file mode 100644 index 00000000..0529c5c8 --- /dev/null +++ b/src/main/module/input.h @@ -0,0 +1,24 @@ +#ifndef MODULE_INPUT_H +#define MODULE_INPUT_H + +#include +#include + +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "api/input.h" + +typedef struct module_input module_input_t; + +void module_input_load(const char *path, module_input_t **module); +void module_input_free(module_input_t **module); + +void module_input_core_log_api_set( + const module_input_t *module, const bt_core_log_api_t *api); +void module_input_core_thread_api_set( + const module_input_t *module, const bt_core_thread_api_t *api); + +void module_input_api_get(const module_input_t *module, bt_input_api_t *api); + +#endif \ No newline at end of file diff --git a/src/main/module/io-ext.c b/src/main/module/io-ext.c new file mode 100644 index 00000000..a3cc32dd --- /dev/null +++ b/src/main/module/io-ext.c @@ -0,0 +1,26 @@ +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "module/io.h" + +void module_io_ext_load_and_init( + const char *path, const char *api_get_func_name, module_io_t **module) +{ + // TODO currently not supported + // bt_core_config_api_t core_config_api; + bt_core_log_api_t core_log_api; + bt_core_thread_api_t core_thread_api; + + module_io_load(path, api_get_func_name, module); + + // TODO currently not supported + // bt_core_config_api_get(&core_config_api); + bt_core_log_api_get(&core_log_api); + bt_core_thread_api_get(&core_thread_api); + + // TODO currently not supported + // module_io_core_config_api_set(*module, &core_config_api); + module_io_core_log_api_set(*module, &core_log_api); + module_io_core_thread_api_set(*module, &core_thread_api); +} \ No newline at end of file diff --git a/src/main/module/io-ext.h b/src/main/module/io-ext.h new file mode 100644 index 00000000..993794fb --- /dev/null +++ b/src/main/module/io-ext.h @@ -0,0 +1,9 @@ +#ifndef MODULE_IO_EXT_H +#define MODULE_IO_EXT_H + +#include "module/io.h" + +void module_io_ext_load_and_init( + const char *path, const char *api_get_func_name, module_io_t **module); + +#endif \ No newline at end of file diff --git a/src/main/module/io.c b/src/main/module/io.c new file mode 100644 index 00000000..bb2887f9 --- /dev/null +++ b/src/main/module/io.c @@ -0,0 +1,162 @@ + +#define LOG_MODULE "module-io" + +#include "api/core/config.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" + +#include "main/module/core.h" +#include "main/module/configure.h" +#include "main/module/io.h" +#include "main/module/module.h" + +#include "util/mem.h" +#include "util/str.h" + +typedef void (*module_io_api_get_t)(void *api); + +struct module_io { + module_t *module; + + bt_module_core_config_api_set_t core_config_api_set; + bt_module_core_log_api_set_t core_log_api_set; + bt_module_core_thread_api_set_t core_thread_api_set; + bt_module_configure_do_t configure_do; + + module_io_api_get_t api_get; + // Keep for debug logging + char api_get_func_name[4096]; +}; + +static void +_module_io_resolve(module_io_t *module, const char *api_get_func_name) +{ + module->core_config_api_set = + (bt_module_core_config_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_config_api_set"); + module->core_log_api_set = + (bt_module_core_log_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_log_api_set"); + module->core_thread_api_set = + (bt_module_core_thread_api_set_t) module_func_optional_resolve( + module->module, "bt_module_core_thread_api_set"); + module->configure_do = + (bt_module_configure_do_t) module_func_optional_resolve( + module->module, "bt_module_configure_do"); + + module->api_get = (module_io_api_get_t) module_func_required_resolve( + module->module, api_get_func_name); + str_cpy( + module->api_get_func_name, + sizeof(module->api_get_func_name), + api_get_func_name); +} + +void module_io_load( + const char *path, const char *api_get_func_name, module_io_t **module) +{ + log_assert(path); + log_assert(api_get_func_name); + log_assert(module); + + *module = xmalloc(sizeof(module_io_t)); + memset(*module, 0, sizeof(module_io_t)); + + module_load(path, &(*module)->module); + + _module_io_resolve(*module, api_get_func_name); +} + +void module_io_free(module_io_t **module) +{ + log_assert(module); + + module_free(&(*module)->module); + memset(*module, 0, sizeof(module_io_t)); +} + +void module_io_core_config_api_set( + const module_io_t *module, const bt_core_config_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_config_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_config_api_set"); + + module->core_config_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_config_api_set"); + } +} + +void module_io_core_log_api_set( + const module_io_t *module, const bt_core_log_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_log_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_log_api_set"); + + module->core_log_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_log_api_set"); + } +} + +void module_io_core_thread_api_set( + const module_io_t *module, const bt_core_thread_api_t *api) +{ + log_assert(module); + log_assert(api); + + if (module->core_thread_api_set) { + module_func_pre_invoke_log( + module->module, "bt_module_core_thread_api_set"); + + module->core_thread_api_set(api); + + module_func_post_invoke_log( + module->module, "bt_module_core_thread_api_set"); + } +} + +bool module_io_configure_do(const module_io_t *module, const bt_core_config_t *config) +{ + bool result; + + log_assert(module); + log_assert(config); + + result = true; + + if (module->configure_do) { + module_func_pre_invoke_log( + module->module, "bt_module_configure_do"); + + result = module->configure_do(config); + + module_func_post_invoke_log( + module->module, "bt_module_configure_do"); + } + + return result; +} + +void module_io_api_get(const module_io_t *module, void *api) +{ + log_assert(module); + log_assert(api); + + module_func_pre_invoke_log(module->module, module->api_get_func_name); + + module->api_get(api); + + module_func_post_invoke_log(module->module, module->api_get_func_name); +} \ No newline at end of file diff --git a/src/main/module/io.h b/src/main/module/io.h new file mode 100644 index 00000000..53fb4230 --- /dev/null +++ b/src/main/module/io.h @@ -0,0 +1,27 @@ +#ifndef MODULE_IO_H +#define MODULE_IO_H + +#include +#include + +#include "api/core/config.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +typedef struct module_io module_io_t; + +void module_io_load( + const char *path, const char *api_get_func_name, module_io_t **module); +void module_io_free(module_io_t **module); + +void module_io_core_config_api_set( + const module_io_t *module, const bt_core_config_api_t *api); +void module_io_core_log_api_set( + const module_io_t *module, const bt_core_log_api_t *api); +void module_io_core_thread_api_set( + const module_io_t *module, const bt_core_thread_api_t *api); +bool module_io_configure_do(const module_io_t *module, const bt_core_config_t *config); + +void module_io_api_get(const module_io_t *module, void *api); + +#endif \ No newline at end of file diff --git a/src/main/module/module.c b/src/main/module/module.c new file mode 100644 index 00000000..22832bbb --- /dev/null +++ b/src/main/module/module.c @@ -0,0 +1,285 @@ +#define LOG_MODULE "module" + +#include + +#include +#include + +#include "hook/pe.h" + +#include "iface-core/log.h" + +#include "module/module.h" + +#include "util/mem.h" +#include "util/str.h" + +#define MM_ALLOCATION_GRANULARITY 0x10000 +#define MODULE_FUNC_NAME_MAX_LEN 256 + +struct module { + char path[MAX_PATH]; + HMODULE handle; +}; + +static void _module_hook_dll_iat( + HMODULE hModule, const char *source_dll, const char *iat_hook) +{ + log_assert(hModule); + log_assert(source_dll); + log_assert(iat_hook); + + log_misc( + "replace dll iat of module %p, %s -> %s", + hModule, + source_dll, + iat_hook); + + PBYTE pbModule = (PBYTE) hModule; + + // Find EXE base in process memory + IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *) pbModule; + IMAGE_NT_HEADERS *inh = (IMAGE_NT_HEADERS *) (pbModule + idh->e_lfanew); + + // Search through import table if it exists and replace the target DLL with + // our DLL filename + PIMAGE_SECTION_HEADER pRemoteSectionHeaders = + (PIMAGE_SECTION_HEADER) ((PBYTE) pbModule + sizeof(inh->Signature) + + sizeof(inh->FileHeader) + + inh->FileHeader.SizeOfOptionalHeader); + size_t total_size = inh->OptionalHeader.SizeOfHeaders; + + for (DWORD n = 0; n < inh->FileHeader.NumberOfSections; ++n) { + IMAGE_SECTION_HEADER *header = + (IMAGE_SECTION_HEADER *) (pRemoteSectionHeaders + n); + size_t new_total_size = + header->VirtualAddress + header->Misc.VirtualSize; + if (new_total_size > total_size) + total_size = new_total_size; + } + + void *remote_addr = NULL; + size_t remote_addr_ptr = 0; + + for (size_t i = 0; i < 10000 && remote_addr == NULL; i++) { + remote_addr = VirtualAlloc( + pbModule + total_size + (MM_ALLOCATION_GRANULARITY * (i + 1)), + MAX_PATH + 1, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + } + + log_assert(remote_addr != NULL); + + if (inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress != 0) { + PIMAGE_IMPORT_DESCRIPTOR pImageImport = + (PIMAGE_IMPORT_DESCRIPTOR) (pbModule + + inh->OptionalHeader + .DataDirectory + [IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress); + + DWORD size = 0; + while (inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .Size == 0 || + size < inh->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .Size) { + IMAGE_IMPORT_DESCRIPTOR *ImageImport = + (IMAGE_IMPORT_DESCRIPTOR *) pImageImport; + + if (ImageImport->Name == 0) { + break; + } + + const char *name = (const char *) (pbModule + ImageImport->Name); + const char *expected_dll = source_dll; + const char *replacement_path_dll = iat_hook; + + if (strcmp(name, expected_dll) == 0) { + pe_patch( + (PBYTE) remote_addr + remote_addr_ptr, + replacement_path_dll, + strlen(replacement_path_dll)); + + log_misc("Replacing %s with %s", name, replacement_path_dll); + + DWORD val = (DWORD) ((PBYTE) remote_addr - pbModule); + + pe_patch(&ImageImport->Name, &val, sizeof(DWORD)); + pe_patch(pImageImport, &ImageImport, sizeof(ImageImport)); + + remote_addr_ptr += strlen(replacement_path_dll) + 1; + } + + pImageImport++; + size += sizeof(IMAGE_IMPORT_DESCRIPTOR); + } + } else { + log_fatal("Couldn't find import table, can't hook DLL: %s", iat_hook); + } +} + +static HMODULE _module_load(const char *path, bool resolve_references) +{ + HMODULE module; + LPSTR buffer; + DWORD err; + + log_misc("%s: loading", path); + + if (resolve_references) { + module = LoadLibraryA(path); + } else { + module = LoadLibraryExA(path, NULL, DONT_RESOLVE_DLL_REFERENCES); + } + + if (module == NULL) { + err = GetLastError(); + + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR) &buffer, + 0, + NULL); + + if (err == ERROR_MOD_NOT_FOUND) { + log_warning("%s is likely missing dependencies", path); + } + + log_fatal("Failed to load module %s: %s", path, buffer); + + LocalFree(buffer); + } + + log_misc("%s (%p): loaded", path, module); + + return module; +} + +void module_load(const char *path, module_t **module) +{ + log_assert(path); + log_assert(module); + + *module = xmalloc(sizeof(module_t)); + memset(*module, 0, sizeof(module_t)); + + log_info("%s: load", path); + + str_cpy((*module)->path, sizeof((*module)->path), path); + (*module)->handle = _module_load(path, true); + + log_misc("%s (%p): loaded", (*module)->path, (*module)->handle); +} + +HMODULE module_handle_get(const module_t *module) +{ + log_assert(module); + + return module->handle; +} + +const char *module_path_get(const module_t *module) +{ + log_assert(module); + + return module->path; +} + +void *module_func_required_resolve(const module_t *module, const char *name) +{ + void *func; + + log_assert(module); + log_assert(name); + + func = GetProcAddress(module->handle, name); + + module_func_required_verify(module, func, name); + + return func; +} + +void *module_func_optional_resolve(const module_t *module, const char *name) +{ + void *func; + + log_assert(module); + log_assert(name); + + func = GetProcAddress(module->handle, name); + + module_func_optional_verify(module, func, name); + + return func; +} + +void module_func_required_verify( + const module_t *module, void *func, const char *name) +{ + log_assert(module); + log_assert(name); + + if (!func) { + log_fatal( + "%s (%p): Missing required function '%s'", + module->path, + module->handle, + name); + } + + log_misc( + "%s (%p): required function '%s' at %p", + module->path, + module->handle, + name, + func); +} + +void module_func_optional_verify( + const module_t *module, void *func, const char *name) +{ + log_assert(module); + log_assert(name); + + if (!func) { + log_misc( + "%s (%p): optional function '%s' NOT IMPLEMENTED", + module->path, + module->handle, + name); + } else { + log_misc( + "%s (%p): optional function '%s' at %p", + module->path, + module->handle, + name, + func); + } +} + +void module_func_pre_invoke_log(const module_t *module, const char *name) +{ + log_misc("%s (%p): >>> %s", module->path, module->handle, name); +} + +void module_func_post_invoke_log(const module_t *module, const char *name) +{ + log_misc("%s (%p): <<< %s", module->path, module->handle, name); +} + +void module_free(module_t **module) +{ + log_assert(module); + + log_misc("%s (%p): free", (*module)->path, (*module)->handle); + + FreeLibrary((*module)->handle); + memset(*module, 0, sizeof(module_t)); +} diff --git a/src/main/module/module.h b/src/main/module/module.h new file mode 100644 index 00000000..8d713398 --- /dev/null +++ b/src/main/module/module.h @@ -0,0 +1,24 @@ +#ifndef MODULE_H +#define MODULE_H + +#include + +#include +#include + +typedef struct module module_t; + +void module_load(const char *path, module_t **module); +HMODULE module_handle_get(const module_t *module); +const char *module_path_get(const module_t *module); +void *module_func_required_resolve(const module_t *module, const char *name); +void *module_func_optional_resolve(const module_t *module, const char *name); +void module_func_required_verify( + const module_t *module, void *func, const char *name); +void module_func_optional_verify( + const module_t *module, void *func, const char *name); +void module_func_pre_invoke_log(const module_t *module, const char *name); +void module_func_post_invoke_log(const module_t *module, const char *name); +void module_free(module_t **module); + +#endif \ No newline at end of file diff --git a/src/main/mxml/Module.mk b/src/main/mxml/Module.mk new file mode 100644 index 00000000..303cb21b --- /dev/null +++ b/src/main/mxml/Module.mk @@ -0,0 +1,14 @@ +libs += mxml + +libs_mxml := \ + +src_mxml := \ + mxml-get.c \ + mxml-options.c \ + mxml-search.c \ + mxml-attr.c \ + mxml-index.c \ + mxml-private.c \ + mxml-set.c \ + mxml-file.c \ + mxml-node.c \ diff --git a/src/main/mxml/config.h b/src/main/mxml/config.h new file mode 100644 index 00000000..dcb50a01 --- /dev/null +++ b/src/main/mxml/config.h @@ -0,0 +1,49 @@ +/* config.h. Generated from config.h.in by configure. */ +// +// Configuration file for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#ifndef MXML_CONFIG_H +# define MXML_CONFIG_H +# include +# include +# include +# include +# include + +// +// Version number +// + +# define MXML_VERSION "Mini-XML v4.0.3" + + +// +// Inline function support +// + +# define inline + + +// +// Long long support +// + +# define HAVE_LONG_LONG_INT 1 + + +// +// Have ? +// + +// # define HAVE_PTHREAD_H 1 + + +#endif // !MXML_CONFIG_H diff --git a/src/main/mxml/mxml-attr.c b/src/main/mxml/mxml-attr.c new file mode 100644 index 00000000..98dd5f51 --- /dev/null +++ b/src/main/mxml/mxml-attr.c @@ -0,0 +1,271 @@ +// +// Attribute support code for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// Local functions... +// + +static bool mxml_set_attr(mxml_node_t *node, const char *name, char *value); + + +// +// 'mxmlElementClearAttr()' - Remove an attribute from an element. +// +// This function removes the attribute `name` from the element `node`. +// + +void +mxmlElementClearAttr(mxml_node_t *node, // I - Element + const char *name) // I - Attribute name +{ + size_t i; // Looping var + _mxml_attr_t *attr; // Cirrent attribute + + + MXML_DEBUG("mxmlElementClearAttr(node=%p, name=\"%s\")\n", node, name ? name : "(null)"); + + // Range check input... + if (!node || node->type != MXML_TYPE_ELEMENT || !name) + return; + + // Look for the attribute... + for (i = node->value.element.num_attrs, attr = node->value.element.attrs; i > 0; i --, attr ++) + { + MXML_DEBUG("mxmlElementClearAttr: %s=\"%s\"\n", attr->name, attr->value); + + if (!strcmp(attr->name, name)) + { + // Delete this attribute... + _mxml_strfree(attr->name); + _mxml_strfree(attr->value); + + i --; + if (i > 0) + memmove(attr, attr + 1, i * sizeof(_mxml_attr_t)); + + node->value.element.num_attrs --; + + if (node->value.element.num_attrs == 0) + free(node->value.element.attrs); + return; + } + } +} + + +// +// 'mxmlElementGetAttr()' - Get the value of an attribute. +// +// This function gets the value for the attribute `name` from the element +// `node`. `NULL` is returned if the node is not an element or the named +// attribute does not exist. +// + +const char * // O - Attribute value or `NULL` +mxmlElementGetAttr(mxml_node_t *node, // I - Element node + const char *name) // I - Name of attribute +{ + size_t i; // Looping var + _mxml_attr_t *attr; // Cirrent attribute + + + MXML_DEBUG("mxmlElementGetAttr(node=%p, name=\"%s\")\n", node, name ? name : "(null)"); + + // Range check input... + if (!node || node->type != MXML_TYPE_ELEMENT || !name) + return (NULL); + + // Look for the attribute... + for (i = node->value.element.num_attrs, attr = node->value.element.attrs; i > 0; i --, attr ++) + { + MXML_DEBUG("mxmlElementGetAttr: %s=\"%s\"\n", attr->name, attr->value); + + if (!strcmp(attr->name, name)) + { + MXML_DEBUG("mxmlElementGetAttr: Returning \"%s\".\n", attr->value); + return (attr->value); + } + } + + // Didn't find attribute, so return NULL... + MXML_DEBUG("mxmlElementGetAttr: Returning NULL.\n"); + + return (NULL); +} + + +// +// 'mxmlElementGetAttrByIndex()' - Get an attribute by index. +// +// This function returned the Nth (`idx`) attribute for element `node`. The +// attribute name is optionallly returned in the `name` argument. `NULL` is +// returned if node is not an element or the specified index is out of range. +// + +const char * // O - Attribute value +mxmlElementGetAttrByIndex( + mxml_node_t *node, // I - Node + size_t idx, // I - Attribute index, starting at `0` + const char **name) // O - Attribute name or `NULL` to not return it +{ + if (!node || node->type != MXML_TYPE_ELEMENT || idx >= node->value.element.num_attrs) + return (NULL); + + if (name) + *name = node->value.element.attrs[idx].name; + + return (node->value.element.attrs[idx].value); +} + + +// +// 'mxmlElementGetAttrCount()' - Get the number of element attributes. +// +// This function returns the number of attributes for the element `node`. `0` +// is returned if the node is not an element or there are no attributes for the +// element. +// + +size_t // O - Number of attributes +mxmlElementGetAttrCount( + mxml_node_t *node) // I - Node +{ + if (node && node->type == MXML_TYPE_ELEMENT) + return (node->value.element.num_attrs); + else + return (0); +} + + +// +// 'mxmlElementSetAttr()' - Set an attribute for an element. +// +// This function sets attribute `name` to the string `value` for the element +// `node`. If the named attribute already exists, the value of the attribute +// is replaced by the new string value. The string value is copied. +// + +void +mxmlElementSetAttr(mxml_node_t *node, // I - Element node + const char *name, // I - Name of attribute + const char *value) // I - Attribute value +{ + char *valuec; // Copy of value + + + MXML_DEBUG("mxmlElementSetAttr(node=%p, name=\"%s\", value=\"%s\")\n", node, name ? name : "(null)", value ? value : "(null)"); + + // Range check input... + if (!node || node->type != MXML_TYPE_ELEMENT || !name) + return; + + if (value) + { + if ((valuec = _mxml_strcopy(value)) == NULL) + return; + } + else + { + valuec = NULL; + } + + if (!mxml_set_attr(node, name, valuec)) + _mxml_strfree(valuec); +} + + +// +// 'mxmlElementSetAttrf()' - Set an attribute with a formatted value. +// +// This function sets attribute `name` to the formatted value of `format` for +// the element `node`. If the named attribute already exists, the value of the +// attribute is replaced by the new formatted string value. +// + +void +mxmlElementSetAttrf(mxml_node_t *node, // I - Element node + const char *name, // I - Name of attribute + const char *format,// I - Printf-style attribute value + ...) // I - Additional arguments as needed +{ + va_list ap; // Argument pointer + char buffer[16384]; // Format buffer + char *value; // Value + + + MXML_DEBUG("mxmlElementSetAttrf(node=%p, name=\"%s\", format=\"%s\", ...)\n", node, name ? name : "(null)", format ? format : "(null)"); + + // Range check input... + if (!node || node->type != MXML_TYPE_ELEMENT || !name || !format) + return; + + // Format the value... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + if ((value = _mxml_strcopy(buffer)) != NULL) + { + if (!mxml_set_attr(node, name, value)) + _mxml_strfree(value); + } +} + + +// +// 'mxml_set_attr()' - Set or add an attribute name/value pair. +// + +static bool // O - `true` on success, `false` on failure +mxml_set_attr(mxml_node_t *node, // I - Element node + const char *name, // I - Attribute name + char *value) // I - Attribute value +{ + int i; // Looping var + _mxml_attr_t *attr; // New attribute + + + // Look for the attribute... + for (i = node->value.element.num_attrs, attr = node->value.element.attrs; i > 0; i --, attr ++) + { + if (!strcmp(attr->name, name)) + { + // Free the old value as needed... + _mxml_strfree(attr->value); + attr->value = value; + + return (true); + } + } + + // Add a new attribute... + if ((node->value.element.num_attrs % MXML_ALLOC_SIZE) == 0) + { + if ((attr = realloc(node->value.element.attrs, (node->value.element.num_attrs + MXML_ALLOC_SIZE) * sizeof(_mxml_attr_t))) == NULL) + return (false); + + node->value.element.attrs = attr; + } + + attr = node->value.element.attrs + node->value.element.num_attrs; + + if ((attr->name = _mxml_strcopy(name)) == NULL) + return (false); + + attr->value = value; + + node->value.element.num_attrs ++; + + return (true); +} diff --git a/src/main/mxml/mxml-file.c b/src/main/mxml/mxml-file.c new file mode 100644 index 00000000..d030e3f6 --- /dev/null +++ b/src/main/mxml/mxml-file.c @@ -0,0 +1,2275 @@ +// +// File loading code for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#ifndef _WIN32 +# include +#endif // !_WIN32 +#include "mxml-private.h" + + +// +// Local types... +// + +typedef enum _mxml_encoding_e // Character encoding +{ + _MXML_ENCODING_UTF8, // UTF-8 + _MXML_ENCODING_UTF16BE, // UTF-16 Big-Endian + _MXML_ENCODING_UTF16LE // UTF-16 Little-Endian +} _mxml_encoding_t; + +typedef struct _mxml_stringbuf_s // String buffer +{ + char *buffer, // Buffer + *bufptr; // Pointer into buffer + size_t bufsize; // Size of buffer + bool bufalloc; // Allocate buffer? +} _mxml_stringbuf_t; + + +// +// Macro to test for a bad XML character... +// + +#define mxml_bad_char(ch) ((ch) < ' ' && (ch) != '\n' && (ch) != '\r' && (ch) != '\t') + + +// +// Local functions... +// + +static bool mxml_add_char(mxml_options_t *options, int ch, char **ptr, char **buffer, size_t *bufsize); +static int mxml_get_entity(mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata, _mxml_encoding_t *encoding, mxml_node_t *parent, int *line); +static int mxml_getc(mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata, _mxml_encoding_t *encoding); +static inline int mxml_isspace(int ch) + { + return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); + } +static mxml_node_t *mxml_load_data(mxml_node_t *top, mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata); +static int mxml_parse_element(mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata, mxml_node_t *node, _mxml_encoding_t *encoding, int *line); +// static size_t mxml_read_cb_fd(int *fd, void *buffer, size_t bytes); +static size_t mxml_read_cb_file(FILE *fp, void *buffer, size_t bytes); +static size_t mxml_read_cb_string(_mxml_stringbuf_t *sb, void *buffer, size_t bytes); +static double mxml_strtod(mxml_options_t *options, const char *buffer, char **bufptr); +// static size_t mxml_io_cb_fd(int *fd, void *buffer, size_t bytes); +static size_t mxml_io_cb_file(FILE *fp, void *buffer, size_t bytes); +static size_t mxml_io_cb_string(_mxml_stringbuf_t *sb, void *buffer, size_t bytes); +static int mxml_write_node(mxml_node_t *node, mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata, int col); +static int mxml_write_string(const char *s, mxml_io_cb_t io_cb, void *io_cbdata, bool use_entities, int col); +static int mxml_write_ws(mxml_node_t *node, mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata, mxml_ws_t ws, int col); + + +// +// 'mxmlLoadFd()' - Load a file descriptor into an XML node tree. +// +// This function loads the file descriptor `fd` into an XML node tree. The +// nodes in the specified file are added to the specified node `top` - if `NULL` +// the XML file MUST be well-formed with a single parent processing instruction +// node like `` at the start of the file. +// +// Load options are provides via the `options` argument. If `NULL`, all values +// will be loaded into `MXML_TYPE_TEXT` nodes. Use the @link mxmlOptionsNew@ +// function to create options when loading XML data. +// + +// mxml_node_t * // O - First node or `NULL` if the file could not be read. +// mxmlLoadFd( +// mxml_node_t *top, // I - Top node +// mxml_options_t *options, // I - Options +// int fd) // I - File descriptor to read from +// { +// // Range check input... +// if (fd < 0) +// return (NULL); + +// // Read the XML data... +// return (mxml_load_data(top, options, (mxml_io_cb_t)mxml_read_cb_fd, &fd)); +// } + + +// +// 'mxmlLoadFile()' - Load a file into an XML node tree. +// +// This function loads the `FILE` pointer `fp` into an XML node tree. The +// nodes in the specified file are added to the specified node `top` - if `NULL` +// the XML file MUST be well-formed with a single parent processing instruction +// node like `` at the start of the file. +// +// Load options are provides via the `options` argument. If `NULL`, all values +// will be loaded into `MXML_TYPE_TEXT` nodes. Use the @link mxmlOptionsNew@ +// function to create options when loading XML data. +// + +mxml_node_t * // O - First node or `NULL` if the file could not be read. +mxmlLoadFile( + mxml_node_t *top, // I - Top node + mxml_options_t *options, // I - Options + FILE *fp) // I - File to read from +{ + // Range check input... + if (!fp) + return (NULL); + + // Read the XML data... + return (mxml_load_data(top, options, (mxml_io_cb_t)mxml_read_cb_file, fp)); +} + + +// +// 'mxmlLoadFilename()' - Load a file into an XML node tree. +// +// This function loads the named file `filename` into an XML node tree. The +// nodes in the specified file are added to the specified node `top` - if `NULL` +// the XML file MUST be well-formed with a single parent processing instruction +// node like `` at the start of the file. +// +// Load options are provides via the `options` argument. If `NULL`, all values +// will be loaded into `MXML_TYPE_TEXT` nodes. Use the @link mxmlOptionsNew@ +// function to create options when loading XML data. +// + +mxml_node_t * // O - First node or `NULL` if the file could not be read. +mxmlLoadFilename( + mxml_node_t *top, // I - Top node + mxml_options_t *options, // I - Options + const char *filename) // I - File to read from +{ + FILE *fp; // File pointer + mxml_node_t *ret; // Node + + + // Range check input... + if (!filename) + return (NULL); + + // Open the file... + if ((fp = fopen(filename, "r")) == NULL) + return (NULL); + + // Read the XML data... + ret = mxml_load_data(top, options, (mxml_io_cb_t)mxml_read_cb_file, fp); + + // Close the file and return... + fclose(fp); + + return (ret); +} + + +// +// 'mxmlLoadIO()' - Load an XML node tree using a read callback. +// +// This function loads data into an XML node tree using a read callback. The +// nodes in the specified file are added to the specified node `top` - if `NULL` +// the XML file MUST be well-formed with a single parent processing instruction +// node like `` at the start of the file. +// +// Load options are provides via the `options` argument. If `NULL`, all values +// will be loaded into `MXML_TYPE_TEXT` nodes. Use the @link mxmlOptionsNew@ +// function to create options when loading XML data. +// +// The read callback function `io_cb` is called to read a number of bytes from +// the source. The callback data pointer `io_cbdata` is passed to the read +// callback with a pointer to a buffer and the maximum number of bytes to read, +// for example: +// +// ```c +// size_t my_io_cb(void *cbdata, void *buffer, size_t bytes) +// { +// ... copy up to "bytes" bytes into buffer ... +// ... return the number of bytes "read" or 0 on error ... +// } +// ``` +// + +mxml_node_t * // O - First node or `NULL` if the file could not be read. +mxmlLoadIO( + mxml_node_t *top, // I - Top node + mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Read callback function + void *io_cbdata) // I - Read callback data +{ + // Range check input... + if (!io_cb) + return (NULL); + + // Read the XML data... + return (mxml_load_data(top, options, io_cb, io_cbdata)); +} + + +// +// 'mxmlLoadString()' - Load a string into an XML node tree. +// +// This function loads the string into an XML node tree. The nodes in the +// specified file are added to the specified node `top` - if `NULL` the XML file +// MUST be well-formed with a single parent processing instruction node like +// `` at the start of the file. +// +// Load options are provides via the `options` argument. If `NULL`, all values +// will be loaded into `MXML_TYPE_TEXT` nodes. Use the @link mxmlOptionsNew@ +// function to create options when loading XML data. +// + +mxml_node_t * // O - First node or `NULL` if the string has errors. +mxmlLoadString( + mxml_node_t *top, // I - Top node + mxml_options_t *options, // I - Options + const char *s) // I - String to load +{ + _mxml_stringbuf_t sb; // String buffer + + + // Range check input... + if (!s) + return (NULL); + + // Setup string buffer... + sb.buffer = (char *)s; + sb.bufptr = (char *)s; + sb.bufsize = strlen(s); + sb.bufalloc = false; + + // Read the XML data... + return (mxml_load_data(top, options, (mxml_io_cb_t)mxml_read_cb_string, &sb)); +} + + +// +// 'mxmlSaveAllocString()' - Save an XML tree to an allocated string. +// +// This function saves the XML tree `node` to an allocated string. The string +// should be freed using `free` (or the string free callback set using +// @link mxmlSetStringCallbacks@) when you are done with it. +// +// `NULL` is returned if the node would produce an empty string or if the string +// cannot be allocated. +// +// Save options are provides via the `options` argument. If `NULL`, the XML +// output will be wrapped at column 72 with no additional whitespace. Use the +// @link mxmlOptionsNew@ function to create options for saving XML data. +// + +char * // O - Allocated string or `NULL` +mxmlSaveAllocString( + mxml_node_t *node, // I - Node to write + mxml_options_t *options) // I - Options +{ + _mxml_stringbuf_t sb; // String buffer + + + // Setup a string buffer + if ((sb.buffer = malloc(1024)) == NULL) + return (NULL); + + sb.bufptr = sb.buffer; + sb.bufsize = 1024; + sb.bufalloc = true; + + // Write the top node... + if (mxml_write_node(node, options, (mxml_io_cb_t)mxml_io_cb_string, &sb, 0) < 0) + { + free(sb.buffer); + return (NULL); + } + + // Nul-terminate the string... + *(sb.bufptr) = '\0'; + + // Return the allocated string... + return (sb.buffer); +} + + +// +// 'mxmlSaveFd()' - Save an XML tree to a file descriptor. +// +// This function saves the XML tree `node` to a file descriptor. +// +// Save options are provides via the `options` argument. If `NULL`, the XML +// output will be wrapped at column 72 with no additional whitespace. Use the +// @link mxmlOptionsNew@ function to create options for saving XML data. +// + +// bool // O - `true` on success, `false` on error. +// mxmlSaveFd(mxml_node_t *node, // I - Node to write +// mxml_options_t *options, // I - Options +// int fd) // I - File descriptor to write to +// { +// int col; // Final column + + +// // Write the node... +// if ((col = mxml_write_node(node, options, (mxml_io_cb_t)mxml_io_cb_fd, &fd, 0)) < 0) +// return (false); + +// // Make sure the file ends with a newline... +// if (col > 0) +// { +// if (write(fd, "\n", 1) < 0) +// return (false); +// } + +// return (true); +// } + + +// +// 'mxmlSaveFile()' - Save an XML tree to a file. +// +// This function saves the XML tree `node` to a stdio `FILE`. +// +// Save options are provides via the `options` argument. If `NULL`, the XML +// output will be wrapped at column 72 with no additional whitespace. Use the +// @link mxmlOptionsNew@ function to create options for saving XML data. +// + +bool // O - `true` on success, `false` on error. +mxmlSaveFile( + mxml_node_t *node, // I - Node to write + mxml_options_t *options, // I - Options + FILE *fp) // I - File to write to +{ + int col; // Final column + + + // Write the node... + if ((col = mxml_write_node(node, options, (mxml_io_cb_t)mxml_io_cb_file, fp, 0)) < 0) + return (false); + + // Make sure the file ends with a newline... + if (col > 0) + { + if (putc('\n', fp) < 0) + return (false); + } + + return (true); +} + + +// +// 'mxmlSaveFilename()' - Save an XML tree to a file. +// +// This function saves the XML tree `node` to a named file. +// +// Save options are provides via the `options` argument. If `NULL`, the XML +// output will be wrapped at column 72 with no additional whitespace. Use the +// @link mxmlOptionsNew@ function to create options for saving XML data. +// + +bool // O - `true` on success, `false` on error. +mxmlSaveFilename( + mxml_node_t *node, // I - Node to write + mxml_options_t *options, // I - Options + const char *filename) // I - File to write to +{ + bool ret = true; // Return value + FILE *fp; // File pointer + int col; // Final column + + + // Open the file... + if ((fp = fopen(filename, "w")) == NULL) + return (false); + + // Write the node... + if ((col = mxml_write_node(node, options, (mxml_io_cb_t)mxml_io_cb_file, fp, 0)) < 0) + { + ret = false; + } + else if (col > 0) + { + // Make sure the file ends with a newline... + if (putc('\n', fp) < 0) + ret = false; + } + + fclose(fp); + + return (ret); +} + + +// +// 'mxmlSaveIO()' - Save an XML tree using a callback. +// +// This function saves the XML tree `node` using a write callback function +// `io_cb`. The write callback is called with the callback data pointer +// `io_cbdata`, a buffer pointer, and the number of bytes to write, for +// example: +// +// ```c +// size_t my_io_cb(void *cbdata, const void *buffer, size_t bytes) +// { +// ... write/copy bytes from buffer to the output ... +// ... return the number of bytes written/copied or 0 on error ... +// } +// ``` +// +// Save options are provides via the `options` argument. If `NULL`, the XML +// output will be wrapped at column 72 with no additional whitespace. Use the +// @link mxmlOptionsNew@ function to create options for saving XML data. +// + +bool // O - `true` on success, `false` on error. +mxmlSaveIO( + mxml_node_t *node, // I - Node to write + mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Write callback function + void *io_cbdata) // I - Write callback data +{ + int col; // Final column + + + // Range check input... + if (!node || !io_cb) + return (false); + + // Write the node... + if ((col = mxml_write_node(node, options, io_cb, io_cbdata, 0)) < 0) + return (false); + + if (col > 0) + { + // Make sure the file ends with a newline... + if ((io_cb)(io_cbdata, "\n", 1) != 1) + return (false); + } + + return (true); +} + + +// +// 'mxmlSaveString()' - Save an XML node tree to a string. +// +// This function saves the XML tree `node` to a fixed-size string buffer. +// +// Save options are provides via the `options` argument. If `NULL`, the XML +// output will be wrapped at column 72 with no additional whitespace. Use the +// @link mxmlOptionsNew@ function to create options for saving XML data. +// + +size_t // O - Size of string +mxmlSaveString( + mxml_node_t *node, // I - Node to write + mxml_options_t *options, // I - Options + char *buffer, // I - String buffer + size_t bufsize) // I - Size of string buffer +{ + _mxml_stringbuf_t sb; // String buffer + + + // Setup the string buffer... + sb.buffer = buffer; + sb.bufptr = buffer; + sb.bufsize = bufsize; + sb.bufalloc = false; + + // Write the node... + if (mxml_write_node(node, options, (mxml_io_cb_t)mxml_io_cb_string, &sb, 0) < 0) + return (false); + + // Nul-terminate the string... + if (sb.bufptr < (sb.buffer + sb.bufsize)) + *(sb.bufptr) = '\0'; + + // Return the number of characters... + return ((size_t)(sb.bufptr - sb.buffer)); +} + + +// +// 'mxml_add_char()' - Add a character to a buffer, expanding as needed. +// + +static bool // O - `true` on success, `false` on error +mxml_add_char(mxml_options_t *options, // I - Options + int ch, // I - Character to add + char **bufptr, // IO - Current position in buffer + char **buffer, // IO - Current buffer + size_t *bufsize) // IO - Current buffer size +{ + char *newbuffer; // New buffer value + + + if (*bufptr >= (*buffer + *bufsize - 4)) + { + // Increase the size of the buffer... + if (*bufsize < 1024) + (*bufsize) *= 2; + else + (*bufsize) += 1024; + + if ((newbuffer = realloc(*buffer, *bufsize)) == NULL) + { + _mxml_error(options, "Unable to expand string buffer to %lu bytes.", (unsigned long)*bufsize); + + return (false); + } + + *bufptr = newbuffer + (*bufptr - *buffer); + *buffer = newbuffer; + } + + if (ch < 0x80) + { + // Single byte ASCII... + *(*bufptr)++ = ch; + } + else if (ch < 0x800) + { + // Two-byte UTF-8... + *(*bufptr)++ = 0xc0 | (ch >> 6); + *(*bufptr)++ = 0x80 | (ch & 0x3f); + } + else if (ch < 0x10000) + { + // Three-byte UTF-8... + *(*bufptr)++ = 0xe0 | (ch >> 12); + *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f); + *(*bufptr)++ = 0x80 | (ch & 0x3f); + } + else + { + // Four-byte UTF-8... + *(*bufptr)++ = 0xf0 | (ch >> 18); + *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f); + *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f); + *(*bufptr)++ = 0x80 | (ch & 0x3f); + } + + return (true); +} + + +// +// 'mxml_get_entity()' - Get the character corresponding to an entity... +// + +static int // O - Character value or `EOF` on error +mxml_get_entity( + mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Read callback function + void *io_cbdata, // I - Read callback data + _mxml_encoding_t *encoding, // IO - Character encoding + mxml_node_t *parent, // I - Parent node + int *line) // IO - Current line number +{ + int ch; // Current character + char entity[64], // Entity string + *entptr; // Pointer into entity + + + // Read a HTML character entity of the form "&NAME;", "&#NUMBER;", or "&#xHEX"... + entptr = entity; + + while ((ch = mxml_getc(options, io_cb, io_cbdata, encoding)) != EOF) + { + if (ch > 126 || (!isalnum(ch) && ch != '#')) + { + break; + } + else if (entptr < (entity + sizeof(entity) - 1)) + { + *entptr++ = ch; + } + else + { + _mxml_error(options, "Entity name too long under parent <%s> on line %d.", mxmlGetElement(parent), *line); + break; + } + } + + *entptr = '\0'; + + if (ch != ';') + { + _mxml_error(options, "Character entity '%s' not terminated under parent <%s> on line %d.", entity, mxmlGetElement(parent), *line); + + if (ch == '\n') + (*line)++; + + return (EOF); + } + + if ((ch = _mxml_entity_value(options, entity)) < 0) + { + _mxml_error(options, "Entity '&%s;' not supported under parent <%s> on line %d.", entity, mxmlGetElement(parent), *line); + return (EOF); + } + + if (mxml_bad_char(ch)) + { + _mxml_error(options, "Bad control character 0x%02x under parent <%s> on line %d not allowed by XML standard.", ch, mxmlGetElement(parent), *line); + return (EOF); + } + + return (ch); +} + + +// +// 'mxml_getc()' - Read a character from a file descriptor. +// + +static int // O - Character or `EOF` +mxml_getc(mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Read callback function + void *io_cbdata, // I - Read callback data + _mxml_encoding_t *encoding) // IO - Encoding +{ + int ch; // Current character + unsigned char buffer[4]; // Read buffer + + + // Grab the next character... + read_first_byte: + + if ((io_cb)(io_cbdata, buffer, 1) != 1) + return (EOF); + + ch = buffer[0]; + + switch (*encoding) + { + case _MXML_ENCODING_UTF8 : + // Got a UTF-8 character; convert UTF-8 to Unicode and return... + if (!(ch & 0x80)) + { + // ASCII + break; + } + else if (ch == 0xfe) + { + // UTF-16 big-endian BOM? + if ((io_cb)(io_cbdata, buffer + 1, 1) != 1) + return (EOF); + + if (buffer[1] != 0xff) + return (EOF); + + // Yes, switch to UTF-16 BE and try reading again... + *encoding = _MXML_ENCODING_UTF16BE; + + goto read_first_byte; + } + else if (ch == 0xff) + { + // UTF-16 little-endian BOM? + if ((io_cb)(io_cbdata, buffer + 1, 1) != 1) + return (EOF); + + if (buffer[1] != 0xfe) + return (EOF); + + // Yes, switch to UTF-16 LE and try reading again... + *encoding = _MXML_ENCODING_UTF16LE; + + goto read_first_byte; + } + else if ((ch & 0xe0) == 0xc0) + { + // Two-byte value... + if ((io_cb)(io_cbdata, buffer + 1, 1) != 1) + return (EOF); + + if ((buffer[1] & 0xc0) != 0x80) + return (EOF); + + ch = ((ch & 0x1f) << 6) | (buffer[1] & 0x3f); + + if (ch < 0x80) + { + _mxml_error(options, "Invalid UTF-8 sequence for character 0x%04x.", ch); + return (EOF); + } + } + else if ((ch & 0xf0) == 0xe0) + { + // Three-byte value... + if ((io_cb)(io_cbdata, buffer + 1, 2) != 2) + return (EOF); + + if ((buffer[1] & 0xc0) != 0x80 || (buffer[2] & 0xc0) != 0x80) + return (EOF); + + ch = ((ch & 0x0f) << 12) | ((buffer[1] & 0x3f) << 6) | (buffer[2] & 0x3f); + + if (ch < 0x800) + { + _mxml_error(options, "Invalid UTF-8 sequence for character 0x%04x.", ch); + return (EOF); + } + + // Ignore (strip) Byte Order Mark (BOM)... + if (ch == 0xfeff) + goto read_first_byte; + } + else if ((ch & 0xf8) == 0xf0) + { + // Four-byte value... + if ((io_cb)(io_cbdata, buffer + 1, 3) != 3) + return (EOF); + + if ((buffer[1] & 0xc0) != 0x80 || (buffer[2] & 0xc0) != 0x80 || (buffer[3] & 0xc0) != 0x80) + return (EOF); + + ch = ((ch & 0x07) << 18) | ((buffer[1] & 0x3f) << 12) | ((buffer[2] & 0x3f) << 6) | (buffer[3] & 0x3f); + + if (ch < 0x10000) + { + _mxml_error(options, "Invalid UTF-8 sequence for character 0x%04x.", ch); + return (EOF); + } + } + else + { + return (EOF); + } + break; + + case _MXML_ENCODING_UTF16BE : + // Read UTF-16 big-endian char... + if ((io_cb)(io_cbdata, buffer + 1, 1) != 1) + return (EOF); + + ch = (ch << 8) | buffer[1]; + + if (ch >= 0xd800 && ch <= 0xdbff) + { + // Multi-word UTF-16 char... + int lch; // Lower bits + + if ((io_cb)(io_cbdata, buffer + 2, 2) != 2) + return (EOF); + + lch = (buffer[2] << 8) | buffer[3]; + + if (lch < 0xdc00 || lch >= 0xdfff) + return (EOF); + + ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000; + } + break; + + case _MXML_ENCODING_UTF16LE : + // Read UTF-16 little-endian char... + if ((io_cb)(io_cbdata, buffer + 1, 1) != 1) + return (EOF); + + ch |= buffer[1] << 8; + + if (ch >= 0xd800 && ch <= 0xdbff) + { + // Multi-word UTF-16 char... + int lch; // Lower bits + + if ((io_cb)(io_cbdata, buffer + 2, 2) != 2) + return (EOF); + + lch = (buffer[3] << 8) | buffer[2]; + + if (lch < 0xdc00 || lch >= 0xdfff) + return (EOF); + + ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000; + } + break; + } + + if (mxml_bad_char(ch)) + { + _mxml_error(options, "Bad control character 0x%02x not allowed by XML standard.", ch); + return (EOF); + } + + return (ch); +} + + +// +// 'mxml_load_data()' - Load data into an XML node tree. +// + +static mxml_node_t * // O - First node or `NULL` if the XML could not be read. +mxml_load_data( + mxml_node_t *top, // I - Top node + mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Read callback function + void *io_cbdata) // I - Read callback data +{ + mxml_node_t *node = NULL, // Current node + *first = NULL, // First node added + *parent = NULL; // Current parent node + int line = 1, // Current line number + ch; // Character from file + bool whitespace = false; // Whitespace seen? + char *buffer, // String buffer + *bufptr; // Pointer into buffer + size_t bufsize; // Size of buffer + mxml_type_t type; // Current node type + _mxml_encoding_t encoding = _MXML_ENCODING_UTF8; + // Character encoding + static const char * const types[] = // Type strings... + { + "MXML_TYPE_CDATA", // CDATA + "MXML_TYPE_COMMENT", // Comment + "MXML_TYPE_DECLARATION",// Declaration + "MXML_TYPE_DIRECTIVE",// Processing instruction/directive + "MXML_TYPE_ELEMENT", // XML element with attributes + "MXML_TYPE_INTEGER", // Integer value + "MXML_TYPE_OPAQUE", // Opaque string + "MXML_TYPE_REAL", // Real value + "MXML_TYPE_TEXT", // Text fragment + "MXML_TYPE_CUSTOM" // Custom data + }; + + + // Read elements and other nodes from the file... + if ((buffer = malloc(64)) == NULL) + { + _mxml_error(options, "Unable to allocate string buffer."); + return (NULL); + } + + bufsize = 64; + bufptr = buffer; + parent = top; + first = NULL; + + if (options && options->type_cb && parent) + type = (options->type_cb)(options->type_cbdata, parent); + else if (options && !options->type_cb) + type = options->type_value; + else + type = MXML_TYPE_IGNORE; + + if ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) == EOF) + { + free(buffer); + return (NULL); + } + else if (ch != '<' && !top) + { + free(buffer); + _mxml_error(options, "XML does not start with '<' (saw '%c').", ch); + return (NULL); + } + + do + { + if ((ch == '<' || (mxml_isspace(ch) && type != MXML_TYPE_OPAQUE && type != MXML_TYPE_CUSTOM)) && bufptr > buffer) + { + // Add a new value node... + *bufptr = '\0'; + + switch (type) + { + case MXML_TYPE_INTEGER : + node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0)); + break; + + case MXML_TYPE_OPAQUE : + node = mxmlNewOpaque(parent, buffer); + break; + + case MXML_TYPE_REAL : + node = mxmlNewReal(parent, mxml_strtod(options, buffer, &bufptr)); + break; + + case MXML_TYPE_TEXT : + node = mxmlNewText(parent, whitespace, buffer); + break; + + case MXML_TYPE_CUSTOM : + if (options && options->custload_cb) + { + // Use the callback to fill in the custom data... + node = mxmlNewCustom(parent, /*data*/NULL, /*free_cb*/NULL, /*free_cbdata*/NULL); + + if (!(options->custload_cb)(options->cust_cbdata, node, buffer)) + { + _mxml_error(options, "Bad custom value '%s' in parent <%s> on line %d.", buffer, parent ? parent->value.element.name : "null", line); + mxmlDelete(node); + node = NULL; + } + break; + } + + default : // Ignore... + node = NULL; + break; + } + + if (*bufptr) + { + // Bad integer/real number value... + _mxml_error(options, "Bad %s value '%s' in parent <%s> on line %d.", type == MXML_TYPE_INTEGER ? "integer" : "real", buffer, parent ? parent->value.element.name : "null", line); + break; + } + + MXML_DEBUG("mxml_load_data: node=%p(%s), parent=%p\n", node, buffer, parent); + + bufptr = buffer; + whitespace = mxml_isspace(ch) && type == MXML_TYPE_TEXT; + + if (!node && type != MXML_TYPE_IGNORE) + { + // Print error and return... + _mxml_error(options, "Unable to add value node of type %s to parent <%s> on line %d.", types[type], parent ? parent->value.element.name : "null", line); + goto error; + } + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_DATA)) + goto error; + + if (!mxmlRelease(node)) + node = NULL; + } + + if (!first && node) + first = node; + } + else if (mxml_isspace(ch) && type == MXML_TYPE_TEXT) + { + whitespace = true; + } + + if (ch == '\n') + line ++; + + // Add lone whitespace node if we have an element and existing whitespace... + if (ch == '<' && whitespace && type == MXML_TYPE_TEXT) + { + if (parent) + { + node = mxmlNewText(parent, whitespace, ""); + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_DATA)) + goto error; + + if (!mxmlRelease(node)) + node = NULL; + } + + if (!first && node) + first = node; + } + + whitespace = false; + } + + if (ch == '<') + { + // Start of open/close tag... + bufptr = buffer; + + while ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) != EOF) + { + if (mxml_isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer)) + { + break; + } + else if (ch == '<') + { + _mxml_error(options, "Bare < in element."); + goto error; + } + else if (ch == '&') + { + if ((ch = mxml_get_entity(options, io_cb, io_cbdata, &encoding, parent, &line)) == EOF) + goto error; + + if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + goto error; + } + else if (ch < '0' && ch != '!' && ch != '-' && ch != '.' && ch != '/') + { + goto error; + } + else if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + { + goto error; + } + else if (((bufptr - buffer) == 1 && buffer[0] == '?') || ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3)) || ((bufptr - buffer) == 8 && !strncmp(buffer, "![CDATA[", 8))) + { + break; + } + + if (ch == '\n') + line ++; + } + + *bufptr = '\0'; + + if (!strcmp(buffer, "!--")) + { + // Gather rest of comment... + while ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) != EOF) + { + if (ch == '>' && bufptr > (buffer + 4) && bufptr[-3] != '-' && bufptr[-2] == '-' && bufptr[-1] == '-') + break; + else if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + goto error; + + if (ch == '\n') + line ++; + } + + // Error out if we didn't get the whole comment... + if (ch != '>') + { + // Print error and return... + _mxml_error(options, "Early EOF in comment node on line %d.", line); + goto error; + } + + // Otherwise add this as an element under the current parent... + bufptr[-2] = '\0'; + + if (!parent && first) + { + // There can only be one root element! + _mxml_error(options, "<%s--> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line); + goto error; + } + + if ((node = mxmlNewComment(parent, buffer + 3)) == NULL) + { + // Just print error for now... + _mxml_error(options, "Unable to add comment node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line); + break; + } + + MXML_DEBUG("mxml_load_data: node=%p(<%s-->), parent=%p\n", node, buffer, parent); + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_COMMENT)) + goto error; + + if (!mxmlRelease(node)) + node = NULL; + } + + if (node && !first) + first = node; + } + else if (!strcmp(buffer, "![CDATA[")) + { + // Gather CDATA section... + while ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) != EOF) + { + if (ch == '>' && !strncmp(bufptr - 2, "]]", 2)) + { + // Drop terminator from CDATA string... + bufptr[-2] = '\0'; + break; + } + else if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + { + goto error; + } + + if (ch == '\n') + line ++; + } + + // Error out if we didn't get the whole comment... + if (ch != '>') + { + // Print error and return... + _mxml_error(options, "Early EOF in CDATA node on line %d.", line); + goto error; + } + + // Otherwise add this as an element under the current parent... + bufptr[-2] = '\0'; + + if (!parent && first) + { + // There can only be one root element! + _mxml_error(options, "<%s]]> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line); + goto error; + } + + if ((node = mxmlNewCDATA(parent, buffer + 8)) == NULL) + { + // Print error and return... + _mxml_error(options, "Unable to add CDATA node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line); + goto error; + } + + MXML_DEBUG("mxml_load_data: node=%p(<%s]]>), parent=%p\n", node, buffer, parent); + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_CDATA)) + goto error; + + if (!mxmlRelease(node)) + node = NULL; + } + + if (node && !first) + first = node; + } + else if (buffer[0] == '?') + { + // Gather rest of processing instruction... + while ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) != EOF) + { + if (ch == '>' && bufptr > buffer && bufptr[-1] == '?') + break; + else if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + goto error; + + if (ch == '\n') + line ++; + } + + // Error out if we didn't get the whole processing instruction... + if (ch != '>') + { + // Print error and return... + _mxml_error(options, "Early EOF in processing instruction node on line %d.", line); + goto error; + } + + // Otherwise add this as an element under the current parent... + bufptr[-1] = '\0'; + + if (!parent && first) + { + // There can only be one root element! + _mxml_error(options, "<%s?> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line); + goto error; + } + + if ((node = mxmlNewDirective(parent, buffer + 1)) == NULL) + { + // Print error and return... + _mxml_error(options, "Unable to add processing instruction node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line); + goto error; + } + + MXML_DEBUG("mxml_load_data: node=%p(<%s?>), parent=%p\n", node, buffer, parent); + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_DIRECTIVE)) + goto error; + + if (strncmp(node->value.directive, "xml ", 4) && !mxmlRelease(node)) + node = NULL; + } + + if (node) + { + if (!first) + first = node; + + if (!parent) + { + parent = node; + + if (options && options->type_cb) + type = (options->type_cb)(options->type_cbdata, parent); + else if (options) + type = options->type_value; + else + type = MXML_TYPE_TEXT; + } + } + } + else if (buffer[0] == '!') + { + // Gather rest of declaration... + do + { + if (ch == '>') + { + break; + } + else + { + if (ch == '&') + { + if ((ch = mxml_get_entity(options, io_cb, io_cbdata, &encoding, parent, &line)) == EOF) + goto error; + } + + if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + goto error; + } + + if (ch == '\n') + line ++; + } + while ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) != EOF); + + // Error out if we didn't get the whole declaration... + if (ch != '>') + { + // Print error and return... + _mxml_error(options, "Early EOF in declaration node on line %d.", line); + goto error; + } + + // Otherwise add this as an element under the current parent... + *bufptr = '\0'; + + if (!parent && first) + { + // There can only be one root element! + _mxml_error(options, "<%s> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line); + goto error; + } + + if ((node = mxmlNewDeclaration(parent, buffer + 1)) == NULL) + { + // Print error and return... + _mxml_error(options, "Unable to add declaration node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line); + goto error; + } + + MXML_DEBUG("mxml_load_data: node=%p(<%s>), parent=%p\n", node, buffer, parent); + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_DECLARATION)) + goto error; + + if (!mxmlRelease(node)) + node = NULL; + } + + if (node) + { + if (!first) + first = node; + + if (!parent) + { + parent = node; + + if (options && options->type_cb) + type = (options->type_cb)(options->type_cbdata, parent); + else if (options) + type = options->type_value; + else + type = MXML_TYPE_TEXT; + } + } + } + else if (buffer[0] == '/') + { + // Handle close tag... + MXML_DEBUG("mxml_load_data: <%s>, parent=%p\n", buffer, parent); + + if (!parent || strcmp(buffer + 1, parent->value.element.name)) + { + // Close tag doesn't match tree; print an error for now... + _mxml_error(options, "Mismatched close tag <%s> under parent <%s> on line %d.", buffer, parent ? parent->value.element.name : "(null)", line); + goto error; + } + + // Keep reading until we see >... + while (ch != '>' && ch != EOF) + ch = mxml_getc(options, io_cb, io_cbdata, &encoding); + + node = parent; + parent = parent->parent; + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_ELEMENT_CLOSE)) + goto error; + + if (!mxmlRelease(node)) + { + if (first == node) + first = NULL; + + node = NULL; + } + } + + // Ascend into the parent and set the value type as needed... + if (options && options->type_cb && parent) + type = (options->type_cb)(options->type_cbdata, parent); + else if (options && !options->type_cb) + type = options->type_value; + } + else + { + // Handle open tag... + if (!parent && first) + { + // There can only be one root element! + _mxml_error(options, "<%s> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line); + goto error; + } + + if ((node = mxmlNewElement(parent, buffer)) == NULL) + { + // Just print error for now... + _mxml_error(options, "Unable to add element node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line); + goto error; + } + + if (mxml_isspace(ch)) + { + MXML_DEBUG("mxml_load_data: node=%p(<%s...>), parent=%p\n", node, buffer, parent); + + if ((ch = mxml_parse_element(options, io_cb, io_cbdata, node, &encoding, &line)) == EOF) + goto error; + } + else if (ch == '/') + { + MXML_DEBUG("mxml_load_data: node=%p(<%s/>), parent=%p\n", node, buffer, parent); + + if ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) != '>') + { + _mxml_error(options, "Expected > but got '%c' instead for element <%s/> on line %d.", ch, buffer, line); + mxmlDelete(node); + node = NULL; + goto error; + } + + ch = '/'; + } + + if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_ELEMENT_OPEN)) + goto error; + } + + if (!first) + first = node; + + if (ch == EOF) + break; + + if (ch != '/') + { + // Descend into this node, setting the value type as needed... + parent = node; + + if (options && options->type_cb && parent) + type = (options->type_cb)(options->type_cbdata, parent); + else if (options && !options->type_cb) + type = options->type_value; + else + type = MXML_TYPE_TEXT; + } + else if (options && options->sax_cb) + { + if (!(options->sax_cb)(options->sax_cbdata, node, MXML_SAX_EVENT_ELEMENT_CLOSE)) + goto error; + + if (!mxmlRelease(node)) + { + if (first == node) + first = NULL; + + node = NULL; + } + } + } + + bufptr = buffer; + } + else if (ch == '&') + { + // Add character entity to current buffer... + if ((ch = mxml_get_entity(options, io_cb, io_cbdata, &encoding, parent, &line)) == EOF) + goto error; + + if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + goto error; + } + else if (type == MXML_TYPE_OPAQUE || type == MXML_TYPE_CUSTOM || !mxml_isspace(ch)) + { + // Add character to current buffer... + if (!mxml_add_char(options, ch, &bufptr, &buffer, &bufsize)) + goto error; + } + } + while ((ch = mxml_getc(options, io_cb, io_cbdata, &encoding)) != EOF); + + // Free the string buffer - we don't need it anymore... + free(buffer); + + // Find the top element and return it... + if (parent) + { + node = parent; + + while (parent != top && parent->parent) + parent = parent->parent; + + if (node != parent) + { + _mxml_error(options, "Missing close tag under parent <%s> on line %d.", mxmlGetElement(node), node->parent ? node->parent->value.element.name : "(null)", line); + + mxmlDelete(first); + + return (NULL); + } + } + + if (parent) + return (parent); + else + return (first); + + // Common error return... + error: + + mxmlDelete(first); + + free(buffer); + + return (NULL); +} + + +// +// 'mxml_parse_element()' - Parse an element for any attributes... +// + +static int // O - Terminating character +mxml_parse_element( + mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Read callback function + void *io_cbdata, // I - Read callback data + mxml_node_t *node, // I - Element node + _mxml_encoding_t *encoding, // IO - Encoding + int *line) // IO - Current line number +{ + int ch, // Current character in file + quote; // Quoting character + char *name, // Attribute name + *value, // Attribute value + *ptr; // Pointer into name/value + size_t namesize, // Size of name string + valsize; // Size of value string + + + // Initialize the name and value buffers... + if ((name = malloc(64)) == NULL) + { + _mxml_error(options, "Unable to allocate memory for name."); + return (EOF); + } + + namesize = 64; + + if ((value = malloc(64)) == NULL) + { + free(name); + _mxml_error(options, "Unable to allocate memory for value."); + return (EOF); + } + + valsize = 64; + + // Loop until we hit a >, /, ?, or EOF... + while ((ch = mxml_getc(options, io_cb, io_cbdata, encoding)) != EOF) + { + MXML_DEBUG("mxml_parse_element: ch='%c'\n", ch); + + // Skip leading whitespace... + if (mxml_isspace(ch)) + { + if (ch == '\n') + (*line)++; + + continue; + } + + // Stop at /, ?, or >... + if (ch == '/' || ch == '?') + { + // Grab the > character and print an error if it isn't there... + quote = mxml_getc(options, io_cb, io_cbdata, encoding); + + if (quote != '>') + { + _mxml_error(options, "Expected '>' after '%c' for element %s, but got '%c' on line %d.", ch, mxmlGetElement(node), quote, *line); + goto error; + } + + break; + } + else if (ch == '<') + { + _mxml_error(options, "Bare < in element %s on line %d.", mxmlGetElement(node), *line); + goto error; + } + else if (ch == '>') + { + break; + } + + // Read the attribute name... + ptr = name; + if (!mxml_add_char(options, ch, &ptr, &name, &namesize)) + goto error; + + if (ch == '\"' || ch == '\'') + { + // Name is in quotes, so get a quoted string... + quote = ch; + + while ((ch = mxml_getc(options, io_cb, io_cbdata, encoding)) != EOF) + { + if (ch == '&') + { + if ((ch = mxml_get_entity(options, io_cb, io_cbdata, encoding, node, line)) == EOF) + goto error; + } + else if (ch == '\n') + { + (*line)++; + } + + if (!mxml_add_char(options, ch, &ptr, &name, &namesize)) + goto error; + + if (ch == quote) + break; + } + } + else + { + // Grab an normal, non-quoted name... + while ((ch = mxml_getc(options, io_cb, io_cbdata, encoding)) != EOF) + { + if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?') + { + if (ch == '\n') + (*line)++; + break; + } + else + { + if (ch == '&') + { + if ((ch = mxml_get_entity(options, io_cb, io_cbdata, encoding, node, line)) == EOF) + goto error; + } + + if (!mxml_add_char(options, ch, &ptr, &name, &namesize)) + goto error; + } + } + } + + *ptr = '\0'; + + if (mxmlElementGetAttr(node, name)) + { + _mxml_error(options, "Duplicate attribute '%s' in element %s on line %d.", name, mxmlGetElement(node), *line); + goto error; + } + + while (ch != EOF && mxml_isspace(ch)) + { + ch = mxml_getc(options, io_cb, io_cbdata, encoding); + + if (ch == '\n') + (*line)++; + } + + if (ch == '=') + { + // Read the attribute value... + while ((ch = mxml_getc(options, io_cb, io_cbdata, encoding)) != EOF && mxml_isspace(ch)) + { + if (ch == '\n') + (*line)++; + } + + if (ch == EOF) + { + _mxml_error(options, "Missing value for attribute '%s' in element %s on line %d.", name, mxmlGetElement(node), *line); + goto error; + } + + if (ch == '\'' || ch == '\"') + { + // Read quoted value... + quote = ch; + ptr = value; + + while ((ch = mxml_getc(options, io_cb, io_cbdata, encoding)) != EOF) + { + if (ch == quote) + { + break; + } + else + { + if (ch == '&') + { + if ((ch = mxml_get_entity(options, io_cb, io_cbdata, encoding, node, line)) == EOF) + goto error; + } + else if (ch == '\n') + { + (*line)++; + } + + if (!mxml_add_char(options, ch, &ptr, &value, &valsize)) + goto error; + } + } + + *ptr = '\0'; + } + else + { + // Read unquoted value... + ptr = value; + if (!mxml_add_char(options, ch, &ptr, &value, &valsize)) + goto error; + + while ((ch = mxml_getc(options, io_cb, io_cbdata, encoding)) != EOF) + { + if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>') + { + if (ch == '\n') + (*line)++; + + break; + } + else + { + if (ch == '&') + { + if ((ch = mxml_get_entity(options, io_cb, io_cbdata, encoding, node, line)) == EOF) + goto error; + } + + if (!mxml_add_char(options, ch, &ptr, &value, &valsize)) + goto error; + } + } + + *ptr = '\0'; + } + + // Set the attribute with the given string value... + mxmlElementSetAttr(node, name, value); + MXML_DEBUG("mxml_parse_element: %s=\"%s\"\n", name, value); + } + else + { + _mxml_error(options, "Missing value for attribute '%s' in element %s on line %d.", name, mxmlGetElement(node), *line); + goto error; + } + + // Check the end character... + if (ch == '/' || ch == '?') + { + // Grab the > character and print an error if it isn't there... + quote = mxml_getc(options, io_cb, io_cbdata, encoding); + + if (quote != '>') + { + _mxml_error(options, "Expected '>' after '%c' for element %s, but got '%c' on line %d.", ch, mxmlGetElement(node), quote, *line); + ch = EOF; + } + + break; + } + else if (ch == '>') + break; + } + + // Free the name and value buffers and return... + free(name); + free(value); + + return (ch); + + // Common error return point... + error: + + free(name); + free(value); + + return (EOF); +} + + +// +// 'mxml_read_cb_fd()' - Read bytes from a file descriptor. +// + +// static size_t // O - Bytes read +// mxml_read_cb_fd(int *fd, // I - File descriptor +// void *buffer, // I - Buffer +// size_t bytes) // I - Bytes to read +// { +// #if _WIN32 +// int rbytes; // Bytes read + + +// rbytes = read(*fd, buffer, bytes); + +// #else +// ssize_t rbytes; // Bytes read + + +// while ((rbytes = read(*fd, buffer, bytes)) < 0) +// { +// if (errno != EINTR && errno != EAGAIN) +// break; +// } +// #endif // _WIN32 + +// if (rbytes < 0) +// return (0); +// else +// return ((size_t)rbytes); +// } + + +// +// 'mxml_read_cb_file()' - Read bytes from a file pointer. +// + +static size_t // O - Bytes read +mxml_read_cb_file(FILE *fp, // I - File pointer + void *buffer, // I - Buffer + size_t bytes) // I - Bytes to read +{ + if (feof(fp)) + return (0); + else + return (fread(buffer, 1, bytes, fp)); +} + + +// +// 'mxml_read_cb_string()' - Read bytes from a string. +// + +static size_t // O - Bytes read +mxml_read_cb_string( + _mxml_stringbuf_t *sb, // I - String buffer + void *buffer, // I - Buffer + size_t bytes) // I - Bytes to read +{ + size_t remaining; // Remaining bytes in buffer + + + if ((remaining = sb->bufsize - (size_t)(sb->bufptr - sb->buffer)) < bytes) + bytes = remaining; + + if (bytes > 0) + { + // Copy bytes from string... + memcpy(buffer, sb->bufptr, bytes); + sb->bufptr += bytes; + } + + return (bytes); +} + + +// +// 'mxml_strtod()' - Convert a string to a double without respect to the locale. +// + +static double // O - Real number +mxml_strtod(mxml_options_t *options, // I - Options + const char *buffer, // I - String + char **bufend) // O - End of number in string +{ + const char *bufptr; // Pointer into buffer + char temp[64], // Temporary buffer + *tempptr; // Pointer into temporary buffer + + + // See if the locale has a special decimal point string... + if (!options || !options->loc) + return (strtod(buffer, bufend)); + + // Copy leading sign, numbers, period, and then numbers... + tempptr = temp; + temp[sizeof(temp) - 1] = '\0'; + bufptr = buffer; + + if (*bufptr == '-' || *bufptr == '+') + *tempptr++ = *bufptr++; + + while (*bufptr && isdigit(*bufptr & 255)) + { + if (tempptr < (temp + sizeof(temp) - 1)) + { + *tempptr++ = *bufptr++; + } + else + { + *bufend = (char *)bufptr; + return (0.0); + } + } + + if (*bufptr == '.') + { + // Convert decimal point to locale equivalent... + size_t declen = strlen(options->loc->decimal_point); + // Length of decimal point + bufptr ++; + + if (declen <= (sizeof(temp) - (size_t)(tempptr - temp))) + { + memcpy(tempptr, options->loc->decimal_point, declen); + tempptr += declen; + } + else + { + *bufend = (char *)bufptr; + return (0.0); + } + } + + // Copy any remaining characters... + while (*bufptr && isdigit(*bufptr & 255)) + { + if (tempptr < (temp + sizeof(temp) - 1)) + *tempptr++ = *bufptr++; + else + break; + } + + *bufend = (char *)bufptr; + + if (*bufptr) + return (0.0); + + // Nul-terminate the temporary string and convert the string... + *tempptr = '\0'; + + return (strtod(temp, NULL)); +} + + +// +// 'mxml_io_cb_fd()' - Write bytes to a file descriptor. +// + +// static size_t // O - Bytes written +// mxml_io_cb_fd(int *fd, // I - File descriptor +// void *buffer, // I - Buffer +// size_t bytes) // I - Bytes to write +// { +// #if _WIN32 +// int wbytes; // Bytes written + + +// wbytes = write(*fd, buffer, bytes); + +// #else +// ssize_t wbytes; // Bytes written + + +// while ((wbytes = write(*fd, buffer, bytes)) < 0) +// { +// if (errno != EINTR && errno != EAGAIN) +// break; +// } +// #endif // _WIN32 + +// if (wbytes < 0) +// return (0); +// else +// return ((size_t)wbytes); +// } + + +// +// 'mxml_io_cb_file()' - Write bytes to a file pointer. +// + +static size_t // O - Bytes written +mxml_io_cb_file(FILE *fp, // I - File pointer + void *buffer, // I - Buffer + size_t bytes) // I - Bytes to write +{ + return (fwrite(buffer, 1, bytes, fp)); +} + + +// +// 'mxml_io_cb_string()' - Write bytes to a string buffer. +// + +static size_t // O - Bytes written +mxml_io_cb_string( + _mxml_stringbuf_t *sb, // I - String buffer + void *buffer, // I - Buffer + size_t bytes) // I - Bytes to write +{ + size_t remaining; // Remaining bytes + + + // Expand buffer as needed... + if ((sb->bufptr + bytes) >= (sb->buffer + sb->bufsize - 1) && sb->bufalloc) + { + // Reallocate buffer + char *temp; // New buffer pointer + size_t newsize; // New bufsize + + newsize = (size_t)(sb->bufptr - sb->buffer) + bytes + 257; + if ((temp = realloc(sb->buffer, newsize)) == NULL) + return (0); + + sb->bufptr = temp + (sb->bufptr - sb->buffer); + sb->buffer = temp; + sb->bufsize = newsize; + } + + // Copy what we can... + if (sb->bufptr >= (sb->buffer + sb->bufsize - 1)) + return (0); // No more room + else if ((remaining = (sb->bufsize - (size_t)(sb->bufptr - sb->buffer) - 1)) < bytes) + bytes = remaining; + + memcpy(sb->bufptr, buffer, bytes); + sb->bufptr += bytes; + + return (bytes); +} + + +// +// 'mxml_write_node()' - Save an XML node to a file. +// + +static int // O - Column or -1 on error +mxml_write_node( + mxml_node_t *node, // I - Node to write + mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Write callback function + void *io_cbdata, // I - Write callback data + int col) // I - Current column +{ + mxml_node_t *current, // Current node + *next; // Next node + size_t i, // Looping var + width; // Width of attr + value + _mxml_attr_t *attr; // Current attribute + char s[255], // Temporary string + *data; // Custom data string + const char *text; // Text string + bool whitespace; // Whitespace before text string? + + + // Loop through this node and all of its children... + for (current = node; current && col >= 0; current = next) + { + // Print the node value... + MXML_DEBUG("mxml_write_node: current=%p(%d)\n", current, current->type); + + switch (mxmlGetType(current)) + { + case MXML_TYPE_CDATA : + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_BEFORE_OPEN, col); + col = mxml_write_string("", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_AFTER_OPEN, col); + break; + + case MXML_TYPE_COMMENT : + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_BEFORE_OPEN, col); + col = mxml_write_string("", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_AFTER_OPEN, col); + break; + + case MXML_TYPE_DECLARATION : + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_BEFORE_OPEN, col); + col = mxml_write_string("", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_AFTER_OPEN, col); + break; + + case MXML_TYPE_DIRECTIVE : + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_BEFORE_OPEN, col); + col = mxml_write_string("", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_AFTER_OPEN, col); + break; + + case MXML_TYPE_ELEMENT : + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_BEFORE_OPEN, col); + col = mxml_write_string("<", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_string(mxmlGetElement(current), io_cb, io_cbdata, /*use_entities*/true, col); + + for (i = current->value.element.num_attrs, attr = current->value.element.attrs; i > 0 && col >= 0; i --, attr ++) + { + width = strlen(attr->name); + + if (attr->value) + width += strlen(attr->value) + 3; + + if (options && options->wrap > 0 && (col + (int)width) > options->wrap) + col = mxml_write_string("\n", io_cb, io_cbdata, /*use_entities*/false, col); + else + col = mxml_write_string(" ", io_cb, io_cbdata, /*use_entities*/false, col); + + col = mxml_write_string(attr->name, io_cb, io_cbdata, /*use_entities*/true, col); + + if (attr->value) + { + col = mxml_write_string("=\"", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_string(attr->value, io_cb, io_cbdata, /*use_entities*/true, col); + col = mxml_write_string("\"", io_cb, io_cbdata, /*use_entities*/false, col); + } + } + + col = mxml_write_string(current->child ? ">" : "/>", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_AFTER_OPEN, col); + break; + + case MXML_TYPE_INTEGER : + if (current->prev) + { + // Add whitespace separator... + if (options && options->wrap > 0 && col > options->wrap) + col = mxml_write_string("\n", io_cb, io_cbdata, /*use_entities*/false, col); + else + col = mxml_write_string(" ", io_cb, io_cbdata, /*use_entities*/false, col); + } + + // Write integer... + snprintf(s, sizeof(s), "%ld", current->value.integer); + col = mxml_write_string(s, io_cb, io_cbdata, /*use_entities*/true, col); + break; + + case MXML_TYPE_OPAQUE : + col = mxml_write_string(mxmlGetOpaque(current), io_cb, io_cbdata, /*use_entities*/true, col); + break; + + case MXML_TYPE_REAL : + if (current->prev) + { + // Add whitespace separator... + if (options && options->wrap > 0 && col > options->wrap) + col = mxml_write_string("\n", io_cb, io_cbdata, /*use_entities*/false, col); + else + col = mxml_write_string(" ", io_cb, io_cbdata, /*use_entities*/false, col); + } + + // Write real number... + snprintf(s, sizeof(s), "%g", current->value.real); + + if (options && options->loc) + { + char *sptr; // Pointer into string + + if ((sptr = strstr(s, options->loc->decimal_point)) != NULL) + { + // Convert locale decimal point to "." + if (options->loc_declen > 1) + memmove(sptr + 1, sptr + options->loc_declen, strlen(sptr + options->loc_declen) + 1); + + *sptr = '.'; + } + } + + col = mxml_write_string(s, io_cb, io_cbdata, /*use_entities*/true, col); + break; + + case MXML_TYPE_TEXT : + text = mxmlGetText(current, &whitespace); + + if (whitespace && col > 0) + { + // Add whitespace separator... + if (options && options->wrap > 0 && col > options->wrap) + col = mxml_write_string("\n", io_cb, io_cbdata, /*use_entities*/false, col); + else + col = mxml_write_string(" ", io_cb, io_cbdata, /*use_entities*/false, col); + } + + col = mxml_write_string(text, io_cb, io_cbdata, /*use_entities*/true, col); + break; + + case MXML_TYPE_CUSTOM : + if (!options || !options->custsave_cb) + return (-1); + + if ((data = (options->custsave_cb)(options->cust_cbdata, current)) == NULL) + return (-1); + + col = mxml_write_string(data, io_cb, io_cbdata, /*use_entities*/true, col); + + free(data); + break; + + default : // Should never happen + return (-1); + } + + // Figure out the next node... + if ((next = mxmlGetFirstChild(current)) == NULL) + { + if (current == node) + { + // Don't traverse to sibling node if we are at the "root" node... + next = NULL; + } + else + { + // Try the next sibling, and continue traversing upwards as needed... + while ((next = mxmlGetNextSibling(current)) == NULL) + { + if (current == node || !mxmlGetParent(current)) + break; + + // Declarations and directives have no end tags... + current = mxmlGetParent(current); + + if (mxmlGetType(current) == MXML_TYPE_ELEMENT) + { + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_BEFORE_CLOSE, col); + col = mxml_write_string("", io_cb, io_cbdata, /*use_entities*/false, col); + col = mxml_write_ws(current, options, io_cb, io_cbdata, MXML_WS_AFTER_CLOSE, col); + } + + if (current == node) + break; + } + } + } + } + + return (col); +} + + +// +// 'mxml_write_string()' - Write a string, escaping & and < as needed. +// + +static int // O - New column or `-1` on error +mxml_write_string( + const char *s, // I - String to write + mxml_io_cb_t io_cb, // I - Write callback function + void *io_cbdata, // I - Write callback data + bool use_entities, // I - Escape special characters? + int col) // I - Current column +{ + const char *frag, // Start of current string fragment + *ptr, // Pointer into string + *ent; // Entity, if any + size_t fraglen; // Length of fragment + + + MXML_DEBUG("mxml_write_string(io_cb=%p, io_cbdata=%p, s=\"%s\", use_entities=%s, col=%d)\n", io_cb, io_cbdata, s, use_entities ? "true" : "false", col); + + if (col < 0) + return (-1); + + for (frag = ptr = s; *ptr; ptr ++) + { + if (use_entities && (ent = _mxml_entity_string(*ptr)) != NULL) + { + size_t entlen = strlen(ent); // Length of entity + + if (ptr > frag) + { + // Write current fragment + fraglen = (size_t)(ptr - frag); + + if ((io_cb)(io_cbdata, (char *)frag, fraglen) != fraglen) + return (-1); + } + + frag = ptr + 1; + + // Write entity + if ((io_cb)(io_cbdata, (char *)ent, entlen) != entlen) + return (-1); + + col ++; + } + else if (*ptr == '\r' || *ptr == '\n') + { + // CR or LF resets column + col = 0; + } + else if (*ptr == '\t') + { + // Tab indents column + col = col - (col % MXML_TAB) + MXML_TAB; + } + else + { + // All other characters are 1 column wide + col ++; + } + } + + if (ptr > frag) + { + // Write final fragment + fraglen = (size_t)(ptr - frag); + + if ((io_cb)(io_cbdata, (char *)frag, fraglen) != fraglen) + return (-1); + } + + return (col); +} + + +// +// 'mxml_write_ws()' - Do whitespace callback... +// + +static int // O - New column or `-1` on error +mxml_write_ws( + mxml_node_t *node, // I - Current node + mxml_options_t *options, // I - Options + mxml_io_cb_t io_cb, // I - Write callback function + void *io_cbdata, // I - Write callback data + mxml_ws_t ws, // I - Whitespace value + int col) // I - Current column +{ + const char *s; // Whitespace string + + + if (options && options->ws_cb && (s = (options->ws_cb)(options->ws_cbdata, node, ws)) != NULL) + col = mxml_write_string(s, io_cb, io_cbdata, /*use_entities*/false, col); + + return (col); +} diff --git a/src/main/mxml/mxml-get.c b/src/main/mxml/mxml-get.c new file mode 100644 index 00000000..384bc8df --- /dev/null +++ b/src/main/mxml/mxml-get.c @@ -0,0 +1,364 @@ +// +// Node get functions for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2014-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// 'mxmlGetCDATA()' - Get the value for a CDATA node. +// +// This function gets the string value of a CDATA node. `NULL` is returned if +// the node is not a CDATA element. +// + +const char * // O - CDATA value or `NULL` +mxmlGetCDATA(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node || node->type != MXML_TYPE_CDATA) + return (NULL); + + // Return the CDATA string... + return (node->value.cdata); +} + + +// +// 'mxmlGetComment()' - Get the value for a comment node. +// +// This function gets the string value of a comment node. `NULL` is returned +// if the node is not a comment. +// + +const char * // O - Comment value or `NULL` +mxmlGetComment(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node || node->type != MXML_TYPE_COMMENT) + return (NULL); + + // Return the comment string... + return (node->value.comment); +} + + +// +// 'mxmlGetCustom()' - Get the value for a custom node. +// +// This function gets the binary value of a custom node. `NULL` is returned if +// the node (or its first child) is not a custom value node. +// + +const void * // O - Custom value or `NULL` +mxmlGetCustom(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node) + return (NULL); + + // Return the custom value... + if (node->type == MXML_TYPE_CUSTOM) + return (node->value.custom.data); + else if (node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CUSTOM) + return (node->child->value.custom.data); + else + return (NULL); +} + + +// +// 'mxmlGetDeclaration()' - Get the value for a declaration node. +// +// This function gets the string value of a declaraction node. `NULL` is +// returned if the node is not a declaration. +// + +const char * // O - Declaraction value or `NULL` +mxmlGetDeclaration(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node || node->type != MXML_TYPE_DECLARATION) + return (NULL); + + // Return the comment string... + return (node->value.declaration); +} + + +// +// 'mxmlGetDirective()' - Get the value for a processing instruction node. +// +// This function gets the string value of a processing instruction. `NULL` is +// returned if the node is not a processing instruction. +// + +const char * // O - Comment value or `NULL` +mxmlGetDirective(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node || node->type != MXML_TYPE_DIRECTIVE) + return (NULL); + + // Return the comment string... + return (node->value.directive); +} + + +// +// 'mxmlGetElement()' - Get the name for an element node. +// +// This function gets the name of an element node. `NULL` is returned if the +// node is not an element node. +// + +const char * // O - Element name or `NULL` +mxmlGetElement(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node || node->type != MXML_TYPE_ELEMENT) + return (NULL); + + // Return the element name... + return (node->value.element.name); +} + + +// +// 'mxmlGetFirstChild()' - Get the first child of a node. +// +// This function gets the first child of a node. `NULL` is returned if the node +// has no children. +// + +mxml_node_t * // O - First child or `NULL` +mxmlGetFirstChild(mxml_node_t *node) // I - Node to get +{ + // Return the first child node... + return (node ? node->child : NULL); +} + + +// +// 'mxmlGetInteger()' - Get the integer value from the specified node or its +// first child. +// +// This function gets the value of an integer node. `0` is returned if the node +// (or its first child) is not an integer value node. +// + +long // O - Integer value or `0` +mxmlGetInteger(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node) + return (0); + + // Return the integer value... + if (node->type == MXML_TYPE_INTEGER) + return (node->value.integer); + else if (node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_INTEGER) + return (node->child->value.integer); + else + return (0); +} + + +// +// 'mxmlGetLastChild()' - Get the last child of a node. +// +// This function gets the last child of a node. `NULL` is returned if the node +// has no children. +// + +mxml_node_t * // O - Last child or `NULL` +mxmlGetLastChild(mxml_node_t *node) // I - Node to get +{ + return (node ? node->last_child : NULL); +} + + +// +// 'mxmlGetNextSibling()' - Get the next node for the current parent. +// +// This function gets the next node for the current parent. `NULL` is returned +// if this is the last child for the current parent. +// + +mxml_node_t * +mxmlGetNextSibling(mxml_node_t *node) // I - Node to get +{ + return (node ? node->next : NULL); +} + + +// +// 'mxmlGetOpaque()' - Get an opaque string value for a node or its first child. +// +// This function gets the string value of an opaque node. `NULL` is returned if +// the node (or its first child) is not an opaque value node. +// + +const char * // O - Opaque string or `NULL` +mxmlGetOpaque(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node) + return (NULL); + + // Return the opaque value... + if (node->type == MXML_TYPE_OPAQUE) + return (node->value.opaque); + else if (node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_OPAQUE) + return (node->child->value.opaque); + else + return (NULL); +} + + +// +// 'mxmlGetParent()' - Get the parent node. +// +// This function gets the parent of a node. `NULL` is returned for a root node. +// + +mxml_node_t * // O - Parent node or `NULL` +mxmlGetParent(mxml_node_t *node) // I - Node to get +{ + return (node ? node->parent : NULL); +} + + +// +// 'mxmlGetPrevSibling()' - Get the previous node for the current parent. +// +// This function gets the previous node for the current parent. `NULL` is +// returned if this is the first child for the current parent. +// + +mxml_node_t * // O - Previous node or `NULL` +mxmlGetPrevSibling(mxml_node_t *node) // I - Node to get +{ + return (node ? node->prev : NULL); +} + + +// +// 'mxmlGetReal()' - Get the real value for a node or its first child. +// +// This function gets the value of a real value node. `0.0` is returned if the +// node (or its first child) is not a real value node. +// + +double // O - Real value or 0.0 +mxmlGetReal(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node) + return (0.0); + + // Return the real value... + if (node->type == MXML_TYPE_REAL) + return (node->value.real); + else if (node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_REAL) + return (node->child->value.real); + else + return (0.0); +} + + +// +// 'mxmlGetText()' - Get the text value for a node or its first child. +// +// This function gets the string and whitespace values of a text node. `NULL` +// and `false` are returned if the node (or its first child) is not a text node. +// The `whitespace` argument can be `NULL` if you don't want to know the +// whitespace value. +// +// Note: Text nodes consist of whitespace-delimited words. You will only get +// single words of text when reading an XML file with `MXML_TYPE_TEXT` nodes. +// If you want the entire string between elements in the XML file, you MUST read +// the XML file with `MXML_TYPE_OPAQUE` nodes and get the resulting strings +// using the @link mxmlGetOpaque@ function instead. +// + +const char * // O - Text string or `NULL` +mxmlGetText(mxml_node_t *node, // I - Node to get + bool *whitespace) // O - `true` if string is preceded by whitespace, `false` otherwise +{ + // Range check input... + if (!node) + { + if (whitespace) + *whitespace = false; + + return (NULL); + } + + // Return the integer value... + if (node->type == MXML_TYPE_TEXT) + { + if (whitespace) + *whitespace = node->value.text.whitespace; + + return (node->value.text.string); + } + else if (node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_TEXT) + { + if (whitespace) + *whitespace = node->child->value.text.whitespace; + + return (node->child->value.text.string); + } + else + { + if (whitespace) + *whitespace = false; + + return (NULL); + } +} + + +// +// 'mxmlGetType()' - Get the node type. +// +// This function gets the type of `node`. `MXML_TYPE_IGNORE` is returned if +// `node` is `NULL`. +// + +mxml_type_t // O - Type of node +mxmlGetType(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node) + return (MXML_TYPE_IGNORE); + + // Return the node type... + return (node->type); +} + + +// +// 'mxmlGetUserData()' - Get the user data pointer for a node. +// +// This function gets the user data pointer associated with `node`. +// + +void * // O - User data pointer +mxmlGetUserData(mxml_node_t *node) // I - Node to get +{ + // Range check input... + if (!node) + return (NULL); + + // Return the user data pointer... + return (node->user_data); +} diff --git a/src/main/mxml/mxml-index.c b/src/main/mxml/mxml-index.c new file mode 100644 index 00000000..9da244b3 --- /dev/null +++ b/src/main/mxml/mxml-index.c @@ -0,0 +1,418 @@ +// +// Index support code for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// Local functions... +// + +static int index_compare(mxml_index_t *ind, mxml_node_t *first, mxml_node_t *second); +static int index_find(mxml_index_t *ind, const char *element, const char *value, mxml_node_t *node); +static void index_sort(mxml_index_t *ind, int left, int right); + + +// +// 'mxmlIndexDelete()' - Delete an index. +// + +void +mxmlIndexDelete(mxml_index_t *ind) // I - Index to delete +{ + // Range check input.. + if (!ind) + return; + + // Free memory... + _mxml_strfree(ind->attr); + free(ind->nodes); + free(ind); +} + + +// +// 'mxmlIndexEnum()' - Return the next node in the index. +// +// This function returns the next node in index `ind`. +// +// You should call @link mxmlIndexReset@ prior to using this function to get +// the first node in the index. Nodes are returned in the sorted order of the +// index. +// + +mxml_node_t * // O - Next node or `NULL` if there is none +mxmlIndexEnum(mxml_index_t *ind) // I - Index to enumerate +{ + // Range check input... + if (!ind) + return (NULL); + + // Return the next node... + if (ind->cur_node < ind->num_nodes) + return (ind->nodes[ind->cur_node ++]); + else + return (NULL); +} + + +// +// 'mxmlIndexFind()' - Find the next matching node. +// +// This function finds the next matching node in index `ind`. +// +// You should call @link mxmlIndexReset@ prior to using this function for +// the first time with a particular set of `element` and `value` +// strings. Passing `NULL` for both `element` and `value` is equivalent +// to calling @link mxmlIndexEnum@. +// + +mxml_node_t * // O - Node or `NULL` if none found +mxmlIndexFind(mxml_index_t *ind, // I - Index to search + const char *element, // I - Element name to find, if any + const char *value) // I - Attribute value, if any +{ + int diff, // Difference between names + current, // Current entity in search + first, // First entity in search + last; // Last entity in search + + + MXML_DEBUG("mxmlIndexFind(ind=%p, element=\"%s\", value=\"%s\")\n", ind, element ? element : "(null)", value ? value : "(null)"); + + // Range check input... + if (!ind || (!ind->attr && value)) + { + MXML_DEBUG("mxmlIndexFind: Returning NULL, ind->attr=\"%s\"...\n", ind && ind->attr ? ind->attr : "(null)"); + return (NULL); + } + + // If both element and value are NULL, just enumerate the nodes in the index... + if (!element && !value) + return (mxmlIndexEnum(ind)); + + // If there are no nodes in the index, return NULL... + if (!ind->num_nodes) + { + MXML_DEBUG("mxmlIndexFind: Returning NULL, no nodes...\n"); + return (NULL); + } + + // If cur_node == 0, then find the first matching node... + if (ind->cur_node == 0) + { + // Find the first node using a modified binary search algorithm... + first = 0; + last = ind->num_nodes - 1; + + MXML_DEBUG("mxmlIndexFind: Find first time, num_nodes=%lu...\n", (unsigned long)ind->num_nodes); + + while ((last - first) > 1) + { + current = (first + last) / 2; + + MXML_DEBUG("mxmlIndexFind: first=%d, last=%d, current=%d\n", first, last, current); + + if ((diff = index_find(ind, element, value, ind->nodes[current])) == 0) + { + // Found a match, move back to find the first... + MXML_DEBUG("mxmlIndexFind: match.\n"); + + while (current > 0 && !index_find(ind, element, value, ind->nodes[current - 1])) + current --; + + MXML_DEBUG("mxmlIndexFind: Returning first match=%d\n", current); + + // Return the first match and save the index to the next... + ind->cur_node = current + 1; + + return (ind->nodes[current]); + } + else if (diff < 0) + { + last = current; + } + else + { + first = current; + } + + MXML_DEBUG("mxmlIndexFind: diff=%d\n", diff); + } + + // If we get this far, then we found exactly 0 or 1 matches... + for (current = first; current <= last; current ++) + { + if (!index_find(ind, element, value, ind->nodes[current])) + { + // Found exactly one (or possibly two) match... + MXML_DEBUG("mxmlIndexFind: Returning only match %d...\n", current); + ind->cur_node = current + 1; + + return (ind->nodes[current]); + } + } + + // No matches... + ind->cur_node = ind->num_nodes; + MXML_DEBUG("mxmlIndexFind: Returning NULL...\n"); + return (NULL); + } + else if (ind->cur_node < ind->num_nodes && !index_find(ind, element, value, ind->nodes[ind->cur_node])) + { + // Return the next matching node... + MXML_DEBUG("mxmlIndexFind: Returning next match %lu...\n", (unsigned long)ind->cur_node); + return (ind->nodes[ind->cur_node ++]); + } + + // If we get this far, then we have no matches... + ind->cur_node = ind->num_nodes; + + MXML_DEBUG("mxmlIndexFind: Returning NULL...\n"); + return (NULL); +} + + +// +// 'mxmlIndexGetCount()' - Get the number of nodes in an index. +// + +size_t // I - Number of nodes in index +mxmlIndexGetCount(mxml_index_t *ind) // I - Index of nodes +{ + // Range check input... + if (!ind) + return (0); + + // Return the number of nodes in the index... + return (ind->num_nodes); +} + + +// +// 'mxmlIndexNew()' - Create a new index. +// +// This function creates a new index for XML tree `node`. +// +// The index will contain all nodes that contain the named element and/or +// attribute. If both `element` and `attr` are `NULL`, then the index will +// contain a sorted list of the elements in the node tree. Nodes are +// sorted by element name and optionally by attribute value if the `attr` +// argument is not `NULL`. +// + +mxml_index_t * // O - New index +mxmlIndexNew(mxml_node_t *node, // I - XML node tree + const char *element, // I - Element to index or `NULL` for all + const char *attr) // I - Attribute to index or `NULL` for none +{ + mxml_index_t *ind; // New index + mxml_node_t *current, // Current node in index + **temp; // Temporary node pointer array + + + // Range check input... + MXML_DEBUG("mxmlIndexNew(node=%p, element=\"%s\", attr=\"%s\")\n", node, element ? element : "(null)", attr ? attr : "(null)"); + + if (!node) + return (NULL); + + // Create a new index... + if ((ind = calloc(1, sizeof(mxml_index_t))) == NULL) + return (NULL); + + if (attr) + { + if ((ind->attr = _mxml_strcopy(attr)) == NULL) + { + free(ind); + return (NULL); + } + } + + if (!element && !attr) + current = node; + else + current = mxmlFindElement(node, node, element, attr, NULL, MXML_DESCEND_ALL); + + while (current) + { + if (ind->num_nodes >= ind->alloc_nodes) + { + if ((temp = realloc(ind->nodes, (ind->alloc_nodes + MXML_ALLOC_SIZE) * sizeof(mxml_node_t *))) == NULL) + { + // Unable to allocate memory for the index, so abort... + mxmlIndexDelete(ind); + return (NULL); + } + + ind->nodes = temp; + ind->alloc_nodes += MXML_ALLOC_SIZE; + } + + ind->nodes[ind->num_nodes ++] = current; + + current = mxmlFindElement(current, node, element, attr, NULL, MXML_DESCEND_ALL); + } + + // Sort nodes based upon the search criteria... + if (ind->num_nodes > 1) + index_sort(ind, 0, ind->num_nodes - 1); + + // Return the new index... + return (ind); +} + + +// +// 'mxmlIndexReset()' - Reset the enumeration/find pointer in the index and +// return the first node in the index. +// +// This function resets the enumeration/find pointer in index `ind` and should +// be called prior to using @link mxmlIndexEnum@ or @link mxmlIndexFind@ for the +// first time. +// + +mxml_node_t * // O - First node or `NULL` if there is none +mxmlIndexReset(mxml_index_t *ind) // I - Index to reset +{ + MXML_DEBUG("mxmlIndexReset(ind=%p)\n", ind); + + // Range check input... + if (!ind) + return (NULL); + + // Set the index to the first element... + ind->cur_node = 0; + + // Return the first node... + if (ind->num_nodes) + return (ind->nodes[0]); + else + return (NULL); +} + + +// +// 'index_compare()' - Compare two nodes. +// + +static int // O - Result of comparison +index_compare(mxml_index_t *ind, // I - Index + mxml_node_t *first, // I - First node + mxml_node_t *second) // I - Second node +{ + int diff; // Difference + + + // Check the element name... + if ((diff = strcmp(first->value.element.name, second->value.element.name)) != 0) + return (diff); + + // Check the attribute value... + if (ind->attr) + { + if ((diff = strcmp(mxmlElementGetAttr(first, ind->attr), mxmlElementGetAttr(second, ind->attr))) != 0) + return (diff); + } + + // No difference, return 0... + return (0); +} + + +// +// 'index_find()' - Compare a node with index values. +// + +static int // O - Result of comparison +index_find(mxml_index_t *ind, // I - Index + const char *element, // I - Element name or `NULL` + const char *value, // I - Attribute value or `NULL` + mxml_node_t *node) // I - Node +{ + int diff; // Difference + + + // Check the element name... + if (element) + { + if ((diff = strcmp(element, node->value.element.name)) != 0) + return (diff); + } + + // Check the attribute value... + if (value) + { + if ((diff = strcmp(value, mxmlElementGetAttr(node, ind->attr))) != 0) + return (diff); + } + + // No difference, return 0... + return (0); +} + + +// +// 'index_sort()' - Sort the nodes in the index... +// +// This function implements the classic quicksort algorithm... +// + +static void +index_sort(mxml_index_t *ind, // I - Index to sort + int left, // I - Left node in partition + int right) // I - Right node in partition +{ + mxml_node_t *pivot, // Pivot node + *temp; // Swap node + int templ, // Temporary left node + tempr; // Temporary right node + + + // Loop until we have sorted all the way to the right... + do + { + // Sort the pivot in the current partition... + pivot = ind->nodes[left]; + + for (templ = left, tempr = right; templ < tempr;) + { + // Move left while left node <= pivot node... + while ((templ < right) && index_compare(ind, ind->nodes[templ], pivot) <= 0) + templ ++; + + // Move right while right node > pivot node... + while ((tempr > left) && index_compare(ind, ind->nodes[tempr], pivot) > 0) + tempr --; + + // Swap nodes if needed... + if (templ < tempr) + { + temp = ind->nodes[templ]; + ind->nodes[templ] = ind->nodes[tempr]; + ind->nodes[tempr] = temp; + } + } + + // When we get here, the right (tempr) node is the new position for the pivot node... + if (index_compare(ind, pivot, ind->nodes[tempr]) > 0) + { + ind->nodes[left] = ind->nodes[tempr]; + ind->nodes[tempr] = pivot; + } + + // Recursively sort the left partition as needed... + if (left < (tempr - 1)) + index_sort(ind, left, tempr - 1); + } + while (right > (left = tempr + 1)); +} diff --git a/src/main/mxml/mxml-node.c b/src/main/mxml/mxml-node.c new file mode 100644 index 00000000..a6978c96 --- /dev/null +++ b/src/main/mxml/mxml-node.c @@ -0,0 +1,937 @@ +// +// Node support code for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// Local functions... +// + +static void mxml_free(mxml_node_t *node); +static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type); + + +// +// 'mxmlAdd()' - Add a node to a tree. +// +// This function adds the specified node `node` to the parent. If the `child` +// argument is not `NULL`, the new node is added before or after the specified +// child depending on the value of the `add` argument. If the `child` argument +// is `NULL`, the new node is placed at the beginning of the child list +// (`MXML_ADD_BEFORE`) or at the end of the child list (`MXML_ADD_AFTER`). +// + +void +mxmlAdd(mxml_node_t *parent, // I - Parent node + mxml_add_t add, // I - Where to add, `MXML_ADD_BEFORE` or `MXML_ADD_AFTER` + mxml_node_t *child, // I - Child node for where or `MXML_ADD_TO_PARENT` + mxml_node_t *node) // I - Node to add +{ + MXML_DEBUG("mxmlAdd(parent=%p, add=%d, child=%p, node=%p)\n", parent, add, child, node); + + // Range check input... + if (!parent || !node) + return; + + // Remove the node from any existing parent... + if (node->parent) + mxmlRemove(node); + + // Reset pointers... + node->parent = parent; + + switch (add) + { + case MXML_ADD_BEFORE : + if (!child || child == parent->child || child->parent != parent) + { + // Insert as first node under parent... + node->next = parent->child; + + if (parent->child) + parent->child->prev = node; + else + parent->last_child = node; + + parent->child = node; + } + else + { + // Insert node before this child... + node->next = child; + node->prev = child->prev; + + if (child->prev) + child->prev->next = node; + else + parent->child = node; + + child->prev = node; + } + break; + + case MXML_ADD_AFTER : + if (!child || child == parent->last_child || child->parent != parent) + { + // Insert as last node under parent... + node->parent = parent; + node->prev = parent->last_child; + + if (parent->last_child) + parent->last_child->next = node; + else + parent->child = node; + + parent->last_child = node; + } + else + { + // Insert node after this child... + node->prev = child; + node->next = child->next; + + if (child->next) + child->next->prev = node; + else + parent->last_child = node; + + child->next = node; + } + break; + } +} + + +// +// 'mxmlDelete()' - Delete a node and all of its children. +// +// This function deletes the node `node` and all of its children. If the +// specified node has a parent, this function first removes the node from its +// parent using the @link mxmlRemove@ function. +// + +void +mxmlDelete(mxml_node_t *node) // I - Node to delete +{ + mxml_node_t *current, // Current node + *next; // Next node + + + MXML_DEBUG("mxmlDelete(node=%p)\n", node); + + // Range check input... + if (!node) + return; + + // Remove the node from its parent, if any... + mxmlRemove(node); + + // Delete children... + for (current = node->child; current; current = next) + { + // Get the next node... + if ((next = current->child) != NULL) + { + // Free parent nodes after child nodes have been freed... + current->child = NULL; + continue; + } + + if ((next = current->next) == NULL) + { + // Next node is the parent, which we'll free as needed... + if ((next = current->parent) == node) + next = NULL; + } + + // Free child... + mxml_free(current); + } + + // Then free the memory used by the parent node... + mxml_free(node); +} + + +// +// 'mxmlGetRefCount()' - Get the current reference (use) count for a node. +// +// The initial reference count of new nodes is 1. Use the @link mxmlRetain@ +// and @link mxmlRelease@ functions to increment and decrement a node's +// reference count. +// + +size_t // O - Reference count +mxmlGetRefCount(mxml_node_t *node) // I - Node +{ + // Range check input... + if (!node) + return (0); + + // Return the reference count... + return (node->ref_count); +} + + +// +// 'mxmlNewCDATA()' - Create a new CDATA node. +// +// The new CDATA node is added to the end of the specified parent's child +// list. The constant `MXML_NO_PARENT` can be used to specify that the new +// CDATA node has no parent. The data string must be nul-terminated and +// is copied into the new node. CDATA nodes currently use the +// `MXML_TYPE_ELEMENT` type. +// + +mxml_node_t * // O - New node +mxmlNewCDATA(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *data) // I - Data string +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewCDATA(parent=%p, data=\"%s\")\n", parent, data ? data : "(null)"); + + // Range check input... + if (!data) + return (NULL); + + // Create the node and set the name value... + if ((node = mxml_new(parent, MXML_TYPE_CDATA)) != NULL) + { + if ((node->value.cdata = _mxml_strcopy(data)) == NULL) + { + mxmlDelete(node); + return (NULL); + } + } + + return (node); +} + + +// +// 'mxmlNewCDATAf()' - Create a new formatted CDATA node. +// +// The new CDATA node is added to the end of the specified parent's +// child list. The constant `MXML_NO_PARENT` can be used to specify that +// the new opaque string node has no parent. The format string must be +// nul-terminated and is formatted into the new node. +// + +mxml_node_t * // O - New node +mxmlNewCDATAf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *format, // I - Printf-style format string + ...) // I - Additional args as needed +{ + mxml_node_t *node; // New node + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + + + MXML_DEBUG("mxmlNewCDATAf(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)"); + + // Range check input... + if (!format) + return (NULL); + + // Create the node and set the text value... + if ((node = mxml_new(parent, MXML_TYPE_CDATA)) != NULL) + { + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + node->value.cdata = _mxml_strcopy(buffer); + } + + return (node); +} + + +// +// 'mxmlNewComment()' - Create a new comment node. +// +// The new comment node is added to the end of the specified parent's child +// list. The constant `MXML_NO_PARENT` can be used to specify that the new +// comment node has no parent. The comment string must be nul-terminated and +// is copied into the new node. +// + +mxml_node_t * // O - New node +mxmlNewComment(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *comment) // I - Comment string +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewComment(parent=%p, comment=\"%s\")\n", parent, comment ? comment : "(null)"); + + // Range check input... + if (!comment) + return (NULL); + + // Create the node and set the name value... + if ((node = mxml_new(parent, MXML_TYPE_COMMENT)) != NULL) + { + if ((node->value.comment = _mxml_strcopy(comment)) == NULL) + { + mxmlDelete(node); + return (NULL); + } + } + + return (node); +} + + +// +// 'mxmlNewCommentf()' - Create a new formatted comment string node. +// +// The new comment string node is added to the end of the specified parent's +// child list. The constant `MXML_NO_PARENT` can be used to specify that +// the new opaque string node has no parent. The format string must be +// nul-terminated and is formatted into the new node. +// + +mxml_node_t * // O - New node +mxmlNewCommentf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *format, // I - Printf-style format string + ...) // I - Additional args as needed +{ + mxml_node_t *node; // New node + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + + + MXML_DEBUG("mxmlNewCommentf(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)"); + + // Range check input... + if (!format) + return (NULL); + + // Create the node and set the text value... + if ((node = mxml_new(parent, MXML_TYPE_COMMENT)) != NULL) + { + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + node->value.comment = _mxml_strcopy(buffer); + } + + return (node); +} + + +// +// 'mxmlNewCustom()' - Create a new custom data node. +// +// The new custom node is added to the end of the specified parent's child +// list. The `free_cb` argument specifies a function to call to free the custom +// data when the node is deleted. +// + +mxml_node_t * // O - New node +mxmlNewCustom( + mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + void *data, // I - Pointer to data + mxml_custfree_cb_t free_cb, // I - Free callback function or `NULL` if none needed + void *free_cbdata) // I - Free callback data +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewCustom(parent=%p, data=%p, free_cb=%p, free_cbdata=%p)\n", parent, data, free_cb, free_cbdata); + + // Create the node and set the value... + if ((node = mxml_new(parent, MXML_TYPE_CUSTOM)) != NULL) + { + node->value.custom.data = data; + node->value.custom.free_cb = free_cb; + node->value.custom.free_cbdata = free_cbdata; + } + + return (node); +} + + +// +// 'mxmlNewDeclaration()' - Create a new declaraction node. +// +// The new declaration node is added to the end of the specified parent's child +// list. The constant `MXML_NO_PARENT` can be used to specify that the new +// declaration node has no parent. The declaration string must be nul- +// terminated and is copied into the new node. +// + +mxml_node_t * // O - New node +mxmlNewDeclaration( + mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *declaration) // I - Declaration string +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewDeclaration(parent=%p, declaration=\"%s\")\n", parent, declaration ? declaration : "(null)"); + + // Range check input... + if (!declaration) + return (NULL); + + // Create the node and set the name value... + if ((node = mxml_new(parent, MXML_TYPE_DECLARATION)) != NULL) + { + if ((node->value.declaration = _mxml_strcopy(declaration)) == NULL) + { + mxmlDelete(node); + return (NULL); + } + } + + return (node); +} + + +// +// 'mxmlNewDeclarationf()' - Create a new formatted declaration node. +// +// The new declaration node is added to the end of the specified parent's +// child list. The constant `MXML_NO_PARENT` can be used to specify that +// the new opaque string node has no parent. The format string must be +// nul-terminated and is formatted into the new node. +// + +mxml_node_t * // O - New node +mxmlNewDeclarationf( + mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *format, // I - Printf-style format string + ...) // I - Additional args as needed +{ + mxml_node_t *node; // New node + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + + + MXML_DEBUG("mxmlNewDeclarationf(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)"); + + // Range check input... + if (!format) + return (NULL); + + // Create the node and set the text value... + if ((node = mxml_new(parent, MXML_TYPE_DECLARATION)) != NULL) + { + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + node->value.declaration = _mxml_strcopy(buffer); + } + + return (node); +} + + +// +// 'mxmlNewDirective()' - Create a new processing instruction node. +// +// The new processing instruction node is added to the end of the specified +// parent's child list. The constant `MXML_NO_PARENT` can be used to specify +// that the new processing instruction node has no parent. The data string must +// be nul-terminated and is copied into the new node. +// + +mxml_node_t * // O - New node +mxmlNewDirective(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *directive)// I - Directive string +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewDirective(parent=%p, directive=\"%s\")\n", parent, directive ? directive : "(null)"); + + // Range check input... + if (!directive) + return (NULL); + + // Create the node and set the name value... + if ((node = mxml_new(parent, MXML_TYPE_DIRECTIVE)) != NULL) + { + if ((node->value.directive = _mxml_strcopy(directive)) == NULL) + { + mxmlDelete(node); + return (NULL); + } + } + + return (node); +} + + +// +// 'mxmlNewDirectivef()' - Create a new formatted processing instruction node. +// +// The new processing instruction node is added to the end of the specified parent's +// child list. The constant `MXML_NO_PARENT` can be used to specify that +// the new opaque string node has no parent. The format string must be +// nul-terminated and is formatted into the new node. +// + +mxml_node_t * // O - New node +mxmlNewDirectivef(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *format, // I - Printf-style format string + ...) // I - Additional args as needed +{ + mxml_node_t *node; // New node + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + + + MXML_DEBUG("mxmlNewDirectivef(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)"); + + // Range check input... + if (!format) + return (NULL); + + // Create the node and set the text value... + if ((node = mxml_new(parent, MXML_TYPE_DIRECTIVE)) != NULL) + { + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + node->value.directive = _mxml_strcopy(buffer); + } + + return (node); +} + + +// +// 'mxmlNewElement()' - Create a new element node. +// +// The new element node is added to the end of the specified parent's child +// list. The constant `MXML_NO_PARENT` can be used to specify that the new +// element node has no parent. +// + +mxml_node_t * // O - New node +mxmlNewElement(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *name) // I - Name of element +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewElement(parent=%p, name=\"%s\")\n", parent, name ? name : "(null)"); + + // Range check input... + if (!name) + return (NULL); + + // Create the node and set the element name... + if ((node = mxml_new(parent, MXML_TYPE_ELEMENT)) != NULL) + node->value.element.name = _mxml_strcopy(name); + + return (node); +} + + +// +// 'mxmlNewInteger()' - Create a new integer node. +// +// The new integer node is added to the end of the specified parent's child +// list. The constant `MXML_NO_PARENT` can be used to specify that the new +// integer node has no parent. +// + +mxml_node_t * // O - New node +mxmlNewInteger(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + long integer) // I - Integer value +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewInteger(parent=%p, integer=%ld)\n", parent, integer); + + // Create the node and set the element name... + if ((node = mxml_new(parent, MXML_TYPE_INTEGER)) != NULL) + node->value.integer = integer; + + return (node); +} + + +// +// 'mxmlNewOpaque()' - Create a new opaque string. +// +// The new opaque string node is added to the end of the specified parent's +// child list. The constant `MXML_NO_PARENT` can be used to specify that +// the new opaque string node has no parent. The opaque string must be nul- +// terminated and is copied into the new node. +// + +mxml_node_t * // O - New node +mxmlNewOpaque(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *opaque) // I - Opaque string +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent, opaque ? opaque : "(null)"); + + // Range check input... + if (!opaque) + return (NULL); + + // Create the node and set the element name... + if ((node = mxml_new(parent, MXML_TYPE_OPAQUE)) != NULL) + node->value.opaque = _mxml_strcopy(opaque); + + return (node); +} + + +// +// 'mxmlNewOpaquef()' - Create a new formatted opaque string node. +// +// The new opaque string node is added to the end of the specified parent's +// child list. The constant `MXML_NO_PARENT` can be used to specify that +// the new opaque string node has no parent. The format string must be +// nul-terminated and is formatted into the new node. +// + +mxml_node_t * // O - New node +mxmlNewOpaquef(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + const char *format, // I - Printf-style format string + ...) // I - Additional args as needed +{ + mxml_node_t *node; // New node + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + + + MXML_DEBUG("mxmlNewOpaquef(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)"); + + // Range check input... + if (!format) + return (NULL); + + // Create the node and set the text value... + if ((node = mxml_new(parent, MXML_TYPE_OPAQUE)) != NULL) + { + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + node->value.opaque = _mxml_strcopy(buffer); + } + + return (node); +} + + +// +// 'mxmlNewReal()' - Create a new real number node. +// +// The new real number node is added to the end of the specified parent's +// child list. The constant `MXML_NO_PARENT` can be used to specify that +// the new real number node has no parent. +// + +mxml_node_t * // O - New node +mxmlNewReal(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + double real) // I - Real number value +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewReal(parent=%p, real=%g)\n", parent, real); + + // Create the node and set the element name... + if ((node = mxml_new(parent, MXML_TYPE_REAL)) != NULL) + node->value.real = real; + + return (node); +} + + +// +// 'mxmlNewText()' - Create a new text fragment node. +// +// The new text node is added to the end of the specified parent's child +// list. The constant `MXML_NO_PARENT` can be used to specify that the new +// text node has no parent. The whitespace parameter is used to specify +// whether leading whitespace is present before the node. The text +// string must be nul-terminated and is copied into the new node. +// + +mxml_node_t * // O - New node +mxmlNewText(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace + const char *string) // I - String +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxmlNewText(parent=%p, whitespace=%s, string=\"%s\")\n", parent, whitespace ? "true" : "false", string ? string : "(null)"); + + // Range check input... + if (!string) + return (NULL); + + // Create the node and set the text value... + if ((node = mxml_new(parent, MXML_TYPE_TEXT)) != NULL) + { + node->value.text.whitespace = whitespace; + node->value.text.string = _mxml_strcopy(string); + } + + return (node); +} + + +// +// 'mxmlNewTextf()' - Create a new formatted text fragment node. +// +// The new text node is added to the end of the specified parent's child +// list. The constant `MXML_NO_PARENT` can be used to specify that the new +// text node has no parent. The whitespace parameter is used to specify +// whether leading whitespace is present before the node. The format +// string must be nul-terminated and is formatted into the new node. +// + +mxml_node_t * // O - New node +mxmlNewTextf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT` + bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace + const char *format, // I - Printf-style format string + ...) // I - Additional args as needed +{ + mxml_node_t *node; // New node + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + + + MXML_DEBUG("mxmlNewTextf(parent=%p, whitespace=%s, format=\"%s\", ...)\n", parent, whitespace ? "true" : "false", format ? format : "(null)"); + + // Range check input... + if (!format) + return (NULL); + + // Create the node and set the text value... + if ((node = mxml_new(parent, MXML_TYPE_TEXT)) != NULL) + { + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + node->value.text.whitespace = whitespace; + node->value.text.string = _mxml_strcopy(buffer); + } + + return (node); +} + + +// +// 'mxmlRemove()' - Remove a node from its parent. +// +// This function does not free memory used by the node - use @link mxmlDelete@ +// for that. This function does nothing if the node has no parent. +// + +void +mxmlRemove(mxml_node_t *node) // I - Node to remove +{ + MXML_DEBUG("mxmlRemove(node=%p)\n", node); + + // Range check input... + if (!node || !node->parent) + return; + + // Remove from parent... + if (node->prev) + node->prev->next = node->next; + else + node->parent->child = node->next; + + if (node->next) + node->next->prev = node->prev; + else + node->parent->last_child = node->prev; + + node->parent = NULL; + node->prev = NULL; + node->next = NULL; +} + + +// +// 'mxmlNewXML()' - Create a new XML document tree. +// +// The "version" argument specifies the version number to put in the +// ?xml directive node. If `NULL`, version "1.0" is assumed. +// + +mxml_node_t * // O - New ?xml node +mxmlNewXML(const char *version) // I - Version number to use +{ + char directive[1024]; // Directive text + + + snprintf(directive, sizeof(directive), "xml version=\"%s\" encoding=\"utf-8\"", version ? version : "1.0"); + + return (mxmlNewDirective(NULL, directive)); +} + + +// +// 'mxmlRelease()' - Release a node. +// +// When the reference count reaches zero, the node (and any children) +// is deleted via @link mxmlDelete@. +// + +int // O - New reference count +mxmlRelease(mxml_node_t *node) // I - Node +{ + if (node) + { + if ((-- node->ref_count) <= 0) + { + mxmlDelete(node); + return (0); + } + else + { + return (node->ref_count); + } + } + else + { + return (-1); + } +} + + +// +// 'mxmlRetain()' - Retain a node. +// + +int // O - New reference count +mxmlRetain(mxml_node_t *node) // I - Node +{ + if (node) + return (++ node->ref_count); + else + return (-1); +} + + +// +// 'mxml_free()' - Free the memory used by a node. +// +// Note: Does not free child nodes, does not remove from parent. +// + +static void +mxml_free(mxml_node_t *node) // I - Node +{ + size_t i; // Looping var + + + switch (node->type) + { + case MXML_TYPE_CDATA : + _mxml_strfree(node->value.cdata); + break; + case MXML_TYPE_COMMENT : + _mxml_strfree(node->value.comment); + break; + case MXML_TYPE_DECLARATION : + _mxml_strfree(node->value.declaration); + break; + case MXML_TYPE_DIRECTIVE : + _mxml_strfree(node->value.directive); + break; + case MXML_TYPE_ELEMENT : + _mxml_strfree(node->value.element.name); + + if (node->value.element.num_attrs) + { + for (i = 0; i < node->value.element.num_attrs; i ++) + { + _mxml_strfree(node->value.element.attrs[i].name); + _mxml_strfree(node->value.element.attrs[i].value); + } + + free(node->value.element.attrs); + } + break; + case MXML_TYPE_INTEGER : + // Nothing to do + break; + case MXML_TYPE_OPAQUE : + _mxml_strfree(node->value.opaque); + break; + case MXML_TYPE_REAL : + // Nothing to do + break; + case MXML_TYPE_TEXT : + _mxml_strfree(node->value.text.string); + break; + case MXML_TYPE_CUSTOM : + if (node->value.custom.data && node->value.custom.free_cb) + (node->value.custom.free_cb)(node->value.custom.free_cbdata, node->value.custom.data); + break; + default : + break; + } + + // Free this node... + free(node); +} + + +// +// 'mxml_new()' - Create a new node. +// + +static mxml_node_t * // O - New node +mxml_new(mxml_node_t *parent, // I - Parent node + mxml_type_t type) // I - Node type +{ + mxml_node_t *node; // New node + + + MXML_DEBUG("mxml_new(parent=%p, type=%d)\n", parent, type); + + // Allocate memory for the node... + if ((node = calloc(1, sizeof(mxml_node_t))) == NULL) + { + MXML_DEBUG("mxml_new: Returning NULL\n"); + return (NULL); + } + + MXML_DEBUG("mxml_new: Returning %p\n", node); + + // Set the node type... + node->type = type; + node->ref_count = 1; + + // Add to the parent if present... + if (parent) + mxmlAdd(parent, MXML_ADD_AFTER, /*child*/NULL, node); + + // Return the new node... + return (node); +} diff --git a/src/main/mxml/mxml-options.c b/src/main/mxml/mxml-options.c new file mode 100644 index 00000000..1f521c28 --- /dev/null +++ b/src/main/mxml/mxml-options.c @@ -0,0 +1,545 @@ +// +// Options functions for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// 'mxmlOptionsDelete()' - Free load/save options. +// + +void +mxmlOptionsDelete( + mxml_options_t *options) // I - Options +{ + free(options); +} + + +// +// 'mxmlOptionsNew()' - Allocate load/save options. +// +// This function creates a new set of load/save options to use with the +// @link mxmlLoadFd@, @link mxmlLoadFile@, @link mxmlLoadFilename@, +// @link mxmlLoadIO@, @link mxmlLoadString@, @link mxmlSaveAllocString@, +// @link mxmlSaveFd@, @link mxmlSaveFile@, @link mxmlSaveFilename@, +// @link mxmlSaveIO@, and @link mxmlSaveString@ functions. Options can be +// reused for multiple calls to these functions and should be freed using the +// @link mxmlOptionsDelete@ function. +// +// The default load/save options load values using the constant type +// `MXML_TYPE_TEXT` and save XML data with a wrap margin of 72 columns. +// The various `mxmlOptionsSet` functions are used to change the defaults, +// for example: +// +// ```c +// mxml_options_t *options = mxmlOptionsNew(); +// +// /* Load values as opaque strings */ +// mxmlOptionsSetTypeValue(options, MXML_TYPE_OPAQUE); +// ``` +// +// Note: The most common programming error when using the Mini-XML library is +// to load an XML file using the `MXML_TYPE_TEXT` node type, which returns +// inline text as a series of whitespace-delimited words, instead of using the +// `MXML_TYPE_OPAQUE` node type which returns the inline text as a single string +// (including whitespace). +// + +mxml_options_t * // O - Options +mxmlOptionsNew(void) +{ + mxml_options_t *options; // Options + + + if ((options = (mxml_options_t *)calloc(1, sizeof(mxml_options_t))) != NULL) + { + // Set default values... + options->type_value = MXML_TYPE_TEXT; + options->wrap = 72; + + if ((options->loc = localeconv()) != NULL) + { + if (!options->loc->decimal_point || !strcmp(options->loc->decimal_point, ".")) + options->loc = NULL; + else + options->loc_declen = strlen(options->loc->decimal_point); + } + } + + return (options); +} + + +// +// 'mxmlOptionsSetCustomCallbacks()' - Set the custom data callbacks. +// +// This function sets the callbacks that are used for loading and saving custom +// data types. The load callback `load_cb` accepts the callback data pointer +// `cbdata`, a node pointer, and a data string and returns `true` on success and +// `false` on error, for example: +// +// ```c +// typedef struct +// { +// unsigned year, /* Year */ +// month, /* Month */ +// day, /* Day */ +// hour, /* Hour */ +// minute, /* Minute */ +// second; /* Second */ +// time_t unix; /* UNIX time */ +// } iso_date_time_t; +// +// void +// my_custom_free_cb(void *cbdata, void *data) +// { +// free(data); +// } +// +// bool +// my_custom_load_cb(void *cbdata, mxml_node_t *node, const char *data) +// { +// iso_date_time_t *dt; +// struct tm tmdata; +// +// /* Allocate custom data structure ... */ +// dt = calloc(1, sizeof(iso_date_time_t)); +// +// /* Parse the data string... */ +// if (sscanf(data, "%u-%u-%uT%u:%u:%uZ", &(dt->year), &(dt->month), +// &(dt->day), &(dt->hour), &(dt->minute), &(dt->second)) != 6) +// { +// /* Unable to parse date and time numbers... */ +// free(dt); +// return (false); +// } +// +// /* Range check values... */ +// if (dt->month < 1 || dt->month > 12 || dt->day < 1 || dt->day > 31 || +// dt->hour < 0 || dt->hour > 23 || dt->minute < 0 || dt->minute > 59 || +// dt->second < 0 || dt->second > 60) +// { +// /* Date information is out of range... */ +// free(dt); +// return (false); +// } +// +// /* Convert ISO time to UNIX time in seconds... */ +// tmdata.tm_year = dt->year - 1900; +// tmdata.tm_mon = dt->month - 1; +// tmdata.tm_day = dt->day; +// tmdata.tm_hour = dt->hour; +// tmdata.tm_min = dt->minute; +// tmdata.tm_sec = dt->second; +// +// dt->unix = gmtime(&tmdata); +// +// /* Set custom data and free function... */ +// mxmlSetCustom(node, data, my_custom_free, /*cbdata*/NULL); +// +// /* Return with no errors... */ +// return (true); +// } +// ``` +// +// The save callback `save_cb` accepts the callback data pointer `cbdata` and a +// node pointer and returns a malloc'd string on success and `NULL` on error, +// for example: +// +// ```c +// char * +// my_custom_save_cb(void *cbdata, mxml_node_t *node) +// { +// char data[255]; +// iso_date_time_t *dt; +// +// /* Get the custom data structure */ +// dt = (iso_date_time_t *)mxmlGetCustom(node); +// +// /* Generate string version of the date/time... */ +// snprintf(data, sizeof(data), "%04u-%02u-%02uT%02u:%02u:%02uZ", +// dt->year, dt->month, dt->day, dt->hour, dt->minute, dt->second); +// +// /* Duplicate the string and return... */ +// return (strdup(data)); +// } +// ``` +// + +void +mxmlOptionsSetCustomCallbacks( + mxml_options_t *options, // I - Options + mxml_custload_cb_t load_cb, // I - Custom load callback function + mxml_custsave_cb_t save_cb, // I - Custom save callback function + void *cbdata) // I - Custom callback data +{ + if (options) + { + options->custload_cb = load_cb; + options->custsave_cb = save_cb; + options->cust_cbdata = cbdata; + } +} + + +// +// 'mxmlOptionsSetEntityCallback()' - Set the entity lookup callback to use when loading XML data. +// +// This function sets the callback that is used to lookup named XML character +// entities when loading XML data. The callback function `cb` accepts the +// callback data pointer `cbdata` and the entity name. The function returns a +// Unicode character value or `-1` if the entity is not known. For example, the +// following entity callback supports the "euro" entity: +// +// ```c +// int my_entity_cb(void *cbdata, const char *name) +// { +// if (!strcmp(name, "euro")) +// return (0x20ac); +// else +// return (-1); +// } +// ``` +// +// Mini-XML automatically supports the "amp", "gt", "lt", and "quot" character +// entities which are required by the base XML specification. +// + +void +mxmlOptionsSetEntityCallback( + mxml_options_t *options, // I - Options + mxml_entity_cb_t cb, // I - Entity callback function + void *cbdata) // I - Entity callback data +{ + if (options) + { + options->entity_cb = cb; + options->entity_cbdata = cbdata; + } +} + + +// +// 'mxmlOptionsSetErrorCallback()' - Set the error message callback. +// +// This function sets a function to use when reporting errors. The callback +// `cb` accepts the data pointer `cbdata` and a string pointer containing the +// error message: +// +// ```c +// void my_error_cb(void *cbdata, const char *message) +// { +// fprintf(stderr, "myprogram: %s\n", message); +// } +// ``` +// +// The default error callback writes the error message to the `stderr` file. +// + +void +mxmlOptionsSetErrorCallback( + mxml_options_t *options, // I - Options + mxml_error_cb_t cb, // I - Error callback function + void *cbdata) // I - Error callback data +{ + if (options) + { + options->error_cb = cb; + options->error_cbdata = cbdata; + } +} + + +// +// 'mxmlOptionsSetSAXCallback()' - Set the SAX callback to use when reading XML data. +// +// This function sets a SAX callback to use when reading XML data. The SAX +// callback function `cb` and associated callback data `cbdata` are used to +// enable the Simple API for XML streaming mode. The callback is called as the +// XML node tree is parsed and receives the `cbdata` pointer, the `mxml_node_t` +// pointer, and an event code. The function returns `true` to continue +// processing or `false` to stop: +// +// ```c +// bool +// sax_cb(void *cbdata, mxml_node_t *node, +// mxml_sax_event_t event) +// { +// ... do something ... +// +// /* Continue processing... */ +// return (true); +// } +// ``` +// +// The event will be one of the following: +// +// - `MXML_SAX_EVENT_CDATA`: CDATA was just read. +// - `MXML_SAX_EVENT_COMMENT`: A comment was just read. +// - `MXML_SAX_EVENT_DATA`: Data (integer, opaque, real, or text) was just read. +// - `MXML_SAX_EVENT_DECLARATION`: A declaration was just read. +// - `MXML_SAX_EVENT_DIRECTIVE`: A processing directive/instruction was just read. +// - `MXML_SAX_EVENT_ELEMENT_CLOSE` - A close element was just read \(``) +// - `MXML_SAX_EVENT_ELEMENT_OPEN` - An open element was just read \(``) +// +// Elements are *released* after the close element is processed. All other nodes +// are released after they are processed. The SAX callback can *retain* the node +// using the [mxmlRetain](@@) function. +// + +void +mxmlOptionsSetSAXCallback( + mxml_options_t *options, // I - Options + mxml_sax_cb_t cb, // I - SAX callback function + void *cbdata) // I - SAX callback data +{ + if (options) + { + options->sax_cb = cb; + options->sax_cbdata = cbdata; + } +} + + +// +// 'mxmlOptionsSetTypeCallback()' - Set the type callback for child/value nodes. +// +// The load callback function `cb` is called to obtain the node type child/value +// nodes and receives the `cbdata` pointer and the `mxml_node_t` pointer, for +// example: +// +// ```c +// mxml_type_t +// my_type_cb(void *cbdata, mxml_node_t *node) +// { +// const char *type; +// +// /* +// * You can lookup attributes and/or use the element name, +// * hierarchy, etc... +// */ +// +// type = mxmlElementGetAttr(node, "type"); +// if (type == NULL) +// type = mxmlGetElement(node); +// if (type == NULL) +// type = "text"; +// +// if (!strcmp(type, "integer")) +// return (MXML_TYPE_INTEGER); +// else if (!strcmp(type, "opaque")) +// return (MXML_TYPE_OPAQUE); +// else if (!strcmp(type, "real")) +// return (MXML_TYPE_REAL); +// else +// return (MXML_TYPE_TEXT); +// } +// ``` +// + +void +mxmlOptionsSetTypeCallback( + mxml_options_t *options, // I - Options + mxml_type_cb_t cb, // I - Type callback function + void *cbdata) // I - Type callback data +{ + if (options) + { + options->type_cb = cb; + options->type_cbdata = cbdata; + } +} + + +// +// 'mxmlOptionsSetTypeValue()' - Set the type to use for all child/value nodes. +// +// This functions sets a constant node type to use for all child/value nodes. +// + +void +mxmlOptionsSetTypeValue( + mxml_options_t *options, // I - Options + mxml_type_t type) // I - Value node type +{ + if (options) + { + options->type_cb = NULL; + options->type_value = type; + } +} + + +// +// 'mxmlOptionsSetWhitespaceCallback()' - Set the whitespace callback. +// +// This function sets the whitespace callback that is used when saving XML data. +// The callback function `cb` specifies a function that returns a whitespace +// string or `NULL` before and after each element. The function receives the +// callback data pointer `cbdata`, the `mxml_node_t` pointer, and a "when" +// value indicating where the whitespace is being added, for example: +// +// ```c +// const char *my_whitespace_cb(void *cbdata, mxml_node_t *node, mxml_ws_t when) +// { +// if (when == MXML_WS_BEFORE_OPEN || when == MXML_WS_AFTER_CLOSE) +// return ("\n"); +// else +// return (NULL); +// } +// ``` +// + +void +mxmlOptionsSetWhitespaceCallback( + mxml_options_t *options, // I - Options + mxml_ws_cb_t cb, // I - Whitespace callback function + void *cbdata) // I - Whitespace callback data +{ + if (options) + { + options->ws_cb = cb; + options->ws_cbdata = cbdata; + } +} + + +// +// 'mxmlOptionsSetWrapMargin()' - Set the wrap margin when saving XML data. +// +// This function sets the wrap margin used when saving XML data. Wrapping is +// disabled when `column` is `0`. +// + +void +mxmlOptionsSetWrapMargin( + mxml_options_t *options, // I - Options + int column) // I - Wrap column +{ + if (options) + options->wrap = column; +} + + +// +// '_mxml_entity_string()' - Get the entity that corresponds to the character, if any. +// + +const char * // O - Entity or `NULL` for none +_mxml_entity_string(int ch) // I - Character +{ + switch (ch) + { + case '&' : + return ("&"); + + case '<' : + return ("<"); + + case '>' : + return (">"); + + case '\"' : + return ("""); + + default : + return (NULL); + } +} + + +// +// '_mxml_entity_value()' - Get the character corresponding to a named entity. +// +// The entity name can also be a numeric constant. `-1` is returned if the +// name is not known. +// + +int // O - Unicode character +_mxml_entity_value( + mxml_options_t *options, // I - Options + const char *name) // I - Entity name +{ + int ch = -1; // Unicode character + + + if (!name) + { + // No name... + return (-1); + } + else if (*name == '#') + { + // Numeric entity... + if (name[1] == 'x') + ch = (int)strtol(name + 2, NULL, 16); + else + ch = (int)strtol(name + 1, NULL, 10); + } + else if (!strcmp(name, "amp")) + { + // Ampersand + ch = '&'; + } + else if (!strcmp(name, "gt")) + { + // Greater than + ch = '>'; + } + else if (!strcmp(name, "lt")) + { + // Less than + ch = '<'; + } + else if (!strcmp(name, "quot")) + { + // Double quote + ch = '\"'; + } + else if (options && options->entity_cb) + { + // Use callback + ch = (options->entity_cb)(options->entity_cbdata, name); + } + + return (ch); +} + + +// +// '_mxml_error()' - Display an error message. +// + +void +_mxml_error(mxml_options_t *options, // I - Load/save options + const char *format, // I - Printf-style format string + ...) // I - Additional arguments as needed +{ + va_list ap; // Pointer to arguments + char s[1024]; // Message string + + + // Range check input... + if (!format) + return; + + // Format the error message string... + va_start(ap, format); + vsnprintf(s, sizeof(s), format, ap); + va_end(ap); + + // And then display the error message... + if (options->error_cb) + (options->error_cb)(options->error_cbdata, s); + else + fprintf(stderr, "%s\n", s); +} diff --git a/src/main/mxml/mxml-private.c b/src/main/mxml/mxml-private.c new file mode 100644 index 00000000..2c26f106 --- /dev/null +++ b/src/main/mxml/mxml-private.c @@ -0,0 +1,280 @@ +// +// Private functions for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// Some crazy people think that unloading a shared object is a good or safe +// thing to do. Unfortunately, most objects are simply *not* safe to unload +// and bad things *will* happen. +// +// The following mess of conditional code allows us to provide a destructor +// function in Mini-XML for our thread-global storage so that it can possibly +// be unloaded safely, although since there is no standard way to do so I +// can't even provide any guarantees that you can do it safely on all platforms. +// +// This code currently supports AIX, HP-UX, Linux, macOS, Solaris, and +// Windows. It might work on the BSDs and IRIX, but I haven't tested that. +// + +#if defined(__sun) || defined(_AIX) +# pragma fini(_mxml_fini) +# define _MXML_FINI _mxml_fini +#elif defined(__hpux) +# pragma FINI _mxml_fini +# define _MXML_FINI _mxml_fini +#elif defined(__GNUC__) // Linux and macOS +# define _MXML_FINI __attribute((destructor)) _mxml_fini +#else +# define _MXML_FINI _fini +#endif // __sun + + +// +// 'mxmlSetStringCallbacks()' - Set the string copy/free callback functions. +// +// This function sets the string copy/free callback functions for the current +// thread. The `strcopy_cb` function makes a copy of the provided string while +// the `strfree_cb` function frees the copy. Each callback accepts the +// `str_cbdata` pointer along with the pointer to the string: +// +// ```c +// char *my_strcopy_cb(void *cbdata, const char *s) +// { +// ... make a copy of "s" ... +// } +// +// void my_strfree_cb(void *cbdata, char *s) +// { +// ... release the memory used by "s" ... +// } +// ``` +// +// The default `strcopy_cb` function calls `strdup` while the default +// `strfree_cb` function calls `free`. +// + +void +mxmlSetStringCallbacks( + mxml_strcopy_cb_t strcopy_cb, // I - String copy callback function + mxml_strfree_cb_t strfree_cb, // I - String free callback function + void *str_cbdata) // I - String callback data +{ + _mxml_global_t *global = _mxml_global(); + // Global data + + + global->strcopy_cb = strcopy_cb; + global->strfree_cb = strfree_cb; + global->str_cbdata = str_cbdata; +} + + +// +// '_mxml_strcopy()' - Copy a string. +// + +char * // O - Copy of string +_mxml_strcopy(const char *s) // I - String +{ + _mxml_global_t *global = _mxml_global(); + // Global data + + + if (!s) + return (NULL); + + if (global->strcopy_cb) + return ((global->strcopy_cb)(global->str_cbdata, s)); + else + return (strdup(s)); +} + + +// +// '_mxml_strfree()' - Free a string. +// + +void +_mxml_strfree(char *s) // I - String +{ + _mxml_global_t *global = _mxml_global(); + // Global data + + + if (!s) + return; + + if (global->strfree_cb) + (global->strfree_cb)(global->str_cbdata, s); + else + free((void *)s); +} + + +#ifdef HAVE_PTHREAD_H // POSIX threading +# include + +static int _mxml_initialized = 0; + // Have we been initialized? +static pthread_key_t _mxml_key; // Thread local storage key +static pthread_once_t _mxml_key_once = PTHREAD_ONCE_INIT; + // One-time initialization object +static void _mxml_init(void); +static void _mxml_destructor(void *g); + + +// +// '_mxml_destructor()' - Free memory used for globals... +// + +static void +_mxml_destructor(void *g) // I - Global data +{ + free(g); +} + + +// +// '_mxml_fini()' - Clean up when unloaded. +// + +static void +_MXML_FINI(void) +{ + if (_mxml_initialized) + pthread_key_delete(_mxml_key); +} + + +// +// '_mxml_global()' - Get global data. +// + +_mxml_global_t * // O - Global data +_mxml_global(void) +{ + _mxml_global_t *global; // Global data + + + pthread_once(&_mxml_key_once, _mxml_init); + + if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) == NULL) + { + global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t)); + pthread_setspecific(_mxml_key, global); + } + + return (global); +} + + +// +// '_mxml_init()' - Initialize global data... +// + +static void +_mxml_init(void) +{ + _mxml_initialized = 1; + pthread_key_create(&_mxml_key, _mxml_destructor); +} + + +#elif defined(_WIN32) && defined(MXML1_EXPORTS) // WIN32 threading +# include + +static DWORD _mxml_tls_index; // Index for global storage + + +// +// 'DllMain()' - Main entry for library. +// + +BOOL WINAPI // O - Success/failure +DllMain(HINSTANCE hinst, // I - DLL module handle + DWORD reason, // I - Reason + LPVOID reserved) // I - Unused +{ + _mxml_global_t *global; // Global data + + + (void)hinst; + (void)reserved; + + switch (reason) + { + case DLL_PROCESS_ATTACH : // Called on library initialization + if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) + return (FALSE); + break; + + case DLL_THREAD_DETACH : // Called when a thread terminates + if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL) + free(global); + break; + + case DLL_PROCESS_DETACH : // Called when library is unloaded + if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL) + free(global); + + TlsFree(_mxml_tls_index); + break; + + default: + break; + } + + return (TRUE); +} + + +// +// '_mxml_global()' - Get global data. +// + +_mxml_global_t * // O - Global data +_mxml_global(void) +{ + _mxml_global_t *global; // Global data + + + if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) == NULL) + { + global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t)); + + TlsSetValue(_mxml_tls_index, (LPVOID)global); + } + + return (global); +} + + +#else // No threading +// +// '_mxml_global()' - Get global data. +// + +_mxml_global_t * // O - Global data +_mxml_global(void) +{ + static _mxml_global_t global = // Global data + { + NULL, // strcopy_cb + NULL, // strfree_cb + NULL, // str_cbdata + }; + + + return (&global); +} +#endif // HAVE_PTHREAD_H diff --git a/src/main/mxml/mxml-private.h b/src/main/mxml/mxml-private.h new file mode 100644 index 00000000..b2346e1e --- /dev/null +++ b/src/main/mxml/mxml-private.h @@ -0,0 +1,140 @@ +// +// Private definitions for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#ifndef MXML_PRIVATE_H +# define MXML_PRIVATE_H +# include "config.h" +# include "mxml.h" +# include + + +// +// Private macros... +// + +# ifdef DEBUG +# define MXML_DEBUG(...) fprintf(stderr, __VA_ARGS__) +# else +# define MXML_DEBUG(...) +# endif // DEBUG +# ifndef MXML_ALLOC_SIZE +# define MXML_ALLOC_SIZE 16 // Allocation increment +# endif // !MXML_ALLOC_SIZE +# define MXML_TAB 8 // Tabs every N columns + + +// +// Private structures... +// + +typedef struct _mxml_attr_s // An XML element attribute value. +{ + char *name; // Attribute name + char *value; // Attribute value +} _mxml_attr_t; + +typedef struct _mxml_element_s // An XML element value. +{ + char *name; // Name of element + size_t num_attrs; // Number of attributes + _mxml_attr_t *attrs; // Attributes +} _mxml_element_t; + +typedef struct _mxml_text_s // An XML text value. +{ + bool whitespace; // Leading whitespace? + char *string; // Fragment string +} _mxml_text_t; + +typedef struct _mxml_custom_s // An XML custom value. +{ + void *data; // Pointer to (allocated) custom data + mxml_custfree_cb_t free_cb; // Free callback function + void *free_cbdata; // Free callback data +} _mxml_custom_t; + +typedef union _mxml_value_u // An XML node value. +{ + char *cdata; // CDATA string + char *comment; // Common string + char *declaration; // Declaration string + char *directive; // Processing instruction string + _mxml_element_t element; // Element + long integer; // Integer number + char *opaque; // Opaque string + double real; // Real number + _mxml_text_t text; // Text fragment + _mxml_custom_t custom; // Custom data +} _mxml_value_t; + +struct _mxml_node_s // An XML node. +{ + mxml_type_t type; // Node type + struct _mxml_node_s *next; // Next node under same parent + struct _mxml_node_s *prev; // Previous node under same parent + struct _mxml_node_s *parent; // Parent node + struct _mxml_node_s *child; // First child node + struct _mxml_node_s *last_child; // Last child node + _mxml_value_t value; // Node value + size_t ref_count; // Use count + void *user_data; // User data +}; + +typedef struct _mxml_global_s // Global, per-thread data +{ + mxml_strcopy_cb_t strcopy_cb; // String copy callback function + mxml_strfree_cb_t strfree_cb; // String free callback function + void *str_cbdata; // String callback data +} _mxml_global_t; + +struct _mxml_index_s // An XML node index. +{ + char *attr; // Attribute used for indexing or NULL + size_t num_nodes; // Number of nodes in index + size_t alloc_nodes; // Allocated nodes in index + size_t cur_node; // Current node + mxml_node_t **nodes; // Node array +}; + +struct _mxml_options_s // XML options +{ + struct lconv *loc; // Locale data + size_t loc_declen; // Length of decimal point string + mxml_custload_cb_t custload_cb; // Custom load callback function + mxml_custsave_cb_t custsave_cb; // Custom save callback function + void *cust_cbdata; // Custom callback data + mxml_entity_cb_t entity_cb; // Entity callback function + void *entity_cbdata; // Entity callback data + mxml_error_cb_t error_cb; // Error callback function + void *error_cbdata; // Error callback data + mxml_sax_cb_t sax_cb; // SAX callback function + void *sax_cbdata; // SAX callback data + mxml_type_cb_t type_cb; // Type callback function + void *type_cbdata; // Type callback data + mxml_type_t type_value; // Fixed type value (if no type callback) + int wrap; // Wrap margin + mxml_ws_cb_t ws_cb; // Whitespace callback function + void *ws_cbdata; // Whitespace callback data +}; + + +// +// Private functions... +// + +extern _mxml_global_t *_mxml_global(void); +extern const char *_mxml_entity_string(int ch); +extern int _mxml_entity_value(mxml_options_t *options, const char *name); +extern void _mxml_error(mxml_options_t *options, const char *format, ...) MXML_FORMAT(2,3); +extern char *_mxml_strcopy(const char *s); +extern void _mxml_strfree(char *s); + +#endif // !MXML_PRIVATE_H diff --git a/src/main/mxml/mxml-search.c b/src/main/mxml/mxml-search.c new file mode 100644 index 00000000..d9a47685 --- /dev/null +++ b/src/main/mxml/mxml-search.c @@ -0,0 +1,237 @@ +// +// Search/navigation functions for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// 'mxmlFindElement()' - Find the named element. +// +// This function finds the named element `element` in XML tree `top` starting at +// node `node`. The search is constrained by element name `element`, attribute +// name `attr`, and attribute value `value` - `NULL` names or values are treated +// as wildcards, so different kinds of searches can be implemented by looking +// for all elements of a given name or all elements with a specific attribute. +// +// The `descend` argument determines whether the search descends into child +// nodes; normally you will use `MXML_DESCEND_FIRST` for the initial search and +// `MXML_DESCEND_NONE` to find additional direct descendents of the node. +// + +mxml_node_t * // O - Element node or `NULL` +mxmlFindElement(mxml_node_t *node, // I - Current node + mxml_node_t *top, // I - Top node + const char *element,// I - Element name or `NULL` for any + const char *attr, // I - Attribute name, or `NULL` for none + const char *value, // I - Attribute value, or `NULL` for any + mxml_descend_t descend) // I - Descend into tree - `MXML_DESCEND_ALL`, `MXML_DESCEND_NONE`, or `MXML_DESCEND_FIRST` +{ + const char *temp; // Current attribute value + + // Range check input... + if (!node || !top || (!attr && value)) + return (NULL); + + // Start with the next node... + node = mxmlWalkNext(node, top, descend); + + // Loop until we find a matching element... + while (node != NULL) + { + // See if this node matches... + if (node->type == MXML_TYPE_ELEMENT && node->value.element.name && (!element || !strcmp(node->value.element.name, element))) + { + // See if we need to check for an attribute... + if (!attr) + return (node); // No attribute search, return it... + + // Check for the attribute... + if ((temp = mxmlElementGetAttr(node, attr)) != NULL) + { + // OK, we have the attribute, does it match? + if (!value || !strcmp(value, temp)) + return (node); // Yes, return it... + } + } + + // No match, move on to the next node... + if (descend == MXML_DESCEND_ALL) + node = mxmlWalkNext(node, top, MXML_DESCEND_ALL); + else + node = node->next; + } + + return (NULL); +} + + +// +// 'mxmlFindPath()' - Find a node with the given path. +// +// This function finds a node in XML tree `top` using a slash-separated list of +// element names in `path`. The name "*" is considered a wildcard for one or +// more levels of elements, for example, "foo/one/two", "bar/two/one", "*\/one", +// and so forth. +// +// The first child node of the found node is returned if the given node has +// children and the first child is a value node. +// + +mxml_node_t * // O - Found node or `NULL` +mxmlFindPath(mxml_node_t *top, // I - Top node + const char *path) // I - Path to element +{ + mxml_node_t *node; // Current node + char element[256]; // Current element name + const char *pathsep; // Separator in path + mxml_descend_t descend; // mxmlFindElement option + + + // Range check input... + if (!top || !path || !*path) + return (NULL); + + // Search each element in the path... + node = top; + while (*path) + { + // Handle wildcards... + if (!strncmp(path, "*/", 2)) + { + path += 2; + descend = MXML_DESCEND_ALL; + } + else + { + descend = MXML_DESCEND_FIRST; + } + + // Get the next element in the path... + if ((pathsep = strchr(path, '/')) == NULL) + pathsep = path + strlen(path); + + if (pathsep == path || (size_t)(pathsep - path) >= sizeof(element)) + return (NULL); + + memcpy(element, path, pathsep - path); + element[pathsep - path] = '\0'; + + if (*pathsep) + path = pathsep + 1; + else + path = pathsep; + + // Search for the element... + if ((node = mxmlFindElement(node, node, element, NULL, NULL, descend)) == NULL) + return (NULL); + } + + // If we get this far, return the node or its first child... + // if (node->child && node->child->type != MXML_TYPE_ELEMENT) + // return (node->child); + // else + return (node); +} + + +// +// 'mxmlWalkNext()' - Walk to the next logical node in the tree. +// +// This function walks to the next logical node in the tree. The `descend` +// argument controls whether the first child is considered to be the next node. +// The `top` argument constrains the walk to that node's children. +// + +mxml_node_t * // O - Next node or `NULL` +mxmlWalkNext(mxml_node_t *node, // I - Current node + mxml_node_t *top, // I - Top node + mxml_descend_t descend) // I - Descend into tree - `MXML_DESCEND_ALL`, `MXML_DESCEND_NONE`, or `MXML_DESCEND_FIRST` +{ + if (!node) + { + return (NULL); + } + else if (node->child && descend != MXML_DESCEND_NONE) + { + return (node->child); + } + else if (node == top) + { + return (NULL); + } + else if (node->next) + { + return (node->next); + } + else if (node->parent && node->parent != top) + { + node = node->parent; + + while (!node->next) + { + if (node->parent == top || !node->parent) + return (NULL); + else + node = node->parent; + } + + return (node->next); + } + else + { + return (NULL); + } +} + + +// +// 'mxmlWalkPrev()' - Walk to the previous logical node in the tree. +// +// This function walks to the previous logical node in the tree. The `descend` +// argument controls whether the first child is considered to be the next node. +// The `top` argument constrains the walk to that node's children. +// + +mxml_node_t * // O - Previous node or `NULL` +mxmlWalkPrev(mxml_node_t *node, // I - Current node + mxml_node_t *top, // I - Top node + mxml_descend_t descend) // I - Descend into tree - `MXML_DESCEND_ALL`, `MXML_DESCEND_NONE`, or `MXML_DESCEND_FIRST` +{ + if (!node || node == top) + { + return (NULL); + } + else if (node->prev) + { + if (node->prev->last_child && descend != MXML_DESCEND_NONE) + { + // Find the last child under the previous node... + node = node->prev->last_child; + + while (node->last_child) + node = node->last_child; + + return (node); + } + else + { + return (node->prev); + } + } + else if (node->parent != top) + { + return (node->parent); + } + else + { + return (NULL); + } +} diff --git a/src/main/mxml/mxml-set.c b/src/main/mxml/mxml-set.c new file mode 100644 index 00000000..79b62188 --- /dev/null +++ b/src/main/mxml/mxml-set.c @@ -0,0 +1,630 @@ +// +// Node set functions for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#include "mxml-private.h" + + +// +// 'mxmlSetCDATA()' - Set the data for a CDATA node. +// +// This function sets the value string for a CDATA node. The node is not +// changed if it (or its first child) is not a CDATA node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetCDATA(mxml_node_t *node, // I - Node to set + const char *data) // I - New data string +{ + char *s; // New element name + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CDATA) + node = node->child; + + if (!node || node->type != MXML_TYPE_CDATA) + return (false); + else if (!data) + return (false); + + if (data == node->value.cdata) + { + // Don't change the value... + return (true); + } + + // Allocate the new value, free any old element value, and set the new value... + if ((s = _mxml_strcopy(data)) == NULL) + return (false); + + _mxml_strfree(node->value.cdata); + node->value.cdata = s; + + return (true); +} + + +// +// 'mxmlSetCDATAf()' - Set the data for a CDATA to a formatted string. +// +// This function sets the formatted string value of a CDATA node. The node is +// not changed if it (or its first child) is not a CDATA node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetCDATAf(mxml_node_t *node, // I - Node + const char *format, // I - `printf`-style format string + ...) // I - Additional arguments as needed +{ + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + char *s; // Temporary string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CDATA) + node = node->child; + + if (!node || node->type != MXML_TYPE_CDATA) + return (false); + else if (!format) + return (false); + + // Format the new string, free any old string value, and set the new value... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + if ((s = _mxml_strcopy(buffer)) == NULL) + return (false); + + _mxml_strfree(node->value.cdata); + node->value.cdata = s; + + return (true); +} + + +// +// 'mxmlSetComment()' - Set a comment to a literal string. +// +// This function sets the string value of a comment node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetComment(mxml_node_t *node, // I - Node + const char *comment) // I - Literal string +{ + char *s; // New string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_COMMENT) + node = node->child; + + if (!node || node->type != MXML_TYPE_COMMENT) + return (false); + else if (!comment) + return (false); + + if (comment == node->value.comment) + return (true); + + // Free any old string value and set the new value... + if ((s = _mxml_strcopy(comment)) == NULL) + return (false); + + _mxml_strfree(node->value.comment); + node->value.comment = s; + + return (true); +} + + +// +// 'mxmlSetCommentf()' - Set a comment to a formatted string. +// +// This function sets the formatted string value of a comment node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetCommentf(mxml_node_t *node, // I - Node + const char *format, // I - `printf`-style format string + ...) // I - Additional arguments as needed +{ + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + char *s; // Temporary string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_COMMENT) + node = node->child; + + if (!node || node->type != MXML_TYPE_COMMENT) + return (false); + else if (!format) + return (false); + + // Format the new string, free any old string value, and set the new value... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + if ((s = _mxml_strcopy(buffer)) == NULL) + return (false); + + _mxml_strfree(node->value.comment); + node->value.comment = s; + + return (true); +} + + +// +// 'mxmlSetCustom()' - Set the data and destructor of a custom data node. +// +// This function sets the data pointer `data` and destructor callback +// `destroy_cb` of a custom data node. The node is not changed if it (or its +// first child) is not a custom node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetCustom( + mxml_node_t *node, // I - Node to set + void *data, // I - New data pointer + mxml_custfree_cb_t free_cb, // I - Free callback function + void *free_cbdata) // I - Free callback data +{ + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CUSTOM) + node = node->child; + + if (!node || node->type != MXML_TYPE_CUSTOM) + return (false); + + if (data == node->value.custom.data) + goto set_free_callback; + + // Free any old element value and set the new value... + if (node->value.custom.data && node->value.custom.free_cb) + (node->value.custom.free_cb)(node->value.custom.free_cbdata, node->value.custom.data); + + node->value.custom.data = data; + + set_free_callback: + + node->value.custom.free_cb = free_cb; + node->value.custom.free_cbdata = free_cbdata; + + return (true); +} + + +// +// 'mxmlSetDeclaration()' - Set a declaration to a literal string. +// +// This function sets the string value of a declaration node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetDeclaration( + mxml_node_t *node, // I - Node + const char *declaration) // I - Literal string +{ + char *s; // New string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_DECLARATION) + node = node->child; + + if (!node || node->type != MXML_TYPE_DECLARATION) + return (false); + else if (!declaration) + return (false); + + if (declaration == node->value.declaration) + return (true); + + // Free any old string value and set the new value... + if ((s = _mxml_strcopy(declaration)) == NULL) + return (false); + + _mxml_strfree(node->value.declaration); + node->value.declaration = s; + + return (true); +} + + +// +// 'mxmlSetDeclarationf()' - Set a declaration to a formatted string. +// +// This function sets the formatted string value of a declaration node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetDeclarationf(mxml_node_t *node, // I - Node + const char *format, // I - `printf`-style format string + ...) // I - Additional arguments as needed +{ + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + char *s; // Temporary string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_DECLARATION) + node = node->child; + + if (!node || node->type != MXML_TYPE_DECLARATION) + return (false); + else if (!format) + return (false); + + // Format the new string, free any old string value, and set the new value... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + if ((s = _mxml_strcopy(buffer)) == NULL) + return (false); + + _mxml_strfree(node->value.declaration); + node->value.declaration = s; + + return (true); +} + + +// +// 'mxmlSetDirective()' - Set a processing instruction to a literal string. +// +// This function sets the string value of a processing instruction node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetDirective(mxml_node_t *node, // I - Node + const char *directive)// I - Literal string +{ + char *s; // New string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_DIRECTIVE) + node = node->child; + + if (!node || node->type != MXML_TYPE_DIRECTIVE) + return (false); + else if (!directive) + return (false); + + if (directive == node->value.directive) + return (true); + + // Free any old string value and set the new value... + if ((s = _mxml_strcopy(directive)) == NULL) + return (false); + + _mxml_strfree(node->value.directive); + node->value.directive = s; + + return (true); +} + + +// +// 'mxmlSetDirectivef()' - Set a processing instruction to a formatted string. +// +// This function sets the formatted string value of a processing instruction +// node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetDirectivef(mxml_node_t *node, // I - Node + const char *format, // I - `printf`-style format string + ...) // I - Additional arguments as needed +{ + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + char *s; // Temporary string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_DIRECTIVE) + node = node->child; + + if (!node || node->type != MXML_TYPE_DIRECTIVE) + return (false); + else if (!format) + return (false); + + // Format the new string, free any old string value, and set the new value... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + if ((s = _mxml_strcopy(buffer)) == NULL) + return (false); + + _mxml_strfree(node->value.directive); + node->value.directive = s; + + return (true); +} + + +// +// 'mxmlSetElement()' - Set the name of an element node. +// +// This function sets the name of an element node. The node is not changed if +// it is not an element node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetElement(mxml_node_t *node, // I - Node to set + const char *name) // I - New name string +{ + char *s; // New name string + + + // Range check input... + if (!node || node->type != MXML_TYPE_ELEMENT) + return (false); + else if (!name) + return (false); + + if (name == node->value.element.name) + return (true); + + // Free any old element value and set the new value... + if ((s = _mxml_strcopy(name)) == NULL) + return (false); + + _mxml_strfree(node->value.element.name); + node->value.element.name = s; + + return (true); +} + + +// +// 'mxmlSetInteger()' - Set the value of an integer node. +// +// This function sets the value of an integer node. The node is not changed if +// it (or its first child) is not an integer node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetInteger(mxml_node_t *node, // I - Node to set + long integer) // I - Integer value +{ + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_INTEGER) + node = node->child; + + if (!node || node->type != MXML_TYPE_INTEGER) + return (false); + + // Set the new value and return... + node->value.integer = integer; + + return (true); +} + + +// +// 'mxmlSetOpaque()' - Set the value of an opaque node. +// +// This function sets the string value of an opaque node. The node is not +// changed if it (or its first child) is not an opaque node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetOpaque(mxml_node_t *node, // I - Node to set + const char *opaque) // I - Opaque string +{ + char *s; // New opaque string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_OPAQUE) + node = node->child; + + if (!node || node->type != MXML_TYPE_OPAQUE) + return (false); + else if (!opaque) + return (false); + + if (node->value.opaque == opaque) + return (true); + + // Free any old opaque value and set the new value... + if ((s = _mxml_strcopy(opaque)) == NULL) + return (false); + + _mxml_strfree(node->value.opaque); + node->value.opaque = s; + + return (true); +} + + +// +// 'mxmlSetOpaquef()' - Set the value of an opaque string node to a formatted string. +// +// This function sets the formatted string value of an opaque node. The node is +// not changed if it (or its first child) is not an opaque node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetOpaquef(mxml_node_t *node, // I - Node to set + const char *format, // I - Printf-style format string + ...) // I - Additional arguments as needed +{ + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + char *s; // Temporary string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_OPAQUE) + node = node->child; + + if (!node || node->type != MXML_TYPE_OPAQUE) + return (false); + else if (!format) + return (false); + + // Format the new string, free any old string value, and set the new value... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + if ((s = _mxml_strcopy(buffer)) == NULL) + return (false); + + _mxml_strfree(node->value.opaque); + node->value.opaque = s; + + return (true); +} + + +// +// 'mxmlSetReal()' - Set the value of a real value node. +// +// This function sets the value of a real value node. The node is not changed +// if it (or its first child) is not a real value node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetReal(mxml_node_t *node, // I - Node to set + double real) // I - Real number value +{ + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_REAL) + node = node->child; + + if (!node || node->type != MXML_TYPE_REAL) + return (false); + + // Set the new value and return... + node->value.real = real; + + return (true); +} + + +// +// 'mxmlSetText()' - Set the value of a text node. +// +// This function sets the string and whitespace values of a text node. The node +// is not changed if it (or its first child) is not a text node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetText(mxml_node_t *node, // I - Node to set + bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace + const char *string) // I - String +{ + char *s; // New string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_TEXT) + node = node->child; + + if (!node || node->type != MXML_TYPE_TEXT) + return (false); + else if (!string) + return (false); + + if (string == node->value.text.string) + { + node->value.text.whitespace = whitespace; + return (true); + } + + // Free any old string value and set the new value... + if ((s = _mxml_strcopy(string)) == NULL) + return (false); + + _mxml_strfree(node->value.text.string); + + node->value.text.whitespace = whitespace; + node->value.text.string = s; + + return (true); +} + + +// +// 'mxmlSetTextf()' - Set the value of a text node to a formatted string. +// +// This function sets the formatted string and whitespace values of a text node. +// The node is not changed if it (or its first child) is not a text node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetTextf(mxml_node_t *node, // I - Node to set + bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace + const char *format, // I - Printf-style format string + ...) // I - Additional arguments as needed +{ + va_list ap; // Pointer to arguments + char buffer[16384]; // Format buffer + char *s; // Temporary string + + + // Range check input... + if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_TEXT) + node = node->child; + + if (!node || node->type != MXML_TYPE_TEXT) + return (false); + else if (!format) + return (false); + + // Free any old string value and set the new value... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + if ((s = _mxml_strcopy(buffer)) == NULL) + return (false); + + _mxml_strfree(node->value.text.string); + + node->value.text.whitespace = whitespace; + node->value.text.string = s; + + return (true); +} + + +// +// 'mxmlSetUserData()' - Set the user data pointer for a node. +// + +bool // O - `true` on success, `false` on failure +mxmlSetUserData(mxml_node_t *node, // I - Node to set + void *data) // I - User data pointer +{ + // Range check input... + if (!node) + return (false); + + // Set the user data pointer and return... + node->user_data = data; + return (true); +} diff --git a/src/main/mxml/mxml.h b/src/main/mxml/mxml.h new file mode 100644 index 00000000..b97f4460 --- /dev/null +++ b/src/main/mxml/mxml.h @@ -0,0 +1,250 @@ +// +// Header file for Mini-XML, a small XML file parsing library. +// +// https://www.msweet.org/mxml +// +// Copyright © 2003-2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// + +#ifndef MXML_H +# define MXML_H +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif // __cplusplus + + +// +// Constants... +// + +# define MXML_MAJOR_VERSION 4 // Major version number +# define MXML_MINOR_VERSION 0 // Minor version number + +# ifdef __GNUC__ +# define MXML_FORMAT(a,b) __attribute__ ((__format__ (__printf__, a, b))) +# else +# define MXML_FORMAT(a,b) +# endif // __GNUC__ + + +// +// Data types... +// + +typedef enum mxml_add_e // @link mxmlAdd@ add values +{ + MXML_ADD_BEFORE, // Add node before specified node + MXML_ADD_AFTER // Add node after specified node +} mxml_add_t; + +typedef enum mxml_descend_e // @link mxmlFindElement@, @link mxmlWalkNext@, and @link mxmlWalkPrev@ descend values +{ + MXML_DESCEND_FIRST = -1, // Descend for first find + MXML_DESCEND_NONE = 0, // Don't descend when finding/walking + MXML_DESCEND_ALL = 1 // Descend when finding/walking +} mxml_descend_t; + +typedef enum mxml_sax_event_e // SAX event type. +{ + MXML_SAX_EVENT_CDATA, // CDATA node + MXML_SAX_EVENT_COMMENT, // Comment node + MXML_SAX_EVENT_DATA, // Data node + MXML_SAX_EVENT_DECLARATION, // Declaration node + MXML_SAX_EVENT_DIRECTIVE, // Processing instruction node + MXML_SAX_EVENT_ELEMENT_CLOSE, // Element closed + MXML_SAX_EVENT_ELEMENT_OPEN // Element opened +} mxml_sax_event_t; + +typedef enum mxml_type_e // The XML node type. +{ + MXML_TYPE_IGNORE = -1, // Ignore/throw away node + MXML_TYPE_CDATA, // CDATA value ("<[CDATA[...]]>") + MXML_TYPE_COMMENT, // Comment ("") + MXML_TYPE_DECLARATION, // Declaration ("") + MXML_TYPE_DIRECTIVE, // Processing instruction ("") + MXML_TYPE_ELEMENT, // XML element with attributes + MXML_TYPE_INTEGER, // Integer value + MXML_TYPE_OPAQUE, // Opaque string + MXML_TYPE_REAL, // Real value + MXML_TYPE_TEXT, // Text fragment + MXML_TYPE_CUSTOM // Custom data +} mxml_type_t; + +typedef enum mxml_ws_e // Whitespace periods +{ + MXML_WS_BEFORE_OPEN, // Callback for before open tag + MXML_WS_AFTER_OPEN, // Callback for after open tag + MXML_WS_BEFORE_CLOSE, // Callback for before close tag + MXML_WS_AFTER_CLOSE, // Callback for after close tag +} mxml_ws_t; + +typedef void (*mxml_error_cb_t)(void *cbdata, const char *message); + // Error callback function + +typedef struct _mxml_node_s mxml_node_t;// An XML node + +typedef struct _mxml_index_s mxml_index_t; + // An XML node index + +typedef struct _mxml_options_s mxml_options_t; + // XML options + +typedef void (*mxml_custfree_cb_t)(void *cbdata, void *custdata); + // Custom data destructor + +typedef bool (*mxml_custload_cb_t)(void *cbdata, mxml_node_t *node, const char *s); + // Custom data load callback function + +typedef char *(*mxml_custsave_cb_t)(void *cbdata, mxml_node_t *node); + // Custom data save callback function + +typedef int (*mxml_entity_cb_t)(void *cbdata, const char *name); + // Entity callback function + +typedef size_t (*mxml_io_cb_t)(void *cbdata, void *buffer, size_t bytes); + // Read/write callback function + +typedef bool (*mxml_sax_cb_t)(void *cbdata, mxml_node_t *node, mxml_sax_event_t event); + // SAX callback function + +typedef char *(*mxml_strcopy_cb_t)(void *cbdata, const char *s); + // String copy/allocation callback +typedef void (*mxml_strfree_cb_t)(void *cbdata, char *s); + // String free callback + +typedef mxml_type_t (*mxml_type_cb_t)(void *cbdata, mxml_node_t *node); + // Type callback function + +typedef const char *(*mxml_ws_cb_t)(void *cbdata, mxml_node_t *node, mxml_ws_t when); + // Whitespace callback function + + + +// +// Prototypes... +// + +extern void mxmlAdd(mxml_node_t *parent, mxml_add_t add, mxml_node_t *child, mxml_node_t *node); + +extern void mxmlDelete(mxml_node_t *node); + +extern void mxmlElementClearAttr(mxml_node_t *node, const char *name); +extern const char *mxmlElementGetAttr(mxml_node_t *node, const char *name); +extern const char *mxmlElementGetAttrByIndex(mxml_node_t *node, size_t idx, const char **name); +extern size_t mxmlElementGetAttrCount(mxml_node_t *node); +extern void mxmlElementSetAttr(mxml_node_t *node, const char *name, const char *value); +extern void mxmlElementSetAttrf(mxml_node_t *node, const char *name, const char *format, ...) MXML_FORMAT(3,4); + +extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top, const char *element, const char *attr, const char *value, mxml_descend_t descend); +extern mxml_node_t *mxmlFindPath(mxml_node_t *node, const char *path); + +extern const char *mxmlGetCDATA(mxml_node_t *node); +extern const char *mxmlGetComment(mxml_node_t *node); +extern const void *mxmlGetCustom(mxml_node_t *node); +extern const char *mxmlGetDeclaration(mxml_node_t *node); +extern const char *mxmlGetDirective(mxml_node_t *node); +extern const char *mxmlGetElement(mxml_node_t *node); +extern mxml_node_t *mxmlGetFirstChild(mxml_node_t *node); +extern long mxmlGetInteger(mxml_node_t *node); +extern mxml_node_t *mxmlGetLastChild(mxml_node_t *node); +extern mxml_node_t *mxmlGetNextSibling(mxml_node_t *node); +extern const char *mxmlGetOpaque(mxml_node_t *node); +extern mxml_node_t *mxmlGetParent(mxml_node_t *node); +extern mxml_node_t *mxmlGetPrevSibling(mxml_node_t *node); +extern double mxmlGetReal(mxml_node_t *node); +extern size_t mxmlGetRefCount(mxml_node_t *node); +extern const char *mxmlGetText(mxml_node_t *node, bool *whitespace); +extern mxml_type_t mxmlGetType(mxml_node_t *node); +extern void *mxmlGetUserData(mxml_node_t *node); + +extern void mxmlIndexDelete(mxml_index_t *ind); +extern mxml_node_t *mxmlIndexEnum(mxml_index_t *ind); +extern mxml_node_t *mxmlIndexFind(mxml_index_t *ind, const char *element, const char *value); +extern size_t mxmlIndexGetCount(mxml_index_t *ind); +extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element, const char *attr); +extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind); + +extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, mxml_options_t *options, int fd); +extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, mxml_options_t *options, FILE *fp); +extern mxml_node_t *mxmlLoadFilename(mxml_node_t *top, mxml_options_t *options, const char *filename); +extern mxml_node_t *mxmlLoadIO(mxml_node_t *top, mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata); +extern mxml_node_t *mxmlLoadString(mxml_node_t *top, mxml_options_t *options, const char *s); + +extern void mxmlOptionsDelete(mxml_options_t *options); +extern mxml_options_t *mxmlOptionsNew(void); +extern void mxmlOptionsSetCustomCallbacks(mxml_options_t *options, mxml_custload_cb_t load_cb, mxml_custsave_cb_t save_cb, void *cbdata); +extern void mxmlOptionsSetEntityCallback(mxml_options_t *options, mxml_entity_cb_t cb, void *cbdata); +extern void mxmlOptionsSetErrorCallback(mxml_options_t *options, mxml_error_cb_t cb, void *cbdata); +extern void mxmlOptionsSetSAXCallback(mxml_options_t *options, mxml_sax_cb_t cb, void *cbdata); +extern void mxmlOptionsSetTypeCallback(mxml_options_t *options, mxml_type_cb_t cb, void *cbdata); +extern void mxmlOptionsSetTypeValue(mxml_options_t *options, mxml_type_t type); +extern void mxmlOptionsSetWhitespaceCallback(mxml_options_t *options, mxml_ws_cb_t cb, void *cbdata); +extern void mxmlOptionsSetWrapMargin(mxml_options_t *options, int column); + +extern mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string); +extern mxml_node_t *mxmlNewCDATAf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3); +extern mxml_node_t *mxmlNewComment(mxml_node_t *parent, const char *comment); +extern mxml_node_t *mxmlNewCommentf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3); +extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data, mxml_custfree_cb_t free_cb, void *free_cbdata); +extern mxml_node_t *mxmlNewDeclaration(mxml_node_t *parent, const char *declaration); +extern mxml_node_t *mxmlNewDeclarationf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3); +extern mxml_node_t *mxmlNewDirective(mxml_node_t *parent, const char *directive); +extern mxml_node_t *mxmlNewDirectivef(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3); +extern mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name); +extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, long integer); +extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque); +extern mxml_node_t *mxmlNewOpaquef(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3); +extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real); +extern mxml_node_t *mxmlNewText(mxml_node_t *parent, bool whitespace, const char *string); +extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, bool whitespace, const char *format, ...) MXML_FORMAT(3,4); +extern mxml_node_t *mxmlNewXML(const char *version); + +extern int mxmlRelease(mxml_node_t *node); +extern void mxmlRemove(mxml_node_t *node); +extern int mxmlRetain(mxml_node_t *node); + +extern char *mxmlSaveAllocString(mxml_node_t *node, mxml_options_t *options); +extern bool mxmlSaveFd(mxml_node_t *node, mxml_options_t *options, int fd); +extern bool mxmlSaveFile(mxml_node_t *node, mxml_options_t *options, FILE *fp); +extern bool mxmlSaveFilename(mxml_node_t *node, mxml_options_t *options, const char *filename); +extern bool mxmlSaveIO(mxml_node_t *node, mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata); +extern size_t mxmlSaveString(mxml_node_t *node, mxml_options_t *options, char *buffer, size_t bufsize); + +extern bool mxmlSetCDATA(mxml_node_t *node, const char *data); +extern bool mxmlSetCDATAf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3); +extern bool mxmlSetComment(mxml_node_t *node, const char *comment); +extern bool mxmlSetCommentf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3); +extern bool mxmlSetDeclaration(mxml_node_t *node, const char *declaration); +extern bool mxmlSetDeclarationf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3); +extern bool mxmlSetDirective(mxml_node_t *node, const char *directive); +extern bool mxmlSetDirectivef(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3); +extern bool mxmlSetCustom(mxml_node_t *node, void *data, mxml_custfree_cb_t free_cb, void *free_cbdata); +extern bool mxmlSetElement(mxml_node_t *node, const char *name); +extern bool mxmlSetInteger(mxml_node_t *node, long integer); +extern bool mxmlSetOpaque(mxml_node_t *node, const char *opaque); +extern bool mxmlSetOpaquef(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3); +extern bool mxmlSetReal(mxml_node_t *node, double real); +extern void mxmlSetStringCallbacks(mxml_strcopy_cb_t strcopy_cb, mxml_strfree_cb_t strfree_cb, void *str_cbdata); +extern bool mxmlSetText(mxml_node_t *node, bool whitespace, const char *string); +extern bool mxmlSetTextf(mxml_node_t *node, bool whitespace, const char *format, ...) MXML_FORMAT(3,4); +extern bool mxmlSetUserData(mxml_node_t *node, void *data); + +extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top, mxml_descend_t descend); +extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, mxml_descend_t descend); + + +# ifdef __cplusplus +} +# endif // __cplusplus +#endif // !MXML_H diff --git a/src/main/p3io-ddr-tool/Module.mk b/src/main/p3io-ddr-tool/Module.mk index 2c76b428..7873a598 100644 --- a/src/main/p3io-ddr-tool/Module.mk +++ b/src/main/p3io-ddr-tool/Module.mk @@ -4,12 +4,14 @@ ldflags_p3io-ddr-tool := \ -lsetupapi \ libs_p3io-ddr-tool := \ + core \ extiodrv \ extio \ p3iodrv \ p3io \ hook \ util \ + iface-core \ src_p3io-ddr-tool := \ main.c \ diff --git a/src/main/p3io-ddr-tool/main.c b/src/main/p3io-ddr-tool/main.c index 939e1e77..0bac6620 100644 --- a/src/main/p3io-ddr-tool/main.c +++ b/src/main/p3io-ddr-tool/main.c @@ -7,15 +7,18 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + #include "extiodrv/extio.h" +#include "iface-core/log.h" + #include "p3io/ddr.h" #include "p3iodrv/ddr.h" #include "p3iodrv/device.h" -#include "util/log.h" -#include "util/thread.h" - #include "mode-test.h" enum mode { @@ -70,7 +73,7 @@ static mode_proc _mode_procs[MODE_TOTAL_COUNT] = { _mode_sensores, }; -static enum log_level _log_level = LOG_LEVEL_FATAL; +static enum core_log_bt_log_level _log_level = CORE_LOG_BT_LOG_LEVEL_FATAL; static bool _extio_enabled = true; static const char *_p3io_device_path = ""; static const char *_extio_com_port = "COM1"; @@ -196,11 +199,11 @@ static bool _process_cmd_args(int argc, char **argv) for (int i = 0; i < argc; i++) { if (!strcmp(argv[i], "-v")) { - _log_level = LOG_LEVEL_WARNING; + _log_level = CORE_LOG_BT_LOG_LEVEL_WARNING; } else if (!strcmp(argv[i], "-vv")) { - _log_level = LOG_LEVEL_INFO; + _log_level = CORE_LOG_BT_LOG_LEVEL_INFO; } else if (!strcmp(argv[i], "-vvv")) { - _log_level = LOG_LEVEL_MISC; + _log_level = CORE_LOG_BT_LOG_LEVEL_MISC; } else if (!strcmp(argv[i], "-noextio")) { _extio_enabled = false; } else if (!strcmp(argv[i], "-p3io")) { @@ -256,8 +259,10 @@ static bool _process_cmd_args(int argc, char **argv) static void _init_logging() { - log_to_writer(log_writer_stderr, NULL); - log_set_level(_log_level); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(_log_level); } static bool _mode_invalid(HANDLE handle) diff --git a/src/main/p3io-ddr-tool/mode-test.c b/src/main/p3io-ddr-tool/mode-test.c index 791e6d2c..2de712b2 100644 --- a/src/main/p3io-ddr-tool/mode-test.c +++ b/src/main/p3io-ddr-tool/mode-test.c @@ -5,12 +5,12 @@ #include "extiodrv/extio.h" +#include "iface-core/log.h" + #include "p3io/ddr.h" #include "p3iodrv/ddr.h" #include "p3iodrv/device.h" -#include "util/log.h" - #include "mode-test.h" struct mode_test_output_state { diff --git a/src/main/p3io/cmd.c b/src/main/p3io/cmd.c index 78c8b020..db7ae7cb 100644 --- a/src/main/p3io/cmd.c +++ b/src/main/p3io/cmd.c @@ -1,8 +1,8 @@ #include -#include "p3io/cmd.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "p3io/cmd.h" uint8_t p3io_get_full_req_size(const union p3io_req_any *req) { diff --git a/src/main/p3io/frame.c b/src/main/p3io/frame.c index bc50dd45..b595427c 100644 --- a/src/main/p3io/frame.c +++ b/src/main/p3io/frame.c @@ -3,10 +3,11 @@ #include #include +#include "iface-core/log.h" + #include "p3io/frame.h" #include "util/iobuf.h" -#include "util/log.h" #define P3IO_FRAME_SOF 0xAA #define P3IO_FRAME_ESCAPE 0xFF diff --git a/src/main/p3iodrv/ddr.c b/src/main/p3iodrv/ddr.c index 2cc45261..039ee831 100644 --- a/src/main/p3iodrv/ddr.c +++ b/src/main/p3iodrv/ddr.c @@ -1,8 +1,8 @@ #define LOG_MODULE "p3iodrv-ddr" -#include "p3io/cmd.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "p3io/cmd.h" #include "ddr.h" #include "device.h" diff --git a/src/main/p3iodrv/device.c b/src/main/p3iodrv/device.c index dbbb04af..27096a7a 100644 --- a/src/main/p3iodrv/device.c +++ b/src/main/p3iodrv/device.c @@ -10,13 +10,14 @@ #include // clang-format on +#include "iface-core/log.h" + #include "p3io/cmd.h" #include "p3io/guid.h" #include "p3io/ioctl.h" #include "p3iodrv/device.h" -#include "util/log.h" #include "util/str.h" #define P3IO_DEVICE_FILENMAME "\\p3io" diff --git a/src/main/p3ioemu/devmgr.c b/src/main/p3ioemu/devmgr.c index fc729b35..fe301413 100644 --- a/src/main/p3ioemu/devmgr.c +++ b/src/main/p3ioemu/devmgr.c @@ -9,12 +9,13 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "p3io/guid.h" #include "p3ioemu/devmgr.h" #include "util/defs.h" -#include "util/log.h" #include "util/str.h" /* Link pointers */ diff --git a/src/main/p3ioemu/emu.c b/src/main/p3ioemu/emu.c index 6486d595..d436c477 100644 --- a/src/main/p3ioemu/emu.c +++ b/src/main/p3ioemu/emu.c @@ -9,6 +9,8 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "p3io/cmd.h" #include "p3io/frame.h" #include "p3io/ioctl.h" @@ -18,7 +20,6 @@ #include "p3ioemu/uart.h" #include "util/iobuf.h" -#include "util/log.h" static HANDLE p3io_emu_fd; static uint8_t p3io_emu_resp_bytes[256]; diff --git a/src/main/p3ioemu/uart.c b/src/main/p3ioemu/uart.c index a4a9f735..f4bc696a 100644 --- a/src/main/p3ioemu/uart.c +++ b/src/main/p3ioemu/uart.c @@ -12,12 +12,13 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "p3io/cmd.h" #include "p3ioemu/uart.h" #include "util/iobuf.h" -#include "util/log.h" static HRESULT p3io_uart_open(const wchar_t *path, uint32_t baud_rate, HANDLE *fd); diff --git a/src/main/p4iodrv/device.c b/src/main/p4iodrv/device.c index 67dd56e3..d8099917 100644 --- a/src/main/p4iodrv/device.c +++ b/src/main/p4iodrv/device.c @@ -2,12 +2,13 @@ #include +#include "iface-core/log.h" + #include "p4io/cmd.h" #include "p4iodrv/device.h" #include "p4iodrv/usb.h" -#include "util/log.h" #include "util/mem.h" struct p4iodrv_ctx { diff --git a/src/main/p4iodrv/usb.c b/src/main/p4iodrv/usb.c index 8c99fc42..25cec642 100644 --- a/src/main/p4iodrv/usb.c +++ b/src/main/p4iodrv/usb.c @@ -10,13 +10,14 @@ #include // clang-format on +#include "iface-core/log.h" + #include "p4io/cmd.h" #include "p4io/guid.h" #include "p4io/ioctl.h" #include "p4iodrv/usb.h" -#include "util/log.h" #include "util/str.h" HANDLE p4io_usb_open(void) diff --git a/src/main/p4ioemu/device.c b/src/main/p4ioemu/device.c index e18e8910..94fb17d6 100644 --- a/src/main/p4ioemu/device.c +++ b/src/main/p4ioemu/device.c @@ -7,10 +7,12 @@ #include #include "hook/iohook.h" + +#include "iface-core/log.h" + #include "p4io/cmd.h" #include "p4io/ioctl.h" #include "util/hex.h" -#include "util/log.h" #include "util/str.h" // #define P4IOEMU_DEBUG_DUMP diff --git a/src/main/pcbidgen/Module.mk b/src/main/pcbidgen/Module.mk index 852a4d00..15fd810d 100644 --- a/src/main/pcbidgen/Module.mk +++ b/src/main/pcbidgen/Module.mk @@ -2,6 +2,8 @@ exes += pcbidgen libs_pcbidgen := \ security \ + core \ + iface-core \ util \ src_pcbidgen := \ diff --git a/src/main/pcbidgen/main.c b/src/main/pcbidgen/main.c index 3e9182be..d92d1a53 100644 --- a/src/main/pcbidgen/main.c +++ b/src/main/pcbidgen/main.c @@ -5,6 +5,10 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + #include "security/id.h" #include "util/hex.h" @@ -30,6 +34,11 @@ int main(int argc, char **argv) return -1; } + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); + if (!strcmp(argv[1], "gen")) { srand(time(NULL)); diff --git a/src/main/popnhook-util/acio.c b/src/main/popnhook-util/acio.c index 60d66b84..3b150be5 100644 --- a/src/main/popnhook-util/acio.c +++ b/src/main/popnhook-util/acio.c @@ -18,13 +18,14 @@ #include "hook/iohook.h" #include "hooklib/rs232.h" +#include "iface-core/log.h" + #include "popnhook-util/acio.h" #include "imports/avs.h" #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu popnhook_acio_emu; diff --git a/src/main/popnhook-util/mixer.c b/src/main/popnhook-util/mixer.c index 91d3c759..e957d8c3 100644 --- a/src/main/popnhook-util/mixer.c +++ b/src/main/popnhook-util/mixer.c @@ -8,8 +8,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" MMRESULT STDCALL hook_mixerGetLineControlsA( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls); diff --git a/src/main/popnhook1/Module.mk b/src/main/popnhook1/Module.mk index c2c15107..26cfe696 100644 --- a/src/main/popnhook1/Module.mk +++ b/src/main/popnhook1/Module.mk @@ -6,8 +6,10 @@ deplibs_popnhook1 := \ ldflags_popnhook1 := \ -lws2_32 \ -liphlpapi \ + -lshlwapi \ libs_popnhook1 := \ + core \ iidxhook-util \ ezusb-emu \ ezusb2-popn-emu \ @@ -16,13 +18,16 @@ libs_popnhook1 := \ acioemu \ hook \ hooklib \ - eamio \ - popnio \ - cconfig \ util \ ezusb \ security \ popnhook-util \ + iface \ + iface-io \ + iface-core \ + module \ + sdk-hook \ + mxml \ src_popnhook1 := \ avs-boot.c \ @@ -32,3 +37,4 @@ src_popnhook1 := \ d3d9.c \ dllmain.c \ filesystem.c \ + popnhook1.c \ diff --git a/src/main/popnhook1/avs-boot.c b/src/main/popnhook1/avs-boot.c index f9833a7b..b2c6aa3d 100644 --- a/src/main/popnhook1/avs-boot.c +++ b/src/main/popnhook1/avs-boot.c @@ -7,12 +7,12 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "popnhook1/avs-boot.h" -#include "util/log.h" - static int (*real_ea3_boot_avs)(struct property_node *config); static int (*real_ea3_boot)(struct property_node *config); diff --git a/src/main/popnhook1/config-eamuse.c b/src/main/popnhook1/config-eamuse.c index 98e406b8..8ca994f2 100644 --- a/src/main/popnhook1/config-eamuse.c +++ b/src/main/popnhook1/config-eamuse.c @@ -1,145 +1,12 @@ -#include - -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "popnhook1/config-eamuse.h" -#include "security/mcode.h" - -#include "util/log.h" - -#define POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY "eamuse.server" -#define POPNHOOK1_CONFIG_EAMUSE_PCBID_KEY "eamuse.pcbid" -#define POPNHOOK1_CONFIG_EAMUSE_EAMID_KEY "eamuse.eamid" - -#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE "localhost:80" -#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE security_id_default -#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN \ - sizeof(security_id_default) -#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE security_id_default -#define POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN \ - sizeof(security_id_default) - -const struct net_addr popnhook1_eamuse_default_server = { - .type = NET_ADDR_TYPE_HOSTNAME, - .hostname.host = "localhost", - .hostname.port = 80, -}; - -void popnhook1_config_eamuse_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY, - POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE, - "URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 " - "(e.g. 127.0.0.1:80) of the target eamuse server. The port is " - "optional " - "but defaults to 80."); - - cconfig_util_set_data( - config, - POPNHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, - POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - "PCBID"); - - cconfig_util_set_data( - config, - POPNHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, - POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - "EAMID"); -} - void popnhook1_config_eamuse_get( - struct popnhook1_config_eamuse *config_eamuse, struct cconfig *config) + const bt_core_config_t *config, + popnhook1_config_eamuse_t *config_out) { - char server_url[1024]; - char *tmp; - char *tmp2; - - memset(config_eamuse, 0, sizeof(struct popnhook1_config_eamuse)); - - if (!cconfig_util_get_str( - config, - POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY, - server_url, - sizeof(server_url), - POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - POPNHOOK1_CONFIG_EAMUSE_SERVER_KEY, - POPNHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE); - } - - if (!net_str_parse(server_url, &config_eamuse->server)) { - memcpy( - &config_eamuse->server, - &popnhook1_eamuse_default_server, - sizeof(config_eamuse->server)); - tmp = net_addr_to_str(&config_eamuse->server); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!cconfig_util_get_data( - config, - POPNHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &config_eamuse->pcbid, - POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - (uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE)) { - tmp = security_id_to_str( - &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } - - if (!cconfig_util_get_data( - config, - POPNHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &config_eamuse->eamid, - POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - (uint8_t *) &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE)) { - tmp = security_id_to_str( - &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } -} + bt_core_config_ext_net_addr_get(config, "eamuse/server", &config_out->server); + bt_core_config_ext_security_id_get(config, "eamuse/pcbid", &config_out->pcbid); + bt_core_config_ext_security_id_get(config, "eamuse/eamid", &config_out->eamid); +} \ No newline at end of file diff --git a/src/main/popnhook1/config-eamuse.h b/src/main/popnhook1/config-eamuse.h index c08c50de..ad5732df 100644 --- a/src/main/popnhook1/config-eamuse.h +++ b/src/main/popnhook1/config-eamuse.h @@ -1,21 +1,20 @@ #ifndef POPNHOOK1_CONFIG_EAMUSE_H #define POPNHOOK1_CONFIG_EAMUSE_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/id.h" #include "util/net.h" -struct popnhook1_config_eamuse { +typedef struct popnhook1_config_eamuse { struct net_addr server; struct security_id pcbid; struct security_id eamid; -}; - -void popnhook1_config_eamuse_init(struct cconfig *config); +} popnhook1_config_eamuse_t; void popnhook1_config_eamuse_get( - struct popnhook1_config_eamuse *config_eamuse, struct cconfig *config); + const bt_core_config_t *config, + popnhook1_config_eamuse_t *config_out); #endif \ No newline at end of file diff --git a/src/main/popnhook1/config-gfx.c b/src/main/popnhook1/config-gfx.c index 8e231d11..5e9cfdaf 100644 --- a/src/main/popnhook1/config-gfx.c +++ b/src/main/popnhook1/config-gfx.c @@ -1,96 +1,18 @@ -#include - -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "popnhook1/config-gfx.h" -#include "util/log.h" - #define POPNHOOK1_CONFIG_GFX_WINDOWED_KEY "gfx.windowed" #define POPNHOOK1_CONFIG_GFX_FRAMED_KEY "gfx.framed" #define POPNHOOK1_CONFIG_GFX_WINDOW_WIDTH_KEY "gfx.window_width" #define POPNHOOK1_CONFIG_GFX_WINDOW_HEIGHT_KEY "gfx.window_height" -#define POPNHOOK1_CONFIG_GFX_DEFAULT_FRAMED_VALUE false -#define POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false -#define POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE -1 -#define POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE -1 - -void popnhook1_config_gfx_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - POPNHOOK1_CONFIG_GFX_WINDOWED_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE, - "Run the game windowed"); - - cconfig_util_set_bool( - config, - POPNHOOK1_CONFIG_GFX_FRAMED_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_FRAMED_VALUE, - "Run the game in a framed window (requires windowed option)"); - - cconfig_util_set_int( - config, - POPNHOOK1_CONFIG_GFX_WINDOW_WIDTH_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE, - "Windowed width, -1 for default size"); - - cconfig_util_set_int( - config, - POPNHOOK1_CONFIG_GFX_WINDOW_HEIGHT_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE, - "Windowed height, -1 for default size"); -} - void popnhook1_config_gfx_get( - struct popnhook1_config_gfx *config_gfx, struct cconfig *config) + const bt_core_config_t *config, + popnhook1_config_gfx_t *out_config) { - if (!cconfig_util_get_bool( - config, - POPNHOOK1_CONFIG_GFX_WINDOWED_KEY, - &config_gfx->windowed, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - POPNHOOK1_CONFIG_GFX_WINDOWED_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE); - } - - if (!cconfig_util_get_bool( - config, - POPNHOOK1_CONFIG_GFX_FRAMED_KEY, - &config_gfx->framed, - POPNHOOK1_CONFIG_GFX_DEFAULT_FRAMED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - POPNHOOK1_CONFIG_GFX_FRAMED_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_FRAMED_VALUE); - } - - if (!cconfig_util_get_int( - config, - POPNHOOK1_CONFIG_GFX_WINDOW_WIDTH_KEY, - &config_gfx->window_width, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - POPNHOOK1_CONFIG_GFX_WINDOW_WIDTH_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE); - } - - if (!cconfig_util_get_int( - config, - POPNHOOK1_CONFIG_GFX_WINDOW_HEIGHT_KEY, - &config_gfx->window_height, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - POPNHOOK1_CONFIG_GFX_WINDOW_HEIGHT_KEY, - POPNHOOK1_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE); - } + bt_core_config_bool_get(config, "gfx/windowed", &out_config->windowed); + bt_core_config_bool_get(config, "gfx/framed", &out_config->framed); + bt_core_config_s32_get(config, "gfx/window_width", &out_config->window_width); + bt_core_config_s32_get(config, "gfx/window_height", &out_config->window_height); } diff --git a/src/main/popnhook1/config-gfx.h b/src/main/popnhook1/config-gfx.h index a0eeba42..29e38aef 100644 --- a/src/main/popnhook1/config-gfx.h +++ b/src/main/popnhook1/config-gfx.h @@ -1,21 +1,20 @@ #ifndef POPNHOOK1_CONFIG_GFX_H #define POPNHOOK1_CONFIG_GFX_H -#include "cconfig/cconfig.h" +#include +#include -#include "popnhook1/d3d9.h" +#include "api/core/config.h" -// see struct popnhook1_d3d9_config for more info -struct popnhook1_config_gfx { +typedef struct popnhook1_config_gfx { bool framed; bool windowed; int32_t window_width; int32_t window_height; -}; - -void popnhook1_config_gfx_init(struct cconfig *config); +} popnhook1_config_gfx_t; void popnhook1_config_gfx_get( - struct popnhook1_config_gfx *config_gfx, struct cconfig *config); - + const bt_core_config_t *config, + popnhook1_config_gfx_t *out_config); + #endif \ No newline at end of file diff --git a/src/main/popnhook1/config-sec.c b/src/main/popnhook1/config-sec.c index f1555200..1d21f87f 100644 --- a/src/main/popnhook1/config-sec.c +++ b/src/main/popnhook1/config-sec.c @@ -1,80 +1,10 @@ -#include -#include - -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "popnhook1/config-sec.h" -#include "security/mcode.h" -#include "security/rp.h" - -#include "util/log.h" -#include "util/mem.h" - -#define POPNHOOK1_CONFIG_SEC_BLACK_PLUG_MCODE_KEY "sec.black_plug_mcode" - -#define POPNHOOK1_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE \ - popnhook1_security_default_black_plug_mcode - -static const struct security_mcode popnhook1_security_default_black_plug_mcode = - { - .header = SECURITY_MCODE_HEADER, - .unkn = SECURITY_MCODE_UNKN_Q, - .game = SECURITY_MCODE_GAME_POPN_15, - .region = SECURITY_MCODE_REGION_JAPAN, - .cabinet = SECURITY_MCODE_CABINET_A, - .revision = SECURITY_MCODE_REVISION_A, -}; - -void popnhook1_config_sec_init(struct cconfig *config) -{ - char *tmp; - - tmp = security_mcode_to_str( - &POPNHOOK1_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE); - - cconfig_util_set_str( - config, - POPNHOOK1_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp, - "Security black plug mcode id string (e.g. GQC02JAA)."); - - free(tmp); -} - void popnhook1_config_sec_get( - struct popnhook1_config_sec *config_sec, struct cconfig *config) + const bt_core_config_t *config, + popnhook1_config_sec_t *out_config) { - char tmp_mcode[sizeof(struct security_mcode) + 1]; - char *tmp_str; - - tmp_str = security_mcode_to_str( - &POPNHOOK1_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE); - - if (!cconfig_util_get_str( - config, - POPNHOOK1_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp_mcode, - sizeof(tmp_mcode) - 1, - tmp_str)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - POPNHOOK1_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp_str); - } - - if (!security_mcode_parse(tmp_mcode, &config_sec->black_plug_mcode)) { - log_warning( - "Invalid format for value of key '%s' specified, fallback " - "to default '%s'", - POPNHOOK1_CONFIG_SEC_BLACK_PLUG_MCODE_KEY, - tmp_str); - memcpy( - &config_sec->black_plug_mcode, - &POPNHOOK1_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE, - sizeof(POPNHOOK1_CONFIG_SEC_DEFAULT_BLACK_PLUG_MCODE_VALUE)); - } - - free(tmp_str); -} + bt_core_config_ext_security_mcode_get(config, "sec/black_plug_mcode", &out_config->black_plug_mcode); +} \ No newline at end of file diff --git a/src/main/popnhook1/config-sec.h b/src/main/popnhook1/config-sec.h index 51671b8f..1b889b36 100644 --- a/src/main/popnhook1/config-sec.h +++ b/src/main/popnhook1/config-sec.h @@ -1,17 +1,16 @@ #ifndef POPNHOOK1_CONFIG_SEC_H #define POPNHOOK1_CONFIG_SEC_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/mcode.h" -struct popnhook1_config_sec { - struct security_mcode black_plug_mcode; -}; - -void popnhook1_config_sec_init(struct cconfig *config); +typedef struct popnhook1_config_sec { + security_mcode_t black_plug_mcode; +} popnhook1_config_sec_t; void popnhook1_config_sec_get( - struct popnhook1_config_sec *config_sec, struct cconfig *config); - + const bt_core_config_t *config, + popnhook1_config_sec_t *out_config); + #endif \ No newline at end of file diff --git a/src/main/popnhook1/d3d9.c b/src/main/popnhook1/d3d9.c index 1d67262c..c6830ba2 100644 --- a/src/main/popnhook1/d3d9.c +++ b/src/main/popnhook1/d3d9.c @@ -9,10 +9,11 @@ #include "hook/pe.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "popnhook1/d3d9.h" #include "util/defs.h" -#include "util/log.h" #include "hook/d3d9.h" diff --git a/src/main/popnhook1/dllmain.c b/src/main/popnhook1/dllmain.c index 5995e222..3c6abb03 100644 --- a/src/main/popnhook1/dllmain.c +++ b/src/main/popnhook1/dllmain.c @@ -1,199 +1,70 @@ -#include - #include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/popnio.h" - -#include "cconfig/cconfig-hook.h" - -#include "ezusb-emu/node-security-plug.h" - -#include "hook/d3d9.h" #include "hook/table.h" -#include "hooklib/adapter.h" - -#include "popnhook1/avs-boot.h" -#include "popnhook1/config-eamuse.h" -#include "popnhook1/config-gfx.h" -#include "popnhook1/config-sec.h" -#include "popnhook1/d3d9.h" -#include "popnhook1/filesystem.h" +#include "popnhook1/popnhook1.h" -#include "popnhook-util/acio.h" -#include "popnhook-util/mixer.h" +#include "main/sdk-hook/dllentry.h" -#include "util/cmdline.h" #include "util/defs.h" -#include "util/log.h" -#include "util/thread.h" - -#include "ezusb2-emu/desc.h" -#include "ezusb2-emu/device.h" - -#include "iidxhook-util/acio.h" - -#include "ezusb2-popn-emu/msg.h" - -#include "hooklib/rs232.h" - -#include "security/rp-sign-key.h" - -#define POPNHOOK1_INFO_HEADER \ - "popnhook1 for pop'n music 15, 16, 17, 18" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define POPNHOOK1_CMD_USAGE \ - "Usage: inject.exe popnhook1.dll [options...]" -static DWORD STDCALL my_GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo); -static DWORD(STDCALL *real_GetStartupInfoA)(LPSTARTUPINFOA lpStartupInfo); +static DWORD STDCALL _popnhook1_dllmain_my_GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo); +static DWORD(STDCALL *_popnhook1_dllmain_real_GetStartupInfoA)(LPSTARTUPINFOA lpStartupInfo); -static bool popnhook1_init_check; +static bool _popnhook1_dllmain_getstartupinfoa_call_check; -static const struct hook_symbol init_hook_syms[] = { +static const struct hook_symbol _popnhook1_dllmain_hook_syms[] = { { .name = "GetStartupInfoA", - .patch = my_GetStartupInfoA, - .link = (void **) &real_GetStartupInfoA, + .patch = _popnhook1_dllmain_my_GetStartupInfoA, + .link = (void **) &_popnhook1_dllmain_real_GetStartupInfoA, }, }; -static void popnhook_setup_d3d9_hooks( - const struct popnhook1_config_gfx *config_gfx, const bool texture_usage_fix) +static DWORD STDCALL +_popnhook1_dllmain_my_GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo) { - struct popnhook1_d3d9_config d3d9_config; - - popnhook1_d3d9_init_config(&d3d9_config); - - d3d9_config.windowed = config_gfx->windowed; - d3d9_config.framed = config_gfx->framed; - d3d9_config.override_window_width = config_gfx->window_width; - d3d9_config.override_window_height = config_gfx->window_height; - d3d9_config.texture_usage_fix = texture_usage_fix; - - popnhook1_d3d9_init(); - popnhook1_d3d9_configure(&d3d9_config); -} - -static DWORD STDCALL my_GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo) -{ - struct cconfig *config; - - struct popnhook1_config_eamuse config_eamuse; - struct popnhook1_config_gfx config_gfx; - struct popnhook1_config_sec config_sec; - - if (popnhook1_init_check) - goto skip; - - popnhook1_init_check = true; - - log_info("-------------------------------------------------------------"); - log_info("----------------- Start popnhook1 hook init -----------------"); - log_info("-------------------------------------------------------------"); - - config = cconfig_init(); - - popnhook1_config_eamuse_init(config); - popnhook1_config_gfx_init(config); - popnhook1_config_sec_init(config); - - if (!cconfig_hook_config_init( - config, - POPNHOOK1_INFO_HEADER "\n" POPNHOOK1_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - popnhook1_config_gfx_get(&config_gfx, config); - popnhook1_config_eamuse_get(&config_eamuse, config); - popnhook1_config_sec_get(&config_sec, config); - - cconfig_finit(config); - - popnhook_setup_d3d9_hooks( - &config_gfx, - // pop'n music 16 requires a patch for the texture usage to not crash on - // newer Windows - memcmp( - config_sec.black_plug_mcode.game, - SECURITY_MCODE_GAME_POPN_16, - sizeof(config_sec.black_plug_mcode.game)) == 0); - - popnhook1_avs_boot_init(); - popnhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); - - /* Round plug security */ - - ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( - &config_sec.black_plug_mcode); - ezusb_iidx_emu_node_security_plug_set_plug_white_mcode( - &security_mcode_eamuse); - ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( - &security_rp_sign_key_black_popn); - ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key( - &security_rp_sign_key_white_eamuse); - - ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); - ezusb_iidx_emu_node_security_plug_set_eamid(&config_eamuse.eamid); - - /* Start up POPNIO.DLL */ - - log_info("Starting pop'n IO backend"); - popn_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!popn_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing pop'n IO backend failed"); + if (_popnhook1_dllmain_getstartupinfoa_call_check) { + return _popnhook1_dllmain_real_GetStartupInfoA(lpStartupInfo); } - /* Start up EAMIO.DLL */ + _popnhook1_dllmain_getstartupinfoa_call_check = true; - log_misc("Initializing card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + bt_hook_dllentry_main_init(); - if (!eam_io_init(thread_create, thread_join, thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - - iohook_push_handler(ezusb2_emu_device_dispatch_irp); - iohook_push_handler(popnhook_acio_dispatch_irp); - - hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); - ezusb2_emu_device_hook_init(ezusb2_popn_emu_msg_init()); - - rs232_hook_init(); - - popnhook_acio_init(true); - - adapter_hook_init(); - filesystem_init(); - popnhook_mixer_hook_init(); - - log_info("-------------------------------------------------------------"); - log_info("------------------ End popnhook1 hook init ------------------"); - log_info("-------------------------------------------------------------"); - -skip: - return real_GetStartupInfoA(lpStartupInfo); + return _popnhook1_dllmain_real_GetStartupInfoA(lpStartupInfo); } -BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() + +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - return TRUE; + if (reason == DLL_PROCESS_ATTACH) { + bt_hook_dllentry_init( + mod, + "popnhook1", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); + + _popnhook1_dllmain_getstartupinfoa_call_check = false; + + hook_table_apply( + NULL, "kernel32.dll", _popnhook1_dllmain_hook_syms, lengthof(_popnhook1_dllmain_hook_syms)); + + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "kernel32.dll", _popnhook1_dllmain_hook_syms, lengthof(_popnhook1_dllmain_hook_syms)); + + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); + + bt_hook_dllentry_fini(); + } } - log_to_writer(log_writer_debug, NULL); - - hook_table_apply( - NULL, "kernel32.dll", init_hook_syms, lengthof(init_hook_syms)); - return TRUE; -} +} \ No newline at end of file diff --git a/src/main/popnhook1/filesystem.c b/src/main/popnhook1/filesystem.c index 3d7fd09a..48cb859a 100644 --- a/src/main/popnhook1/filesystem.c +++ b/src/main/popnhook1/filesystem.c @@ -9,8 +9,9 @@ #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" diff --git a/src/main/popnhook1/popnhook1.c b/src/main/popnhook1/popnhook1.c new file mode 100644 index 00000000..0ae96c6d --- /dev/null +++ b/src/main/popnhook1/popnhook1.c @@ -0,0 +1,196 @@ +#include + +#include + +#include +#include + +#include "ezusb-emu/node-security-plug.h" + +#include "hook/d3d9.h" + +#include "hooklib/adapter.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/popn.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "popnhook1/avs-boot.h" +#include "popnhook1/config-eamuse.h" +#include "popnhook1/config-gfx.h" +#include "popnhook1/config-sec.h" +#include "popnhook1/d3d9.h" +#include "popnhook1/filesystem.h" + +#include "popnhook-util/acio.h" +#include "popnhook-util/mixer.h" + +#include "util/cmdline.h" +#include "util/defs.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "popnhook-util/acio.h" + +#include "ezusb2-popn-emu/msg.h" + +#include "hooklib/rs232.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "security/rp-sign-key.h" + +static module_io_t *popnhook_module_io_popn; +static module_io_t *popnhook_module_io_eam; + +static void _popnhook1_io_popn_init(module_io_t **module) +{ + bt_io_popn_api_t api; + + module_io_ext_load_and_init( + "popnio.dll", "bt_module_io_popn_api_get", module); + module_io_api_get(*module, &api); + bt_io_popn_api_set(&api); +} + +static void _popnhook1_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static void popnhook_setup_d3d9_hooks( + const popnhook1_config_gfx_t *config_gfx, const bool texture_usage_fix) +{ + struct popnhook1_d3d9_config d3d9_config; + + popnhook1_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.texture_usage_fix = texture_usage_fix; + + popnhook1_d3d9_init(); + popnhook1_d3d9_configure(&d3d9_config); +} + +static bool +_popnhook1_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + popnhook1_config_eamuse_t config_eamuse; + popnhook1_config_gfx_t config_gfx; + popnhook1_config_sec_t config_sec; + + log_info("popnhook1 for pop'n music 15, 16, 17, 18"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + popnhook1_config_gfx_get(config, &config_gfx); + popnhook1_config_eamuse_get(config, &config_eamuse); + popnhook1_config_sec_get(config, &config_sec); + + popnhook_setup_d3d9_hooks( + &config_gfx, + // pop'n music 16 requires a patch for the texture usage to not crash on + // newer Windows + memcmp( + config_sec.black_plug_mcode.game, + SECURITY_MCODE_GAME_POPN_16, + sizeof(config_sec.black_plug_mcode.game)) == 0); + + popnhook1_avs_boot_init(); + popnhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); + + /* Round plug security */ + + ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( + &config_sec.black_plug_mcode); + ezusb_iidx_emu_node_security_plug_set_plug_white_mcode( + &security_mcode_eamuse); + ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( + &security_rp_sign_key_black_popn); + ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key( + &security_rp_sign_key_white_eamuse); + + ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + ezusb_iidx_emu_node_security_plug_set_eamid(&config_eamuse.eamid); + + /* Start up POPNIO.DLL */ + + log_info("Starting pop'n IO backend"); + + _popnhook1_io_popn_init(&popnhook_module_io_popn); + + if (!bt_io_popn_init()) { + log_fatal("Initializing pop'n IO backend failed"); + } + + /* Start up EAMIO.DLL */ + + log_misc("Initializing card reader backend"); + + _popnhook1_io_eam_init(&popnhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(popnhook_acio_dispatch_irp); + + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_popn_emu_msg_init()); + + rs232_hook_init(); + + popnhook_acio_init(true); + + adapter_hook_init(); + filesystem_init(); + popnhook_mixer_hook_init(); + + return true; +} + +static void _popnhook1_main_fini() +{ + // TODO cleanup +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _popnhook1_main_init; + api->v1.main_fini = _popnhook1_main_fini; +} \ No newline at end of file diff --git a/src/main/popnhook1/popnhook1.def b/src/main/popnhook1/popnhook1.def index 95732630..9fe2c524 100644 --- a/src/main/popnhook1/popnhook1.def +++ b/src/main/popnhook1/popnhook1.def @@ -2,3 +2,9 @@ LIBRARY popnhook1 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/popnhook1/popnhook1.h b/src/main/popnhook1/popnhook1.h new file mode 100644 index 00000000..5c1a1d2c --- /dev/null +++ b/src/main/popnhook1/popnhook1.h @@ -0,0 +1,9 @@ +#ifndef POPNHOOK1_H +#define POPNHOOK1_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/popnio/Module.mk b/src/main/popnio/Module.mk index 38944130..83664d36 100644 --- a/src/main/popnio/Module.mk +++ b/src/main/popnio/Module.mk @@ -4,7 +4,11 @@ ldflags_popnio := \ -lwinmm libs_popnio := \ - geninput \ + iface \ + module \ + iface-io \ + iface-core \ + util \ src_popnio := \ popnio.c \ diff --git a/src/main/popnio/popnio.c b/src/main/popnio/popnio.c index d5389cd2..c083797e 100644 --- a/src/main/popnio/popnio.c +++ b/src/main/popnio/popnio.c @@ -1,76 +1,136 @@ +#define LOG_MODULE "popnio" + +// clang-format off +// Don't format because the order is important here +#include +#include +// clang-format on + #include #include #include -#include "bemanitools/input.h" -#include "bemanitools/popnio.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/input.h" + +#include "main/module/input-ext.h" +#include "main/module/input.h" +#include "main/module/io-ext.h" +#include "main/module/io.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/popn.h" + +static module_input_t *_popn_io_module_input; -void popn_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +static void _bt_io_popn_module_input_init(module_input_t **module) { - input_set_loggers(misc, info, warning, fatal); + bt_input_api_t api; + + module_input_ext_load_and_init("geninput.dll", module); + module_input_api_get(*module, &api); + bt_input_api_set(&api); } -bool popn_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_popn_init() { - input_init(thread_create, thread_join, thread_destroy); - mapper_config_load("pnm"); + bool result; + + _bt_io_popn_module_input_init(&_popn_io_module_input); + + timeBeginPeriod(1); + + result = bt_input_init(); + + if (!result) { + log_warning("Initializing input failed"); + return false; + } - return true; + return bt_input_mapper_config_load("pnm"); } -void popn_io_fini(void) +void bt_io_popn_fini(void) { - input_fini(); + bt_input_fini(); + bt_input_api_clear(); + module_input_free(&_popn_io_module_input); + + timeEndPeriod(1); } -uint32_t popn_io_get_buttons(void) +uint32_t bt_io_popn_buttons_get(void) { - return (uint32_t) mapper_update(); + return (uint32_t) bt_input_mapper_update(); } -void popn_io_set_top_lights(uint32_t lights) +void bt_io_popn_top_lights_set(uint32_t lights) { uint8_t i; for (i = 0; i < 5; i++) { - mapper_write_light(0x20 + i, lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(0x20 + i, lights & (1 << i) ? 255 : 0); } } -void popn_io_set_side_lights(uint32_t lights) +void bt_io_popn_side_lights_set(uint32_t lights) { uint8_t i; for (i = 0; i < 4; i++) { - mapper_write_light(0x25 + i, lights & (1 << i) ? 255 : 0); + bt_input_mapper_light_write(0x25 + i, lights & (1 << i) ? 255 : 0); } } -void popn_io_set_button_lights(uint32_t lights) +void bt_io_popn_button_lights_set(uint32_t lights) { uint8_t i; // Special case for POPN_LIGHT_SW_LAMP1 which is 4 bits wide - mapper_write_light(0x17, lights & 0xf ? 255 : 0); + bt_input_mapper_light_write(0x17, lights & 0xf ? 255 : 0); for (i = 0; i < 8; i++) { - mapper_write_light(0x18 + i, lights & (1 << (i + 4)) ? 255 : 0); + bt_input_mapper_light_write( + 0x18 + i, lights & (1 << (i + 4)) ? 255 : 0); } } -void popn_io_set_coin_blocker_light(bool enabled) +void bt_io_popn_coin_blocker_light_set(bool enabled) +{ + // bt_input_mapper_light_write(x, enabled ? 255 : 0); +} + +void bt_io_popn_coin_counter_light_set(bool enabled) { - // mapper_write_light(x, enabled ? 255 : 0); + // bt_input_mapper_light_write(x, enabled ? 255 : 0); } -void popn_io_set_coin_counter_light(bool enabled) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - // mapper_write_light(x, enabled ? 255 : 0); + bt_core_log_api_set(api); } + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_popn_api_get(bt_io_popn_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_popn_init; + api->v1.fini = bt_io_popn_fini; + api->v1.buttons_get = bt_io_popn_buttons_get; + api->v1.top_lights_set = bt_io_popn_top_lights_set; + api->v1.side_lights_set = bt_io_popn_side_lights_set; + api->v1.button_lights_set = bt_io_popn_button_lights_set; + api->v1.coin_blocker_light_set = bt_io_popn_coin_blocker_light_set; + api->v1.coin_counter_light_set = bt_io_popn_coin_counter_light_set; +} \ No newline at end of file diff --git a/src/main/popnio/popnio.def b/src/main/popnio/popnio.def index f35a5950..4302ac23 100644 --- a/src/main/popnio/popnio.def +++ b/src/main/popnio/popnio.def @@ -1,12 +1,17 @@ LIBRARY popnio EXPORTS - popn_io_get_buttons - popn_io_set_top_lights - popn_io_set_side_lights - popn_io_set_button_lights - popn_io_set_coin_blocker_light - popn_io_set_coin_counter_light - popn_io_fini - popn_io_init - popn_io_set_loggers + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_popn_api_get + + ; Direct API + bt_io_popn_init + bt_io_popn_fini + bt_io_popn_buttons_get + bt_io_popn_top_lights_set + bt_io_popn_side_lights_set + bt_io_popn_button_lights_set + bt_io_popn_coin_blocker_light_set + bt_io_popn_coin_counter_light_set diff --git a/src/main/procmon/Module.mk b/src/main/procmon/Module.mk new file mode 100644 index 00000000..1e1d8b21 --- /dev/null +++ b/src/main/procmon/Module.mk @@ -0,0 +1,17 @@ +dlls += procmon + +libs_procmon := \ + core \ + hook \ + util \ + iface-core \ + +src_procmon := \ + bt-hook.c \ + config.c \ + dllmain.c \ + file.c \ + module.c \ + procmon.c \ + thread.c \ + diff --git a/src/main/procmon/bt-hook.c b/src/main/procmon/bt-hook.c new file mode 100644 index 00000000..3dd44147 --- /dev/null +++ b/src/main/procmon/bt-hook.c @@ -0,0 +1,50 @@ +#define LOG_MODULE "procmon-hook" + +#include + +#include +#include + +#include "iface-core/config.h" +#include "iface-core/log.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/hook.h" + +#include "procmon/config.h" +#include "procmon/procmon.h" + +bool bt_hook_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + procmon_config_t procmon_config; + + procmon_config_load(config, &procmon_config); + + procmon_init(&procmon_config); + + return true; +} + +void bt_hook_main_fini() +{ + procmon_fini(); +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = bt_hook_main_init; + api->v1.main_fini = bt_hook_main_fini; +} \ No newline at end of file diff --git a/src/main/procmon/config.c b/src/main/procmon/config.c new file mode 100644 index 00000000..51cd8bff --- /dev/null +++ b/src/main/procmon/config.c @@ -0,0 +1,39 @@ +#define LOG_MODULE "procmon-config" + +#include "iface-core/config.h" +#include "iface-core/log.h" + +#include "procmon/config.h" + +static void _procmon_config_init_default(procmon_config_t *config) +{ + config->file_enable = false; + config->module_enable = false; + config->thread_enable = false; +} + +void procmon_config_load( + const bt_core_config_t *config, procmon_config_t *procmon_config) +{ + uint32_t version; + + log_assert(config); + log_assert(procmon_config); + + _procmon_config_init_default(procmon_config); + + version = 0; + + bt_core_config_u32_get(config, "/version", &version); + + if (version != 1) { + log_fatal("Unsupported configuration version: %d", version); + } + + bt_core_config_bool_get( + config, "/file/enable", &procmon_config->file_enable); + bt_core_config_bool_get( + config, "/module/enable", &procmon_config->module_enable); + bt_core_config_bool_get( + config, "/thread/enable", &procmon_config->thread_enable); +} \ No newline at end of file diff --git a/src/main/procmon/config.h b/src/main/procmon/config.h new file mode 100644 index 00000000..3a6bab8c --- /dev/null +++ b/src/main/procmon/config.h @@ -0,0 +1,17 @@ +#ifndef PROCMON_CONFIG_H +#define PROCMON_CONFIG_H + +#include + +#include "api/core/config.h" + +typedef struct procmon_config { + bool file_enable; + bool module_enable; + bool thread_enable; +} procmon_config_t; + +void procmon_config_load( + const bt_core_config_t *config, procmon_config_t *procmon_config); + +#endif \ No newline at end of file diff --git a/src/main/procmon/dllmain.c b/src/main/procmon/dllmain.c new file mode 100644 index 00000000..71f1a587 --- /dev/null +++ b/src/main/procmon/dllmain.c @@ -0,0 +1,6 @@ +#include + +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ + return TRUE; +} diff --git a/src/main/procmon/file.c b/src/main/procmon/file.c new file mode 100644 index 00000000..ac864517 --- /dev/null +++ b/src/main/procmon/file.c @@ -0,0 +1,176 @@ +#define LOG_MODULE "procmon-file" + +#include + +#include "hook/table.h" + +#include "iface-core/log.h" + +#include "util/str.h" + +static HANDLE(STDCALL *real_CreateFileW)( + const wchar_t *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); +static HANDLE(STDCALL *real_CreateFileA)( + const char *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); + +static HANDLE STDCALL my_CreateFileW( + const wchar_t *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); + +static HANDLE STDCALL my_CreateFileA( + const char *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); + +static const struct hook_symbol _procmon_file_hook_syms[] = { + { + .name = "CreateFileW", + .patch = my_CreateFileW, + .link = (void **) &real_CreateFileW, + }, + { + .name = "CreateFileA", + .patch = my_CreateFileA, + .link = (void **) &real_CreateFileA, + }, +}; + +static HANDLE STDCALL my_CreateFileW( + const wchar_t *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + HANDLE result; + char *tmp; + + wstr_narrow(lpFileName, &tmp); + + log_misc( + "CreateFileW(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p)", + tmp, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + result = real_CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + log_misc( + "CreateFileW(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p) = %p", + tmp, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + result); + + free(tmp); + + return result; +} + +static HANDLE STDCALL my_CreateFileA( + const char *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + HANDLE result; + + log_misc( + "CreateFileA(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p)", + lpFileName, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + result = real_CreateFileA( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + log_misc( + "CreateFileA(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p) = %p", + lpFileName, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + result); + + return result; +} + +void procmon_file_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + _procmon_file_hook_syms, + lengthof(_procmon_file_hook_syms)); + + log_misc("init"); +} + +void procmon_file_fini() +{ + hook_table_revert( + NULL, + "kernel32.dll", + _procmon_file_hook_syms, + lengthof(_procmon_file_hook_syms)); + + log_misc("fini"); +} \ No newline at end of file diff --git a/src/main/procmon/file.h b/src/main/procmon/file.h new file mode 100644 index 00000000..6b9d7516 --- /dev/null +++ b/src/main/procmon/file.h @@ -0,0 +1,7 @@ +#ifndef PROCMON_FILE_H +#define PROCMON_FILE_H + +void procmon_file_init(); +void procmon_file_fini(); + +#endif \ No newline at end of file diff --git a/src/main/procmon/module.c b/src/main/procmon/module.c new file mode 100644 index 00000000..0d36b395 --- /dev/null +++ b/src/main/procmon/module.c @@ -0,0 +1,289 @@ +#define LOG_MODULE "procmon-module" + +#include + +#include "hook/table.h" + +#include "iface-core/log.h" + +#include "util/str.h" + +static HMODULE(STDCALL *real_GetModuleHandleA)(LPCSTR lpModuleName); +static BOOL(STDCALL *real_GetModuleHandleExA)( + DWORD dwFlags, LPCSTR lpModuleName, HMODULE *phModule); +static BOOL(STDCALL *real_GetModuleHandleExW)( + DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule); +static HMODULE(STDCALL *real_GetModuleHandleW)(LPCWSTR lpModuleName); +static HMODULE(STDCALL *real_LoadLibraryA)(LPCSTR lpLibFileName); +static HMODULE(STDCALL *real_LoadLibraryW)(LPCWSTR lpLibFileName); +static HMODULE(STDCALL *real_LoadLibraryExA)( + LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static HMODULE(STDCALL *real_LoadLibraryExW)( + LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static FARPROC(STDCALL *real_GetProcAddress)( + HMODULE hModule, LPCSTR lpProcName); + +static HMODULE STDCALL my_GetModuleHandleA(LPCSTR lpModuleName); +static BOOL STDCALL +my_GetModuleHandleExA(DWORD dwFlags, LPCSTR lpModuleName, HMODULE *phModule); +static BOOL STDCALL +my_GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule); +static HMODULE STDCALL my_GetModuleHandleW(LPCWSTR lpModuleName); +static HMODULE STDCALL my_LoadLibraryA(LPCSTR lpLibFileName); +static HMODULE STDCALL my_LoadLibraryW(LPCWSTR lpLibFileName); +static HMODULE STDCALL +my_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static HMODULE STDCALL +my_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static FARPROC STDCALL my_GetProcAddress(HMODULE hModule, LPCSTR lpProcName); + +static const struct hook_symbol _procmon_module_hook_syms[] = { + { + .name = "GetModuleHandleA", + .patch = my_GetModuleHandleA, + .link = (void **) &real_GetModuleHandleA, + }, + { + .name = "GetModuleHandleExA", + .patch = my_GetModuleHandleExA, + .link = (void **) &real_GetModuleHandleExA, + }, + { + .name = "GetModuleHandleExW", + .patch = my_GetModuleHandleExW, + .link = (void **) &real_GetModuleHandleExW, + }, + { + .name = "GetModuleHandleW", + .patch = my_GetModuleHandleW, + .link = (void **) &real_GetModuleHandleW, + }, + { + .name = "LoadLibraryA", + .patch = my_LoadLibraryA, + .link = (void **) &real_LoadLibraryA, + }, + { + .name = "LoadLibraryW", + .patch = my_LoadLibraryW, + .link = (void **) &real_LoadLibraryW, + }, + { + .name = "LoadLibraryExA", + .patch = my_LoadLibraryExA, + .link = (void **) &real_LoadLibraryExA, + }, + { + .name = "LoadLibraryExW", + .patch = my_LoadLibraryExW, + .link = (void **) &real_LoadLibraryExW, + }, + { + .name = "GetProcAddress", + .patch = my_GetProcAddress, + .link = (void **) &real_GetProcAddress, + }, +}; + +static HMODULE STDCALL my_GetModuleHandleA(LPCSTR lpModuleName) +{ + HMODULE result; + + log_misc("GetModuleHandleA(lpModuleName %s)", lpModuleName); + + result = real_GetModuleHandleA(lpModuleName); + + log_misc("GetModuleHandleA(lpModuleName %s) = %p", lpModuleName, result); + + return result; +} + +static BOOL STDCALL +my_GetModuleHandleExA(DWORD dwFlags, LPCSTR lpModuleName, HMODULE *phModule) +{ + BOOL result; + + log_misc( + "GetModuleHandleExA(dwFlags %lu, lpModuleName %s, phModule %p)", + dwFlags, + lpModuleName, + phModule); + + result = real_GetModuleHandleExA(dwFlags, lpModuleName, phModule); + + log_misc( + "GetModuleHandleExA(dwFlags %lu, lpModuleName %s, phModule %p) = %d", + dwFlags, + lpModuleName, + phModule, + result); + + return result; +} + +static BOOL STDCALL +my_GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule) +{ + BOOL result; + char *tmp; + + wstr_narrow(lpModuleName, &tmp); + + log_misc( + "GetModuleHandleExW(dwFlags %lu, lpModuleName %s, phModule %p)", + dwFlags, + tmp, + phModule); + + result = real_GetModuleHandleExW(dwFlags, lpModuleName, phModule); + + log_misc( + "GetModuleHandleExW(dwFlags %lu, lpModuleName %s, phModule %p) = %d", + dwFlags, + tmp, + phModule, + result); + + free(tmp); + + return result; +} + +static HMODULE STDCALL my_GetModuleHandleW(LPCWSTR lpModuleName) +{ + HMODULE result; + char *tmp; + + wstr_narrow(lpModuleName, &tmp); + + log_misc("GetModuleHandleW(lpModuleName %s)", tmp); + + result = real_GetModuleHandleW(lpModuleName); + + log_misc("GetModuleHandleW(lpModuleName %s) = %p", tmp, result); + + free(tmp); + + return result; +} + +static HMODULE STDCALL my_LoadLibraryA(LPCSTR lpLibFileName) +{ + HMODULE result; + + log_misc("LoadLibraryA(lpLibFileName %s)", lpLibFileName); + + result = real_LoadLibraryA(lpLibFileName); + + log_misc("LoadLibraryA(lpLibFileName %s) = %p", lpLibFileName, result); + + return result; +} + +static HMODULE STDCALL my_LoadLibraryW(LPCWSTR lpLibFileName) +{ + HMODULE result; + char *tmp; + + wstr_narrow(lpLibFileName, &tmp); + + log_misc("LoadLibraryW(lpLibFileName %s)", tmp); + + result = real_LoadLibraryW(lpLibFileName); + + log_misc("LoadLibraryW(lpLibFileName %s) = %p", tmp, result); + + free(tmp); + + return result; +} + +static HMODULE STDCALL +my_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) +{ + HMODULE result; + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu)", + lpLibFileName, + hFile, + dwFlags); + + result = real_LoadLibraryExA(lpLibFileName, hFile, dwFlags); + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu) = %p", + lpLibFileName, + hFile, + dwFlags, + result); + + return result; +} + +static HMODULE STDCALL +my_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) +{ + HMODULE result; + char *tmp; + + wstr_narrow(lpLibFileName, &tmp); + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu)", + tmp, + hFile, + dwFlags); + + result = real_LoadLibraryExW(lpLibFileName, hFile, dwFlags); + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu) = %p", + tmp, + hFile, + dwFlags, + result); + + free(tmp); + + return result; +} + +static FARPROC STDCALL my_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) +{ + FARPROC result; + + log_misc("GetProcAddress(hModule %p, lpProcName %s)", hModule, lpProcName); + + result = real_GetProcAddress(hModule, lpProcName); + + log_misc( + "GetProcAddress(hModule %p, lpProcName %s = %p", + hModule, + lpProcName, + result); + + return result; +} + +void procmon_module_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + _procmon_module_hook_syms, + lengthof(_procmon_module_hook_syms)); + + log_misc("init"); +} + +void procmon_module_fini() +{ + hook_table_revert( + NULL, + "kernel32.dll", + _procmon_module_hook_syms, + lengthof(_procmon_module_hook_syms)); + + log_misc("fini"); +} \ No newline at end of file diff --git a/src/main/procmon/module.h b/src/main/procmon/module.h new file mode 100644 index 00000000..8cb89129 --- /dev/null +++ b/src/main/procmon/module.h @@ -0,0 +1,7 @@ +#ifndef PROCMON_MODULE_H +#define PROCMON_MODULE_H + +void procmon_module_init(); +void procmon_module_fini(); + +#endif \ No newline at end of file diff --git a/src/main/procmon/procmon.c b/src/main/procmon/procmon.c new file mode 100644 index 00000000..cbbf9002 --- /dev/null +++ b/src/main/procmon/procmon.c @@ -0,0 +1,46 @@ +#include "iface-core/log.h" + +#include "procmon/file.h" +#include "procmon/module.h" +#include "procmon/procmon.h" +#include "procmon/thread.h" + +static bool _procmon_file_monitor_enabled; +static bool _procmon_module_monitor_enabled; +static bool _procmon_thread_monitor_enabled; + +void procmon_init(const procmon_config_t *config) +{ + log_assert(config); + + _procmon_file_monitor_enabled = config->file_enable; + _procmon_module_monitor_enabled = config->module_enable; + _procmon_thread_monitor_enabled = config->thread_enable; + + if (_procmon_file_monitor_enabled) { + procmon_file_init(); + } + + if (_procmon_module_monitor_enabled) { + procmon_module_init(); + } + + if (_procmon_thread_monitor_enabled) { + procmon_thread_init(); + } +} + +void procmon_fini() +{ + if (_procmon_thread_monitor_enabled) { + procmon_thread_fini(); + } + + if (_procmon_module_monitor_enabled) { + procmon_module_fini(); + } + + if (_procmon_file_monitor_enabled) { + procmon_file_fini(); + } +} \ No newline at end of file diff --git a/src/main/procmon/procmon.def b/src/main/procmon/procmon.def new file mode 100644 index 00000000..5e78a593 --- /dev/null +++ b/src/main/procmon/procmon.def @@ -0,0 +1,13 @@ +LIBRARY procmon + +EXPORTS + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_hook_api_get + + DllMain@12 @1 NONAME + + ; Direct API + bt_hook_main_init + bt_hook_main_fini diff --git a/src/main/procmon/procmon.h b/src/main/procmon/procmon.h new file mode 100644 index 00000000..8f6df217 --- /dev/null +++ b/src/main/procmon/procmon.h @@ -0,0 +1,10 @@ +#ifndef PROCMON_PROCMON_H +#define PROCMON_PROCMON_H + +#include "procmon/config.h" + +void procmon_init(const procmon_config_t *config); + +void procmon_fini(); + +#endif \ No newline at end of file diff --git a/src/main/procmon/thread.c b/src/main/procmon/thread.c new file mode 100644 index 00000000..27888dfc --- /dev/null +++ b/src/main/procmon/thread.c @@ -0,0 +1,106 @@ +#define LOG_MODULE "procmon-thread" + +#include + +#include "hook/table.h" + +#include "iface-core/log.h" + +#ifdef _WIN64 +#define SIZE_T_FORMAT_SPECIFIER "llu" +#else +#define SIZE_T_FORMAT_SPECIFIER "lu" +#endif + +static HANDLE(STDCALL *real_CreateThread)( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId); + +static HANDLE STDCALL my_CreateThread( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId); + +static const struct hook_symbol _procmon_thread_hook_syms[] = { + { + .name = "CreateThread", + .patch = my_CreateThread, + .link = (void **) &real_CreateThread, + }, +}; + +static HANDLE STDCALL my_CreateThread( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId) +{ + HANDLE result; + + log_misc( + "CreateThread(lpThreadAttributes %p, dwStackSize " + "%" SIZE_T_FORMAT_SPECIFIER + ", lpStartAddress %p, lpParameter %p, dwCreationFlags %lu, lpThreadId " + "%p)", + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + lpThreadId); + + result = real_CreateThread( + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + lpThreadId); + + log_misc( + "CreateThread(lpThreadAttributes %p, dwStackSize " + "%" SIZE_T_FORMAT_SPECIFIER + ", lpStartAddress %p, lpParameter %p, dwCreationFlags %lu, lpThreadId " + "%p) = %p, tid %lu", + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + lpThreadId, + result, + lpThreadId ? *lpThreadId : -1); + + return result; +} + +void procmon_thread_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + _procmon_thread_hook_syms, + lengthof(_procmon_thread_hook_syms)); + + log_misc("init"); +} + +void procmon_thread_fini() +{ + hook_table_revert( + NULL, + "kernel32.dll", + _procmon_thread_hook_syms, + lengthof(_procmon_thread_hook_syms)); + + log_misc("fini"); +} \ No newline at end of file diff --git a/src/main/procmon/thread.h b/src/main/procmon/thread.h new file mode 100644 index 00000000..c90e89c9 --- /dev/null +++ b/src/main/procmon/thread.h @@ -0,0 +1,7 @@ +#ifndef PROCMON_THREAD_H +#define PROCMON_THREAD_H + +void procmon_thread_init(); +void procmon_thread_fini(); + +#endif \ No newline at end of file diff --git a/src/main/sdk-hook/Module.mk b/src/main/sdk-hook/Module.mk new file mode 100644 index 00000000..e0d28de0 --- /dev/null +++ b/src/main/sdk-hook/Module.mk @@ -0,0 +1,13 @@ +libs += sdk-hook + +ldflags_sdk-hook := \ + -lshlwapi \ + +libs_sdk-hook := \ + util \ + +src_sdk-hook := \ + dllentry.c \ + hooks-config.c \ + inject-config.c \ + logger-config.c \ diff --git a/src/main/sdk-hook/dllentry.c b/src/main/sdk-hook/dllentry.c new file mode 100644 index 00000000..3b79c55a --- /dev/null +++ b/src/main/sdk-hook/dllentry.c @@ -0,0 +1,215 @@ +#define LOG_MODULE "hook-dllentry" + +// clang-format off +// Don't format because the order is important here +#include +#include +// clang-format on + +#include + +#include "core/boot.h" +#include "core/config-property-node.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/property-ext.h" +#include "core/property-node.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface/hook.h" + +#include "iidxhook1/iidxhook1.h" + +#include "main/module/core.h" +#include "main/module/hook.h" + +#include "sdk-hook/inject-config.h" + +#include "util/str.h" + +static HMODULE _bt_hook_dllentry_hook_module; +static bt_hook_t *_bt_hook_dllentry_hook; +static bt_hook_inject_config_t _bt_hook_dllentry_inject_config; + +static void _bt_hook_dllentry_current_module_name_get(char *name, size_t len) +{ + char path[MAX_PATH]; + const char *filename; + + log_assert(name); + log_assert(len > 0); + + if (GetModuleFileName(_bt_hook_dllentry_hook_module, path, MAX_PATH) != 0) { + filename = PathFindFileName(path); + + str_cpy(name, len, filename); + } else { + log_fatal("GetModuleFileName to get current module name failed"); + } +} + +static const core_property_t *_bt_hook_dllentry_hook_property_config_get() +{ + char current_module_name[MAX_PATH]; + const struct bt_hook_hooks_hook_config *configs; + const char *filename; + int i; + + _bt_hook_dllentry_current_module_name_get(current_module_name, sizeof(current_module_name)); + + configs = _bt_hook_dllentry_inject_config.hooks.hooks; + + for (i = 0; i < BT_HOOK_HOOKS_CONFIG_MAX_HOOKS; i++) { + filename = PathFindFileName(configs[i].path); + + if (str_eq(current_module_name, filename)) { + log_misc("Property hook config for %s", configs[i].path); + core_property_ext_log(configs[i].config, log_misc_func); + + return configs[i].config; + } + } + + log_fatal("Could not find hook configuration for module %s in inject configuration", current_module_name); +} + +static void _bt_hook_dllentry_config_load() +{ + char inject_config_path[MAX_PATH]; + + // Duct-tape to allow access to config path and load config in hook dlls + GetEnvironmentVariable("INJECT_CONFIG_PATH", inject_config_path, sizeof(inject_config_path)); + + // With DllMain as the only callable entry point from inject, + // the only way to get the configuration for the hook is through + // injects configuration file + command line arguments + // Thus, the whole loading process (that is also done in inject) + // is replicated here (inject config etc. are also copy-pasted from + // the inject module) + bt_hook_inject_config_init(&_bt_hook_dllentry_inject_config); + bt_hook_inject_config_file_load(inject_config_path, &_bt_hook_dllentry_inject_config); +} + +static void _bt_hook_dllentry_logger_reinit() +{ + // Apply same logger configurations as inject + if (!_bt_hook_dllentry_inject_config.logger.enable) { + core_log_bt_fini(); + + core_log_bt_ext_init_with_null(); + } else { + // Logger already initialized previously, just switch log level + core_log_bt_level_set(_bt_hook_dllentry_inject_config.logger.level); + } +} + +void bt_hook_dllentry_init( + HMODULE module, + const char* name, + bt_module_core_config_api_set_t hook_config_api_set, + bt_module_core_log_api_set_t hook_log_api_set, + bt_module_core_thread_api_set_t hook_thread_api_set, + bt_module_hook_api_get_t hook_api_get) +{ + bt_core_config_api_t config_api; + bt_core_log_api_t log_api; + bt_core_thread_api_t thread_api; + bt_hook_api_t hook_api; + + core_boot_dll(name); + + // Debug logging is captured by debugger in inject and actually + // sunk to outputs there, e.g. terminal/file + core_log_bt_ext_init_with_debug(); + core_log_bt_core_api_set(); + // TODO change log level according to how inject is configured, read from config + command line args + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); + + _bt_hook_dllentry_config_load(); + + _bt_hook_dllentry_logger_reinit(); + + // Assert after log init to get visible error output if these fail + log_assert(module); + log_assert(hook_config_api_set); + log_assert(hook_log_api_set); + log_assert(hook_thread_api_set); + log_assert(hook_api_get); + + _bt_hook_dllentry_hook_module = module; + + bt_core_config_api_get(&config_api); + bt_core_log_api_get(&log_api); + bt_core_thread_api_get(&thread_api); + + hook_config_api_set(&config_api); + hook_log_api_set(&log_api); + hook_thread_api_set(&thread_api); + + hook_api_get(&hook_api); + + bt_hook_init(&hook_api, name, &_bt_hook_dllentry_hook); + + log_misc("<<< bt_hook_dllentry_boot_init"); +} + +void bt_hook_dllentry_fini() +{ + log_misc(">>> bt_hook_dllentry_fini"); + + bt_hook_inject_config_fini(&_bt_hook_dllentry_inject_config); + + bt_hook_fini(&_bt_hook_dllentry_hook); + + core_log_bt_fini(); + + bt_core_config_api_clear(); + bt_core_log_api_clear(); + bt_core_thread_api_clear(); +} + +void bt_hook_dllentry_main_init() +{ + bool result; + const core_property_t *property; + core_property_node_t root_node; + bt_core_config_t *config; + core_property_result_t result_prop; + HMODULE game_module; + + log_misc(">>> bt_hook_dllentry_main_init"); + + property = _bt_hook_dllentry_hook_property_config_get(); + + result_prop = core_property_root_node_get(property, &root_node); + core_property_fatal_on_error(result_prop); + + core_config_property_node_init(&root_node, &config); + + // Because this is loaded into the game's process space, this yields the executable module + game_module = GetModuleHandle(NULL); + + result = bt_hook_main_init(_bt_hook_dllentry_hook, game_module, config); + + core_config_property_node_free(&config); + + if (!result) { + log_fatal("Calling hook main init failed"); + } + + log_misc("<<< bt_hook_dllentry_main_init"); +} + +void bt_hook_dllentry_main_fini() +{ + log_misc(">>> bt_hook_dllentry_boot_fini"); + + bt_hook_main_fini(_bt_hook_dllentry_hook); + + bt_hook_fini(&_bt_hook_dllentry_hook); + + log_misc("<<< bt_hook_dllentry_boot_fini"); +} diff --git a/src/main/sdk-hook/dllentry.h b/src/main/sdk-hook/dllentry.h new file mode 100644 index 00000000..079eb549 --- /dev/null +++ b/src/main/sdk-hook/dllentry.h @@ -0,0 +1,23 @@ +#ifndef BT_SDK_HOOK_DLLENTRY_H +#define BT_SDK_HOOK_DLLENTRY_H + +#include + +#include "main/module/core.h" +#include "main/module/hook.h" + +void bt_hook_dllentry_init( + HMODULE module, + const char *name, + bt_module_core_config_api_set_t hook_config_api_set, + bt_module_core_log_api_set_t hook_log_api_set, + bt_module_core_thread_api_set_t hook_thread_api_set, + bt_module_hook_api_get_t hook_api_get); + +void bt_hook_dllentry_fini(); + +void bt_hook_dllentry_main_init(); + +void bt_hook_dllentry_main_fini(); + +#endif \ No newline at end of file diff --git a/src/main/sdk-hook/hooks-config.c b/src/main/sdk-hook/hooks-config.c new file mode 100644 index 00000000..7336eaab --- /dev/null +++ b/src/main/sdk-hook/hooks-config.c @@ -0,0 +1,161 @@ +#define LOG_MODULE "bt-hook-inject-hooks-config" + +#include "core/property-ext.h" +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "sdk-hook/hooks-config.h" + +#define BT_HOOK_HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES 8 + +static core_property_t * +_bt_hook_hooks_config_layered_config_nodes_load(const core_property_node_t *node) +{ + char kind[64]; + char file[MAX_PATH]; + int cnt; + + core_property_node_t cur; + core_property_node_t tmp; + core_property_t *config_property[BT_HOOK_HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES]; + core_property_t *merged_property; + core_property_node_result_t result; + core_property_result_t prop_result; + + log_assert(node); + + cnt = 0; + result = core_property_node_search(node, "config", &cur); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + while (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + if (cnt >= BT_HOOK_HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES) { + log_fatal( + "Exceeding max supported config nodes for layering, max is %d", + BT_HOOK_HOOKS_CONFIG_MAX_LAYER_CONFIG_NODES); + } + + result = + core_property_node_attr_read(&cur, "kind", kind, sizeof(kind)); + + if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) { + log_fatal("Failed reading 'kind' attribute value of config node"); + } + + if (!strcmp(kind, "file")) { + core_property_node_str_read(&cur, file, sizeof(file)); + + prop_result = core_property_file_load(file, &config_property[cnt]); + core_property_fatal_on_error(prop_result); + } else if (!strcmp(kind, "inline")) { + // The nested child is the actual root of the inline, not the outer + // node + result = core_property_node_child_get(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + + result = + core_property_node_ext_extract(&cur, &config_property[cnt]); + core_property_node_fatal_on_error(result); + } else { + log_fatal( + "Unsupported 'kind' attribute value '%s' of config node", kind); + } + + cnt++; + result = core_property_node_next_result_search(&cur, &tmp); + memcpy(&cur, &tmp, sizeof(core_property_node_t)); + + if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + core_property_node_fatal_on_error(result); + } + } + + if (cnt == 0) { + prop_result = core_property_str_load("", &merged_property); + core_property_fatal_on_error(prop_result); + } else { + prop_result = + core_property_ext_many_merge(config_property, cnt, &merged_property); + core_property_fatal_on_error(prop_result); + + for (int i = 0; i < cnt; i++) { + core_property_free(&config_property[i]); + } + } + + return merged_property; +} + +static void _bt_hook_hooks_config_hooks_load( + const core_property_node_t *node, + struct bt_hook_hooks_hook_config *configs) +{ + core_property_node_result_t result; + core_property_node_t child; + core_property_node_t tmp; + uint8_t processed_hooks; + + processed_hooks = 0; + + result = core_property_node_search(node, "hook", &child); + + do { + if (processed_hooks >= BT_HOOK_HOOKS_CONFIG_MAX_HOOKS) { + log_fatal("Cannot load more hooks, max supported capacity reached"); + } + + if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) { + return; + } else { + core_property_node_fatal_on_error(result); + } + + result = core_property_node_ext_bool_read(&child, "enable", &configs[processed_hooks].enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(&child, "path", configs[processed_hooks].path, sizeof(configs[processed_hooks].path)); + core_property_node_fatal_on_error(result); + + configs[processed_hooks].config = _bt_hook_hooks_config_layered_config_nodes_load(&child); + + result = core_property_node_next_result_search(&child, &tmp); + memcpy(&child, &tmp, sizeof(core_property_node_t)); + + processed_hooks++; + } while (true); +} + +void bt_hook_hooks_config_init(bt_hook_hooks_config_t *config) +{ + log_assert(config); + + memset(config, 0, sizeof(bt_hook_hooks_config_t)); +} + +void bt_hook_hooks_config_load( + const core_property_node_t *node, bt_hook_hooks_config_t *config) +{ + log_assert(node); + log_assert(config); + + _bt_hook_hooks_config_hooks_load(node, config->hooks); +} + +void bt_hook_hooks_config_fini(bt_hook_hooks_config_t *config) +{ + uint32_t i; + + log_assert(config); + + for (i = 0; i < BT_HOOK_HOOKS_CONFIG_MAX_HOOKS; i++) { + core_property_free(&config->hooks[i].config); + } +} \ No newline at end of file diff --git a/src/main/sdk-hook/hooks-config.h b/src/main/sdk-hook/hooks-config.h new file mode 100644 index 00000000..62173d29 --- /dev/null +++ b/src/main/sdk-hook/hooks-config.h @@ -0,0 +1,28 @@ +#ifndef BT_SDK_HOOK_INJECT_HOOKS_CONFIG_H +#define BT_SDK_HOOK_INJECT_HOOKS_CONFIG_H + +#include + +#include + +#include "core/property.h" +#include "core/property-node.h" + +#define BT_HOOK_HOOKS_CONFIG_MAX_HOOKS 16 + +typedef struct bt_hook_hooks_config { + struct bt_hook_hooks_hook_config { + bool enable; + char path[MAX_PATH]; + core_property_t *config; + } hooks[BT_HOOK_HOOKS_CONFIG_MAX_HOOKS]; +} bt_hook_hooks_config_t; + +void bt_hook_hooks_config_init(bt_hook_hooks_config_t *config); + +void bt_hook_hooks_config_load( + const core_property_node_t *node, bt_hook_hooks_config_t *config); + +void bt_hook_hooks_config_fini(bt_hook_hooks_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/sdk-hook/inject-config.c b/src/main/sdk-hook/inject-config.c new file mode 100644 index 00000000..f828356a --- /dev/null +++ b/src/main/sdk-hook/inject-config.c @@ -0,0 +1,61 @@ +#define LOG_MODULE "bt-hook-inject-config" + +#include "core/property-ext.h" +#include "core/property-node.h" +#include "core/property.h" + +#include "core/property-mxml-internal.h" +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "sdk-hook/hooks-config.h" +#include "sdk-hook/inject-config.h" +#include "sdk-hook/logger-config.h" + +void bt_hook_inject_config_init(struct bt_hook_inject_config *config) +{ + log_assert(config); + + config->version = 1; + + bt_hook_hooks_config_init(&config->hooks); + bt_hook_logger_config_init(&config->logger); +} + +void bt_hook_inject_config_file_load(const char *path, bt_hook_inject_config_t *config) +{ + core_property_result_t result_prop; + core_property_node_result_t result; + core_property_t *property; + core_property_node_t root_node; + core_property_node_t child_node; + + log_info("Loading configuration file: %s", path); + + result_prop = core_property_file_load(path, &property); + core_property_fatal_on_error(result_prop); + + result = core_property_root_node_get(property, &root_node); + core_property_node_fatal_on_error(result); + + result = core_property_node_search(&root_node, "hooks", &child_node); + core_property_node_fatal_on_error(result); + bt_hook_hooks_config_load(&child_node, &config->hooks); + + result = core_property_node_search(&root_node, "logger", &child_node); + core_property_node_fatal_on_error(result); + bt_hook_logger_config_load(&child_node, &config->logger); + + core_property_free(&property); + + log_misc("Loading done"); +} + +void bt_hook_inject_config_fini(bt_hook_inject_config_t *config) +{ + log_assert(config); + + // Other configs don't have a fini + bt_hook_hooks_config_fini(&config->hooks); +} \ No newline at end of file diff --git a/src/main/sdk-hook/inject-config.h b/src/main/sdk-hook/inject-config.h new file mode 100644 index 00000000..a6d2e552 --- /dev/null +++ b/src/main/sdk-hook/inject-config.h @@ -0,0 +1,22 @@ +#ifndef BT_SDK_HOOK_INJECT_CONFIG_H +#define BT_SDK_HOOK_INJECT_CONFIG_H + +#include + +#include "sdk-hook/hooks-config.h" +#include "sdk-hook/logger-config.h" + +typedef struct bt_hook_inject_config { + uint32_t version; + + bt_hook_hooks_config_t hooks; + bt_hook_logger_config_t logger; +} bt_hook_inject_config_t; + +void bt_hook_inject_config_init(struct bt_hook_inject_config *config); + +void bt_hook_inject_config_file_load(const char *path, bt_hook_inject_config_t *config); + +void bt_hook_inject_config_fini(bt_hook_inject_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/sdk-hook/logger-config.c b/src/main/sdk-hook/logger-config.c new file mode 100644 index 00000000..62c8e0a0 --- /dev/null +++ b/src/main/sdk-hook/logger-config.c @@ -0,0 +1,52 @@ +#define LOG_MODULE "bt-hook-inject-logger-config" + +#include "core/property-node-ext.h" + +#include "iface-core/log.h" + +#include "sdk-hook/logger-config.h" + +#include "util/str.h" + +static enum core_log_bt_log_level _bt_hook_logger_config_str_to_loglevel(const char *str) +{ + log_assert(str); + + if (str_eq(str, "off")) { + return CORE_LOG_BT_LOG_LEVEL_OFF; + } else if (str_eq(str, "fatal")) { + return CORE_LOG_BT_LOG_LEVEL_FATAL; + } else if (str_eq(str, "warning")) { + return CORE_LOG_BT_LOG_LEVEL_WARNING; + } else if (str_eq(str, "info")) { + return CORE_LOG_BT_LOG_LEVEL_INFO; + } else if (str_eq(str, "misc")) { + return CORE_LOG_BT_LOG_LEVEL_MISC; + } else { + log_fatal("Invalid log level string in config: %s", str); + } +} + +void bt_hook_logger_config_init(bt_hook_logger_config_t *config) +{ + log_assert(config); + + memset(config, 0, sizeof(bt_hook_logger_config_t)); +} + +void bt_hook_logger_config_load( + const core_property_node_t *node, bt_hook_logger_config_t *config) +{ + core_property_node_result_t result; + char buffer[16]; + + log_assert(node); + log_assert(config); + + result = core_property_node_ext_bool_read(node, "enable", &config->enable); + core_property_node_fatal_on_error(result); + + result = core_property_node_ext_str_read(node, "level", buffer, sizeof(buffer)); + core_property_node_fatal_on_error(result); + config->level = _bt_hook_logger_config_str_to_loglevel(buffer); +} diff --git a/src/main/sdk-hook/logger-config.h b/src/main/sdk-hook/logger-config.h new file mode 100644 index 00000000..6ad89d8c --- /dev/null +++ b/src/main/sdk-hook/logger-config.h @@ -0,0 +1,23 @@ +#ifndef BT_SDK_HOOK_INJECT_LOGGER_CONFIG_H +#define BT_SDK_HOOK_INJECT_LOGGER_CONFIG_H + +#include +#include + +#include + +#include "core/log-bt.h" +#include "core/log-sink-async.h" +#include "core/property-node.h" + +typedef struct bt_hook_logger_config { + bool enable; + enum core_log_bt_log_level level; +} bt_hook_logger_config_t; + +void bt_hook_logger_config_init(bt_hook_logger_config_t *config); + +void bt_hook_logger_config_load( + const core_property_node_t *node, bt_hook_logger_config_t *config); + +#endif \ No newline at end of file diff --git a/src/main/sdvxhook/Module.mk b/src/main/sdvxhook/Module.mk index c1a8c5b0..926c42f8 100644 --- a/src/main/sdvxhook/Module.mk +++ b/src/main/sdvxhook/Module.mk @@ -3,13 +3,19 @@ avsdlls += sdvxhook deplibs_sdvxhook := \ avs \ +avslibs_sdvxhook := \ + avs-ext \ + libs_sdvxhook := \ + core \ acioemu \ hook \ hooklib \ util \ - eamio \ - sdvxio \ + iface \ + iface-io \ + iface-core \ + module \ src_sdvxhook := \ acio.c \ diff --git a/src/main/sdvxhook/acio.c b/src/main/sdvxhook/acio.c index 6596ee41..02d23e60 100644 --- a/src/main/sdvxhook/acio.c +++ b/src/main/sdvxhook/acio.c @@ -17,6 +17,8 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "imports/avs.h" #include "sdvxhook/acio.h" @@ -24,7 +26,6 @@ #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu ac_io_emu; diff --git a/src/main/sdvxhook/dllmain.c b/src/main/sdvxhook/dllmain.c index 391f4c99..ad55b16d 100644 --- a/src/main/sdvxhook/dllmain.c +++ b/src/main/sdvxhook/dllmain.c @@ -3,39 +3,94 @@ #include #include -#include "bemanitools/eamio.h" -#include "bemanitools/sdvxio.h" - #include "hook/iohook.h" #include "hooklib/app.h" #include "hooklib/rs232.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/sdvx.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + #include "sdvxhook/acio.h" #include "sdvxhook/gfx.h" #include "sdvxhook/lcd.h" #include "util/cmdline.h" #include "util/defs.h" -#include "util/log.h" -static bool my_dll_entry_init(char *sidcode, struct property_node *config); -static bool my_dll_entry_main(void); +static module_io_t *_sdvxhook_module_io_sdvx; +static module_io_t *_sdvxhook_module_io_eam; -static bool my_dll_entry_init(char *sidcode, struct property_node *config) +static void _sdvxhook_io_sdvx_init(module_io_t **module) +{ + bt_io_sdvx_api_t api; + + module_io_ext_load_and_init( + "sdvxio.dll", "bt_module_io_sdvx_api_get", module); + module_io_api_get(*module, &api); + bt_io_sdvx_api_set(&api); +} + +static void _sdvxhook_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_sdvxhook_main_init(HMODULE game_module, const bt_core_config_t *config_) { bool ok; + int i; + int argc; + char **argv; + + args_recover(&argc, &argv); + + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + continue; + } + + switch (argv[i][1]) { + case 'c': + gfx_set_confined(); + + break; + + case 'w': + gfx_set_windowed(); + + break; + } + } + + args_free(argc, argv); log_info("--- Begin sdvxhook dll_entry_init ---"); + gfx_init(); ac_io_bus_init(); log_info("Starting up SDVX IO backend"); - sdvx_io_set_loggers( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); + _sdvxhook_io_sdvx_init(&_sdvxhook_module_io_sdvx); - ok = sdvx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + ok = bt_io_sdvx_init(); if (!ok) { goto sdvx_io_fail; @@ -43,10 +98,9 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *config) log_info("Starting up card reader backend"); - eam_io_set_loggers( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); + _sdvxhook_io_eam_init(&_sdvxhook_module_io_eam); - ok = eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); + ok = bt_io_eam_init(); /* Set up IO emulation hooks _after_ IO API setup to allow API implementations with real IO devices */ @@ -62,10 +116,13 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *config) log_info("--- End sdvxhook dll_entry_init ---"); - return app_hook_invoke_init(sidcode, config); + return true; eam_io_fail: - sdvx_io_fini(); + bt_io_sdvx_fini(); + + bt_io_sdvx_api_clear(); + module_io_free(&_sdvxhook_module_io_sdvx); sdvx_io_fail: ac_io_bus_fini(); @@ -73,61 +130,42 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *config) return false; } -static bool my_dll_entry_main(void) +static void _sdvxhook_main_fini() { - bool result; - - result = app_hook_invoke_main(); - log_info("Shutting down card reader backend"); - eam_io_fini(); + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&_sdvxhook_module_io_eam); log_info("Shutting down SDVX IO backend"); - sdvx_io_fini(); + bt_io_sdvx_fini(); - ac_io_bus_fini(); + bt_io_sdvx_api_clear(); + module_io_free(&_sdvxhook_module_io_sdvx); - return result; + ac_io_bus_fini(); } -BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +void bt_module_core_log_api_set(const bt_core_log_api_t *api) { - int i; - int argc; - char **argv; - - if (reason != DLL_PROCESS_ATTACH) { - return TRUE; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - args_recover(&argc, &argv); - - for (i = 1; i < argc; i++) { - if (argv[i][0] != '-') { - continue; - } - - switch (argv[i][1]) { - case 'c': - gfx_set_confined(); - - break; - - case 'w': - gfx_set_windowed(); - - break; - } - } + bt_core_log_api_set(api); +} - args_free(argc, argv); +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} - app_hook_init(my_dll_entry_init, my_dll_entry_main); +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; - gfx_init(); + api->v1.main_init = _sdvxhook_main_init; + api->v1.main_fini = _sdvxhook_main_fini; +} +BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +{ return TRUE; } diff --git a/src/main/sdvxhook/gfx.c b/src/main/sdvxhook/gfx.c index 16cf7330..e7090ed0 100644 --- a/src/main/sdvxhook/gfx.c +++ b/src/main/sdvxhook/gfx.c @@ -7,10 +7,11 @@ #include "hook/pe.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "sdvxhook/gfx.h" #include "util/defs.h" -#include "util/log.h" static LRESULT CALLBACK my_WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); diff --git a/src/main/sdvxhook/kfca.c b/src/main/sdvxhook/kfca.c index 5c89686e..3980cb62 100644 --- a/src/main/sdvxhook/kfca.c +++ b/src/main/sdvxhook/kfca.c @@ -7,10 +7,10 @@ #include "acioemu/emu.h" -#include "bemanitools/sdvxio.h" +#include "iface-core/log.h" +#include "iface-io/sdvx.h" #include "util/defs.h" -#include "util/log.h" #include "util/time.h" static void kfca_send_version(const struct ac_io_message *req); @@ -122,7 +122,7 @@ static void kfca_amp_control(const struct ac_io_message *req) // bytes 0-4: main, headphone, unused, subwoofer - if (!sdvx_io_set_amp_volume( + if (!bt_io_sdvx_amp_volume_set( req->cmd.raw[0], req->cmd.raw[1], req->cmd.raw[3])) { log_warning("Unable to set amp volume?"); } @@ -142,13 +142,13 @@ static void kfca_poll(const struct ac_io_message *req) pout = &req->cmd.kfca_poll_out; - sdvx_io_set_gpio_lights(ac_io_u32(pout->gpio)); + bt_io_sdvx_gpio_lights_set(ac_io_u32(pout->gpio)); for (i = 0; i < lengthof(pout->pwm); i++) { - sdvx_io_set_pwm_light(i, pout->pwm[i]); + bt_io_sdvx_pwm_light_set(i, pout->pwm[i]); } - sdvx_io_write_output(); + bt_io_sdvx_output_write(); /* SDVX expects only one poll response per frame. @@ -187,17 +187,17 @@ static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp) resp->cmd.seq_no = req_seq_no; resp->cmd.nbytes = sizeof(*pin); - sdvx_io_read_input(); + bt_io_sdvx_input_read(); memset(pin, 0, sizeof(*pin)); - pin->adc[0] = sdvx_io_get_spinner_pos(0) << 6; - pin->adc[1] = sdvx_io_get_spinner_pos(1) << 6; + pin->adc[0] = bt_io_sdvx_spinner_pos_get(0) << 6; + pin->adc[1] = bt_io_sdvx_spinner_pos_get(1) << 6; - pin->gpio_sys |= sdvx_io_get_input_gpio_sys() & 0x3F; + pin->gpio_sys |= bt_io_sdvx_input_gpio_sys_get() & 0x3F; pin->adc[0] = ac_io_u16(pin->adc[0]); pin->adc[1] = ac_io_u16(pin->adc[1]); - pin->gpio[0] = ac_io_u16(sdvx_io_get_input_gpio(0)); - pin->gpio[1] = ac_io_u16(sdvx_io_get_input_gpio(1)); + pin->gpio[0] = ac_io_u16(bt_io_sdvx_input_gpio_get(0)); + pin->gpio[1] = ac_io_u16(bt_io_sdvx_input_gpio_get(1)); } diff --git a/src/main/sdvxhook/lcd.c b/src/main/sdvxhook/lcd.c index 06ea1e6c..b279e4f6 100644 --- a/src/main/sdvxhook/lcd.c +++ b/src/main/sdvxhook/lcd.c @@ -14,11 +14,12 @@ #include "hook/iohook.h" +#include "iface-core/log.h" + #include "sdvxhook/lcd.h" #include "util/hex.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static HRESULT lcd_open(struct irp *irp); diff --git a/src/main/sdvxhook/sdvxhook.def b/src/main/sdvxhook/sdvxhook.def index b692fa7a..a23971ff 100644 --- a/src/main/sdvxhook/sdvxhook.def +++ b/src/main/sdvxhook/sdvxhook.def @@ -2,3 +2,8 @@ LIBRARY sdvxhook EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/Module.mk b/src/main/sdvxhook2-cn/Module.mk index fd00fc62..9cb1d4ac 100644 --- a/src/main/sdvxhook2-cn/Module.mk +++ b/src/main/sdvxhook2-cn/Module.mk @@ -7,23 +7,32 @@ ldflags_sdvxhook2-cn := \ -lmf \ -lmfplat \ -lole32 \ + -lws2_32 \ deplibs_sdvxhook2-cn := \ avs \ +avslibs_sdvxhook2-cn:= \ + avs-ext \ + libs_sdvxhook2-cn := \ + core \ acioemu \ camhook \ d3d9exhook \ - sdvxio \ hook \ hooklib \ - cconfig \ util \ + iface \ + iface-io \ + iface-core \ + module \ + security \ src_sdvxhook2-cn := \ acio.c \ - kfca.c \ - dllmain.c \ config-cn.c \ + dllmain.c \ + kfca.c \ + sdvxhook2-cn.c \ unis-version.c \ diff --git a/src/main/sdvxhook2-cn/acio.c b/src/main/sdvxhook2-cn/acio.c index f7116e28..2d45a970 100644 --- a/src/main/sdvxhook2-cn/acio.c +++ b/src/main/sdvxhook2-cn/acio.c @@ -17,6 +17,8 @@ #include "hook/iohook.h" #include "hooklib/rs232.h" +#include "iface-core/log.h" + #include "sdvxhook2-cn/acio.h" #include "sdvxhook2-cn/kfca.h" @@ -24,7 +26,6 @@ #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu ac_io_emu; diff --git a/src/main/sdvxhook2-cn/config-cn.c b/src/main/sdvxhook2-cn/config-cn.c index c492603e..1a2c99e8 100644 --- a/src/main/sdvxhook2-cn/config-cn.c +++ b/src/main/sdvxhook2-cn/config-cn.c @@ -1,55 +1,10 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "sdvxhook2-cn/config-cn.h" -#include "util/log.h" - -#define SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY "io.disable_io_emu" -#define SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY "cn.unis_path" - -#define SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE false -#define SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE "prop/unis.xml" - -void sdvxhook2_cn_config_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY, - SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE, - "Disable IO emulation and enable usage of real KFCA hardware"); - - cconfig_util_set_str( - config, - SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY, - SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE, - "Path to unis version file under the prop.s folder"); -} - void sdvxhook2_cn_config_get( - struct sdvxhook2_cn_config *cn_config, struct cconfig *config) + const bt_core_config_t *config, sdvxhook2_cn_config_t *config_out) { - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY, - &cn_config->disable_io_emu, - SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY, - SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE); - } - - if (!cconfig_util_get_str( - config, - SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY, - cn_config->unis_path, - sizeof(cn_config->unis_path), - SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY, - SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE); - } + bt_core_config_ext_bool_get(config, "io/disable_io_emu", &config_out->disable_io_emu); + bt_core_config_ext_str_get(config, "cn/unis_path", config_out->unis_path, sizeof(config_out->unis_path)); } diff --git a/src/main/sdvxhook2-cn/config-cn.h b/src/main/sdvxhook2-cn/config-cn.h index 7458b112..f7a738bf 100644 --- a/src/main/sdvxhook2-cn/config-cn.h +++ b/src/main/sdvxhook2-cn/config-cn.h @@ -1,18 +1,16 @@ #ifndef SDVXHOOK2_CN_CONFIG_H #define SDVXHOOK2_CN_CONFIG_H -#include +#include -#include "cconfig/cconfig.h" +#include "api/core/config.h" -struct sdvxhook2_cn_config { +typedef struct sdvxhook2_cn_config { bool disable_io_emu; char unis_path[256]; -}; - -void sdvxhook2_cn_config_init(struct cconfig *config); +} sdvxhook2_cn_config_t; void sdvxhook2_cn_config_get( - struct sdvxhook2_cn_config *cn_config, struct cconfig *config); + const bt_core_config_t *config, sdvxhook2_cn_config_t *config_out); #endif \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/dllmain.c b/src/main/sdvxhook2-cn/dllmain.c index d94cade5..f8f6588d 100644 --- a/src/main/sdvxhook2-cn/dllmain.c +++ b/src/main/sdvxhook2-cn/dllmain.c @@ -1,148 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/sdvxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/rs232.h" - -#include "sdvxhook2-cn/acio.h" -#include "sdvxhook2-cn/config-cn.h" -#include "sdvxhook2-cn/unis-version.h" - -#include "camhook/cam.h" -#include "camhook/config-cam.h" - -#include "d3d9exhook/config-gfx.h" -#include "d3d9exhook/d3d9ex.h" - -#include "imports/avs.h" - -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#define SDVXHOOK2_CN_INFO_HEADER \ - "sdvxhook for VW CN" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n" -#define SDVXHOOK2_CN_CMD_USAGE \ - "Usage: launcher.exe -K sdvxhook2.dll [options...]" - -struct sdvxhook2_cn_config config_cn; -struct camhook_config_cam config_cam; -struct d3d9exhook_config_gfx config_gfx; - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - struct cconfig *config; - - log_info("--- Begin sdvxhook dll_entry_init ---"); - - config = cconfig_init(); - - sdvxhook2_cn_config_init(config); - d3d9exhook_config_gfx_init(config); - camhook_config_cam_init(config, 1, false); - - if (!cconfig_hook_config_init( - config, - SDVXHOOK2_CN_INFO_HEADER "\n" SDVXHOOK2_CN_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - sdvxhook2_cn_config_get(&config_cn, config); - camhook_config_cam_get(&config_cam, config, 1, false); - d3d9exhook_config_gfx_get(&config_gfx, config); - - cconfig_finit(config); - - log_info(SDVXHOOK2_CN_INFO_HEADER); - log_info("Initializing sdvxhook2-cn..."); - - d3d9ex_configure(&config_gfx); - - /* Start up sdvxio.DLL */ - if (!config_cn.disable_io_emu) { - log_info("Starting sdvx IO backend"); - sdvx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!sdvx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing sdvx IO backend failed"); - } - } - - /* iohooks are okay, even if emu is diabled since the fake handlers won't be - * used */ - iohook_push_handler(ac_io_port_dispatch_irp); - - rs232_hook_init(); - rs232_hook_limit_hooks(); - - if (!config_cn.disable_io_emu) { - ac_io_port_init(); - } - - // camera hooks - if (!config_cam.disable_emu) { - camhook_init(&config_cam); - } - - unis_version_hook_init(config_cn.unis_path); - - log_info("--- End sdvxhook dll_entry_init ---"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - if (!config_cam.disable_emu) { - camhook_fini(); - } - - if (!config_cn.disable_io_emu) { - log_misc("Shutting down sdvx IO backend"); - sdvx_io_fini(); - } - - return result; -} - -/** - * Hook library SDVX5 CN - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - acp_hook_init(); - adapter_hook_init(); - d3d9ex_hook_init(); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/kfca.c b/src/main/sdvxhook2-cn/kfca.c index f4d88948..b14476d9 100644 --- a/src/main/sdvxhook2-cn/kfca.c +++ b/src/main/sdvxhook2-cn/kfca.c @@ -7,10 +7,10 @@ #include "acioemu/emu.h" -#include "bemanitools/sdvxio.h" +#include "iface-core/log.h" +#include "iface-io/sdvx.h" #include "util/defs.h" -#include "util/log.h" #include "util/time.h" static void kfca_send_version(const struct ac_io_message *req); @@ -135,13 +135,13 @@ static void kfca_poll(const struct ac_io_message *req) pout = &req->cmd.kfca_poll_out; - sdvx_io_set_gpio_lights(ac_io_u32(pout->gpio)); + bt_io_sdvx_gpio_lights_set(ac_io_u32(pout->gpio)); for (i = 0; i < lengthof(pout->pwm); i++) { - sdvx_io_set_pwm_light(i, pout->pwm[i]); + bt_io_sdvx_pwm_light_set(i, pout->pwm[i]); } - sdvx_io_write_output(); + bt_io_sdvx_output_write(); /* SDVX expects only one poll response per frame. @@ -180,17 +180,17 @@ static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp) resp->cmd.seq_no = req_seq_no; resp->cmd.nbytes = sizeof(*pin); - sdvx_io_read_input(); + bt_io_sdvx_input_read(); memset(pin, 0, sizeof(*pin)); - pin->adc[0] = sdvx_io_get_spinner_pos(0) << 6; - pin->adc[1] = sdvx_io_get_spinner_pos(1) << 6; + pin->adc[0] = bt_io_sdvx_spinner_pos_get(0) << 6; + pin->adc[1] = bt_io_sdvx_spinner_pos_get(1) << 6; - pin->gpio_sys |= sdvx_io_get_input_gpio_sys() & 0x3F; + pin->gpio_sys |= bt_io_sdvx_input_gpio_sys_get() & 0x3F; pin->adc[0] = ac_io_u16(pin->adc[0]); pin->adc[1] = ac_io_u16(pin->adc[1]); - pin->gpio[0] = ac_io_u16(sdvx_io_get_input_gpio(0)); - pin->gpio[1] = ac_io_u16(sdvx_io_get_input_gpio(1)); + pin->gpio[0] = ac_io_u16(bt_io_sdvx_input_gpio_get(0)); + pin->gpio[1] = ac_io_u16(bt_io_sdvx_input_gpio_get(1)); } diff --git a/src/main/sdvxhook2-cn/sdvxhook2-cn.c b/src/main/sdvxhook2-cn/sdvxhook2-cn.c new file mode 100644 index 00000000..420e77c2 --- /dev/null +++ b/src/main/sdvxhook2-cn/sdvxhook2-cn.c @@ -0,0 +1,138 @@ +#include + +#include +#include +#include +#include + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/sdvx.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "sdvxhook2-cn/acio.h" +#include "sdvxhook2-cn/config-cn.h" +#include "sdvxhook2-cn/unis-version.h" + +#include "camhook/cam.h" +#include "camhook/config-cam.h" + +#include "d3d9exhook/config-gfx.h" +#include "d3d9exhook/d3d9ex.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/str.h" + +static sdvxhook2_cn_config_t _sdvxhook2_cn_config; +static camhook_config_cam_t _sdvxhook2_cn_config_cam; +static d3d9exhook_config_gfx_t _sdvxhook2_cn_config_gfx; + +static module_io_t *_sdvxhook2_cn_module_io_sdvx; + +static void _sdvxhook2_cn_io_sdvx_init(module_io_t **module) +{ + bt_io_sdvx_api_t api; + + module_io_ext_load_and_init( + "sdvxio.dll", "bt_module_io_sdvx_api_get", module); + module_io_api_get(*module, &api); + bt_io_sdvx_api_set(&api); +} + +static bool +_sdvxhook2_cn_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + log_info("sdvxhook for Vivid Wave CN"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + sdvxhook2_cn_config_get(config, &_sdvxhook2_cn_config); + camhook_config_cam_get(config, &_sdvxhook2_cn_config_cam, 1, false); + d3d9exhook_config_gfx_get(config, &_sdvxhook2_cn_config_gfx); + + acp_hook_init(); + adapter_hook_init(); + d3d9ex_hook_init(); + + d3d9ex_configure(&_sdvxhook2_cn_config_gfx); + + /* Start up sdvxio.DLL */ + if (!_sdvxhook2_cn_config.disable_io_emu) { + log_info("Starting sdvx IO backend"); + + _sdvxhook2_cn_io_sdvx_init(&_sdvxhook2_cn_module_io_sdvx); + + if (!bt_io_sdvx_init()) { + log_fatal("Initializing sdvx IO backend failed"); + } + } + + /* iohooks are okay, even if emu is diabled since the fake handlers won't be + * used */ + iohook_push_handler(ac_io_port_dispatch_irp); + + rs232_hook_init(); + rs232_hook_limit_hooks(); + + if (!_sdvxhook2_cn_config.disable_io_emu) { + ac_io_port_init(); + } + + // camera hooks + if (!_sdvxhook2_cn_config_cam.disable_emu) { + camhook_init(&_sdvxhook2_cn_config_cam); + } + + unis_version_hook_init(_sdvxhook2_cn_config.unis_path); + + return true; +} + +static void _sdvxhook2_cn_main_fini() +{ + if (!_sdvxhook2_cn_config_cam.disable_emu) { + camhook_fini(); + } + + if (!_sdvxhook2_cn_config.disable_io_emu) { + log_misc("Shutting down sdvx IO backend"); + + bt_io_sdvx_fini(); + + bt_io_sdvx_api_clear(); + module_io_free(&_sdvxhook2_cn_module_io_sdvx); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _sdvxhook2_cn_main_init; + api->v1.main_fini = _sdvxhook2_cn_main_fini; +} \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/sdvxhook2-cn.def b/src/main/sdvxhook2-cn/sdvxhook2-cn.def index dc4610b5..1db94ef1 100644 --- a/src/main/sdvxhook2-cn/sdvxhook2-cn.def +++ b/src/main/sdvxhook2-cn/sdvxhook2-cn.def @@ -2,3 +2,9 @@ LIBRARY sdvxhook2-cn EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/sdvxhook2-cn.h b/src/main/sdvxhook2-cn/sdvxhook2-cn.h new file mode 100644 index 00000000..9aa224f7 --- /dev/null +++ b/src/main/sdvxhook2-cn/sdvxhook2-cn.h @@ -0,0 +1,9 @@ +#ifndef SDVXHOOK2_CN_H +#define SDVXHOOK2_CN_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/unis-version.c b/src/main/sdvxhook2-cn/unis-version.c index d6609992..f88d6188 100644 --- a/src/main/sdvxhook2-cn/unis-version.c +++ b/src/main/sdvxhook2-cn/unis-version.c @@ -11,8 +11,9 @@ #include "hook/com-proxy.h" #include "hook/table.h" +#include "iface-core/log.h" + #include "util/defs.h" -#include "util/log.h" #include "util/str.h" #include "util/time.h" diff --git a/src/main/sdvxhook2/Module.mk b/src/main/sdvxhook2/Module.mk index aa38c669..3e087831 100644 --- a/src/main/sdvxhook2/Module.mk +++ b/src/main/sdvxhook2/Module.mk @@ -7,26 +7,34 @@ ldflags_sdvxhook2 := \ -lmf \ -lmfplat \ -lole32 \ + -lws2_32 \ deplibs_sdvxhook2 := \ avs \ +avslibs_sdvxhook2 := \ + avs-ext \ + libs_sdvxhook2 := \ + core \ acioemu \ bio2emu \ camhook \ d3d9exhook \ - sdvxio \ hook \ hooklib \ - cconfig \ util \ - eamio \ + iface \ + iface-io \ + iface-core \ + module \ + security \ src_sdvxhook2 := \ acio.c \ bi2a.c \ - dllmain.c \ config-io.c \ + dllmain.c \ nvapi.c \ power.c \ + sdvxhook2.c \ diff --git a/src/main/sdvxhook2/acio.c b/src/main/sdvxhook2/acio.c index 6ac0cdca..564b17bb 100644 --- a/src/main/sdvxhook2/acio.c +++ b/src/main/sdvxhook2/acio.c @@ -18,13 +18,14 @@ #include "hook/iohook.h" #include "hooklib/rs232.h" +#include "iface-core/log.h" + #include "sdvxhook2/acio.h" #include "imports/avs.h" #include "util/defs.h" #include "util/iobuf.h" -#include "util/log.h" #include "util/str.h" static struct ac_io_emu ac_io_emu; diff --git a/src/main/sdvxhook2/bi2a.c b/src/main/sdvxhook2/bi2a.c index f71230c7..ac4f0250 100644 --- a/src/main/sdvxhook2/bi2a.c +++ b/src/main/sdvxhook2/bi2a.c @@ -10,7 +10,7 @@ #include "bio2emu/emu.h" #include "sdvxhook2/bi2a.h" -#include "bemanitools/sdvxio.h" +#include "iface-io/sdvx.h" static void bio2_emu_bi2a_cmd_send_version( struct ac_io_emu *emu, const struct ac_io_message *req); @@ -209,44 +209,44 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req) gpio |= assign_light(0x01, pout->gpio[5]); gpio |= assign_light(0x02, pout->gpio[6]); - sdvx_io_set_gpio_lights(gpio); + bt_io_sdvx_gpio_lights_set(gpio); - sdvx_io_set_pwm_light(0x0, pout->wingUpper[0]); - sdvx_io_set_pwm_light(0x1, pout->wingUpper[1]); - sdvx_io_set_pwm_light(0x2, pout->wingUpper[2]); - sdvx_io_set_pwm_light(0x3, pout->wingUpper[0]); - sdvx_io_set_pwm_light(0x4, pout->wingUpper[1]); - sdvx_io_set_pwm_light(0x5, pout->wingUpper[2]); + bt_io_sdvx_pwm_light_set(0x0, pout->wingUpper[0]); + bt_io_sdvx_pwm_light_set(0x1, pout->wingUpper[1]); + bt_io_sdvx_pwm_light_set(0x2, pout->wingUpper[2]); + bt_io_sdvx_pwm_light_set(0x3, pout->wingUpper[0]); + bt_io_sdvx_pwm_light_set(0x4, pout->wingUpper[1]); + bt_io_sdvx_pwm_light_set(0x5, pout->wingUpper[2]); - sdvx_io_set_pwm_light(0x6, pout->wingLower[0]); - sdvx_io_set_pwm_light(0x7, pout->wingLower[1]); - sdvx_io_set_pwm_light(0x8, pout->wingLower[2]); - sdvx_io_set_pwm_light(0x9, pout->wingLower[0]); - sdvx_io_set_pwm_light(0xA, pout->wingLower[1]); - sdvx_io_set_pwm_light(0xB, pout->wingLower[2]); + bt_io_sdvx_pwm_light_set(0x6, pout->wingLower[0]); + bt_io_sdvx_pwm_light_set(0x7, pout->wingLower[1]); + bt_io_sdvx_pwm_light_set(0x8, pout->wingLower[2]); + bt_io_sdvx_pwm_light_set(0x9, pout->wingLower[0]); + bt_io_sdvx_pwm_light_set(0xA, pout->wingLower[1]); + bt_io_sdvx_pwm_light_set(0xB, pout->wingLower[2]); - sdvx_io_set_pwm_light(0xC, pout->woof_r); - sdvx_io_set_pwm_light(0xD, pout->woof_g); - sdvx_io_set_pwm_light(0xE, pout->woof_b); + bt_io_sdvx_pwm_light_set(0xC, pout->woof_r); + bt_io_sdvx_pwm_light_set(0xD, pout->woof_g); + bt_io_sdvx_pwm_light_set(0xE, pout->woof_b); - sdvx_io_set_pwm_light(0xF, pout->controller[0]); - sdvx_io_set_pwm_light(0x10, pout->controller[1]); - sdvx_io_set_pwm_light(0x11, pout->controller[2]); + bt_io_sdvx_pwm_light_set(0xF, pout->controller[0]); + bt_io_sdvx_pwm_light_set(0x10, pout->controller[1]); + bt_io_sdvx_pwm_light_set(0x11, pout->controller[2]); - sdvx_io_write_output(); + bt_io_sdvx_output_write(); - sdvx_io_read_input(); - uint8_t sys = sdvx_io_get_input_gpio_sys(); - uint16_t gpio0 = sdvx_io_get_input_gpio(0); - uint16_t gpio1 = sdvx_io_get_input_gpio(1); + bt_io_sdvx_input_read(); + uint8_t sys = bt_io_sdvx_input_gpio_sys_get(); + uint16_t gpio0 = bt_io_sdvx_input_gpio_get(0); + uint16_t gpio1 = bt_io_sdvx_input_gpio_get(1); // TODO: Make a counter or smth to counteract the accuracy lost in *4 - pin->analogs[0].a_val = sdvx_io_get_spinner_pos(0); - pin->analogs[1].a_val = sdvx_io_get_spinner_pos(1); + pin->analogs[0].a_val = bt_io_sdvx_spinner_pos_get(0); + pin->analogs[1].a_val = bt_io_sdvx_spinner_pos_get(1); - pin->analogs[0].a_test = check_pin(sys, SDVX_IO_IN_GPIO_SYS_TEST); - pin->analogs[0].a_service = check_pin(sys, SDVX_IO_IN_GPIO_SYS_SERVICE); - pin->analogs[0].a_coin = check_pin(sys, SDVX_IO_IN_GPIO_SYS_COIN); + pin->analogs[0].a_test = check_pin(sys, BT_IO_SDVX_IN_GPIO_SYS_TEST); + pin->analogs[0].a_service = check_pin(sys, BT_IO_SDVX_IN_GPIO_SYS_SERVICE); + pin->analogs[0].a_coin = check_pin(sys, BT_IO_SDVX_IN_GPIO_SYS_COIN); if (pin->analogs[0].a_coin) { if (!coin_latch) { @@ -263,17 +263,18 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req) pin->raw[0] = ac_io_u16(pin->raw[0]); pin->raw[1] = ac_io_u16(pin->raw[1]); - pin->buttons_1.b_start = check_pin(gpio0, SDVX_IO_IN_GPIO_0_START); - pin->buttons_1.b_headphone = check_pin(gpio0, SDVX_IO_IN_GPIO_0_HEADPHONE); + pin->buttons_1.b_start = check_pin(gpio0, BT_IO_SDVX_IN_GPIO_0_START); + pin->buttons_1.b_headphone = + check_pin(gpio0, BT_IO_SDVX_IN_GPIO_0_HEADPHONE); if (force_headphones_on) { pin->buttons_1.b_headphone = 1; } - pin->buttons_1.b_a = check_pin(gpio0, SDVX_IO_IN_GPIO_0_A); - pin->buttons_1.b_b = check_pin(gpio0, SDVX_IO_IN_GPIO_0_B); - pin->buttons_1.b_c = check_pin(gpio0, SDVX_IO_IN_GPIO_0_C); - pin->buttons_1.b_d = check_pin(gpio1, SDVX_IO_IN_GPIO_1_D); - pin->buttons_1.b_fxl = check_pin(gpio1, SDVX_IO_IN_GPIO_1_FX_L); - pin->buttons_2.b_fxr = check_pin(gpio1, SDVX_IO_IN_GPIO_1_FX_R); + pin->buttons_1.b_a = check_pin(gpio0, BT_IO_SDVX_IN_GPIO_0_A); + pin->buttons_1.b_b = check_pin(gpio0, BT_IO_SDVX_IN_GPIO_0_B); + pin->buttons_1.b_c = check_pin(gpio0, BT_IO_SDVX_IN_GPIO_0_C); + pin->buttons_1.b_d = check_pin(gpio1, BT_IO_SDVX_IN_GPIO_1_D); + pin->buttons_1.b_fxl = check_pin(gpio1, BT_IO_SDVX_IN_GPIO_1_FX_L); + pin->buttons_2.b_fxr = check_pin(gpio1, BT_IO_SDVX_IN_GPIO_1_FX_R); ac_io_emu_response_push(emu, &resp, 0); } diff --git a/src/main/sdvxhook2/config-io.c b/src/main/sdvxhook2/config-io.c index 6d87bc0b..9f3700c6 100644 --- a/src/main/sdvxhook2/config-io.c +++ b/src/main/sdvxhook2/config-io.c @@ -1,180 +1,16 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "sdvxhook2/config-io.h" -#include "util/log.h" - -#define SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY \ - "io.disable_card_reader_emu" -#define SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY "io.disable_bio2_emu" -#define SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter" -#define SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY "io.force_headphones" -#define SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY "io.disable_file_hooks" -#define SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY "io.disable_power_hooks" -#define SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY "io.disable_nvapi_hooks" -#define SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY "io.com1_card_reader" - -#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false -#define SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE false - -void sdvxhook2_config_io_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE, - "Disable card reader emulation and enable usage of real card reader " - "hardware on COM2"); - - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE, - "Disable BIO2 emulation and enable usage of real BIO2 hardware"); - - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE, - "Disables the poll limiter, warning very high CPU usage may arise"); - - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE, - "Forces game to think headphones are attached"); - - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE, - "Disables the built in file hooks, requiring manual file creation " - "(/dev/raw/j.dest)"); - - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE, - "Disables the built in power control hooks, allowing game to modify " - "system power settings"); - - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE, - "Disables the built in NVAPI control hooks, allowing game to modify " - "system monitor settings"); - - cconfig_util_set_bool( - config, - SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE, - "Emulates the card reader on COM1 instead of COM2"); -} - void sdvxhook2_config_io_get( - struct sdvxhook2_config_io *config_io, struct cconfig *config) + const bt_core_config_t *config, sdvxhook2_config_io_t *config_out) { - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - &config_io->disable_card_reader_emu, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE); - } - - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - &config_io->disable_bio2_emu, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE); - } - - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - &config_io->disable_poll_limiter, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE); - } - - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY, - &config_io->force_headphones, - SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE); - } - - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, - &config_io->disable_file_hooks, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE); - } - - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY, - &config_io->disable_power_hooks, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE); - } - - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY, - &config_io->disable_nvapi_hooks, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE); - } - - if (!cconfig_util_get_bool( - config, - SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY, - &config_io->com1_card_reader, - SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY, - SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE); - } -} + bt_core_config_ext_bool_get(config, "io/disable_card_reader_emu", &config_out->disable_card_reader_emu); + bt_core_config_ext_bool_get(config, "io/disable_bio2_emu", &config_out->disable_bio2_emu); + bt_core_config_ext_bool_get(config, "io/disable_poll_limiter", &config_out->disable_poll_limiter); + bt_core_config_ext_bool_get(config, "io/force_headphones", &config_out->force_headphones); + bt_core_config_ext_bool_get(config, "io/disable_file_hooks", &config_out->disable_file_hooks); + bt_core_config_ext_bool_get(config, "io/disable_power_hooks", &config_out->disable_power_hooks); + bt_core_config_ext_bool_get(config, "io/disable_nvapi_hooks", &config_out->disable_nvapi_hooks); + bt_core_config_ext_bool_get(config, "io/com1_card_reader", &config_out->com1_card_reader); +} \ No newline at end of file diff --git a/src/main/sdvxhook2/config-io.h b/src/main/sdvxhook2/config-io.h index dec90fbf..141c7303 100644 --- a/src/main/sdvxhook2/config-io.h +++ b/src/main/sdvxhook2/config-io.h @@ -1,11 +1,11 @@ #ifndef SDVXHOOK2_CONFIG_IO_H #define SDVXHOOK2_CONFIG_IO_H -#include +#include -#include "cconfig/cconfig.h" +#include "api/core/config.h" -struct sdvxhook2_config_io { +typedef struct sdvxhook2_config_io { bool disable_card_reader_emu; bool disable_bio2_emu; bool disable_poll_limiter; @@ -14,11 +14,9 @@ struct sdvxhook2_config_io { bool disable_power_hooks; bool disable_nvapi_hooks; bool com1_card_reader; -}; - -void sdvxhook2_config_io_init(struct cconfig *config); +} sdvxhook2_config_io_t; void sdvxhook2_config_io_get( - struct sdvxhook2_config_io *config_io, struct cconfig *config); + const bt_core_config_t *config, sdvxhook2_config_io_t *config_out); #endif \ No newline at end of file diff --git a/src/main/sdvxhook2/dllmain.c b/src/main/sdvxhook2/dllmain.c index f19142b0..f8f6588d 100644 --- a/src/main/sdvxhook2/dllmain.c +++ b/src/main/sdvxhook2/dllmain.c @@ -1,221 +1,6 @@ #include -#include -#include -#include -#include - -#include "bemanitools/eamio.h" -#include "bemanitools/sdvxio.h" - -#include "cconfig/cconfig-hook.h" - -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/app.h" -#include "hooklib/config-adapter.h" -#include "hooklib/memfile.h" -#include "hooklib/rs232.h" - -#include "bio2emu/emu.h" - -#include "sdvxhook2/acio.h" -#include "sdvxhook2/bi2a.h" -#include "sdvxhook2/config-io.h" -#include "sdvxhook2/nvapi.h" -#include "sdvxhook2/power.h" - -#include "camhook/cam.h" -#include "camhook/config-cam.h" - -#include "d3d9exhook/config-gfx.h" -#include "d3d9exhook/d3d9ex.h" - -#include "imports/avs.h" - -#include "util/log.h" -#include "util/str.h" -#include "util/thread.h" - -#define SDVXHOOK2_INFO_HEADER \ - "sdvxhook for VW" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n" -#define SDVXHOOK2_CMD_USAGE \ - "Usage: launcher.exe -K sdvxhook2.dll [options...]" - -struct sdvxhook2_config_io config_io; -struct camhook_config_cam config_cam; -struct d3d9exhook_config_gfx config_gfx; -struct hooklib_config_adapter config_adapter; - -static struct bio2emu_port bio2_emu = { - .port = "COM4", - .wport = L"\\\\.\\COM4", - .dispatcher = bio2_emu_bi2a_dispatch_request, -}; - -static void attach_dest_fd_intercept(const char *sidcode) -{ - char region = sidcode[3]; - - if (region == 'X') { - region = 'J'; - } - - char target_file[8] = "\\x.dest"; - target_file[1] = tolower(region); - - // can only capture these by ending path due to /dev/raw being mountable - memfile_hook_add_fd(target_file, ENDING_MATCH, NULL, 0); -} - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) -{ - struct cconfig *config; - - log_info("--- Begin sdvxhook dll_entry_init ---"); - - config = cconfig_init(); - - sdvxhook2_config_io_init(config); - d3d9exhook_config_gfx_init(config); - camhook_config_cam_init(config, 1, false); - hooklib_config_adapter_init(config); - - if (!cconfig_hook_config_init( - config, - SDVXHOOK2_INFO_HEADER "\n" SDVXHOOK2_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - sdvxhook2_config_io_get(&config_io, config); - camhook_config_cam_get(&config_cam, config, 1, false); - d3d9exhook_config_gfx_get(&config_gfx, config); - hooklib_config_adapter_get(&config_adapter, config); - - cconfig_finit(config); - - log_info(SDVXHOOK2_INFO_HEADER); - log_info("Initializing sdvxhook2..."); - - d3d9ex_configure(&config_gfx); - - /* Start up sdvxio.DLL */ - if (!config_io.disable_bio2_emu) { - log_info("Starting sdvx IO backend"); - sdvx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!sdvx_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing sdvx IO backend failed"); - } - } - - /* Start up EAMIO.DLL */ - if (!config_io.disable_card_reader_emu) { - log_misc("Initializing card reader backend"); - eam_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); - - if (!eam_io_init( - avs_thread_create, avs_thread_join, avs_thread_destroy)) { - log_fatal("Initializing card reader backend failed"); - } - } - - /* iohooks are okay, even if emu is diabled since the fake handlers won't be - * used */ - iohook_push_handler(ac_io_port_dispatch_irp); - iohook_push_handler(bio2emu_port_dispatch_irp); - - if (!config_io.disable_file_hooks) { - memfile_hook_init(); - iohook_push_handler(memfile_hook_dispatch_irp); - attach_dest_fd_intercept(sidcode); - } - - rs232_hook_init(); - rs232_hook_limit_hooks(); - - if (!config_io.disable_bio2_emu) { - bio2emu_init(); - bio2_emu_bi2a_init( - &bio2_emu, - config_io.disable_poll_limiter, - config_io.force_headphones); - } - - if (!config_io.disable_card_reader_emu) { - ac_io_port_init(config_io.com1_card_reader); - } - - if (!config_cam.disable_emu) { - camhook_init(&config_cam); - } - - if (!config_io.disable_power_hooks) { - powerhook_init(); - } - - if (!config_io.disable_nvapi_hooks) { - nvapihook_init(); - } - - adapter_hook_override(config_adapter.override_ip); - - log_info("--- End sdvxhook dll_entry_init ---"); - - return app_hook_invoke_init(sidcode, param); -} - -static bool my_dll_entry_main(void) -{ - bool result; - - result = app_hook_invoke_main(); - - if (!config_cam.disable_emu) { - camhook_fini(); - } - - if (!config_io.disable_card_reader_emu) { - log_misc("Shutting down card reader backend"); - eam_io_fini(); - } - - if (!config_io.disable_bio2_emu) { - log_misc("Shutting down sdvx IO backend"); - sdvx_io_fini(); - } - - if (!config_io.disable_file_hooks) { - memfile_hook_fini(); - } - - return result; -} - -/** - * Hook library SDVX5+ - */ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } - - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); - - app_hook_init(my_dll_entry_init, my_dll_entry_main); - - acp_hook_init(); - adapter_hook_init(); - d3d9ex_hook_init(); - -end: return TRUE; -} +} \ No newline at end of file diff --git a/src/main/sdvxhook2/nvapi.c b/src/main/sdvxhook2/nvapi.c index fbe14d83..004104ea 100644 --- a/src/main/sdvxhook2/nvapi.c +++ b/src/main/sdvxhook2/nvapi.c @@ -13,9 +13,9 @@ #include "hook/com-proxy.h" #include "hook/table.h" -#include "sdvxhook2/nvapi.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "sdvxhook2/nvapi.h" static void *my_GetProcAddress(HMODULE dll, const char *name); diff --git a/src/main/sdvxhook2/power.c b/src/main/sdvxhook2/power.c index f860c1b9..803c3684 100644 --- a/src/main/sdvxhook2/power.c +++ b/src/main/sdvxhook2/power.c @@ -13,9 +13,9 @@ #include "hook/com-proxy.h" #include "hook/table.h" -#include "sdvxhook2/power.h" +#include "iface-core/log.h" -#include "util/log.h" +#include "sdvxhook2/power.h" static DWORD my_PowerSetActiveScheme(HKEY UserRootPowerKey, const GUID *SchemeGuid); diff --git a/src/main/sdvxhook2/sdvxhook2.c b/src/main/sdvxhook2/sdvxhook2.c new file mode 100644 index 00000000..acdd55c9 --- /dev/null +++ b/src/main/sdvxhook2/sdvxhook2.c @@ -0,0 +1,231 @@ +#define LOG_MODULE "sdvxhook2" + +#include + +#include +#include +#include +#include + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/config-adapter.h" +#include "hooklib/memfile.h" +#include "hooklib/rs232.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/sdvx.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "bio2emu/emu.h" + +#include "sdvxhook2/acio.h" +#include "sdvxhook2/bi2a.h" +#include "sdvxhook2/config-io.h" +#include "sdvxhook2/nvapi.h" +#include "sdvxhook2/power.h" + +#include "camhook/cam.h" +#include "camhook/config-cam.h" + +#include "d3d9exhook/config-gfx.h" +#include "d3d9exhook/d3d9ex.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#include "util/str.h" + +static sdvxhook2_config_io_t _sdvxhook2_config_io; +static camhook_config_cam_t _sdvxhook2_config_cam; +static d3d9exhook_config_gfx_t _sdvxhook2_config_gfx; +static hooklib_config_adapter_t _sdvxhook2_config_adapter; + +static module_io_t *_sdvxhook2_module_io_sdvx; +static module_io_t *_sdvxhook2_module_io_eam; + +static struct bio2emu_port bio2_emu = { + .port = "COM4", + .wport = L"\\\\.\\COM4", + .dispatcher = bio2_emu_bi2a_dispatch_request, +}; + +static void attach_dest_fd_intercept(const char *sidcode) +{ + char region = sidcode[3]; + + if (region == 'X') { + region = 'J'; + } + + char target_file[8] = "\\x.dest"; + target_file[1] = tolower(region); + + // can only capture these by ending path due to /dev/raw being mountable + memfile_hook_add_fd(target_file, ENDING_MATCH, NULL, 0); +} + +static void _sdvxhook2_io_sdvx_init(module_io_t **module) +{ + bt_io_sdvx_api_t api; + + module_io_ext_load_and_init( + "sdvxio.dll", "bt_module_io_sdvx_api_get", module); + module_io_api_get(*module, &api); + bt_io_sdvx_api_set(&api); +} + +static void _sdvxhook2_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_sdvxhook2_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + log_info("sdvxhook for Vivid Wave and EXCEED GEAR"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + // TODO sidcode back-propagation required like jubeat, figure out, crash for now + char *sidcode = NULL; + log_fatal("DEV TODO: sidcode back-propagation missing"); + log_assert(sidcode); + + sdvxhook2_config_io_get(config, &_sdvxhook2_config_io); + camhook_config_cam_get(config, &_sdvxhook2_config_cam, 1, false); + d3d9exhook_config_gfx_get(config, &_sdvxhook2_config_gfx); + hooklib_config_adapter_get(config, &_sdvxhook2_config_adapter); + + acp_hook_init(); + adapter_hook_init(); + d3d9ex_hook_init(); + + d3d9ex_configure(&_sdvxhook2_config_gfx); + + /* Start up sdvxio.DLL */ + if (!_sdvxhook2_config_io.disable_bio2_emu) { + log_info("Starting sdvx IO backend"); + + _sdvxhook2_io_sdvx_init(&_sdvxhook2_module_io_sdvx); + + if (!bt_io_sdvx_init()) { + log_fatal("Initializing sdvx IO backend failed"); + } + } + + /* Start up EAMIO.DLL */ + if (!_sdvxhook2_config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + _sdvxhook2_io_eam_init(&_sdvxhook2_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + } + + /* iohooks are okay, even if emu is diabled since the fake handlers won't be + * used */ + iohook_push_handler(ac_io_port_dispatch_irp); + iohook_push_handler(bio2emu_port_dispatch_irp); + + if (!_sdvxhook2_config_io.disable_file_hooks) { + memfile_hook_init(); + iohook_push_handler(memfile_hook_dispatch_irp); + attach_dest_fd_intercept(sidcode); + } + + rs232_hook_init(); + rs232_hook_limit_hooks(); + + if (!_sdvxhook2_config_io.disable_bio2_emu) { + bio2emu_init(); + bio2_emu_bi2a_init( + &bio2_emu, + _sdvxhook2_config_io.disable_poll_limiter, + _sdvxhook2_config_io.force_headphones); + } + + if (!_sdvxhook2_config_io.disable_card_reader_emu) { + ac_io_port_init(_sdvxhook2_config_io.com1_card_reader); + } + + if (!_sdvxhook2_config_cam.disable_emu) { + camhook_init(&_sdvxhook2_config_cam); + } + + if (!_sdvxhook2_config_io.disable_power_hooks) { + powerhook_init(); + } + + if (!_sdvxhook2_config_io.disable_nvapi_hooks) { + nvapihook_init(); + } + + adapter_hook_override(_sdvxhook2_config_adapter.override_ip); + + return true; +} + +static void _sdvxhook2_main_fini() +{ + if (!_sdvxhook2_config_cam.disable_emu) { + camhook_fini(); + } + + if (!_sdvxhook2_config_io.disable_card_reader_emu) { + log_misc("Shutting down card reader backend"); + + bt_io_eam_fini(); + + bt_io_eam_api_clear(); + module_io_free(&_sdvxhook2_module_io_eam); + } + + if (!_sdvxhook2_config_io.disable_bio2_emu) { + log_misc("Shutting down sdvx IO backend"); + + bt_io_sdvx_fini(); + + bt_io_sdvx_api_clear(); + module_io_free(&_sdvxhook2_module_io_sdvx); + } + + if (!_sdvxhook2_config_io.disable_file_hooks) { + memfile_hook_fini(); + } +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _sdvxhook2_main_init; + api->v1.main_fini = _sdvxhook2_main_fini; +} \ No newline at end of file diff --git a/src/main/sdvxhook2/sdvxhook2.def b/src/main/sdvxhook2/sdvxhook2.def index 9da2aa69..a68079c3 100644 --- a/src/main/sdvxhook2/sdvxhook2.def +++ b/src/main/sdvxhook2/sdvxhook2.def @@ -2,3 +2,9 @@ LIBRARY sdvxhook2 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/sdvxhook2/sdvxhook2.h b/src/main/sdvxhook2/sdvxhook2.h new file mode 100644 index 00000000..671b926e --- /dev/null +++ b/src/main/sdvxhook2/sdvxhook2.h @@ -0,0 +1,9 @@ +#ifndef SDVXHOOK2_H +#define SDVXHOOK2_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file diff --git a/src/main/sdvxio-bio2/Module.mk b/src/main/sdvxio-bio2/Module.mk index bf16a3be..8dd4a8e6 100644 --- a/src/main/sdvxio-bio2/Module.mk +++ b/src/main/sdvxio-bio2/Module.mk @@ -2,12 +2,16 @@ dlls += sdvxio-bio2 ldflags_sdvxio-bio2 := \ -lsetupapi \ + -lws2_32 \ libs_sdvxio-bio2 := \ aciodrv \ bio2drv \ - cconfig \ util \ + iface-core \ + util \ + security \ + core \ src_sdvxio-bio2 := \ sdvxio.c \ diff --git a/src/main/sdvxio-bio2/sdvxio-bio2.def b/src/main/sdvxio-bio2/sdvxio-bio2.def index 7b149217..9d3ff88d 100644 --- a/src/main/sdvxio-bio2/sdvxio-bio2.def +++ b/src/main/sdvxio-bio2/sdvxio-bio2.def @@ -1,15 +1,20 @@ LIBRARY sdvxio-bio2 EXPORTS - sdvx_io_fini - sdvx_io_get_input_gpio - sdvx_io_get_input_gpio_sys - sdvx_io_get_spinner_pos - sdvx_io_init - sdvx_io_read_input - sdvx_io_set_gpio_lights - sdvx_io_set_loggers - sdvx_io_set_pwm_light - sdvx_io_write_output - sdvx_io_set_amp_volume - _bio2_sdvx_io_poll + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_configure_do + bt_module_io_sdvx_api_get + + ; Direct API + bt_io_sdvx_init + bt_io_sdvx_fini + bt_io_sdvx_gpio_lights_set + bt_io_sdvx_pwm_light_set + bt_io_sdvx_output_write + bt_io_sdvx_input_read + bt_io_sdvx_input_gpio_sys_get + bt_io_sdvx_input_gpio_get + bt_io_sdvx_spinner_pos_get + bt_io_sdvx_amp_volume_set diff --git a/src/main/sdvxio-bio2/sdvxio.c b/src/main/sdvxio-bio2/sdvxio.c index e4dcb6a3..2d422ea0 100644 --- a/src/main/sdvxio-bio2/sdvxio.c +++ b/src/main/sdvxio-bio2/sdvxio.c @@ -1,30 +1,31 @@ +#define LOG_MODULE "sdvxio-bio2" + #include #include #include #include #include -#include "bemanitools/glue.h" -#include "bemanitools/sdvxio.h" +#include "api/core/config.h" +#include "api/core/log.h" -#include "cconfig/cconfig-main.h" +#include "iface-core/config.h" +#include "iface-core/log.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/io/sdvx.h" #include "aciodrv/device.h" #include "bio2drv/bi2a-sdvx.h" -#include "bio2drv/config-bio2.h" +#include "bio2drv/config.h" #include "bio2drv/detect.h" -#define LOG_MODULE "sdvxio-bio2" - -#define log_misc(...) sdvx_io_log_misc(LOG_MODULE, __VA_ARGS__) -#define log_info(...) sdvx_io_log_info(LOG_MODULE, __VA_ARGS__) -#define log_warning(...) sdvx_io_log_warning(LOG_MODULE, __VA_ARGS__) -#define log_fatal(...) sdvx_io_log_fatal(LOG_MODULE, __VA_ARGS__) +#include "sdk/module/core/config.h" +#include "sdk/module/configure.h" +#include "sdk/module/core/log.h" +#include "sdk/module/io/sdvx.h" -static log_formatter_t sdvx_io_log_misc; -static log_formatter_t sdvx_io_log_info; -static log_formatter_t sdvx_io_log_warning; -static log_formatter_t sdvx_io_log_fatal; +static bio2drv_config_t _sdvxio_bio2_config; static uint16_t sdvx_io_gpio[2]; static uint8_t sdvx_io_gpio_sys; @@ -42,52 +43,11 @@ struct bi2a_sdvx_state_out pout_ready; static struct aciodrv_device_ctx *bio2_device_ctx; -void sdvx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +bool bt_io_sdvx_init() { - sdvx_io_log_misc = misc; - sdvx_io_log_info = info; - sdvx_io_log_warning = warning; - sdvx_io_log_fatal = fatal; - - bio2drv_set_loggers(misc, info, warning, fatal); -} - -bool sdvx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) -{ - - struct cconfig *config; - struct bio2drv_config_bio2 config_bio2; - - config = cconfig_init(); - - bio2drv_config_bio2_init(config); - - if (!cconfig_main_config_init( - config, - "--bio2-config", - "sdvxio-bio2.conf", - "--help", - "-h", - "sdvxio-bio2", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - bio2drv_config_bio2_get(&config_bio2, config); + const char *selected_port = _sdvxio_bio2_config.port; - cconfig_finit(config); - - const char *selected_port = config_bio2.port; - - if (config_bio2.autodetect) { + if (_sdvxio_bio2_config.autodetect) { log_info("Attempting autodetect"); if (bio2drv_detect( @@ -102,7 +62,7 @@ bool sdvx_io_init( } // BIO2's cannot share a bus with anything else, so use device directly - bio2_device_ctx = aciodrv_device_open_path(selected_port, config_bio2.baud); + bio2_device_ctx = aciodrv_device_open_path(selected_port, _sdvxio_bio2_config.baud); if (bio2_device_ctx == NULL) { log_info("Opening BIO2 device on [%s] failed", selected_port); @@ -152,7 +112,7 @@ bool sdvx_io_init( return running; } -void sdvx_io_fini(void) +void bt_io_sdvx_fini(void) { running = false; while (processing_io) { @@ -175,20 +135,20 @@ static uint8_t assign_light(uint32_t gpio_lights, uint32_t shift) /* Blue generator lights are gpio, while the red and green are pwm on the KFCA. Tested this on a gen 1 sdvx pcb, and indeed the blue lights are only on/off, while the red & green can fade. */ -void sdvx_io_set_gpio_lights(uint32_t gpio_lights) +void bt_io_sdvx_gpio_lights_set(uint32_t gpio_lights) { - pout_staging.gpio[0] = assign_light(gpio_lights, SDVX_IO_OUT_GPIO_START); - pout_staging.gpio[1] = assign_light(gpio_lights, SDVX_IO_OUT_GPIO_A); - pout_staging.gpio[2] = assign_light(gpio_lights, SDVX_IO_OUT_GPIO_B); - pout_staging.gpio[3] = assign_light(gpio_lights, SDVX_IO_OUT_GPIO_C); - pout_staging.gpio[4] = assign_light(gpio_lights, SDVX_IO_OUT_GPIO_D); - pout_staging.gpio[5] = assign_light(gpio_lights, SDVX_IO_OUT_GPIO_FX_L); - pout_staging.gpio[6] = assign_light(gpio_lights, SDVX_IO_OUT_GPIO_FX_R); + pout_staging.gpio[0] = assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_START); + pout_staging.gpio[1] = assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_A); + pout_staging.gpio[2] = assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_B); + pout_staging.gpio[3] = assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_C); + pout_staging.gpio[4] = assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_D); + pout_staging.gpio[5] = assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_FX_L); + pout_staging.gpio[6] = assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_FX_R); pout_staging.generator[2] = - assign_light(gpio_lights, SDVX_IO_OUT_GPIO_GENERATOR_B); + assign_light(gpio_lights, BT_IO_SDVX_OUT_GPIO_GENERATOR_B); } -void sdvx_io_set_pwm_light(uint8_t light_no, uint8_t intensity) +void bt_io_sdvx_pwm_light_set(uint8_t light_no, uint8_t intensity) { if (light_no < 12) { wing_staging[light_no] = intensity; @@ -224,7 +184,7 @@ void sdvx_io_set_pwm_light(uint8_t light_no, uint8_t intensity) } } -bool sdvx_io_write_output(void) +bool bt_io_sdvx_output_write(void) { memcpy(&pout_ready, &pout_staging, sizeof(struct bi2a_sdvx_state_out)); pout_ready.wingUpper[0] = wing_staging[0] / 2 + wing_staging[3] / 2; @@ -269,7 +229,7 @@ bool _bio2_sdvx_io_poll( return true; } -bool sdvx_io_read_input(void) +bool bt_io_sdvx_input_read(void) { struct bi2a_sdvx_state_in pin; @@ -285,35 +245,37 @@ bool sdvx_io_read_input(void) sdvx_io_gpio_sys = 0; sdvx_io_gpio_sys |= - shift_pin(pin.analogs[0].a_coin, SDVX_IO_IN_GPIO_SYS_COIN); + shift_pin(pin.analogs[0].a_coin, BT_IO_SDVX_IN_GPIO_SYS_COIN); sdvx_io_gpio_sys |= - shift_pin(pin.analogs[0].a_test, SDVX_IO_IN_GPIO_SYS_TEST); + shift_pin(pin.analogs[0].a_test, BT_IO_SDVX_IN_GPIO_SYS_TEST); sdvx_io_gpio_sys |= - shift_pin(pin.analogs[0].a_service, SDVX_IO_IN_GPIO_SYS_SERVICE); + shift_pin(pin.analogs[0].a_service, BT_IO_SDVX_IN_GPIO_SYS_SERVICE); sdvx_io_gpio[0] = 0; sdvx_io_gpio[1] = 0; sdvx_io_gpio[0] |= - shift_pin(pin.buttons_1.b_start, SDVX_IO_IN_GPIO_0_START); + shift_pin(pin.buttons_1.b_start, BT_IO_SDVX_IN_GPIO_0_START); sdvx_io_gpio[0] |= - shift_pin(pin.buttons_1.b_headphone, SDVX_IO_IN_GPIO_0_HEADPHONE); - sdvx_io_gpio[0] |= shift_pin(pin.buttons_1.b_a, SDVX_IO_IN_GPIO_0_A); - sdvx_io_gpio[0] |= shift_pin(pin.buttons_1.b_b, SDVX_IO_IN_GPIO_0_B); - sdvx_io_gpio[0] |= shift_pin(pin.buttons_1.b_c, SDVX_IO_IN_GPIO_0_C); - sdvx_io_gpio[1] |= shift_pin(pin.buttons_1.b_d, SDVX_IO_IN_GPIO_1_D); - sdvx_io_gpio[1] |= shift_pin(pin.buttons_1.b_fxl, SDVX_IO_IN_GPIO_1_FX_L); - sdvx_io_gpio[1] |= shift_pin(pin.buttons_2.b_fxr, SDVX_IO_IN_GPIO_1_FX_R); + shift_pin(pin.buttons_1.b_headphone, BT_IO_SDVX_IN_GPIO_0_HEADPHONE); + sdvx_io_gpio[0] |= shift_pin(pin.buttons_1.b_a, BT_IO_SDVX_IN_GPIO_0_A); + sdvx_io_gpio[0] |= shift_pin(pin.buttons_1.b_b, BT_IO_SDVX_IN_GPIO_0_B); + sdvx_io_gpio[0] |= shift_pin(pin.buttons_1.b_c, BT_IO_SDVX_IN_GPIO_0_C); + sdvx_io_gpio[1] |= shift_pin(pin.buttons_1.b_d, BT_IO_SDVX_IN_GPIO_1_D); + sdvx_io_gpio[1] |= + shift_pin(pin.buttons_1.b_fxl, BT_IO_SDVX_IN_GPIO_1_FX_L); + sdvx_io_gpio[1] |= + shift_pin(pin.buttons_2.b_fxr, BT_IO_SDVX_IN_GPIO_1_FX_R); return true; } -uint8_t sdvx_io_get_input_gpio_sys(void) +uint8_t bt_io_sdvx_input_gpio_sys_get(void) { return sdvx_io_gpio_sys; } -uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank) +uint16_t bt_io_sdvx_input_gpio_get(uint8_t gpio_bank) { if (gpio_bank > 1) { return 0; @@ -322,7 +284,7 @@ uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank) return sdvx_io_gpio[gpio_bank]; } -uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no) +uint16_t bt_io_sdvx_spinner_pos_get(uint8_t spinner_no) { if (spinner_no >= 2) { return 0; @@ -330,7 +292,7 @@ uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no) return sdvx_io_analog[spinner_no]; } -bool sdvx_io_set_amp_volume( +bool bt_io_sdvx_amp_volume_set( uint8_t primary, uint8_t headphone, uint8_t subwoofer) { if (!running) { @@ -346,3 +308,36 @@ bool sdvx_io_set_amp_volume( return true; } + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +bool bt_module_configure_do(const bt_core_config_t *config) +{ + bio2drv_config_bio2_get(config, &_sdvxio_bio2_config); + + return true; +} + +void bt_module_io_sdvx_api_get(bt_io_sdvx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_sdvx_init; + api->v1.fini = bt_io_sdvx_fini; + api->v1.gpio_lights_set = bt_io_sdvx_gpio_lights_set; + api->v1.pwm_light_set = bt_io_sdvx_pwm_light_set; + api->v1.output_write = bt_io_sdvx_output_write; + api->v1.input_read = bt_io_sdvx_input_read; + api->v1.input_gpio_sys_get = bt_io_sdvx_input_gpio_sys_get; + api->v1.input_gpio_get = bt_io_sdvx_input_gpio_get; + api->v1.spinner_pos_get = bt_io_sdvx_spinner_pos_get; + api->v1.amp_volume_set = bt_io_sdvx_amp_volume_set; +} \ No newline at end of file diff --git a/src/main/sdvxio-kfca/Module.mk b/src/main/sdvxio-kfca/Module.mk index cb10b225..2c87646d 100644 --- a/src/main/sdvxio-kfca/Module.mk +++ b/src/main/sdvxio-kfca/Module.mk @@ -1,11 +1,14 @@ dlls += sdvxio-kfca libs_sdvxio-kfca := \ - geninput \ aciodrv \ - aciomgr \ - cconfig \ util \ + iface \ + module \ + iface-acio \ + iface-core \ + util \ + security \ src_sdvxio-kfca := \ sdvxio.c \ diff --git a/src/main/sdvxio-kfca/config-kfca.c b/src/main/sdvxio-kfca/config-kfca.c index 91814e67..58b9ff2f 100644 --- a/src/main/sdvxio-kfca/config-kfca.c +++ b/src/main/sdvxio-kfca/config-kfca.c @@ -1,118 +1,14 @@ -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "sdvxio-kfca/config-kfca.h" -#include "util/log.h" - -#define SDVXIO_KFCA_CONFIG_KFCA_PORT_KEY "kfca.port" -#define SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY "kfca.baud" -#define SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY "kfca.main_override" -#define SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY "kfca.headphone_override" -#define SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY "kfca.subwoofer_override" - -#define SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_PORT_VALUE "COM3" -#define SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE 57600 -#define SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE -1 -#define SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE -1 -#define SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE -1 - -void sdvxio_kfca_config_kfca_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - SDVXIO_KFCA_CONFIG_KFCA_PORT_KEY, - SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_PORT_VALUE, - "KFCA ACIO serial port"); - - cconfig_util_set_int( - config, - SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY, - SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE, - "KFCA ACIO bus baudrate (real devices expect 57600)"); - - cconfig_util_set_int( - config, - SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY, - SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE, - "SDVXIO digital amp main volume (0-96) 0 is high, 96 is low. -1 is no " - "override."); - - cconfig_util_set_int( - config, - SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY, - SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE, - "SDVXIO digital amp headphone volume (0-96) 0 is high, 96 is low. -1 " - "is no override."); - - cconfig_util_set_int( - config, - SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY, - SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE, - "SDVXIO digital amp subwoofer volume (0-96) 0 is high, 96 is low. -1 " - "is no override."); -} - void sdvxio_kfca_config_kfca_get( - struct sdvxio_kfca_config_kfca *config_kfca, struct cconfig *config) + const bt_core_config_t *config, + sdvxio_kfca_config_kfca_t *config_out) { - if (!cconfig_util_get_str( - config, - SDVXIO_KFCA_CONFIG_KFCA_PORT_KEY, - config_kfca->port, - sizeof(config_kfca->port) - 1, - SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_PORT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - SDVXIO_KFCA_CONFIG_KFCA_PORT_KEY, - SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_PORT_VALUE); - } - - if (!cconfig_util_get_int( - config, - SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY, - &config_kfca->baud, - SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY, - SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE); - } - - if (!cconfig_util_get_int( - config, - SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY, - &config_kfca->override_main_volume, - SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY, - SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE); - } - - if (!cconfig_util_get_int( - config, - SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY, - &config_kfca->override_headphone_volume, - SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY, - SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE); - } - - if (!cconfig_util_get_int( - config, - SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY, - &config_kfca->override_sub_volume, - SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY, - SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE); - } -} + bt_core_config_str_get(config, "kfca/port", config_out->port, sizeof(config_out->port)); + bt_core_config_s32_get(config, "kfca/baud", &config_out->baud); + bt_core_config_s32_get(config, "kfca/main_override", &config_out->override_main_volume); + bt_core_config_s32_get(config, "kfca/headphone_override", &config_out->override_headphone_volume); + bt_core_config_s32_get(config, "kfca/subwoofer_override", &config_out->override_sub_volume); +} \ No newline at end of file diff --git a/src/main/sdvxio-kfca/config-kfca.h b/src/main/sdvxio-kfca/config-kfca.h index f2128828..3949f96b 100644 --- a/src/main/sdvxio-kfca/config-kfca.h +++ b/src/main/sdvxio-kfca/config-kfca.h @@ -1,21 +1,20 @@ #ifndef SDVXIO_KFCA_CONFIG_KFCA_H #define SDVXIO_KFCA_CONFIG_KFCA_H -#include +#include -#include "cconfig/cconfig.h" +#include "api/core/config.h" -struct sdvxio_kfca_config_kfca { +typedef struct sdvxio_kfca_config_kfca { char port[64]; int32_t baud; int32_t override_main_volume; int32_t override_headphone_volume; int32_t override_sub_volume; -}; - -void sdvxio_kfca_config_kfca_init(struct cconfig *config); +} sdvxio_kfca_config_kfca_t; void sdvxio_kfca_config_kfca_get( - struct sdvxio_kfca_config_kfca *config_kfca, struct cconfig *config); - + const bt_core_config_t *config, + sdvxio_kfca_config_kfca_t *config_out); + #endif \ No newline at end of file diff --git a/src/main/sdvxio-kfca/sdvxio-kfca.def b/src/main/sdvxio-kfca/sdvxio-kfca.def index 8d6e632d..8f233a62 100644 --- a/src/main/sdvxio-kfca/sdvxio-kfca.def +++ b/src/main/sdvxio-kfca/sdvxio-kfca.def @@ -1,14 +1,20 @@ LIBRARY sdvxio EXPORTS - sdvx_io_fini - sdvx_io_get_input_gpio - sdvx_io_get_input_gpio_sys - sdvx_io_get_spinner_pos - sdvx_io_init - sdvx_io_read_input - sdvx_io_set_gpio_lights - sdvx_io_set_loggers - sdvx_io_set_pwm_light - sdvx_io_write_output - sdvx_io_set_amp_volume + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_configure_do + bt_module_io_sdvx_api_get + + ; Direct API + bt_io_sdvx_init + bt_io_sdvx_fini + bt_io_sdvx_gpio_lights_set + bt_io_sdvx_pwm_light_set + bt_io_sdvx_output_write + bt_io_sdvx_input_read + bt_io_sdvx_input_gpio_sys_get + bt_io_sdvx_input_gpio_get + bt_io_sdvx_spinner_pos_get + bt_io_sdvx_amp_volume_set diff --git a/src/main/sdvxio-kfca/sdvxio.c b/src/main/sdvxio-kfca/sdvxio.c index e2304496..d099f74e 100644 --- a/src/main/sdvxio-kfca/sdvxio.c +++ b/src/main/sdvxio-kfca/sdvxio.c @@ -1,32 +1,32 @@ +#define LOG_MODULE "sdvxio-kfca" + #include #include #include #include #include -#include "bemanitools/glue.h" -#include "bemanitools/sdvxio.h" +#include "acio/acio.h" -#include "cconfig/cconfig-main.h" +#include "api/core/config.h" +#include "api/core/log.h" -#include "acio/acio.h" +#include "iface-core/config.h" +#include "iface-acio/mgr.h" +#include "iface-core/log.h" -#include "aciodrv/kfca.h" -#include "aciomgr/manager.h" +#include "main/module/acio-mgr-ext.h" -#include "sdvxio-kfca/config-kfca.h" +#include "sdk/module/core/config.h" +#include "sdk/module/configure.h" +#include "sdk/module/core/log.h" +#include "sdk/module/io/sdvx.h" -#define LOG_MODULE "sdvxio-kfca" +#include "aciodrv/kfca.h" -#define log_misc(...) sdvx_io_log_misc(LOG_MODULE, __VA_ARGS__) -#define log_info(...) sdvx_io_log_info(LOG_MODULE, __VA_ARGS__) -#define log_warning(...) sdvx_io_log_warning(LOG_MODULE, __VA_ARGS__) -#define log_fatal(...) sdvx_io_log_fatal(LOG_MODULE, __VA_ARGS__) +#include "sdvxio-kfca/config-kfca.h" -static log_formatter_t sdvx_io_log_misc; -static log_formatter_t sdvx_io_log_info; -static log_formatter_t sdvx_io_log_warning; -static log_formatter_t sdvx_io_log_fatal; +static sdvxio_kfca_config_kfca_t _sdvxio_kfca_config; static uint16_t sdvx_io_gpio[2]; static uint8_t sdvx_io_gpio_sys; @@ -39,68 +39,41 @@ static int16_t kfca_node_id; struct ac_io_kfca_poll_out pout_staging; struct ac_io_kfca_poll_out pout_ready; -static struct aciomgr_port_dispatcher *acio_manager_ctx; +static bt_acio_mgr_port_dispatcher_t *acio_manager_ctx; + +static module_acio_mgr_t *acio_mgr_module; -void sdvx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +static void _bt_io_jb_module_acio_mgr_init(module_acio_mgr_t **module) { - aciomgr_set_loggers(misc, info, warning, fatal); + bt_acio_mgr_api_t api; - sdvx_io_log_misc = misc; - sdvx_io_log_info = info; - sdvx_io_log_warning = warning; - sdvx_io_log_fatal = fatal; + module_acio_mgr_ext_load_and_init("acio-mgr.dll", module); + module_acio_mgr_api_get(*module, &api); + bt_acio_mgr_api_set(&api); } -bool sdvx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_sdvx_init() { + _bt_io_jb_module_acio_mgr_init(&acio_mgr_module); - struct cconfig *config; - struct sdvxio_kfca_config_kfca config_kfca; - - config = cconfig_init(); - - sdvxio_kfca_config_kfca_init(config); - - if (!cconfig_main_config_init( - config, - "--kfca-config", - "sdvxio-kfca.conf", - "--help", - "-h", - "sdvxio-kfca", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - sdvxio_kfca_config_kfca_get(&config_kfca, config); - - cconfig_finit(config); - - acio_manager_ctx = aciomgr_port_init(config_kfca.port, config_kfca.baud); + acio_manager_ctx = + bt_acio_mgr_port_init(_sdvxio_kfca_config.port, _sdvxio_kfca_config.baud); if (acio_manager_ctx == NULL) { - log_info("Opening acio device on [%s] failed", config_kfca.port); + log_info("Opening acio device on [%s] failed", _sdvxio_kfca_config.port); return 0; } log_info("Opening acio device successful"); - uint8_t node_count = aciomgr_get_node_count(acio_manager_ctx); + uint8_t node_count = bt_acio_mgr_node_count_get(acio_manager_ctx); log_info("Enumerated %d nodes", node_count); kfca_node_id = -1; for (uint8_t i = 0; i < node_count; i++) { char product[4]; - aciomgr_get_node_product_ident(acio_manager_ctx, i, product); + bt_acio_mgr_node_product_ident_get(acio_manager_ctx, i, product); log_info( "> %d: %c%c%c%c\n", i, @@ -124,24 +97,24 @@ bool sdvx_io_init( uint8_t headphone = 0; uint8_t subwoofer = 0; - if (config_kfca.override_main_volume >= 0) { - primary = config_kfca.override_main_volume; + if (_sdvxio_kfca_config.override_main_volume >= 0) { + primary = _sdvxio_kfca_config.override_main_volume; } - if (config_kfca.override_headphone_volume >= 0) { - headphone = config_kfca.override_headphone_volume; + if (_sdvxio_kfca_config.override_headphone_volume >= 0) { + headphone = _sdvxio_kfca_config.override_headphone_volume; } - if (config_kfca.override_sub_volume >= 0) { - subwoofer = config_kfca.override_sub_volume; + if (_sdvxio_kfca_config.override_sub_volume >= 0) { + subwoofer = _sdvxio_kfca_config.override_sub_volume; } bool init_result = aciodrv_kfca_amp( - aciomgr_port_checkout(acio_manager_ctx), + bt_acio_mgr_port_checkout(acio_manager_ctx), kfca_node_id, primary, headphone, 0, subwoofer); - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkin(acio_manager_ctx); if (!init_result) { log_warning("Unable to start KFCA on node: %d", kfca_node_id); @@ -157,16 +130,19 @@ bool sdvx_io_init( return running; } -void sdvx_io_fini(void) +void bt_io_sdvx_fini(void) { running = false; while (processing_io) { // avoid banging Sleep(1); } + + bt_acio_mgr_api_clear(); + module_acio_mgr_free(&acio_mgr_module); } -void sdvx_io_set_gpio_lights(uint32_t gpio_lights) +void bt_io_sdvx_gpio_lights_set(uint32_t gpio_lights) { pout_staging.gpio = gpio_lights; pout_staging.gpio |= 1 << 0x16; @@ -174,18 +150,18 @@ void sdvx_io_set_gpio_lights(uint32_t gpio_lights) pout_staging.gpio = ac_io_u32(pout_staging.gpio); } -void sdvx_io_set_pwm_light(uint8_t light_no, uint8_t intensity) +void bt_io_sdvx_pwm_light_set(uint8_t light_no, uint8_t intensity) { pout_staging.pwm[light_no] = intensity; } -bool sdvx_io_write_output(void) +bool bt_io_sdvx_output_write(void) { memcpy(&pout_ready, &pout_staging, sizeof(struct ac_io_kfca_poll_out)); return true; } -bool sdvx_io_read_input(void) +bool bt_io_sdvx_input_read(void) { struct ac_io_kfca_poll_in pin; @@ -195,11 +171,11 @@ bool sdvx_io_read_input(void) processing_io = true; bool poll_result = aciodrv_kfca_poll( - aciomgr_port_checkout(acio_manager_ctx), + bt_acio_mgr_port_checkout(acio_manager_ctx), kfca_node_id, &pout_ready, &pin); - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkin(acio_manager_ctx); if (!poll_result) { return false; @@ -224,12 +200,12 @@ bool sdvx_io_read_input(void) return true; } -uint8_t sdvx_io_get_input_gpio_sys(void) +uint8_t bt_io_sdvx_input_gpio_sys_get(void) { return sdvx_io_gpio_sys; } -uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank) +uint16_t bt_io_sdvx_input_gpio_get(uint8_t gpio_bank) { if (gpio_bank > 1) { return 0; @@ -238,7 +214,7 @@ uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank) return sdvx_io_gpio[gpio_bank]; } -uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no) +uint16_t bt_io_sdvx_spinner_pos_get(uint8_t spinner_no) { if (spinner_no >= 2) { return 0; @@ -246,7 +222,7 @@ uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no) return sdvx_io_analog[spinner_no]; } -bool sdvx_io_set_amp_volume( +bool bt_io_sdvx_amp_volume_set( uint8_t primary, uint8_t headphone, uint8_t subwoofer) { if (!running) { @@ -254,13 +230,13 @@ bool sdvx_io_set_amp_volume( } bool amp_result = aciodrv_kfca_amp( - aciomgr_port_checkout(acio_manager_ctx), + bt_acio_mgr_port_checkout(acio_manager_ctx), kfca_node_id, primary, headphone, 96, subwoofer); - aciomgr_port_checkin(acio_manager_ctx); + bt_acio_mgr_port_checkin(acio_manager_ctx); if (!amp_result) { return false; @@ -268,3 +244,36 @@ bool sdvx_io_set_amp_volume( return true; } + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +bool bt_module_configure_do(const bt_core_config_t *config) +{ + sdvxio_kfca_config_kfca_get(config, &_sdvxio_kfca_config); + + return true; +} + +void bt_module_io_sdvx_api_get(bt_io_sdvx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_sdvx_init; + api->v1.fini = bt_io_sdvx_fini; + api->v1.gpio_lights_set = bt_io_sdvx_gpio_lights_set; + api->v1.pwm_light_set = bt_io_sdvx_pwm_light_set; + api->v1.output_write = bt_io_sdvx_output_write; + api->v1.input_read = bt_io_sdvx_input_read; + api->v1.input_gpio_sys_get = bt_io_sdvx_input_gpio_sys_get; + api->v1.input_gpio_get = bt_io_sdvx_input_gpio_get; + api->v1.spinner_pos_get = bt_io_sdvx_spinner_pos_get; + api->v1.amp_volume_set = bt_io_sdvx_amp_volume_set; +} \ No newline at end of file diff --git a/src/main/sdvxio/Module.mk b/src/main/sdvxio/Module.mk index ffeca72b..3eecfe23 100644 --- a/src/main/sdvxio/Module.mk +++ b/src/main/sdvxio/Module.mk @@ -1,7 +1,14 @@ dlls += sdvxio +ldflags_sdvxio := \ + -lwinmm + libs_sdvxio := \ - geninput \ + iface \ + module \ + iface-io \ + iface-core \ + util \ src_sdvxio := \ sdvxio.c \ diff --git a/src/main/sdvxio/sdvxio.c b/src/main/sdvxio/sdvxio.c index 5478c736..18581573 100644 --- a/src/main/sdvxio/sdvxio.c +++ b/src/main/sdvxio/sdvxio.c @@ -1,67 +1,101 @@ +#define LOG_MODULE "sdvxio" + +// clang-format off +// Don't format because the order is important here +#include +#include +// clang-format on + #include #include #include -#include "bemanitools/glue.h" -#include "bemanitools/input.h" -#include "bemanitools/sdvxio.h" +#include "api/core/log.h" +#include "api/core/thread.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface/input.h" + +#include "main/module/input-ext.h" +#include "main/module/input.h" +#include "main/module/io-ext.h" +#include "main/module/io.h" + +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/input.h" +#include "sdk/module/io/sdvx.h" static uint16_t sdvx_io_gpio[2]; static uint8_t sdvx_io_gpio_sys; -void sdvx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) +static module_input_t *_sdvx_io_module_input; + +static void _bt_io_sdvx_module_input_init(module_input_t **module) { - input_set_loggers(misc, info, warning, fatal); + bt_input_api_t api; + + module_input_ext_load_and_init("geninput.dll", module); + module_input_api_get(*module, &api); + bt_input_api_set(&api); } -bool sdvx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_sdvx_init() { - input_init(thread_create, thread_join, thread_destroy); - mapper_config_load("sdvx"); + bool result; - return true; + _bt_io_sdvx_module_input_init(&_sdvx_io_module_input); + + timeBeginPeriod(1); + + result = bt_input_init(); + + if (!result) { + log_warning("Initializing input failed"); + return false; + } + + return bt_input_mapper_config_load("sdvx"); } -void sdvx_io_fini(void) +void bt_io_sdvx_fini(void) { - input_fini(); + bt_input_fini(); + bt_input_api_clear(); + module_input_free(&_sdvx_io_module_input); + + timeEndPeriod(1); } -void sdvx_io_set_gpio_lights(uint32_t gpio_lights) +void bt_io_sdvx_gpio_lights_set(uint32_t gpio_lights) { size_t i; for (i = 0; i < 16; i++) { if (gpio_lights & (1 << i)) { - mapper_write_light(i, 255); + bt_input_mapper_light_write(i, 255); } else { - mapper_write_light(i, 0); + bt_input_mapper_light_write(i, 0); } } } -void sdvx_io_set_pwm_light(uint8_t light_no, uint8_t intensity) +void bt_io_sdvx_pwm_light_set(uint8_t light_no, uint8_t intensity) { - mapper_write_light(light_no + 0x10, intensity); + bt_input_mapper_light_write(light_no + 0x10, intensity); } -bool sdvx_io_write_output(void) +bool bt_io_sdvx_output_write(void) { return true; } -bool sdvx_io_read_input(void) +bool bt_io_sdvx_input_read(void) { uint32_t pack; - pack = mapper_update(); + pack = bt_input_mapper_update(); sdvx_io_gpio_sys = pack & 0xFF; sdvx_io_gpio[0] = (pack >> 8) & 0x00FF; @@ -70,12 +104,12 @@ bool sdvx_io_read_input(void) return true; } -uint8_t sdvx_io_get_input_gpio_sys(void) +uint8_t bt_io_sdvx_input_gpio_sys_get(void) { return sdvx_io_gpio_sys; } -uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank) +uint16_t bt_io_sdvx_input_gpio_get(uint8_t gpio_bank) { if (gpio_bank > 1) { return 0; @@ -84,13 +118,39 @@ uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank) return sdvx_io_gpio[gpio_bank]; } -uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no) +uint16_t bt_io_sdvx_spinner_pos_get(uint8_t spinner_no) { - return mapper_read_analog(spinner_no) * 4; + return bt_input_mapper_analog_read(spinner_no) * 4; } -bool sdvx_io_set_amp_volume( +bool bt_io_sdvx_amp_volume_set( uint8_t primary, uint8_t headphone, uint8_t subwoofer) { return true; } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_io_sdvx_api_get(bt_io_sdvx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_sdvx_init; + api->v1.fini = bt_io_sdvx_fini; + api->v1.gpio_lights_set = bt_io_sdvx_gpio_lights_set; + api->v1.pwm_light_set = bt_io_sdvx_pwm_light_set; + api->v1.output_write = bt_io_sdvx_output_write; + api->v1.input_read = bt_io_sdvx_input_read; + api->v1.input_gpio_sys_get = bt_io_sdvx_input_gpio_sys_get; + api->v1.input_gpio_get = bt_io_sdvx_input_gpio_get; + api->v1.spinner_pos_get = bt_io_sdvx_spinner_pos_get; + api->v1.amp_volume_set = bt_io_sdvx_amp_volume_set; +} diff --git a/src/main/sdvxio/sdvxio.def b/src/main/sdvxio/sdvxio.def index 8d6e632d..e9b62af4 100644 --- a/src/main/sdvxio/sdvxio.def +++ b/src/main/sdvxio/sdvxio.def @@ -1,14 +1,19 @@ LIBRARY sdvxio EXPORTS - sdvx_io_fini - sdvx_io_get_input_gpio - sdvx_io_get_input_gpio_sys - sdvx_io_get_spinner_pos - sdvx_io_init - sdvx_io_read_input - sdvx_io_set_gpio_lights - sdvx_io_set_loggers - sdvx_io_set_pwm_light - sdvx_io_write_output - sdvx_io_set_amp_volume + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_io_sdvx_api_get + + ; Direct API + bt_io_sdvx_init + bt_io_sdvx_fini + bt_io_sdvx_gpio_lights_set + bt_io_sdvx_pwm_light_set + bt_io_sdvx_output_write + bt_io_sdvx_input_read + bt_io_sdvx_input_gpio_sys_get + bt_io_sdvx_input_gpio_get + bt_io_sdvx_spinner_pos_get + bt_io_sdvx_amp_volume_set diff --git a/src/main/security/id.c b/src/main/security/id.c index b591fb2d..1d949f51 100644 --- a/src/main/security/id.c +++ b/src/main/security/id.c @@ -1,9 +1,10 @@ #include +#include "iface-core/log.h" + #include "security/id.h" #include "util/hex.h" -#include "util/log.h" #include "util/mem.h" const struct security_id security_id_default = { diff --git a/src/main/security/id.h b/src/main/security/id.h index 6043a44a..b62d1916 100644 --- a/src/main/security/id.h +++ b/src/main/security/id.h @@ -9,11 +9,11 @@ /** * Structure of a security id, e.g. PCBID or EAMID. */ -struct security_id { +typedef struct security_id { uint8_t header; uint8_t id[8]; uint8_t checksum; -}; +} security_id_t; /** * "Default" security id with updated header and cheacksum ready for use. diff --git a/src/main/security/mcode.c b/src/main/security/mcode.c index 5bc93fa9..2245d5e5 100644 --- a/src/main/security/mcode.c +++ b/src/main/security/mcode.c @@ -1,8 +1,9 @@ #include +#include "iface-core/log.h" + #include "security/mcode.h" -#include "util/log.h" #include "util/mem.h" const struct security_mcode security_mcode_eamuse = { diff --git a/src/main/security/mcode.h b/src/main/security/mcode.h index a58f860d..a46f1f79 100644 --- a/src/main/security/mcode.h +++ b/src/main/security/mcode.h @@ -83,7 +83,7 @@ * Structure to represent a Konami mcode which is used to identify games and * different hardware/software revisions. */ -struct security_mcode { +typedef struct security_mcode { char header; char unkn; /* Identify the game and version, e.g. IIDX 12 */ @@ -91,7 +91,7 @@ struct security_mcode { char region; char cabinet; char revision; -}; +} security_mcode_t; /** * Default mcode used to identify white eamuse roundplugs. diff --git a/src/main/security/rp-blowfish.c b/src/main/security/rp-blowfish.c index 9aeb6965..5570ba2b 100644 --- a/src/main/security/rp-blowfish.c +++ b/src/main/security/rp-blowfish.c @@ -1,10 +1,10 @@ #include +#include "iface-core/log.h" + #include "security/rp-blowfish-table.h" #include "security/rp-blowfish.h" -#include "util/log.h" - static int security_rp_blowfish_enc_sub(int a1) { int result; // eax@1 diff --git a/src/main/security/rp.c b/src/main/security/rp.c index ba828644..f4011937 100644 --- a/src/main/security/rp.c +++ b/src/main/security/rp.c @@ -1,3 +1,5 @@ +#include "iface-core/log.h" + #include "security/rp.h" #include "security/rp-blowfish.h" @@ -5,7 +7,6 @@ #include "security/util.h" #include "util/crypto.h" -#include "util/log.h" static uint32_t security_rp_get_len_mcode(const struct security_mcode *mcode) { diff --git a/src/main/security/rp2.c b/src/main/security/rp2.c index 51480a69..92a35d1d 100644 --- a/src/main/security/rp2.c +++ b/src/main/security/rp2.c @@ -1,11 +1,12 @@ #include +#include "iface-core/log.h" + #include "security/rp-util.h" #include "security/rp2.h" #include "security/util.h" #include "util/crypto.h" -#include "util/log.h" static uint8_t security_rp2_signature_scramble_table[16] = { 0x0C, diff --git a/src/main/security/rp3.c b/src/main/security/rp3.c index a6dd5bf5..b43e1132 100644 --- a/src/main/security/rp3.c +++ b/src/main/security/rp3.c @@ -1,12 +1,13 @@ #include +#include "iface-core/log.h" + #include "security/rp-util.h" #include "security/rp2.h" #include "security/rp3.h" #include "security/util.h" #include "util/crc.h" -#include "util/log.h" void security_rp3_generate_signed_eeprom_data( enum security_rp_util_rp_type type, diff --git a/src/main/unicorntail/Module.mk b/src/main/unicorntail/Module.mk index bd6d3606..e08b7d97 100644 --- a/src/main/unicorntail/Module.mk +++ b/src/main/unicorntail/Module.mk @@ -3,12 +3,17 @@ avsdlls += unicorntail deplibs_unicorntail := \ avs \ +avslibs_unicorntail := \ + avs-ext \ + libs_unicorntail := \ + core \ p3io \ p3ioemu \ hook \ hooklib \ util \ + iface-core \ src_unicorntail := \ dllmain.c \ diff --git a/src/main/unicorntail/dllmain.c b/src/main/unicorntail/dllmain.c index 59f862de..07df638e 100644 --- a/src/main/unicorntail/dllmain.c +++ b/src/main/unicorntail/dllmain.c @@ -4,20 +4,20 @@ #include "hook/iohook.h" -#include "hooklib/app.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" -#include "imports/avs.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" #include "unicorntail/p3io.h" #include "unicorntail/usbmem.h" #include "util/defs.h" -#include "util/log.h" -static bool my_dll_entry_init(char *sidcode, struct property_node *param); -static bool my_dll_entry_main(void); - -static bool my_dll_entry_init(char *sidcode, struct property_node *param) +static bool +_unicorntail_main_init(HMODULE game_module, const bt_core_config_t *config_) { log_info("--- Begin unicorntail dll_entry_init ---"); @@ -29,32 +29,34 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) log_info("--- End unicorntail dll_entry_init ---"); - return app_hook_invoke_init(sidcode, param); + return true; } -static bool my_dll_entry_main(void) +static void _unicorntail_main_fini() { - bool result; - - result = app_hook_invoke_main(); - usbmem_fini(); p3io_filter_fini(); +} - return result; +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); } -BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) { - if (reason != DLL_PROCESS_ATTACH) { - goto end; - } + bt_core_thread_api_set(api); +} - log_to_external( - log_body_misc, log_body_info, log_body_warning, log_body_fatal); +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; - app_hook_init(my_dll_entry_init, my_dll_entry_main); + api->v1.main_init = _unicorntail_main_init; + api->v1.main_fini = _unicorntail_main_fini; +} -end: +BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx) +{ return TRUE; } diff --git a/src/main/unicorntail/p3io.c b/src/main/unicorntail/p3io.c index fd0a85c4..bc68b047 100644 --- a/src/main/unicorntail/p3io.c +++ b/src/main/unicorntail/p3io.c @@ -3,6 +3,8 @@ #include #include +#include "iface-core/log.h" + #include "p3io/cmd.h" #include "p3io/frame.h" @@ -11,7 +13,6 @@ #include "unicorntail/p3io.h" #include "util/array.h" -#include "util/log.h" #include "util/str.h" static bool p3io_match_irp_locked(const struct irp *irp); diff --git a/src/main/unicorntail/unicorntail.def b/src/main/unicorntail/unicorntail.def index e45383d9..7f68ad03 100644 --- a/src/main/unicorntail/unicorntail.def +++ b/src/main/unicorntail/unicorntail.def @@ -2,3 +2,8 @@ LIBRARY unicorntail EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/unicorntail/usbmem.c b/src/main/unicorntail/usbmem.c index 50b496e6..b143b030 100644 --- a/src/main/unicorntail/usbmem.c +++ b/src/main/unicorntail/usbmem.c @@ -3,9 +3,10 @@ #include #include +#include "iface-core/log.h" + #include "hook/iohook.h" -#include "util/log.h" #include "util/str.h" static bool usbmem_match_irp(const struct irp *irp); diff --git a/src/main/util/Module.mk b/src/main/util/Module.mk index ab8d4956..c0273e70 100644 --- a/src/main/util/Module.mk +++ b/src/main/util/Module.mk @@ -5,11 +5,11 @@ src_util := \ cmdline.c \ crc.c \ crypto.c \ + debug.c \ fs.c \ hex.c \ iobuf.c \ list.c \ - log.c \ math.c \ mem.c \ msg-thread.c \ @@ -18,7 +18,6 @@ src_util := \ proc.c \ signal.c \ str.c \ - thread.c \ time.c \ winres.c \ diff --git a/src/main/util/array.c b/src/main/util/array.c index 900fba17..5a9d52f5 100644 --- a/src/main/util/array.c +++ b/src/main/util/array.c @@ -2,8 +2,9 @@ #include #include +#include "iface-core/log.h" + #include "util/array.h" -#include "util/log.h" #include "util/mem.h" void array_init(struct array *array) diff --git a/src/main/util/crc.c b/src/main/util/crc.c index c49af451..4c163a9a 100644 --- a/src/main/util/crc.c +++ b/src/main/util/crc.c @@ -1,7 +1,7 @@ #include #include -#include "util/log.h" +#include "iface-core/log.h" uint8_t crc8(const void *ptr, size_t nbytes, uint8_t in) { diff --git a/src/main/util/crypto.c b/src/main/util/crypto.c index 110dd99e..6ca2009f 100644 --- a/src/main/util/crypto.c +++ b/src/main/util/crypto.c @@ -1,12 +1,13 @@ #define LOG_MODULE "crypto" -#include "util/crypto.h" -#include "util/log.h" -#include "util/mem.h" - #include #include +#include "iface-core/log.h" + +#include "util/crypto.h" +#include "util/mem.h" + static const char vista_prov[] = "Microsoft Enhanced RSA and AES Cryptographic Provider"; static const char winxp_prov[] = diff --git a/src/main/util/debug.c b/src/main/util/debug.c new file mode 100644 index 00000000..67091561 --- /dev/null +++ b/src/main/util/debug.c @@ -0,0 +1,47 @@ +#define LOG_MODULE "util-debug" + +#include + +#include + +#include "iface-core/log.h" + +#define EX_DESC(name) \ + case EXCEPTION_##name: \ + desc = " (" #name ")"; \ + break + +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..8467eada --- /dev/null +++ b/src/main/util/debug.h @@ -0,0 +1,8 @@ +#ifndef UTIL_DEBUG_H +#define UTIL_DEBUG_H + +#include + +const char *debug_exception_code_to_str(DWORD code); + +#endif \ No newline at end of file diff --git a/src/main/util/fs.c b/src/main/util/fs.c index 731fdf93..b40dd645 100644 --- a/src/main/util/fs.c +++ b/src/main/util/fs.c @@ -6,9 +6,10 @@ #include #include +#include "iface-core/log.h" + #include "util/defs.h" #include "util/fs.h" -#include "util/log.h" #include "util/mem.h" #include "util/str.h" diff --git a/src/main/util/hex.c b/src/main/util/hex.c index 1ac6b4d6..da45a3cd 100644 --- a/src/main/util/hex.c +++ b/src/main/util/hex.c @@ -2,8 +2,9 @@ #include #include +#include "iface-core/log.h" + #include "util/hex.h" -#include "util/log.h" static bool hex_decode_nibble(char c, uint8_t *nibble) { diff --git a/src/main/util/iobuf.c b/src/main/util/iobuf.c index 45884ead..31ad8d13 100644 --- a/src/main/util/iobuf.c +++ b/src/main/util/iobuf.c @@ -1,8 +1,9 @@ #define LOG_MODULE "util-iobuf" -#include "util/iobuf.h" +#include "iface-core/log.h" + #include "util/hex.h" -#include "util/log.h" +#include "util/iobuf.h" #include "util/mem.h" void iobuf_log(struct iobuf *buffer, const char *tag) diff --git a/src/main/util/log.c b/src/main/util/log.c deleted file mode 100644 index 7da1d63a..00000000 --- a/src/main/util/log.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "util/log.h" -#include "util/str.h" - -#include - -#include -#include -#include -#include - -static log_writer_t log_writer; -static void *log_writer_ctx; -static enum log_level log_level; - -static void log_builtin_fatal(const char *module, const char *fmt, ...); -static void log_builtin_info(const char *module, const char *fmt, ...); -static void log_builtin_misc(const char *module, const char *fmt, ...); -static void log_builtin_warning(const char *module, const char *fmt, ...); -static void log_builtin_format( - enum log_level msg_level, const char *module, const char *fmt, va_list ap); - -#define IMPLEMENT_SINK(name, msg_level) \ - static void name(const char *module, const char *fmt, ...) \ - { \ - va_list ap; \ - \ - va_start(ap, fmt); \ - log_builtin_format(msg_level, module, fmt, ap); \ - va_end(ap); \ - } - -IMPLEMENT_SINK(log_builtin_info, LOG_LEVEL_INFO) -IMPLEMENT_SINK(log_builtin_misc, LOG_LEVEL_MISC) -IMPLEMENT_SINK(log_builtin_warning, LOG_LEVEL_WARNING) - -static void log_builtin_fatal(const char *module, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - log_builtin_format(LOG_LEVEL_FATAL, module, fmt, ap); - va_end(ap); - - DebugBreak(); - ExitProcess(EXIT_FAILURE); -} - -static void log_builtin_format( - enum log_level msg_level, const char *module, const char *fmt, va_list ap) -{ - static const char chars[] = "FWIM"; - - /* 64k so we can log data dumps of rs232 without crashing */ - char line[65536]; - char msg[65536]; - int result; - - if (msg_level <= log_level) { - str_vformat(msg, sizeof(msg), fmt, ap); - result = str_format( - line, sizeof(line), "%c:%s: %s\n", chars[msg_level], module, msg); - - log_writer(log_writer_ctx, line, result); - } -} - -void log_assert_body(const char *file, int line, const char *function) -{ - log_impl_fatal("assert", "%s:%d: function `%s'", file, line, function); -} - -void log_to_external( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - log_impl_misc = misc; - log_impl_info = info; - log_impl_warning = warning; - log_impl_fatal = fatal; -} - -void log_to_writer(log_writer_t writer, void *ctx) -{ - log_impl_misc = log_builtin_misc; - log_impl_info = log_builtin_info; - log_impl_warning = log_builtin_warning; - log_impl_fatal = log_builtin_fatal; - - if (writer != NULL) { - log_writer = writer; - log_writer_ctx = ctx; - } else { - log_writer = log_writer_null; - } -} - -void log_set_level(enum log_level new_level) -{ - log_level = new_level; -} - -void log_writer_debug(void *ctx, const char *chars, size_t nchars) -{ - OutputDebugStringA(chars); -} - -void log_writer_stdout(void *ctx, const char *chars, size_t nchars) -{ - printf("%s", chars); -} - -void log_writer_stderr(void *ctx, const char *chars, size_t nchars) -{ - fprintf(stderr, "%s", chars); -} - -void log_writer_file(void *ctx, const char *chars, size_t nchars) -{ - fwrite(chars, 1, nchars, (FILE *) ctx); - fflush((FILE *) ctx); -} - -void log_writer_null(void *ctx, const char *chars, size_t nchars) -{ -} - -log_formatter_t log_impl_misc = log_builtin_misc; -log_formatter_t log_impl_info = log_builtin_info; -log_formatter_t log_impl_warning = log_builtin_warning; -log_formatter_t log_impl_fatal = log_builtin_fatal; -static log_writer_t log_writer = log_writer_null; -static enum log_level log_level = LOG_LEVEL_MISC; diff --git a/src/main/util/log.h b/src/main/util/log.h deleted file mode 100644 index 47603fa1..00000000 --- a/src/main/util/log.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef UTIL_LOG_H -#define UTIL_LOG_H - -#include -#include - -#include "bemanitools/glue.h" - -#include "util/defs.h" - -/* Dynamically retargetable logging system modeled on (and potentially - integrateable with) the one found in AVS2 */ - -/* BUILD_MODULE is passed in as a command-line #define by the makefile */ - -#ifndef LOG_MODULE -#define LOG_MODULE STRINGIFY(BUILD_MODULE) -#endif - -#ifndef LOG_SUPPRESS - -#define log_misc(...) log_impl_misc(LOG_MODULE, __VA_ARGS__) -#define log_info(...) log_impl_info(LOG_MODULE, __VA_ARGS__) -#define log_warning(...) log_impl_warning(LOG_MODULE, __VA_ARGS__) - -/* This doesn't really belong here, but it's what libavs does so w/e */ - -#define log_assert(x) \ - do { \ - if (!(x)) { \ - log_assert_body(__FILE__, __LINE__, __FUNCTION__); \ - } \ - } while (0) - -#else - -#define log_misc(...) -#define log_info(...) -#define log_warning(...) -#define log_assert(x) \ - do { \ - if (!(x)) { \ - abort(); \ - } \ - } while (0) - -#endif - -#define log_fatal(...) \ - do { \ - log_impl_fatal(LOG_MODULE, __VA_ARGS__); \ - abort(); \ - } while (0) - -typedef void (*log_writer_t)(void *ctx, const char *chars, size_t nchars); - -extern log_formatter_t log_impl_misc; -extern log_formatter_t log_impl_info; -extern log_formatter_t log_impl_warning; -extern log_formatter_t log_impl_fatal; - -enum log_level { - LOG_LEVEL_FATAL = 0, - LOG_LEVEL_WARNING = 1, - LOG_LEVEL_INFO = 2, - LOG_LEVEL_MISC = 3, -}; - -void log_assert_body(const char *file, int line, const char *function); -void log_to_external( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal); -void log_to_writer(log_writer_t writer, void *ctx); - -void log_set_level(enum log_level new_level); - -/* I tried to make this API match the function signature of the AVS log writer - callback, but then the signature changed and the explicit line breaks - being passed to that callback went away. So we don't try to track that API - any more. Launcher defines its own custom writer anyway. */ - -void log_writer_debug(void *ctx, const char *chars, size_t nchars); -void log_writer_stdout(void *ctx, const char *chars, size_t nchars); -void log_writer_stderr(void *ctx, const char *chars, size_t nchars); -void log_writer_file(void *ctx, const char *chars, size_t nchars); -void log_writer_null(void *ctx, const char *chars, size_t nchars); - -#endif diff --git a/src/main/util/mem.c b/src/main/util/mem.c index 53e84ffb..8a1053f1 100644 --- a/src/main/util/mem.c +++ b/src/main/util/mem.c @@ -7,7 +7,7 @@ #include #include -#include "util/log.h" +#include "iface-core/log.h" void *xcalloc(size_t nbytes) { diff --git a/src/main/util/msg-thread.c b/src/main/util/msg-thread.c index 6b5623d8..8b9dd2ee 100644 --- a/src/main/util/msg-thread.c +++ b/src/main/util/msg-thread.c @@ -5,15 +5,16 @@ #include #include -#include "util/log.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + #include "util/msg-thread.h" -#include "util/thread.h" static bool msg_thread_step(HWND hwnd); static const char msg_wndclass_name[] = "msg-thread"; -static int msg_thread_id; +static bt_core_thread_id_t msg_thread_id; static HANDLE msg_thread_ready; static HANDLE msg_thread_stop; static HWND msg_window; @@ -100,9 +101,14 @@ static bool msg_thread_step(HWND hwnd) void msg_thread_init(HINSTANCE inst) { + bt_core_thread_result_t result; + msg_thread_ready = CreateEvent(NULL, TRUE, FALSE, NULL); msg_thread_stop = CreateEvent(NULL, TRUE, FALSE, NULL); - msg_thread_id = thread_create(msg_thread_proc, inst, 0x4000, 0); + result = + bt_core_thread_create(msg_thread_proc, inst, 0x4000, 0, &msg_thread_id); + + bt_core_thread_fatal_on_error(result); WaitForSingleObject(msg_thread_ready, INFINITE); CloseHandle(msg_thread_ready); @@ -110,10 +116,15 @@ void msg_thread_init(HINSTANCE inst) void msg_thread_fini(void) { + bt_core_thread_result_t result; + SetEvent(msg_thread_stop); - thread_join(msg_thread_id, NULL); - thread_destroy(msg_thread_id); + result = bt_core_thread_join(msg_thread_id, NULL); + bt_core_thread_fatal_on_error(result); + + result = bt_core_thread_destroy(msg_thread_id); + bt_core_thread_fatal_on_error(result); CloseHandle(msg_thread_stop); } diff --git a/src/main/util/net.c b/src/main/util/net.c index 492e3ef1..b62952cb 100644 --- a/src/main/util/net.c +++ b/src/main/util/net.c @@ -6,7 +6,8 @@ #include #include -#include "util/log.h" +#include "iface-core/log.h" + #include "util/mem.h" #include "util/net.h" #include "util/str.h" diff --git a/src/main/util/os.c b/src/main/util/os.c index c63de00d..10e50bdd 100644 --- a/src/main/util/os.c +++ b/src/main/util/os.c @@ -6,7 +6,8 @@ #include -#include "util/log.h" +#include "iface-core/log.h" + #include "util/os.h" #include "util/str.h" diff --git a/src/main/util/proc.c b/src/main/util/proc.c index 84731133..8ee2ec96 100644 --- a/src/main/util/proc.c +++ b/src/main/util/proc.c @@ -1,12 +1,16 @@ #define LOG_MODULE "util-proc" +// clang-format off +// Don't format because the order is important here #include +#include #include +// clang-format on #include #include -#include "util/log.h" +#include "iface-core/log.h" bool proc_is_running_as_admin_user() { @@ -58,4 +62,38 @@ void proc_terminate_current_process(uint32_t exit_code) SYNCHRONIZE | PROCESS_TERMINATE, TRUE, GetCurrentProcessId()); TerminateProcess(hnd, exit_code); +} + +bool proc_is_module_loaded(const char *name) +{ + HMODULE modules[1024]; + HANDLE process; + DWORD size; + char module_name[MAX_PATH]; + + process = GetCurrentProcess(); + + if (EnumProcessModules(process, modules, sizeof(modules), &size)) { + for (int i = 0; i < (size / sizeof(HMODULE)); i++) { + if (GetModuleFileNameEx( + process, + modules[i], + module_name, + sizeof(module_name) / sizeof(char))) { + const char *p = strrchr(module_name, '\\'); + + if (p != NULL) { + p++; + } else { + p = module_name; + } + + if (_stricmp(p, name) == 0) { + return true; + } + } + } + } + + return false; } \ No newline at end of file diff --git a/src/main/util/proc.h b/src/main/util/proc.h index be47a40d..e86a42e9 100644 --- a/src/main/util/proc.h +++ b/src/main/util/proc.h @@ -5,4 +5,6 @@ bool proc_is_running_as_admin_user(); -void proc_terminate_current_process(uint32_t exit_code); \ No newline at end of file +void proc_terminate_current_process(uint32_t exit_code); + +bool proc_is_module_loaded(const char *name); \ No newline at end of file diff --git a/src/main/util/signal.c b/src/main/util/signal.c index 4c15acd5..78942b0d 100644 --- a/src/main/util/signal.c +++ b/src/main/util/signal.c @@ -1,8 +1,10 @@ +#define LOG_MODULE "util-signal" + #include -#include + +#include "iface-core/log.h" #include "util/hex.h" -#include "util/log.h" #include "util/signal.h" static signal_shutdown_handler_t shutdown_handler; @@ -45,40 +47,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 +59,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 diff --git a/src/main/util/thread.c b/src/main/util/thread.c deleted file mode 100644 index daa82677..00000000 --- a/src/main/util/thread.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include - -#include -#include - -#include "util/defs.h" -#include "util/thread.h" - -struct shim_ctx { - HANDLE barrier; - int (*proc)(void *); - void *ctx; -}; - -thread_create_t thread_impl_create = crt_thread_create; -thread_join_t thread_impl_join = crt_thread_join; -thread_destroy_t thread_impl_destroy = crt_thread_destroy; - -static unsigned int STDCALL crt_thread_shim(void *outer_ctx) -{ - struct shim_ctx *sctx = outer_ctx; - int (*proc)(void *); - void *inner_ctx; - - proc = sctx->proc; - inner_ctx = sctx->ctx; - - SetEvent(sctx->barrier); - - return proc(inner_ctx); -} - -int crt_thread_create( - int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority) -{ - struct shim_ctx sctx; - uintptr_t thread_id; - - sctx.barrier = CreateEvent(NULL, TRUE, FALSE, NULL); - sctx.proc = proc; - sctx.ctx = ctx; - - thread_id = _beginthreadex(NULL, stack_sz, crt_thread_shim, &sctx, 0, NULL); - - WaitForSingleObject(sctx.barrier, INFINITE); - CloseHandle(sctx.barrier); - - return (int) thread_id; -} - -void crt_thread_destroy(int thread_id) -{ - CloseHandle((HANDLE) (uintptr_t) thread_id); -} - -void crt_thread_join(int thread_id, int *result) -{ - WaitForSingleObject((HANDLE) (uintptr_t) thread_id, INFINITE); - - if (result) { - GetExitCodeThread((HANDLE) (uintptr_t) thread_id, (DWORD *) result); - } -} - -void thread_api_init( - thread_create_t create, thread_join_t join, thread_destroy_t destroy) -{ - if (create == NULL || join == NULL || destroy == NULL) { - abort(); - } - - thread_impl_create = create; - thread_impl_join = join; - thread_impl_destroy = destroy; -} - -int thread_create( - int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority) -{ - return thread_impl_create(proc, ctx, stack_sz, priority); -} - -void thread_join(int thread_id, int *result) -{ - thread_impl_join(thread_id, result); -} - -void thread_destroy(int thread_id) -{ - thread_impl_destroy(thread_id); -} diff --git a/src/main/util/thread.h b/src/main/util/thread.h deleted file mode 100644 index dca396b7..00000000 --- a/src/main/util/thread.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef UTIL_THREAD_H -#define UTIL_THREAD_H - -#include - -#include "bemanitools/glue.h" - -int crt_thread_create( - int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority); -void crt_thread_join(int thread_id, int *result); -void crt_thread_destroy(int thread_id); - -void thread_api_init( - thread_create_t create, thread_join_t join, thread_destroy_t destroy); -int thread_create( - int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority); -void thread_join(int thread_id, int *result); -void thread_destroy(int thread_id); - -#endif diff --git a/src/main/util/time.c b/src/main/util/time.c index 0412b29c..d875978f 100644 --- a/src/main/util/time.c +++ b/src/main/util/time.c @@ -1,6 +1,7 @@ #include -#include "util/log.h" +#include "iface-core/log.h" + #include "util/time.h" static uint64_t counter_freq_ns; diff --git a/src/main/vefxio/Module.mk b/src/main/vefxio/Module.mk index 6f2f168b..a52d6e2b 100644 --- a/src/main/vefxio/Module.mk +++ b/src/main/vefxio/Module.mk @@ -4,7 +4,8 @@ ldflags_vefxio := \ -lwinmm libs_vefxio := \ - geninput + iface-core \ + geninput \ src_vefxio := \ vefxio.c \ diff --git a/src/main/vefxio/vefxio.c b/src/main/vefxio/vefxio.c index 5d430560..3c42f4d5 100644 --- a/src/main/vefxio/vefxio.c +++ b/src/main/vefxio/vefxio.c @@ -1,13 +1,4 @@ -/* This is the source code for the VEFXIO.DLL that ships with Bemanitools 5. - - If you want to add on some minor functionality like a custom 16seg display - or a customer slider board then feel free to extend this code with support - for your custom device. - - This DLL is only used by the generic input variant of IIDXIO.DLL that ships - with Bemanitools by default. If you want to create a custom IO board that - provides all of the inputs for IIDX then you should replace IIDXIO.DLL - instead and not call into this DLL at all. */ +#define LOG_MODULE "vefxio" // clang-format off // Don't format because the order is important here @@ -18,8 +9,10 @@ #include #include -#include "bemanitools/input.h" -#include "bemanitools/vefxio.h" +#include "iface-core/log.h" +#include "iface-io/vefx.h" + +#include "sdk/module/io/vefx.h" #define MSEC_PER_NOTCH 128 @@ -63,37 +56,7 @@ static struct vefx_io_slider vefx_io_slider[5]; static void vefx_io_slider_update(uint64_t *ppad); -/* Uncomment these if you need them. */ - -#if 0 -static log_formatter_t vefx_io_log_misc; -static log_formatter_t vefx_io_log_info; -static log_formatter_t vefx_io_log_warning; -static log_formatter_t vefx_io_log_fatal; -#endif - -void vefx_io_set_loggers( - log_formatter_t misc, - log_formatter_t info, - log_formatter_t warning, - log_formatter_t fatal) -{ - /* Uncomment this block if you have something you'd like to log. - - You should probably return false from the appropriate function instead - of calling the fatal logger yourself though. */ -#if 0 - vefx_io_log_misc = misc; - vefx_io_log_info = info; - vefx_io_log_warning = warning; - vefx_io_log_fatal = fatal; -#endif -} - -bool vefx_io_init( - thread_create_t thread_create, - thread_join_t thread_join, - thread_destroy_t thread_destroy) +bool bt_io_vefx_init() { /* geninput should have already been initted be now so we don't do it */ vefx_io_slider[0].pos = 8; @@ -108,17 +71,16 @@ bool vefx_io_init( return true; } -bool vefx_io_recv(uint64_t *ppad) +bool bt_io_vefx_recv(uint64_t *ppad) { vefx_io_slider_update(ppad); return true; } -void vefx_io_fini(void) +void bt_io_vefx_fini(void) { - /* This function gets called as IIDX shuts down after an Alt-F4. Close your - connections to your IO devices here. */ + // noop } static void vefx_io_slider_update(uint64_t *ppad) @@ -170,7 +132,7 @@ static void vefx_io_slider_update(uint64_t *ppad) } } -uint8_t vefx_io_get_slider(uint8_t slider_no) +uint8_t bt_io_vefx_slider_get(uint8_t slider_no) { if (slider_no > 4) { return 0; @@ -179,10 +141,26 @@ uint8_t vefx_io_get_slider(uint8_t slider_no) return vefx_io_slider[slider_no].pos; } -bool vefx_io_write_16seg(const char *text) +bool bt_io_vefx_16seg_send(const char *text) { /* Insert code to write to your 16seg display here. Log something and return false if you encounter an IO error. */ return true; } + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_io_vefx_api_get(bt_io_vefx_api_t *api) +{ + api->version = 1; + + api->v1.init = bt_io_vefx_init; + api->v1.fini = bt_io_vefx_fini; + api->v1.recv = bt_io_vefx_recv; + api->v1.slider_get = bt_io_vefx_slider_get; + api->v1._16seg_send = bt_io_vefx_16seg_send; +} \ No newline at end of file diff --git a/src/main/vefxio/vefxio.def b/src/main/vefxio/vefxio.def index 550384ea..7959bdc0 100644 --- a/src/main/vefxio/vefxio.def +++ b/src/main/vefxio/vefxio.def @@ -1,9 +1,13 @@ LIBRARY vefxio EXPORTS - vefx_io_get_slider - vefx_io_recv - vefx_io_write_16seg - vefx_io_fini - vefx_io_init - vefx_io_set_loggers + ; Bemanitools 6 API + bt_module_core_log_api_set + bt_module_io_vefx_api_get + + ; Direct API + bt_io_vefx_init + bt_io_vefx_fini + bt_io_vefx_recv + bt_io_vefx_slider_get + bt_io_vefx_16seg_send diff --git a/src/main/vigem-ddrio/Module.mk b/src/main/vigem-ddrio/Module.mk index 8aae8a25..20d9ca6d 100644 --- a/src/main/vigem-ddrio/Module.mk +++ b/src/main/vigem-ddrio/Module.mk @@ -8,13 +8,17 @@ cppflags_vigem-ddrio := \ ldflags_vigem-ddrio := \ -lsetupapi \ + -lws2_32 \ libs_vigem-ddrio := \ - cconfig \ - ddrio \ - util \ + core \ vigemstub \ + module \ + iface-io \ + iface-core \ + security \ + util \ src_vigem-ddrio := \ + config.c \ main.c \ - config-vigem-ddrio.c \ diff --git a/src/main/vigem-ddrio/config-vigem-ddrio.c b/src/main/vigem-ddrio/config-vigem-ddrio.c deleted file mode 100644 index 59e8251f..00000000 --- a/src/main/vigem-ddrio/config-vigem-ddrio.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "cconfig/cconfig-main.h" -#include "cconfig/cconfig-util.h" - -#include "vigem-ddrio/config-vigem-ddrio.h" - -#include "util/log.h" - -#define VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY \ - "ddrio.enable_reactive_light" - -#define VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE true - -static void vigem_ddrio_config_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY, - VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE, - "Enable reactive lights based on input."); -} - -static void vigem_ddrio_config_get( - struct vigem_ddrio_config *vigem_config, struct cconfig *config) -{ - if (!cconfig_util_get_bool( - config, - VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY, - &vigem_config->enable_reactive_light, - VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY, - VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE); - } -} - -bool get_vigem_ddrio_config(struct vigem_ddrio_config *config_out) -{ - struct cconfig *config; - - config = cconfig_init(); - - vigem_ddrio_config_init(config); - - if (!cconfig_main_config_init( - config, - "--config", - "vigem-ddrio.conf", - "--help", - "-h", - "vigem-ddrio", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - return false; - } - - vigem_ddrio_config_get(config_out, config); - - cconfig_finit(config); - - return true; -} diff --git a/src/main/vigem-ddrio/config-vigem-ddrio.h b/src/main/vigem-ddrio/config-vigem-ddrio.h deleted file mode 100644 index df006454..00000000 --- a/src/main/vigem-ddrio/config-vigem-ddrio.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef VIGEM_DDRIO_CONFIG_H -#define VIGEM_DDRIO_CONFIG_H - -#include - -#include "cconfig/cconfig.h" - -struct vigem_ddrio_config { - bool enable_reactive_light; -}; - -bool get_vigem_ddrio_config(struct vigem_ddrio_config *config_out); - -#endif \ No newline at end of file diff --git a/src/main/vigem-ddrio/config.c b/src/main/vigem-ddrio/config.c new file mode 100644 index 00000000..53586c13 --- /dev/null +++ b/src/main/vigem-ddrio/config.c @@ -0,0 +1,8 @@ +#include "core/config-ext.h" + +#include "vigem-ddrio/config.h" + +void vigem_ddrio_config_get(const bt_core_config_t *config, vigem_ddrio_config_t *config_out) +{ + bt_core_config_ext_bool_get(config, "enable_reactive_light", &config_out->enable_reactive_light); +} diff --git a/src/main/vigem-ddrio/config.h b/src/main/vigem-ddrio/config.h new file mode 100644 index 00000000..6b8d55ad --- /dev/null +++ b/src/main/vigem-ddrio/config.h @@ -0,0 +1,12 @@ +#ifndef VIGEM_DDRIO_CONFIG_H +#define VIGEM_DDRIO_CONFIG_H + +#include "api/core/config.h" + +typedef struct vigem_ddrio_config { + bool enable_reactive_light; +} vigem_ddrio_config_t; + +void vigem_ddrio_config_get(const bt_core_config_t *config, vigem_ddrio_config_t *config_out); + +#endif \ No newline at end of file diff --git a/src/main/vigem-ddrio/main.c b/src/main/vigem-ddrio/main.c index 62cc7b18..2c95a81a 100644 --- a/src/main/vigem-ddrio/main.c +++ b/src/main/vigem-ddrio/main.c @@ -7,16 +7,29 @@ #include "ViGEm/Client.h" -#include "bemanitools/ddrio.h" -#include "util/log.h" +#include "core/config-property-node.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" +#include "core/thread-crt.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" +#include "iface-io/ddr.h" + +#include "module/io-ext.h" +#include "module/io.h" + #include "util/math.h" -#include "util/thread.h" + #include "vigemstub/helper.h" -#include "vigem-ddrio/config-vigem-ddrio.h" +#include "vigem-ddrio/config.h" #define NUM_PADS 2 +static module_io_t *_module_io_ddr; + bool check_key(uint32_t input, size_t idx_in) { if ((input >> idx_in) & 1) { @@ -46,13 +59,13 @@ uint32_t check_assign_light(uint32_t input, size_t idx_in, size_t gpio_out) void set_all_lights(bool on) { - ddr_io_set_lights_extio(on ? UINT32_MAX : 0); - ddr_io_set_lights_p3io(on ? UINT32_MAX : 0); - ddr_io_set_lights_hdxs_panel(on ? UINT32_MAX : 0); + bt_io_ddr_extio_lights_set(on ? UINT32_MAX : 0); + bt_io_ddr_p3io_lights_set(on ? UINT32_MAX : 0); + bt_io_ddr_hdxs_lights_panel_set(on ? UINT32_MAX : 0); for (int i = 0; i < 4; i++) { uint8_t val = on ? UINT8_MAX : 0; - ddr_io_set_lights_hdxs_rgb(i, val, val, val); + bt_io_ddr_hdxs_lights_rgb_set(i, val, val, val); } } @@ -62,67 +75,115 @@ void set_reactive_lights(uint32_t input_state) uint32_t new_p3io_state = 0; uint32_t new_hdxs_state = 0; - new_extio_state |= check_assign_light(input_state, DDR_P1_UP, LIGHT_P1_UP); - new_extio_state |= - check_assign_light(input_state, DDR_P1_DOWN, LIGHT_P1_DOWN); - new_extio_state |= - check_assign_light(input_state, DDR_P1_LEFT, LIGHT_P1_LEFT); - new_extio_state |= - check_assign_light(input_state, DDR_P1_RIGHT, LIGHT_P1_RIGHT); - - new_extio_state |= check_assign_light(input_state, DDR_P2_UP, LIGHT_P2_UP); - new_extio_state |= - check_assign_light(input_state, DDR_P2_DOWN, LIGHT_P2_DOWN); - new_extio_state |= - check_assign_light(input_state, DDR_P2_LEFT, LIGHT_P2_LEFT); - new_extio_state |= - check_assign_light(input_state, DDR_P2_RIGHT, LIGHT_P2_RIGHT); - - new_p3io_state |= - check_assign_light(input_state, DDR_P1_START, LIGHT_P1_MENU); - new_p3io_state |= - check_assign_light(input_state, DDR_P2_START, LIGHT_P2_MENU); - - new_hdxs_state |= - check_assign_light(input_state, DDR_P1_START, LIGHT_HD_P1_START); - new_hdxs_state |= - check_assign_light(input_state, DDR_P1_MENU_UP, LIGHT_HD_P1_UP_DOWN); - new_hdxs_state |= - check_assign_light(input_state, DDR_P1_MENU_DOWN, LIGHT_HD_P1_UP_DOWN); + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P1_UP, BT_IO_DDR_EXTIO_LIGHT_P1_UP); + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P1_DOWN, BT_IO_DDR_EXTIO_LIGHT_P1_DOWN); + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P1_LEFT, BT_IO_DDR_EXTIO_LIGHT_P1_LEFT); + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P1_RIGHT, BT_IO_DDR_EXTIO_LIGHT_P1_RIGHT); + + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P2_UP, BT_IO_DDR_EXTIO_LIGHT_P2_UP); + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P2_DOWN, BT_IO_DDR_EXTIO_LIGHT_P2_DOWN); + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P2_LEFT, BT_IO_DDR_EXTIO_LIGHT_P2_LEFT); + new_extio_state |= check_assign_light( + input_state, BT_IO_DDR_P2_RIGHT, BT_IO_DDR_EXTIO_LIGHT_P2_RIGHT); + + new_p3io_state |= check_assign_light( + input_state, BT_IO_DDR_P1_START, BT_IO_DDR_P3IO_LIGHT_P1_MENU); + new_p3io_state |= check_assign_light( + input_state, BT_IO_DDR_P2_START, BT_IO_DDR_P3IO_LIGHT_P2_MENU); + + new_hdxs_state |= check_assign_light( + input_state, BT_IO_DDR_P1_START, BT_IO_DDR_HDXS_LIGHT_HD_P1_START); + new_hdxs_state |= check_assign_light( + input_state, BT_IO_DDR_P1_MENU_UP, BT_IO_DDR_HDXS_LIGHT_HD_P1_UP_DOWN); + new_hdxs_state |= check_assign_light( + input_state, + BT_IO_DDR_P1_MENU_DOWN, + BT_IO_DDR_HDXS_LIGHT_HD_P1_UP_DOWN); + new_hdxs_state |= check_assign_light( + input_state, + BT_IO_DDR_P1_MENU_LEFT, + BT_IO_DDR_HDXS_LIGHT_HD_P1_LEFT_RIGHT); + new_hdxs_state |= check_assign_light( + input_state, + BT_IO_DDR_P1_MENU_RIGHT, + BT_IO_DDR_HDXS_LIGHT_HD_P1_LEFT_RIGHT); + new_hdxs_state |= check_assign_light( - input_state, DDR_P1_MENU_LEFT, LIGHT_HD_P1_LEFT_RIGHT); + input_state, BT_IO_DDR_P2_START, BT_IO_DDR_HDXS_LIGHT_HD_P2_START); new_hdxs_state |= check_assign_light( - input_state, DDR_P1_MENU_RIGHT, LIGHT_HD_P1_LEFT_RIGHT); - - new_hdxs_state |= - check_assign_light(input_state, DDR_P2_START, LIGHT_HD_P2_START); - new_hdxs_state |= - check_assign_light(input_state, DDR_P2_MENU_UP, LIGHT_HD_P2_UP_DOWN); - new_hdxs_state |= - check_assign_light(input_state, DDR_P2_MENU_DOWN, LIGHT_HD_P2_UP_DOWN); + input_state, BT_IO_DDR_P2_MENU_UP, BT_IO_DDR_HDXS_LIGHT_HD_P2_UP_DOWN); new_hdxs_state |= check_assign_light( - input_state, DDR_P2_MENU_LEFT, LIGHT_HD_P2_LEFT_RIGHT); + input_state, + BT_IO_DDR_P2_MENU_DOWN, + BT_IO_DDR_HDXS_LIGHT_HD_P2_UP_DOWN); new_hdxs_state |= check_assign_light( - input_state, DDR_P2_MENU_RIGHT, LIGHT_HD_P2_LEFT_RIGHT); + input_state, + BT_IO_DDR_P2_MENU_LEFT, + BT_IO_DDR_HDXS_LIGHT_HD_P2_LEFT_RIGHT); + new_hdxs_state |= check_assign_light( + input_state, + BT_IO_DDR_P2_MENU_RIGHT, + BT_IO_DDR_HDXS_LIGHT_HD_P2_LEFT_RIGHT); - ddr_io_set_lights_extio(new_extio_state); - ddr_io_set_lights_p3io(new_p3io_state); - ddr_io_set_lights_hdxs_panel(new_hdxs_state); + bt_io_ddr_extio_lights_set(new_extio_state); + bt_io_ddr_p3io_lights_set(new_p3io_state); + bt_io_ddr_hdxs_lights_panel_set(new_hdxs_state); +} + +static void _module_io_ddr_init(module_io_t **module) +{ + bt_io_ddr_api_t api; + + module_io_ext_load_and_init( + "ddrio.dll", "bt_module_io_ddr_api_get", module); + module_io_api_get(*module, &api); + bt_io_ddr_api_set(&api); +} + +static void _config_load(vigem_ddrio_config_t *config_out) +{ + core_property_t *property; + core_property_result_t property_result; + core_property_node_t node; + core_property_node_result_t node_result; + bt_core_config_t *config; + + property_result = core_property_file_load("vigem-ddrio.xml", &property); + core_property_fatal_on_error(property_result); + + node_result = core_property_root_node_get(property, &node); + core_property_node_fatal_on_error(node_result); + + core_config_property_node_init(&node, &config); + + vigem_ddrio_config_get(config, config_out); + + core_config_property_node_free(&config); + core_property_free(&property); } int main(int argc, char **argv) { - log_to_writer(log_writer_stdout, NULL); + vigem_ddrio_config_t config; + + core_log_bt_core_api_set(); + core_thread_crt_core_api_set(); + core_config_property_node_core_api_set(); - struct vigem_ddrio_config config; - if (!get_vigem_ddrio_config(&config)) { - exit(EXIT_FAILURE); - } + core_log_bt_ext_init_with_stdout(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_INFO); - ddr_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _config_load(&config); + _module_io_ddr_init(&_module_io_ddr); - if (!ddr_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) { + if (!bt_io_ddr_init()) { log_warning("Initializing ddrio failed"); return -1; } @@ -150,7 +211,9 @@ int main(int argc, char **argv) } if (failed) { - ddr_io_fini(); + bt_io_ddr_fini(); + bt_io_ddr_api_clear(); + module_io_free(&_module_io_ddr); return -1; } @@ -161,59 +224,59 @@ int main(int argc, char **argv) log_info("vigem init succeeded, beginning poll loop"); while (loop) { - pad_state = ddr_io_read_pad(); + pad_state = bt_io_ddr_pad_read(); for (uint8_t i = 0; i < NUM_PADS; i++) { memset(&state[i], 0, sizeof(state[i])); } + state[0].wButtons |= check_assign_key( + pad_state, BT_IO_DDR_TEST, XUSB_GAMEPAD_LEFT_THUMB); + state[0].wButtons |= check_assign_key( + pad_state, BT_IO_DDR_SERVICE, XUSB_GAMEPAD_RIGHT_THUMB); state[0].wButtons |= - check_assign_key(pad_state, DDR_TEST, XUSB_GAMEPAD_LEFT_THUMB); - state[0].wButtons |= - check_assign_key(pad_state, DDR_SERVICE, XUSB_GAMEPAD_RIGHT_THUMB); - state[0].wButtons |= - check_assign_key(pad_state, DDR_COIN, XUSB_GAMEPAD_BACK); + check_assign_key(pad_state, BT_IO_DDR_COIN, XUSB_GAMEPAD_BACK); // assign arrows to face buttons due to jumps / hat interpretation state[0].wButtons |= - check_assign_key(pad_state, DDR_P1_UP, XUSB_GAMEPAD_Y); + check_assign_key(pad_state, BT_IO_DDR_P1_UP, XUSB_GAMEPAD_Y); state[0].wButtons |= - check_assign_key(pad_state, DDR_P1_DOWN, XUSB_GAMEPAD_A); + check_assign_key(pad_state, BT_IO_DDR_P1_DOWN, XUSB_GAMEPAD_A); state[0].wButtons |= - check_assign_key(pad_state, DDR_P1_LEFT, XUSB_GAMEPAD_X); + check_assign_key(pad_state, BT_IO_DDR_P1_LEFT, XUSB_GAMEPAD_X); state[0].wButtons |= - check_assign_key(pad_state, DDR_P1_RIGHT, XUSB_GAMEPAD_B); + check_assign_key(pad_state, BT_IO_DDR_P1_RIGHT, XUSB_GAMEPAD_B); state[0].wButtons |= - check_assign_key(pad_state, DDR_P1_START, XUSB_GAMEPAD_START); - state[0].wButtons |= - check_assign_key(pad_state, DDR_P1_MENU_UP, XUSB_GAMEPAD_DPAD_UP); + check_assign_key(pad_state, BT_IO_DDR_P1_START, XUSB_GAMEPAD_START); state[0].wButtons |= check_assign_key( - pad_state, DDR_P1_MENU_DOWN, XUSB_GAMEPAD_DPAD_DOWN); + pad_state, BT_IO_DDR_P1_MENU_UP, XUSB_GAMEPAD_DPAD_UP); state[0].wButtons |= check_assign_key( - pad_state, DDR_P1_MENU_LEFT, XUSB_GAMEPAD_DPAD_LEFT); + pad_state, BT_IO_DDR_P1_MENU_DOWN, XUSB_GAMEPAD_DPAD_DOWN); state[0].wButtons |= check_assign_key( - pad_state, DDR_P1_MENU_RIGHT, XUSB_GAMEPAD_DPAD_RIGHT); + pad_state, BT_IO_DDR_P1_MENU_LEFT, XUSB_GAMEPAD_DPAD_LEFT); + state[0].wButtons |= check_assign_key( + pad_state, BT_IO_DDR_P1_MENU_RIGHT, XUSB_GAMEPAD_DPAD_RIGHT); state[1].wButtons |= - check_assign_key(pad_state, DDR_P2_UP, XUSB_GAMEPAD_Y); + check_assign_key(pad_state, BT_IO_DDR_P2_UP, XUSB_GAMEPAD_Y); state[1].wButtons |= - check_assign_key(pad_state, DDR_P2_DOWN, XUSB_GAMEPAD_A); + check_assign_key(pad_state, BT_IO_DDR_P2_DOWN, XUSB_GAMEPAD_A); state[1].wButtons |= - check_assign_key(pad_state, DDR_P2_LEFT, XUSB_GAMEPAD_X); + check_assign_key(pad_state, BT_IO_DDR_P2_LEFT, XUSB_GAMEPAD_X); state[1].wButtons |= - check_assign_key(pad_state, DDR_P2_RIGHT, XUSB_GAMEPAD_B); + check_assign_key(pad_state, BT_IO_DDR_P2_RIGHT, XUSB_GAMEPAD_B); state[1].wButtons |= - check_assign_key(pad_state, DDR_P2_START, XUSB_GAMEPAD_START); - state[1].wButtons |= - check_assign_key(pad_state, DDR_P2_MENU_UP, XUSB_GAMEPAD_DPAD_UP); + check_assign_key(pad_state, BT_IO_DDR_P2_START, XUSB_GAMEPAD_START); state[1].wButtons |= check_assign_key( - pad_state, DDR_P2_MENU_DOWN, XUSB_GAMEPAD_DPAD_DOWN); + pad_state, BT_IO_DDR_P2_MENU_UP, XUSB_GAMEPAD_DPAD_UP); state[1].wButtons |= check_assign_key( - pad_state, DDR_P2_MENU_LEFT, XUSB_GAMEPAD_DPAD_LEFT); + pad_state, BT_IO_DDR_P2_MENU_DOWN, XUSB_GAMEPAD_DPAD_DOWN); state[1].wButtons |= check_assign_key( - pad_state, DDR_P2_MENU_RIGHT, XUSB_GAMEPAD_DPAD_RIGHT); + pad_state, BT_IO_DDR_P2_MENU_LEFT, XUSB_GAMEPAD_DPAD_LEFT); + state[1].wButtons |= check_assign_key( + pad_state, BT_IO_DDR_P2_MENU_RIGHT, XUSB_GAMEPAD_DPAD_RIGHT); for (uint8_t i = 0; i < NUM_PADS; i++) { vigem_target_x360_update(client, pad[i], state[i]); @@ -223,8 +286,8 @@ int main(int argc, char **argv) set_reactive_lights(pad_state); } - if (check_key(pad_state, DDR_TEST) && - check_key(pad_state, DDR_SERVICE)) { + if (check_key(pad_state, BT_IO_DDR_TEST) && + check_key(pad_state, BT_IO_DDR_SERVICE)) { loop = false; } @@ -238,7 +301,10 @@ int main(int argc, char **argv) } vigem_free(client); - ddr_io_fini(); + + bt_io_ddr_fini(); + bt_io_ddr_api_clear(); + module_io_free(&_module_io_ddr); return 0; } diff --git a/src/main/vigem-iidxio/Module.mk b/src/main/vigem-iidxio/Module.mk index 887a70f0..d2419cac 100644 --- a/src/main/vigem-iidxio/Module.mk +++ b/src/main/vigem-iidxio/Module.mk @@ -8,15 +8,21 @@ cppflags_vigem-iidxio := \ ldflags_vigem-iidxio := \ -lsetupapi \ + -lws2_32 \ libs_vigem-iidxio := \ - cconfig \ - iidxio \ - util \ + core \ vigemstub \ + module \ + ezusb \ + iface \ + iface-io \ + iface-core \ + security \ + util \ src_vigem-iidxio := \ cab-16seg-sequencer.c \ cab-light-sequencer.c \ - main.c \ config.c \ + main.c \ diff --git a/src/main/vigem-iidxio/cab-16seg-sequencer.c b/src/main/vigem-iidxio/cab-16seg-sequencer.c index 01ea12bd..14e2c8fd 100644 --- a/src/main/vigem-iidxio/cab-16seg-sequencer.c +++ b/src/main/vigem-iidxio/cab-16seg-sequencer.c @@ -4,7 +4,8 @@ #include #include -#include "util/log.h" +#include "iface-core/log.h" + #include "util/time.h" static const uint8_t _MAX_LEN_16SEG = 9; diff --git a/src/main/vigem-iidxio/cab-light-sequencer.c b/src/main/vigem-iidxio/cab-light-sequencer.c index 95214f90..99a2fa90 100644 --- a/src/main/vigem-iidxio/cab-light-sequencer.c +++ b/src/main/vigem-iidxio/cab-light-sequencer.c @@ -4,9 +4,10 @@ #include #include +#include "iface-core/log.h" + #include "vigem-iidxio/cab-light-sequencer.h" -#include "util/log.h" #include "util/math.h" #include "util/time.h" diff --git a/src/main/vigem-iidxio/config.c b/src/main/vigem-iidxio/config.c index 40eeae56..6bdf4344 100644 --- a/src/main/vigem-iidxio/config.c +++ b/src/main/vigem-iidxio/config.c @@ -1,243 +1,16 @@ -#include "cconfig/cconfig-main.h" -#include "cconfig/cconfig-util.h" +#include "core/config-ext.h" #include "vigem-iidxio/config.h" -#include "util/log.h" - -#define VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY \ - "vigem.iidxio.tt.anlog.relative" -#define VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY \ - "vigem.iidxio.tt.anlog.relative_sensitivity" -#define VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY \ - "vigem.iidxio.tt.button.debounce" -#define VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY \ - "vigem.iidxio.tt.button.threshold" -#define VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY "vigem.iidxio.tt.debug_output" -#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY \ - "vigem.iidxio.cab_light.enable_keylight" -#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY \ - "vigem.iidxio.cab_light.light_mode" -#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY \ - "vigem.iidxio.cab_light.text_16seg" -#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY \ - "vigem.iidxio.cab_light.text_scroll_cycle_time_ms" - -#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE false -#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE 1024 -#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE 20 -#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE 2 -#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE false -#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE true -#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE 0 -#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE "" -#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE \ - 500 - -static void _vigem_iidxio_config_init(struct cconfig *config) +void vigem_iidxio_config_get(const bt_core_config_t *config, vigem_iidxio_config_t *config_out) { - cconfig_util_set_bool( - config, - VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE, - "Use relative mode analog mapping instead of absolute analog values"); - - cconfig_util_set_int( - config, - VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE, - "Sensitivity value for relative mode (1 to 32767). Tweak if you are " - "having issues with " - "jittering/misfiring/unresponsiveness"); - - cconfig_util_set_int( - config, - VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE, - "Button turntable: \"debounce\" value (1 to 50, recommend 20). Tweak " - "if you are having " - "issues with TT button misfiring/unresponsiveness"); - - cconfig_util_set_int( - config, - VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE, - "Button turntable: minimum ticks required within (debounce * 2) ms to " - "register movement " - "(1 to 4, recommend 2). Tweak if you button input is too (un-) " - "responsive"); - - cconfig_util_set_bool( - config, - VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE, - "Print verbose debug output to the console for debugging turntable " - "sensitivity issues"); - - cconfig_util_set_bool( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE, - "Enable input based key lighting"); - - cconfig_util_set_int( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE, - "Different cabinet light modes: 0 = off, 1 = neons sequence, 2 = neons " - "flash on TT spin"); - - cconfig_util_set_str( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE, - "Display text on 16seg. If text exceeds 9 char display limit, it will " - "scroll + cycle"); - - cconfig_util_set_int( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE, - "Cycle time/scroll speed for text exceeding 16seg display length (9) " - "to scroll from right"); -} - -static void _vigem_iidxio_config_get( - struct vigem_iidxio_config *vigem_config, struct cconfig *config) -{ - if (!cconfig_util_get_bool( - config, - VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY, - &vigem_config->tt.analog.relative, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY, - &vigem_config->tt.analog.relative_sensitivity, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY, - &vigem_config->tt.button.debounce, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY, - &vigem_config->tt.button.threshold, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE); - } - - if (!cconfig_util_get_bool( - config, - VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY, - &vigem_config->tt.debug_output, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE); - } - - if (!cconfig_util_get_bool( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY, - &vigem_config->cab_light.enable_keylight, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY, - &vigem_config->cab_light.light_mode, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE); - } - - if (!cconfig_util_get_str( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY, - vigem_config->cab_light.text_16seg, - sizeof(vigem_config->cab_light.text_16seg), - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY, - &vigem_config->cab_light.text_scroll_cycle_time_ms, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY, - VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE); - } -} - -bool vigem_iidxio_config_get(struct vigem_iidxio_config *config_out) -{ - struct cconfig *config; - - config = cconfig_init(); - - _vigem_iidxio_config_init(config); - - if (!cconfig_main_config_init( - config, - "--config", - "vigem-iidxio.conf", - "--help", - "-h", - "vigem-iidxio", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - return false; - } - - _vigem_iidxio_config_get(config_out, config); - - cconfig_finit(config); - - return true; -} + bt_core_config_ext_bool_get(config, "tt/anlog/relative", &config_out->tt.analog.relative); + bt_core_config_ext_s32_get(config, "tt/anlog/relative_sensitivity", &config_out->tt.analog.relative_sensitivity); + bt_core_config_ext_s32_get(config, "tt/button/debounce", &config_out->tt.button.debounce); + bt_core_config_ext_s32_get(config, "tt/button/threshold", &config_out->tt.button.threshold); + bt_core_config_ext_bool_get(config, "tt/debug_output", &config_out->tt.debug_output); + bt_core_config_ext_bool_get(config, "cab_light/enable_keylight", &config_out->cab_light.enable_keylight); + bt_core_config_ext_s32_get(config, "cab_light/light_mode", &config_out->cab_light.light_mode); + bt_core_config_ext_str_get(config, "cab_light/text_16seg", config_out->cab_light.text_16seg, sizeof(config_out->cab_light.text_16seg)); + bt_core_config_ext_s32_get(config, "cab_light/text_scroll_cycle_time_ms", &config_out->cab_light.text_scroll_cycle_time_ms); +} \ No newline at end of file diff --git a/src/main/vigem-iidxio/config.h b/src/main/vigem-iidxio/config.h index f4f0446b..db454215 100644 --- a/src/main/vigem-iidxio/config.h +++ b/src/main/vigem-iidxio/config.h @@ -1,11 +1,12 @@ #ifndef VIGEM_IIDXIO_CONFIG_H #define VIGEM_IIDXIO_CONFIG_H -#include +#include +#include -#include "cconfig/cconfig.h" +#include "api/core/config.h" -struct vigem_iidxio_config { +typedef struct vigem_iidxio_config { struct tt { struct analog { bool relative; @@ -26,8 +27,8 @@ struct vigem_iidxio_config { char text_16seg[1024 + 1]; int32_t text_scroll_cycle_time_ms; } cab_light; -}; +} vigem_iidxio_config_t; -bool vigem_iidxio_config_get(struct vigem_iidxio_config *config_out); +void vigem_iidxio_config_get(const bt_core_config_t *config, vigem_iidxio_config_t *config_out); #endif \ No newline at end of file diff --git a/src/main/vigem-iidxio/main.c b/src/main/vigem-iidxio/main.c index 3527545a..179e89bf 100644 --- a/src/main/vigem-iidxio/main.c +++ b/src/main/vigem-iidxio/main.c @@ -7,11 +7,21 @@ #include -#include "bemanitools/iidxio.h" +#include "core/config-property-node.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" +#include "core/thread-crt.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/iidx.h" + +#include "module/io-ext.h" +#include "module/io.h" -#include "util/log.h" #include "util/math.h" -#include "util/thread.h" #include "util/time.h" #include "vigem-iidxio/cab-16seg-sequencer.h" @@ -23,6 +33,8 @@ #define JOYSTICKS_NUM 3 #define TURNTABLE_NUM 2 +static module_io_t *_module_io_iidx; + static uint8_t _tt_last_raw[TURNTABLE_NUM]; static int32_t _tt_state_for_analog[TURNTABLE_NUM]; static int16_t _tt_state_for_btn[TURNTABLE_NUM]; @@ -195,82 +207,115 @@ static void _handle_turntable( static void _handle_buttons_14keys(uint16_t keys, XUSB_REPORT *state) { state[0].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P1_1, XUSB_GAMEPAD_A); + _check_assign_key(keys, BT_IO_IIDX_KEY_P1_1, XUSB_GAMEPAD_A); state[0].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P1_2, XUSB_GAMEPAD_B); + _check_assign_key(keys, BT_IO_IIDX_KEY_P1_2, XUSB_GAMEPAD_B); state[0].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P1_3, XUSB_GAMEPAD_X); + _check_assign_key(keys, BT_IO_IIDX_KEY_P1_3, XUSB_GAMEPAD_X); state[0].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P1_4, XUSB_GAMEPAD_Y); - state[0].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P1_5, XUSB_GAMEPAD_LEFT_SHOULDER); - state[0].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P1_6, XUSB_GAMEPAD_RIGHT_SHOULDER); + _check_assign_key(keys, BT_IO_IIDX_KEY_P1_4, XUSB_GAMEPAD_Y); + state[0].wButtons |= _check_assign_key( + keys, BT_IO_IIDX_KEY_P1_5, XUSB_GAMEPAD_LEFT_SHOULDER); + state[0].wButtons |= _check_assign_key( + keys, BT_IO_IIDX_KEY_P1_6, XUSB_GAMEPAD_RIGHT_SHOULDER); state[0].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P1_7, XUSB_GAMEPAD_BACK); + _check_assign_key(keys, BT_IO_IIDX_KEY_P1_7, XUSB_GAMEPAD_BACK); state[1].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P2_1, XUSB_GAMEPAD_A); + _check_assign_key(keys, BT_IO_IIDX_KEY_P2_1, XUSB_GAMEPAD_A); state[1].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P2_2, XUSB_GAMEPAD_B); + _check_assign_key(keys, BT_IO_IIDX_KEY_P2_2, XUSB_GAMEPAD_B); state[1].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P2_3, XUSB_GAMEPAD_X); + _check_assign_key(keys, BT_IO_IIDX_KEY_P2_3, XUSB_GAMEPAD_X); state[1].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P2_4, XUSB_GAMEPAD_Y); - state[1].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P2_5, XUSB_GAMEPAD_LEFT_SHOULDER); - state[1].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P2_6, XUSB_GAMEPAD_RIGHT_SHOULDER); + _check_assign_key(keys, BT_IO_IIDX_KEY_P2_4, XUSB_GAMEPAD_Y); + state[1].wButtons |= _check_assign_key( + keys, BT_IO_IIDX_KEY_P2_5, XUSB_GAMEPAD_LEFT_SHOULDER); + state[1].wButtons |= _check_assign_key( + keys, BT_IO_IIDX_KEY_P2_6, XUSB_GAMEPAD_RIGHT_SHOULDER); state[1].wButtons |= - _check_assign_key(keys, IIDX_IO_KEY_P2_7, XUSB_GAMEPAD_BACK); + _check_assign_key(keys, BT_IO_IIDX_KEY_P2_7, XUSB_GAMEPAD_BACK); } static void _handle_buttons_panel(uint8_t panel, XUSB_REPORT *state) { state[0].wButtons |= _check_assign_key( - panel, IIDX_IO_PANEL_LIGHT_P1_START, XUSB_GAMEPAD_START); + panel, BT_IO_IIDX_PANEL_LIGHT_P1_START, XUSB_GAMEPAD_START); state[1].wButtons |= _check_assign_key( - panel, IIDX_IO_PANEL_LIGHT_P2_START, XUSB_GAMEPAD_START); + panel, BT_IO_IIDX_PANEL_LIGHT_P2_START, XUSB_GAMEPAD_START); state[2].wButtons |= - _check_assign_key(panel, IIDX_IO_PANEL_LIGHT_VEFX, XUSB_GAMEPAD_B); + _check_assign_key(panel, BT_IO_IIDX_PANEL_LIGHT_VEFX, XUSB_GAMEPAD_B); state[2].wButtons |= - _check_assign_key(panel, IIDX_IO_PANEL_LIGHT_EFFECT, XUSB_GAMEPAD_A); + _check_assign_key(panel, BT_IO_IIDX_PANEL_LIGHT_EFFECT, XUSB_GAMEPAD_A); } static void _handle_buttons_system(uint8_t system, XUSB_REPORT *state) { state[2].wButtons |= - _check_assign_key(system, IIDX_IO_SYS_TEST, XUSB_GAMEPAD_X); + _check_assign_key(system, BT_IO_IIDX_SYS_TEST, XUSB_GAMEPAD_X); state[2].wButtons |= - _check_assign_key(system, IIDX_IO_SYS_SERVICE, XUSB_GAMEPAD_Y); + _check_assign_key(system, BT_IO_IIDX_SYS_SERVICE, XUSB_GAMEPAD_Y); state[2].wButtons |= - _check_assign_key(system, IIDX_IO_SYS_COIN, XUSB_GAMEPAD_START); + _check_assign_key(system, BT_IO_IIDX_SYS_COIN, XUSB_GAMEPAD_START); } static void _all_lights_off() { - iidx_io_ep1_set_deck_lights(0); - iidx_io_ep1_set_panel_lights(0); - iidx_io_ep1_set_top_lamps(0); - iidx_io_ep1_set_top_neons(false); - iidx_io_ep3_write_16seg(" "); + bt_io_iidx_ep1_deck_lights_set(0); + bt_io_iidx_ep1_panel_lights_set(0); + bt_io_iidx_ep1_top_lamps_set(0); + bt_io_iidx_ep1_top_neons_set(false); + bt_io_iidx_ep3_16seg_send(" "); +} + +static void _io_iidx_init(module_io_t **module) +{ + bt_io_iidx_api_t api; + + module_io_ext_load_and_init( + "iidxio.dll", "bt_module_io_iidx_api_get", module); + module_io_api_get(*module, &api); + bt_io_iidx_api_set(&api); +} + +static void _config_load(vigem_iidxio_config_t *config_out) +{ + core_property_t *property; + core_property_result_t property_result; + core_property_node_t node; + core_property_node_result_t node_result; + bt_core_config_t *config; + + property_result = core_property_file_load("vigem-iidxio.xml", &property); + core_property_fatal_on_error(property_result); + + node_result = core_property_root_node_get(property, &node); + core_property_node_fatal_on_error(node_result); + + core_config_property_node_init(&node, &config); + + vigem_iidxio_config_get(config, config_out); + + core_config_property_node_free(&config); + core_property_free(&property); } int main(int argc, char **argv) { - log_to_writer(log_writer_stdout, NULL); + vigem_iidxio_config_t config; - struct vigem_iidxio_config config; + core_log_bt_core_api_set(); + core_thread_crt_core_api_set(); + core_config_property_node_core_api_set(); - if (!vigem_iidxio_config_get(&config)) { - return -1; - } + core_log_bt_ext_init_with_stdout(); - iidx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _config_load(&config); - if (!iidx_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) { + _io_iidx_init(&_module_io_iidx); + + if (!bt_io_iidx_init()) { log_warning("Initializing iidxio failed"); return -1; } @@ -280,7 +325,10 @@ int main(int argc, char **argv) if (!client) { log_warning("VIGEM client failed to connect"); - iidx_io_fini(); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&_module_io_iidx); return -1; } @@ -300,7 +348,11 @@ int main(int argc, char **argv) } if (failed) { - iidx_io_fini(); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&_module_io_iidx); + return -1; } @@ -326,16 +378,16 @@ int main(int argc, char **argv) memset(&state[i], 0, sizeof(state[i])); } - if (!iidx_io_ep2_recv()) { + if (!bt_io_iidx_ep2_recv()) { log_warning("iidxio receiving failed"); break; } // Keys/buttons - uint16_t keys = iidx_io_ep2_get_keys(); - uint8_t panel = iidx_io_ep2_get_panel(); - uint8_t system = iidx_io_ep2_get_sys(); + uint16_t keys = bt_io_iidx_ep2_keys_get(); + uint8_t panel = bt_io_iidx_ep2_panel_get(); + uint8_t system = bt_io_iidx_ep2_sys_get(); _handle_buttons_14keys(keys, state); _handle_buttons_panel(panel, state); @@ -346,7 +398,7 @@ int main(int argc, char **argv) uint8_t turntable[TURNTABLE_NUM]; for (uint8_t i = 0; i < TURNTABLE_NUM; i++) { - turntable[i] = iidx_io_ep2_get_turntable(i); + turntable[i] = bt_io_iidx_ep2_turntable_get(i); } _handle_turntable(&config, turntable, state); @@ -362,8 +414,8 @@ int main(int argc, char **argv) // Light related outputs if (config.cab_light.enable_keylight) { - iidx_io_ep1_set_deck_lights(keys); - iidx_io_ep1_set_panel_lights(panel); + bt_io_iidx_ep1_deck_lights_set(keys); + bt_io_iidx_ep1_panel_lights_set(panel); } if (config.cab_light.light_mode != LIGHT_SEQ_MODE_OFF) { @@ -376,24 +428,24 @@ int main(int argc, char **argv) vigem_iidxio_cab_light_sequencer_update( keys, turntable[0], turntable[1], &neon, &spots); - iidx_io_ep1_set_top_neons(neon); - iidx_io_ep1_set_top_lamps(spots); + bt_io_iidx_ep1_top_neons_set(neon); + bt_io_iidx_ep1_top_lamps_set(spots); } if (config.cab_light.text_16seg[0] != '\0') { char buffer_16seg[9]; vigem_iidxio_cab_16seg_sequencer_update(buffer_16seg); - iidx_io_ep3_write_16seg(buffer_16seg); + bt_io_iidx_ep3_16seg_send(buffer_16seg); } - if (!iidx_io_ep1_send()) { + if (!bt_io_iidx_ep1_send()) { log_warning("iidxio sending failed"); break; } - if (_check_key(system, IIDX_IO_SYS_TEST) && - _check_key(system, IIDX_IO_SYS_SERVICE)) { + if (_check_key(system, BT_IO_IIDX_SYS_TEST) && + _check_key(system, BT_IO_IIDX_SYS_SERVICE)) { log_info("Test + service pressed, exiting..."); loop = false; } @@ -413,7 +465,10 @@ int main(int argc, char **argv) _all_lights_off(); - iidx_io_fini(); + bt_io_iidx_fini(); + + bt_io_iidx_api_clear(); + module_io_free(&_module_io_iidx); return 0; } diff --git a/src/main/vigem-sdvxio/Module.mk b/src/main/vigem-sdvxio/Module.mk index 6907fbf8..d06fc681 100644 --- a/src/main/vigem-sdvxio/Module.mk +++ b/src/main/vigem-sdvxio/Module.mk @@ -8,13 +8,18 @@ cppflags_vigem-sdvxio := \ ldflags_vigem-sdvxio := \ -lsetupapi \ + -lws2_32 \ libs_vigem-sdvxio := \ - cconfig \ - sdvxio \ - util \ + core \ vigemstub \ + module \ + iface \ + iface-io \ + iface-core \ + security \ + util \ src_vigem-sdvxio := \ + config.c \ main.c \ - config-vigem-sdvxio.c \ diff --git a/src/main/vigem-sdvxio/config-vigem-sdvxio.c b/src/main/vigem-sdvxio/config-vigem-sdvxio.c deleted file mode 100644 index 768a514c..00000000 --- a/src/main/vigem-sdvxio/config-vigem-sdvxio.c +++ /dev/null @@ -1,149 +0,0 @@ -#include "cconfig/cconfig-main.h" -#include "cconfig/cconfig-util.h" - -#include "vigem-sdvxio/config-vigem-sdvxio.h" - -#include "util/log.h" - -#define VIGEM_SDVXIO_CONFIG_ENABLE_KEYLIGHT_KEY "sdvxio.enable_keylight" -#define VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY "sdvxio.use_relative_analog" -#define VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY "sdvxio.pwm_wings" -#define VIGEM_SDVXIO_CONFIG_PWM_CONTROLLER_KEY "sdvxio.pwm_controller" -#define VIGEM_SDVXIO_CONFIG_AMP_VOLUME_KEY "sdvxio.amp_volume" - -#define VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE true -#define VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE false -#define VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_WINGS_VALUE 128 -#define VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_CONTROLLER_VALUE 64 -#define VIGEM_SDVXIO_CONFIG_DEFAULT_AMP_VOLUME_VALUE 48 - -static void vigem_sdvxio_config_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - VIGEM_SDVXIO_CONFIG_ENABLE_KEYLIGHT_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE, - "Enable input based key lighting"); - - cconfig_util_set_bool( - config, - VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE, - "Use relative mode analog mapping"); - - cconfig_util_set_int( - config, - VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_WINGS_VALUE, - "Brightness to set wings to (0-255)"); - - cconfig_util_set_int( - config, - VIGEM_SDVXIO_CONFIG_PWM_CONTROLLER_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_CONTROLLER_VALUE, - "Brightness to set control deck to (0-255)"); - - cconfig_util_set_int( - config, - VIGEM_SDVXIO_CONFIG_AMP_VOLUME_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_AMP_VOLUME_VALUE, - "SDVXIO digital amp volume (0-96) 0 is high, 96 is low."); -} - -static void vigem_sdvxio_config_get( - struct vigem_sdvxio_config *vigem_config, struct cconfig *config) -{ - if (!cconfig_util_get_bool( - config, - VIGEM_SDVXIO_CONFIG_ENABLE_KEYLIGHT_KEY, - &vigem_config->enable_keylight, - VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_SDVXIO_CONFIG_ENABLE_KEYLIGHT_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE); - } - - if (!cconfig_util_get_bool( - config, - VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY, - &vigem_config->relative_analog, - VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY, - &vigem_config->pwm_wings, - VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_WINGS_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_WINGS_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_SDVXIO_CONFIG_PWM_CONTROLLER_KEY, - &vigem_config->pwm_controller, - VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_CONTROLLER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_SDVXIO_CONFIG_PWM_CONTROLLER_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_CONTROLLER_VALUE); - } - - if (!cconfig_util_get_int( - config, - VIGEM_SDVXIO_CONFIG_AMP_VOLUME_KEY, - &vigem_config->amp_volume, - VIGEM_SDVXIO_CONFIG_DEFAULT_AMP_VOLUME_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - VIGEM_SDVXIO_CONFIG_AMP_VOLUME_KEY, - VIGEM_SDVXIO_CONFIG_DEFAULT_AMP_VOLUME_VALUE); - } -} - -bool get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out) -{ - struct cconfig *config; - - config = cconfig_init(); - - vigem_sdvxio_config_init(config); - - if (!cconfig_main_config_init( - config, - "--config", - "vigem-sdvxio.conf", - "--help", - "-h", - "vigem-sdvxio", - CCONFIG_CMD_USAGE_OUT_STDOUT)) { - cconfig_finit(config); - return false; - } - - vigem_sdvxio_config_get(config_out, config); - - cconfig_finit(config); - - if (config_out->pwm_controller > 255) { - config_out->pwm_controller = 255; - } - - if (config_out->pwm_wings > 255) { - config_out->pwm_wings = 255; - } - return true; -} diff --git a/src/main/vigem-sdvxio/config-vigem-sdvxio.h b/src/main/vigem-sdvxio/config-vigem-sdvxio.h deleted file mode 100644 index b689735b..00000000 --- a/src/main/vigem-sdvxio/config-vigem-sdvxio.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef VIGEM_SDVXIO_CONFIG_H -#define VIGEM_SDVXIO_CONFIG_H - -#include - -#include "cconfig/cconfig.h" - -struct vigem_sdvxio_config { - bool enable_keylight; - bool relative_analog; - int32_t pwm_wings; - int32_t pwm_controller; - int32_t amp_volume; -}; - -bool get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out); - -#endif \ No newline at end of file diff --git a/src/main/vigem-sdvxio/config.c b/src/main/vigem-sdvxio/config.c new file mode 100644 index 00000000..6b59f621 --- /dev/null +++ b/src/main/vigem-sdvxio/config.c @@ -0,0 +1,14 @@ +#include "core/config-ext.h" + +#include "vigem-sdvxio/config.h" + +void vigem_sdvxio_config_get( + const bt_core_config_t *config, + vigem_sdvxio_config_t *config_out) +{ + bt_core_config_ext_bool_get(config, "enable_keylight", &config_out->enable_keylight); + bt_core_config_ext_bool_get(config, "use_relative_analog", &config_out->relative_analog); + bt_core_config_ext_s32_get(config, "pwm_wings", &config_out->pwm_wings); + bt_core_config_ext_s32_get(config, "pwm_controller", &config_out->pwm_controller); + bt_core_config_ext_s32_get(config, "amp_volume", &config_out->amp_volume); +} \ No newline at end of file diff --git a/src/main/vigem-sdvxio/config.h b/src/main/vigem-sdvxio/config.h new file mode 100644 index 00000000..eebe5b8b --- /dev/null +++ b/src/main/vigem-sdvxio/config.h @@ -0,0 +1,21 @@ +#ifndef VIGEM_SDVXIO_CONFIG_H +#define VIGEM_SDVXIO_CONFIG_H + +#include +#include + +#include "api/core/config.h" + +typedef struct vigem_sdvxio_config { + bool enable_keylight; + bool relative_analog; + int32_t pwm_wings; + int32_t pwm_controller; + int32_t amp_volume; +} vigem_sdvxio_config_t; + +void vigem_sdvxio_config_get( + const bt_core_config_t *config, + vigem_sdvxio_config_t *config_out); + +#endif \ No newline at end of file diff --git a/src/main/vigem-sdvxio/main.c b/src/main/vigem-sdvxio/main.c index cf4b4e22..2c92461e 100644 --- a/src/main/vigem-sdvxio/main.c +++ b/src/main/vigem-sdvxio/main.c @@ -1,22 +1,36 @@ +#include + #include #include #include #include -#include - #include "ViGEm/Client.h" -#include "bemanitools/sdvxio.h" -#include "util/log.h" +#include "core/config-property-node.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" +#include "core/thread-crt.h" + +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/sdvx.h" + +#include "module/io-ext.h" +#include "module/io.h" + #include "util/math.h" -#include "util/thread.h" + #include "vigemstub/helper.h" -#include "vigem-sdvxio/config-vigem-sdvxio.h" +#include "vigem-sdvxio/config.h" #define ANALOG_FIXED_SENSITIVITY 1024 +static module_io_t *_module_io_sdvx; + int16_t convert_analog_to_s16(uint16_t val) { // val is 10 bit @@ -98,59 +112,99 @@ void gpio_keylight(uint16_t gpio0, uint16_t gpio1) uint16_t gpio_lights = 0; gpio_lights |= check_assign_gpio( - gpio0, SDVX_IO_IN_GPIO_0_START, SDVX_IO_OUT_GPIO_START); + gpio0, BT_IO_SDVX_IN_GPIO_0_START, BT_IO_SDVX_OUT_GPIO_START); gpio_lights |= - check_assign_gpio(gpio0, SDVX_IO_IN_GPIO_0_A, SDVX_IO_OUT_GPIO_A); + check_assign_gpio(gpio0, BT_IO_SDVX_IN_GPIO_0_A, BT_IO_SDVX_OUT_GPIO_A); gpio_lights |= - check_assign_gpio(gpio0, SDVX_IO_IN_GPIO_0_B, SDVX_IO_OUT_GPIO_B); + check_assign_gpio(gpio0, BT_IO_SDVX_IN_GPIO_0_B, BT_IO_SDVX_OUT_GPIO_B); gpio_lights |= - check_assign_gpio(gpio0, SDVX_IO_IN_GPIO_0_C, SDVX_IO_OUT_GPIO_C); + check_assign_gpio(gpio0, BT_IO_SDVX_IN_GPIO_0_C, BT_IO_SDVX_OUT_GPIO_C); gpio_lights |= - check_assign_gpio(gpio1, SDVX_IO_IN_GPIO_1_D, SDVX_IO_OUT_GPIO_D); - gpio_lights |= - check_assign_gpio(gpio1, SDVX_IO_IN_GPIO_1_FX_L, SDVX_IO_OUT_GPIO_FX_L); - gpio_lights |= - check_assign_gpio(gpio1, SDVX_IO_IN_GPIO_1_FX_R, SDVX_IO_OUT_GPIO_FX_R); + check_assign_gpio(gpio1, BT_IO_SDVX_IN_GPIO_1_D, BT_IO_SDVX_OUT_GPIO_D); + gpio_lights |= check_assign_gpio( + gpio1, BT_IO_SDVX_IN_GPIO_1_FX_L, BT_IO_SDVX_OUT_GPIO_FX_L); + gpio_lights |= check_assign_gpio( + gpio1, BT_IO_SDVX_IN_GPIO_1_FX_R, BT_IO_SDVX_OUT_GPIO_FX_R); - sdvx_io_set_gpio_lights(gpio_lights); + bt_io_sdvx_gpio_lights_set(gpio_lights); } void set_pwm_brightness(uint8_t wing_pwm, uint8_t controller_pwm) { // 0-11 are the 4 wings for (size_t i = 0; i < 12; ++i) { - sdvx_io_set_pwm_light(i, wing_pwm); + bt_io_sdvx_pwm_light_set(i, wing_pwm); } // 12-17 are the woofer / control deck for (size_t i = 12; i < 18; ++i) { - sdvx_io_set_pwm_light(i, controller_pwm); + bt_io_sdvx_pwm_light_set(i, controller_pwm); } } +static void _io_sdvx_init(module_io_t **module) +{ + bt_io_sdvx_api_t api; + + module_io_ext_load_and_init( + "sdvxio.dll", "bt_module_io_sdvx_api_get", module); + module_io_api_get(*module, &api); + bt_io_sdvx_api_set(&api); +} + +static void _config_load(vigem_sdvxio_config_t *config_out) +{ + core_property_t *property; + core_property_result_t property_result; + core_property_node_t node; + core_property_node_result_t node_result; + bt_core_config_t *config; + + property_result = core_property_file_load("vigem-sdvxio.xml", &property); + core_property_fatal_on_error(property_result); + + node_result = core_property_root_node_get(property, &node); + core_property_node_fatal_on_error(node_result); + + core_config_property_node_init(&node, &config); + + vigem_sdvxio_config_get(config, config_out); + + core_config_property_node_free(&config); + core_property_free(&property); +} + int main(int argc, char **argv) { - log_to_writer(log_writer_stdout, NULL); + vigem_sdvxio_config_t config; - struct vigem_sdvxio_config config; - if (!get_vigem_sdvxio_config(&config)) { - exit(EXIT_FAILURE); - } + core_log_bt_core_api_set(); + core_thread_crt_core_api_set(); + core_config_property_node_core_api_set(); + + core_log_bt_ext_init_with_stdout(); + + _config_load(&config); - sdvx_io_set_loggers( - log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + _io_sdvx_init(&_module_io_sdvx); - if (!sdvx_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) { + if (!bt_io_sdvx_init()) { log_warning("Initializing sdvxio failed"); return -1; } - sdvx_io_set_amp_volume( + bt_io_sdvx_amp_volume_set( config.amp_volume, config.amp_volume, config.amp_volume); PVIGEM_CLIENT client = vigem_helper_setup(); if (!client) { log_warning("client failed to connect failed"); + + bt_io_sdvx_fini(); + + bt_io_sdvx_api_clear(); + module_io_free(&_module_io_sdvx); + return -1; } @@ -158,6 +212,12 @@ int main(int argc, char **argv) if (!pad) { log_warning("vigem_alloc pad 1 failed"); + + bt_io_sdvx_fini(); + + bt_io_sdvx_api_clear(); + module_io_free(&_module_io_sdvx); + return -1; } @@ -176,14 +236,14 @@ int main(int argc, char **argv) log_info("vigem init succeeded, beginning poll loop"); while (loop) { - sdvx_io_read_input(); + bt_io_sdvx_input_read(); - sys = sdvx_io_get_input_gpio_sys(); - gpio0 = sdvx_io_get_input_gpio(0); - gpio1 = sdvx_io_get_input_gpio(1); + sys = bt_io_sdvx_input_gpio_sys_get(); + gpio0 = bt_io_sdvx_input_gpio_get(0); + gpio1 = bt_io_sdvx_input_gpio_get(1); - vol[0] = sdvx_io_get_spinner_pos(0); - vol[1] = sdvx_io_get_spinner_pos(1); + vol[0] = bt_io_sdvx_spinner_pos_get(0); + vol[1] = bt_io_sdvx_spinner_pos_get(1); memset(&state, 0, sizeof(state)); @@ -206,21 +266,21 @@ int main(int argc, char **argv) } state.wButtons |= check_assign_key( - gpio0, SDVX_IO_IN_GPIO_0_START, XUSB_GAMEPAD_START); - state.wButtons |= - check_assign_key(sys, SDVX_IO_IN_GPIO_SYS_TEST, XUSB_GAMEPAD_BACK); + gpio0, BT_IO_SDVX_IN_GPIO_0_START, XUSB_GAMEPAD_START); + state.wButtons |= check_assign_key( + sys, BT_IO_SDVX_IN_GPIO_SYS_TEST, XUSB_GAMEPAD_BACK); state.wButtons |= - check_assign_key(gpio0, SDVX_IO_IN_GPIO_0_A, XUSB_GAMEPAD_A); + check_assign_key(gpio0, BT_IO_SDVX_IN_GPIO_0_A, XUSB_GAMEPAD_A); state.wButtons |= - check_assign_key(gpio0, SDVX_IO_IN_GPIO_0_B, XUSB_GAMEPAD_B); + check_assign_key(gpio0, BT_IO_SDVX_IN_GPIO_0_B, XUSB_GAMEPAD_B); state.wButtons |= - check_assign_key(gpio0, SDVX_IO_IN_GPIO_0_C, XUSB_GAMEPAD_X); + check_assign_key(gpio0, BT_IO_SDVX_IN_GPIO_0_C, XUSB_GAMEPAD_X); state.wButtons |= - check_assign_key(gpio1, SDVX_IO_IN_GPIO_1_D, XUSB_GAMEPAD_Y); + check_assign_key(gpio1, BT_IO_SDVX_IN_GPIO_1_D, XUSB_GAMEPAD_Y); state.wButtons |= check_assign_key( - gpio1, SDVX_IO_IN_GPIO_1_FX_L, XUSB_GAMEPAD_LEFT_SHOULDER); + gpio1, BT_IO_SDVX_IN_GPIO_1_FX_L, XUSB_GAMEPAD_LEFT_SHOULDER); state.wButtons |= check_assign_key( - gpio1, SDVX_IO_IN_GPIO_1_FX_R, XUSB_GAMEPAD_RIGHT_SHOULDER); + gpio1, BT_IO_SDVX_IN_GPIO_1_FX_R, XUSB_GAMEPAD_RIGHT_SHOULDER); vigem_target_x360_update(client, pad, state); @@ -229,10 +289,10 @@ int main(int argc, char **argv) } set_pwm_brightness(config.pwm_wings, config.pwm_controller); - sdvx_io_write_output(); + bt_io_sdvx_output_write(); - if (check_key(sys, SDVX_IO_IN_GPIO_SYS_TEST) && - check_key(sys, SDVX_IO_IN_GPIO_SYS_SERVICE)) { + if (check_key(sys, BT_IO_SDVX_IN_GPIO_SYS_TEST) && + check_key(sys, BT_IO_SDVX_IN_GPIO_SYS_SERVICE)) { loop = false; } @@ -245,10 +305,13 @@ int main(int argc, char **argv) vigem_free(client); - sdvx_io_set_amp_volume(96, 96, 96); + bt_io_sdvx_amp_volume_set(96, 96, 96); Sleep(1000); - sdvx_io_fini(); + bt_io_sdvx_fini(); + + bt_io_sdvx_api_clear(); + module_io_free(&_module_io_sdvx); return 0; } diff --git a/src/main/vigemstub/helper.c b/src/main/vigemstub/helper.c index 4aeb5192..791237f2 100644 --- a/src/main/vigemstub/helper.c +++ b/src/main/vigemstub/helper.c @@ -2,9 +2,10 @@ #include #include +#include "iface-core/log.h" + #include "ViGEm/Client.h" -#include "util/log.h" #include "vigemstub/helper.h" PVIGEM_CLIENT vigem_helper_setup(void) diff --git a/src/sdk/module/acio/mgr.h b/src/sdk/module/acio/mgr.h new file mode 100644 index 00000000..adab65d3 --- /dev/null +++ b/src/sdk/module/acio/mgr.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_ACIO_MGR_H +#define BT_SDK_ACIO_MGR_H + +#include "api/acio/mgr.h" + +void bt_module_acio_mgr_api_get(bt_acio_mgr_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/configure.h b/src/sdk/module/configure.h new file mode 100644 index 00000000..8ff4cf2a --- /dev/null +++ b/src/sdk/module/configure.h @@ -0,0 +1,10 @@ +#ifndef MODULE_CONFIGURE_H +#define MODULE_CONFIGURE_H + +#include + +#include "api/core/config.h" + +bool bt_module_configure_do(const bt_core_config_t *config); + +#endif \ No newline at end of file diff --git a/src/sdk/module/core/config.h b/src/sdk/module/core/config.h new file mode 100644 index 00000000..ac941765 --- /dev/null +++ b/src/sdk/module/core/config.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_CORE_CONFIG_H +#define BT_SDK_MODULE_CORE_CONFIG_H + +#include "api/core/config.h" + +void bt_module_core_config_api_set(const bt_core_config_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/core/log.h b/src/sdk/module/core/log.h new file mode 100644 index 00000000..9224b2ee --- /dev/null +++ b/src/sdk/module/core/log.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_CORE_LOG_H +#define BT_SDK_MODULE_CORE_LOG_H + +#include "api/core/log.h" + +void bt_module_core_log_api_set(const bt_core_log_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/core/thread.h b/src/sdk/module/core/thread.h new file mode 100644 index 00000000..b7192630 --- /dev/null +++ b/src/sdk/module/core/thread.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_CORE_THREAD_H +#define BT_SDK_MODULE_CORE_THREAD_H + +#include "api/core/thread.h" + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/hook.h b/src/sdk/module/hook.h new file mode 100644 index 00000000..56cd5192 --- /dev/null +++ b/src/sdk/module/hook.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_HOOK_H +#define BT_SDK_MODULE_HOOK_H + +#include "api/hook.h" + +void bt_module_hook_api_get(bt_hook_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/input.h b/src/sdk/module/input.h new file mode 100644 index 00000000..96fd14b1 --- /dev/null +++ b/src/sdk/module/input.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_INPUT_H +#define BT_SDK_MODULE_INPUT_H + +#include "api/input.h" + +void bt_module_input_api_set(const bt_input_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/bst.h b/src/sdk/module/io/bst.h new file mode 100644 index 00000000..5592196b --- /dev/null +++ b/src/sdk/module/io/bst.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_BST_H +#define BT_SDK_MODULE_IO_BST_H + +#include "api/io/bst.h" + +void bt_module_io_bst_api_get(bt_io_bst_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/ddr.h b/src/sdk/module/io/ddr.h new file mode 100644 index 00000000..d006df5b --- /dev/null +++ b/src/sdk/module/io/ddr.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_DDR_H +#define BT_SDK_MODULE_IO_DDR_H + +#include "api/io/ddr.h" + +void bt_module_io_ddr_api_get(bt_io_ddr_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/eam.h b/src/sdk/module/io/eam.h new file mode 100644 index 00000000..89ae6ced --- /dev/null +++ b/src/sdk/module/io/eam.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_EAM_H +#define BT_SDK_MODULE_IO_EAM_H + +#include "api/io/eam.h" + +void bt_module_io_eam_api_get(bt_io_eam_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/iidx.h b/src/sdk/module/io/iidx.h new file mode 100644 index 00000000..cb8fb342 --- /dev/null +++ b/src/sdk/module/io/iidx.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_IIDX_H +#define BT_SDK_MODULE_IO_IIDX_H + +#include "api/io/iidx.h" + +void bt_module_io_iidx_api_get(bt_io_iidx_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/jb.h b/src/sdk/module/io/jb.h new file mode 100644 index 00000000..709851b4 --- /dev/null +++ b/src/sdk/module/io/jb.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_JB_H +#define BT_SDK_MODULE_IO_JB_H + +#include "api/io/jb.h" + +void bt_module_io_jb_api_get(bt_io_jb_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/popn.h b/src/sdk/module/io/popn.h new file mode 100644 index 00000000..ac09b0db --- /dev/null +++ b/src/sdk/module/io/popn.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_POPN_H +#define BT_SDK_MODULE_IO_POPN_H + +#include "api/io/popn.h" + +void bt_module_io_popn_api_get(bt_io_popn_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/sdvx.h b/src/sdk/module/io/sdvx.h new file mode 100644 index 00000000..648e6404 --- /dev/null +++ b/src/sdk/module/io/sdvx.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_SDVX_H +#define BT_SDK_MODULE_IO_SDVX_H + +#include "api/io/sdvx.h" + +void bt_module_io_sdvx_api_get(bt_io_sdvx_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/module/io/vefx.h b/src/sdk/module/io/vefx.h new file mode 100644 index 00000000..4e636014 --- /dev/null +++ b/src/sdk/module/io/vefx.h @@ -0,0 +1,8 @@ +#ifndef BT_SDK_MODULE_IO_VEFX_H +#define BT_SDK_MODULE_IO_VEFX_H + +#include "api/io/vefx.h" + +void bt_module_io_vefx_api_get(bt_io_vefx_api_t *api); + +#endif \ No newline at end of file diff --git a/src/sdk/version.h b/src/sdk/version.h new file mode 100644 index 00000000..e69de29b diff --git a/src/test/cconfig/Module.mk b/src/test/cconfig/Module.mk deleted file mode 100644 index a61e8d9b..00000000 --- a/src/test/cconfig/Module.mk +++ /dev/null @@ -1,41 +0,0 @@ -testexes += cconfig-test - -srcdir_cconfig-test := src/test/cconfig - -libs_cconfig-test := \ - cconfig \ - test \ - util \ - -src_cconfig-test := \ - cconfig-test.c \ - -################################################################################ - -testexes += cconfig-util-test - -srcdir_cconfig-util-test := src/test/cconfig - -libs_cconfig-util-test := \ - cconfig \ - test \ - util \ - -src_cconfig-util-test := \ - cconfig-util-test.c \ - -################################################################################ - -testexes += cconfig-cmd-test - -srcdir_cconfig-cmd-test := src/test/cconfig - -libs_cconfig-cmd-test := \ - cconfig \ - test \ - util \ - -src_cconfig-cmd-test := \ - cconfig-cmd-test.c \ - -################################################################################ \ No newline at end of file diff --git a/src/test/cconfig/cconfig-cmd-test.c b/src/test/cconfig/cconfig-cmd-test.c deleted file mode 100644 index 3800fc5a..00000000 --- a/src/test/cconfig/cconfig-cmd-test.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "cconfig/cconfig-util.h" -#include "cconfig/cmd.h" - -#include "test/check.h" -#include "test/test.h" - -static void test_cmd() -{ - struct cconfig *config; - int argc = 6; - char *argv[] = {"-P", "test=aaa", "-C", "asdf", "-P", "test2=123"}; - char str[32]; - int32_t val; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - check_bool_true(cconfig_cmd_parse(config, "-P", argc, argv, true)); - - check_int_eq(config->nentries, 2); - - check_bool_true( - cconfig_util_get_str(config, "test", str, sizeof(str), "1")); - check_str_eq(str, "aaa"); - - check_bool_true(cconfig_util_get_int(config, "test2", &val, 0)); - check_int_eq(val, 123); - - cconfig_finit(config); -} - -static void test_cmd_absent_entries() -{ - struct cconfig *config; - int argc = 6; - char *argv[] = {"-P", "test=aaa", "-C", "asdf", "-P", "test2=123"}; - char str[32]; - int32_t val; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_set2(config, "test", "aaa"); - - check_bool_true(cconfig_cmd_parse(config, "-P", argc, argv, false)); - - check_int_eq(config->nentries, 1); - - check_bool_true( - cconfig_util_get_str(config, "test", str, sizeof(str), "1")); - check_str_eq(str, "aaa"); - - check_bool_false(cconfig_util_get_int(config, "test2", &val, 0)); - check_int_eq(val, 0); - - cconfig_finit(config); -} - -TEST_MODULE_BEGIN("cconfig-cmd") -TEST_MODULE_TEST(test_cmd) -TEST_MODULE_TEST(test_cmd_absent_entries) -TEST_MODULE_END() diff --git a/src/test/cconfig/cconfig-test.c b/src/test/cconfig/cconfig-test.c deleted file mode 100644 index 4feb6d64..00000000 --- a/src/test/cconfig/cconfig-test.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "cconfig/cconfig.h" - -#include "test/check.h" -#include "test/test.h" - -static void test_init() -{ - struct cconfig *config; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_finit(config); -} - -static void test_get_empty() -{ - struct cconfig *config; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - check_null(cconfig_get(config, "test")); - - cconfig_finit(config); -} - -static void test_set_get_one_elem() -{ - struct cconfig *config; - struct cconfig_entry *entry; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_set(config, "test", "123", "desc"); - - check_int_eq(config->nentries, 1); - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].value, "123"); - check_str_eq(config->entries[0].desc, "desc"); - - entry = cconfig_get(config, "test"); - - check_str_eq(entry->key, "test"); - check_str_eq(entry->value, "123"); - check_str_eq(entry->desc, "desc"); - - cconfig_finit(config); -} - -static void test_set_get_one_elem2() -{ - struct cconfig *config; - struct cconfig_entry *entry; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_set2(config, "test", "123"); - - check_int_eq(config->nentries, 1); - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].value, "123"); - check_str_eq(config->entries[0].desc, ""); - - entry = cconfig_get(config, "test"); - - check_str_eq(entry->key, "test"); - check_str_eq(entry->value, "123"); - check_str_eq(entry->desc, ""); - - cconfig_finit(config); -} - -static void test_set_get_same_elem() -{ - struct cconfig *config; - struct cconfig_entry *entry; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_set(config, "test", "123", "desc"); - cconfig_set(config, "test", "12345", "aaa"); - - check_int_eq(config->nentries, 1); - - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].value, "12345"); - check_str_eq(config->entries[0].desc, "aaa"); - - entry = cconfig_get(config, "test"); - - check_str_eq(entry->key, "test"); - check_str_eq(entry->value, "12345"); - check_str_eq(entry->desc, "aaa"); - - cconfig_finit(config); -} - -static void test_set_get_many_elem() -{ - struct cconfig *config; - struct cconfig_entry *entry; - char key[16]; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - for (int i = 0; i < 1000; i++) { - sprintf(key, "%d", i); - cconfig_set(config, key, "123", "desc"); - } - - check_int_eq(config->nentries, 1000); - - for (int i = 0; i < 1000; i++) { - sprintf(key, "%d", i); - check_str_eq(config->entries[i].key, key); - check_str_eq(config->entries[i].value, "123"); - check_str_eq(config->entries[i].desc, "desc"); - } - - for (int i = 0; i < 1000; i++) { - sprintf(key, "%d", i); - entry = cconfig_get(config, key); - - check_str_eq(entry->key, key); - check_str_eq(entry->value, "123"); - check_str_eq(entry->desc, "desc"); - } - - cconfig_finit(config); -} - -TEST_MODULE_BEGIN("cconfig") -TEST_MODULE_TEST(test_init) -TEST_MODULE_TEST(test_get_empty) -TEST_MODULE_TEST(test_set_get_one_elem) -TEST_MODULE_TEST(test_set_get_one_elem2) -TEST_MODULE_TEST(test_set_get_same_elem) -TEST_MODULE_TEST(test_set_get_many_elem) -TEST_MODULE_END() diff --git a/src/test/cconfig/cconfig-util-test.c b/src/test/cconfig/cconfig-util-test.c deleted file mode 100644 index 78cf49c1..00000000 --- a/src/test/cconfig/cconfig-util-test.c +++ /dev/null @@ -1,220 +0,0 @@ -#include "cconfig/cconfig-util.h" -#include "cconfig/cconfig.h" - -#include "test/check.h" -#include "test/test.h" - -static void test_set_get_int() -{ - struct cconfig *config; - int32_t value; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_util_set_int(config, "test", 12345, "desc"); - - check_int_eq(config->nentries, 1); - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].value, "12345"); - check_str_eq(config->entries[0].desc, "desc"); - - check_bool_true(cconfig_util_get_int(config, "test", &value, 0)); - check_int_eq(value, 12345); - - cconfig_finit(config); -} - -static void test_get_int_na() -{ - struct cconfig *config; - int32_t value; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - check_bool_false(cconfig_util_get_int(config, "test", &value, 123)); - check_int_eq(value, 123); - - cconfig_finit(config); -} - -static void test_set_get_float() -{ - struct cconfig *config; - float value; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_util_set_float(config, "test", 100.5f, "desc"); - - check_int_eq(config->nentries, 1); - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].desc, "desc"); - - check_bool_true(cconfig_util_get_float(config, "test", &value, 0)); - check_float_eq(value, 100.5f, 0.1f); - - cconfig_finit(config); -} - -static void test_get_float_na() -{ - struct cconfig *config; - float value; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - check_bool_false(cconfig_util_get_float(config, "test", &value, 115.9f)); - check_float_eq(value, 115.9f, 0.1f); - - cconfig_finit(config); -} - -static void test_set_get_bool() -{ - struct cconfig *config; - bool value; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_util_set_bool(config, "test", true, "desc"); - - check_int_eq(config->nentries, 1); - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].desc, "desc"); - - check_bool_true(cconfig_util_get_bool(config, "test", &value, 0)); - check_bool_true(value); - - cconfig_finit(config); -} - -static void test_get_bool_na() -{ - struct cconfig *config; - bool value; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - check_bool_false(cconfig_util_get_bool(config, "test", &value, true)); - check_bool_true(value); - - cconfig_finit(config); -} - -static void test_set_get_str() -{ - struct cconfig *config; - char value[1024]; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - cconfig_util_set_str(config, "test", "hello world", "desc"); - - check_int_eq(config->nentries, 1); - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].desc, "desc"); - - check_bool_true(cconfig_util_get_str( - config, "test", value, sizeof(value), "world hello")); - check_str_eq(value, "hello world"); - - cconfig_finit(config); -} - -static void test_get_str_na() -{ - struct cconfig *config; - char value[1024]; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - check_bool_false(cconfig_util_get_str( - config, "test", value, sizeof(value), "world hello")); - check_str_eq(value, "world hello"); - - cconfig_finit(config); -} - -static void test_set_get_data() -{ - struct cconfig *config; - uint8_t value[1024]; - uint8_t value2[1024]; - uint8_t value_default[] = {0x00}; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - for (int i = 0; i < sizeof(value); i++) { - value[i] = (uint8_t) i; - } - - cconfig_util_set_data(config, "test", value, sizeof(value), "desc"); - - check_int_eq(config->nentries, 1); - check_str_eq(config->entries[0].key, "test"); - check_str_eq(config->entries[0].desc, "desc"); - - check_bool_true(cconfig_util_get_data( - config, "test", value2, sizeof(value2), value_default)); - check_data_eq(value2, sizeof(value2), value, sizeof(value)); - - cconfig_finit(config); -} - -static void test_get_data_na() -{ - struct cconfig *config; - uint8_t value[1024]; - uint8_t value_default[] = {0x01}; - - config = cconfig_init(); - - check_int_eq(config->nentries, 0); - check_null(config->entries); - - check_bool_false(cconfig_util_get_data( - config, "test", value, sizeof(value), value_default)); - check_data_eq(value, 1, value_default, sizeof(value_default)); - - cconfig_finit(config); -} - -TEST_MODULE_BEGIN("cconfig-util") -TEST_MODULE_TEST(test_set_get_int) -TEST_MODULE_TEST(test_get_int_na) -TEST_MODULE_TEST(test_set_get_float) -TEST_MODULE_TEST(test_get_float_na) -TEST_MODULE_TEST(test_set_get_bool) -TEST_MODULE_TEST(test_get_bool_na) -TEST_MODULE_TEST(test_set_get_str) -TEST_MODULE_TEST(test_get_str_na) -TEST_MODULE_TEST(test_set_get_data) -TEST_MODULE_TEST(test_get_data_na) -TEST_MODULE_END() diff --git a/src/test/d3d9hook/Module.mk b/src/test/d3d9hook/Module.mk index 585139c5..eac964f6 100644 --- a/src/test/d3d9hook/Module.mk +++ b/src/test/d3d9hook/Module.mk @@ -5,9 +5,11 @@ srcdir_d3d9hook := src/test/d3d9hook ldflags_d3d9hook := \ libs_d3d9hook := \ + core \ hook \ test \ util \ + iface-core \ src_d3d9hook := \ dllmain.c \ @@ -25,6 +27,8 @@ libs_d3d9hook-test := \ hook \ test \ util \ + core \ + iface-core \ src_d3d9hook-test := \ main.c \ diff --git a/src/test/d3d9hook/dllmain.c b/src/test/d3d9hook/dllmain.c index 88060bb5..5253975c 100644 --- a/src/test/d3d9hook/dllmain.c +++ b/src/test/d3d9hook/dllmain.c @@ -2,12 +2,16 @@ #include #include +#include "core/log-bt-ext.h" +#include "core/log-bt.h" +#include "core/log-sink-std.h" + +#include "iface-core/log.h" + #include "hook/d3d9.h" #include "test/check.h" -#include "util/log.h" - #define debug_print(...) fprintf(stderr, __VA_ARGS__) static HRESULT my_d3d9_handler(struct hook_d3d9_irp *irp); @@ -298,7 +302,11 @@ static HRESULT my_d3d9_handler(struct hook_d3d9_irp *irp) BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - log_to_writer(log_writer_stderr, NULL); + core_log_bt_core_api_set(); + + core_log_bt_ext_init_with_stderr(); + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); + debug_print("Initializing d3d9 hook module...\n"); hook_d3d9_init(d3d9_handlers, lengthof(d3d9_handlers)); diff --git a/src/test/iidxhook-util/Module.mk b/src/test/iidxhook-util/Module.mk deleted file mode 100644 index be4883eb..00000000 --- a/src/test/iidxhook-util/Module.mk +++ /dev/null @@ -1,66 +0,0 @@ -testexes += iidxhook-util-config-eamuse-test - -srcdir_iidxhook-util-config-eamuse-test := src/test/iidxhook-util - -ldflags_iidxhook-util-config-eamuse-test := \ - -lws2_32 \ - -libs_iidxhook-util-config-eamuse-test := \ - security \ - iidxhook-util \ - cconfig \ - test \ - util \ - -src_iidxhook-util-config-eamuse-test := \ - iidxhook-util-config-eamuse-test.c \ - -################################################################################ - -testexes += iidxhook-util-config-gfx-test - -srcdir_iidxhook-util-config-gfx-test := src/test/iidxhook-util - -libs_iidxhook-util-config-gfx-test := \ - security \ - iidxhook-util \ - cconfig \ - test \ - util \ - -src_iidxhook-util-config-gfx-test := \ - iidxhook-util-config-gfx-test.c \ - -################################################################################ - -testexes += iidxhook-util-config-misc-test - -srcdir_iidxhook-util-config-misc-test := src/test/iidxhook-util - -libs_iidxhook-util-config-misc-test := \ - security \ - iidxhook-util \ - cconfig \ - test \ - util \ - -src_iidxhook-util-config-misc-test := \ - iidxhook-util-config-misc-test.c \ - -################################################################################ - -testexes += iidxhook-util-config-sec-test - -srcdir_iidxhook-util-config-sec-test := src/test/iidxhook-util - -libs_iidxhook-util-config-sec-test := \ - security \ - iidxhook-util \ - cconfig \ - test \ - util \ - -src_iidxhook-util-config-sec-test := \ - iidxhook-util-config-sec-test.c \ - -################################################################################ \ No newline at end of file diff --git a/src/test/iidxhook-util/iidxhook-util-config-eamuse-test.c b/src/test/iidxhook-util/iidxhook-util-config-eamuse-test.c deleted file mode 100644 index ade73ffb..00000000 --- a/src/test/iidxhook-util/iidxhook-util-config-eamuse-test.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "iidxhook-util/config-eamuse.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering - the tests */ - -static void test_config_eamuse_defaults() -{ - struct cconfig *config; - struct iidxhook_util_config_eamuse config_eamuse; - - config = cconfig_init(); - - iidxhook_util_config_eamuse_init(config); - iidxhook_util_config_eamuse_get(&config_eamuse, config); - - cconfig_finit(config); - - check_str_eq(config_eamuse.card_type, "C02"); - check_str_eq(net_addr_to_str(&config_eamuse.server), "localhost:80"); - check_str_eq( - security_id_to_str(&config_eamuse.pcbid, false), - "0101020304050607086F"); - check_str_eq( - security_id_to_str(&config_eamuse.eamid, false), - "0101020304050607086F"); -} - -static void test_config_eamuse() -{ - struct cconfig *config; - struct iidxhook_util_config_eamuse config_eamuse; - - config = cconfig_init(); - - iidxhook_util_config_eamuse_init(config); - - cconfig_set2(config, "eamuse.card_type", "D01"); - cconfig_set2(config, "eamuse.server", "http://myServer.com/legacy"); - cconfig_set2(config, "eamuse.pcbid", "0101020304050607086F"); - cconfig_set2(config, "eamuse.eamid", "0101020304050607086F"); - - iidxhook_util_config_eamuse_get(&config_eamuse, config); - - cconfig_finit(config); - - check_str_eq(config_eamuse.card_type, "D01"); - check_str_eq( - net_addr_to_str(&config_eamuse.server), "http://myServer.com/legacy"); - check_str_eq( - security_id_to_str(&config_eamuse.pcbid, false), - "0101020304050607086F"); - check_str_eq( - security_id_to_str(&config_eamuse.eamid, false), - "0101020304050607086F"); -} - -static void test_config_eamuse_invalid_values() -{ - struct cconfig *config; - struct iidxhook_util_config_eamuse config_eamuse; - - config = cconfig_init(); - - iidxhook_util_config_eamuse_init(config); - - cconfig_set2(config, "eamuse.card_type", "XXXX"); - cconfig_set2(config, "eamuse.server", "asdf"); - cconfig_set2(config, "eamuse.pcbid", "00000000000000000000"); - cconfig_set2(config, "eamuse.eamid", "00000000000000000000"); - - iidxhook_util_config_eamuse_get(&config_eamuse, config); - - cconfig_finit(config); - - check_str_eq(config_eamuse.card_type, "C02"); - check_str_eq(net_addr_to_str(&config_eamuse.server), "asdf"); - check_str_eq( - security_id_to_str(&config_eamuse.pcbid, false), - "00000000000000000000"); - check_str_eq( - security_id_to_str(&config_eamuse.eamid, false), - "00000000000000000000"); -} - -TEST_MODULE_BEGIN("iidxhook-config-eamuse") -TEST_MODULE_TEST(test_config_eamuse_defaults) -TEST_MODULE_TEST(test_config_eamuse) -TEST_MODULE_TEST(test_config_eamuse_invalid_values) -TEST_MODULE_END() diff --git a/src/test/iidxhook-util/iidxhook-util-config-gfx-test.c b/src/test/iidxhook-util/iidxhook-util-config-gfx-test.c deleted file mode 100644 index 3009df03..00000000 --- a/src/test/iidxhook-util/iidxhook-util-config-gfx-test.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "iidxhook-util/config-gfx.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering - the tests */ - -static void test_config_gfx_defaults() -{ - struct cconfig *config; - struct iidxhook_config_gfx config_gfx; - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - iidxhook_config_gfx_get(&config_gfx, config); - - cconfig_finit(config); - - check_bool_false(config_gfx.bgvideo_uv_fix); - check_bool_false(config_gfx.framed); - check_float_eq(config_gfx.frame_rate_limit, 0.0f, 0.1f); - check_float_eq(config_gfx.monitor_check, -1.0f, 0.1f); - check_int_eq(config_gfx.pci_id_vid, 0x1002); - check_int_eq(config_gfx.pci_id_pid, 0x7146); - check_bool_false(config_gfx.windowed); - check_int_eq(config_gfx.scale_back_buffer_width, 0); - check_int_eq(config_gfx.scale_back_buffer_height, 0); - check_int_eq( - config_gfx.scale_back_buffer_width, - IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_NONE); -} - -static void test_config_gfx() -{ - struct cconfig *config; - struct iidxhook_config_gfx config_gfx; - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - - cconfig_set2(config, "gfx.bgvideo_uv_fix", "true"); - cconfig_set2(config, "gfx.framed", "true"); - cconfig_set2(config, "gfx.frame_rate_limit", "60.04"); - cconfig_set2(config, "gfx.monitor_check", "59.999"); - cconfig_set2(config, "gfx.pci_id", "1111:1234"); - cconfig_set2(config, "gfx.windowed", "true"); - cconfig_set2(config, "gfx.scale_back_buffer_width", "1920"); - cconfig_set2(config, "gfx.scale_back_buffer_height", "1080"); - cconfig_set2(config, "gfx.scale_back_buffer_filter", "linear"); - - iidxhook_config_gfx_get(&config_gfx, config); - - cconfig_finit(config); - - check_bool_true(config_gfx.bgvideo_uv_fix); - check_bool_true(config_gfx.framed); - check_float_eq(config_gfx.frame_rate_limit, 60.04f, 0.1f); - check_float_eq(config_gfx.monitor_check, 59.999f, 0.001f); - check_int_eq(config_gfx.pci_id_vid, 0x1111); - check_int_eq(config_gfx.pci_id_pid, 0x1234); - check_bool_true(config_gfx.windowed); - check_int_eq(config_gfx.scale_back_buffer_width, 1920); - check_int_eq(config_gfx.scale_back_buffer_height, 1080); - check_int_eq( - config_gfx.scale_back_buffer_filter, - IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_LINEAR); -} - -static void test_config_gfx_invalid_values() -{ - struct cconfig *config; - struct iidxhook_config_gfx config_gfx; - - config = cconfig_init(); - - iidxhook_config_gfx_init(config); - - cconfig_set2(config, "gfx.bgvideo_uv_fix", "123"); - cconfig_set2(config, "gfx.framed", "aaa"); - cconfig_set2(config, "gfx.frame_rate_limit", "-1.0f"); - cconfig_set2(config, "gfx.monitor_check", "asdf"); - cconfig_set2(config, "gfx.pci_id", "11111234"); - cconfig_set2(config, "gfx.windowed", "-5"); - cconfig_set2(config, "gfx.scale_back_buffer_width", "asdf"); - cconfig_set2(config, "gfx.scale_back_buffer_height", ""); - cconfig_set2(config, "gfx.scale_back_buffer_filter", "ffff"); - - iidxhook_config_gfx_get(&config_gfx, config); - - cconfig_finit(config); - - check_bool_false(config_gfx.bgvideo_uv_fix); - check_bool_false(config_gfx.framed); - check_float_eq(config_gfx.frame_rate_limit, 0.0f, 0.1f); - check_float_eq(config_gfx.monitor_check, -1.0f, 0.1f); - check_int_eq(config_gfx.pci_id_vid, 0x1002); - check_int_eq(config_gfx.pci_id_pid, 0x7146); - check_bool_false(config_gfx.windowed); - check_int_eq(config_gfx.scale_back_buffer_width, 0); - check_int_eq(config_gfx.scale_back_buffer_height, 0); - check_int_eq( - config_gfx.scale_back_buffer_width, - IIDXHOOK_UTIL_D3D9_BACK_BUFFER_SCALE_FILTER_NONE); -} - -TEST_MODULE_BEGIN("iidxhook-config-gfx") -TEST_MODULE_TEST(test_config_gfx_defaults) -TEST_MODULE_TEST(test_config_gfx) -TEST_MODULE_TEST(test_config_gfx_invalid_values) -TEST_MODULE_END() diff --git a/src/test/iidxhook-util/iidxhook-util-config-misc-test.c b/src/test/iidxhook-util/iidxhook-util-config-misc-test.c deleted file mode 100644 index 6aa9d3e3..00000000 --- a/src/test/iidxhook-util/iidxhook-util-config-misc-test.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "iidxhook-util/config-misc.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering the - * tests */ - -static void test_config_misc_defaults() -{ - struct cconfig *config; - struct iidxhook_config_misc config_misc; - - config = cconfig_init(); - - iidxhook_config_misc_init(config); - iidxhook_config_misc_get(&config_misc, config); - - cconfig_finit(config); - - check_bool_false(config_misc.disable_clock_set); - check_bool_false(config_misc.rteffect_stub); -} - -static void test_config_misc() -{ - struct cconfig *config; - struct iidxhook_config_misc config_misc; - - config = cconfig_init(); - - iidxhook_config_misc_init(config); - - cconfig_set2(config, "misc.disable_clock_set", "true"); - cconfig_set2(config, "misc.rteffect_stub", "true"); - - iidxhook_config_misc_get(&config_misc, config); - - cconfig_finit(config); - - check_bool_true(config_misc.disable_clock_set); - check_bool_true(config_misc.rteffect_stub); -} - -static void test_config_misc_invalid_values() -{ - struct cconfig *config; - struct iidxhook_config_misc config_misc; - - config = cconfig_init(); - - iidxhook_config_misc_init(config); - - cconfig_set2(config, "misc.disable_clock_set", "asdf"); - cconfig_set2(config, "misc.rteffect_stub", "222"); - - iidxhook_config_misc_get(&config_misc, config); - - cconfig_finit(config); - - check_bool_false(config_misc.disable_clock_set); - check_bool_false(config_misc.rteffect_stub); -} - -TEST_MODULE_BEGIN("iidxhook-config-misc") -TEST_MODULE_TEST(test_config_misc_defaults) -TEST_MODULE_TEST(test_config_misc) -TEST_MODULE_TEST(test_config_misc_invalid_values) -TEST_MODULE_END() diff --git a/src/test/iidxhook-util/iidxhook-util-config-sec-test.c b/src/test/iidxhook-util/iidxhook-util-config-sec-test.c deleted file mode 100644 index 9c12aa4e..00000000 --- a/src/test/iidxhook-util/iidxhook-util-config-sec-test.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "iidxhook-util/config-sec.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering the - * tests */ - -static void test_config_sec_defaults() -{ - struct cconfig *config; - struct iidxhook_config_sec config_sec; - const uint32_t boot_seeds[3] = {0, 0, 0}; - - config = cconfig_init(); - - iidxhook_config_sec_init(config); - iidxhook_config_sec_get(&config_sec, config); - - cconfig_finit(config); - - check_str_eq(security_mcode_to_str(&config_sec.boot_version), "GEC02 "); - check_data_eq( - config_sec.boot_seeds, - sizeof(config_sec.boot_seeds), - (void *) boot_seeds, - sizeof(boot_seeds)); - check_str_eq( - security_mcode_to_str(&config_sec.black_plug_mcode), "GQC02JAA"); -} - -static void test_config_sec() -{ - struct cconfig *config; - struct iidxhook_config_sec config_sec; - const uint32_t boot_seeds[3] = {1, 1, 1}; - - config = cconfig_init(); - - iidxhook_config_sec_init(config); - - cconfig_set2(config, "sec.boot_version", "ASDFG "); - cconfig_set2(config, "sec.boot_seeds", "1:1:1"); - cconfig_set2(config, "sec.black_plug_mcode", "GQD01JAB"); - - iidxhook_config_sec_get(&config_sec, config); - - cconfig_finit(config); - - check_str_eq(security_mcode_to_str(&config_sec.boot_version), "ASDFG "); - check_data_eq( - config_sec.boot_seeds, - sizeof(config_sec.boot_seeds), - (void *) boot_seeds, - sizeof(boot_seeds)); - check_str_eq( - security_mcode_to_str(&config_sec.black_plug_mcode), "GQD01JAB"); -} - -static void test_config_sec_invalid_values() -{ - struct cconfig *config; - struct iidxhook_config_sec config_sec; - const uint32_t boot_seeds[3] = {0, 0, 0}; - - config = cconfig_init(); - - iidxhook_config_sec_init(config); - - cconfig_set2(config, "sec.boot_version", "ASDFG1234"); - cconfig_set2(config, "sec.boot_seeds", "1:11"); - cconfig_set2(config, "sec.black_plug_mcode", "GQD01JABA"); - - iidxhook_config_sec_get(&config_sec, config); - - cconfig_finit(config); - - check_str_eq(security_mcode_to_str(&config_sec.boot_version), "GEC02 "); - check_data_eq( - config_sec.boot_seeds, - sizeof(config_sec.boot_seeds), - (void *) boot_seeds, - sizeof(boot_seeds)); - check_str_eq( - security_mcode_to_str(&config_sec.black_plug_mcode), "GQC02JAA"); -} - -TEST_MODULE_BEGIN("iidxhook-config-sec") -TEST_MODULE_TEST(test_config_sec_defaults) -TEST_MODULE_TEST(test_config_sec) -TEST_MODULE_TEST(test_config_sec_invalid_values) -TEST_MODULE_END() diff --git a/src/test/iidxhook/Module.mk b/src/test/iidxhook/Module.mk deleted file mode 100644 index 8c086423..00000000 --- a/src/test/iidxhook/Module.mk +++ /dev/null @@ -1,29 +0,0 @@ -testexes += iidxhook-config-iidxhook1-test - -srcdir_iidxhook-config-iidxhook1-test := src/test/iidxhook - -libs_iidxhook-config-iidxhook1-test := \ - cconfig \ - iidxhook1 \ - test \ - util \ - -src_iidxhook-config-iidxhook1-test := \ - iidxhook-config-iidxhook1-test.c \ - -################################################################################ - -testexes += iidxhook-config-iidxhook2-test - -srcdir_iidxhook-config-iidxhook2-test := src/test/iidxhook - -libs_iidxhook-config-iidxhook2-test := \ - iidxhook2 \ - cconfig \ - test \ - util \ - -src_iidxhook-config-iidxhook2-test := \ - iidxhook-config-iidxhook2-test.c \ - -################################################################################ diff --git a/src/test/iidxhook/iidxhook-config-iidxhook1-test.c b/src/test/iidxhook/iidxhook-config-iidxhook1-test.c deleted file mode 100644 index 9825898b..00000000 --- a/src/test/iidxhook/iidxhook-config-iidxhook1-test.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "iidxhook1/config-iidxhook1.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering the - * tests */ - -static void test_config_iidxhook1_defaults() -{ - struct cconfig *config; - struct iidxhook_config_iidxhook1 config_iidxhook1; - - config = cconfig_init(); - - iidxhook_config_iidxhook1_init(config); - iidxhook_config_iidxhook1_get(&config_iidxhook1, config); - - cconfig_finit(config); - - check_bool_false(config_iidxhook1.happy_sky_ms_bg_fix); -} - -static void test_config_iidxhook1() -{ - struct cconfig *config; - struct iidxhook_config_iidxhook1 config_iidxhook1; - - config = cconfig_init(); - - iidxhook_config_iidxhook1_init(config); - - cconfig_set2(config, "misc.happy_sky_ms_bg_fix", "true"); - - iidxhook_config_iidxhook1_get(&config_iidxhook1, config); - - cconfig_finit(config); - - check_bool_true(config_iidxhook1.happy_sky_ms_bg_fix); -} - -static void test_config_iidxhook1_invalid_values() -{ - struct cconfig *config; - struct iidxhook_config_iidxhook1 config_iidxhook1; - - config = cconfig_init(); - - iidxhook_config_iidxhook1_init(config); - - cconfig_set2(config, "misc.happy_sky_ms_bg_fix", "123"); - - iidxhook_config_iidxhook1_get(&config_iidxhook1, config); - - cconfig_finit(config); - - check_bool_false(config_iidxhook1.happy_sky_ms_bg_fix); -} - -TEST_MODULE_BEGIN("iidxhook-config-iidxhook1") -TEST_MODULE_TEST(test_config_iidxhook1_defaults) -TEST_MODULE_TEST(test_config_iidxhook1) -TEST_MODULE_TEST(test_config_iidxhook1_invalid_values) -TEST_MODULE_END() diff --git a/src/test/iidxhook/iidxhook-config-iidxhook2-test.c b/src/test/iidxhook/iidxhook-config-iidxhook2-test.c deleted file mode 100644 index 00f3e94e..00000000 --- a/src/test/iidxhook/iidxhook-config-iidxhook2-test.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "iidxhook2/config-iidxhook2.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering the - * tests */ - -static void test_config_iidxhook2_defaults() -{ - struct cconfig *config; - struct iidxhook_config_iidxhook2 config_iidxhook2; - - config = cconfig_init(); - - iidxhook_config_iidxhook2_init(config); - iidxhook_config_iidxhook2_get(&config_iidxhook2, config); - - cconfig_finit(config); - - check_bool_false(config_iidxhook2.distorted_ms_bg_fix); -} - -static void test_config_iidxhook2() -{ - struct cconfig *config; - struct iidxhook_config_iidxhook2 config_iidxhook2; - - config = cconfig_init(); - - iidxhook_config_iidxhook2_init(config); - - cconfig_set2(config, "misc.distorted_ms_bg_fix", "true"); - - iidxhook_config_iidxhook2_get(&config_iidxhook2, config); - - cconfig_finit(config); - - check_bool_true(config_iidxhook2.distorted_ms_bg_fix); -} - -static void test_config_iidxhook2_invalid_values() -{ - struct cconfig *config; - struct iidxhook_config_iidxhook2 config_iidxhook2; - - config = cconfig_init(); - - iidxhook_config_iidxhook2_init(config); - - cconfig_set2(config, "misc.distorted_ms_bg_fix", "123"); - - iidxhook_config_iidxhook2_get(&config_iidxhook2, config); - - cconfig_finit(config); - - check_bool_false(config_iidxhook2.distorted_ms_bg_fix); -} - -TEST_MODULE_BEGIN("iidxhook-config-iidxhook2") -TEST_MODULE_TEST(test_config_iidxhook2_defaults) -TEST_MODULE_TEST(test_config_iidxhook2) -TEST_MODULE_TEST(test_config_iidxhook2_invalid_values) -TEST_MODULE_END() diff --git a/src/test/iidxhook8/Module.mk b/src/test/iidxhook8/Module.mk deleted file mode 100644 index 57731d54..00000000 --- a/src/test/iidxhook8/Module.mk +++ /dev/null @@ -1,28 +0,0 @@ -testexes += iidxhook8-config-cam-test - -srcdir_iidxhook8-config-cam-test := src/test/iidxhook8 - -libs_iidxhook8-config-cam-test := \ - camhook \ - cconfig \ - test \ - util \ - -src_iidxhook8-config-cam-test := \ - iidxhook8-config-cam-test.c \ - -################################################################################ - -testexes += iidxhook8-config-io-test - -srcdir_iidxhook8-config-io-test := src/test/iidxhook8 - -libs_iidxhook8-config-io-test := \ - cconfig \ - test \ - util \ - -src_iidxhook8-config-io-test := \ - iidxhook8-config-io-test.c \ - -################################################################################ \ No newline at end of file diff --git a/src/test/iidxhook8/iidxhook8-config-cam-test.c b/src/test/iidxhook8/iidxhook8-config-cam-test.c deleted file mode 100644 index bc7f3ae4..00000000 --- a/src/test/iidxhook8/iidxhook8-config-cam-test.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "camhook/config-cam.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering the - * tests */ - -static void test_config_cam_defaults() -{ - struct cconfig *config; - struct camhook_config_cam config_cam; - - config = cconfig_init(); - - camhook_config_cam_init(config, 2, false); - camhook_config_cam_get(&config_cam, config, 2, false); - - cconfig_finit(config); - - check_bool_false(config_cam.disable_emu); - check_str_eq(config_cam.device_id[0], ""); - check_str_eq(config_cam.device_id[1], ""); -} - -static void test_config_cam() -{ - struct cconfig *config; - struct camhook_config_cam config_cam; - - config = cconfig_init(); - - camhook_config_cam_init(config, 2, false); - - cconfig_set2(config, "cam.disable_emu", "true"); - cconfig_set2(config, "cam.device_id1", "asdjkasd"); - cconfig_set2(config, "cam.device_id2", "1234"); - - camhook_config_cam_get(&config_cam, config, 2, false); - - cconfig_finit(config); - - check_bool_true(config_cam.disable_emu); - check_str_eq(config_cam.device_id[0], "asdjkasd"); - check_str_eq(config_cam.device_id[1], "1234"); -} - -static void test_config_cam_invalid_values() -{ - struct cconfig *config; - struct camhook_config_cam config_cam; - - config = cconfig_init(); - - camhook_config_cam_init(config, 2, false); - - cconfig_set2(config, "cam.disable_emu", "123"); - cconfig_set2(config, "cam.device_id1", "asdjkasd"); - cconfig_set2(config, "cam.device_id2", "1234"); - - camhook_config_cam_get(&config_cam, config, 2, false); - - cconfig_finit(config); - - check_bool_false(config_cam.disable_emu); - check_str_eq(config_cam.device_id[0], "asdjkasd"); - check_str_eq(config_cam.device_id[1], "1234"); -} - -TEST_MODULE_BEGIN("camhook-config-cam") -TEST_MODULE_TEST(test_config_cam_defaults) -TEST_MODULE_TEST(test_config_cam) -TEST_MODULE_TEST(test_config_cam_invalid_values) -TEST_MODULE_END() diff --git a/src/test/iidxhook8/iidxhook8-config-io-test.c b/src/test/iidxhook8/iidxhook8-config-io-test.c deleted file mode 100644 index 5524ba6a..00000000 --- a/src/test/iidxhook8/iidxhook8-config-io-test.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "iidxhook8/config-io.h" - -#include "test/check.h" -#include "test/test.h" - -/* We don't care about cleaning up some of the memory to avoid cluttering the - * tests */ - -static void test_config_io_defaults() -{ - struct cconfig *config; - struct iidxhook8_config_io config_io; - - config = cconfig_init(); - - iidxhook8_config_io_init(config); - iidxhook8_config_io_get(&config_io, config); - - cconfig_finit(config); - - check_bool_false(config_io.disable_card_reader_emu); - check_bool_false(config_io.disable_bio2_emu); - check_bool_false(config_io.disable_poll_limiter); -} - -static void test_config_io() -{ - struct cconfig *config; - struct iidxhook8_config_io config_io; - - config = cconfig_init(); - - iidxhook8_config_io_init(config); - - cconfig_set2(config, "io.disable_card_reader_emu", "true"); - cconfig_set2(config, "io.disable_bio2_emu", "true"); - cconfig_set2(config, "io.disable_poll_limiter", "true"); - - iidxhook8_config_io_get(&config_io, config); - - cconfig_finit(config); - - check_bool_true(config_io.disable_card_reader_emu); - check_bool_true(config_io.disable_bio2_emu); - check_bool_true(config_io.disable_poll_limiter); -} - -static void test_config_io_invalid_values() -{ - struct cconfig *config; - struct iidxhook8_config_io config_io; - - config = cconfig_init(); - - iidxhook8_config_io_init(config); - - cconfig_set2(config, "io.disable_card_reader_emu", "asdf"); - cconfig_set2(config, "io.disable_bio2_emu", "123"); - cconfig_set2(config, "io.disable_poll_limiter", ""); - - iidxhook8_config_io_get(&config_io, config); - - cconfig_finit(config); - - check_bool_false(config_io.disable_card_reader_emu); - check_bool_false(config_io.disable_bio2_emu); - check_bool_false(config_io.disable_poll_limiter); -} - -TEST_MODULE_BEGIN("iidxhook8-config-io") -TEST_MODULE_TEST(test_config_io_defaults) -TEST_MODULE_TEST(test_config_io) -TEST_MODULE_TEST(test_config_io_invalid_values) -TEST_MODULE_END() diff --git a/src/test/security/Module.mk b/src/test/security/Module.mk index 3bdef674..18867a44 100644 --- a/src/test/security/Module.mk +++ b/src/test/security/Module.mk @@ -3,9 +3,11 @@ testexes += security-id-test srcdir_security-id-test := src/test/security libs_security-id-test := \ + core \ security \ test \ util \ + iface-core \ src_security-id-test := \ security-id-test.c \ @@ -17,9 +19,11 @@ testexes += security-mcode-test srcdir_security-mcode-test := src/test/security libs_security-mcode-test := \ + core \ security \ test \ util \ + iface-core \ src_security-mcode-test := \ security-mcode-test.c \ @@ -31,9 +35,11 @@ testexes += security-util-test srcdir_security-util-test := src/test/security libs_security-util-test := \ + core \ security \ test \ util \ + iface-core \ src_security-util-test := \ security-util-test.c \ @@ -45,9 +51,11 @@ testexes += security-rp-test srcdir_security-rp-test := src/test/security libs_security-rp-test := \ + core \ security \ test \ util \ + iface-core \ src_security-rp-test := \ security-rp-test.c \ @@ -59,9 +67,11 @@ testexes += security-rp2-test srcdir_security-rp2-test := src/test/security libs_security-rp2-test := \ + core \ security \ test \ util \ + iface-core \ src_security-rp2-test := \ security-rp2-test.c \ @@ -73,9 +83,11 @@ testexes += security-rp3-test srcdir_security-rp3-test := src/test/security libs_security-rp3-test := \ + core \ security \ test \ util \ + iface-core \ src_security-rp3-test := \ security-rp3-test.c \ diff --git a/src/test/test/test.h b/src/test/test/test.h index 91fb01bb..e9b48e37 100644 --- a/src/test/test/test.h +++ b/src/test/test/test.h @@ -3,12 +3,18 @@ #include -#include "util/log.h" +#include "core/log-bt-ext.h" +#include "core/log-bt.h" -#define TEST_MODULE_BEGIN(name) \ - int main(int argc, char **argv) \ - { \ - log_to_writer(log_writer_stderr, NULL); \ +#include "iface-core/log.h" + +#define TEST_MODULE_BEGIN(name) \ + int main(int argc, char **argv) \ + { \ + core_log_bt_core_api_set(); \ + \ + core_log_bt_ext_init_with_stderr(); \ + core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); \ fprintf(stderr, "Executing test module '%s'...\n", #name); #define TEST_MODULE_TEST(func) \ @@ -19,6 +25,8 @@ #define TEST_MODULE_END() \ fprintf(stderr, "Finished execution of test module\n"); \ + core_log_bt_fini(); \ + \ return 0; \ } diff --git a/src/test/util/Module.mk b/src/test/util/Module.mk index ca13ecc6..1b65d0de 100644 --- a/src/test/util/Module.mk +++ b/src/test/util/Module.mk @@ -7,8 +7,10 @@ ldflags_util-net-test := \ -liphlpapi \ libs_util-net-test := \ + core \ test \ util \ + iface-core \ src_util-net-test := \ util-net-test.c \ diff --git a/todo.md b/todo.md new file mode 100644 index 00000000..32e11a56 --- /dev/null +++ b/todo.md @@ -0,0 +1,130 @@ +# Bemanitools 6 TODOs + +Lose list of TODOs/notes/thoughts that might or might not need to worked on. Some of these are +already sorted and moved to separate sub-sections outlining some kind of "roadmap". + +## Alpha 4 + +* rename bt_module_configure_do to bt_module_configure_load as we don't want to imply to actually configure anything, but just load configuration +* use config-ext helpers in iidxconfig for dongle mcodes, pcbid, eamid +* have private verify functions in all config modules that check valid values and ranges +* update security/mcode with knowledge from arcade-docs -> see macros +* rethink a bunch of configuration values and if they even must be exposed, e.g. dongle mcode on ddrhook1 which + must even have the same value to boot correctly +* have separate verify parameter functions in all config modules, see iidxhook-util/gfx-config +* have cleaner config defaults included in dist package here targeted for "living room arcade" use + with sane defaults that have a high likelihood that the game just runs on most off-the-shelf hardware +* implement fini function in iidxhook2, 3, 4 etc. -> cleanup hook modules +* inline iidxhook-util d3d9 config stuff -> config class + module +* reflect optional in configuration API? it's quite a mess of using -1 and stuff to reflect that something is not there. with xml, the value can be kept empty simply to reflect that or leaving out the node entirely + +goal: migrate and cleanup all old/inject (iidx)hooks + +* deprecate cconfig and replace with core-config everywhere, e.g. in IO libs +* Support config api, required implementation for modules such as IO once being used, see modules/io-ext -> TODOs next to api inits + +## Alpha 5 - command line stuff + +* have some unified tooling in core for this? -> works well together with existing config API +* command line tooling unification: command arg parsing, common command args like setting log level/enabling/disabling log file +* command line overrides for hook (and other?) configurations managed in + inject and launcher, transparent to hook which just gets the final config +* improve command line tool/usage docs by following the man page style format with sections name, synopsis description, options etc. +* improve config defaults, e.g. on old iidx games: have various gfx fixes enabled by default, cause disabling is rather the exception, e.g. running on actual old hardware that doesn't have these issues +* have a library that provides global options for any + command line tool such as setting log level, log file etc. + and have a piece of code allowing for quick and simply usage everywhere -> unify command line args +* support command lines with paths, i.e. -P launcher.hooks.bla.gfx.windowed + as well as allowing hooks and other things to define arbitrary short versions + e.g. -w for windowed + +## Alpha ??? - cleanup pass + stabilize iidxhook + +go through all iidxhook modules and check for stuff like TODOs or anything that +could benefit from a little tidying up + +* dissolve iidxhook-util and instead have earliest appearance and share with successive +modules +* consolidate loading of iidxio and eamio code in separate modules iidxio-module, eamio-module +in iidxhook1, then re-use on later iidxhooks + +## Alpha ??? - inject native bemanitools 6 hook API support + +* inject + * Modify loading of hooks -> need to call btapi thread + log set functions somehow + * Modify hooking to hook main_init and main_fini of hook before and after the main function of the exe + * Load exe (PE) file, resolve references but don't call the start() function, yet + * Run the start() function with hook main_init and main_finit before and after that -> issue if exe has nothing, not even heap etc. initialized? + * Which functions can i use from hooklib for that? + * Requires writing our own PE loader for executables? + * See hook/process -> process_hijack_startup and hook/pe + +bemanitools: new tool called “loader” that’s a PE loader with additional btools 6 api. also supports generic hooks with just DllMain as it supports loading of arbitrary DLLs. should work trapping BT ApI before start() function because DllMain methods were called even earlier already. just need to make sure BT hook stuff is called after the entire process is set up and all dependencies loaded + +push back loader idea as inject still works fine with the debugger idea and everything else. +also check my own references and read up to refresh my mind how windows loads executables/PE files +regarding the stages/steps it takes before writing the bemanitools loader that replaces inject + +* use new bemanitools hook api in iidxhooks + * replace inject logging through debug api with unified logging through bemanitools 6 api + +## TBD/unsorted + +* jbhook1: gfx hooks partially broken due to change in hooking setup/bootstrapping, see TODO in jbhook1 +* sidcode backpropagation required and currently broken for sdvxhook2 and jbhook (?) at least (marked with TODO) +* meson as build system: requires getting rid of all the special AVS sauce in the current build system -> planned to load and resolve AVS libs dynamically, pre-requisite +* iat hook impl in launcher not complete and working, yet +* dynamically load AVS to get rid of all the static linking and different AVS + version builds -> cleans up build process significantly and also makes + switching to a new/different build system easier +* document life cycle of hooks, when they happen, what gets called, what to do and what not to do -> document this in the API + overview with references from some sdk docs + * dll load: DllMain + * ... refer to hook API calls +* documentation as a rendered page on bemanitools.github.io domain + * Design and style like sapling documentation +* think about splitting mono hooks into smaller ones. iidx is probably a good + example because stuff is being re-used everywhere, e.g. gfx stuff? +* group all hooks in its own subfolder -> name them all with a "hook" postfix? +* procmon: lib avs monitor +* make vtables for core thread and log +* for io api + * use structs with bit fields everywhere to avoid all the bit shifting etc + * align several IO interfaces regarding separate polling (read/write) calls etc + * make them work closer to the actual device IOs, e.g. ddr with different sensor modes polling vs individual + * have all IO APIs in the style of + * setters + getters: modify internal state, but don't transfer to hardware/device, yet + * transactional functions: read/write (or send/recv) or update to execute a transaction to the hardware. this also can be a stubbed function that doesn't do anything if the backend is async driven but the API is not exposing that and looks like a sync API + * split iidxio into vefx and control deck parts -> have this as a separate library that loads two libs and composes them to the iidxio one? +* btapi design choice: have return types always be a status code and use parameter pointers to return actual data, e.g. for getting IO values +* io/popn: doesn't have read/write (poll) calls to explicitly drive the hardware +* have command in build script/justfile to create a package that can be used as a standalone project + to develop for bemanitools using the sdk +* Have a version.h/version.c for every dll/exe in bemanitools, see launcher. Print these at the first possible occasion when logging is available to console +* have shim dlls in sdk (?) that create backward compatibility with + BT5 equivalent DLLs but only support the api v1 of BT6 +* make vefx.dll optional in iidxio.dll with geninput.dll +* iidx io emulation is not getting values "atomic" from iidxio API + see the various msg implementations which hook the API + for example + msg_resp.inverted_pad = ((iidx_io_ep2_get_keys() & 0x3FFF) << 16) | + (iidx_io_ep2_get_panel() & 0x0F) | + ((iidx_io_ep2_get_sys() & 0x07) << 4) | + (((iidx_io_ep2_get_sys() >> 2) & 0x01) << 30); + -> iidx_io_ep2_get_sys is called twice +* notes for migration guide from bemanitools 5 to 6 + * Delete config.exe configurations in appdata: C:\Users\\AppData\Roaming\DJHACKERS\iidx.bin + * incompatibility list to BT5 + * All IO libs + * hooks? + * configuration files .conf + * previous setups with eapki data, keep stuff stock now and use bootstrap.xml provided by btools or stock bootstrap.xml +* config tool broken -> various functions from geninput need + to be loaded in addition to the input interface +* rteffects stubs don't seem to work, iidxhook1+2 +* split all games and versions for distribution files to distribution packages for each game version. avoids having a mixed bag of multiple versions with different startup scripts and sometimes oneofs, e.g. one specific lib for one version. +* for iidx e,f settings folders (old games), have default configuration values allocate them outside of the revision dirs, e.g. under settings/save next to the bemanitools folder to keep revision folders clean +* similar to trace wrapper for core api, have performance measuring around IO api +* reverse engineer NvDisplayConfigLDJ and make bemanitools version of that +* bemanitools performance monitoring of IO and rendering loops, measure and expose metrics alert on flaky performance +* tool to easily read and change xml properties configs from command line, similar to jq, but a lot simpler. no query language, just simple get and put +* moving build system to meson once AVS libs are dynamically loaded \ No newline at end of file