From 6c914266d9264f14c9df4ac0289e1ccd9d7613bc Mon Sep 17 00:00:00 2001 From: smpn2 Date: Fri, 16 Dec 2022 23:15:54 +0900 Subject: [PATCH] chore: CRLF to LF --- .dockerignore | 8 +- Dockerfile | 12 +- LICENSE | 1348 +- README.md | 522 +- acio/acio.h | 36 +- acio/bi2a/bi2a.cpp | 1020 +- acio/bi2a/bi2a.h | 26 +- acio/bmpu/bmpu.cpp | 1192 +- acio/bmpu/bmpu.h | 26 +- acio/core/core.cpp | 380 +- acio/core/core.h | 26 +- acio/hbhi/hbhi.h | 26 +- acio/hdxs/hdxs.h | 26 +- acio/hgth/hgth.cpp | 244 +- acio/hgth/hgth.h | 26 +- acio/i36g/i36g.cpp | 750 +- acio/i36g/i36g.h | 26 +- acio/i36i/i36i.h | 26 +- acio/icca/icca.h | 42 +- acio/j32d/j32d.h | 26 +- acio/kfca/kfca.cpp | 966 +- acio/kfca/kfca.h | 36 +- acio/klpa/klpa.cpp | 476 +- acio/klpa/klpa.h | 26 +- acio/mdxf/mdxf.h | 26 +- acio/module.h | 110 +- acio/nddb/nddb.cpp | 128 +- acio/nddb/nddb.h | 26 +- acio/panb/panb.h | 26 +- acio/pix/pix.cpp | 1040 +- acio/pix/pix.h | 26 +- acio/pjec/pjec.h | 26 +- acio/pjei/pjei.cpp | 446 +- acio/pjei/pjei.h | 26 +- acioemu/acioemu.cpp | 410 +- acioemu/acioemu.h | 64 +- acioemu/bi2a.h | 160 +- acioemu/device.cpp | 236 +- acioemu/device.h | 206 +- acioemu/handle.cpp | 138 +- acioemu/handle.h | 56 +- acioemu/icca.h | 84 +- api/controller.h | 164 +- api/module.cpp | 86 +- api/module.h | 134 +- api/modules/analogs.cpp | 354 +- api/modules/analogs.h | 56 +- api/modules/buttons.h | 56 +- api/modules/capture.cpp | 164 +- api/modules/capture.h | 36 +- api/modules/card.h | 34 +- api/modules/coin.h | 40 +- api/modules/control.cpp | 360 +- api/modules/control.h | 44 +- api/modules/info.h | 38 +- api/modules/keypads.cpp | 352 +- api/modules/keypads.h | 38 +- api/modules/lcd.cpp | 72 +- api/modules/lcd.h | 34 +- api/modules/lights.cpp | 358 +- api/modules/lights.h | 56 +- api/modules/memory.cpp | 466 +- api/modules/memory.h | 38 +- api/request.cpp | 110 +- api/request.h | 42 +- api/resources/arduino/README.md | 8 +- api/resources/arduino/spiceapi/rc4.h | 130 +- api/resources/arduino/spiceapi/spiceapi.ino | 344 +- api/resources/arduino/spiceapi/wrappers.h | 1432 +- api/resources/cpp/README.md | 16 +- api/resources/cpp/spiceapi/LICENSE | 48 +- api/resources/cpp/spiceapi/connection.cpp | 362 +- api/resources/cpp/spiceapi/connection.h | 62 +- api/resources/cpp/spiceapi/rc4.cpp | 90 +- api/resources/cpp/spiceapi/rc4.h | 42 +- api/resources/cpp/spiceapi/wrappers.cpp | 1276 +- api/resources/cpp/spiceapi/wrappers.h | 208 +- api/resources/dart/spiceapi-websocket/LICENSE | 48 +- .../dart/spiceapi-websocket/spiceapi.dart | 44 +- .../spiceapi-websocket/src/connection.dart | 386 +- .../spiceapi-websocket/src/exceptions.dart | 22 +- .../dart/spiceapi-websocket/src/rc4.dart | 96 +- .../dart/spiceapi-websocket/src/request.dart | 90 +- .../dart/spiceapi-websocket/src/response.dart | 70 +- .../src/wrappers/analogs.dart | 108 +- .../src/wrappers/buttons.dart | 108 +- .../spiceapi-websocket/src/wrappers/card.dart | 16 +- .../spiceapi-websocket/src/wrappers/coin.dart | 42 +- .../src/wrappers/control.dart | 72 +- .../spiceapi-websocket/src/wrappers/iidx.dart | 38 +- .../spiceapi-websocket/src/wrappers/info.dart | 44 +- .../src/wrappers/keypads.dart | 56 +- .../src/wrappers/lights.dart | 108 +- .../src/wrappers/memory.dart | 70 +- .../src/wrappers/touch.dart | 106 +- api/resources/dart/spiceapi/LICENSE | 48 +- api/resources/dart/spiceapi/spiceapi.dart | 46 +- .../dart/spiceapi/src/connection.dart | 384 +- .../dart/spiceapi/src/exceptions.dart | 22 +- api/resources/dart/spiceapi/src/rc4.dart | 96 +- api/resources/dart/spiceapi/src/request.dart | 90 +- api/resources/dart/spiceapi/src/response.dart | 70 +- .../dart/spiceapi/src/wrappers/analogs.dart | 108 +- .../dart/spiceapi/src/wrappers/buttons.dart | 108 +- .../dart/spiceapi/src/wrappers/capture.dart | 76 +- .../dart/spiceapi/src/wrappers/card.dart | 16 +- .../dart/spiceapi/src/wrappers/coin.dart | 42 +- .../dart/spiceapi/src/wrappers/control.dart | 72 +- .../dart/spiceapi/src/wrappers/iidx.dart | 38 +- .../dart/spiceapi/src/wrappers/info.dart | 44 +- .../dart/spiceapi/src/wrappers/keypads.dart | 56 +- .../dart/spiceapi/src/wrappers/lights.dart | 108 +- .../dart/spiceapi/src/wrappers/memory.dart | 70 +- .../dart/spiceapi/src/wrappers/touch.dart | 136 +- api/resources/python/.gitignore | 232 +- api/resources/python/spiceapi/LICENSE | 48 +- api/resources/python/spiceapi/__init__.py | 28 +- api/resources/python/spiceapi/analogs.py | 56 +- api/resources/python/spiceapi/buttons.py | 56 +- api/resources/python/spiceapi/card.py | 18 +- api/resources/python/spiceapi/coin.py | 40 +- api/resources/python/spiceapi/connection.py | 278 +- api/resources/python/spiceapi/control.py | 102 +- api/resources/python/spiceapi/exceptions.py | 20 +- api/resources/python/spiceapi/iidx.py | 36 +- api/resources/python/spiceapi/info.py | 34 +- api/resources/python/spiceapi/keypads.py | 48 +- api/resources/python/spiceapi/lights.py | 56 +- api/resources/python/spiceapi/memory.py | 62 +- api/resources/python/spiceapi/rc4.py | 48 +- api/resources/python/spiceapi/request.py | 126 +- api/resources/python/spiceapi/response.py | 60 +- api/resources/python/spiceapi/touch.py | 42 +- api/resources/python/spiceremote.py | 1148 +- api/resources/python/stringreplace.py | 104 +- api/response.cpp | 102 +- api/response.h | 74 +- api/serial.h | 60 +- api/websocket.cpp | 338 +- api/websocket.h | 42 +- avs/automap.h | 42 +- avs/ea3.cpp | 1300 +- avs/ea3.h | 108 +- avs/game.cpp | 218 +- avs/game.h | 88 +- build/defs.cpp | 56 +- build/defs.h | 204 +- build/icon.h | 6 +- build/icon.rc | 4 +- build/manifest.h | 8 +- build/manifest.manifest | 60 +- build/manifest.rc | 60 +- build/manifest64.rc | 60 +- build/resource.h | 16 +- build/version_num.h | 8 +- build_msvc.py | 170 +- cfg/Win32D.rc | 34 +- cfg/api.h | 316 +- cfg/config.h | 120 +- cfg/configurator.h | 52 +- cfg/configurator_wnd.cpp | 346 +- cfg/configurator_wnd.h | 38 +- cfg/game.cpp | 50 +- cfg/game.h | 168 +- cfg/icon.h | 6 +- cfg/icon.rc | 4 +- cfg/light.cpp | 146 +- cfg/light.h | 136 +- cfg/manifest.h | 8 +- cfg/manifest.manifest | 56 +- cfg/manifest.rc | 60 +- cfg/option.cpp | 168 +- cfg/option.h | 116 +- cfg/resource.h | 12 +- cfg/screen_resize.cpp | 244 +- cfg/screen_resize.h | 62 +- cfg/spicecfg.cpp | 140 +- cfg/spicecfg.h | 12 +- easrv/easrv.h | 8 +- easrv/responses/bs_info2_common.h | 14 +- easrv/responses/bs_pcb2_boot.h | 20 +- easrv/responses/bs_pcb2_error.h | 14 +- easrv/responses/op2_common_get_music_info.h | 12818 ++++++++-------- easrv/responses/pcbtracker_alive.h | 26 +- easrv/responses_raw/update_responses.sh | 22 +- easrv/smartea.cpp | 170 +- easrv/smartea.h | 16 +- external/asio/asio.h | 2146 +-- external/asio/asiolist.cpp | 402 +- external/asio/asiolist.h | 72 +- external/asio/asiosys.h | 164 +- external/asio/changes.txt | 44 +- external/asio/iasiodrv.h | 78 +- external/cardio/cardio_hid.cpp | 900 +- external/cardio/cardio_hid.h | 170 +- external/cardio/cardio_runner.cpp | 214 +- external/cardio/cardio_runner.h | 18 +- external/cardio/cardio_window.cpp | 346 +- external/cardio/cardio_window.h | 80 +- external/cv2pdb/.gitignore | 18 +- external/cv2pdb/README.md | 72 +- external/discord-rpc/.clang-format | 184 +- external/discord-rpc/.gitignore | 8 +- external/discord-rpc/.travis.yml | 94 +- external/discord-rpc/CMakeLists.txt | 60 +- external/discord-rpc/LICENSE | 38 +- external/discord-rpc/README.md | 308 +- external/discord-rpc/appveyor.yml | 34 +- external/discord-rpc/build.py | 608 +- .../discord-rpc/include/discord_register.h | 52 +- external/discord-rpc/include/discord_rpc.h | 174 +- external/discord-rpc/src/CMakeLists.txt | 294 +- external/discord-rpc/src/backoff.h | 80 +- external/discord-rpc/src/connection.h | 38 +- external/discord-rpc/src/connection_unix.cpp | 250 +- external/discord-rpc/src/connection_win.cpp | 260 +- .../src/discord_register_linux.cpp | 204 +- .../discord-rpc/src/discord_register_osx.m | 160 +- .../discord-rpc/src/discord_register_win.cpp | 374 +- external/discord-rpc/src/discord_rpc.cpp | 1008 +- external/discord-rpc/src/dllmain.cpp | 16 +- external/discord-rpc/src/msg_queue.h | 72 +- external/discord-rpc/src/rpc_connection.cpp | 274 +- external/discord-rpc/src/rpc_connection.h | 118 +- external/discord-rpc/src/serialization.cpp | 490 +- external/discord-rpc/src/serialization.h | 430 +- external/fmt/.clang-format | 16 +- external/fmt/.gitignore | 74 +- external/fmt/CMakeLists.txt | 820 +- external/fmt/CONTRIBUTING.md | 40 +- external/fmt/ChangeLog.rst | 8476 +++++----- external/fmt/LICENSE.rst | 54 +- external/fmt/README.rst | 1048 +- external/fmt/include/fmt/args.h | 464 +- external/fmt/include/fmt/chrono.h | 2518 +-- external/fmt/include/fmt/color.h | 1254 +- external/fmt/include/fmt/compile.h | 1276 +- external/fmt/include/fmt/core.h | 5916 +++---- external/fmt/include/fmt/format-inl.h | 5248 +++---- external/fmt/include/fmt/format.h | 5684 +++---- external/fmt/include/fmt/locale.h | 4 +- external/fmt/include/fmt/os.h | 1030 +- external/fmt/include/fmt/ostream.h | 362 +- external/fmt/include/fmt/printf.h | 1416 +- external/fmt/include/fmt/ranges.h | 926 +- external/fmt/include/fmt/xchar.h | 422 +- external/fmt/src/fmt.cc | 200 +- external/fmt/src/format.cc | 150 +- external/fmt/src/os.cc | 720 +- external/fmt/support/Android.mk | 30 +- external/fmt/support/AndroidManifest.xml | 2 +- external/fmt/support/C++.sublime-syntax | 4122 ++--- external/fmt/support/README | 8 +- external/fmt/support/Vagrantfile | 40 +- external/fmt/support/appveyor-build.py | 86 +- external/fmt/support/appveyor.yml | 62 +- external/fmt/support/build-docs.py | 116 +- external/fmt/support/build.gradle | 264 +- external/fmt/support/cmake/FindSetEnv.cmake | 14 +- external/fmt/support/cmake/JoinPaths.cmake | 52 +- external/fmt/support/cmake/cxx14.cmake | 140 +- .../fmt/support/cmake/fmt-config.cmake.in | 8 +- external/fmt/support/cmake/fmt.pc.in | 22 +- external/fmt/support/compute-powers.py | 106 +- external/fmt/support/docopt.py | 1162 +- external/fmt/support/manage.py | 580 +- external/fmt/support/rst2md.py | 318 +- external/fmt/support/rtd/conf.py | 14 +- external/fmt/support/rtd/index.rst | 4 +- external/fmt/support/rtd/theme/layout.html | 34 +- external/fmt/support/rtd/theme/theme.conf | 4 +- external/hash-library/CMakeLists.txt | 50 +- external/hash-library/LICENSE | 20 +- external/hash-library/crc32.cpp | 862 +- external/hash-library/crc32.h | 138 +- external/hash-library/digest.cpp | 218 +- external/hash-library/hash.h | 56 +- external/hash-library/hmac.h | 166 +- external/hash-library/keccak.cpp | 578 +- external/hash-library/keccak.h | 162 +- external/hash-library/md5.cpp | 760 +- external/hash-library/md5.h | 156 +- external/hash-library/readme.md | 102 +- external/hash-library/sha1.cpp | 652 +- external/hash-library/sha1.h | 156 +- external/hash-library/sha256.cpp | 822 +- external/hash-library/sha256.h | 156 +- external/hash-library/sha3.cpp | 578 +- external/hash-library/sha3.h | 162 +- external/hash-library/tests/tests.cpp | 722 +- external/headsocket.h | 4382 +++--- external/http-parser/http_parser.c | 4960 +++--- external/http-parser/http_parser.h | 872 +- external/imgui/CMakeLists.txt | 42 +- external/imgui/LICENSE.txt | 42 +- external/imgui/imgui_memory_editor.h | 1480 +- .../layeredfs/3rd_party/GuillotineBinPack.cpp | 1286 +- .../layeredfs/3rd_party/GuillotineBinPack.h | 268 +- external/layeredfs/3rd_party/Rect.cpp | 100 +- external/layeredfs/3rd_party/Rect.h | 188 +- external/layeredfs/3rd_party/rapidxml.hpp | 5192 +++---- .../layeredfs/3rd_party/rapidxml_print.hpp | 892 +- external/layeredfs/3rd_party/stb_dxt.cpp | 74 +- external/layeredfs/3rd_party/stb_dxt.h | 2086 +-- external/layeredfs/LICENSE | 18 +- external/layeredfs/config.cpp | 76 +- external/layeredfs/config.h | 26 +- external/layeredfs/hook.cpp | 1694 +- external/layeredfs/hook.h | 28 +- external/layeredfs/modpath_handler.cpp | 454 +- external/layeredfs/modpath_handler.h | 58 +- external/layeredfs/texture_packer.cpp | 138 +- external/layeredfs/texture_packer.h | 70 +- external/layeredfs/utils.cpp | 370 +- external/layeredfs/utils.h | 56 +- external/linalg.h | 1442 +- external/minhook/.editorconfig | 44 +- external/minhook/.gitignore | 86 +- external/minhook/AUTHORS.txt | 16 +- external/minhook/CMakeLists.txt | 42 +- external/minhook/LICENSE.txt | 162 +- external/minhook/README.md | 176 +- external/minhook/build/MinGW/Makefile | 66 +- external/minhook/build/VC10/MinHook.vcxproj | 376 +- external/minhook/build/VC10/MinHookVC10.sln | 78 +- .../minhook/build/VC10/libMinHook.vcxproj | 342 +- .../build/VC10/libMinHook.vcxproj.filters | 108 +- external/minhook/build/VC11/MinHook.vcxproj | 376 +- external/minhook/build/VC11/MinHookVC11.sln | 78 +- .../minhook/build/VC11/libMinHook.vcxproj | 342 +- .../build/VC11/libMinHook.vcxproj.filters | 108 +- external/minhook/build/VC12/MinHook.vcxproj | 376 +- external/minhook/build/VC12/MinHookVC12.sln | 82 +- .../minhook/build/VC12/libMinHook.vcxproj | 346 +- .../build/VC12/libMinHook.vcxproj.filters | 108 +- external/minhook/build/VC14/MinHook.vcxproj | 376 +- external/minhook/build/VC14/MinHookVC14.sln | 82 +- .../minhook/build/VC14/libMinHook.vcxproj | 346 +- .../build/VC14/libMinHook.vcxproj.filters | 108 +- external/minhook/build/VC15/MinHook.vcxproj | 378 +- external/minhook/build/VC15/MinHookVC15.sln | 82 +- .../minhook/build/VC15/libMinHook.vcxproj | 348 +- .../build/VC15/libMinHook.vcxproj.filters | 108 +- external/minhook/build/VC9/MinHook.vcproj | 686 +- external/minhook/build/VC9/MinHookVC9.sln | 78 +- external/minhook/build/VC9/libMinHook.vcproj | 820 +- external/minhook/dll_resources/MinHook.def | 28 +- external/minhook/dll_resources/MinHook.rc | 64 +- external/minhook/include/MinHook.h | 372 +- external/minhook/src/buffer.c | 624 +- external/minhook/src/buffer.h | 84 +- external/minhook/src/hde/hde32.c | 652 +- external/minhook/src/hde/hde32.h | 210 +- external/minhook/src/hde/hde64.c | 674 +- external/minhook/src/hde/hde64.h | 224 +- external/minhook/src/hde/pstdint.h | 78 +- external/minhook/src/hde/table32.h | 146 +- external/minhook/src/hde/table64.h | 148 +- external/minhook/src/hook.c | 1778 +-- external/minhook/src/trampoline.c | 634 +- external/minhook/src/trampoline.h | 210 +- external/rapidjson/allocators.h | 542 +- external/rapidjson/document.h | 5164 +++---- external/rapidjson/encodedstream.h | 598 +- external/rapidjson/encodings.h | 1432 +- external/rapidjson/error/en.h | 148 +- external/rapidjson/error/error.h | 310 +- external/rapidjson/filereadstream.h | 198 +- external/rapidjson/filewritestream.h | 208 +- external/rapidjson/fwd.h | 302 +- external/rapidjson/internal/biginteger.h | 580 +- external/rapidjson/internal/diyfp.h | 516 +- external/rapidjson/internal/dtoa.h | 490 +- external/rapidjson/internal/ieee754.h | 156 +- external/rapidjson/internal/itoa.h | 608 +- external/rapidjson/internal/meta.h | 362 +- external/rapidjson/internal/pow10.h | 110 +- external/rapidjson/internal/regex.h | 1402 +- external/rapidjson/internal/stack.h | 460 +- external/rapidjson/internal/strfunc.h | 110 +- external/rapidjson/internal/strtod.h | 538 +- external/rapidjson/internal/swap.h | 92 +- external/rapidjson/istreamwrapper.h | 230 +- external/rapidjson/memorybuffer.h | 140 +- external/rapidjson/memorystream.h | 142 +- external/rapidjson/msinttypes/inttypes.h | 632 +- external/rapidjson/msinttypes/stdint.h | 600 +- external/rapidjson/ostreamwrapper.h | 162 +- external/rapidjson/pointer.h | 2716 ++-- external/rapidjson/prettywriter.h | 510 +- external/rapidjson/rapidjson.h | 1230 +- external/rapidjson/reader.h | 3758 ++--- external/rapidjson/schema.h | 4012 ++--- external/rapidjson/stream.h | 358 +- external/rapidjson/stringbuffer.h | 234 +- external/rapidjson/writer.h | 1220 +- external/readerwriterqueue/.gitignore | 52 +- external/readerwriterqueue/LICENSE.md | 56 +- external/readerwriterqueue/README.md | 244 +- external/readerwriterqueue/atomicops.h | 1352 +- .../readerwriterqueue/readerwriterqueue.h | 1878 +-- external/robin_hood.h | 5060 +++--- external/scard/scard.cpp | 726 +- external/scard/scard.h | 164 +- external/stackwalker/stackwalker.cpp | 2536 +-- external/stackwalker/stackwalker.h | 388 +- external/stb_image_write.h | 2916 ++-- external/tinyxml2/tinyxml2.cpp | 5478 +++---- external/tinyxml2/tinyxml2.h | 4532 +++--- external/toojpeg/LICENSE | 20 +- external/toojpeg/toojpeg.cpp | 1330 +- external/toojpeg/toojpeg.h | 124 +- external/usbhidusage/usb-hid-usage.c | 1448 +- external/usbhidusage/usb-hid-usage.h | 12 +- games/bbc/bbc.cpp | 74 +- games/bbc/bbc.h | 26 +- games/bbc/io.cpp | 210 +- games/bbc/io.h | 184 +- games/bs/bs.cpp | 106 +- games/bs/bs.h | 24 +- games/bs/io.cpp | 82 +- games/bs/io.h | 70 +- games/ddr/ddr.cpp | 234 +- games/ddr/ddr.h | 32 +- games/ddr/io.cpp | 174 +- games/ddr/io.h | 164 +- games/ddr/p3io/foot.cpp | 184 +- games/ddr/p3io/foot.h | 46 +- games/ddr/p3io/p3io.cpp | 1100 +- games/ddr/p3io/p3io.h | 74 +- games/ddr/p3io/sate.cpp | 204 +- games/ddr/p3io/sate.h | 62 +- games/ddr/p3io/usbmem.cpp | 120 +- games/ddr/p3io/usbmem.h | 52 +- games/dea/dea.cpp | 52 +- games/dea/dea.h | 24 +- games/dea/io.cpp | 136 +- games/dea/io.h | 124 +- games/drs/drs.cpp | 818 +- games/drs/drs.h | 102 +- games/drs/io.cpp | 82 +- games/drs/io.h | 72 +- games/ftt/ftt.cpp | 304 +- games/ftt/ftt.h | 24 +- games/ftt/io.cpp | 130 +- games/ftt/io.h | 104 +- games/ftt/nui.h | 366 +- games/game.cpp | 44 +- games/game.h | 48 +- games/gitadora/gitadora.cpp | 412 +- games/gitadora/gitadora.h | 36 +- games/gitadora/io.cpp | 236 +- games/gitadora/io.h | 216 +- games/hpm/hpm.cpp | 76 +- games/hpm/hpm.h | 26 +- games/hpm/io.cpp | 108 +- games/hpm/io.h | 96 +- games/iidx/bi2a.cpp | 482 +- games/iidx/bi2a.h | 60 +- games/iidx/bi2x.cpp | 496 +- games/iidx/bi2x.h | 60 +- games/iidx/bi2x_hook.h | 12 +- games/iidx/ezusb.cpp | 554 +- games/iidx/ezusb.h | 64 +- games/iidx/io.h | 322 +- games/io.h | 126 +- games/jb/io.cpp | 132 +- games/jb/io.h | 120 +- games/jb/jb.cpp | 290 +- games/jb/jb.h | 34 +- games/loveplus/io.cpp | 76 +- games/loveplus/io.h | 64 +- games/loveplus/loveplus.cpp | 342 +- games/loveplus/loveplus.h | 32 +- games/mfc/io.cpp | 44 +- games/mfc/io.h | 42 +- games/mfc/mfc.cpp | 764 +- games/mfc/mfc.h | 40 +- games/mga/gunio.cpp | 316 +- games/mga/gunio.h | 58 +- games/mga/io.cpp | 146 +- games/mga/io.h | 118 +- games/mga/mga.cpp | 164 +- games/mga/mga.h | 26 +- games/museca/io.cpp | 196 +- games/museca/io.h | 172 +- games/nost/io.cpp | 382 +- games/nost/io.h | 358 +- games/nost/nost.cpp | 92 +- games/nost/nost.h | 24 +- games/otoca/io.cpp | 80 +- games/otoca/io.h | 68 +- games/otoca/otoca.cpp | 54 +- games/otoca/otoca.h | 28 +- games/otoca/p4io.cpp | 266 +- games/otoca/p4io.h | 12 +- games/pcm/io.cpp | 44 +- games/pcm/io.h | 40 +- games/pcm/pcm.cpp | 236 +- games/pcm/pcm.h | 22 +- games/popn/io.cpp | 188 +- games/popn/io.h | 176 +- games/popn/popn.cpp | 598 +- games/popn/popn.h | 28 +- games/qma/ezusb.cpp | 602 +- games/qma/ezusb.h | 12 +- games/qma/io.cpp | 166 +- games/qma/io.h | 154 +- games/qma/qma.cpp | 270 +- games/qma/qma.h | 26 +- games/rb/io.cpp | 90 +- games/rb/io.h | 80 +- games/rb/rb.h | 26 +- games/rb/touch.cpp | 384 +- games/rb/touch.h | 66 +- games/rf3d/io.cpp | 94 +- games/rf3d/io.h | 82 +- games/rf3d/rf3d.cpp | 68 +- games/rf3d/rf3d.h | 26 +- games/sc/io.cpp | 132 +- games/sc/io.h | 106 +- games/sc/sc.cpp | 298 +- games/sc/sc.h | 28 +- games/scotto/io.cpp | 138 +- games/scotto/io.h | 126 +- games/scotto/scotto.cpp | 46 +- games/scotto/scotto.h | 26 +- games/sdvx/camera.cpp | 294 +- games/sdvx/camera.h | 12 +- games/shared/lcdhandle.cpp | 280 +- games/shared/lcdhandle.h | 78 +- games/shared/printer.cpp | 1218 +- games/shared/printer.h | 36 +- games/shared/twtouch.cpp | 300 +- games/shared/twtouch.h | 72 +- games/shogikai/io.cpp | 70 +- games/shogikai/io.h | 56 +- games/shogikai/shogikai.cpp | 954 +- games/shogikai/shogikai.h | 28 +- games/silentscope/io.cpp | 82 +- games/silentscope/io.h | 72 +- games/silentscope/silentscope.cpp | 54 +- games/silentscope/silentscope.h | 28 +- games/we/io.cpp | 166 +- games/we/io.h | 140 +- games/we/touchpanel.cpp | 282 +- games/we/touchpanel.h | 12 +- games/we/we.cpp | 292 +- games/we/we.h | 28 +- hooks/audio/audio.cpp | 174 +- hooks/audio/audio.h | 68 +- hooks/audio/audio_private.h | 28 +- hooks/audio/backends/mmdevice/device.cpp | 246 +- hooks/audio/backends/mmdevice/device.h | 72 +- .../backends/mmdevice/device_enumerator.cpp | 170 +- .../backends/mmdevice/device_enumerator.h | 66 +- hooks/audio/backends/wasapi/audio_client.cpp | 968 +- hooks/audio/backends/wasapi/audio_client.h | 110 +- .../backends/wasapi/audio_render_client.cpp | 176 +- .../backends/wasapi/audio_render_client.h | 76 +- hooks/audio/backends/wasapi/defs.h | 102 +- .../backends/wasapi/dummy_audio_client.cpp | 432 +- .../backends/wasapi/dummy_audio_client.h | 126 +- .../backends/wasapi/dummy_audio_clock.cpp | 124 +- .../audio/backends/wasapi/dummy_audio_clock.h | 78 +- .../wasapi/dummy_audio_render_client.cpp | 114 +- .../wasapi/dummy_audio_render_client.h | 76 +- .../wasapi/dummy_audio_session_control.cpp | 352 +- .../wasapi/dummy_audio_session_control.h | 98 +- hooks/audio/backends/wasapi/util.cpp | 40 +- hooks/audio/backends/wasapi/util.h | 16 +- hooks/audio/backends/wasapi/wasapi_private.h | 58 +- hooks/audio/buffer.cpp | 198 +- hooks/audio/implementations/asio.cpp | 2120 +-- hooks/audio/implementations/asio.h | 306 +- hooks/audio/implementations/backend.h | 110 +- hooks/audio/implementations/wave_out.cpp | 448 +- hooks/audio/implementations/wave_out.h | 116 +- hooks/audio/util.cpp | 160 +- hooks/audio/util.h | 24 +- hooks/avshook.cpp | 586 +- hooks/avshook.h | 34 +- hooks/cfgmgr32hook.cpp | 168 +- hooks/cfgmgr32hook.h | 30 +- hooks/debughook.cpp | 206 +- hooks/debughook.h | 32 +- hooks/devicehook.cpp | 1150 +- hooks/devicehook.h | 150 +- hooks/graphics/backends/d3d9/d3d9_backend.h | 130 +- hooks/graphics/backends/d3d9/d3d9_device.h | 420 +- .../backends/d3d9/d3d9_fake_swapchain.cpp | 260 +- .../backends/d3d9/d3d9_fake_swapchain.h | 172 +- .../graphics/backends/d3d9/d3d9_swapchain.cpp | 282 +- hooks/graphics/backends/d3d9/d3d9_swapchain.h | 116 +- hooks/graphics/backends/d3d9/d3d9_texture.cpp | 254 +- hooks/graphics/backends/d3d9/d3d9_texture.h | 116 +- hooks/input/dinput8/fake_backend.cpp | 224 +- hooks/input/dinput8/fake_backend.h | 70 +- hooks/input/dinput8/fake_device.cpp | 414 +- hooks/input/dinput8/fake_device.h | 130 +- hooks/input/dinput8/hook.cpp | 102 +- hooks/input/dinput8/hook.h | 14 +- hooks/lang.cpp | 260 +- hooks/lang.h | 14 +- hooks/libraryhook.cpp | 250 +- hooks/libraryhook.h | 26 +- hooks/networkhook.cpp | 448 +- hooks/networkhook.h | 16 +- hooks/rom.cpp | 150 +- hooks/rom.h | 18 +- hooks/setupapihook.h | 28 +- hooks/sleephook.cpp | 86 +- hooks/sleephook.h | 14 +- hooks/unisintrhook.cpp | 288 +- hooks/unisintrhook.h | 6 +- launcher/launcher.h | 54 +- launcher/logger.cpp | 540 +- launcher/logger.h | 68 +- launcher/richpresence.cpp | 302 +- launcher/richpresence.h | 30 +- launcher/shutdown.cpp | 222 +- launcher/shutdown.h | 22 +- launcher/signal.cpp | 444 +- launcher/signal.h | 22 +- launcher/superexit.cpp | 198 +- launcher/superexit.h | 14 +- misc/bt5api.cpp | 588 +- misc/bt5api.h | 72 +- misc/clipboard.cpp | 286 +- misc/clipboard.h | 14 +- misc/device.cpp | 1444 +- misc/device.h | 10 +- misc/eamuse.h | 150 +- misc/extdev.cpp | 2124 +-- misc/extdev.h | 8 +- misc/sciunit.cpp | 614 +- misc/sciunit.h | 8 +- misc/sde.cpp | 56 +- misc/sde.h | 10 +- misc/vrutil.cpp | 240 +- misc/vrutil.h | 278 +- misc/wintouchemu.cpp | 752 +- misc/wintouchemu.h | 34 +- overlay/imgui/extensions.cpp | 88 +- overlay/imgui/extensions.h | 16 +- overlay/imgui/impl_dx9.cpp | 720 +- overlay/imgui/impl_dx9.h | 50 +- overlay/imgui/impl_spice.h | 20 +- overlay/imgui/impl_sw.h | 130 +- overlay/overlay.h | 200 +- overlay/windows/acio_status_buffers.cpp | 88 +- overlay/windows/acio_status_buffers.h | 44 +- overlay/windows/card_manager.cpp | 520 +- overlay/windows/card_manager.h | 66 +- overlay/windows/control.h | 106 +- overlay/windows/eadev.h | 44 +- overlay/windows/fps.cpp | 58 +- overlay/windows/fps.h | 30 +- overlay/windows/iidx_sub.h | 62 +- overlay/windows/keypad.cpp | 188 +- overlay/windows/keypad.h | 38 +- overlay/windows/log.cpp | 244 +- overlay/windows/log.h | 56 +- overlay/windows/midi.cpp | 258 +- overlay/windows/midi.h | 60 +- overlay/windows/screen_resize.cpp | 162 +- overlay/windows/screen_resize.h | 38 +- overlay/windows/vr.cpp | 436 +- overlay/windows/vr.h | 34 +- overlay/windows/wnd_manager.h | 38 +- rawinput/hotplug.cpp | 264 +- rawinput/hotplug.h | 40 +- rawinput/piuio.cpp | 788 +- rawinput/piuio.h | 156 +- rawinput/sextet.cpp | 356 +- rawinput/sextet.h | 132 +- rawinput/touch.cpp | 1134 +- rawinput/touch.h | 40 +- reader/crypt.cpp | 170 +- reader/crypt.h | 34 +- reader/message.cpp | 102 +- reader/message.h | 48 +- reader/reader.cpp | 948 +- reader/reader.h | 144 +- reader/structuredmessage.cpp | 28 +- reader/structuredmessage.h | 18 +- stubs/stubs.cpp | 240 +- stubs/stubs.def | 18 +- stubs/stubs.h | 36 +- touch/handler.h | 120 +- touch/win7.cpp | 594 +- touch/win7.h | 36 +- touch/win8.cpp | 632 +- touch/win8.h | 36 +- util/circular_buffer.h | 256 +- util/co_task_mem_ptr.h | 90 +- util/cpuutils.cpp | 268 +- util/cpuutils.h | 16 +- util/crypt.cpp | 140 +- util/crypt.h | 26 +- util/detour.cpp | 892 +- util/flags_helper.h | 62 +- util/libutils.cpp | 648 +- util/libutils.h | 154 +- util/logging.cpp | 28 +- util/logging.h | 180 +- util/lz77.cpp | 520 +- util/lz77.h | 22 +- util/memutils.cpp | 146 +- util/memutils.h | 88 +- util/netutils.cpp | 228 +- util/netutils.h | 16 +- util/peb.cpp | 212 +- util/peb.h | 32 +- util/rc4.cpp | 92 +- util/rc4.h | 36 +- util/resutils.cpp | 46 +- util/resutils.h | 22 +- util/sigscan.cpp | 332 +- util/sigscan.h | 76 +- util/time.cpp | 120 +- util/time.h | 18 +- util/unique_plain_ptr.h | 44 +- util/utils.cpp | 156 +- util/utils.h | 538 +- 725 files changed, 131020 insertions(+), 131020 deletions(-) diff --git a/.dockerignore b/.dockerignore index 1f1a307..852f8ce 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,4 @@ -bin/** -dist/** -docker/** -cmake-build* +bin/** +dist/** +docker/** +cmake-build* diff --git a/Dockerfile b/Dockerfile index 59287aa..0300cf9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM spicetools/deps -WORKDIR /src -RUN chown user:user /src -USER user -COPY --chown=user:user . /src -CMD ./build_all.sh +FROM spicetools/deps +WORKDIR /src +RUN chown user:user /src +USER user +COPY --chown=user:user . /src +CMD ./build_all.sh diff --git a/LICENSE b/LICENSE index 3877ae0..f288702 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,674 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index f404eb0..a555a36 100644 --- a/README.md +++ b/README.md @@ -1,261 +1,261 @@ -SpiceTools -========== -This is a loader for various arcade games developed by 573. -The project is using CMake as it's build system, with a custom build -script for making packages ready for distribution and to keep it easy -for people not knowing how to use CMake. - -## Building/Distribution - -We're currently using Arch Linux for building the binaries. -You'll need: -- MinGW-64 packages (can be found in the AUR) -- bash -- git -- zip -- upx (optional) - -For any other GNU/Linux distributions (or Windows lol), you're on your -own. - -To build the project, run: - - $ ./build_all.sh - -## Build Configuration - -You can tweak some settings at the beginning of the build script. You -might want to modify the paths of the toolchains if yours differ. It's -also possible to disable UPX compression and source distribution for -example. - -If you're not using an IDE and want to run the build script from command -line manually each time you make a change, you can set CLEAN_BUILD to 0 -so it will only compile what's needed. When modifying the resources you -should build from scratch, since CMake isn't able to track changes of -those files (e.g. changelog.txt, licenses.txt). - -You can put your custom build script under "build_all.local.sh" if you -don't want git to track the changes you made to the build settings. - -## Debug Build - -To get proper stackstraces, you need to build with the DEBUG setting -enabled. This will set the CMake build type to debug and the script -will try to make use of cv2pdb. -Check external/cv2pdb/README.md for details on how to set it up. -It is required to use cv2pdb to generate PDB output, because at time of -writing, MinGW still didn't support Microsoft's proprietary file format. - -## API - -SpiceTools is providing a TCP/JSON based API. You can enable it with the -`-api [PORT]` option. It's recommended to also set a password with -`-apipass [PASS]`. - -The protocol is meant to be simple, easy to use and with few overhead. -To connect to the API, just open a TCP connection to the host computer -at the specified port. -To make a request you write the UTF-8 encoded JSON contents to the -socket. To mark the end of the request, you need to terminate the JSON -string with `0x00`. The server returns its answer on the same way, -UTF-8 encoded JSON terminated with NULL. - -To save space, by default the JSONs are without whitespace. To enable -pretty printing, use `-apipretty`. - -If you want to test the API server without running a game, you can -run it headless via `-apidebug`. - -If a password is specified, both request and response are encrypted -using RC4 with the key being the password encoded in UTF-8. -While only providing weak security when the password is static, -it's simple to implement and requires no authentication protocol. -The password is also able to change dynamically, see -`control.session_refresh()` for details. - -If you don't want to worry about all the details, you can just use one -of the supplied libraries (check /api/resources). There's also a little -remote control GUI available for python. - -### WebSocket -SpiceTools opens a WebSocket server on the specified port plus one. -That means if the API is on 1337, the WebSocket server will be on 1338. -The protocol is the very same as for the normal API, but instead of -directly sending the data over TCP you need to send binary datapackets. -The included dart spiceapi library also has a WebSocket implementation. - -### Example Call -This example inserts the a card into P1's reader slot. -If you need more examples, you can check the example code. - -#### Request -```JSON -{ - "id": 1, - "module": "card", - "function": "insert", - "params": [0, "E004000000000000"] -} -``` -#### Response -```JSON -{ - "id": 1, - "errors": [], - "data": [] -} -``` - -### Modules - -For the sake of simplifying this documentation, I will describe functions -as if they were called via a normal programming language. That means, -besides `module`/`function` needing to be set accordingly, the `params` field -must contain all the parameters described below. Some of them are optional. -The returning data will always be in the `data` field of the response. - -Errors will be reported as strings in the `errors` field. Sometimes, you can -receive more than one error. The error messages may be changed/improved in the -future, so you shouldn't rely on them. If the error list is empty, the function -executed successfully. - -The `id` of the response will always match the `id` of the request. The API -server itself doesn't expect any logic of your ID choices, however you can use -them to make sure your answers aren't arriving out of order. Currently it -doesn't matter since the TCP protocol doesn't allow for out of order data, -however this may change when/if support for UDP is being introduced. The only -restriction is that the ID has to be a valid 64-bit unsigned integer. - -#### Card -- insert(index: uint, card_id: hex) - - inserts a card which gets read by the emulated card readers for the game - - index has to be either 0 (for P1) or 1 (for P2) - - card_id has to be a valid 16-character hex string - -#### Coin -- get() - - returns the amount of unprocessed coins in queue - - not equal to the amount of coins shown ingame since the game may drain it -- set(amount: int) - - sets the amount of coins in queue for the game to process -- insert(amount: int) - - adds the amount to the coins in queue - - amount is optional and defaults to 1 -- blocker_get() - - returns the current coin blocker state (false: open, true: closed) - -#### Info -- avs() - - returns a dict including the AVS model, dest, spec, rev and ext -- launcher() - - returns a dict including the version, compile date/time, system time and - the arguments used to start the process -- memory() - - returns a dict including total, total used and bytes used by the process - for both physical and virtual RAM - -#### Keypads -For all functions in this module, the keypad parameter must be -either 0 (for P1) or 1 (for P2). Accepted keypad characters are "0" to "9" for -the single digit numbers, "A" for the double zero and "D" for the decimal key. -- write(keypad: uint, input: str) - - writes all characters in input sequentially to the keypad - - this should be used for things like PIN input -- set(keypad: uint, key: char, ...) - - clears all overrides, then applies each given key as override - - if a key is overridden, it shows up as pressed in-game -- get(keypad: uint) - - returns all pressed keys of the specified keypad - -#### Analogs/Buttons/Lights -All of those three modules have equally named methods for you to call. -- read() - - returns an array of state objects containing name, state and a bool - - the bool indicates if the object is active (e.g. the button was overridden) -- write([name: str, state: float], ...) - - applies the states as an override value - - the device binding via the config will be ignored while an override is set - - if an override value is set, the object will be marked as active -- write_reset([name: str], ...) - - removes the override value from the objects specified by name - - if no names were passed, all overrides will be removed - -#### Touch -- read() - - returns an array of state objects containing id, x and y -- write([id: uint, x: int, y: int], ...) - - adds the given touch points having an unknown ID - - overrides old touch points when the ID matches -- write_reset(id: uint, ...) - - removes the touch points matching one of the given IDs - -#### Control -This module only functions if a password is being used to communicate, -with the single exception of session_refresh(). -- raise(signal: str) - - raises a signal to the current process - - signal is a string and must be one of the following values: - "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", "SIGTERM" - - the signal will be raised while the message is being processed -- exit(code: int) - - code is optional and defaults to 0 - - the process will end while the message is being processed -- restart() - - spawns a new instance with the same arguments as passed to the main executable -- session_refresh() - - generates a new secure password and applies it after the response - - can be used to increase the security by using the password as some kind of - session token - - recommended to call directly after connecting and once in a while for - persistent connections -- shutdown() - - tries to force shutdown the computer -- reboot() - - tries to force reboot the computer - -#### Memory -This module only functions if a password is being used to communicate. -All offsets are specified in file offsets of the corresponding `dll_name`, -which also means that your hex edits are applicable directly. -- write(dll_name: str, data: hex, offset: uint) - - writes the bytes in data to the specified offset -- read(dll_name: str, offset: uint, size: uint) - - reads bytes starting from offset and returns it -- signature(dll_name: str, signature: hex, replacement: hex, offset: uint, - usage: uint) - - tries to find the signature in the module's memory - - unknown bytes are masked out via "??" (e.g. "75??90????74") - - masking out bytes works for both the signature and the replacement - - offset is the byte difference between the offset of the found signature and - the offset where the replacement data gets written to - - usage is the number of the result being used for replacement, starting at 0 - - returns the offset where the replacement data gets written to - - the replacement string can be empty, so you can only get the address of the - signature while not actually replacing anything - -#### IIDX -- ticker_get() - - returns a string of the characters displayed on the 16 segment display -- ticker_set(text: str) - - sets the contents of the 16 segment display and disables writes from game -- ticker_reset() - - re-enables writes from game - -#### LCD -- info() - - returns information about the serial LCD controller some games use - -## License -Unless otherwise noted, all files are licensed under the GPLv3. -See the LICENSE file for the full license text. -Files not originating from this project should be placed in "external", -they each have their own license. - -###### What that means for you -- If you want to distribute the binaries, you'll have to include the - sources, otherwise you're violating the GPL. -- If you want to merge some of this project's code into similar - software, that software has to be put under the GPL as well. - You'll probably have to modify a lot anyways, so you can just use the - source as some kind of documentation. +SpiceTools +========== +This is a loader for various arcade games developed by 573. +The project is using CMake as it's build system, with a custom build +script for making packages ready for distribution and to keep it easy +for people not knowing how to use CMake. + +## Building/Distribution + +We're currently using Arch Linux for building the binaries. +You'll need: +- MinGW-64 packages (can be found in the AUR) +- bash +- git +- zip +- upx (optional) + +For any other GNU/Linux distributions (or Windows lol), you're on your +own. + +To build the project, run: + + $ ./build_all.sh + +## Build Configuration + +You can tweak some settings at the beginning of the build script. You +might want to modify the paths of the toolchains if yours differ. It's +also possible to disable UPX compression and source distribution for +example. + +If you're not using an IDE and want to run the build script from command +line manually each time you make a change, you can set CLEAN_BUILD to 0 +so it will only compile what's needed. When modifying the resources you +should build from scratch, since CMake isn't able to track changes of +those files (e.g. changelog.txt, licenses.txt). + +You can put your custom build script under "build_all.local.sh" if you +don't want git to track the changes you made to the build settings. + +## Debug Build + +To get proper stackstraces, you need to build with the DEBUG setting +enabled. This will set the CMake build type to debug and the script +will try to make use of cv2pdb. +Check external/cv2pdb/README.md for details on how to set it up. +It is required to use cv2pdb to generate PDB output, because at time of +writing, MinGW still didn't support Microsoft's proprietary file format. + +## API + +SpiceTools is providing a TCP/JSON based API. You can enable it with the +`-api [PORT]` option. It's recommended to also set a password with +`-apipass [PASS]`. + +The protocol is meant to be simple, easy to use and with few overhead. +To connect to the API, just open a TCP connection to the host computer +at the specified port. +To make a request you write the UTF-8 encoded JSON contents to the +socket. To mark the end of the request, you need to terminate the JSON +string with `0x00`. The server returns its answer on the same way, +UTF-8 encoded JSON terminated with NULL. + +To save space, by default the JSONs are without whitespace. To enable +pretty printing, use `-apipretty`. + +If you want to test the API server without running a game, you can +run it headless via `-apidebug`. + +If a password is specified, both request and response are encrypted +using RC4 with the key being the password encoded in UTF-8. +While only providing weak security when the password is static, +it's simple to implement and requires no authentication protocol. +The password is also able to change dynamically, see +`control.session_refresh()` for details. + +If you don't want to worry about all the details, you can just use one +of the supplied libraries (check /api/resources). There's also a little +remote control GUI available for python. + +### WebSocket +SpiceTools opens a WebSocket server on the specified port plus one. +That means if the API is on 1337, the WebSocket server will be on 1338. +The protocol is the very same as for the normal API, but instead of +directly sending the data over TCP you need to send binary datapackets. +The included dart spiceapi library also has a WebSocket implementation. + +### Example Call +This example inserts the a card into P1's reader slot. +If you need more examples, you can check the example code. + +#### Request +```JSON +{ + "id": 1, + "module": "card", + "function": "insert", + "params": [0, "E004000000000000"] +} +``` +#### Response +```JSON +{ + "id": 1, + "errors": [], + "data": [] +} +``` + +### Modules + +For the sake of simplifying this documentation, I will describe functions +as if they were called via a normal programming language. That means, +besides `module`/`function` needing to be set accordingly, the `params` field +must contain all the parameters described below. Some of them are optional. +The returning data will always be in the `data` field of the response. + +Errors will be reported as strings in the `errors` field. Sometimes, you can +receive more than one error. The error messages may be changed/improved in the +future, so you shouldn't rely on them. If the error list is empty, the function +executed successfully. + +The `id` of the response will always match the `id` of the request. The API +server itself doesn't expect any logic of your ID choices, however you can use +them to make sure your answers aren't arriving out of order. Currently it +doesn't matter since the TCP protocol doesn't allow for out of order data, +however this may change when/if support for UDP is being introduced. The only +restriction is that the ID has to be a valid 64-bit unsigned integer. + +#### Card +- insert(index: uint, card_id: hex) + - inserts a card which gets read by the emulated card readers for the game + - index has to be either 0 (for P1) or 1 (for P2) + - card_id has to be a valid 16-character hex string + +#### Coin +- get() + - returns the amount of unprocessed coins in queue + - not equal to the amount of coins shown ingame since the game may drain it +- set(amount: int) + - sets the amount of coins in queue for the game to process +- insert(amount: int) + - adds the amount to the coins in queue + - amount is optional and defaults to 1 +- blocker_get() + - returns the current coin blocker state (false: open, true: closed) + +#### Info +- avs() + - returns a dict including the AVS model, dest, spec, rev and ext +- launcher() + - returns a dict including the version, compile date/time, system time and + the arguments used to start the process +- memory() + - returns a dict including total, total used and bytes used by the process + for both physical and virtual RAM + +#### Keypads +For all functions in this module, the keypad parameter must be +either 0 (for P1) or 1 (for P2). Accepted keypad characters are "0" to "9" for +the single digit numbers, "A" for the double zero and "D" for the decimal key. +- write(keypad: uint, input: str) + - writes all characters in input sequentially to the keypad + - this should be used for things like PIN input +- set(keypad: uint, key: char, ...) + - clears all overrides, then applies each given key as override + - if a key is overridden, it shows up as pressed in-game +- get(keypad: uint) + - returns all pressed keys of the specified keypad + +#### Analogs/Buttons/Lights +All of those three modules have equally named methods for you to call. +- read() + - returns an array of state objects containing name, state and a bool + - the bool indicates if the object is active (e.g. the button was overridden) +- write([name: str, state: float], ...) + - applies the states as an override value + - the device binding via the config will be ignored while an override is set + - if an override value is set, the object will be marked as active +- write_reset([name: str], ...) + - removes the override value from the objects specified by name + - if no names were passed, all overrides will be removed + +#### Touch +- read() + - returns an array of state objects containing id, x and y +- write([id: uint, x: int, y: int], ...) + - adds the given touch points having an unknown ID + - overrides old touch points when the ID matches +- write_reset(id: uint, ...) + - removes the touch points matching one of the given IDs + +#### Control +This module only functions if a password is being used to communicate, +with the single exception of session_refresh(). +- raise(signal: str) + - raises a signal to the current process + - signal is a string and must be one of the following values: + "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", "SIGTERM" + - the signal will be raised while the message is being processed +- exit(code: int) + - code is optional and defaults to 0 + - the process will end while the message is being processed +- restart() + - spawns a new instance with the same arguments as passed to the main executable +- session_refresh() + - generates a new secure password and applies it after the response + - can be used to increase the security by using the password as some kind of + session token + - recommended to call directly after connecting and once in a while for + persistent connections +- shutdown() + - tries to force shutdown the computer +- reboot() + - tries to force reboot the computer + +#### Memory +This module only functions if a password is being used to communicate. +All offsets are specified in file offsets of the corresponding `dll_name`, +which also means that your hex edits are applicable directly. +- write(dll_name: str, data: hex, offset: uint) + - writes the bytes in data to the specified offset +- read(dll_name: str, offset: uint, size: uint) + - reads bytes starting from offset and returns it +- signature(dll_name: str, signature: hex, replacement: hex, offset: uint, + usage: uint) + - tries to find the signature in the module's memory + - unknown bytes are masked out via "??" (e.g. "75??90????74") + - masking out bytes works for both the signature and the replacement + - offset is the byte difference between the offset of the found signature and + the offset where the replacement data gets written to + - usage is the number of the result being used for replacement, starting at 0 + - returns the offset where the replacement data gets written to + - the replacement string can be empty, so you can only get the address of the + signature while not actually replacing anything + +#### IIDX +- ticker_get() + - returns a string of the characters displayed on the 16 segment display +- ticker_set(text: str) + - sets the contents of the 16 segment display and disables writes from game +- ticker_reset() + - re-enables writes from game + +#### LCD +- info() + - returns information about the serial LCD controller some games use + +## License +Unless otherwise noted, all files are licensed under the GPLv3. +See the LICENSE file for the full license text. +Files not originating from this project should be placed in "external", +they each have their own license. + +###### What that means for you +- If you want to distribute the binaries, you'll have to include the + sources, otherwise you're violating the GPL. +- If you want to merge some of this project's code into similar + software, that software has to be put under the GPL as well. + You'll probably have to modify a lot anyways, so you can just use the + source as some kind of documentation. diff --git a/acio/acio.h b/acio/acio.h index 7a0cb20..b2f1838 100644 --- a/acio/acio.h +++ b/acio/acio.h @@ -1,18 +1,18 @@ -#pragma once - -#include - -#include - -#include "module.h" - -namespace acio { - - // globals - extern HINSTANCE DLL_INSTANCE; - extern std::vector MODULES; - - void attach(); - void attach_icca(); - void detach(); -} +#pragma once + +#include + +#include + +#include "module.h" + +namespace acio { + + // globals + extern HINSTANCE DLL_INSTANCE; + extern std::vector MODULES; + + void attach(); + void attach_icca(); + void detach(); +} diff --git a/acio/bi2a/bi2a.cpp b/acio/bi2a/bi2a.cpp index 2f245aa..9a690f2 100644 --- a/acio/bi2a/bi2a.cpp +++ b/acio/bi2a/bi2a.cpp @@ -1,510 +1,510 @@ -#include "bi2a.h" - -#include "avs/game.h" -#include "games/ddr/io.h" -#include "games/sdvx/io.h" -#include "games/drs/io.h" -#include "games/drs/drs.h" -#include "misc/eamuse.h" -#include "util/logging.h" -#include "util/utils.h" - -using namespace GameAPI; - -// state -static uint8_t STATUS_BUFFER[272] {}; -static bool STATUS_BUFFER_FREEZE = false; -static unsigned int BI2A_VOLL = 0; -static unsigned int BI2A_VOLR = 0; - - -static bool __cdecl ac_io_bi2a_init_is_finished() { - return true; -} - -static bool __cdecl ac_io_bi2a_get_control_status_buffer(void *buffer) { - - // copy buffer - memcpy(buffer, STATUS_BUFFER, std::size(STATUS_BUFFER)); - return true; -} - -static bool __cdecl ac_io_bi2a_update_control_status_buffer() { - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // Sound Voltex - if (avs::game::is_model("KFC")) { - - // clear buffer - memset(STATUS_BUFFER, 0, std::size(STATUS_BUFFER)); - STATUS_BUFFER[0] = 1; - - /* - * Unmapped Buttons - * - * Control Bit - * EX BUTTON 1 93 - * EX BUTTON 2 92 - * EX ANALOG 1 170-183 - * EX ANALOG 2 186-199 - */ - - // get buttons - auto &buttons = games::sdvx::get_buttons(); - - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Test))) { - ARRAY_SETB(STATUS_BUFFER, 19); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Service))) { - ARRAY_SETB(STATUS_BUFFER, 18); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::CoinMech))) { - ARRAY_SETB(STATUS_BUFFER, 17); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Start))) { - ARRAY_SETB(STATUS_BUFFER, 85); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_A))) { - ARRAY_SETB(STATUS_BUFFER, 84); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_B))) { - ARRAY_SETB(STATUS_BUFFER, 83); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_C))) { - ARRAY_SETB(STATUS_BUFFER, 82); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_D))) { - ARRAY_SETB(STATUS_BUFFER, 81); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_L))) { - ARRAY_SETB(STATUS_BUFFER, 80); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_R))) { - ARRAY_SETB(STATUS_BUFFER, 95); - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Headphone))) { - ARRAY_SETB(STATUS_BUFFER, 87); - } - - // volume left - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Left))) { - BI2A_VOLL = (BI2A_VOLL - 16) & 1023; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Right))) { - BI2A_VOLL = (BI2A_VOLL + 16) & 1023; - } - - // volume right - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Left))) { - BI2A_VOLR = (BI2A_VOLR - 16) & 1023; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Right))) { - BI2A_VOLR = (BI2A_VOLR + 16) & 1023; - } - - // update volumes - auto &analogs = games::sdvx::get_analogs(); - auto vol_left = BI2A_VOLL; - auto vol_right = BI2A_VOLR; - if (analogs.at(0).isSet() || analogs.at(1).isSet()) { - vol_left += (unsigned int) (Analogs::getState(RI_MGR, - analogs.at(games::sdvx::Analogs::VOL_L)) * 1023.99f); - vol_right += (unsigned int) (Analogs::getState(RI_MGR, - analogs.at(games::sdvx::Analogs::VOL_R)) * 1023.99f); - } - - // proper loops - vol_left %= 1024; - vol_right %= 1024; - - // save volumes in buffer - *((uint16_t*) &STATUS_BUFFER[17]) = (uint16_t) ((vol_left) << 2); - *((uint16_t*) &STATUS_BUFFER[19]) = (uint16_t) ((vol_right) << 2); - } - - // DanceDanceRevolution - if (avs::game::is_model("MDX")) { - - // clear buffer - memset(STATUS_BUFFER, 0, std::size(STATUS_BUFFER)); - STATUS_BUFFER[0] = 1; - - // get buttons - auto &buttons = games::ddr::get_buttons(); - - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::COIN_MECH)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[2] |= 1 << 1; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::SERVICE)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[2] |= 1 << 2; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::TEST)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[2] |= 1 << 3; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_START)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[10] |= 1 << 7; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_UP)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[10] |= 1 << 6; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_DOWN)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[10] |= 1 << 5; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_LEFT)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[10] |= 1 << 4; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_RIGHT)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[10] |= 1 << 3; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_START)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[11] |= 1 << 5; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_UP)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[11] |= 1 << 4; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_DOWN)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[11] |= 1 << 3; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_LEFT)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[11] |= 1 << 2; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_RIGHT)) == Buttons::BUTTON_PRESSED) { - STATUS_BUFFER[11] |= 1 << 1; - } - } - - // DANCERUSH - if (avs::game::is_model("REC")) { - - // clear buffer - memset(STATUS_BUFFER, 0, std::size(STATUS_BUFFER)); - STATUS_BUFFER[0] = 1; - - // get buttons - auto &buttons = games::drs::get_buttons(); - - // test - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 19); - } - - // service - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 18); - } - - // coin - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::CoinMech)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 17); - } - - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Start)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 87); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Up)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 86); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Down)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 85); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Left)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 84); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Right)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 83); - } - - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Start)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 93); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Up)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 92); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Down)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 91); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Left)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 90); - } - if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Right)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 89); - } - } - - return true; -} - -static bool __cdecl ac_io_bi2a_current_coinstock(size_t index, DWORD *coins) { - - // check index - if (index > 1) - return false; - - // get coins and return success - *coins = (DWORD) eamuse_coin_get_stock(); - return true; -} - -static bool __cdecl ac_io_bi2a_consume_coinstock(size_t index, int amount) { - - // check index - if (index > 1) - return false; - - // calculate new stock - auto stock = eamuse_coin_get_stock(); - auto stock_new = stock - amount; - - // check new stock - if (stock_new < 0) - return false; - - // apply new stock - eamuse_coin_set_stock(stock_new); - return true; -} - -static bool __cdecl ac_io_bi2a_lock_coincounter(size_t index) { - - // check index - if (index > 1) - return false; - - // enable coin blocker - eamuse_coin_set_block(true); - return true; -} - -static bool __cdecl ac_io_bi2a_unlock_coincounter(size_t index) { - - // check index - if (index > 1) - return false; - - // disable coin blocker - eamuse_coin_set_block(false); - return true; -} - -static void __cdecl ac_io_bi2a_control_coin_blocker_close(size_t index) { - - // check index - if (index > 1) - return; - - // enable coin blocker - eamuse_coin_set_block(true); -} - -static void __cdecl ac_io_bi2a_control_coin_blocker_open(size_t index) { - - // check index - if (index > 1) - return; - - // disable coin blocker - eamuse_coin_set_block(false); -} - -static long __cdecl ac_io_bi2a_control_led_bright(size_t index, uint8_t brightness) { - - // Sound Voltex - if (avs::game::is_model("KFC")) { - - /* - * Control R G B - * ======================= - * WING UP 28 29 30 - * WING LOW 31 32 33 - * WOOFER 0 1 3 - * CONTROLLER 4 5 6 - * - * Values go up to 255. - * - * - * Control Index - * ================== - * START BUTTON 8 - * A BUTTON 9 - * B BUTTON 10 - * C BUTTON 11 - * D BUTTON 12 - * FX L BUTTON 13 - * FX R BUTTON 14 - * POP 24 - * TITLE LEFT 25 - * TITLE RIGHT 26 - * - * Values go up to 127. - */ - - static const struct { - int light1, light2; - float max; - } mapping[] = { - { games::sdvx::Lights::WOOFER_R, -1, 255 }, - { games::sdvx::Lights::WOOFER_G, -1, 255 }, - { -1, -1, 0 }, - { games::sdvx::Lights::WOOFER_B, -1, 255 }, - { games::sdvx::Lights::CONTROLLER_R, -1, 255 }, - { games::sdvx::Lights::CONTROLLER_G, -1, 255 }, - { games::sdvx::Lights::CONTROLLER_B, -1, 255 }, - { -1, -1, 0 }, - { games::sdvx::Lights::START, -1, 127 }, - { games::sdvx::Lights::BT_A, -1, 127 }, - { games::sdvx::Lights::BT_B, -1, 127 }, - { games::sdvx::Lights::BT_C, -1, 127 }, - { games::sdvx::Lights::BT_D, -1, 127 }, - { games::sdvx::Lights::FX_L, -1, 127 }, - { games::sdvx::Lights::FX_R, -1, 127 }, - { -1, -1, 0 }, { -1, -1, 0 }, { -1, -1, 0 }, - { games::sdvx::Lights::GENERATOR_R, -1, 255 }, - { games::sdvx::Lights::GENERATOR_G, -1, 255 }, - { games::sdvx::Lights::GENERATOR_B, -1, 255 }, - { -1, -1, 0 }, { -1, -1, 0 }, { -1, -1, 0 }, - { games::sdvx::Lights::POP, -1, 127 }, - { games::sdvx::Lights::TITLE_LEFT, -1, 127 }, - { games::sdvx::Lights::TITLE_RIGHT, -1, 127 }, - { -1, -1, 0 }, - { games::sdvx::Lights::WING_RIGHT_UP_R, games::sdvx::Lights::WING_LEFT_UP_R, 255 }, - { games::sdvx::Lights::WING_RIGHT_UP_G, games::sdvx::Lights::WING_LEFT_UP_G, 255 }, - { games::sdvx::Lights::WING_RIGHT_UP_B, games::sdvx::Lights::WING_LEFT_UP_B, 255 }, - { games::sdvx::Lights::WING_RIGHT_LOW_R, games::sdvx::Lights::WING_LEFT_LOW_R, 255 }, - { games::sdvx::Lights::WING_RIGHT_LOW_G, games::sdvx::Lights::WING_LEFT_LOW_G, 255 }, - { games::sdvx::Lights::WING_RIGHT_LOW_B, games::sdvx::Lights::WING_LEFT_LOW_B, 255 }, - }; - - // ignore index out of range - if (index > std::size(mapping)) { - return true; - } - - // get lights - auto &lights = games::sdvx::get_lights(); - - // get light from mapping - auto light = mapping[index]; - - // write lights - if (light.light1 >= 0) { - Lights::writeLight(RI_MGR, lights[light.light1], brightness / light.max); - } else { - log_warning("sdvx", "light unset {} {}", index, (int) brightness); - } - if (light.light2 >= 0) { - Lights::writeLight(RI_MGR, lights[light.light2], brightness / light.max); - } - } - - // return success - return true; -} - -static long __cdecl ac_io_bi2a_get_watchdog_time_min() { - return -1; -} - -static long __cdecl ac_io_bi2a_get_watchdog_time_now() { - return -1; -} - -static void __cdecl ac_io_bi2a_watchdog_off() { -} - -static bool __cdecl ac_io_bi2a_init(uint8_t param) { - return true; -} - -static bool __cdecl ac_io_bi2a_set_watchdog_time(uint16_t time) { - return true; -} - -static bool __cdecl ac_io_bi2a_get_watchdog_status() { - return true; -} - -static bool __cdecl ac_io_bi2a_set_amp_volume(uint8_t a1, uint8_t a2) { - return true; -} - -static bool __cdecl ac_io_bi2a_tapeled_init(uint8_t a1, uint8_t a2) { - return true; -} - -static bool __cdecl ac_io_bi2a_tapeled_init_is_finished() { - return true; -} - -static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_sz, size_t y_sz) { - - // check dimensions - if (x_sz != 38 || y_sz != 49) { - log_fatal("drs", "DRS tapeled wrong dimensions"); - } - - // copy data into our buffer - 4 bytes per pixel BGR - for (size_t i = 0; i < x_sz * y_sz; i++) { - games::drs::DRS_TAPELED[i][0] = data[i*4+2]; - games::drs::DRS_TAPELED[i][1] = data[i*4+1]; - games::drs::DRS_TAPELED[i][2] = data[i*4]; - } - - // success - return true; -} - -// TODO: this controls the upright RGB bars on the sides -static bool __cdecl ac_io_bi2a_control_tapeled_bright(size_t off1, size_t off2, - uint8_t r, uint8_t g, uint8_t b, uint8_t bank) { - return true; -} - -static bool __cdecl ac_io_bi2a_tapeled_send() { - return true; -} - -static int __cdecl ac_io_bi2a_get_exbio2_status(uint8_t *info) { - // surely this meme never gets old - info[5] = 5; - info[6] = 7; - info[7] = 3; - return 0; -} - -acio::BI2AModule::BI2AModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("BI2A", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::BI2AModule::attach() { - ACIOModule::attach(); - - ACIO_MODULE_HOOK(ac_io_bi2a_init_is_finished); - ACIO_MODULE_HOOK(ac_io_bi2a_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_bi2a_update_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_bi2a_current_coinstock); - ACIO_MODULE_HOOK(ac_io_bi2a_consume_coinstock); - ACIO_MODULE_HOOK(ac_io_bi2a_lock_coincounter); - ACIO_MODULE_HOOK(ac_io_bi2a_unlock_coincounter); - ACIO_MODULE_HOOK(ac_io_bi2a_control_coin_blocker_close); - ACIO_MODULE_HOOK(ac_io_bi2a_control_coin_blocker_open); - ACIO_MODULE_HOOK(ac_io_bi2a_control_led_bright); - ACIO_MODULE_HOOK(ac_io_bi2a_get_watchdog_time_min); - ACIO_MODULE_HOOK(ac_io_bi2a_get_watchdog_time_now); - ACIO_MODULE_HOOK(ac_io_bi2a_watchdog_off); - ACIO_MODULE_HOOK(ac_io_bi2a_init); - ACIO_MODULE_HOOK(ac_io_bi2a_set_watchdog_time); - ACIO_MODULE_HOOK(ac_io_bi2a_get_watchdog_status); - ACIO_MODULE_HOOK(ac_io_bi2a_set_amp_volume); - ACIO_MODULE_HOOK(ac_io_bi2a_tapeled_init); - ACIO_MODULE_HOOK(ac_io_bi2a_tapeled_init_is_finished); - ACIO_MODULE_HOOK(ac_io_bi2a_get_exbio2_status); - ACIO_MODULE_HOOK(ac_io_bi2a_control_tapeled_rec_set); - ACIO_MODULE_HOOK(ac_io_bi2a_control_tapeled_bright); - ACIO_MODULE_HOOK(ac_io_bi2a_tapeled_send); -} +#include "bi2a.h" + +#include "avs/game.h" +#include "games/ddr/io.h" +#include "games/sdvx/io.h" +#include "games/drs/io.h" +#include "games/drs/drs.h" +#include "misc/eamuse.h" +#include "util/logging.h" +#include "util/utils.h" + +using namespace GameAPI; + +// state +static uint8_t STATUS_BUFFER[272] {}; +static bool STATUS_BUFFER_FREEZE = false; +static unsigned int BI2A_VOLL = 0; +static unsigned int BI2A_VOLR = 0; + + +static bool __cdecl ac_io_bi2a_init_is_finished() { + return true; +} + +static bool __cdecl ac_io_bi2a_get_control_status_buffer(void *buffer) { + + // copy buffer + memcpy(buffer, STATUS_BUFFER, std::size(STATUS_BUFFER)); + return true; +} + +static bool __cdecl ac_io_bi2a_update_control_status_buffer() { + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // Sound Voltex + if (avs::game::is_model("KFC")) { + + // clear buffer + memset(STATUS_BUFFER, 0, std::size(STATUS_BUFFER)); + STATUS_BUFFER[0] = 1; + + /* + * Unmapped Buttons + * + * Control Bit + * EX BUTTON 1 93 + * EX BUTTON 2 92 + * EX ANALOG 1 170-183 + * EX ANALOG 2 186-199 + */ + + // get buttons + auto &buttons = games::sdvx::get_buttons(); + + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Test))) { + ARRAY_SETB(STATUS_BUFFER, 19); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Service))) { + ARRAY_SETB(STATUS_BUFFER, 18); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::CoinMech))) { + ARRAY_SETB(STATUS_BUFFER, 17); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Start))) { + ARRAY_SETB(STATUS_BUFFER, 85); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_A))) { + ARRAY_SETB(STATUS_BUFFER, 84); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_B))) { + ARRAY_SETB(STATUS_BUFFER, 83); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_C))) { + ARRAY_SETB(STATUS_BUFFER, 82); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_D))) { + ARRAY_SETB(STATUS_BUFFER, 81); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_L))) { + ARRAY_SETB(STATUS_BUFFER, 80); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_R))) { + ARRAY_SETB(STATUS_BUFFER, 95); + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Headphone))) { + ARRAY_SETB(STATUS_BUFFER, 87); + } + + // volume left + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Left))) { + BI2A_VOLL = (BI2A_VOLL - 16) & 1023; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Right))) { + BI2A_VOLL = (BI2A_VOLL + 16) & 1023; + } + + // volume right + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Left))) { + BI2A_VOLR = (BI2A_VOLR - 16) & 1023; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Right))) { + BI2A_VOLR = (BI2A_VOLR + 16) & 1023; + } + + // update volumes + auto &analogs = games::sdvx::get_analogs(); + auto vol_left = BI2A_VOLL; + auto vol_right = BI2A_VOLR; + if (analogs.at(0).isSet() || analogs.at(1).isSet()) { + vol_left += (unsigned int) (Analogs::getState(RI_MGR, + analogs.at(games::sdvx::Analogs::VOL_L)) * 1023.99f); + vol_right += (unsigned int) (Analogs::getState(RI_MGR, + analogs.at(games::sdvx::Analogs::VOL_R)) * 1023.99f); + } + + // proper loops + vol_left %= 1024; + vol_right %= 1024; + + // save volumes in buffer + *((uint16_t*) &STATUS_BUFFER[17]) = (uint16_t) ((vol_left) << 2); + *((uint16_t*) &STATUS_BUFFER[19]) = (uint16_t) ((vol_right) << 2); + } + + // DanceDanceRevolution + if (avs::game::is_model("MDX")) { + + // clear buffer + memset(STATUS_BUFFER, 0, std::size(STATUS_BUFFER)); + STATUS_BUFFER[0] = 1; + + // get buttons + auto &buttons = games::ddr::get_buttons(); + + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::COIN_MECH)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[2] |= 1 << 1; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::SERVICE)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[2] |= 1 << 2; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::TEST)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[2] |= 1 << 3; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_START)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[10] |= 1 << 7; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_UP)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[10] |= 1 << 6; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_DOWN)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[10] |= 1 << 5; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_LEFT)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[10] |= 1 << 4; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P1_MENU_RIGHT)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[10] |= 1 << 3; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_START)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[11] |= 1 << 5; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_UP)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[11] |= 1 << 4; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_DOWN)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[11] |= 1 << 3; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_LEFT)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[11] |= 1 << 2; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ddr::Buttons::P2_MENU_RIGHT)) == Buttons::BUTTON_PRESSED) { + STATUS_BUFFER[11] |= 1 << 1; + } + } + + // DANCERUSH + if (avs::game::is_model("REC")) { + + // clear buffer + memset(STATUS_BUFFER, 0, std::size(STATUS_BUFFER)); + STATUS_BUFFER[0] = 1; + + // get buttons + auto &buttons = games::drs::get_buttons(); + + // test + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 19); + } + + // service + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 18); + } + + // coin + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::CoinMech)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 17); + } + + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Start)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 87); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Up)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 86); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Down)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 85); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Left)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 84); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P1_Right)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 83); + } + + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Start)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 93); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Up)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 92); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Down)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 91); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Left)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 90); + } + if (Buttons::getState(RI_MGR, buttons.at(games::drs::Buttons::P2_Right)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 89); + } + } + + return true; +} + +static bool __cdecl ac_io_bi2a_current_coinstock(size_t index, DWORD *coins) { + + // check index + if (index > 1) + return false; + + // get coins and return success + *coins = (DWORD) eamuse_coin_get_stock(); + return true; +} + +static bool __cdecl ac_io_bi2a_consume_coinstock(size_t index, int amount) { + + // check index + if (index > 1) + return false; + + // calculate new stock + auto stock = eamuse_coin_get_stock(); + auto stock_new = stock - amount; + + // check new stock + if (stock_new < 0) + return false; + + // apply new stock + eamuse_coin_set_stock(stock_new); + return true; +} + +static bool __cdecl ac_io_bi2a_lock_coincounter(size_t index) { + + // check index + if (index > 1) + return false; + + // enable coin blocker + eamuse_coin_set_block(true); + return true; +} + +static bool __cdecl ac_io_bi2a_unlock_coincounter(size_t index) { + + // check index + if (index > 1) + return false; + + // disable coin blocker + eamuse_coin_set_block(false); + return true; +} + +static void __cdecl ac_io_bi2a_control_coin_blocker_close(size_t index) { + + // check index + if (index > 1) + return; + + // enable coin blocker + eamuse_coin_set_block(true); +} + +static void __cdecl ac_io_bi2a_control_coin_blocker_open(size_t index) { + + // check index + if (index > 1) + return; + + // disable coin blocker + eamuse_coin_set_block(false); +} + +static long __cdecl ac_io_bi2a_control_led_bright(size_t index, uint8_t brightness) { + + // Sound Voltex + if (avs::game::is_model("KFC")) { + + /* + * Control R G B + * ======================= + * WING UP 28 29 30 + * WING LOW 31 32 33 + * WOOFER 0 1 3 + * CONTROLLER 4 5 6 + * + * Values go up to 255. + * + * + * Control Index + * ================== + * START BUTTON 8 + * A BUTTON 9 + * B BUTTON 10 + * C BUTTON 11 + * D BUTTON 12 + * FX L BUTTON 13 + * FX R BUTTON 14 + * POP 24 + * TITLE LEFT 25 + * TITLE RIGHT 26 + * + * Values go up to 127. + */ + + static const struct { + int light1, light2; + float max; + } mapping[] = { + { games::sdvx::Lights::WOOFER_R, -1, 255 }, + { games::sdvx::Lights::WOOFER_G, -1, 255 }, + { -1, -1, 0 }, + { games::sdvx::Lights::WOOFER_B, -1, 255 }, + { games::sdvx::Lights::CONTROLLER_R, -1, 255 }, + { games::sdvx::Lights::CONTROLLER_G, -1, 255 }, + { games::sdvx::Lights::CONTROLLER_B, -1, 255 }, + { -1, -1, 0 }, + { games::sdvx::Lights::START, -1, 127 }, + { games::sdvx::Lights::BT_A, -1, 127 }, + { games::sdvx::Lights::BT_B, -1, 127 }, + { games::sdvx::Lights::BT_C, -1, 127 }, + { games::sdvx::Lights::BT_D, -1, 127 }, + { games::sdvx::Lights::FX_L, -1, 127 }, + { games::sdvx::Lights::FX_R, -1, 127 }, + { -1, -1, 0 }, { -1, -1, 0 }, { -1, -1, 0 }, + { games::sdvx::Lights::GENERATOR_R, -1, 255 }, + { games::sdvx::Lights::GENERATOR_G, -1, 255 }, + { games::sdvx::Lights::GENERATOR_B, -1, 255 }, + { -1, -1, 0 }, { -1, -1, 0 }, { -1, -1, 0 }, + { games::sdvx::Lights::POP, -1, 127 }, + { games::sdvx::Lights::TITLE_LEFT, -1, 127 }, + { games::sdvx::Lights::TITLE_RIGHT, -1, 127 }, + { -1, -1, 0 }, + { games::sdvx::Lights::WING_RIGHT_UP_R, games::sdvx::Lights::WING_LEFT_UP_R, 255 }, + { games::sdvx::Lights::WING_RIGHT_UP_G, games::sdvx::Lights::WING_LEFT_UP_G, 255 }, + { games::sdvx::Lights::WING_RIGHT_UP_B, games::sdvx::Lights::WING_LEFT_UP_B, 255 }, + { games::sdvx::Lights::WING_RIGHT_LOW_R, games::sdvx::Lights::WING_LEFT_LOW_R, 255 }, + { games::sdvx::Lights::WING_RIGHT_LOW_G, games::sdvx::Lights::WING_LEFT_LOW_G, 255 }, + { games::sdvx::Lights::WING_RIGHT_LOW_B, games::sdvx::Lights::WING_LEFT_LOW_B, 255 }, + }; + + // ignore index out of range + if (index > std::size(mapping)) { + return true; + } + + // get lights + auto &lights = games::sdvx::get_lights(); + + // get light from mapping + auto light = mapping[index]; + + // write lights + if (light.light1 >= 0) { + Lights::writeLight(RI_MGR, lights[light.light1], brightness / light.max); + } else { + log_warning("sdvx", "light unset {} {}", index, (int) brightness); + } + if (light.light2 >= 0) { + Lights::writeLight(RI_MGR, lights[light.light2], brightness / light.max); + } + } + + // return success + return true; +} + +static long __cdecl ac_io_bi2a_get_watchdog_time_min() { + return -1; +} + +static long __cdecl ac_io_bi2a_get_watchdog_time_now() { + return -1; +} + +static void __cdecl ac_io_bi2a_watchdog_off() { +} + +static bool __cdecl ac_io_bi2a_init(uint8_t param) { + return true; +} + +static bool __cdecl ac_io_bi2a_set_watchdog_time(uint16_t time) { + return true; +} + +static bool __cdecl ac_io_bi2a_get_watchdog_status() { + return true; +} + +static bool __cdecl ac_io_bi2a_set_amp_volume(uint8_t a1, uint8_t a2) { + return true; +} + +static bool __cdecl ac_io_bi2a_tapeled_init(uint8_t a1, uint8_t a2) { + return true; +} + +static bool __cdecl ac_io_bi2a_tapeled_init_is_finished() { + return true; +} + +static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_sz, size_t y_sz) { + + // check dimensions + if (x_sz != 38 || y_sz != 49) { + log_fatal("drs", "DRS tapeled wrong dimensions"); + } + + // copy data into our buffer - 4 bytes per pixel BGR + for (size_t i = 0; i < x_sz * y_sz; i++) { + games::drs::DRS_TAPELED[i][0] = data[i*4+2]; + games::drs::DRS_TAPELED[i][1] = data[i*4+1]; + games::drs::DRS_TAPELED[i][2] = data[i*4]; + } + + // success + return true; +} + +// TODO: this controls the upright RGB bars on the sides +static bool __cdecl ac_io_bi2a_control_tapeled_bright(size_t off1, size_t off2, + uint8_t r, uint8_t g, uint8_t b, uint8_t bank) { + return true; +} + +static bool __cdecl ac_io_bi2a_tapeled_send() { + return true; +} + +static int __cdecl ac_io_bi2a_get_exbio2_status(uint8_t *info) { + // surely this meme never gets old + info[5] = 5; + info[6] = 7; + info[7] = 3; + return 0; +} + +acio::BI2AModule::BI2AModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("BI2A", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::BI2AModule::attach() { + ACIOModule::attach(); + + ACIO_MODULE_HOOK(ac_io_bi2a_init_is_finished); + ACIO_MODULE_HOOK(ac_io_bi2a_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_bi2a_update_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_bi2a_current_coinstock); + ACIO_MODULE_HOOK(ac_io_bi2a_consume_coinstock); + ACIO_MODULE_HOOK(ac_io_bi2a_lock_coincounter); + ACIO_MODULE_HOOK(ac_io_bi2a_unlock_coincounter); + ACIO_MODULE_HOOK(ac_io_bi2a_control_coin_blocker_close); + ACIO_MODULE_HOOK(ac_io_bi2a_control_coin_blocker_open); + ACIO_MODULE_HOOK(ac_io_bi2a_control_led_bright); + ACIO_MODULE_HOOK(ac_io_bi2a_get_watchdog_time_min); + ACIO_MODULE_HOOK(ac_io_bi2a_get_watchdog_time_now); + ACIO_MODULE_HOOK(ac_io_bi2a_watchdog_off); + ACIO_MODULE_HOOK(ac_io_bi2a_init); + ACIO_MODULE_HOOK(ac_io_bi2a_set_watchdog_time); + ACIO_MODULE_HOOK(ac_io_bi2a_get_watchdog_status); + ACIO_MODULE_HOOK(ac_io_bi2a_set_amp_volume); + ACIO_MODULE_HOOK(ac_io_bi2a_tapeled_init); + ACIO_MODULE_HOOK(ac_io_bi2a_tapeled_init_is_finished); + ACIO_MODULE_HOOK(ac_io_bi2a_get_exbio2_status); + ACIO_MODULE_HOOK(ac_io_bi2a_control_tapeled_rec_set); + ACIO_MODULE_HOOK(ac_io_bi2a_control_tapeled_bright); + ACIO_MODULE_HOOK(ac_io_bi2a_tapeled_send); +} diff --git a/acio/bi2a/bi2a.h b/acio/bi2a/bi2a.h index 00bbc13..9aef074 100644 --- a/acio/bi2a/bi2a.h +++ b/acio/bi2a/bi2a.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class BI2AModule : public ACIOModule { - public: - BI2AModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class BI2AModule : public ACIOModule { + public: + BI2AModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/bmpu/bmpu.cpp b/acio/bmpu/bmpu.cpp index e55d5d4..c3e1f16 100644 --- a/acio/bmpu/bmpu.cpp +++ b/acio/bmpu/bmpu.cpp @@ -1,596 +1,596 @@ -#include "bmpu.h" - -#include "acio/icca/icca.h" -#include "avs/game.h" -#include "cfg/api.h" -#include "cfg/light.h" -#include "games/bbc/io.h" -#include "games/dea/io.h" -#include "games/ftt/io.h" -#include "games/museca/io.h" -#include "games/silentscope/io.h" -#include "launcher/launcher.h" -#include "misc/eamuse.h" - -using namespace GameAPI; - -// state -static uint8_t STATUS_BUFFER[64] {}; -static bool STATUS_BUFFER_FREEZE = false; - -/* - * Implementations - */ - -static char __cdecl ac_io_bmpu_consume_coinstock(int a1, int a2) { - eamuse_coin_consume_stock(); - return 1; -} - -static int __cdecl ac_io_bmpu_control_1p_start_led_off() { - - // dance evolution - if (avs::game::is_model("KDM")) { - auto &lights = games::dea::get_lights(); - Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f); - } - - return 1; -} - -static int __cdecl ac_io_bmpu_control_1p_start_led_on() { - - // dance evolution - if (avs::game::is_model("KDM")) { - auto &lights = games::dea::get_lights(); - Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f); - } - - return 1; -} - -static int __cdecl ac_io_bmpu_control_2p_start_led_off() { - - // dance evolution - if (avs::game::is_model("KDM")) { - auto &lights = games::dea::get_lights(); - Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f); - } - - return 1; -} - -static int __cdecl ac_io_bmpu_control_2p_start_led_on() { - - // dance evolution - if (avs::game::is_model("KDM")) { - auto &lights = games::dea::get_lights(); - Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f); - } - - return 1; -} - -static int __cdecl ac_io_bmpu_control_coin_blocker_close() { - eamuse_coin_set_block(true); - return 1; -} - -static int __cdecl ac_io_bmpu_control_coin_blocker_open() { - eamuse_coin_set_block(false); - return 1; -} - -static bool __cdecl ac_io_bmpu_control_led_bright(uint32_t led_field, uint8_t brightness) { - - // MUSECA - if (avs::game::is_model("PIX")) { - - // get lights - auto &lights = games::museca::get_lights(); - - // control mapping - static const int mapping[] = { - games::museca::Lights::UnderLED3G, - games::museca::Lights::UnderLED3R, - games::museca::Lights::UnderLED2B, - games::museca::Lights::UnderLED2G, - games::museca::Lights::UnderLED2R, - games::museca::Lights::UnderLED1B, - games::museca::Lights::UnderLED1G, - games::museca::Lights::UnderLED1R, - -1, -1, -1, -1, - games::museca::Lights::SideB, - games::museca::Lights::SideG, - games::museca::Lights::SideR, - games::museca::Lights::UnderLED3B, - }; - - // write light - float value = brightness > 127.f ? 1.f : brightness / 127.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (mapping[i] >= 0 && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); - } - } - } - - // BISHI BASHI CHANNEL - if (avs::game::is_model("R66")) { - - // get lights - auto &lights = games::bbc::get_lights(); - - // control mapping - static int mapping[] = { - games::bbc::Lights::UNDER_LED3_G, - games::bbc::Lights::UNDER_LED3_R, - games::bbc::Lights::UNDER_LED2_B, - games::bbc::Lights::UNDER_LED2_G, - games::bbc::Lights::UNDER_LED2_R, - games::bbc::Lights::UNDER_LED1_B, - games::bbc::Lights::UNDER_LED1_G, - games::bbc::Lights::UNDER_LED1_R, - -1, -1, -1, -1, - games::bbc::Lights::IC_CARD_B, - games::bbc::Lights::IC_CARD_G, - games::bbc::Lights::IC_CARD_R, - games::bbc::Lights::UNDER_LED3_B, - }; - - // write light - float value = brightness > 127.f ? 1.f : brightness / 127.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (mapping[i] >= 0 && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); - } - } - } - - // FutureTomTom - if (avs::game::is_model("MMD")) { - - // get lights - auto &lights = games::ftt::get_lights(); - - // control mapping - static int mapping[] = { - games::ftt::Lights::Pad3_G, - games::ftt::Lights::Pad3_R, - games::ftt::Lights::Pad2_B, - games::ftt::Lights::Pad2_G, - games::ftt::Lights::Pad2_R, - games::ftt::Lights::Pad1_B, - games::ftt::Lights::Pad1_G, - games::ftt::Lights::Pad1_R, - -1, -1, -1, -1, - games::ftt::Lights::Pad4_B, - games::ftt::Lights::Pad4_G, - games::ftt::Lights::Pad4_R, - games::ftt::Lights::Pad3_B, - }; - - // write light - float value = brightness > 127.f ? 1.f : brightness / 127.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (mapping[i] >= 0 && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); - } - } - } - - // Dance Evolution - if (avs::game::is_model("KDM")) { - - // get lights - auto &lights = games::dea::get_lights(); - - // control mapping - static int mapping[] = { - -1, - -1, - -1, - -1, - -1, - -1, - games::dea::Lights::P2LRButton, - games::dea::Lights::P1LRButton, - -1, - games::dea::Lights::TitleB, - games::dea::Lights::TitleR, - games::dea::Lights::TitleG, - -1, - }; - - // write light - float value = brightness > 128.f ? 1.f : brightness / 128.f; - for (size_t i = 0; i < std::size(mapping); i++) - if (mapping[i] >= 0 && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); - } - } - - // return success - return true; -} - -static bool __cdecl ac_io_bmpu_control_led_bright_pack(int a1, int a2, int a3) { - // TODO(felix): NDD lights - - return true; -} - -static bool __cdecl ac_io_bmpu_create_get_status_thread() { - return true; -} - -static char __cdecl ac_io_bmpu_current_coinstock(int a1, int *a2) { - *a2 = eamuse_coin_get_stock(); - return 1; -} - -static bool __cdecl ac_io_bmpu_destroy_get_status_thread() { - return true; -} - -static char __cdecl ac_io_bmpu_get_control_status_buffer(void *buffer) { - size_t buffer_len = 0; - - if (avs::game::is_model({ "KDM", "MMD" })) { - buffer_len = sizeof(STATUS_BUFFER); - } else if (avs::game::is_model("PIX")) { - buffer_len = 16; - } else if (avs::game::is_model("R66")) { - buffer_len = 56; - } else if (avs::game::is_model("NDD")) { - buffer_len = 56; - } - - if (buffer_len > 0) { - memcpy(buffer, &STATUS_BUFFER, buffer_len); - } - - // success - return true; -} - -static char *__cdecl ac_io_bmpu_get_softwareid(char *a1) { - *a1 = 0; - return a1; -} - -static char *__cdecl ac_io_bmpu_get_systemid(char *a1) { - *a1 = 0; - return a1; -} - -static char __cdecl ac_io_bmpu_init_outport() { - return 1; -} - -static char __cdecl ac_io_bmpu_lock_coincounter(signed int a1) { - return 1; -} - -static char __cdecl ac_io_bmpu_req_secplug_check_isfinished(DWORD *a1) { - return 1; -} - -static char __cdecl ac_io_bmpu_req_secplug_check_softwareplug(char *a1) { - return 1; -} - -static char __cdecl ac_io_bmpu_req_secplug_check_systemplug() { - return 1; -} - -static char __cdecl ac_io_bmpu_req_secplug_missing_check() { - return 1; -} - -static int __cdecl ac_io_bmpu_req_secplug_missing_check_isfinished(DWORD *a1) { - return 1; -} - -static int __cdecl ac_io_bmpu_set_outport_led(uint8_t *data1, uint8_t *data2) { - - // dance evolution - if (avs::game::is_model("KDM")) { - - // get lights - auto &lights = games::dea::get_lights(); - - // mapping - static const size_t mapping[] { - games::dea::Lights::SideUpperLeftR, - games::dea::Lights::SideUpperLeftG, - games::dea::Lights::SideUpperLeftB, - games::dea::Lights::SideLowerLeft1R, - games::dea::Lights::SideLowerLeft1G, - games::dea::Lights::SideLowerLeft1B, - games::dea::Lights::SideLowerLeft2R, - games::dea::Lights::SideLowerLeft2G, - games::dea::Lights::SideLowerLeft2B, - games::dea::Lights::SideLowerLeft3R, - games::dea::Lights::SideLowerLeft3G, - games::dea::Lights::SideLowerLeft3B, - games::dea::Lights::SideUpperRightR, - games::dea::Lights::SideUpperRightG, - games::dea::Lights::SideUpperRightB, - games::dea::Lights::SideLowerRight1R, - games::dea::Lights::SideLowerRight1G, - games::dea::Lights::SideLowerRight1B, - games::dea::Lights::SideLowerRight2R, - games::dea::Lights::SideLowerRight2G, - games::dea::Lights::SideLowerRight2B, - games::dea::Lights::SideLowerRight3R, - games::dea::Lights::SideLowerRight3G, - games::dea::Lights::SideLowerRight3B, - }; - - // write lights - for (size_t i = 0; i < std::size(mapping); i++) { - float brightness = data1[i * 2] / 255.f; - Lights::writeLight(RI_MGR, lights.at(mapping[i]), brightness); - } - } - - // success - return true; -} - -static int __cdecl ac_io_bmpu_set_output_mode(__int16 a1) { - return 1; -} - -static char __cdecl ac_io_bmpu_unlock_coincounter(int a1) { - return 1; -} - -static bool __cdecl ac_io_bmpu_update_control_status_buffer() { - unsigned int control_data = 0; - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // DEA - if (avs::game::is_model("KDM")) { - - // keypad mirror fix - acio::ICCA_FLIP_ROWS = true; - - // get buttons - auto &buttons = games::dea::get_buttons(); - - // get control data - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::Test))) { - control_data |= 0xF0000000; - } - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::Service))) { - control_data |= 0x0F000000; - } - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P1Start))) { - control_data |= 0x00000001; - } - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P1Left))) { - control_data |= 0x00000008; - } - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P1Right))) { - control_data |= 0x00000010; - } - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P2Start))) { - control_data |= 0x00000100; - } - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P2Left))) { - control_data |= 0x00000800; - } - if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P2Right))) { - control_data |= 0x00001000; - } - - // set control data - auto buffer = reinterpret_cast(STATUS_BUFFER); - for (size_t i = 0; i < 16; i++) { - buffer[i] = control_data; - } - } - - // FutureTomTom - if (avs::game::is_model("MMD")) { - - // keypad mirror fix - acio::ICCA_FLIP_ROWS = true; - - // get buttons - auto &buttons = games::ftt::get_buttons(); - - // get control data - if (Buttons::getState(RI_MGR, buttons.at(games::ftt::Buttons::Service))) { - control_data |= 0x0F000000; - } - if (Buttons::getState(RI_MGR, buttons.at(games::ftt::Buttons::Test))) { - control_data |= 0xF0000000; - } - - // set control data - auto buffer = reinterpret_cast(STATUS_BUFFER); - for (size_t i = 0; i < 16; i++) { - buffer[i] = control_data; - } - } - - // MUSECA - if (avs::game::is_model("PIX")) { - - // get buttons - auto &buttons = games::museca::get_buttons(); - - // get control data - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Service))) { - control_data |= 0x0F000000; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Test))) { - control_data |= 0xF0000000; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Start))) { - control_data |= 0x00000001; - } - - // set control data - auto buffer = reinterpret_cast(STATUS_BUFFER); - for (size_t i = 0; i < 4; i++) { - buffer[i] = control_data; - } - } - - // BISHI BASHI CHANNEL - if (avs::game::is_model("R66")) { - - // get buttons - auto &buttons = games::bbc::get_buttons(); - - // get control data - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::Service))) { - control_data |= 0x0F000000; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::Test))) { - control_data |= 0xF0000000; - } - - // set control data - auto buffer = reinterpret_cast(STATUS_BUFFER); - for (size_t i = 0; i < 4; i++) { - buffer[i] = control_data; - } - } - - // Silent Scope Bone Eater - if (avs::game::is_model("NDD")) { - - // clear state - memset(STATUS_BUFFER, 0, 56); - - // get buttons - auto &buttons = games::silentscope::get_buttons(); - - // get control data - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::TEST))) { - STATUS_BUFFER[7] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::SERVICE))) { - STATUS_BUFFER[7] |= 0x2; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::COIN_MECH))) { - STATUS_BUFFER[7] |= 0x1; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::START))) { - STATUS_BUFFER[5] |= 0x1; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::UP))) { - STATUS_BUFFER[5] |= 0x2; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::DOWN))) { - STATUS_BUFFER[5] |= 0x4; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::LEFT))) { - STATUS_BUFFER[5] |= 0x8; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::RIGHT))) { - STATUS_BUFFER[5] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::SCOPE_RIGHT))) { - STATUS_BUFFER[4] |= 0x80; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::SCOPE_LEFT))) { - STATUS_BUFFER[4] |= 0x40; - } - if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::GUN_PRESSED))) { - STATUS_BUFFER[4] |= 0x20; - } - - // joy stick raw input - auto &analogs = games::silentscope::get_analogs(); - unsigned short joy_x = 0x7FFF; - unsigned short joy_y = 0x7FFF; - if (analogs.at(games::silentscope::Analogs::GUN_X).isSet()) { - joy_x = (unsigned short) (Analogs::getState(RI_MGR, analogs.at(games::silentscope::Analogs::GUN_X)) * USHRT_MAX); - } - if (analogs.at(games::silentscope::Analogs::GUN_Y).isSet()) { - joy_y = (unsigned short) (Analogs::getState(RI_MGR, analogs.at(games::silentscope::Analogs::GUN_Y)) * USHRT_MAX); - } - - // invert X axis - joy_x = USHRT_MAX - joy_x; - - STATUS_BUFFER[8] = HIBYTE(joy_x); - STATUS_BUFFER[9] = LOBYTE(joy_x); - STATUS_BUFFER[10] = HIBYTE(joy_y); - STATUS_BUFFER[11] = LOBYTE(joy_y); - } - - // success - return true; -} - -static bool __cdecl ac_io_bmpu_set_watchdog_time(char a1) { - return true; -} - -static char __cdecl ac_io_bmpu_get_watchdog_time_min() { - return 0; -} - -static char __cdecl ac_io_bmpu_get_watchdog_time_now() { - return 0; -} - -static void __cdecl ac_io_bmpu_watchdog_off() { -} - -/* - * Module stuff - */ - -acio::BMPUModule::BMPUModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("BMPU", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::BMPUModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_bmpu_consume_coinstock); - ACIO_MODULE_HOOK(ac_io_bmpu_control_1p_start_led_off); - ACIO_MODULE_HOOK(ac_io_bmpu_control_1p_start_led_on); - ACIO_MODULE_HOOK(ac_io_bmpu_control_2p_start_led_off); - ACIO_MODULE_HOOK(ac_io_bmpu_control_2p_start_led_on); - ACIO_MODULE_HOOK(ac_io_bmpu_control_coin_blocker_close); - ACIO_MODULE_HOOK(ac_io_bmpu_control_coin_blocker_open); - ACIO_MODULE_HOOK(ac_io_bmpu_control_led_bright); - ACIO_MODULE_HOOK(ac_io_bmpu_control_led_bright_pack); - ACIO_MODULE_HOOK(ac_io_bmpu_create_get_status_thread); - ACIO_MODULE_HOOK(ac_io_bmpu_current_coinstock); - ACIO_MODULE_HOOK(ac_io_bmpu_destroy_get_status_thread); - ACIO_MODULE_HOOK(ac_io_bmpu_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_bmpu_get_softwareid); - ACIO_MODULE_HOOK(ac_io_bmpu_get_systemid); - ACIO_MODULE_HOOK(ac_io_bmpu_init_outport); - ACIO_MODULE_HOOK(ac_io_bmpu_lock_coincounter); - ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_check_isfinished); - ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_check_softwareplug); - ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_check_systemplug); - ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_missing_check); - ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_missing_check_isfinished); - ACIO_MODULE_HOOK(ac_io_bmpu_set_outport_led); - ACIO_MODULE_HOOK(ac_io_bmpu_set_output_mode); - ACIO_MODULE_HOOK(ac_io_bmpu_unlock_coincounter); - ACIO_MODULE_HOOK(ac_io_bmpu_update_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_bmpu_set_watchdog_time); - ACIO_MODULE_HOOK(ac_io_bmpu_get_watchdog_time_min); - ACIO_MODULE_HOOK(ac_io_bmpu_get_watchdog_time_now); - ACIO_MODULE_HOOK(ac_io_bmpu_watchdog_off); -} +#include "bmpu.h" + +#include "acio/icca/icca.h" +#include "avs/game.h" +#include "cfg/api.h" +#include "cfg/light.h" +#include "games/bbc/io.h" +#include "games/dea/io.h" +#include "games/ftt/io.h" +#include "games/museca/io.h" +#include "games/silentscope/io.h" +#include "launcher/launcher.h" +#include "misc/eamuse.h" + +using namespace GameAPI; + +// state +static uint8_t STATUS_BUFFER[64] {}; +static bool STATUS_BUFFER_FREEZE = false; + +/* + * Implementations + */ + +static char __cdecl ac_io_bmpu_consume_coinstock(int a1, int a2) { + eamuse_coin_consume_stock(); + return 1; +} + +static int __cdecl ac_io_bmpu_control_1p_start_led_off() { + + // dance evolution + if (avs::game::is_model("KDM")) { + auto &lights = games::dea::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f); + } + + return 1; +} + +static int __cdecl ac_io_bmpu_control_1p_start_led_on() { + + // dance evolution + if (avs::game::is_model("KDM")) { + auto &lights = games::dea::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f); + } + + return 1; +} + +static int __cdecl ac_io_bmpu_control_2p_start_led_off() { + + // dance evolution + if (avs::game::is_model("KDM")) { + auto &lights = games::dea::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f); + } + + return 1; +} + +static int __cdecl ac_io_bmpu_control_2p_start_led_on() { + + // dance evolution + if (avs::game::is_model("KDM")) { + auto &lights = games::dea::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f); + } + + return 1; +} + +static int __cdecl ac_io_bmpu_control_coin_blocker_close() { + eamuse_coin_set_block(true); + return 1; +} + +static int __cdecl ac_io_bmpu_control_coin_blocker_open() { + eamuse_coin_set_block(false); + return 1; +} + +static bool __cdecl ac_io_bmpu_control_led_bright(uint32_t led_field, uint8_t brightness) { + + // MUSECA + if (avs::game::is_model("PIX")) { + + // get lights + auto &lights = games::museca::get_lights(); + + // control mapping + static const int mapping[] = { + games::museca::Lights::UnderLED3G, + games::museca::Lights::UnderLED3R, + games::museca::Lights::UnderLED2B, + games::museca::Lights::UnderLED2G, + games::museca::Lights::UnderLED2R, + games::museca::Lights::UnderLED1B, + games::museca::Lights::UnderLED1G, + games::museca::Lights::UnderLED1R, + -1, -1, -1, -1, + games::museca::Lights::SideB, + games::museca::Lights::SideG, + games::museca::Lights::SideR, + games::museca::Lights::UnderLED3B, + }; + + // write light + float value = brightness > 127.f ? 1.f : brightness / 127.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (mapping[i] >= 0 && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); + } + } + } + + // BISHI BASHI CHANNEL + if (avs::game::is_model("R66")) { + + // get lights + auto &lights = games::bbc::get_lights(); + + // control mapping + static int mapping[] = { + games::bbc::Lights::UNDER_LED3_G, + games::bbc::Lights::UNDER_LED3_R, + games::bbc::Lights::UNDER_LED2_B, + games::bbc::Lights::UNDER_LED2_G, + games::bbc::Lights::UNDER_LED2_R, + games::bbc::Lights::UNDER_LED1_B, + games::bbc::Lights::UNDER_LED1_G, + games::bbc::Lights::UNDER_LED1_R, + -1, -1, -1, -1, + games::bbc::Lights::IC_CARD_B, + games::bbc::Lights::IC_CARD_G, + games::bbc::Lights::IC_CARD_R, + games::bbc::Lights::UNDER_LED3_B, + }; + + // write light + float value = brightness > 127.f ? 1.f : brightness / 127.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (mapping[i] >= 0 && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); + } + } + } + + // FutureTomTom + if (avs::game::is_model("MMD")) { + + // get lights + auto &lights = games::ftt::get_lights(); + + // control mapping + static int mapping[] = { + games::ftt::Lights::Pad3_G, + games::ftt::Lights::Pad3_R, + games::ftt::Lights::Pad2_B, + games::ftt::Lights::Pad2_G, + games::ftt::Lights::Pad2_R, + games::ftt::Lights::Pad1_B, + games::ftt::Lights::Pad1_G, + games::ftt::Lights::Pad1_R, + -1, -1, -1, -1, + games::ftt::Lights::Pad4_B, + games::ftt::Lights::Pad4_G, + games::ftt::Lights::Pad4_R, + games::ftt::Lights::Pad3_B, + }; + + // write light + float value = brightness > 127.f ? 1.f : brightness / 127.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (mapping[i] >= 0 && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); + } + } + } + + // Dance Evolution + if (avs::game::is_model("KDM")) { + + // get lights + auto &lights = games::dea::get_lights(); + + // control mapping + static int mapping[] = { + -1, + -1, + -1, + -1, + -1, + -1, + games::dea::Lights::P2LRButton, + games::dea::Lights::P1LRButton, + -1, + games::dea::Lights::TitleB, + games::dea::Lights::TitleR, + games::dea::Lights::TitleG, + -1, + }; + + // write light + float value = brightness > 128.f ? 1.f : brightness / 128.f; + for (size_t i = 0; i < std::size(mapping); i++) + if (mapping[i] >= 0 && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); + } + } + + // return success + return true; +} + +static bool __cdecl ac_io_bmpu_control_led_bright_pack(int a1, int a2, int a3) { + // TODO(felix): NDD lights + + return true; +} + +static bool __cdecl ac_io_bmpu_create_get_status_thread() { + return true; +} + +static char __cdecl ac_io_bmpu_current_coinstock(int a1, int *a2) { + *a2 = eamuse_coin_get_stock(); + return 1; +} + +static bool __cdecl ac_io_bmpu_destroy_get_status_thread() { + return true; +} + +static char __cdecl ac_io_bmpu_get_control_status_buffer(void *buffer) { + size_t buffer_len = 0; + + if (avs::game::is_model({ "KDM", "MMD" })) { + buffer_len = sizeof(STATUS_BUFFER); + } else if (avs::game::is_model("PIX")) { + buffer_len = 16; + } else if (avs::game::is_model("R66")) { + buffer_len = 56; + } else if (avs::game::is_model("NDD")) { + buffer_len = 56; + } + + if (buffer_len > 0) { + memcpy(buffer, &STATUS_BUFFER, buffer_len); + } + + // success + return true; +} + +static char *__cdecl ac_io_bmpu_get_softwareid(char *a1) { + *a1 = 0; + return a1; +} + +static char *__cdecl ac_io_bmpu_get_systemid(char *a1) { + *a1 = 0; + return a1; +} + +static char __cdecl ac_io_bmpu_init_outport() { + return 1; +} + +static char __cdecl ac_io_bmpu_lock_coincounter(signed int a1) { + return 1; +} + +static char __cdecl ac_io_bmpu_req_secplug_check_isfinished(DWORD *a1) { + return 1; +} + +static char __cdecl ac_io_bmpu_req_secplug_check_softwareplug(char *a1) { + return 1; +} + +static char __cdecl ac_io_bmpu_req_secplug_check_systemplug() { + return 1; +} + +static char __cdecl ac_io_bmpu_req_secplug_missing_check() { + return 1; +} + +static int __cdecl ac_io_bmpu_req_secplug_missing_check_isfinished(DWORD *a1) { + return 1; +} + +static int __cdecl ac_io_bmpu_set_outport_led(uint8_t *data1, uint8_t *data2) { + + // dance evolution + if (avs::game::is_model("KDM")) { + + // get lights + auto &lights = games::dea::get_lights(); + + // mapping + static const size_t mapping[] { + games::dea::Lights::SideUpperLeftR, + games::dea::Lights::SideUpperLeftG, + games::dea::Lights::SideUpperLeftB, + games::dea::Lights::SideLowerLeft1R, + games::dea::Lights::SideLowerLeft1G, + games::dea::Lights::SideLowerLeft1B, + games::dea::Lights::SideLowerLeft2R, + games::dea::Lights::SideLowerLeft2G, + games::dea::Lights::SideLowerLeft2B, + games::dea::Lights::SideLowerLeft3R, + games::dea::Lights::SideLowerLeft3G, + games::dea::Lights::SideLowerLeft3B, + games::dea::Lights::SideUpperRightR, + games::dea::Lights::SideUpperRightG, + games::dea::Lights::SideUpperRightB, + games::dea::Lights::SideLowerRight1R, + games::dea::Lights::SideLowerRight1G, + games::dea::Lights::SideLowerRight1B, + games::dea::Lights::SideLowerRight2R, + games::dea::Lights::SideLowerRight2G, + games::dea::Lights::SideLowerRight2B, + games::dea::Lights::SideLowerRight3R, + games::dea::Lights::SideLowerRight3G, + games::dea::Lights::SideLowerRight3B, + }; + + // write lights + for (size_t i = 0; i < std::size(mapping); i++) { + float brightness = data1[i * 2] / 255.f; + Lights::writeLight(RI_MGR, lights.at(mapping[i]), brightness); + } + } + + // success + return true; +} + +static int __cdecl ac_io_bmpu_set_output_mode(__int16 a1) { + return 1; +} + +static char __cdecl ac_io_bmpu_unlock_coincounter(int a1) { + return 1; +} + +static bool __cdecl ac_io_bmpu_update_control_status_buffer() { + unsigned int control_data = 0; + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // DEA + if (avs::game::is_model("KDM")) { + + // keypad mirror fix + acio::ICCA_FLIP_ROWS = true; + + // get buttons + auto &buttons = games::dea::get_buttons(); + + // get control data + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::Test))) { + control_data |= 0xF0000000; + } + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::Service))) { + control_data |= 0x0F000000; + } + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P1Start))) { + control_data |= 0x00000001; + } + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P1Left))) { + control_data |= 0x00000008; + } + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P1Right))) { + control_data |= 0x00000010; + } + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P2Start))) { + control_data |= 0x00000100; + } + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P2Left))) { + control_data |= 0x00000800; + } + if (Buttons::getState(RI_MGR, buttons.at(games::dea::Buttons::P2Right))) { + control_data |= 0x00001000; + } + + // set control data + auto buffer = reinterpret_cast(STATUS_BUFFER); + for (size_t i = 0; i < 16; i++) { + buffer[i] = control_data; + } + } + + // FutureTomTom + if (avs::game::is_model("MMD")) { + + // keypad mirror fix + acio::ICCA_FLIP_ROWS = true; + + // get buttons + auto &buttons = games::ftt::get_buttons(); + + // get control data + if (Buttons::getState(RI_MGR, buttons.at(games::ftt::Buttons::Service))) { + control_data |= 0x0F000000; + } + if (Buttons::getState(RI_MGR, buttons.at(games::ftt::Buttons::Test))) { + control_data |= 0xF0000000; + } + + // set control data + auto buffer = reinterpret_cast(STATUS_BUFFER); + for (size_t i = 0; i < 16; i++) { + buffer[i] = control_data; + } + } + + // MUSECA + if (avs::game::is_model("PIX")) { + + // get buttons + auto &buttons = games::museca::get_buttons(); + + // get control data + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Service))) { + control_data |= 0x0F000000; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Test))) { + control_data |= 0xF0000000; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Start))) { + control_data |= 0x00000001; + } + + // set control data + auto buffer = reinterpret_cast(STATUS_BUFFER); + for (size_t i = 0; i < 4; i++) { + buffer[i] = control_data; + } + } + + // BISHI BASHI CHANNEL + if (avs::game::is_model("R66")) { + + // get buttons + auto &buttons = games::bbc::get_buttons(); + + // get control data + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::Service))) { + control_data |= 0x0F000000; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::Test))) { + control_data |= 0xF0000000; + } + + // set control data + auto buffer = reinterpret_cast(STATUS_BUFFER); + for (size_t i = 0; i < 4; i++) { + buffer[i] = control_data; + } + } + + // Silent Scope Bone Eater + if (avs::game::is_model("NDD")) { + + // clear state + memset(STATUS_BUFFER, 0, 56); + + // get buttons + auto &buttons = games::silentscope::get_buttons(); + + // get control data + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::TEST))) { + STATUS_BUFFER[7] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::SERVICE))) { + STATUS_BUFFER[7] |= 0x2; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::COIN_MECH))) { + STATUS_BUFFER[7] |= 0x1; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::START))) { + STATUS_BUFFER[5] |= 0x1; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::UP))) { + STATUS_BUFFER[5] |= 0x2; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::DOWN))) { + STATUS_BUFFER[5] |= 0x4; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::LEFT))) { + STATUS_BUFFER[5] |= 0x8; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::RIGHT))) { + STATUS_BUFFER[5] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::SCOPE_RIGHT))) { + STATUS_BUFFER[4] |= 0x80; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::SCOPE_LEFT))) { + STATUS_BUFFER[4] |= 0x40; + } + if (Buttons::getState(RI_MGR, buttons.at(games::silentscope::Buttons::GUN_PRESSED))) { + STATUS_BUFFER[4] |= 0x20; + } + + // joy stick raw input + auto &analogs = games::silentscope::get_analogs(); + unsigned short joy_x = 0x7FFF; + unsigned short joy_y = 0x7FFF; + if (analogs.at(games::silentscope::Analogs::GUN_X).isSet()) { + joy_x = (unsigned short) (Analogs::getState(RI_MGR, analogs.at(games::silentscope::Analogs::GUN_X)) * USHRT_MAX); + } + if (analogs.at(games::silentscope::Analogs::GUN_Y).isSet()) { + joy_y = (unsigned short) (Analogs::getState(RI_MGR, analogs.at(games::silentscope::Analogs::GUN_Y)) * USHRT_MAX); + } + + // invert X axis + joy_x = USHRT_MAX - joy_x; + + STATUS_BUFFER[8] = HIBYTE(joy_x); + STATUS_BUFFER[9] = LOBYTE(joy_x); + STATUS_BUFFER[10] = HIBYTE(joy_y); + STATUS_BUFFER[11] = LOBYTE(joy_y); + } + + // success + return true; +} + +static bool __cdecl ac_io_bmpu_set_watchdog_time(char a1) { + return true; +} + +static char __cdecl ac_io_bmpu_get_watchdog_time_min() { + return 0; +} + +static char __cdecl ac_io_bmpu_get_watchdog_time_now() { + return 0; +} + +static void __cdecl ac_io_bmpu_watchdog_off() { +} + +/* + * Module stuff + */ + +acio::BMPUModule::BMPUModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("BMPU", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::BMPUModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_bmpu_consume_coinstock); + ACIO_MODULE_HOOK(ac_io_bmpu_control_1p_start_led_off); + ACIO_MODULE_HOOK(ac_io_bmpu_control_1p_start_led_on); + ACIO_MODULE_HOOK(ac_io_bmpu_control_2p_start_led_off); + ACIO_MODULE_HOOK(ac_io_bmpu_control_2p_start_led_on); + ACIO_MODULE_HOOK(ac_io_bmpu_control_coin_blocker_close); + ACIO_MODULE_HOOK(ac_io_bmpu_control_coin_blocker_open); + ACIO_MODULE_HOOK(ac_io_bmpu_control_led_bright); + ACIO_MODULE_HOOK(ac_io_bmpu_control_led_bright_pack); + ACIO_MODULE_HOOK(ac_io_bmpu_create_get_status_thread); + ACIO_MODULE_HOOK(ac_io_bmpu_current_coinstock); + ACIO_MODULE_HOOK(ac_io_bmpu_destroy_get_status_thread); + ACIO_MODULE_HOOK(ac_io_bmpu_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_bmpu_get_softwareid); + ACIO_MODULE_HOOK(ac_io_bmpu_get_systemid); + ACIO_MODULE_HOOK(ac_io_bmpu_init_outport); + ACIO_MODULE_HOOK(ac_io_bmpu_lock_coincounter); + ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_check_isfinished); + ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_check_softwareplug); + ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_check_systemplug); + ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_missing_check); + ACIO_MODULE_HOOK(ac_io_bmpu_req_secplug_missing_check_isfinished); + ACIO_MODULE_HOOK(ac_io_bmpu_set_outport_led); + ACIO_MODULE_HOOK(ac_io_bmpu_set_output_mode); + ACIO_MODULE_HOOK(ac_io_bmpu_unlock_coincounter); + ACIO_MODULE_HOOK(ac_io_bmpu_update_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_bmpu_set_watchdog_time); + ACIO_MODULE_HOOK(ac_io_bmpu_get_watchdog_time_min); + ACIO_MODULE_HOOK(ac_io_bmpu_get_watchdog_time_now); + ACIO_MODULE_HOOK(ac_io_bmpu_watchdog_off); +} diff --git a/acio/bmpu/bmpu.h b/acio/bmpu/bmpu.h index f074ac2..8ef0b94 100644 --- a/acio/bmpu/bmpu.h +++ b/acio/bmpu/bmpu.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class BMPUModule : public ACIOModule { - public: - BMPUModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class BMPUModule : public ACIOModule { + public: + BMPUModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/core/core.cpp b/acio/core/core.cpp index 13991df..5e6313c 100644 --- a/acio/core/core.cpp +++ b/acio/core/core.cpp @@ -1,190 +1,190 @@ -#include "core.h" - -#include "avs/game.h" -#include "launcher/launcher.h" -#include "misc/wintouchemu.h" -#include "rawinput/rawinput.h" - -// static stuff -static int ACIO_WARMUP = 0; -static HHOOK ACIO_KB_HOOK = nullptr; - -/* - * Implementations - */ - -// needed for some games to make GetAsyncKeyState() working -static LRESULT CALLBACK ac_io_kb_hook_callback(int nCode, WPARAM wParam, LPARAM lParam) { - CallNextHookEx(ACIO_KB_HOOK, nCode, wParam, lParam); - return 0; -} - -static char __cdecl ac_io_begin( - size_t dev, - const char *ver, - unsigned int *val, - size_t flags, - void *ptr, - size_t baud) -{ - if (ACIO_KB_HOOK == nullptr) { - ACIO_KB_HOOK = SetWindowsHookEx(WH_KEYBOARD_LL, ac_io_kb_hook_callback, GetModuleHandle(nullptr), 0); - } - - // always return success - if (val && avs::game::is_model("KFC")) { - *val = 2; - } - - return 1; -} - -static char __cdecl ac_io_begin_get_status() { - return 1; -} - -static int __cdecl ac_io_end(int a1) { - return 1; -} - -static int __cdecl ac_io_end_get_status(int a1) { - return 1; -} - -static void *__cdecl ac_io_get_rs232c_status(char *a1, int a2) { - return memset(a1, 0, 88); -} - -static char __cdecl ac_io_get_version(uint8_t *a1, int a2) { - - // some games have version checks - // pop'n music only accepts versions bigger than 1.X.X (check yourself), anything starting with 2 works though - memset(a1 + 5, 2, 1); - memset(a1 + 6, 0, 1); - memset(a1 + 7, 0, 1); - - return 1; -} - -static const char *__cdecl ac_io_get_version_string() { - static const char *version = "1.25.0"; - return version; -} - -static char __cdecl ac_io_is_active(int a1, int a2) { - if (a1 == 1 && avs::game::is_model("JMA")) { - return 1; - } - - return (char) (++ACIO_WARMUP > 601 ? 1 : 0); -} - -static int __cdecl ac_io_is_active2(int a1, int *a2, int a3) { - ACIO_WARMUP = 601; - *a2 = 6; - return 1; -} - -static char __cdecl ac_io_is_active_device(int index, int a2) { - - // for scotto - static bool CHECKED_24 = false; - - // dance evolution - if (avs::game::is_model("KDM")) { - - // disable mysterious LED devices - if (index >= 12 && index <= 15) - return false; - } - - // scotto - if (avs::game::is_model("NSC") && index == 24) { - - // scotto expects device index 24 to come online after - // it initializes device index 22 - if (!CHECKED_24) { - CHECKED_24 = true; - return false; - } - - return true; - } - - // dunno for what game we did this again - return (char) (index != 5); -} - -static int __cdecl ac_io_reset(int a1) { - return a1; -} - -static int __cdecl ac_io_secplug_set_encodedpasswd(void *a1, int a2) { - return 1; -} - -static int __cdecl ac_io_set_soft_watch_dog(int a1, int a2) { - return 1; -} - -static int __cdecl ac_io_soft_watch_dog_on(int a1) { - return 1; -} - -static int __cdecl ac_io_soft_watch_dog_off() { - return 1; -} - -static int __cdecl ac_io_update(int a1) { - - // flush device output - RI_MGR->devices_flush_output(); - - // update wintouchemu - wintouchemu::update(); - - return 1; -} - -static int __cdecl ac_io_get_firmware_update_device_index() { - return 0xFF; -} - -static void __cdecl ac_io_go_firmware_update() { -} - -static int __cdecl ac_io_set_get_status_device(int a1) { - return a1; -} - -/* - * Module stuff - */ - -acio::CoreModule::CoreModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("Core", module, hookMode) { -} - -void acio::CoreModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_begin); - ACIO_MODULE_HOOK(ac_io_begin_get_status); - ACIO_MODULE_HOOK(ac_io_end); - ACIO_MODULE_HOOK(ac_io_end_get_status); - ACIO_MODULE_HOOK(ac_io_get_rs232c_status); - ACIO_MODULE_HOOK(ac_io_get_version); - ACIO_MODULE_HOOK(ac_io_get_version_string); - ACIO_MODULE_HOOK(ac_io_is_active); - ACIO_MODULE_HOOK(ac_io_is_active2); - ACIO_MODULE_HOOK(ac_io_is_active_device); - ACIO_MODULE_HOOK(ac_io_reset); - ACIO_MODULE_HOOK(ac_io_secplug_set_encodedpasswd); - ACIO_MODULE_HOOK(ac_io_set_soft_watch_dog); - ACIO_MODULE_HOOK(ac_io_soft_watch_dog_on); - ACIO_MODULE_HOOK(ac_io_soft_watch_dog_off); - ACIO_MODULE_HOOK(ac_io_update); - ACIO_MODULE_HOOK(ac_io_get_firmware_update_device_index); - ACIO_MODULE_HOOK(ac_io_go_firmware_update); - ACIO_MODULE_HOOK(ac_io_set_get_status_device); -} +#include "core.h" + +#include "avs/game.h" +#include "launcher/launcher.h" +#include "misc/wintouchemu.h" +#include "rawinput/rawinput.h" + +// static stuff +static int ACIO_WARMUP = 0; +static HHOOK ACIO_KB_HOOK = nullptr; + +/* + * Implementations + */ + +// needed for some games to make GetAsyncKeyState() working +static LRESULT CALLBACK ac_io_kb_hook_callback(int nCode, WPARAM wParam, LPARAM lParam) { + CallNextHookEx(ACIO_KB_HOOK, nCode, wParam, lParam); + return 0; +} + +static char __cdecl ac_io_begin( + size_t dev, + const char *ver, + unsigned int *val, + size_t flags, + void *ptr, + size_t baud) +{ + if (ACIO_KB_HOOK == nullptr) { + ACIO_KB_HOOK = SetWindowsHookEx(WH_KEYBOARD_LL, ac_io_kb_hook_callback, GetModuleHandle(nullptr), 0); + } + + // always return success + if (val && avs::game::is_model("KFC")) { + *val = 2; + } + + return 1; +} + +static char __cdecl ac_io_begin_get_status() { + return 1; +} + +static int __cdecl ac_io_end(int a1) { + return 1; +} + +static int __cdecl ac_io_end_get_status(int a1) { + return 1; +} + +static void *__cdecl ac_io_get_rs232c_status(char *a1, int a2) { + return memset(a1, 0, 88); +} + +static char __cdecl ac_io_get_version(uint8_t *a1, int a2) { + + // some games have version checks + // pop'n music only accepts versions bigger than 1.X.X (check yourself), anything starting with 2 works though + memset(a1 + 5, 2, 1); + memset(a1 + 6, 0, 1); + memset(a1 + 7, 0, 1); + + return 1; +} + +static const char *__cdecl ac_io_get_version_string() { + static const char *version = "1.25.0"; + return version; +} + +static char __cdecl ac_io_is_active(int a1, int a2) { + if (a1 == 1 && avs::game::is_model("JMA")) { + return 1; + } + + return (char) (++ACIO_WARMUP > 601 ? 1 : 0); +} + +static int __cdecl ac_io_is_active2(int a1, int *a2, int a3) { + ACIO_WARMUP = 601; + *a2 = 6; + return 1; +} + +static char __cdecl ac_io_is_active_device(int index, int a2) { + + // for scotto + static bool CHECKED_24 = false; + + // dance evolution + if (avs::game::is_model("KDM")) { + + // disable mysterious LED devices + if (index >= 12 && index <= 15) + return false; + } + + // scotto + if (avs::game::is_model("NSC") && index == 24) { + + // scotto expects device index 24 to come online after + // it initializes device index 22 + if (!CHECKED_24) { + CHECKED_24 = true; + return false; + } + + return true; + } + + // dunno for what game we did this again + return (char) (index != 5); +} + +static int __cdecl ac_io_reset(int a1) { + return a1; +} + +static int __cdecl ac_io_secplug_set_encodedpasswd(void *a1, int a2) { + return 1; +} + +static int __cdecl ac_io_set_soft_watch_dog(int a1, int a2) { + return 1; +} + +static int __cdecl ac_io_soft_watch_dog_on(int a1) { + return 1; +} + +static int __cdecl ac_io_soft_watch_dog_off() { + return 1; +} + +static int __cdecl ac_io_update(int a1) { + + // flush device output + RI_MGR->devices_flush_output(); + + // update wintouchemu + wintouchemu::update(); + + return 1; +} + +static int __cdecl ac_io_get_firmware_update_device_index() { + return 0xFF; +} + +static void __cdecl ac_io_go_firmware_update() { +} + +static int __cdecl ac_io_set_get_status_device(int a1) { + return a1; +} + +/* + * Module stuff + */ + +acio::CoreModule::CoreModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("Core", module, hookMode) { +} + +void acio::CoreModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_begin); + ACIO_MODULE_HOOK(ac_io_begin_get_status); + ACIO_MODULE_HOOK(ac_io_end); + ACIO_MODULE_HOOK(ac_io_end_get_status); + ACIO_MODULE_HOOK(ac_io_get_rs232c_status); + ACIO_MODULE_HOOK(ac_io_get_version); + ACIO_MODULE_HOOK(ac_io_get_version_string); + ACIO_MODULE_HOOK(ac_io_is_active); + ACIO_MODULE_HOOK(ac_io_is_active2); + ACIO_MODULE_HOOK(ac_io_is_active_device); + ACIO_MODULE_HOOK(ac_io_reset); + ACIO_MODULE_HOOK(ac_io_secplug_set_encodedpasswd); + ACIO_MODULE_HOOK(ac_io_set_soft_watch_dog); + ACIO_MODULE_HOOK(ac_io_soft_watch_dog_on); + ACIO_MODULE_HOOK(ac_io_soft_watch_dog_off); + ACIO_MODULE_HOOK(ac_io_update); + ACIO_MODULE_HOOK(ac_io_get_firmware_update_device_index); + ACIO_MODULE_HOOK(ac_io_go_firmware_update); + ACIO_MODULE_HOOK(ac_io_set_get_status_device); +} diff --git a/acio/core/core.h b/acio/core/core.h index 0606846..d5571c0 100644 --- a/acio/core/core.h +++ b/acio/core/core.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class CoreModule : public ACIOModule { - public: - CoreModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class CoreModule : public ACIOModule { + public: + CoreModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/hbhi/hbhi.h b/acio/hbhi/hbhi.h index 8fef347..607805c 100644 --- a/acio/hbhi/hbhi.h +++ b/acio/hbhi/hbhi.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class HBHIModule : public ACIOModule { - public: - HBHIModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class HBHIModule : public ACIOModule { + public: + HBHIModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/hdxs/hdxs.h b/acio/hdxs/hdxs.h index 3060558..7ac27de 100644 --- a/acio/hdxs/hdxs.h +++ b/acio/hdxs/hdxs.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class HDXSModule : public ACIOModule { - public: - HDXSModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class HDXSModule : public ACIOModule { + public: + HDXSModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/hgth/hgth.cpp b/acio/hgth/hgth.cpp index d46dd94..b6d7036 100644 --- a/acio/hgth/hgth.cpp +++ b/acio/hgth/hgth.cpp @@ -1,122 +1,122 @@ -#include "hgth.h" - -#include "acio/icca/icca.h" -#include "avs/game.h" -#include "cfg/api.h" -#include "games/rf3d/io.h" -#include "launcher/launcher.h" - -using namespace GameAPI; - -// state -static uint8_t STATUS_BUFFER[32] {}; -static bool STATUS_BUFFER_FREEZE = false; - -/* - * Implementations - */ - -static int __cdecl ac_io_hgth_set_senddata(int a1) { - return 1; -} - -static char __cdecl ac_io_hgth_update_recvdata() { - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // Road Fighters 3D - if (avs::game::is_model("JGT")) { - - // keypad mirror fix - acio::ICCA_FLIP_ROWS = true; - - // variables - uint16_t wheel = 0x7FFF; - uint16_t accelerator = 0x00; - uint16_t brake = 0x00; - - // get buttons - auto &buttons = games::rf3d::get_buttons(); - - // check buttons - bool wheel_button = false; - bool accelerate_button = false; - bool brake_button = false; - if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelLeft))) { - wheel -= 0x7FFF; - wheel_button = true; - } - if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelRight))) { - wheel += 0x8000; - wheel_button = true; - } - if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Accelerate))) { - accelerator = 0xFFFF; - accelerate_button = true; - } - if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Brake))) { - brake = 0xFFFF; - brake_button = true; - } - - // analogs - auto &analogs = games::rf3d::get_analogs(); - if (!wheel_button && analogs.at(games::rf3d::Analogs::Wheel).isSet()) { - wheel = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Wheel)) * 0xFFFF); - } - if (!accelerate_button && analogs.at(games::rf3d::Analogs::Accelerate).isSet()) { - accelerator = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Accelerate)) * 0xFFFF); - } - if (!brake_button && analogs.at(games::rf3d::Analogs::Brake).isSet()) { - brake = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Brake)) * 0xFFFF); - } - - // write values - *((uint16_t *) STATUS_BUFFER + 1) = wheel; - *((uint16_t *) STATUS_BUFFER + 2) = accelerator; - *((uint16_t *) STATUS_BUFFER + 3) = brake; - } - - // success - return true; -} - -static void __cdecl ac_io_hgth_get_recvdata(void *buffer) { - - // copy buffer - memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER)); -} - -static char __cdecl ac_io_hgth_directreq_set_handle_limit(char a1, int *a2) { - *a2 = 1; - return 1; -} - -static bool __cdecl ac_io_hgth_directreq_set_handle_limit_isfinished(int *a1) { - *a1 = 2; - return true; -} - -/* - * Module stuff - */ - -acio::HGTHModule::HGTHModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("HGTH", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::HGTHModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_hgth_set_senddata); - ACIO_MODULE_HOOK(ac_io_hgth_update_recvdata); - ACIO_MODULE_HOOK(ac_io_hgth_get_recvdata); - ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit); - ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit_isfinished); -} +#include "hgth.h" + +#include "acio/icca/icca.h" +#include "avs/game.h" +#include "cfg/api.h" +#include "games/rf3d/io.h" +#include "launcher/launcher.h" + +using namespace GameAPI; + +// state +static uint8_t STATUS_BUFFER[32] {}; +static bool STATUS_BUFFER_FREEZE = false; + +/* + * Implementations + */ + +static int __cdecl ac_io_hgth_set_senddata(int a1) { + return 1; +} + +static char __cdecl ac_io_hgth_update_recvdata() { + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // Road Fighters 3D + if (avs::game::is_model("JGT")) { + + // keypad mirror fix + acio::ICCA_FLIP_ROWS = true; + + // variables + uint16_t wheel = 0x7FFF; + uint16_t accelerator = 0x00; + uint16_t brake = 0x00; + + // get buttons + auto &buttons = games::rf3d::get_buttons(); + + // check buttons + bool wheel_button = false; + bool accelerate_button = false; + bool brake_button = false; + if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelLeft))) { + wheel -= 0x7FFF; + wheel_button = true; + } + if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelRight))) { + wheel += 0x8000; + wheel_button = true; + } + if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Accelerate))) { + accelerator = 0xFFFF; + accelerate_button = true; + } + if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Brake))) { + brake = 0xFFFF; + brake_button = true; + } + + // analogs + auto &analogs = games::rf3d::get_analogs(); + if (!wheel_button && analogs.at(games::rf3d::Analogs::Wheel).isSet()) { + wheel = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Wheel)) * 0xFFFF); + } + if (!accelerate_button && analogs.at(games::rf3d::Analogs::Accelerate).isSet()) { + accelerator = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Accelerate)) * 0xFFFF); + } + if (!brake_button && analogs.at(games::rf3d::Analogs::Brake).isSet()) { + brake = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Brake)) * 0xFFFF); + } + + // write values + *((uint16_t *) STATUS_BUFFER + 1) = wheel; + *((uint16_t *) STATUS_BUFFER + 2) = accelerator; + *((uint16_t *) STATUS_BUFFER + 3) = brake; + } + + // success + return true; +} + +static void __cdecl ac_io_hgth_get_recvdata(void *buffer) { + + // copy buffer + memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER)); +} + +static char __cdecl ac_io_hgth_directreq_set_handle_limit(char a1, int *a2) { + *a2 = 1; + return 1; +} + +static bool __cdecl ac_io_hgth_directreq_set_handle_limit_isfinished(int *a1) { + *a1 = 2; + return true; +} + +/* + * Module stuff + */ + +acio::HGTHModule::HGTHModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("HGTH", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::HGTHModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_hgth_set_senddata); + ACIO_MODULE_HOOK(ac_io_hgth_update_recvdata); + ACIO_MODULE_HOOK(ac_io_hgth_get_recvdata); + ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit); + ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit_isfinished); +} diff --git a/acio/hgth/hgth.h b/acio/hgth/hgth.h index ca47cb5..3233ac1 100644 --- a/acio/hgth/hgth.h +++ b/acio/hgth/hgth.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class HGTHModule : public ACIOModule { - public: - HGTHModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class HGTHModule : public ACIOModule { + public: + HGTHModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/i36g/i36g.cpp b/acio/i36g/i36g.cpp index aeee56a..336d69d 100644 --- a/acio/i36g/i36g.cpp +++ b/acio/i36g/i36g.cpp @@ -1,375 +1,375 @@ -#include "i36g.h" -#include "launcher/launcher.h" -#include "avs/game.h" -#include "rawinput/rawinput.h" -#include "games/mga/io.h" -#include "misc/eamuse.h" -#include "util/utils.h" - -using namespace GameAPI; - -// static stuff -static uint8_t STATUS_BUFFER[88 * 2] {}; -static bool STATUS_BUFFER_FREEZE = false; - -/* - * Implementations - */ - -static int __cdecl ac_io_i36g_add_coin(int a1, int a2, int a3) { - - // not so sure we want to add coins - return 1; -} - -static char __cdecl ac_io_i36g_consume_coinstock(int a1, int a2, int a3) { - eamuse_coin_consume_stock(); - return 1; -} - -static int __cdecl ac_io_i36g_control_coin_blocker_close(int a1, int a2) { - eamuse_coin_set_block(true); - return 1; -} - -static int __cdecl ac_io_i36g_control_coin_blocker_open(int a1, int a2) { - eamuse_coin_set_block(false); - return 1; -} - -static int __cdecl ac_io_i36g_control_lamp_bright(uint32_t device, uint32_t lamp_bits, uint8_t brightness) { - - // calculate value - float value = (float) brightness / 255.f; - - // get lights - auto &lights = games::mga::get_lights(); - - // cabinet device - if (device == 21) { - if (lamp_bits & 1) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftR], value); - } - if (lamp_bits & 2) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftG], value); - } - if (lamp_bits & 4) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftB], value); - } - if (lamp_bits & 8) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightR], value); - } - if (lamp_bits & 16) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightG], value); - } - if (lamp_bits & 32) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightB], value); - } - if (lamp_bits & 512) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::Start], value); - } - } - - // gun device - if (device == 22) { - if (lamp_bits & 1) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunR], value); - } - if (lamp_bits & 2) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunG], value); - } - if (lamp_bits & 4) { - Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunB], value); - } - } - - // success - return 1; -} - -static int __cdecl ac_io_i36g_control_motor_power(int device, uint8_t strength) { - - // gun device - if (device == 22) { - float value = (float) strength / 255.f; - auto &lights = games::mga::get_lights(); - Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunVibration], value); - } - - // success - return 1; -} - -static char __cdecl ac_io_i36g_current_coinstock(int a1, int a2, int *a3) { - - // get coinstock - *a3 = eamuse_coin_get_stock(); - return 1; -} - -static char __cdecl ac_io_i36g_get_coin_input_wave_buffer(int a1, char *a2) { - return 1; -} - -static void __cdecl ac_io_i36g_get_control_status_buffer(int device, void *buffer) { - - // cabinet buffer - if (device == 21) { - memcpy(buffer, &STATUS_BUFFER[0], 88); - } - - // gun buffer - if (device == 22) { - memcpy(buffer, &STATUS_BUFFER[88], 88); - } -} - -static char __cdecl ac_io_i36g_get_softwareid(int a1, int a2) { - return 1; -} - -static char __cdecl ac_io_i36g_get_systemid(int a1, int a2) { - return 1; -} - -static bool __cdecl ac_io_i36g_get_watchdog_status(int a1) { - return false; -} - -static short __cdecl ac_io_i36g_get_watchdog_time_min(int a1) { - return 0; -} - -static short __cdecl ac_io_i36g_get_watchdog_time_now(int a1) { - return 0; -} - -static char __cdecl ac_io_i36g_lock_coincounter(int a1, int a2) { - return 1; -} - -static char __cdecl ac_io_i36g_req_coin_input_wave(int a1) { - return 1; -} - -static char __cdecl ac_io_i36g_req_get_control_status(int a1, int *a2) { - return 1; -} - -static char __cdecl ac_io_i36g_req_secplug_check(int a1, char *a2) { - return 1; -} - -static bool __cdecl ac_io_i36g_req_secplug_check_isfinished(int a1, int *a2) { - return true; -} - -static char __cdecl ac_io_i36g_req_secplug_check_softwareplug(int a1, char *a2) { - return 1; -} - -static char __cdecl ac_io_i36g_req_secplug_check_systemplug(int a1) { - return 1; -} - -static char __cdecl ac_io_i36g_req_secplug_missing_check(int a1) { - return 1; -} - -static bool __cdecl ac_io_i36g_req_secplug_missing_check_isfinished(int a1, int *a2) { - return true; -} - -static bool __cdecl ac_io_i36g_req_volume_control(int a1, char a2, char a3, char a4, char a5) { - return true; -} - -static bool __cdecl ac_io_i36g_req_volume_control_isfinished(int a1, int *ret_state) { - *ret_state = 3; - return true; -} - -static int __cdecl ac_io_i36g_set_cmdmode(int a1, int a2) { - return 1; -} - -static int __cdecl ac_io_i36g_set_framing_err_packet_send_interval(int a1) { - return 1; -} - -static bool __cdecl ac_io_i36g_set_watchdog_time(int a1, short a2) { - return true; -} - -static char __cdecl ac_io_i36g_unlock_coincounter(int a1, int a2) { - return 1; -} - -static bool __cdecl ac_io_i36g_update_control_status_buffer(int node) { - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // Metal Gear Arcade - if (avs::game::is_model("I36")) { - - // get buttons - auto &buttons = games::mga::get_buttons(); - - // cabinet device - if (node == 21) { - - // clear status buffer - memset(&STATUS_BUFFER[0], 0, 88); - - // update buttons - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Service))) { - ARRAY_SETB(&STATUS_BUFFER[0], 44); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Test))) { - ARRAY_SETB(&STATUS_BUFFER[0], 45); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::CoinMech))) { - ARRAY_SETB(&STATUS_BUFFER[0], 42); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Start))) { - ARRAY_SETB(&STATUS_BUFFER[0], 124); - } - } - - // gun device - if (node == 22) { - - // clear status buffer - memset(&STATUS_BUFFER[88], 0, 88); - - // update buttons - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::TriggerButton)) - || (GetKeyState(VK_LBUTTON) & 0x100) != 0) { // mouse button - ARRAY_SETB(&STATUS_BUFFER[88], 109); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontTop))) { - ARRAY_SETB(&STATUS_BUFFER[88], 108); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontBottom))) { - ARRAY_SETB(&STATUS_BUFFER[88], 106); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLeft))) { - ARRAY_SETB(&STATUS_BUFFER[88], 107); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideRight))) { - ARRAY_SETB(&STATUS_BUFFER[88], 105); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLever))) { - ARRAY_SETB(&STATUS_BUFFER[88], 104); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SwitchButton))) { - ARRAY_SETB(&STATUS_BUFFER[88], 125); - } - if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Top))) { - ARRAY_SETB(&STATUS_BUFFER[88], 124); - } - - // joy stick - unsigned short joy_x = 0x7FFF; - unsigned short joy_y = 0x7FFF; - bool joy_x_pressed = false; - bool joy_y_pressed = false; - if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyForwards])) { - joy_y -= 0x7FFF; - joy_y_pressed = true; - } - if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyBackwards])) { - joy_y += 0x7FFF; - joy_y_pressed = true; - } - if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyLeft])) { - joy_x -= 0x7FFF; - joy_x_pressed = true; - } - if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyRight])) { - joy_x += 0x7FFF; - joy_x_pressed = true; - } - - // joy stick raw input - auto &analogs = games::mga::get_analogs(); - if (!joy_x_pressed && analogs[games::mga::Analogs::JoyX].isSet()) { - joy_x = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyX]) * 0xFFFF); - } - if (!joy_y_pressed && analogs[games::mga::Analogs::JoyY].isSet()) { - joy_y = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyY]) * 0xFFFF); - } - - // save joy stick - STATUS_BUFFER[88 + 42] = LOBYTE(joy_y); - STATUS_BUFFER[88 + 43] = HIBYTE(joy_y); - STATUS_BUFFER[88 + 44] = LOBYTE(joy_x); - STATUS_BUFFER[88 + 45] = HIBYTE(joy_x); - } - } - - // return success - return true; -} - -static int __cdecl ac_io_i36g_watchdog_off(int a1) { - return 1; -} - -/* - * Module stuff - */ - -acio::I36GModule::I36GModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("I36G", module, hookMode) { - this->status_buffer = &STATUS_BUFFER[0]; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::I36GModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_i36g_add_coin); - ACIO_MODULE_HOOK(ac_io_i36g_consume_coinstock); - ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_close); - ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_open); - ACIO_MODULE_HOOK(ac_io_i36g_control_lamp_bright); - ACIO_MODULE_HOOK(ac_io_i36g_control_motor_power); - ACIO_MODULE_HOOK(ac_io_i36g_current_coinstock); - ACIO_MODULE_HOOK(ac_io_i36g_get_coin_input_wave_buffer); - ACIO_MODULE_HOOK(ac_io_i36g_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_i36g_get_softwareid); - ACIO_MODULE_HOOK(ac_io_i36g_get_systemid); - ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_status); - ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_min); - ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_now); - ACIO_MODULE_HOOK(ac_io_i36g_lock_coincounter); - ACIO_MODULE_HOOK(ac_io_i36g_req_coin_input_wave); - ACIO_MODULE_HOOK(ac_io_i36g_req_get_control_status); - ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check); - ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_isfinished); - ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_softwareplug); - ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_systemplug); - ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check); - ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check_isfinished); - ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control); - ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control_isfinished); - ACIO_MODULE_HOOK(ac_io_i36g_set_cmdmode); - ACIO_MODULE_HOOK(ac_io_i36g_set_framing_err_packet_send_interval); - ACIO_MODULE_HOOK(ac_io_i36g_set_watchdog_time); - ACIO_MODULE_HOOK(ac_io_i36g_unlock_coincounter); - ACIO_MODULE_HOOK(ac_io_i36g_update_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_i36g_watchdog_off); - - // I36S links - this->hook((void *) ac_io_i36g_update_control_status_buffer, - "ac_io_i36s_update_control_status_buffer"); - this->hook((void *) ac_io_i36g_get_control_status_buffer, - "ac_io_i36s_get_control_status_buffer"); - this->hook((void *) ac_io_i36g_set_cmdmode, - "ac_io_i36s_set_cmdmode"); -} +#include "i36g.h" +#include "launcher/launcher.h" +#include "avs/game.h" +#include "rawinput/rawinput.h" +#include "games/mga/io.h" +#include "misc/eamuse.h" +#include "util/utils.h" + +using namespace GameAPI; + +// static stuff +static uint8_t STATUS_BUFFER[88 * 2] {}; +static bool STATUS_BUFFER_FREEZE = false; + +/* + * Implementations + */ + +static int __cdecl ac_io_i36g_add_coin(int a1, int a2, int a3) { + + // not so sure we want to add coins + return 1; +} + +static char __cdecl ac_io_i36g_consume_coinstock(int a1, int a2, int a3) { + eamuse_coin_consume_stock(); + return 1; +} + +static int __cdecl ac_io_i36g_control_coin_blocker_close(int a1, int a2) { + eamuse_coin_set_block(true); + return 1; +} + +static int __cdecl ac_io_i36g_control_coin_blocker_open(int a1, int a2) { + eamuse_coin_set_block(false); + return 1; +} + +static int __cdecl ac_io_i36g_control_lamp_bright(uint32_t device, uint32_t lamp_bits, uint8_t brightness) { + + // calculate value + float value = (float) brightness / 255.f; + + // get lights + auto &lights = games::mga::get_lights(); + + // cabinet device + if (device == 21) { + if (lamp_bits & 1) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftR], value); + } + if (lamp_bits & 2) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftG], value); + } + if (lamp_bits & 4) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftB], value); + } + if (lamp_bits & 8) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightR], value); + } + if (lamp_bits & 16) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightG], value); + } + if (lamp_bits & 32) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightB], value); + } + if (lamp_bits & 512) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::Start], value); + } + } + + // gun device + if (device == 22) { + if (lamp_bits & 1) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunR], value); + } + if (lamp_bits & 2) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunG], value); + } + if (lamp_bits & 4) { + Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunB], value); + } + } + + // success + return 1; +} + +static int __cdecl ac_io_i36g_control_motor_power(int device, uint8_t strength) { + + // gun device + if (device == 22) { + float value = (float) strength / 255.f; + auto &lights = games::mga::get_lights(); + Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunVibration], value); + } + + // success + return 1; +} + +static char __cdecl ac_io_i36g_current_coinstock(int a1, int a2, int *a3) { + + // get coinstock + *a3 = eamuse_coin_get_stock(); + return 1; +} + +static char __cdecl ac_io_i36g_get_coin_input_wave_buffer(int a1, char *a2) { + return 1; +} + +static void __cdecl ac_io_i36g_get_control_status_buffer(int device, void *buffer) { + + // cabinet buffer + if (device == 21) { + memcpy(buffer, &STATUS_BUFFER[0], 88); + } + + // gun buffer + if (device == 22) { + memcpy(buffer, &STATUS_BUFFER[88], 88); + } +} + +static char __cdecl ac_io_i36g_get_softwareid(int a1, int a2) { + return 1; +} + +static char __cdecl ac_io_i36g_get_systemid(int a1, int a2) { + return 1; +} + +static bool __cdecl ac_io_i36g_get_watchdog_status(int a1) { + return false; +} + +static short __cdecl ac_io_i36g_get_watchdog_time_min(int a1) { + return 0; +} + +static short __cdecl ac_io_i36g_get_watchdog_time_now(int a1) { + return 0; +} + +static char __cdecl ac_io_i36g_lock_coincounter(int a1, int a2) { + return 1; +} + +static char __cdecl ac_io_i36g_req_coin_input_wave(int a1) { + return 1; +} + +static char __cdecl ac_io_i36g_req_get_control_status(int a1, int *a2) { + return 1; +} + +static char __cdecl ac_io_i36g_req_secplug_check(int a1, char *a2) { + return 1; +} + +static bool __cdecl ac_io_i36g_req_secplug_check_isfinished(int a1, int *a2) { + return true; +} + +static char __cdecl ac_io_i36g_req_secplug_check_softwareplug(int a1, char *a2) { + return 1; +} + +static char __cdecl ac_io_i36g_req_secplug_check_systemplug(int a1) { + return 1; +} + +static char __cdecl ac_io_i36g_req_secplug_missing_check(int a1) { + return 1; +} + +static bool __cdecl ac_io_i36g_req_secplug_missing_check_isfinished(int a1, int *a2) { + return true; +} + +static bool __cdecl ac_io_i36g_req_volume_control(int a1, char a2, char a3, char a4, char a5) { + return true; +} + +static bool __cdecl ac_io_i36g_req_volume_control_isfinished(int a1, int *ret_state) { + *ret_state = 3; + return true; +} + +static int __cdecl ac_io_i36g_set_cmdmode(int a1, int a2) { + return 1; +} + +static int __cdecl ac_io_i36g_set_framing_err_packet_send_interval(int a1) { + return 1; +} + +static bool __cdecl ac_io_i36g_set_watchdog_time(int a1, short a2) { + return true; +} + +static char __cdecl ac_io_i36g_unlock_coincounter(int a1, int a2) { + return 1; +} + +static bool __cdecl ac_io_i36g_update_control_status_buffer(int node) { + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // Metal Gear Arcade + if (avs::game::is_model("I36")) { + + // get buttons + auto &buttons = games::mga::get_buttons(); + + // cabinet device + if (node == 21) { + + // clear status buffer + memset(&STATUS_BUFFER[0], 0, 88); + + // update buttons + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Service))) { + ARRAY_SETB(&STATUS_BUFFER[0], 44); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Test))) { + ARRAY_SETB(&STATUS_BUFFER[0], 45); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::CoinMech))) { + ARRAY_SETB(&STATUS_BUFFER[0], 42); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Start))) { + ARRAY_SETB(&STATUS_BUFFER[0], 124); + } + } + + // gun device + if (node == 22) { + + // clear status buffer + memset(&STATUS_BUFFER[88], 0, 88); + + // update buttons + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::TriggerButton)) + || (GetKeyState(VK_LBUTTON) & 0x100) != 0) { // mouse button + ARRAY_SETB(&STATUS_BUFFER[88], 109); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontTop))) { + ARRAY_SETB(&STATUS_BUFFER[88], 108); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontBottom))) { + ARRAY_SETB(&STATUS_BUFFER[88], 106); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLeft))) { + ARRAY_SETB(&STATUS_BUFFER[88], 107); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideRight))) { + ARRAY_SETB(&STATUS_BUFFER[88], 105); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLever))) { + ARRAY_SETB(&STATUS_BUFFER[88], 104); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SwitchButton))) { + ARRAY_SETB(&STATUS_BUFFER[88], 125); + } + if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Top))) { + ARRAY_SETB(&STATUS_BUFFER[88], 124); + } + + // joy stick + unsigned short joy_x = 0x7FFF; + unsigned short joy_y = 0x7FFF; + bool joy_x_pressed = false; + bool joy_y_pressed = false; + if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyForwards])) { + joy_y -= 0x7FFF; + joy_y_pressed = true; + } + if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyBackwards])) { + joy_y += 0x7FFF; + joy_y_pressed = true; + } + if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyLeft])) { + joy_x -= 0x7FFF; + joy_x_pressed = true; + } + if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyRight])) { + joy_x += 0x7FFF; + joy_x_pressed = true; + } + + // joy stick raw input + auto &analogs = games::mga::get_analogs(); + if (!joy_x_pressed && analogs[games::mga::Analogs::JoyX].isSet()) { + joy_x = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyX]) * 0xFFFF); + } + if (!joy_y_pressed && analogs[games::mga::Analogs::JoyY].isSet()) { + joy_y = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyY]) * 0xFFFF); + } + + // save joy stick + STATUS_BUFFER[88 + 42] = LOBYTE(joy_y); + STATUS_BUFFER[88 + 43] = HIBYTE(joy_y); + STATUS_BUFFER[88 + 44] = LOBYTE(joy_x); + STATUS_BUFFER[88 + 45] = HIBYTE(joy_x); + } + } + + // return success + return true; +} + +static int __cdecl ac_io_i36g_watchdog_off(int a1) { + return 1; +} + +/* + * Module stuff + */ + +acio::I36GModule::I36GModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("I36G", module, hookMode) { + this->status_buffer = &STATUS_BUFFER[0]; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::I36GModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_i36g_add_coin); + ACIO_MODULE_HOOK(ac_io_i36g_consume_coinstock); + ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_close); + ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_open); + ACIO_MODULE_HOOK(ac_io_i36g_control_lamp_bright); + ACIO_MODULE_HOOK(ac_io_i36g_control_motor_power); + ACIO_MODULE_HOOK(ac_io_i36g_current_coinstock); + ACIO_MODULE_HOOK(ac_io_i36g_get_coin_input_wave_buffer); + ACIO_MODULE_HOOK(ac_io_i36g_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_i36g_get_softwareid); + ACIO_MODULE_HOOK(ac_io_i36g_get_systemid); + ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_status); + ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_min); + ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_now); + ACIO_MODULE_HOOK(ac_io_i36g_lock_coincounter); + ACIO_MODULE_HOOK(ac_io_i36g_req_coin_input_wave); + ACIO_MODULE_HOOK(ac_io_i36g_req_get_control_status); + ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check); + ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_isfinished); + ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_softwareplug); + ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_systemplug); + ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check); + ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check_isfinished); + ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control); + ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control_isfinished); + ACIO_MODULE_HOOK(ac_io_i36g_set_cmdmode); + ACIO_MODULE_HOOK(ac_io_i36g_set_framing_err_packet_send_interval); + ACIO_MODULE_HOOK(ac_io_i36g_set_watchdog_time); + ACIO_MODULE_HOOK(ac_io_i36g_unlock_coincounter); + ACIO_MODULE_HOOK(ac_io_i36g_update_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_i36g_watchdog_off); + + // I36S links + this->hook((void *) ac_io_i36g_update_control_status_buffer, + "ac_io_i36s_update_control_status_buffer"); + this->hook((void *) ac_io_i36g_get_control_status_buffer, + "ac_io_i36s_get_control_status_buffer"); + this->hook((void *) ac_io_i36g_set_cmdmode, + "ac_io_i36s_set_cmdmode"); +} diff --git a/acio/i36g/i36g.h b/acio/i36g/i36g.h index d0e00d8..7d22628 100644 --- a/acio/i36g/i36g.h +++ b/acio/i36g/i36g.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class I36GModule : public ACIOModule { - public: - I36GModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class I36GModule : public ACIOModule { + public: + I36GModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/i36i/i36i.h b/acio/i36i/i36i.h index d48980e..514fa8c 100644 --- a/acio/i36i/i36i.h +++ b/acio/i36i/i36i.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class I36IModule : public ACIOModule { - public: - I36IModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class I36IModule : public ACIOModule { + public: + I36IModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/icca/icca.h b/acio/icca/icca.h index 0632c75..b9722cc 100644 --- a/acio/icca/icca.h +++ b/acio/icca/icca.h @@ -1,21 +1,21 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - // settings - extern bool ICCA_FLIP_ROWS; - extern bool ICCA_COMPAT_ACTIVE; - - class ICCAModule : public ACIOModule { - public: - ICCAModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} - -static inline bool is_card_uid_felica(uint8_t *uid) { - return uid[0] != 0xE0 && uid[1] != 0x04; -} +#pragma once + +#include "../module.h" + +namespace acio { + + // settings + extern bool ICCA_FLIP_ROWS; + extern bool ICCA_COMPAT_ACTIVE; + + class ICCAModule : public ACIOModule { + public: + ICCAModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} + +static inline bool is_card_uid_felica(uint8_t *uid) { + return uid[0] != 0xE0 && uid[1] != 0x04; +} diff --git a/acio/j32d/j32d.h b/acio/j32d/j32d.h index e3102ba..1acb591 100644 --- a/acio/j32d/j32d.h +++ b/acio/j32d/j32d.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class J32DModule : public ACIOModule { - public: - J32DModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class J32DModule : public ACIOModule { + public: + J32DModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/kfca/kfca.cpp b/acio/kfca/kfca.cpp index 3ec5f34..e492b57 100644 --- a/acio/kfca/kfca.cpp +++ b/acio/kfca/kfca.cpp @@ -1,483 +1,483 @@ -#include "kfca.h" - -#include "avs/game.h" -#include "games/bs/io.h" -#include "games/nost/io.h" -#include "games/scotto/io.h" -#include "games/sdvx/io.h" -#include "misc/eamuse.h" -#include "rawinput/rawinput.h" -#include "util/utils.h" - -using namespace GameAPI; - -// globals -uint8_t KFCA_VOL_SOUND = 96; -uint8_t KFCA_VOL_HEADPHONE = 96; -uint8_t KFCA_VOL_EXTERNAL = 96; -uint8_t KFCA_VOL_WOOFER = 96; - -// static stuff -static uint8_t STATUS_BUFFER[64] {}; -static bool STATUS_BUFFER_FREEZE = false; -static unsigned int KFCA_VOLL = 0; -static unsigned int KFCA_VOLR = 0; - -/* - * Implementations - */ - -static int __cdecl ac_io_kfca_control_button_led(unsigned int button, bool state) { - - // Sound Voltex - if (avs::game::is_model("KFC")) { - - // control mapping - static const size_t mapping[] = { - games::sdvx::Lights::BT_A, - games::sdvx::Lights::BT_B, - games::sdvx::Lights::BT_C, - games::sdvx::Lights::BT_D, - games::sdvx::Lights::FX_L, - games::sdvx::Lights::FX_R, - games::sdvx::Lights::START, - games::sdvx::Lights::GENERATOR_B, - }; - - // check if button is mapped - if (button < 8) { - - // get lights - auto &lights = games::sdvx::get_lights(); - - // write light - float value = state ? 1.f : 0.f; - Lights::writeLight(RI_MGR, lights.at(mapping[button]), value); - } - } - - // Scotto - if (avs::game::is_model("NSC")) { - - // control mapping - static const size_t mapping[] = { - games::scotto::Lights::PAD_F_B, - games::scotto::Lights::PAD_E_R, - games::scotto::Lights::PAD_E_B, - ~0u, - ~0u, - ~0u, - games::scotto::Lights::PAD_F_R, - games::scotto::Lights::BUTTON, - }; - - // check if button is mapped - if (button < std::size(mapping) && button[mapping] != ~0u) { - - // get lights - auto &lights = games::scotto::get_lights(); - - // write light - float value = state ? 1.f : 0.f; - Lights::writeLight(RI_MGR, lights.at(mapping[button]), value); - } - } - - // return success - return 1; -} - -static int __cdecl ac_io_kfca_control_coin_blocker_close(int a1) { - eamuse_coin_set_block(true); - return 1; -} - -static int __cdecl ac_io_kfca_control_coin_blocker_open(int a1) { - eamuse_coin_set_block(false); - return 1; -} - -static int __cdecl ac_io_kfca_control_led_bright(uint32_t led_field, uint8_t brightness) { - - // Sound Voltex - if (avs::game::is_model("KFC")) { - - // get lights - auto &lights = games::sdvx::get_lights(); - - // control mapping - static const size_t mapping[] { - games::sdvx::Lights::WING_LEFT_UP_R, - games::sdvx::Lights::WING_LEFT_UP_G, - games::sdvx::Lights::WING_LEFT_UP_B, - games::sdvx::Lights::WING_RIGHT_UP_R, - games::sdvx::Lights::WING_RIGHT_UP_G, - games::sdvx::Lights::WING_RIGHT_UP_B, - games::sdvx::Lights::WING_LEFT_LOW_R, - games::sdvx::Lights::WING_LEFT_LOW_G, - games::sdvx::Lights::WING_LEFT_LOW_B, - games::sdvx::Lights::WING_RIGHT_LOW_R, - games::sdvx::Lights::WING_RIGHT_LOW_G, - games::sdvx::Lights::WING_RIGHT_LOW_B, - games::sdvx::Lights::WOOFER_R, - games::sdvx::Lights::WOOFER_G, - games::sdvx::Lights::WOOFER_B, - games::sdvx::Lights::CONTROLLER_R, - games::sdvx::Lights::CONTROLLER_G, - games::sdvx::Lights::CONTROLLER_B, - games::sdvx::Lights::GENERATOR_R, - games::sdvx::Lights::GENERATOR_G, - }; - - // write light - float value = brightness / 255.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); - } - } - } - - // BeatStream - if (avs::game::is_model("NBT")) { - - // get lights - auto &lights = games::bs::get_lights(); - - // mapping - static const size_t mapping[] { - ~0u, ~0u, ~0u, - games::bs::Lights::RightR, - games::bs::Lights::RightG, - games::bs::Lights::RightB, - games::bs::Lights::LeftR, - games::bs::Lights::LeftG, - games::bs::Lights::LeftB, - games::bs::Lights::BottomR, - games::bs::Lights::BottomG, - games::bs::Lights::BottomB, - }; - - // write light - float value = brightness / 127.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (mapping[i] != ~0u && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); - } - } - } - - // Nostalgia - if (avs::game::is_model("PAN")) { - - // get lights - auto &lights = games::nost::get_lights(); - - // mapping - static const size_t mapping[] { - ~0u, ~0u, ~0u, - games::nost::Lights::TitleR, - games::nost::Lights::TitleG, - games::nost::Lights::TitleB, - ~0u, ~0u, ~0u, - games::nost::Lights::BottomR, - games::nost::Lights::BottomG, - games::nost::Lights::BottomB, - }; - - // write light - float value = brightness / 127.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (mapping[i] != ~0u && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); - } - } - } - - // Scotto - if (avs::game::is_model("NSC")) { - - // get lights - auto &lights = games::scotto::get_lights(); - - // mapping - static const size_t mapping[] { - games::scotto::Lights::CUP_R, - games::scotto::Lights::CUP_G, - games::scotto::Lights::CUP_B, - games::scotto::Lights::PAD_A_R, - games::scotto::Lights::PAD_A_G, - games::scotto::Lights::PAD_A_B, - games::scotto::Lights::PAD_B_R, - games::scotto::Lights::PAD_B_G, - games::scotto::Lights::PAD_B_B, - games::scotto::Lights::PAD_C_R, - games::scotto::Lights::PAD_C_G, - games::scotto::Lights::PAD_C_B, - games::scotto::Lights::PAD_D_R, - games::scotto::Lights::PAD_D_G, - games::scotto::Lights::PAD_D_B, - games::scotto::Lights::FIRST_PAD_R, - games::scotto::Lights::FIRST_PAD_G, - games::scotto::Lights::FIRST_PAD_B, - games::scotto::Lights::PAD_F_G, - games::scotto::Lights::PAD_E_G, - }; - - // write light - float value = brightness / 255.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); - } - } - } - - // return success - return 1; -} - -static char __cdecl ac_io_kfca_current_coinstock(int a1, DWORD *a2) { - *a2 = (DWORD) eamuse_coin_get_stock(); - return 1; -} - -static void *__cdecl ac_io_kfca_get_control_status_buffer(void *target_buffer) { - - // copy buffer - return memcpy(target_buffer, STATUS_BUFFER, 64); -} - -static int __cdecl ac_io_kfca_lock_coincounter(int a1) { - eamuse_coin_set_block(true); - return 1; -} - -static bool __cdecl ac_io_kfca_req_volume_control( - uint8_t vol_sound, uint8_t vol_headphone, uint8_t vol_external, uint8_t vol_woofer) { - - // update globals - KFCA_VOL_SOUND = vol_sound; - KFCA_VOL_HEADPHONE = vol_headphone; - KFCA_VOL_EXTERNAL = vol_external; - KFCA_VOL_WOOFER = vol_woofer; - - // Sound Voltex - if (avs::game::is_model("KFC")) { - - // get lights - auto &lights = games::sdvx::get_lights(); - GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_SOUND], - (100 - vol_sound) / 100.f); - GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_HEADPHONE], - (100 - vol_headphone) / 100.f); - GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_EXTERNAL], - (100 - vol_external) / 100.f); - GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_WOOFER], - (100 - vol_woofer) / 100.f); - } - - return true; -} - -static bool __cdecl ac_io_kfca_set_watchdog_time(short a1) { - return true; -} - -static char __cdecl ac_io_kfca_unlock_coincounter(int a1) { - eamuse_coin_set_block(false); - return 1; -} - -static char __cdecl ac_io_kfca_update_control_status_buffer() { - static const int input_offset = 4; - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // clear buffer - memset(STATUS_BUFFER, 0, 64); - - // SDVX - if (avs::game::is_model("KFC")) { - - // get buttons - auto &buttons = games::sdvx::get_buttons(); - - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Test))) { - STATUS_BUFFER[input_offset + 1] |= 0x20; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Service))) { - STATUS_BUFFER[input_offset + 1] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::CoinMech))) { - STATUS_BUFFER[input_offset + 1] |= 0x04; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Start))) { - STATUS_BUFFER[input_offset + 9] |= 0x08; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_A))) { - STATUS_BUFFER[input_offset + 9] |= 0x04; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_B))) { - STATUS_BUFFER[input_offset + 9] |= 0x02; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_C))) { - STATUS_BUFFER[input_offset + 9] |= 0x01; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_D))) { - STATUS_BUFFER[input_offset + 11] |= 0x20; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_L))) { - STATUS_BUFFER[input_offset + 11] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_R))) { - STATUS_BUFFER[input_offset + 11] |= 0x08; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Headphone))) { - STATUS_BUFFER[input_offset + 9] |= 0x20; - } - - // volume left - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Left))) { - KFCA_VOLL = (KFCA_VOLL - 16) & 1023; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Right))) { - KFCA_VOLL = (KFCA_VOLL + 16) & 1023; - } - - // volume right - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Left))) { - KFCA_VOLR = (KFCA_VOLR - 16) & 1023; - } - if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Right))) { - KFCA_VOLR = (KFCA_VOLR + 16) & 1023; - } - - // update volumes - auto &analogs = games::sdvx::get_analogs(); - auto vol_left = KFCA_VOLL; - auto vol_right = KFCA_VOLR; - if (analogs.at(0).isSet() || analogs.at(1).isSet()) { - vol_left += (unsigned int) (Analogs::getState(RI_MGR, - analogs.at(games::sdvx::Analogs::VOL_L)) * 1023.99f); - vol_right += (unsigned int) (Analogs::getState(RI_MGR, - analogs.at(games::sdvx::Analogs::VOL_R)) * 1023.99f); - } - - // proper loops - vol_left %= 1024; - vol_right %= 1024; - - // save volumes in buffer - STATUS_BUFFER[input_offset + 16 + 0] |= (unsigned char) ((vol_left << 6) & 0xFF); - STATUS_BUFFER[input_offset + 16 + 1] |= (unsigned char) ((vol_left >> 2) & 0xFF); - STATUS_BUFFER[input_offset + 16 + 2] |= (unsigned char) ((vol_right << 6) & 0xFF); - STATUS_BUFFER[input_offset + 16 + 3] |= (unsigned char) ((vol_right >> 2) & 0xFF); - } - - // Beatstream - if (avs::game::is_model("NBT")) { - - // get buttons - auto &buttons = games::bs::get_buttons(); - - if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Test))) { - STATUS_BUFFER[input_offset + 1] |= 0x20; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Service))) { - STATUS_BUFFER[input_offset + 1] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::CoinMech))) { - STATUS_BUFFER[input_offset + 1] |= 0x04; - } - } - - // Nostalgia - if (avs::game::is_model("PAN")) { - - // get buttons - auto &buttons = games::nost::get_buttons(); - - if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Service))) { - STATUS_BUFFER[input_offset + 1] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Test))) { - STATUS_BUFFER[input_offset + 1] |= 0x20; - } - if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::CoinMech))) { - STATUS_BUFFER[input_offset + 1] |= 0x04; - } - } - - // Scotto - if (avs::game::is_model("NSC")) { - - // get buttons - auto &buttons = games::scotto::get_buttons(); - - if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[input_offset + 1] |= 0x20; - } - if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[input_offset + 1] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::CoinMech)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[input_offset + 1] |= 0x04; - } - if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Start)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[input_offset + 9] |= 0x20; - } - if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Up)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[input_offset + 9] |= 0x10; - } - if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Down)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[input_offset + 9] |= 0x08; - } - - // the code also checks `input_offset + 9` for 0x01 but that does not trigger any response - // in the "I/O CHECK" scene - } - - // success - return true; -} - -static void __cdecl ac_io_kfca_watchdog_off() { -} - -// yes this is spelled "marge" instead of "merge" -static int __cdecl ac_io_kfca_set_status_marge_func(void *cb) { - return 1; -} - -/* - * Module stuff - */ - -acio::KFCAModule::KFCAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KFCA", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::KFCAModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_kfca_control_button_led); - ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_close); - ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_open); - ACIO_MODULE_HOOK(ac_io_kfca_control_led_bright); - ACIO_MODULE_HOOK(ac_io_kfca_current_coinstock); - ACIO_MODULE_HOOK(ac_io_kfca_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_kfca_lock_coincounter); - ACIO_MODULE_HOOK(ac_io_kfca_req_volume_control); - ACIO_MODULE_HOOK(ac_io_kfca_set_watchdog_time); - ACIO_MODULE_HOOK(ac_io_kfca_unlock_coincounter); - ACIO_MODULE_HOOK(ac_io_kfca_update_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_kfca_watchdog_off); - ACIO_MODULE_HOOK(ac_io_kfca_set_status_marge_func); -} +#include "kfca.h" + +#include "avs/game.h" +#include "games/bs/io.h" +#include "games/nost/io.h" +#include "games/scotto/io.h" +#include "games/sdvx/io.h" +#include "misc/eamuse.h" +#include "rawinput/rawinput.h" +#include "util/utils.h" + +using namespace GameAPI; + +// globals +uint8_t KFCA_VOL_SOUND = 96; +uint8_t KFCA_VOL_HEADPHONE = 96; +uint8_t KFCA_VOL_EXTERNAL = 96; +uint8_t KFCA_VOL_WOOFER = 96; + +// static stuff +static uint8_t STATUS_BUFFER[64] {}; +static bool STATUS_BUFFER_FREEZE = false; +static unsigned int KFCA_VOLL = 0; +static unsigned int KFCA_VOLR = 0; + +/* + * Implementations + */ + +static int __cdecl ac_io_kfca_control_button_led(unsigned int button, bool state) { + + // Sound Voltex + if (avs::game::is_model("KFC")) { + + // control mapping + static const size_t mapping[] = { + games::sdvx::Lights::BT_A, + games::sdvx::Lights::BT_B, + games::sdvx::Lights::BT_C, + games::sdvx::Lights::BT_D, + games::sdvx::Lights::FX_L, + games::sdvx::Lights::FX_R, + games::sdvx::Lights::START, + games::sdvx::Lights::GENERATOR_B, + }; + + // check if button is mapped + if (button < 8) { + + // get lights + auto &lights = games::sdvx::get_lights(); + + // write light + float value = state ? 1.f : 0.f; + Lights::writeLight(RI_MGR, lights.at(mapping[button]), value); + } + } + + // Scotto + if (avs::game::is_model("NSC")) { + + // control mapping + static const size_t mapping[] = { + games::scotto::Lights::PAD_F_B, + games::scotto::Lights::PAD_E_R, + games::scotto::Lights::PAD_E_B, + ~0u, + ~0u, + ~0u, + games::scotto::Lights::PAD_F_R, + games::scotto::Lights::BUTTON, + }; + + // check if button is mapped + if (button < std::size(mapping) && button[mapping] != ~0u) { + + // get lights + auto &lights = games::scotto::get_lights(); + + // write light + float value = state ? 1.f : 0.f; + Lights::writeLight(RI_MGR, lights.at(mapping[button]), value); + } + } + + // return success + return 1; +} + +static int __cdecl ac_io_kfca_control_coin_blocker_close(int a1) { + eamuse_coin_set_block(true); + return 1; +} + +static int __cdecl ac_io_kfca_control_coin_blocker_open(int a1) { + eamuse_coin_set_block(false); + return 1; +} + +static int __cdecl ac_io_kfca_control_led_bright(uint32_t led_field, uint8_t brightness) { + + // Sound Voltex + if (avs::game::is_model("KFC")) { + + // get lights + auto &lights = games::sdvx::get_lights(); + + // control mapping + static const size_t mapping[] { + games::sdvx::Lights::WING_LEFT_UP_R, + games::sdvx::Lights::WING_LEFT_UP_G, + games::sdvx::Lights::WING_LEFT_UP_B, + games::sdvx::Lights::WING_RIGHT_UP_R, + games::sdvx::Lights::WING_RIGHT_UP_G, + games::sdvx::Lights::WING_RIGHT_UP_B, + games::sdvx::Lights::WING_LEFT_LOW_R, + games::sdvx::Lights::WING_LEFT_LOW_G, + games::sdvx::Lights::WING_LEFT_LOW_B, + games::sdvx::Lights::WING_RIGHT_LOW_R, + games::sdvx::Lights::WING_RIGHT_LOW_G, + games::sdvx::Lights::WING_RIGHT_LOW_B, + games::sdvx::Lights::WOOFER_R, + games::sdvx::Lights::WOOFER_G, + games::sdvx::Lights::WOOFER_B, + games::sdvx::Lights::CONTROLLER_R, + games::sdvx::Lights::CONTROLLER_G, + games::sdvx::Lights::CONTROLLER_B, + games::sdvx::Lights::GENERATOR_R, + games::sdvx::Lights::GENERATOR_G, + }; + + // write light + float value = brightness / 255.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); + } + } + } + + // BeatStream + if (avs::game::is_model("NBT")) { + + // get lights + auto &lights = games::bs::get_lights(); + + // mapping + static const size_t mapping[] { + ~0u, ~0u, ~0u, + games::bs::Lights::RightR, + games::bs::Lights::RightG, + games::bs::Lights::RightB, + games::bs::Lights::LeftR, + games::bs::Lights::LeftG, + games::bs::Lights::LeftB, + games::bs::Lights::BottomR, + games::bs::Lights::BottomG, + games::bs::Lights::BottomB, + }; + + // write light + float value = brightness / 127.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (mapping[i] != ~0u && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); + } + } + } + + // Nostalgia + if (avs::game::is_model("PAN")) { + + // get lights + auto &lights = games::nost::get_lights(); + + // mapping + static const size_t mapping[] { + ~0u, ~0u, ~0u, + games::nost::Lights::TitleR, + games::nost::Lights::TitleG, + games::nost::Lights::TitleB, + ~0u, ~0u, ~0u, + games::nost::Lights::BottomR, + games::nost::Lights::BottomG, + games::nost::Lights::BottomB, + }; + + // write light + float value = brightness / 127.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (mapping[i] != ~0u && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); + } + } + } + + // Scotto + if (avs::game::is_model("NSC")) { + + // get lights + auto &lights = games::scotto::get_lights(); + + // mapping + static const size_t mapping[] { + games::scotto::Lights::CUP_R, + games::scotto::Lights::CUP_G, + games::scotto::Lights::CUP_B, + games::scotto::Lights::PAD_A_R, + games::scotto::Lights::PAD_A_G, + games::scotto::Lights::PAD_A_B, + games::scotto::Lights::PAD_B_R, + games::scotto::Lights::PAD_B_G, + games::scotto::Lights::PAD_B_B, + games::scotto::Lights::PAD_C_R, + games::scotto::Lights::PAD_C_G, + games::scotto::Lights::PAD_C_B, + games::scotto::Lights::PAD_D_R, + games::scotto::Lights::PAD_D_G, + games::scotto::Lights::PAD_D_B, + games::scotto::Lights::FIRST_PAD_R, + games::scotto::Lights::FIRST_PAD_G, + games::scotto::Lights::FIRST_PAD_B, + games::scotto::Lights::PAD_F_G, + games::scotto::Lights::PAD_E_G, + }; + + // write light + float value = brightness / 255.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); + } + } + } + + // return success + return 1; +} + +static char __cdecl ac_io_kfca_current_coinstock(int a1, DWORD *a2) { + *a2 = (DWORD) eamuse_coin_get_stock(); + return 1; +} + +static void *__cdecl ac_io_kfca_get_control_status_buffer(void *target_buffer) { + + // copy buffer + return memcpy(target_buffer, STATUS_BUFFER, 64); +} + +static int __cdecl ac_io_kfca_lock_coincounter(int a1) { + eamuse_coin_set_block(true); + return 1; +} + +static bool __cdecl ac_io_kfca_req_volume_control( + uint8_t vol_sound, uint8_t vol_headphone, uint8_t vol_external, uint8_t vol_woofer) { + + // update globals + KFCA_VOL_SOUND = vol_sound; + KFCA_VOL_HEADPHONE = vol_headphone; + KFCA_VOL_EXTERNAL = vol_external; + KFCA_VOL_WOOFER = vol_woofer; + + // Sound Voltex + if (avs::game::is_model("KFC")) { + + // get lights + auto &lights = games::sdvx::get_lights(); + GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_SOUND], + (100 - vol_sound) / 100.f); + GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_HEADPHONE], + (100 - vol_headphone) / 100.f); + GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_EXTERNAL], + (100 - vol_external) / 100.f); + GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_WOOFER], + (100 - vol_woofer) / 100.f); + } + + return true; +} + +static bool __cdecl ac_io_kfca_set_watchdog_time(short a1) { + return true; +} + +static char __cdecl ac_io_kfca_unlock_coincounter(int a1) { + eamuse_coin_set_block(false); + return 1; +} + +static char __cdecl ac_io_kfca_update_control_status_buffer() { + static const int input_offset = 4; + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // clear buffer + memset(STATUS_BUFFER, 0, 64); + + // SDVX + if (avs::game::is_model("KFC")) { + + // get buttons + auto &buttons = games::sdvx::get_buttons(); + + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Test))) { + STATUS_BUFFER[input_offset + 1] |= 0x20; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Service))) { + STATUS_BUFFER[input_offset + 1] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::CoinMech))) { + STATUS_BUFFER[input_offset + 1] |= 0x04; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Start))) { + STATUS_BUFFER[input_offset + 9] |= 0x08; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_A))) { + STATUS_BUFFER[input_offset + 9] |= 0x04; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_B))) { + STATUS_BUFFER[input_offset + 9] |= 0x02; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_C))) { + STATUS_BUFFER[input_offset + 9] |= 0x01; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_D))) { + STATUS_BUFFER[input_offset + 11] |= 0x20; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_L))) { + STATUS_BUFFER[input_offset + 11] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_R))) { + STATUS_BUFFER[input_offset + 11] |= 0x08; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Headphone))) { + STATUS_BUFFER[input_offset + 9] |= 0x20; + } + + // volume left + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Left))) { + KFCA_VOLL = (KFCA_VOLL - 16) & 1023; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Right))) { + KFCA_VOLL = (KFCA_VOLL + 16) & 1023; + } + + // volume right + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Left))) { + KFCA_VOLR = (KFCA_VOLR - 16) & 1023; + } + if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Right))) { + KFCA_VOLR = (KFCA_VOLR + 16) & 1023; + } + + // update volumes + auto &analogs = games::sdvx::get_analogs(); + auto vol_left = KFCA_VOLL; + auto vol_right = KFCA_VOLR; + if (analogs.at(0).isSet() || analogs.at(1).isSet()) { + vol_left += (unsigned int) (Analogs::getState(RI_MGR, + analogs.at(games::sdvx::Analogs::VOL_L)) * 1023.99f); + vol_right += (unsigned int) (Analogs::getState(RI_MGR, + analogs.at(games::sdvx::Analogs::VOL_R)) * 1023.99f); + } + + // proper loops + vol_left %= 1024; + vol_right %= 1024; + + // save volumes in buffer + STATUS_BUFFER[input_offset + 16 + 0] |= (unsigned char) ((vol_left << 6) & 0xFF); + STATUS_BUFFER[input_offset + 16 + 1] |= (unsigned char) ((vol_left >> 2) & 0xFF); + STATUS_BUFFER[input_offset + 16 + 2] |= (unsigned char) ((vol_right << 6) & 0xFF); + STATUS_BUFFER[input_offset + 16 + 3] |= (unsigned char) ((vol_right >> 2) & 0xFF); + } + + // Beatstream + if (avs::game::is_model("NBT")) { + + // get buttons + auto &buttons = games::bs::get_buttons(); + + if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Test))) { + STATUS_BUFFER[input_offset + 1] |= 0x20; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Service))) { + STATUS_BUFFER[input_offset + 1] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::CoinMech))) { + STATUS_BUFFER[input_offset + 1] |= 0x04; + } + } + + // Nostalgia + if (avs::game::is_model("PAN")) { + + // get buttons + auto &buttons = games::nost::get_buttons(); + + if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Service))) { + STATUS_BUFFER[input_offset + 1] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Test))) { + STATUS_BUFFER[input_offset + 1] |= 0x20; + } + if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::CoinMech))) { + STATUS_BUFFER[input_offset + 1] |= 0x04; + } + } + + // Scotto + if (avs::game::is_model("NSC")) { + + // get buttons + auto &buttons = games::scotto::get_buttons(); + + if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[input_offset + 1] |= 0x20; + } + if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[input_offset + 1] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::CoinMech)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[input_offset + 1] |= 0x04; + } + if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Start)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[input_offset + 9] |= 0x20; + } + if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Up)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[input_offset + 9] |= 0x10; + } + if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Down)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[input_offset + 9] |= 0x08; + } + + // the code also checks `input_offset + 9` for 0x01 but that does not trigger any response + // in the "I/O CHECK" scene + } + + // success + return true; +} + +static void __cdecl ac_io_kfca_watchdog_off() { +} + +// yes this is spelled "marge" instead of "merge" +static int __cdecl ac_io_kfca_set_status_marge_func(void *cb) { + return 1; +} + +/* + * Module stuff + */ + +acio::KFCAModule::KFCAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KFCA", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::KFCAModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_kfca_control_button_led); + ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_close); + ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_open); + ACIO_MODULE_HOOK(ac_io_kfca_control_led_bright); + ACIO_MODULE_HOOK(ac_io_kfca_current_coinstock); + ACIO_MODULE_HOOK(ac_io_kfca_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_kfca_lock_coincounter); + ACIO_MODULE_HOOK(ac_io_kfca_req_volume_control); + ACIO_MODULE_HOOK(ac_io_kfca_set_watchdog_time); + ACIO_MODULE_HOOK(ac_io_kfca_unlock_coincounter); + ACIO_MODULE_HOOK(ac_io_kfca_update_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_kfca_watchdog_off); + ACIO_MODULE_HOOK(ac_io_kfca_set_status_marge_func); +} diff --git a/acio/kfca/kfca.h b/acio/kfca/kfca.h index 85e2385..2fb464a 100644 --- a/acio/kfca/kfca.h +++ b/acio/kfca/kfca.h @@ -1,18 +1,18 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - extern uint8_t KFCA_VOL_SOUND; - extern uint8_t KFCA_VOL_HEADPHONE; - extern uint8_t KFCA_VOL_EXTERNAL; - extern uint8_t KFCA_VOL_WOOFER; - - class KFCAModule : public ACIOModule { - public: - KFCAModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + extern uint8_t KFCA_VOL_SOUND; + extern uint8_t KFCA_VOL_HEADPHONE; + extern uint8_t KFCA_VOL_EXTERNAL; + extern uint8_t KFCA_VOL_WOOFER; + + class KFCAModule : public ACIOModule { + public: + KFCAModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/klpa/klpa.cpp b/acio/klpa/klpa.cpp index 56c644b..dd39d90 100644 --- a/acio/klpa/klpa.cpp +++ b/acio/klpa/klpa.cpp @@ -1,238 +1,238 @@ -#include "klpa.h" - -#include "avs/game.h" -#include "games/loveplus/io.h" -#include "misc/eamuse.h" -#include "rawinput/rawinput.h" -#include "util/utils.h" - -using namespace GameAPI; - -static uint8_t STATUS_BUFFER[48]; -static bool STATUS_BUFFER_FREEZE = false; - -static const size_t LOVEPLUS_LIGHTS_MAPPING[] = { - games::loveplus::Lights::Red, - games::loveplus::Lights::Green, - games::loveplus::Lights::Blue, - SIZE_MAX, - games::loveplus::Lights::Right, - games::loveplus::Lights::Left, -}; - -static char __cdecl ac_io_klpa_consume_coinstock(int a1, DWORD *a2) { - *a2 = (DWORD) eamuse_coin_get_stock(); - return 1; -} - -static int __cdecl ac_io_klpa_control_coin_blocker_close(int a1) { - eamuse_coin_set_block(true); - return 1; -} - -static int __cdecl ac_io_klpa_control_coin_blocker_open(int a1) { - eamuse_coin_set_block(false); - return 1; -} - -static int __cdecl ac_io_klpa_control_led_off(size_t index) { - - // LovePlus - if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { - - // get lights - auto &lights = games::loveplus::get_lights(); - - if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { - Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 0.f); - } - } - - // return success - return 1; -} - -static int __cdecl ac_io_klpa_control_led_on(size_t index) { - - // LovePlus - if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { - - // get lights - auto &lights = games::loveplus::get_lights(); - - if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { - Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 1.f); - } - } - - // return success - return 1; -} - -static bool __cdecl ac_io_klpa_create_get_status_thread() { - return 1; -} - -static char __cdecl ac_io_klpa_current_coinstock(int a1, DWORD *a2) { - - // check bounds - if (a1 < 0 || a1 >= 2) { - return 0; - } - - *a2 = (DWORD) eamuse_coin_get_stock(); - - // return success - return 1; -} - -static bool __cdecl ac_io_klpa_destroy_get_status_thread() { - return 1; -} - -static void* __cdecl ac_io_klpa_get_control_status_buffer(void *a1) { - - // copy buffer - return memcpy(a1, STATUS_BUFFER, sizeof(STATUS_BUFFER)); -} - -static void __cdecl ac_io_klpa_get_io_command_mode(void *a1) { - memset(a1, 0, 4); -} - -static int __cdecl ac_io_klpa_led_reset() { - if (avs::game::is_model("KLP")) { - - // get lights - auto &lights = games::loveplus::get_lights(); - - for (const auto &mapping : LOVEPLUS_LIGHTS_MAPPING) { - if (mapping != SIZE_MAX) { - Lights::writeLight(RI_MGR, lights.at(mapping), 0.f); - } - } - } - - return 1; -} - -static int __cdecl ac_io_klpa_lock_coincounter(int a1) { - eamuse_coin_set_block(true); - return 1; -} - -static bool __cdecl ac_io_klpa_set_io_command_mode(int a1) { - return true; -} - -static bool __cdecl ac_io_klpa_set_io_command_mode_is_finished(uint8_t *a1) { - *a1 = 0; - return true; -} - -static int __cdecl ac_io_klpa_set_led_bright(size_t index, uint8_t brightness) { - - // LovePlus - if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { - - // get lights - auto &lights = games::loveplus::get_lights(); - - if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { - Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), brightness / 127.f); - } - } - - return 1; -} - -static bool __cdecl ac_io_klpa_set_sound_mute(int a1) { - return true; -} - -static bool __cdecl ac_io_klpa_set_sound_mute_is_finished(int a1) { - return true; -} - -static bool __cdecl ac_io_klpa_set_watchdog_time(short a1) { - return true; -} - -static char __cdecl ac_io_klpa_unlock_coincounter(int a1) { - eamuse_coin_set_block(false); - return 1; -} - -static bool __cdecl ac_io_klpa_update_control_status_buffer() { - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // reset buffer - memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); - - // LovePlus - if (avs::game::is_model("KLP")) { - - // get buttons - auto &buttons = games::loveplus::get_buttons(); - - if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[5] |= 1 << 5; - } - if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[5] |= 1 << 4; - } - if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Left)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[12] |= 1 << 6; - } - if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Right)) == Buttons::State::BUTTON_PRESSED) { - STATUS_BUFFER[12] |= 1 << 7; - } - - // x[9] & 0x3F) = volume output level? - // x[11] & 0x3F) = volume output level? - // x[12] |= (1 << 4) = headphone jack - } - - // success - return true; -} - -/* - * Module stuff - */ - -acio::KLPAModule::KLPAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KLPA", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::KLPAModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_klpa_consume_coinstock); - ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_close); - ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_open); - ACIO_MODULE_HOOK(ac_io_klpa_control_led_off); - ACIO_MODULE_HOOK(ac_io_klpa_control_led_on); - ACIO_MODULE_HOOK(ac_io_klpa_create_get_status_thread); - ACIO_MODULE_HOOK(ac_io_klpa_current_coinstock); - ACIO_MODULE_HOOK(ac_io_klpa_destroy_get_status_thread); - ACIO_MODULE_HOOK(ac_io_klpa_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_klpa_get_io_command_mode); - ACIO_MODULE_HOOK(ac_io_klpa_led_reset); - ACIO_MODULE_HOOK(ac_io_klpa_lock_coincounter); - ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode); - ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode_is_finished); - ACIO_MODULE_HOOK(ac_io_klpa_set_led_bright); - ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute); - ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute_is_finished); - ACIO_MODULE_HOOK(ac_io_klpa_set_watchdog_time); - ACIO_MODULE_HOOK(ac_io_klpa_unlock_coincounter); - ACIO_MODULE_HOOK(ac_io_klpa_update_control_status_buffer); -} +#include "klpa.h" + +#include "avs/game.h" +#include "games/loveplus/io.h" +#include "misc/eamuse.h" +#include "rawinput/rawinput.h" +#include "util/utils.h" + +using namespace GameAPI; + +static uint8_t STATUS_BUFFER[48]; +static bool STATUS_BUFFER_FREEZE = false; + +static const size_t LOVEPLUS_LIGHTS_MAPPING[] = { + games::loveplus::Lights::Red, + games::loveplus::Lights::Green, + games::loveplus::Lights::Blue, + SIZE_MAX, + games::loveplus::Lights::Right, + games::loveplus::Lights::Left, +}; + +static char __cdecl ac_io_klpa_consume_coinstock(int a1, DWORD *a2) { + *a2 = (DWORD) eamuse_coin_get_stock(); + return 1; +} + +static int __cdecl ac_io_klpa_control_coin_blocker_close(int a1) { + eamuse_coin_set_block(true); + return 1; +} + +static int __cdecl ac_io_klpa_control_coin_blocker_open(int a1) { + eamuse_coin_set_block(false); + return 1; +} + +static int __cdecl ac_io_klpa_control_led_off(size_t index) { + + // LovePlus + if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { + + // get lights + auto &lights = games::loveplus::get_lights(); + + if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { + Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 0.f); + } + } + + // return success + return 1; +} + +static int __cdecl ac_io_klpa_control_led_on(size_t index) { + + // LovePlus + if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { + + // get lights + auto &lights = games::loveplus::get_lights(); + + if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { + Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 1.f); + } + } + + // return success + return 1; +} + +static bool __cdecl ac_io_klpa_create_get_status_thread() { + return 1; +} + +static char __cdecl ac_io_klpa_current_coinstock(int a1, DWORD *a2) { + + // check bounds + if (a1 < 0 || a1 >= 2) { + return 0; + } + + *a2 = (DWORD) eamuse_coin_get_stock(); + + // return success + return 1; +} + +static bool __cdecl ac_io_klpa_destroy_get_status_thread() { + return 1; +} + +static void* __cdecl ac_io_klpa_get_control_status_buffer(void *a1) { + + // copy buffer + return memcpy(a1, STATUS_BUFFER, sizeof(STATUS_BUFFER)); +} + +static void __cdecl ac_io_klpa_get_io_command_mode(void *a1) { + memset(a1, 0, 4); +} + +static int __cdecl ac_io_klpa_led_reset() { + if (avs::game::is_model("KLP")) { + + // get lights + auto &lights = games::loveplus::get_lights(); + + for (const auto &mapping : LOVEPLUS_LIGHTS_MAPPING) { + if (mapping != SIZE_MAX) { + Lights::writeLight(RI_MGR, lights.at(mapping), 0.f); + } + } + } + + return 1; +} + +static int __cdecl ac_io_klpa_lock_coincounter(int a1) { + eamuse_coin_set_block(true); + return 1; +} + +static bool __cdecl ac_io_klpa_set_io_command_mode(int a1) { + return true; +} + +static bool __cdecl ac_io_klpa_set_io_command_mode_is_finished(uint8_t *a1) { + *a1 = 0; + return true; +} + +static int __cdecl ac_io_klpa_set_led_bright(size_t index, uint8_t brightness) { + + // LovePlus + if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { + + // get lights + auto &lights = games::loveplus::get_lights(); + + if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { + Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), brightness / 127.f); + } + } + + return 1; +} + +static bool __cdecl ac_io_klpa_set_sound_mute(int a1) { + return true; +} + +static bool __cdecl ac_io_klpa_set_sound_mute_is_finished(int a1) { + return true; +} + +static bool __cdecl ac_io_klpa_set_watchdog_time(short a1) { + return true; +} + +static char __cdecl ac_io_klpa_unlock_coincounter(int a1) { + eamuse_coin_set_block(false); + return 1; +} + +static bool __cdecl ac_io_klpa_update_control_status_buffer() { + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // reset buffer + memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); + + // LovePlus + if (avs::game::is_model("KLP")) { + + // get buttons + auto &buttons = games::loveplus::get_buttons(); + + if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[5] |= 1 << 5; + } + if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[5] |= 1 << 4; + } + if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Left)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[12] |= 1 << 6; + } + if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Right)) == Buttons::State::BUTTON_PRESSED) { + STATUS_BUFFER[12] |= 1 << 7; + } + + // x[9] & 0x3F) = volume output level? + // x[11] & 0x3F) = volume output level? + // x[12] |= (1 << 4) = headphone jack + } + + // success + return true; +} + +/* + * Module stuff + */ + +acio::KLPAModule::KLPAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KLPA", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::KLPAModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_klpa_consume_coinstock); + ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_close); + ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_open); + ACIO_MODULE_HOOK(ac_io_klpa_control_led_off); + ACIO_MODULE_HOOK(ac_io_klpa_control_led_on); + ACIO_MODULE_HOOK(ac_io_klpa_create_get_status_thread); + ACIO_MODULE_HOOK(ac_io_klpa_current_coinstock); + ACIO_MODULE_HOOK(ac_io_klpa_destroy_get_status_thread); + ACIO_MODULE_HOOK(ac_io_klpa_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_klpa_get_io_command_mode); + ACIO_MODULE_HOOK(ac_io_klpa_led_reset); + ACIO_MODULE_HOOK(ac_io_klpa_lock_coincounter); + ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode); + ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode_is_finished); + ACIO_MODULE_HOOK(ac_io_klpa_set_led_bright); + ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute); + ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute_is_finished); + ACIO_MODULE_HOOK(ac_io_klpa_set_watchdog_time); + ACIO_MODULE_HOOK(ac_io_klpa_unlock_coincounter); + ACIO_MODULE_HOOK(ac_io_klpa_update_control_status_buffer); +} diff --git a/acio/klpa/klpa.h b/acio/klpa/klpa.h index 1ef0bc2..79ca4a5 100644 --- a/acio/klpa/klpa.h +++ b/acio/klpa/klpa.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class KLPAModule : public ACIOModule { - public: - KLPAModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class KLPAModule : public ACIOModule { + public: + KLPAModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/mdxf/mdxf.h b/acio/mdxf/mdxf.h index e6f48a7..cf22516 100644 --- a/acio/mdxf/mdxf.h +++ b/acio/mdxf/mdxf.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class MDXFModule : public ACIOModule { - public: - MDXFModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class MDXFModule : public ACIOModule { + public: + MDXFModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/module.h b/acio/module.h index eaf6041..da07c09 100644 --- a/acio/module.h +++ b/acio/module.h @@ -1,55 +1,55 @@ -#pragma once - -#include -#include - -// macro for lazy typing of hooks -#define ACIO_MODULE_HOOK(f) this->hook(reinterpret_cast(f), #f) - -namespace acio { - - /* - * Hook Modes - * Since some versions can't handle inline hooking - */ - enum class HookMode { - INLINE, - IAT - }; - - // this makes logging easier - const char *hook_mode_str(HookMode hook_mode); - - /* - * The ACIO module itself - * Inherit this for extending our libacio implementation - */ - class ACIOModule { - protected: - - // the magic - void hook(void* func, const char *func_name); - - public: - - ACIOModule(std::string name, HMODULE module, HookMode hook_mode) : - name(std::move(name)), - module(module), - hook_mode(hook_mode) {}; - - virtual ~ACIOModule() = default; - - virtual void attach(); - - // settings - std::string name; - HMODULE module; - HookMode hook_mode; - bool attached = false; - - // buffer state (optional) - uint8_t *status_buffer = nullptr; - size_t status_buffer_size = 0; - bool *status_buffer_freeze = nullptr; - }; -} +#pragma once + +#include +#include + +// macro for lazy typing of hooks +#define ACIO_MODULE_HOOK(f) this->hook(reinterpret_cast(f), #f) + +namespace acio { + + /* + * Hook Modes + * Since some versions can't handle inline hooking + */ + enum class HookMode { + INLINE, + IAT + }; + + // this makes logging easier + const char *hook_mode_str(HookMode hook_mode); + + /* + * The ACIO module itself + * Inherit this for extending our libacio implementation + */ + class ACIOModule { + protected: + + // the magic + void hook(void* func, const char *func_name); + + public: + + ACIOModule(std::string name, HMODULE module, HookMode hook_mode) : + name(std::move(name)), + module(module), + hook_mode(hook_mode) {}; + + virtual ~ACIOModule() = default; + + virtual void attach(); + + // settings + std::string name; + HMODULE module; + HookMode hook_mode; + bool attached = false; + + // buffer state (optional) + uint8_t *status_buffer = nullptr; + size_t status_buffer_size = 0; + bool *status_buffer_freeze = nullptr; + }; +} diff --git a/acio/nddb/nddb.cpp b/acio/nddb/nddb.cpp index 4bcf881..2b0910a 100644 --- a/acio/nddb/nddb.cpp +++ b/acio/nddb/nddb.cpp @@ -1,64 +1,64 @@ -#include "nddb.h" - -#include "avs/game.h" -#include "misc/eamuse.h" -#include "util/utils.h" - -// static stuff -static uint8_t STATUS_BUFFER[4] {}; -static bool STATUS_BUFFER_FREEZE = false; - -/* - * Implementations - */ - -static void __cdecl ac_io_nddb_control_pwm(int a1, int a2) { - log_misc("acio::nddb", "ac_io_nddb_control_pwm({}, {})", a1, a2); -} - -static void __cdecl ac_io_nddb_control_solenoide(int a1, int a2) { - log_misc("acio::nddb", "ac_io_nddb_control_solenoide({}, {})", a1, a2); -} - -static bool __cdecl ac_io_nddb_create_get_status_thread() { - return true; -} - -static bool __cdecl ac_io_nddb_destroy_get_status_thread() { - return true; -} - -static void __cdecl ac_io_nddb_get_control_status_buffer(void *buffer) { -} - -static bool __cdecl ac_io_nddb_req_solenoide_control(uint8_t *buffer) { - log_misc("acio::nddb", "ac_io_nddb_req_solenoide_control"); - - return true; -} - -static bool __cdecl ac_io_nddb_update_control_status_buffer() { - return true; -} - -/* - * Module stuff - */ - -acio::NDDBModule::NDDBModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("NDDB", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::NDDBModule::attach() { - ACIOModule::attach(); - - ACIO_MODULE_HOOK(ac_io_nddb_control_pwm); - ACIO_MODULE_HOOK(ac_io_nddb_control_solenoide); - ACIO_MODULE_HOOK(ac_io_nddb_create_get_status_thread); - ACIO_MODULE_HOOK(ac_io_nddb_destroy_get_status_thread); - ACIO_MODULE_HOOK(ac_io_nddb_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_nddb_req_solenoide_control); - ACIO_MODULE_HOOK(ac_io_nddb_update_control_status_buffer); -} +#include "nddb.h" + +#include "avs/game.h" +#include "misc/eamuse.h" +#include "util/utils.h" + +// static stuff +static uint8_t STATUS_BUFFER[4] {}; +static bool STATUS_BUFFER_FREEZE = false; + +/* + * Implementations + */ + +static void __cdecl ac_io_nddb_control_pwm(int a1, int a2) { + log_misc("acio::nddb", "ac_io_nddb_control_pwm({}, {})", a1, a2); +} + +static void __cdecl ac_io_nddb_control_solenoide(int a1, int a2) { + log_misc("acio::nddb", "ac_io_nddb_control_solenoide({}, {})", a1, a2); +} + +static bool __cdecl ac_io_nddb_create_get_status_thread() { + return true; +} + +static bool __cdecl ac_io_nddb_destroy_get_status_thread() { + return true; +} + +static void __cdecl ac_io_nddb_get_control_status_buffer(void *buffer) { +} + +static bool __cdecl ac_io_nddb_req_solenoide_control(uint8_t *buffer) { + log_misc("acio::nddb", "ac_io_nddb_req_solenoide_control"); + + return true; +} + +static bool __cdecl ac_io_nddb_update_control_status_buffer() { + return true; +} + +/* + * Module stuff + */ + +acio::NDDBModule::NDDBModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("NDDB", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::NDDBModule::attach() { + ACIOModule::attach(); + + ACIO_MODULE_HOOK(ac_io_nddb_control_pwm); + ACIO_MODULE_HOOK(ac_io_nddb_control_solenoide); + ACIO_MODULE_HOOK(ac_io_nddb_create_get_status_thread); + ACIO_MODULE_HOOK(ac_io_nddb_destroy_get_status_thread); + ACIO_MODULE_HOOK(ac_io_nddb_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_nddb_req_solenoide_control); + ACIO_MODULE_HOOK(ac_io_nddb_update_control_status_buffer); +} diff --git a/acio/nddb/nddb.h b/acio/nddb/nddb.h index be1eae4..92e18ba 100644 --- a/acio/nddb/nddb.h +++ b/acio/nddb/nddb.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class NDDBModule : public ACIOModule { - public: - NDDBModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class NDDBModule : public ACIOModule { + public: + NDDBModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/panb/panb.h b/acio/panb/panb.h index d910e44..ebbc067 100644 --- a/acio/panb/panb.h +++ b/acio/panb/panb.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class PANBModule : public ACIOModule { - public: - PANBModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class PANBModule : public ACIOModule { + public: + PANBModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/pix/pix.cpp b/acio/pix/pix.cpp index dad37f7..511f716 100644 --- a/acio/pix/pix.cpp +++ b/acio/pix/pix.cpp @@ -1,520 +1,520 @@ -#include "pix.h" -#include "launcher/launcher.h" -#include "rawinput/rawinput.h" -#include "games/museca/io.h" -#include "games/bbc/io.h" -#include "util/utils.h" -#include "avs/game.h" - -using namespace GameAPI; - -// static stuff -static int ACIO_PIX_WARMUP = 0; -static uint8_t STATUS_BUFFER[60]; -static bool STATUS_BUFFER_FREEZE = false; - -/* - * Implementations - */ - -static char __cdecl ac_io_pix_begin(char a1, long long a2, int a3, int a4, int a5, int a6) { - return 1; -} - -static char __cdecl ac_io_pix_begin_get_status(int a1, int a2) { - return 1; -} - -static char __cdecl ac_io_pix_end(int a1) { - return 1; -} - -static char __cdecl ac_io_pix_end_get_status(int a1) { - return 1; -} - -static char __cdecl ac_io_pix_get_firmware_update_device_index(int a1) { - return 1; -} - -static char __cdecl ac_io_pix_get_node_no(int a1, int a2) { - return 1; -} - -static void *__cdecl ac_io_pix_get_recv_log(long long a1, void *a2, int a3) { - return a2; -} - -static void *__cdecl ac_io_pix_get_rs232c_status(void *a1, int a2) { - return a1; -} - -static void *__cdecl ac_io_pix_get_send_log(long long a1, void *a2, int a3) { - return a2; -} - -static char __cdecl ac_io_pix_get_version(void *a1, int a2, int a3) { - return 1; -} - -static const char *__cdecl ac_io_pix_get_version_string() { - static const char *version = "1.25.0"; - return version; -} - -static char __cdecl ac_io_pix_go_firmware_update(int a1) { - return 1; -} - -static char __cdecl ac_io_pix_is_active(int a1, int a2) { - return (char) (++ACIO_PIX_WARMUP > 601 ? 1 : 0); -} - -static char __cdecl ac_io_pix_is_active2(int a1, int *a2, int a3) { - ACIO_PIX_WARMUP = 601; - *a2 = 6; - return 1; -} - -static char __cdecl ac_io_pix_is_active_device(int a1, int a2) { - return (char) (a1 != 5); -} - -static long long __cdecl ac_io_pix_reset(int a1) { - return a1; -} - -static bool __cdecl ac_io_pix_rvol_change_expand_mode(char a1) { - return true; -} - -static long long __cdecl ac_io_pix_rvol_control_led_bright(uint32_t led_field, uint8_t brightness) { - - // MUSECA - if (avs::game::is_model("PIX")) { - - // get lights - auto &lights = games::museca::get_lights(); - - // control mapping - static int mapping[] = { - games::museca::Lights::Spinner1R, - games::museca::Lights::Spinner1G, - games::museca::Lights::Spinner1B, - games::museca::Lights::Spinner2R, - games::museca::Lights::Spinner2G, - games::museca::Lights::Spinner2B, - games::museca::Lights::Spinner3R, - games::museca::Lights::Spinner3G, - games::museca::Lights::Spinner3B, - games::museca::Lights::Spinner4R, - games::museca::Lights::Spinner4G, - games::museca::Lights::Spinner4B, - games::museca::Lights::Spinner5R, - games::museca::Lights::Spinner5G, - games::museca::Lights::Spinner5B, - games::museca::Lights::TitleR, - games::museca::Lights::TitleG, - games::museca::Lights::TitleB - }; - - // write light - float value = brightness > 127.f ? 1.f : brightness / 127.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (mapping[i] >= 0 && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); - } - } - } - - // BISHI BASHI CHANNEL - if (avs::game::is_model("R66")) { - - // get lights - auto &lights = games::bbc::get_lights(); - - // control mapping - static int mapping[] = { - games::bbc::Lights::P1_DISC_R, - games::bbc::Lights::P1_DISC_G, - games::bbc::Lights::P1_DISC_B, - games::bbc::Lights::P3_DISC_R, - games::bbc::Lights::P3_DISC_G, - games::bbc::Lights::P3_DISC_B, - games::bbc::Lights::P2_DISC_R, - games::bbc::Lights::P2_DISC_G, - games::bbc::Lights::P2_DISC_B, - games::bbc::Lights::P4_DISC_R, - games::bbc::Lights::P4_DISC_G, - games::bbc::Lights::P4_DISC_B, - games::bbc::Lights::P1_R, - games::bbc::Lights::P1_B, - -1, -1, -1, -1, -1, -1, - games::bbc::Lights::P2_R, - games::bbc::Lights::P2_B, - games::bbc::Lights::P3_R, - games::bbc::Lights::P3_B, - games::bbc::Lights::P4_R, - games::bbc::Lights::P4_B, - }; - - // write light - float value = brightness / 255.f; - for (size_t i = 0; i < std::size(mapping); i++) { - if (mapping[i] >= 0 && led_field & (1 << i)) { - Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); - } - } - } - - // return success - return 1; -} - -static long long __cdecl ac_io_pix_rvol_control_reset() { - return 1; -} - -static bool __cdecl ac_io_pix_rvol_create_get_status_thread() { - return true; -} - -static long long __cdecl ac_io_pix_rvol_destroy_get_status_thread() { - return 1; -} - -static void *__cdecl ac_io_pix_rvol_get_control_status_buffer(void *a1) { - - // copy buffer - return memcpy(a1, STATUS_BUFFER, sizeof(STATUS_BUFFER)); -} - -static bool __cdecl ac_io_pix_rvol_get_watchdog_status() { - return true; -} - -static short __cdecl ac_io_pix_rvol_get_watchdog_time_min() { - return 0; -} - -static short __cdecl ac_io_pix_rvol_get_watchdog_time_now() { - return 0; -} - -static bool __cdecl ac_io_pix_rvol_modify_auto_input_get(long long a1, long long a2) { - return true; -} - -static char __cdecl ac_io_pix_rvol_req_get_control_status(DWORD *a1) { - *a1 = 1; - return 1; -} - -static bool __cdecl ac_io_pix_rvol_req_volume_control(char a1, char a2, char a3, char a4) { - return true; -} - -static bool __cdecl ac_io_pix_rvol_req_volume_control_isfinished(DWORD *a1) { - *a1 = 5; - return true; -} - -static long long __cdecl ac_io_pix_rvol_set_framing_err_packet_send_interval(long long a1) { - return a1; -} - -static bool __cdecl ac_io_pix_rvol_set_watchdog_time(short a1) { - return true; -} - -static bool __cdecl ac_io_pix_rvol_update_control_status_buffer() { - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // clear buffer - memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); - - // MUSECA - if (avs::game::is_model("PIX")) { - - // get input - auto &buttons = games::museca::get_buttons(); - - // get slowdown status - bool slowdown = Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::AnalogSlowdown)); - - // update disk buttons - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk1Press))) - ARRAY_SETB(STATUS_BUFFER, 107); - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk2Press))) - ARRAY_SETB(STATUS_BUFFER, 104); - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk3Press))) - ARRAY_SETB(STATUS_BUFFER, 123); - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk4Press))) - ARRAY_SETB(STATUS_BUFFER, 42); - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk5Press))) - ARRAY_SETB(STATUS_BUFFER, 44); - - // foot pedal (inverted) - if (!Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::FootPedal))) - ARRAY_SETB(STATUS_BUFFER, 43); - - // update analogs - static uint8_t analogs[5] = { 0, 0, 0, 0, 0 }; - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk1Minus))) { - analogs[0] -= slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk1Plus))) { - analogs[0] += slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk2Minus))) { - analogs[1] -= slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk2Plus))) { - analogs[1] += slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk3Minus))) { - analogs[2] -= slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk3Plus))) { - analogs[2] += slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk4Minus))) { - analogs[3] -= slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk4Plus))) { - analogs[3] += slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk5Minus))) { - analogs[4] -= slowdown ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk5Plus))) { - analogs[4] += slowdown ? 3 : 12; - } - - // raw input analogs - auto &analog_list = games::museca::get_analogs(); - size_t analog_mapping[] = { - games::museca::Analogs::Disk1, - games::museca::Analogs::Disk2, - games::museca::Analogs::Disk3, - games::museca::Analogs::Disk4, - games::museca::Analogs::Disk5, - }; - uint8_t set_values[5]; - std::copy(std::begin(analogs), std::end(analogs), std::begin(set_values)); - for (size_t i = 0; i < 5; i++) { - auto &analog_item = analog_list.at(analog_mapping[i]); - if (analog_item.isSet()) { - set_values[i] = analogs[i] + (uint8_t) (Analogs::getState(RI_MGR, analog_item) * 255.99f); - } - } - - // set analogs - for (int i = 0; i < 5; i++) - STATUS_BUFFER[20 + i] = set_values[i]; - } - - // BISHI BASHI CHANNEL - if (avs::game::is_model("R66")) { - - // get input - auto &buttons = games::bbc::get_buttons(); - auto &analogs = games::bbc::get_analogs(); - - // get slowdown status - bool slowdown1 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_DiskSlowdown)); - bool slowdown2 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_DiskSlowdown)); - bool slowdown3 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_DiskSlowdown)); - bool slowdown4 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_DiskSlowdown)); - - // update buttons - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_R)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 44); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_G)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 107); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_B)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 41); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_R)) == Buttons::State::BUTTON_NOT_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 39); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_G)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 123); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_B)) == Buttons::State::BUTTON_NOT_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 55); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_R)) == Buttons::State::BUTTON_NOT_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 71); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_G)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 104); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_B)) == Buttons::State::BUTTON_NOT_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 87); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_R)) == Buttons::State::BUTTON_NOT_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 103); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_G)) == Buttons::State::BUTTON_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 42); - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_B)) == Buttons::State::BUTTON_NOT_PRESSED) { - ARRAY_SETB(STATUS_BUFFER, 119); - } - - // update analogs - static uint8_t analog_states[4] = { 0, 0, 0, 0 }; - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[0] -= slowdown1 ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[0] += slowdown1 ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[1] -= slowdown2 ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[1] += slowdown2 ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[2] -= slowdown3 ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[2] += slowdown3 ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[3] -= slowdown4 ? 3 : 12; - } - if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { - analog_states[3] += slowdown4 ? 3 : 12; - } - - // raw input analogs - uint8_t set_values[4]; - size_t analog_mappings[] = { - games::bbc::Analogs::P1_Disk, - games::bbc::Analogs::P2_Disk, - games::bbc::Analogs::P3_Disk, - games::bbc::Analogs::P4_Disk, - }; - std::copy(std::begin(analog_states), std::end(analog_states), std::begin(set_values)); - for (size_t i = 0; i < 4; i++) { - auto &analog_item = analogs.at(analog_mappings[i]); - if (analog_item.isSet()) { - set_values[i] = analog_states[i] + (uint8_t) (Analogs::getState(RI_MGR, analog_item) * 255.99f); - } - } - - // flip disk 2/3 - set_values[1] ^= set_values[2]; - set_values[2] ^= set_values[1]; - set_values[1] ^= set_values[2]; - - // set analogs - for (int i = 0; i < 4; i++) { - STATUS_BUFFER[20 + i] = set_values[i]; - } - } - - // success - return true; -} - -static void __cdecl ac_io_pix_rvol_watchdog_off() { -} - -static void *__cdecl ac_io_pix_secplug_set_encodedpasswd(void *a1, unsigned int a2) { - return a1; -} - -static void *__cdecl ac_io_pix_set_get_status_device(void *a1, int a2) { - return a1; -} - -static void *__cdecl ac_io_pix_set_soft_watch_dog(void *a1, int a2) { - return a1; -} - -static char __cdecl ac_io_pix_soft_watch_dog_off(int a1) { - return 1; -} - -static char __cdecl ac_io_pix_soft_watch_dog_on(int a1) { - return 1; -} - -static char __cdecl ac_io_pix_update(long long a1) { - - // flush outputs - RI_MGR->devices_flush_output(); - - return 1; -} - -static const char* __cdecl ac_io_pix_version() { - static const char *version = "Version: 1.25.0\nBuild Date: Sep 20 2016 15:16:13\nBuild Host: DEMETER\n"; - return version; -} - -/* - * Module stuff - */ - -acio::PIXModule::PIXModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("PIX", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::PIXModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_pix_begin); - ACIO_MODULE_HOOK(ac_io_pix_begin_get_status); - ACIO_MODULE_HOOK(ac_io_pix_end); - ACIO_MODULE_HOOK(ac_io_pix_end_get_status); - ACIO_MODULE_HOOK(ac_io_pix_get_firmware_update_device_index); - ACIO_MODULE_HOOK(ac_io_pix_get_node_no); - ACIO_MODULE_HOOK(ac_io_pix_get_recv_log); - ACIO_MODULE_HOOK(ac_io_pix_get_rs232c_status); - ACIO_MODULE_HOOK(ac_io_pix_get_send_log); - ACIO_MODULE_HOOK(ac_io_pix_get_version); - ACIO_MODULE_HOOK(ac_io_pix_get_version_string); - ACIO_MODULE_HOOK(ac_io_pix_go_firmware_update); - ACIO_MODULE_HOOK(ac_io_pix_is_active); - ACIO_MODULE_HOOK(ac_io_pix_is_active2); - ACIO_MODULE_HOOK(ac_io_pix_is_active_device); - ACIO_MODULE_HOOK(ac_io_pix_reset); - ACIO_MODULE_HOOK(ac_io_pix_rvol_change_expand_mode); - ACIO_MODULE_HOOK(ac_io_pix_rvol_control_led_bright); - ACIO_MODULE_HOOK(ac_io_pix_rvol_control_reset); - ACIO_MODULE_HOOK(ac_io_pix_rvol_create_get_status_thread); - ACIO_MODULE_HOOK(ac_io_pix_rvol_destroy_get_status_thread); - ACIO_MODULE_HOOK(ac_io_pix_rvol_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_pix_rvol_get_watchdog_status); - ACIO_MODULE_HOOK(ac_io_pix_rvol_get_watchdog_time_min); - ACIO_MODULE_HOOK(ac_io_pix_rvol_get_watchdog_time_now); - ACIO_MODULE_HOOK(ac_io_pix_rvol_modify_auto_input_get); - ACIO_MODULE_HOOK(ac_io_pix_rvol_req_get_control_status); - ACIO_MODULE_HOOK(ac_io_pix_rvol_req_volume_control); - ACIO_MODULE_HOOK(ac_io_pix_rvol_req_volume_control_isfinished); - ACIO_MODULE_HOOK(ac_io_pix_rvol_set_framing_err_packet_send_interval); - ACIO_MODULE_HOOK(ac_io_pix_rvol_set_watchdog_time); - ACIO_MODULE_HOOK(ac_io_pix_rvol_update_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_pix_rvol_watchdog_off); - ACIO_MODULE_HOOK(ac_io_pix_secplug_set_encodedpasswd); - ACIO_MODULE_HOOK(ac_io_pix_set_get_status_device); - ACIO_MODULE_HOOK(ac_io_pix_set_soft_watch_dog); - ACIO_MODULE_HOOK(ac_io_pix_soft_watch_dog_off); - ACIO_MODULE_HOOK(ac_io_pix_soft_watch_dog_on); - ACIO_MODULE_HOOK(ac_io_pix_update); - ACIO_MODULE_HOOK(ac_io_pix_version); -} +#include "pix.h" +#include "launcher/launcher.h" +#include "rawinput/rawinput.h" +#include "games/museca/io.h" +#include "games/bbc/io.h" +#include "util/utils.h" +#include "avs/game.h" + +using namespace GameAPI; + +// static stuff +static int ACIO_PIX_WARMUP = 0; +static uint8_t STATUS_BUFFER[60]; +static bool STATUS_BUFFER_FREEZE = false; + +/* + * Implementations + */ + +static char __cdecl ac_io_pix_begin(char a1, long long a2, int a3, int a4, int a5, int a6) { + return 1; +} + +static char __cdecl ac_io_pix_begin_get_status(int a1, int a2) { + return 1; +} + +static char __cdecl ac_io_pix_end(int a1) { + return 1; +} + +static char __cdecl ac_io_pix_end_get_status(int a1) { + return 1; +} + +static char __cdecl ac_io_pix_get_firmware_update_device_index(int a1) { + return 1; +} + +static char __cdecl ac_io_pix_get_node_no(int a1, int a2) { + return 1; +} + +static void *__cdecl ac_io_pix_get_recv_log(long long a1, void *a2, int a3) { + return a2; +} + +static void *__cdecl ac_io_pix_get_rs232c_status(void *a1, int a2) { + return a1; +} + +static void *__cdecl ac_io_pix_get_send_log(long long a1, void *a2, int a3) { + return a2; +} + +static char __cdecl ac_io_pix_get_version(void *a1, int a2, int a3) { + return 1; +} + +static const char *__cdecl ac_io_pix_get_version_string() { + static const char *version = "1.25.0"; + return version; +} + +static char __cdecl ac_io_pix_go_firmware_update(int a1) { + return 1; +} + +static char __cdecl ac_io_pix_is_active(int a1, int a2) { + return (char) (++ACIO_PIX_WARMUP > 601 ? 1 : 0); +} + +static char __cdecl ac_io_pix_is_active2(int a1, int *a2, int a3) { + ACIO_PIX_WARMUP = 601; + *a2 = 6; + return 1; +} + +static char __cdecl ac_io_pix_is_active_device(int a1, int a2) { + return (char) (a1 != 5); +} + +static long long __cdecl ac_io_pix_reset(int a1) { + return a1; +} + +static bool __cdecl ac_io_pix_rvol_change_expand_mode(char a1) { + return true; +} + +static long long __cdecl ac_io_pix_rvol_control_led_bright(uint32_t led_field, uint8_t brightness) { + + // MUSECA + if (avs::game::is_model("PIX")) { + + // get lights + auto &lights = games::museca::get_lights(); + + // control mapping + static int mapping[] = { + games::museca::Lights::Spinner1R, + games::museca::Lights::Spinner1G, + games::museca::Lights::Spinner1B, + games::museca::Lights::Spinner2R, + games::museca::Lights::Spinner2G, + games::museca::Lights::Spinner2B, + games::museca::Lights::Spinner3R, + games::museca::Lights::Spinner3G, + games::museca::Lights::Spinner3B, + games::museca::Lights::Spinner4R, + games::museca::Lights::Spinner4G, + games::museca::Lights::Spinner4B, + games::museca::Lights::Spinner5R, + games::museca::Lights::Spinner5G, + games::museca::Lights::Spinner5B, + games::museca::Lights::TitleR, + games::museca::Lights::TitleG, + games::museca::Lights::TitleB + }; + + // write light + float value = brightness > 127.f ? 1.f : brightness / 127.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (mapping[i] >= 0 && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); + } + } + } + + // BISHI BASHI CHANNEL + if (avs::game::is_model("R66")) { + + // get lights + auto &lights = games::bbc::get_lights(); + + // control mapping + static int mapping[] = { + games::bbc::Lights::P1_DISC_R, + games::bbc::Lights::P1_DISC_G, + games::bbc::Lights::P1_DISC_B, + games::bbc::Lights::P3_DISC_R, + games::bbc::Lights::P3_DISC_G, + games::bbc::Lights::P3_DISC_B, + games::bbc::Lights::P2_DISC_R, + games::bbc::Lights::P2_DISC_G, + games::bbc::Lights::P2_DISC_B, + games::bbc::Lights::P4_DISC_R, + games::bbc::Lights::P4_DISC_G, + games::bbc::Lights::P4_DISC_B, + games::bbc::Lights::P1_R, + games::bbc::Lights::P1_B, + -1, -1, -1, -1, -1, -1, + games::bbc::Lights::P2_R, + games::bbc::Lights::P2_B, + games::bbc::Lights::P3_R, + games::bbc::Lights::P3_B, + games::bbc::Lights::P4_R, + games::bbc::Lights::P4_B, + }; + + // write light + float value = brightness / 255.f; + for (size_t i = 0; i < std::size(mapping); i++) { + if (mapping[i] >= 0 && led_field & (1 << i)) { + Lights::writeLight(RI_MGR, lights.at((size_t) mapping[i]), value); + } + } + } + + // return success + return 1; +} + +static long long __cdecl ac_io_pix_rvol_control_reset() { + return 1; +} + +static bool __cdecl ac_io_pix_rvol_create_get_status_thread() { + return true; +} + +static long long __cdecl ac_io_pix_rvol_destroy_get_status_thread() { + return 1; +} + +static void *__cdecl ac_io_pix_rvol_get_control_status_buffer(void *a1) { + + // copy buffer + return memcpy(a1, STATUS_BUFFER, sizeof(STATUS_BUFFER)); +} + +static bool __cdecl ac_io_pix_rvol_get_watchdog_status() { + return true; +} + +static short __cdecl ac_io_pix_rvol_get_watchdog_time_min() { + return 0; +} + +static short __cdecl ac_io_pix_rvol_get_watchdog_time_now() { + return 0; +} + +static bool __cdecl ac_io_pix_rvol_modify_auto_input_get(long long a1, long long a2) { + return true; +} + +static char __cdecl ac_io_pix_rvol_req_get_control_status(DWORD *a1) { + *a1 = 1; + return 1; +} + +static bool __cdecl ac_io_pix_rvol_req_volume_control(char a1, char a2, char a3, char a4) { + return true; +} + +static bool __cdecl ac_io_pix_rvol_req_volume_control_isfinished(DWORD *a1) { + *a1 = 5; + return true; +} + +static long long __cdecl ac_io_pix_rvol_set_framing_err_packet_send_interval(long long a1) { + return a1; +} + +static bool __cdecl ac_io_pix_rvol_set_watchdog_time(short a1) { + return true; +} + +static bool __cdecl ac_io_pix_rvol_update_control_status_buffer() { + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // clear buffer + memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); + + // MUSECA + if (avs::game::is_model("PIX")) { + + // get input + auto &buttons = games::museca::get_buttons(); + + // get slowdown status + bool slowdown = Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::AnalogSlowdown)); + + // update disk buttons + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk1Press))) + ARRAY_SETB(STATUS_BUFFER, 107); + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk2Press))) + ARRAY_SETB(STATUS_BUFFER, 104); + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk3Press))) + ARRAY_SETB(STATUS_BUFFER, 123); + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk4Press))) + ARRAY_SETB(STATUS_BUFFER, 42); + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk5Press))) + ARRAY_SETB(STATUS_BUFFER, 44); + + // foot pedal (inverted) + if (!Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::FootPedal))) + ARRAY_SETB(STATUS_BUFFER, 43); + + // update analogs + static uint8_t analogs[5] = { 0, 0, 0, 0, 0 }; + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk1Minus))) { + analogs[0] -= slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk1Plus))) { + analogs[0] += slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk2Minus))) { + analogs[1] -= slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk2Plus))) { + analogs[1] += slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk3Minus))) { + analogs[2] -= slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk3Plus))) { + analogs[2] += slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk4Minus))) { + analogs[3] -= slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk4Plus))) { + analogs[3] += slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk5Minus))) { + analogs[4] -= slowdown ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::museca::Buttons::Disk5Plus))) { + analogs[4] += slowdown ? 3 : 12; + } + + // raw input analogs + auto &analog_list = games::museca::get_analogs(); + size_t analog_mapping[] = { + games::museca::Analogs::Disk1, + games::museca::Analogs::Disk2, + games::museca::Analogs::Disk3, + games::museca::Analogs::Disk4, + games::museca::Analogs::Disk5, + }; + uint8_t set_values[5]; + std::copy(std::begin(analogs), std::end(analogs), std::begin(set_values)); + for (size_t i = 0; i < 5; i++) { + auto &analog_item = analog_list.at(analog_mapping[i]); + if (analog_item.isSet()) { + set_values[i] = analogs[i] + (uint8_t) (Analogs::getState(RI_MGR, analog_item) * 255.99f); + } + } + + // set analogs + for (int i = 0; i < 5; i++) + STATUS_BUFFER[20 + i] = set_values[i]; + } + + // BISHI BASHI CHANNEL + if (avs::game::is_model("R66")) { + + // get input + auto &buttons = games::bbc::get_buttons(); + auto &analogs = games::bbc::get_analogs(); + + // get slowdown status + bool slowdown1 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_DiskSlowdown)); + bool slowdown2 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_DiskSlowdown)); + bool slowdown3 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_DiskSlowdown)); + bool slowdown4 = Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_DiskSlowdown)); + + // update buttons + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_R)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 44); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_G)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 107); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_B)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 41); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_R)) == Buttons::State::BUTTON_NOT_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 39); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_G)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 123); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_B)) == Buttons::State::BUTTON_NOT_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 55); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_R)) == Buttons::State::BUTTON_NOT_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 71); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_G)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 104); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_B)) == Buttons::State::BUTTON_NOT_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 87); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_R)) == Buttons::State::BUTTON_NOT_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 103); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_G)) == Buttons::State::BUTTON_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 42); + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_B)) == Buttons::State::BUTTON_NOT_PRESSED) { + ARRAY_SETB(STATUS_BUFFER, 119); + } + + // update analogs + static uint8_t analog_states[4] = { 0, 0, 0, 0 }; + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[0] -= slowdown1 ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P1_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[0] += slowdown1 ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[1] -= slowdown2 ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P2_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[1] += slowdown2 ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[2] -= slowdown3 ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P3_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[2] += slowdown3 ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_DiskMinus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[3] -= slowdown4 ? 3 : 12; + } + if (Buttons::getState(RI_MGR, buttons.at(games::bbc::Buttons::P4_DiskPlus)) == Buttons::State::BUTTON_PRESSED) { + analog_states[3] += slowdown4 ? 3 : 12; + } + + // raw input analogs + uint8_t set_values[4]; + size_t analog_mappings[] = { + games::bbc::Analogs::P1_Disk, + games::bbc::Analogs::P2_Disk, + games::bbc::Analogs::P3_Disk, + games::bbc::Analogs::P4_Disk, + }; + std::copy(std::begin(analog_states), std::end(analog_states), std::begin(set_values)); + for (size_t i = 0; i < 4; i++) { + auto &analog_item = analogs.at(analog_mappings[i]); + if (analog_item.isSet()) { + set_values[i] = analog_states[i] + (uint8_t) (Analogs::getState(RI_MGR, analog_item) * 255.99f); + } + } + + // flip disk 2/3 + set_values[1] ^= set_values[2]; + set_values[2] ^= set_values[1]; + set_values[1] ^= set_values[2]; + + // set analogs + for (int i = 0; i < 4; i++) { + STATUS_BUFFER[20 + i] = set_values[i]; + } + } + + // success + return true; +} + +static void __cdecl ac_io_pix_rvol_watchdog_off() { +} + +static void *__cdecl ac_io_pix_secplug_set_encodedpasswd(void *a1, unsigned int a2) { + return a1; +} + +static void *__cdecl ac_io_pix_set_get_status_device(void *a1, int a2) { + return a1; +} + +static void *__cdecl ac_io_pix_set_soft_watch_dog(void *a1, int a2) { + return a1; +} + +static char __cdecl ac_io_pix_soft_watch_dog_off(int a1) { + return 1; +} + +static char __cdecl ac_io_pix_soft_watch_dog_on(int a1) { + return 1; +} + +static char __cdecl ac_io_pix_update(long long a1) { + + // flush outputs + RI_MGR->devices_flush_output(); + + return 1; +} + +static const char* __cdecl ac_io_pix_version() { + static const char *version = "Version: 1.25.0\nBuild Date: Sep 20 2016 15:16:13\nBuild Host: DEMETER\n"; + return version; +} + +/* + * Module stuff + */ + +acio::PIXModule::PIXModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("PIX", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::PIXModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_pix_begin); + ACIO_MODULE_HOOK(ac_io_pix_begin_get_status); + ACIO_MODULE_HOOK(ac_io_pix_end); + ACIO_MODULE_HOOK(ac_io_pix_end_get_status); + ACIO_MODULE_HOOK(ac_io_pix_get_firmware_update_device_index); + ACIO_MODULE_HOOK(ac_io_pix_get_node_no); + ACIO_MODULE_HOOK(ac_io_pix_get_recv_log); + ACIO_MODULE_HOOK(ac_io_pix_get_rs232c_status); + ACIO_MODULE_HOOK(ac_io_pix_get_send_log); + ACIO_MODULE_HOOK(ac_io_pix_get_version); + ACIO_MODULE_HOOK(ac_io_pix_get_version_string); + ACIO_MODULE_HOOK(ac_io_pix_go_firmware_update); + ACIO_MODULE_HOOK(ac_io_pix_is_active); + ACIO_MODULE_HOOK(ac_io_pix_is_active2); + ACIO_MODULE_HOOK(ac_io_pix_is_active_device); + ACIO_MODULE_HOOK(ac_io_pix_reset); + ACIO_MODULE_HOOK(ac_io_pix_rvol_change_expand_mode); + ACIO_MODULE_HOOK(ac_io_pix_rvol_control_led_bright); + ACIO_MODULE_HOOK(ac_io_pix_rvol_control_reset); + ACIO_MODULE_HOOK(ac_io_pix_rvol_create_get_status_thread); + ACIO_MODULE_HOOK(ac_io_pix_rvol_destroy_get_status_thread); + ACIO_MODULE_HOOK(ac_io_pix_rvol_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_pix_rvol_get_watchdog_status); + ACIO_MODULE_HOOK(ac_io_pix_rvol_get_watchdog_time_min); + ACIO_MODULE_HOOK(ac_io_pix_rvol_get_watchdog_time_now); + ACIO_MODULE_HOOK(ac_io_pix_rvol_modify_auto_input_get); + ACIO_MODULE_HOOK(ac_io_pix_rvol_req_get_control_status); + ACIO_MODULE_HOOK(ac_io_pix_rvol_req_volume_control); + ACIO_MODULE_HOOK(ac_io_pix_rvol_req_volume_control_isfinished); + ACIO_MODULE_HOOK(ac_io_pix_rvol_set_framing_err_packet_send_interval); + ACIO_MODULE_HOOK(ac_io_pix_rvol_set_watchdog_time); + ACIO_MODULE_HOOK(ac_io_pix_rvol_update_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_pix_rvol_watchdog_off); + ACIO_MODULE_HOOK(ac_io_pix_secplug_set_encodedpasswd); + ACIO_MODULE_HOOK(ac_io_pix_set_get_status_device); + ACIO_MODULE_HOOK(ac_io_pix_set_soft_watch_dog); + ACIO_MODULE_HOOK(ac_io_pix_soft_watch_dog_off); + ACIO_MODULE_HOOK(ac_io_pix_soft_watch_dog_on); + ACIO_MODULE_HOOK(ac_io_pix_update); + ACIO_MODULE_HOOK(ac_io_pix_version); +} diff --git a/acio/pix/pix.h b/acio/pix/pix.h index 9592b8a..f547ed5 100644 --- a/acio/pix/pix.h +++ b/acio/pix/pix.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class PIXModule : public ACIOModule { - public: - PIXModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class PIXModule : public ACIOModule { + public: + PIXModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/pjec/pjec.h b/acio/pjec/pjec.h index 7220e2b..78e38a0 100644 --- a/acio/pjec/pjec.h +++ b/acio/pjec/pjec.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class PJECModule : public ACIOModule { - public: - PJECModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class PJECModule : public ACIOModule { + public: + PJECModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acio/pjei/pjei.cpp b/acio/pjei/pjei.cpp index 540407d..101380a 100644 --- a/acio/pjei/pjei.cpp +++ b/acio/pjei/pjei.cpp @@ -1,223 +1,223 @@ -#include "pjei.h" -#include "launcher/launcher.h" -#include "rawinput/rawinput.h" -#include "util/utils.h" -#include "misc/eamuse.h" -#include "games/we/io.h" -#include "avs/game.h" - -//using namespace GameAPI; - -// static stuff -static uint8_t STATUS_BUFFER[40]; -static bool STATUS_BUFFER_FREEZE = false; - -/* - * Implementations - */ - -static bool __cdecl ac_io_pjei_current_coinstock(int a1, uint32_t *coinstock) { - *coinstock = eamuse_coin_get_stock(); - return true; -} - -static bool __cdecl ac_io_pjei_consume_coinstock(int a1, uint32_t amount) { - return eamuse_coin_consume(amount); -} - -static bool __cdecl ac_io_pjei_get_softwareid(char *dst) { - static char DATA[] = "0140FFFFFFFFFFFFFFFF"; - memcpy(dst, DATA, sizeof(DATA)); - return true; -} - -static bool __cdecl ac_io_pjei_get_systemid(char *dst) { - static char DATA[] = "0140FFFFFFFFFFFFFFFF"; - memcpy(dst, DATA, sizeof(DATA)); - return true; -} - -static bool __cdecl ac_io_pjei_update_control_status_buffer() { - - // check freeze - if (STATUS_BUFFER_FREEZE) { - return true; - } - - // clear buffer - memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); - - // Winning Eleven - if (avs::game::is_model({ "KCK", "NCK" })) { - - // get buttons - auto &buttons = games::we::get_buttons(); - - // apply buttons - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Service])) { - STATUS_BUFFER[16] |= 0x10; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Test])) { - STATUS_BUFFER[16] |= 0x20; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::CoinMech])) { - STATUS_BUFFER[16] |= 0x04; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Start])) { - STATUS_BUFFER[4] |= 0x80; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Up])) { - STATUS_BUFFER[4] |= 0x40; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Down])) { - STATUS_BUFFER[4] |= 0x20; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Left])) { - STATUS_BUFFER[4] |= 0x10; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Right])) { - STATUS_BUFFER[4] |= 0x08; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonA])) { - STATUS_BUFFER[4] |= 0x04; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonB])) { - STATUS_BUFFER[4] |= 0x02; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonC])) { - STATUS_BUFFER[4] |= 0x01; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonD])) { - STATUS_BUFFER[6] |= 0x80; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonE])) { - STATUS_BUFFER[6] |= 0x40; - } - if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonF])) { - STATUS_BUFFER[6] |= 0x20; - } - } - - // success - return true; -} - -static bool ac_io_pjei_get_control_status_buffer(uint8_t *buffer) { - memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER)); - return true; -} - -static bool __cdecl ac_io_pjei_req_secplug_check() { - return true; -} - -static bool __cdecl ac_io_pjei_req_secplug_check_isfinished() { - return true; -} - -static bool __cdecl ac_io_pjei_req_secplug_missing_check() { - return true; -} - -static bool __cdecl ac_io_pjei_req_secplug_missing_check_isfinished() { - return true; -} - -static bool __cdecl ac_io_pjei_lock_coincounter(int a1) { - eamuse_coin_set_block(true); - return true; -} - -static bool __cdecl ac_io_pjei_unlock_coincounter(int a1) { - eamuse_coin_set_block(false); - return true; -} - -static bool __cdecl ac_io_pjei_control_coin_blocker_on(bool a1) { - eamuse_coin_set_block(true); - return true; -} - -static bool __cdecl ac_io_pjei_control_coin_blocker_off(bool a1) { - eamuse_coin_set_block(false); - return true; -} - -/* - * Helper method for easily setting the light values - */ -static void ac_io_pjei_control_lamp_set(uint8_t lamp_bits, uint8_t brightness) { - auto &lights = games::we::get_lights(); - float value = CLAMP(brightness / 31.f, 0.f, 1.f); - if (lamp_bits & 0x20) { - GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftRed], value); - } - if (lamp_bits & 0x10) { - GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftGreen], value); - } - if (lamp_bits & 0x08) { - GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftBlue], value); - } - if (lamp_bits & 0x04) { - GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightRed], value); - } - if (lamp_bits & 0x02) { - GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightGreen], value); - } - if (lamp_bits & 0x01) { - GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightBlue], value); - } -} - -static bool __cdecl ac_io_pjei_control_lamp_on(uint8_t lamp_bits) { - ac_io_pjei_control_lamp_set(lamp_bits, 31); - return true; -} - -static bool __cdecl ac_io_pjei_control_lamp_off(uint8_t lamp_bits) { - ac_io_pjei_control_lamp_set(lamp_bits, 0); - return true; -} - -static bool __cdecl ac_io_pjei_control_lamp_bright(uint8_t lamp_bit, uint8_t brightness) { - ac_io_pjei_control_lamp_set(lamp_bit, brightness); - return true; -} - -static bool __cdecl ac_io_pjei_control_lamp_mode(int mode) { - // mode -> [0,1] (0 is static, 1 is brightness?) - return true; -} - -/* - * Module stuff - */ -acio::PJEIModule::PJEIModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("PJEI", module, hookMode) { - this->status_buffer = STATUS_BUFFER; - this->status_buffer_size = sizeof(STATUS_BUFFER); - this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; -} - -void acio::PJEIModule::attach() { - ACIOModule::attach(); - - // hooks - ACIO_MODULE_HOOK(ac_io_pjei_current_coinstock); - ACIO_MODULE_HOOK(ac_io_pjei_consume_coinstock); - ACIO_MODULE_HOOK(ac_io_pjei_get_softwareid); - ACIO_MODULE_HOOK(ac_io_pjei_get_systemid); - ACIO_MODULE_HOOK(ac_io_pjei_update_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_pjei_get_control_status_buffer); - ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check); - ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check_isfinished); - ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check); - ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check_isfinished); - ACIO_MODULE_HOOK(ac_io_pjei_lock_coincounter); - ACIO_MODULE_HOOK(ac_io_pjei_unlock_coincounter); - ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_on); - ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_off); - ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_on); - ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_off); - ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_bright); - ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_mode); -} +#include "pjei.h" +#include "launcher/launcher.h" +#include "rawinput/rawinput.h" +#include "util/utils.h" +#include "misc/eamuse.h" +#include "games/we/io.h" +#include "avs/game.h" + +//using namespace GameAPI; + +// static stuff +static uint8_t STATUS_BUFFER[40]; +static bool STATUS_BUFFER_FREEZE = false; + +/* + * Implementations + */ + +static bool __cdecl ac_io_pjei_current_coinstock(int a1, uint32_t *coinstock) { + *coinstock = eamuse_coin_get_stock(); + return true; +} + +static bool __cdecl ac_io_pjei_consume_coinstock(int a1, uint32_t amount) { + return eamuse_coin_consume(amount); +} + +static bool __cdecl ac_io_pjei_get_softwareid(char *dst) { + static char DATA[] = "0140FFFFFFFFFFFFFFFF"; + memcpy(dst, DATA, sizeof(DATA)); + return true; +} + +static bool __cdecl ac_io_pjei_get_systemid(char *dst) { + static char DATA[] = "0140FFFFFFFFFFFFFFFF"; + memcpy(dst, DATA, sizeof(DATA)); + return true; +} + +static bool __cdecl ac_io_pjei_update_control_status_buffer() { + + // check freeze + if (STATUS_BUFFER_FREEZE) { + return true; + } + + // clear buffer + memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); + + // Winning Eleven + if (avs::game::is_model({ "KCK", "NCK" })) { + + // get buttons + auto &buttons = games::we::get_buttons(); + + // apply buttons + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Service])) { + STATUS_BUFFER[16] |= 0x10; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Test])) { + STATUS_BUFFER[16] |= 0x20; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::CoinMech])) { + STATUS_BUFFER[16] |= 0x04; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Start])) { + STATUS_BUFFER[4] |= 0x80; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Up])) { + STATUS_BUFFER[4] |= 0x40; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Down])) { + STATUS_BUFFER[4] |= 0x20; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Left])) { + STATUS_BUFFER[4] |= 0x10; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Right])) { + STATUS_BUFFER[4] |= 0x08; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonA])) { + STATUS_BUFFER[4] |= 0x04; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonB])) { + STATUS_BUFFER[4] |= 0x02; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonC])) { + STATUS_BUFFER[4] |= 0x01; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonD])) { + STATUS_BUFFER[6] |= 0x80; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonE])) { + STATUS_BUFFER[6] |= 0x40; + } + if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonF])) { + STATUS_BUFFER[6] |= 0x20; + } + } + + // success + return true; +} + +static bool ac_io_pjei_get_control_status_buffer(uint8_t *buffer) { + memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER)); + return true; +} + +static bool __cdecl ac_io_pjei_req_secplug_check() { + return true; +} + +static bool __cdecl ac_io_pjei_req_secplug_check_isfinished() { + return true; +} + +static bool __cdecl ac_io_pjei_req_secplug_missing_check() { + return true; +} + +static bool __cdecl ac_io_pjei_req_secplug_missing_check_isfinished() { + return true; +} + +static bool __cdecl ac_io_pjei_lock_coincounter(int a1) { + eamuse_coin_set_block(true); + return true; +} + +static bool __cdecl ac_io_pjei_unlock_coincounter(int a1) { + eamuse_coin_set_block(false); + return true; +} + +static bool __cdecl ac_io_pjei_control_coin_blocker_on(bool a1) { + eamuse_coin_set_block(true); + return true; +} + +static bool __cdecl ac_io_pjei_control_coin_blocker_off(bool a1) { + eamuse_coin_set_block(false); + return true; +} + +/* + * Helper method for easily setting the light values + */ +static void ac_io_pjei_control_lamp_set(uint8_t lamp_bits, uint8_t brightness) { + auto &lights = games::we::get_lights(); + float value = CLAMP(brightness / 31.f, 0.f, 1.f); + if (lamp_bits & 0x20) { + GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftRed], value); + } + if (lamp_bits & 0x10) { + GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftGreen], value); + } + if (lamp_bits & 0x08) { + GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftBlue], value); + } + if (lamp_bits & 0x04) { + GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightRed], value); + } + if (lamp_bits & 0x02) { + GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightGreen], value); + } + if (lamp_bits & 0x01) { + GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightBlue], value); + } +} + +static bool __cdecl ac_io_pjei_control_lamp_on(uint8_t lamp_bits) { + ac_io_pjei_control_lamp_set(lamp_bits, 31); + return true; +} + +static bool __cdecl ac_io_pjei_control_lamp_off(uint8_t lamp_bits) { + ac_io_pjei_control_lamp_set(lamp_bits, 0); + return true; +} + +static bool __cdecl ac_io_pjei_control_lamp_bright(uint8_t lamp_bit, uint8_t brightness) { + ac_io_pjei_control_lamp_set(lamp_bit, brightness); + return true; +} + +static bool __cdecl ac_io_pjei_control_lamp_mode(int mode) { + // mode -> [0,1] (0 is static, 1 is brightness?) + return true; +} + +/* + * Module stuff + */ +acio::PJEIModule::PJEIModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("PJEI", module, hookMode) { + this->status_buffer = STATUS_BUFFER; + this->status_buffer_size = sizeof(STATUS_BUFFER); + this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; +} + +void acio::PJEIModule::attach() { + ACIOModule::attach(); + + // hooks + ACIO_MODULE_HOOK(ac_io_pjei_current_coinstock); + ACIO_MODULE_HOOK(ac_io_pjei_consume_coinstock); + ACIO_MODULE_HOOK(ac_io_pjei_get_softwareid); + ACIO_MODULE_HOOK(ac_io_pjei_get_systemid); + ACIO_MODULE_HOOK(ac_io_pjei_update_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_pjei_get_control_status_buffer); + ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check); + ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check_isfinished); + ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check); + ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check_isfinished); + ACIO_MODULE_HOOK(ac_io_pjei_lock_coincounter); + ACIO_MODULE_HOOK(ac_io_pjei_unlock_coincounter); + ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_on); + ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_off); + ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_on); + ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_off); + ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_bright); + ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_mode); +} diff --git a/acio/pjei/pjei.h b/acio/pjei/pjei.h index ae48512..e14787d 100644 --- a/acio/pjei/pjei.h +++ b/acio/pjei/pjei.h @@ -1,13 +1,13 @@ -#pragma once - -#include "../module.h" - -namespace acio { - - class PJEIModule : public ACIOModule { - public: - PJEIModule(HMODULE module, HookMode hookMode); - - virtual void attach() override; - }; -} +#pragma once + +#include "../module.h" + +namespace acio { + + class PJEIModule : public ACIOModule { + public: + PJEIModule(HMODULE module, HookMode hookMode); + + virtual void attach() override; + }; +} diff --git a/acioemu/acioemu.cpp b/acioemu/acioemu.cpp index 5a94a3a..be452ef 100644 --- a/acioemu/acioemu.cpp +++ b/acioemu/acioemu.cpp @@ -1,205 +1,205 @@ -#include "acioemu.h" -#include "util/logging.h" -#include "util/utils.h" - -using namespace acioemu; - -ACIOEmu::ACIOEmu() { - this->devices = new std::vector(); - this->response_buffer = new circular_buffer(4096); - this->read_buffer = new circular_buffer(1024); -} - -ACIOEmu::~ACIOEmu() { - - // delete devices - for (auto device : *this->devices) { - delete device; - } - delete this->devices; - - // delete buffers - delete this->response_buffer; - delete this->read_buffer; -} - -void ACIOEmu::add_device(ACIODeviceEmu *device) { - this->devices->push_back(device); -} - -void ACIOEmu::write(uint8_t byte) { - - // insert into buffer - if (!invert) { - if (byte == ACIO_ESCAPE) { - invert = true; - } else { - this->read_buffer->put(byte); - } - } else { - byte = ~byte; - invert = false; - this->read_buffer->put(byte); - } - - // clean garbage - while (!this->read_buffer->empty() && this->read_buffer->peek() != 0xAA) { - this->read_buffer->get(); - } - while (this->read_buffer->size() > 1 && this->read_buffer->peek(1) == 0xAA) { - this->read_buffer->get(); - } - - // handshake counter - static unsigned int handshake_counter = 0; - if (byte == 0xAA) { - handshake_counter++; - } else { - handshake_counter = 0; - } - - // check for handshake - if (handshake_counter > 1) { - - /* - * small hack - BIO2 seems to expect more bytes here - sending two bytes each time fixes it - * TODO replace this handshake code with something better - */ - this->response_buffer->put(ACIO_SOF); - this->response_buffer->put(ACIO_SOF); - handshake_counter--; - return; - } - - // parse - if (!this->read_buffer->empty() && this->read_buffer->size() >= 6) { - bool is_complete = false; - - // check if broadcast - if (this->read_buffer->peek(1) == ACIO_BROADCAST) { - - // check msg data size - auto data_size = this->read_buffer->peek(2); - - // check if msg is complete (SOF + checksum + broadcast header + data_size) - is_complete = this->read_buffer->size() >= 2u + 2u + data_size; - } else { - - // check msg data size - auto data_size = this->read_buffer->peek(5); - - // check if msg is complete (SOF + checksum + command header + data_size) - is_complete = this->read_buffer->size() >= 2u + MSG_HEADER_SIZE + data_size; - } - - // parse message if complete - if (is_complete) { - this->msg_parse(); - this->read_buffer->reset(); - } - } -} - -std::optional ACIOEmu::read() { - if (this->response_buffer->empty()) { - return std::nullopt; - } - - return this->response_buffer->get(); -} - -void ACIOEmu::msg_parse() { - -#ifdef ACIOEMU_LOG - log_info("acioemu", "MSG RECV: {}", bin2hex(*this->read_buffer)); -#endif - - // calculate checksum - uint8_t chk = 0; - size_t max = this->read_buffer->size() - 1; - for (size_t i = 1; i < max; i++) { - chk += this->read_buffer->peek(i); - } - - // check checksum - uint8_t chk_receive = this->read_buffer->peek(this->read_buffer->size() - 1); - if (chk != chk_receive) { -#ifdef ACIOEMU_LOG - log_info("acioemu", "detected wrong checksum: {}/{}", chk, chk_receive); -#endif - return; - } - - // get message data - auto msg_data = this->read_buffer->peek_all(); - auto msg_in = (MessageData *) &msg_data[1]; - - // correct cmd code endianness if this is not a broadcast - if (msg_in->addr != ACIO_BROADCAST) { - msg_in->cmd.code = acio_u16(msg_in->cmd.code); - } - - // pass to applicable device - uint8_t node_offset = 0; - for (auto device : *this->devices) { - if (device->is_applicable(node_offset, msg_in->addr)) { - auto cur_offset = msg_in->addr - node_offset - 1; - if (cur_offset < 0) { - break; - } - if (device->parse_msg(msg_in, this->response_buffer)) { - return; - } else { - break; - } - } - node_offset += device->node_count; - } - - // ignore broadcast messages by default - if (msg_in->addr == ACIO_BROADCAST) { - return; - } - - /* - * Default Behavior - * If you want to do anything different, just handle the - * commands in your own device implementation. - */ - switch (msg_in->cmd.code) { - - // node count report - case ACIO_CMD_ASSIGN_ADDRS: { - if (msg_in->addr == 0x00 && node_offset > 0) { - auto msg = ACIODeviceEmu::create_msg(msg_in, 1, &node_offset); - ACIODeviceEmu::write_msg(msg, this->response_buffer); - delete msg; - return; - } - break; - } - - // status 0 defaults - case ACIO_CMD_CLEAR: - case ACIO_CMD_STARTUP: - case 0x80: // KEEPALIVE - case 0xFF: // BROADCAST - { - // send status 0 - auto msg = ACIODeviceEmu::create_msg_status(msg_in, 0); - ACIODeviceEmu::write_msg(msg, response_buffer); - delete msg; - return; - } - - default: - break; - } - -#ifdef ACIOEMU_LOG - log_info("acioemu", "UNHANDLED MSG FOR ADDR: {}, CMD: 0x{:x}), DATA: {}", - msg_in->addr, - msg_in->cmd.code, - bin2hex(*this->read_buffer)); -#endif -} +#include "acioemu.h" +#include "util/logging.h" +#include "util/utils.h" + +using namespace acioemu; + +ACIOEmu::ACIOEmu() { + this->devices = new std::vector(); + this->response_buffer = new circular_buffer(4096); + this->read_buffer = new circular_buffer(1024); +} + +ACIOEmu::~ACIOEmu() { + + // delete devices + for (auto device : *this->devices) { + delete device; + } + delete this->devices; + + // delete buffers + delete this->response_buffer; + delete this->read_buffer; +} + +void ACIOEmu::add_device(ACIODeviceEmu *device) { + this->devices->push_back(device); +} + +void ACIOEmu::write(uint8_t byte) { + + // insert into buffer + if (!invert) { + if (byte == ACIO_ESCAPE) { + invert = true; + } else { + this->read_buffer->put(byte); + } + } else { + byte = ~byte; + invert = false; + this->read_buffer->put(byte); + } + + // clean garbage + while (!this->read_buffer->empty() && this->read_buffer->peek() != 0xAA) { + this->read_buffer->get(); + } + while (this->read_buffer->size() > 1 && this->read_buffer->peek(1) == 0xAA) { + this->read_buffer->get(); + } + + // handshake counter + static unsigned int handshake_counter = 0; + if (byte == 0xAA) { + handshake_counter++; + } else { + handshake_counter = 0; + } + + // check for handshake + if (handshake_counter > 1) { + + /* + * small hack - BIO2 seems to expect more bytes here - sending two bytes each time fixes it + * TODO replace this handshake code with something better + */ + this->response_buffer->put(ACIO_SOF); + this->response_buffer->put(ACIO_SOF); + handshake_counter--; + return; + } + + // parse + if (!this->read_buffer->empty() && this->read_buffer->size() >= 6) { + bool is_complete = false; + + // check if broadcast + if (this->read_buffer->peek(1) == ACIO_BROADCAST) { + + // check msg data size + auto data_size = this->read_buffer->peek(2); + + // check if msg is complete (SOF + checksum + broadcast header + data_size) + is_complete = this->read_buffer->size() >= 2u + 2u + data_size; + } else { + + // check msg data size + auto data_size = this->read_buffer->peek(5); + + // check if msg is complete (SOF + checksum + command header + data_size) + is_complete = this->read_buffer->size() >= 2u + MSG_HEADER_SIZE + data_size; + } + + // parse message if complete + if (is_complete) { + this->msg_parse(); + this->read_buffer->reset(); + } + } +} + +std::optional ACIOEmu::read() { + if (this->response_buffer->empty()) { + return std::nullopt; + } + + return this->response_buffer->get(); +} + +void ACIOEmu::msg_parse() { + +#ifdef ACIOEMU_LOG + log_info("acioemu", "MSG RECV: {}", bin2hex(*this->read_buffer)); +#endif + + // calculate checksum + uint8_t chk = 0; + size_t max = this->read_buffer->size() - 1; + for (size_t i = 1; i < max; i++) { + chk += this->read_buffer->peek(i); + } + + // check checksum + uint8_t chk_receive = this->read_buffer->peek(this->read_buffer->size() - 1); + if (chk != chk_receive) { +#ifdef ACIOEMU_LOG + log_info("acioemu", "detected wrong checksum: {}/{}", chk, chk_receive); +#endif + return; + } + + // get message data + auto msg_data = this->read_buffer->peek_all(); + auto msg_in = (MessageData *) &msg_data[1]; + + // correct cmd code endianness if this is not a broadcast + if (msg_in->addr != ACIO_BROADCAST) { + msg_in->cmd.code = acio_u16(msg_in->cmd.code); + } + + // pass to applicable device + uint8_t node_offset = 0; + for (auto device : *this->devices) { + if (device->is_applicable(node_offset, msg_in->addr)) { + auto cur_offset = msg_in->addr - node_offset - 1; + if (cur_offset < 0) { + break; + } + if (device->parse_msg(msg_in, this->response_buffer)) { + return; + } else { + break; + } + } + node_offset += device->node_count; + } + + // ignore broadcast messages by default + if (msg_in->addr == ACIO_BROADCAST) { + return; + } + + /* + * Default Behavior + * If you want to do anything different, just handle the + * commands in your own device implementation. + */ + switch (msg_in->cmd.code) { + + // node count report + case ACIO_CMD_ASSIGN_ADDRS: { + if (msg_in->addr == 0x00 && node_offset > 0) { + auto msg = ACIODeviceEmu::create_msg(msg_in, 1, &node_offset); + ACIODeviceEmu::write_msg(msg, this->response_buffer); + delete msg; + return; + } + break; + } + + // status 0 defaults + case ACIO_CMD_CLEAR: + case ACIO_CMD_STARTUP: + case 0x80: // KEEPALIVE + case 0xFF: // BROADCAST + { + // send status 0 + auto msg = ACIODeviceEmu::create_msg_status(msg_in, 0); + ACIODeviceEmu::write_msg(msg, response_buffer); + delete msg; + return; + } + + default: + break; + } + +#ifdef ACIOEMU_LOG + log_info("acioemu", "UNHANDLED MSG FOR ADDR: {}, CMD: 0x{:x}), DATA: {}", + msg_in->addr, + msg_in->cmd.code, + bin2hex(*this->read_buffer)); +#endif +} diff --git a/acioemu/acioemu.h b/acioemu/acioemu.h index f151807..b9f597c 100644 --- a/acioemu/acioemu.h +++ b/acioemu/acioemu.h @@ -1,32 +1,32 @@ -#pragma once - -#include -#include - -#include "util/circular_buffer.h" - -#include "device.h" -#include "icca.h" - -namespace acioemu { - - class ACIOEmu { - private: - std::vector *devices; - circular_buffer *response_buffer; - circular_buffer *read_buffer; - bool invert = false; - - void msg_parse(); - - public: - - explicit ACIOEmu(); - ~ACIOEmu(); - - void add_device(ACIODeviceEmu *device); - - void write(uint8_t byte); - std::optional read(); - }; -} +#pragma once + +#include +#include + +#include "util/circular_buffer.h" + +#include "device.h" +#include "icca.h" + +namespace acioemu { + + class ACIOEmu { + private: + std::vector *devices; + circular_buffer *response_buffer; + circular_buffer *read_buffer; + bool invert = false; + + void msg_parse(); + + public: + + explicit ACIOEmu(); + ~ACIOEmu(); + + void add_device(ACIODeviceEmu *device); + + void write(uint8_t byte); + std::optional read(); + }; +} diff --git a/acioemu/bi2a.h b/acioemu/bi2a.h index a8ec8fe..53669a6 100644 --- a/acioemu/bi2a.h +++ b/acioemu/bi2a.h @@ -1,80 +1,80 @@ -#pragma once - -#include -#include -#include -#include -#include "device.h" -#include "hooks/sleephook.h" - -namespace acioemu { - -#pragma pack(push, 1) - struct bio2_bi2a_state_in { - uint8_t pad0[3]; - uint8_t panel[4]; - uint8_t deck_switch[14]; - uint8_t pad21[2]; - uint8_t led_ticker[9]; - uint8_t spot_light_1[4]; - uint8_t neon_light; - uint8_t spot_light_2[4]; - uint8_t pad41[7]; - }; - - struct bio2_bi2a_status { - uint8_t slider_1; - uint8_t system; - uint8_t slider_2; - uint8_t pad3; - uint8_t slider_3; - uint8_t pad5; - uint8_t slider_4; - uint8_t slider_5; - uint8_t pad8; - uint8_t panel; - uint8_t pad10[6]; - uint8_t tt_p1; - uint8_t tt_p2; - uint8_t p1_s1; - uint8_t pad20; - uint8_t p1_s2; - uint8_t pad22; - uint8_t p1_s3; - uint8_t pad24; - uint8_t p1_s4; - uint8_t pad26; - uint8_t p1_s5; - uint8_t pad28; - uint8_t p1_s6; - uint8_t pad30; - uint8_t p1_s7; - uint8_t pad32; - uint8_t p2_s1; - uint8_t pad34; - uint8_t p2_s2; - uint8_t pad36; - uint8_t p2_s3; - uint8_t pad38; - uint8_t p2_s4; - uint8_t pad40; - }; -#pragma pack(pop) - - class BI2A : public ACIODeviceEmu { - private: - uint8_t coin_counter = 0; - - public: - explicit BI2A(bool type_new, bool flip_order, bool keypad_thread, uint8_t node_count); - ~BI2A() override; - - bool parse_msg(unsigned int node_offset, - MessageData *msg_in, - circular_buffer *response_buffer) override; - - void update_card(int unit); - void update_keypad(int unit, bool update_edge); - void update_status(int unit); - }; -} +#pragma once + +#include +#include +#include +#include +#include "device.h" +#include "hooks/sleephook.h" + +namespace acioemu { + +#pragma pack(push, 1) + struct bio2_bi2a_state_in { + uint8_t pad0[3]; + uint8_t panel[4]; + uint8_t deck_switch[14]; + uint8_t pad21[2]; + uint8_t led_ticker[9]; + uint8_t spot_light_1[4]; + uint8_t neon_light; + uint8_t spot_light_2[4]; + uint8_t pad41[7]; + }; + + struct bio2_bi2a_status { + uint8_t slider_1; + uint8_t system; + uint8_t slider_2; + uint8_t pad3; + uint8_t slider_3; + uint8_t pad5; + uint8_t slider_4; + uint8_t slider_5; + uint8_t pad8; + uint8_t panel; + uint8_t pad10[6]; + uint8_t tt_p1; + uint8_t tt_p2; + uint8_t p1_s1; + uint8_t pad20; + uint8_t p1_s2; + uint8_t pad22; + uint8_t p1_s3; + uint8_t pad24; + uint8_t p1_s4; + uint8_t pad26; + uint8_t p1_s5; + uint8_t pad28; + uint8_t p1_s6; + uint8_t pad30; + uint8_t p1_s7; + uint8_t pad32; + uint8_t p2_s1; + uint8_t pad34; + uint8_t p2_s2; + uint8_t pad36; + uint8_t p2_s3; + uint8_t pad38; + uint8_t p2_s4; + uint8_t pad40; + }; +#pragma pack(pop) + + class BI2A : public ACIODeviceEmu { + private: + uint8_t coin_counter = 0; + + public: + explicit BI2A(bool type_new, bool flip_order, bool keypad_thread, uint8_t node_count); + ~BI2A() override; + + bool parse_msg(unsigned int node_offset, + MessageData *msg_in, + circular_buffer *response_buffer) override; + + void update_card(int unit); + void update_keypad(int unit, bool update_edge); + void update_status(int unit); + }; +} diff --git a/acioemu/device.cpp b/acioemu/device.cpp index e6fd695..6e8dacf 100644 --- a/acioemu/device.cpp +++ b/acioemu/device.cpp @@ -1,118 +1,118 @@ -#include "device.h" - -#include "util/logging.h" -#include "util/utils.h" - -using namespace acioemu; - -void ACIODeviceEmu::set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, - uint8_t data_size) -{ - // flag as response - if (addr != 0) { - addr |= ACIO_RESPONSE_FLAG; - } - - // set header data - data->addr = addr; - data->cmd.code = acio_u16(code); - data->cmd.pid = pid; - data->cmd.data_size = data_size; -} - -void ACIODeviceEmu::set_version(MessageData* data, uint32_t type, uint8_t flag, - uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev, std::string code) -{ - - // set version data - auto data_version = &data->cmd.data_version; - data_version->type = type; - data_version->flag = flag; - data_version->ver_major = ver_major; - data_version->ver_minor = ver_minor; - data_version->ver_rev = ver_rev; - strncpy(data_version->code, code.c_str(), sizeof(data_version->code)); - strncpy(data_version->date, __DATE__, sizeof(data_version->date)); - strncpy(data_version->time, __TIME__, sizeof(data_version->time)); -} - -MessageData *ACIODeviceEmu::create_msg(uint8_t addr, uint16_t code, uint8_t pid, size_t data_size, - uint8_t *data) -{ - // check data size - if (data_size > 0xFF) { - log_warning("acio", "data size > 255: {}", data_size); - data_size = 0xFF; - } - - // allocate data - auto data_raw = new uint8_t[MSG_HEADER_SIZE + data_size]; - - // set header - auto msg = (MessageData *) &data_raw[0]; - set_header(msg, addr, code, pid, (uint8_t) data_size); - - // set data - if (data) { - memcpy(data_raw + MSG_HEADER_SIZE, data, data_size); - } else { - memset(data_raw + MSG_HEADER_SIZE, 0, data_size); - } - - // return prepared message - return msg; -} - -MessageData *ACIODeviceEmu::create_msg(MessageData *msg_in, size_t data_size, uint8_t *data) { - return create_msg(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, data_size, data); -} - -MessageData *ACIODeviceEmu::create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status) { - return create_msg(addr, code, pid, 1, &status); -} - -MessageData *ACIODeviceEmu::create_msg_status(MessageData *msg_in, uint8_t status) { - return create_msg_status(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, status); -} - -bool ACIODeviceEmu::is_applicable(uint8_t node_offset, uint8_t node) { - return node > node_offset && node <= node_offset + this->node_count; -} - -void ACIODeviceEmu::write_msg(const uint8_t *data, size_t size, circular_buffer *response_buffer) { - - // header - for (int i = 0; i < 2; i++) { - response_buffer->put(ACIO_SOF); - } - - // msg data and checksum - uint8_t b, chk = 0; - for (size_t i = 0; i <= size; i++) { - - // set byte to data or checksum - if (i < size) { - b = data[i]; - chk += b; - } else { - b = chk; - } - - // check for escape - if (b == ACIO_SOF || b == ACIO_ESCAPE) { - response_buffer->put(ACIO_ESCAPE); - response_buffer->put(~b); - } else { - response_buffer->put(b); - } - } - -#ifdef ACIOEMU_LOG - log_info("acioemu", "ACIO MSG OUT: AA{}{:02X}", bin2hex(data, size), chk); -#endif -} - -void ACIODeviceEmu::write_msg(MessageData *msg, circular_buffer *response_buffer) { - auto data = reinterpret_cast(msg); - write_msg(data, MSG_HEADER_SIZE + msg->cmd.data_size, response_buffer); -} +#include "device.h" + +#include "util/logging.h" +#include "util/utils.h" + +using namespace acioemu; + +void ACIODeviceEmu::set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, + uint8_t data_size) +{ + // flag as response + if (addr != 0) { + addr |= ACIO_RESPONSE_FLAG; + } + + // set header data + data->addr = addr; + data->cmd.code = acio_u16(code); + data->cmd.pid = pid; + data->cmd.data_size = data_size; +} + +void ACIODeviceEmu::set_version(MessageData* data, uint32_t type, uint8_t flag, + uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev, std::string code) +{ + + // set version data + auto data_version = &data->cmd.data_version; + data_version->type = type; + data_version->flag = flag; + data_version->ver_major = ver_major; + data_version->ver_minor = ver_minor; + data_version->ver_rev = ver_rev; + strncpy(data_version->code, code.c_str(), sizeof(data_version->code)); + strncpy(data_version->date, __DATE__, sizeof(data_version->date)); + strncpy(data_version->time, __TIME__, sizeof(data_version->time)); +} + +MessageData *ACIODeviceEmu::create_msg(uint8_t addr, uint16_t code, uint8_t pid, size_t data_size, + uint8_t *data) +{ + // check data size + if (data_size > 0xFF) { + log_warning("acio", "data size > 255: {}", data_size); + data_size = 0xFF; + } + + // allocate data + auto data_raw = new uint8_t[MSG_HEADER_SIZE + data_size]; + + // set header + auto msg = (MessageData *) &data_raw[0]; + set_header(msg, addr, code, pid, (uint8_t) data_size); + + // set data + if (data) { + memcpy(data_raw + MSG_HEADER_SIZE, data, data_size); + } else { + memset(data_raw + MSG_HEADER_SIZE, 0, data_size); + } + + // return prepared message + return msg; +} + +MessageData *ACIODeviceEmu::create_msg(MessageData *msg_in, size_t data_size, uint8_t *data) { + return create_msg(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, data_size, data); +} + +MessageData *ACIODeviceEmu::create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status) { + return create_msg(addr, code, pid, 1, &status); +} + +MessageData *ACIODeviceEmu::create_msg_status(MessageData *msg_in, uint8_t status) { + return create_msg_status(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, status); +} + +bool ACIODeviceEmu::is_applicable(uint8_t node_offset, uint8_t node) { + return node > node_offset && node <= node_offset + this->node_count; +} + +void ACIODeviceEmu::write_msg(const uint8_t *data, size_t size, circular_buffer *response_buffer) { + + // header + for (int i = 0; i < 2; i++) { + response_buffer->put(ACIO_SOF); + } + + // msg data and checksum + uint8_t b, chk = 0; + for (size_t i = 0; i <= size; i++) { + + // set byte to data or checksum + if (i < size) { + b = data[i]; + chk += b; + } else { + b = chk; + } + + // check for escape + if (b == ACIO_SOF || b == ACIO_ESCAPE) { + response_buffer->put(ACIO_ESCAPE); + response_buffer->put(~b); + } else { + response_buffer->put(b); + } + } + +#ifdef ACIOEMU_LOG + log_info("acioemu", "ACIO MSG OUT: AA{}{:02X}", bin2hex(data, size), chk); +#endif +} + +void ACIODeviceEmu::write_msg(MessageData *msg, circular_buffer *response_buffer) { + auto data = reinterpret_cast(msg); + write_msg(data, MSG_HEADER_SIZE + msg->cmd.data_size, response_buffer); +} diff --git a/acioemu/device.h b/acioemu/device.h index d54253e..3bd0fcc 100644 --- a/acioemu/device.h +++ b/acioemu/device.h @@ -1,103 +1,103 @@ -#pragma once - -#include - -#include "util/circular_buffer.h" - -// convert big-endian to little-endian -#define acio_u16 _byteswap_ushort -#define acio_u32 _byteswap_ulong - -namespace acioemu { - - constexpr uint8_t ACIO_SOF = 0xAA; - constexpr uint8_t ACIO_ESCAPE = 0xFF; - constexpr uint8_t ACIO_BROADCAST = 0x70; - constexpr uint8_t ACIO_RESPONSE_FLAG = 0x80; - - // general command codes - enum acio_cmd_codes { - ACIO_CMD_ASSIGN_ADDRS = 0x0001, - ACIO_CMD_GET_VERSION = 0x0002, - ACIO_CMD_STARTUP = 0x0003, - ACIO_CMD_KEEPALIVE = 0x0080, - ACIO_CMD_CLEAR = 0x0100, - }; - - // message structs -#pragma pack(push, 1) - struct VersionData { - uint32_t type; - uint8_t flag; - uint8_t ver_major; - uint8_t ver_minor; - uint8_t ver_rev; - char code[4]; - char date[16]; - char time[16]; - }; - - struct MessageData { - uint8_t addr; - - union { - struct { - uint16_t code; - uint8_t pid; - uint8_t data_size; - - union { - uint8_t raw[0xFF]; - uint8_t status; - VersionData data_version; - }; - } cmd; - - struct { - uint8_t data_size; - uint8_t raw[0xFF]; - } broadcast; - }; - }; -#pragma pack(pop) - - // message sizes - constexpr size_t MSG_HEADER_SIZE = 5; - constexpr size_t MSG_VERSION_SIZE = sizeof(VersionData); - - class ACIODeviceEmu { - public: - - // attributes - uint8_t node_count = 0; - - /* - * Helper functions for getting/setting the message contents - */ - static void set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, uint8_t data_size); - static void set_version(MessageData* data, uint32_t type, uint8_t flag, - uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev, - std::string code); - - /* - * This function creates a basic message with optional parameter data. - * If data is set to null, the parameter data will be initialized with 0x00 - */ - static MessageData* create_msg(uint8_t addr, uint16_t cmd, uint8_t pid, - size_t data_size, uint8_t *data = nullptr); - static MessageData* create_msg(MessageData* msg_in, size_t data_size, uint8_t *data = nullptr); - - /* - * Helper functions for generating messages - */ - static MessageData* create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status); - static MessageData* create_msg_status(MessageData* msg_in, uint8_t status); - - virtual ~ACIODeviceEmu() = default; - - virtual bool is_applicable(uint8_t node_offset, uint8_t node); - virtual bool parse_msg(MessageData *msg_in, circular_buffer *response_buffer) = 0; - static void write_msg(const uint8_t *data, size_t size, circular_buffer *response_buffer); - static void write_msg(MessageData *msg, circular_buffer *response_buffer); - }; -} +#pragma once + +#include + +#include "util/circular_buffer.h" + +// convert big-endian to little-endian +#define acio_u16 _byteswap_ushort +#define acio_u32 _byteswap_ulong + +namespace acioemu { + + constexpr uint8_t ACIO_SOF = 0xAA; + constexpr uint8_t ACIO_ESCAPE = 0xFF; + constexpr uint8_t ACIO_BROADCAST = 0x70; + constexpr uint8_t ACIO_RESPONSE_FLAG = 0x80; + + // general command codes + enum acio_cmd_codes { + ACIO_CMD_ASSIGN_ADDRS = 0x0001, + ACIO_CMD_GET_VERSION = 0x0002, + ACIO_CMD_STARTUP = 0x0003, + ACIO_CMD_KEEPALIVE = 0x0080, + ACIO_CMD_CLEAR = 0x0100, + }; + + // message structs +#pragma pack(push, 1) + struct VersionData { + uint32_t type; + uint8_t flag; + uint8_t ver_major; + uint8_t ver_minor; + uint8_t ver_rev; + char code[4]; + char date[16]; + char time[16]; + }; + + struct MessageData { + uint8_t addr; + + union { + struct { + uint16_t code; + uint8_t pid; + uint8_t data_size; + + union { + uint8_t raw[0xFF]; + uint8_t status; + VersionData data_version; + }; + } cmd; + + struct { + uint8_t data_size; + uint8_t raw[0xFF]; + } broadcast; + }; + }; +#pragma pack(pop) + + // message sizes + constexpr size_t MSG_HEADER_SIZE = 5; + constexpr size_t MSG_VERSION_SIZE = sizeof(VersionData); + + class ACIODeviceEmu { + public: + + // attributes + uint8_t node_count = 0; + + /* + * Helper functions for getting/setting the message contents + */ + static void set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, uint8_t data_size); + static void set_version(MessageData* data, uint32_t type, uint8_t flag, + uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev, + std::string code); + + /* + * This function creates a basic message with optional parameter data. + * If data is set to null, the parameter data will be initialized with 0x00 + */ + static MessageData* create_msg(uint8_t addr, uint16_t cmd, uint8_t pid, + size_t data_size, uint8_t *data = nullptr); + static MessageData* create_msg(MessageData* msg_in, size_t data_size, uint8_t *data = nullptr); + + /* + * Helper functions for generating messages + */ + static MessageData* create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status); + static MessageData* create_msg_status(MessageData* msg_in, uint8_t status); + + virtual ~ACIODeviceEmu() = default; + + virtual bool is_applicable(uint8_t node_offset, uint8_t node); + virtual bool parse_msg(MessageData *msg_in, circular_buffer *response_buffer) = 0; + static void write_msg(const uint8_t *data, size_t size, circular_buffer *response_buffer); + static void write_msg(MessageData *msg, circular_buffer *response_buffer); + }; +} diff --git a/acioemu/handle.cpp b/acioemu/handle.cpp index 7d4da48..c8d8841 100644 --- a/acioemu/handle.cpp +++ b/acioemu/handle.cpp @@ -1,69 +1,69 @@ -#include "handle.h" - -#include "misc/eamuse.h" -#include "rawinput/rawinput.h" -#include "util/utils.h" - -acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort) { - this->com_port = lpCOMPort; -} - -bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) { - if (wcscmp(lpFileName, com_port) != 0) { - return false; - } - - log_info("acioemu", "Opened {} (ACIO)", ws2s(com_port)); - - // ACIO device - acio_emu.add_device(new acioemu::ICCADevice(false, true, 2)); - - return true; -} - -int acioemu::ACIOHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) { - auto buffer = reinterpret_cast(lpBuffer); - - // read from emu - DWORD bytes_read = 0; - while (bytes_read < nNumberOfBytesToRead) { - auto cur_byte = acio_emu.read(); - - if (cur_byte.has_value()) { - buffer[bytes_read++] = cur_byte.value(); - } else { - break; - } - } - - // return amount of bytes read - return (int) bytes_read; -} - -int acioemu::ACIOHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) { - auto buffer = reinterpret_cast(lpBuffer); - - // write to emu - for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) { - acio_emu.write(buffer[i]); - } - - // return all data written - return (int) nNumberOfBytesToWrite; -} - -int acioemu::ACIOHandle::device_io( - DWORD dwIoControlCode, - LPVOID lpInBuffer, - DWORD nInBufferSize, - LPVOID lpOutBuffer, - DWORD nOutBufferSize -) { - return -1; -} - -bool acioemu::ACIOHandle::close() { - log_info("acioemu", "Closed {} (ACIO)", ws2s(com_port)); - - return true; -} +#include "handle.h" + +#include "misc/eamuse.h" +#include "rawinput/rawinput.h" +#include "util/utils.h" + +acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort) { + this->com_port = lpCOMPort; +} + +bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) { + if (wcscmp(lpFileName, com_port) != 0) { + return false; + } + + log_info("acioemu", "Opened {} (ACIO)", ws2s(com_port)); + + // ACIO device + acio_emu.add_device(new acioemu::ICCADevice(false, true, 2)); + + return true; +} + +int acioemu::ACIOHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) { + auto buffer = reinterpret_cast(lpBuffer); + + // read from emu + DWORD bytes_read = 0; + while (bytes_read < nNumberOfBytesToRead) { + auto cur_byte = acio_emu.read(); + + if (cur_byte.has_value()) { + buffer[bytes_read++] = cur_byte.value(); + } else { + break; + } + } + + // return amount of bytes read + return (int) bytes_read; +} + +int acioemu::ACIOHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) { + auto buffer = reinterpret_cast(lpBuffer); + + // write to emu + for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) { + acio_emu.write(buffer[i]); + } + + // return all data written + return (int) nNumberOfBytesToWrite; +} + +int acioemu::ACIOHandle::device_io( + DWORD dwIoControlCode, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize +) { + return -1; +} + +bool acioemu::ACIOHandle::close() { + log_info("acioemu", "Closed {} (ACIO)", ws2s(com_port)); + + return true; +} diff --git a/acioemu/handle.h b/acioemu/handle.h index 5940d83..a1fd9cc 100644 --- a/acioemu/handle.h +++ b/acioemu/handle.h @@ -1,28 +1,28 @@ -#pragma once - -#include "acioemu/acioemu.h" -#include "hooks/devicehook.h" - -namespace acioemu { - - class ACIOHandle : public CustomHandle { - private: - LPCWSTR com_port; - - acioemu::ACIOEmu acio_emu; - - public: - ACIOHandle(LPCWSTR lpCOMPort); - - bool open(LPCWSTR lpFileName) override; - - int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override; - - int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override; - - int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, - DWORD nOutBufferSize) override; - - bool close() override; - }; -} +#pragma once + +#include "acioemu/acioemu.h" +#include "hooks/devicehook.h" + +namespace acioemu { + + class ACIOHandle : public CustomHandle { + private: + LPCWSTR com_port; + + acioemu::ACIOEmu acio_emu; + + public: + ACIOHandle(LPCWSTR lpCOMPort); + + bool open(LPCWSTR lpFileName) override; + + int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override; + + int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override; + + int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, + DWORD nOutBufferSize) override; + + bool close() override; + }; +} diff --git a/acioemu/icca.h b/acioemu/icca.h index 96c8341..f7d3aea 100644 --- a/acioemu/icca.h +++ b/acioemu/icca.h @@ -1,42 +1,42 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "device.h" -#include "hooks/sleephook.h" -#include "reader/crypt.h" - -namespace acioemu { - class ICCADevice : public ACIODeviceEmu { - private: - bool type_new; - bool flip_order; - std::thread *keypad_thread; - std::mutex keypad_mutex; - uint8_t **cards; - time_t *cards_time; - uint8_t *status; - bool *accept; - bool *hold; - uint8_t *keydown; - uint16_t *keypad; - bool **keypad_last; - uint8_t *keypad_capture; - std::optional *crypt; - uint8_t *counter; - - public: - explicit ICCADevice(bool flip_order, bool keypad_thread, uint8_t node_count); - ~ICCADevice() override; - - bool parse_msg(MessageData *msg_in, circular_buffer *response_buffer) override; - - void update_card(int unit); - void update_keypad(int unit, bool update_edge); - void update_status(int unit); - }; -} +#pragma once + +#include +#include +#include +#include +#include + +#include "device.h" +#include "hooks/sleephook.h" +#include "reader/crypt.h" + +namespace acioemu { + class ICCADevice : public ACIODeviceEmu { + private: + bool type_new; + bool flip_order; + std::thread *keypad_thread; + std::mutex keypad_mutex; + uint8_t **cards; + time_t *cards_time; + uint8_t *status; + bool *accept; + bool *hold; + uint8_t *keydown; + uint16_t *keypad; + bool **keypad_last; + uint8_t *keypad_capture; + std::optional *crypt; + uint8_t *counter; + + public: + explicit ICCADevice(bool flip_order, bool keypad_thread, uint8_t node_count); + ~ICCADevice() override; + + bool parse_msg(MessageData *msg_in, circular_buffer *response_buffer) override; + + void update_card(int unit); + void update_keypad(int unit, bool update_edge); + void update_status(int unit); + }; +} diff --git a/api/controller.h b/api/controller.h index 1267b09..5413f44 100644 --- a/api/controller.h +++ b/api/controller.h @@ -1,82 +1,82 @@ -#pragma once - -#include -#include -#include -#include - -#include - -#include "util/rc4.h" - -#include "module.h" -#include "websocket.h" -#include "serial.h" - -namespace api { - - struct ClientState { - SOCKADDR_IN address; - SOCKET socket; - bool close = false; - std::vector modules; - std::string password; - bool password_change = false; - util::RC4 *cipher = nullptr; - }; - - class Controller { - private: - - // configuration - const static int server_backlog = 16; - const static int server_receive_buffer_size = 64 * 1024; - const static int server_message_buffer_max_size = 64 * 1024; - const static int server_worker_count = 2; - const static int server_connection_limit = 4096; - - // settings - unsigned short port; - std::string password; - bool pretty; - - // server - WebSocketController *websocket; - std::vector serial; - std::vector server_workers; - std::vector server_handlers; - std::mutex server_handlers_m; - std::vector client_states; - std::mutex client_states_m; - SOCKET server; - void server_worker(); - void connection_handler(ClientState client_state); - - public: - - // state - bool server_running; - - // constructor / destructor - Controller(unsigned short port, std::string password, bool pretty); - ~Controller(); - - void listen_serial(std::string port, DWORD baud); - - bool process_request(ClientState *state, std::vector *in, std::vector *out); - bool process_request(ClientState *state, const char *in, size_t in_size, std::vector *out); - static void process_password_change(ClientState *state); - - void init_state(ClientState *state); - static void free_state(ClientState *state); - - void free_socket(); - void obtain_client_states(std::vector *output); - - std::string get_ip_address(sockaddr_in addr); - - inline const std::string &get_password() const { - return this->password; - } - }; -} +#pragma once + +#include +#include +#include +#include + +#include + +#include "util/rc4.h" + +#include "module.h" +#include "websocket.h" +#include "serial.h" + +namespace api { + + struct ClientState { + SOCKADDR_IN address; + SOCKET socket; + bool close = false; + std::vector modules; + std::string password; + bool password_change = false; + util::RC4 *cipher = nullptr; + }; + + class Controller { + private: + + // configuration + const static int server_backlog = 16; + const static int server_receive_buffer_size = 64 * 1024; + const static int server_message_buffer_max_size = 64 * 1024; + const static int server_worker_count = 2; + const static int server_connection_limit = 4096; + + // settings + unsigned short port; + std::string password; + bool pretty; + + // server + WebSocketController *websocket; + std::vector serial; + std::vector server_workers; + std::vector server_handlers; + std::mutex server_handlers_m; + std::vector client_states; + std::mutex client_states_m; + SOCKET server; + void server_worker(); + void connection_handler(ClientState client_state); + + public: + + // state + bool server_running; + + // constructor / destructor + Controller(unsigned short port, std::string password, bool pretty); + ~Controller(); + + void listen_serial(std::string port, DWORD baud); + + bool process_request(ClientState *state, std::vector *in, std::vector *out); + bool process_request(ClientState *state, const char *in, size_t in_size, std::vector *out); + static void process_password_change(ClientState *state); + + void init_state(ClientState *state); + static void free_state(ClientState *state); + + void free_socket(); + void obtain_client_states(std::vector *output); + + std::string get_ip_address(sockaddr_in addr); + + inline const std::string &get_password() const { + return this->password; + } + }; +} diff --git a/api/module.cpp b/api/module.cpp index 326851c..700a562 100644 --- a/api/module.cpp +++ b/api/module.cpp @@ -1,43 +1,43 @@ -#include - -#include "util/logging.h" - -#include "module.h" - -using namespace rapidjson; - -namespace api { - - // logging setting - bool LOGGING = false; - - Module::Module(std::string name, bool password_force) { - this->name = std::move(name); - this->password_force = password_force; - } - - void Module::handle(Request &req, Response &res) { - - // log module access - if (LOGGING) - log_info("api::" + this->name, "handling request"); - - // find function - auto pos = functions.find(req.function); - if (pos == functions.end()) - return error_function_unknown(res); - - // call function - pos->second(req, res); - } - - void Module::error(Response &res, std::string err) { - - // log the warning - log_warning("api::" + this->name, "error: {}", err); - - // add error to response - Value val(err.c_str(), res.doc()->GetAllocator()); - res.add_error(val); - } -} +#include + +#include "util/logging.h" + +#include "module.h" + +using namespace rapidjson; + +namespace api { + + // logging setting + bool LOGGING = false; + + Module::Module(std::string name, bool password_force) { + this->name = std::move(name); + this->password_force = password_force; + } + + void Module::handle(Request &req, Response &res) { + + // log module access + if (LOGGING) + log_info("api::" + this->name, "handling request"); + + // find function + auto pos = functions.find(req.function); + if (pos == functions.end()) + return error_function_unknown(res); + + // call function + pos->second(req, res); + } + + void Module::error(Response &res, std::string err) { + + // log the warning + log_warning("api::" + this->name, "error: {}", err); + + // add error to response + Value val(err.c_str(), res.doc()->GetAllocator()); + res.add_error(val); + } +} diff --git a/api/module.h b/api/module.h index fdedbdd..d41b787 100644 --- a/api/module.h +++ b/api/module.h @@ -1,67 +1,67 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "response.h" -#include "request.h" - -namespace api { - - // logging setting - extern bool LOGGING; - - // callback - typedef std::function ModuleFunctionCallback; - - class Module { - protected: - - // map of available functions - robin_hood::unordered_map functions; - - // default constructor - explicit Module(std::string name, bool password_force=false); - - public: - - // virtual deconstructor - virtual ~Module() = default; - - // name of the module (should match namespace) - std::string name; - bool password_force; - - // the magic - void handle(Request &req, Response &res); - - /* - * Error definitions. - */ - - void error(Response &res, std::string err); - void error_type(Response &res, const std::string &field, const std::string &type) { - std::ostringstream s; - s << field << " must be a " << type; - error(res, s.str()); - }; - void error_size(Response &res, const std::string &field, size_t size) { - std::ostringstream s; - s << field << " must be of size " << size; - error(res, s.str()); - } - void error_unknown(Response &res, const std::string &field, const std::string &name) { - std::ostringstream s; - s << "Unknown " << field << ": " << name; - error(res, s.str()); - } - -#define ERR(name, err) void error_##name(Response &res) { error(res, err); } - ERR(function_unknown, "Unknown function."); - ERR(params_insufficient, "Insufficient number of parameters."); -#undef ERR - }; -} +#pragma once + +#include +#include +#include +#include +#include + +#include "response.h" +#include "request.h" + +namespace api { + + // logging setting + extern bool LOGGING; + + // callback + typedef std::function ModuleFunctionCallback; + + class Module { + protected: + + // map of available functions + robin_hood::unordered_map functions; + + // default constructor + explicit Module(std::string name, bool password_force=false); + + public: + + // virtual deconstructor + virtual ~Module() = default; + + // name of the module (should match namespace) + std::string name; + bool password_force; + + // the magic + void handle(Request &req, Response &res); + + /* + * Error definitions. + */ + + void error(Response &res, std::string err); + void error_type(Response &res, const std::string &field, const std::string &type) { + std::ostringstream s; + s << field << " must be a " << type; + error(res, s.str()); + }; + void error_size(Response &res, const std::string &field, size_t size) { + std::ostringstream s; + s << field << " must be of size " << size; + error(res, s.str()); + } + void error_unknown(Response &res, const std::string &field, const std::string &name) { + std::ostringstream s; + s << "Unknown " << field << ": " << name; + error(res, s.str()); + } + +#define ERR(name, err) void error_##name(Response &res) { error(res, err); } + ERR(function_unknown, "Unknown function."); + ERR(params_insufficient, "Insufficient number of parameters."); +#undef ERR + }; +} diff --git a/api/modules/analogs.cpp b/api/modules/analogs.cpp index d130dad..3cb2be1 100644 --- a/api/modules/analogs.cpp +++ b/api/modules/analogs.cpp @@ -1,177 +1,177 @@ -#include "analogs.h" -#include -#include "external/rapidjson/document.h" -#include "misc/eamuse.h" -#include "cfg/analog.h" -#include "launcher/launcher.h" -#include "games/io.h" -#include "util/utils.h" - -using namespace std::placeholders; -using namespace rapidjson; - - -namespace api::modules { - - Analogs::Analogs() : Module("analogs") { - functions["read"] = std::bind(&Analogs::read, this, _1, _2); - functions["write"] = std::bind(&Analogs::write, this, _1, _2); - functions["write_reset"] = std::bind(&Analogs::write_reset, this, _1, _2); - analogs = games::get_analogs(eamuse_get_game()); - } - - /** - * read() - */ - void Analogs::read(api::Request &req, Response &res) { - - // check analog cache - if (!analogs) { - return; - } - - // add state for each analog - for (auto &analog : *this->analogs) { - Value state(kArrayType); - Value analog_name(analog.getName().c_str(), res.doc()->GetAllocator()); - Value analog_state(GameAPI::Analogs::getState(RI_MGR, analog)); - Value analog_enabled(analog.override_enabled); - state.PushBack(analog_name, res.doc()->GetAllocator()); - state.PushBack(analog_state, res.doc()->GetAllocator()); - state.PushBack(analog_enabled, res.doc()->GetAllocator()); - res.add_data(state); - } - } - - /** - * write([name: str, state: float], ...) - */ - void Analogs::write(Request &req, Response &res) { - - // check analog cache - if (!analogs) - return; - - // loop parameters - for (Value ¶m : req.params.GetArray()) { - - // check params - if (!param.IsArray()) { - error(res, "parameters must be arrays"); - return; - } - if (param.Size() < 2) { - error_params_insufficient(res); - continue; - } - if (!param[0].IsString()) { - error_type(res, "name", "string"); - continue; - } - if (!param[1].IsFloat() && !param[1].IsInt()) { - error_type(res, "state", "float"); - continue; - } - - // get params - auto analog_name = param[0].GetString(); - auto analog_state = param[1].GetFloat(); - - // write analog state - if (!this->write_analog(analog_name, analog_state)) { - error_unknown(res, "analog", analog_name); - continue; - } - } - } - - /** - * write_reset() - * write_reset([name: str], ...) - */ - void Analogs::write_reset(Request &req, Response &res) { - - // check analog cache - if (!analogs) - return; - - // get params - auto params = req.params.GetArray(); - - // write_reset() - if (params.Size() == 0) { - if (analogs != nullptr) { - for (auto &analog : *this->analogs) { - analog.override_enabled = false; - } - } - return; - } - - // loop parameters - for (Value ¶m : req.params.GetArray()) { - - // check params - if (!param.IsArray()) { - error(res, "parameters must be arrays"); - return; - } - if (param.Size() < 1) { - error_params_insufficient(res); - continue; - } - if (!param[0].IsString()) { - error_type(res, "name", "string"); - continue; - } - - // get params - auto analog_name = param[0].GetString(); - - // write analog state - if (!this->write_analog_reset(analog_name)) { - error_unknown(res, "analog", analog_name); - continue; - } - } - } - - bool Analogs::write_analog(std::string name, float state) { - - // check analog cache - if (!this->analogs) { - return false; - } - - // find analog - for (auto &analog : *this->analogs) { - if (analog.getName() == name) { - analog.override_state = CLAMP(state, 0.f, 1.f); - analog.override_enabled = true; - return true; - } - } - - // unknown analog - return false; - } - - bool Analogs::write_analog_reset(std::string name) { - - // check analog cache - if (!analogs) { - return false; - } - - // find analog - for (auto &analog : *this->analogs) { - if (analog.getName() == name) { - analog.override_enabled = false; - return true; - } - } - - // unknown analog - return false; - } -} +#include "analogs.h" +#include +#include "external/rapidjson/document.h" +#include "misc/eamuse.h" +#include "cfg/analog.h" +#include "launcher/launcher.h" +#include "games/io.h" +#include "util/utils.h" + +using namespace std::placeholders; +using namespace rapidjson; + + +namespace api::modules { + + Analogs::Analogs() : Module("analogs") { + functions["read"] = std::bind(&Analogs::read, this, _1, _2); + functions["write"] = std::bind(&Analogs::write, this, _1, _2); + functions["write_reset"] = std::bind(&Analogs::write_reset, this, _1, _2); + analogs = games::get_analogs(eamuse_get_game()); + } + + /** + * read() + */ + void Analogs::read(api::Request &req, Response &res) { + + // check analog cache + if (!analogs) { + return; + } + + // add state for each analog + for (auto &analog : *this->analogs) { + Value state(kArrayType); + Value analog_name(analog.getName().c_str(), res.doc()->GetAllocator()); + Value analog_state(GameAPI::Analogs::getState(RI_MGR, analog)); + Value analog_enabled(analog.override_enabled); + state.PushBack(analog_name, res.doc()->GetAllocator()); + state.PushBack(analog_state, res.doc()->GetAllocator()); + state.PushBack(analog_enabled, res.doc()->GetAllocator()); + res.add_data(state); + } + } + + /** + * write([name: str, state: float], ...) + */ + void Analogs::write(Request &req, Response &res) { + + // check analog cache + if (!analogs) + return; + + // loop parameters + for (Value ¶m : req.params.GetArray()) { + + // check params + if (!param.IsArray()) { + error(res, "parameters must be arrays"); + return; + } + if (param.Size() < 2) { + error_params_insufficient(res); + continue; + } + if (!param[0].IsString()) { + error_type(res, "name", "string"); + continue; + } + if (!param[1].IsFloat() && !param[1].IsInt()) { + error_type(res, "state", "float"); + continue; + } + + // get params + auto analog_name = param[0].GetString(); + auto analog_state = param[1].GetFloat(); + + // write analog state + if (!this->write_analog(analog_name, analog_state)) { + error_unknown(res, "analog", analog_name); + continue; + } + } + } + + /** + * write_reset() + * write_reset([name: str], ...) + */ + void Analogs::write_reset(Request &req, Response &res) { + + // check analog cache + if (!analogs) + return; + + // get params + auto params = req.params.GetArray(); + + // write_reset() + if (params.Size() == 0) { + if (analogs != nullptr) { + for (auto &analog : *this->analogs) { + analog.override_enabled = false; + } + } + return; + } + + // loop parameters + for (Value ¶m : req.params.GetArray()) { + + // check params + if (!param.IsArray()) { + error(res, "parameters must be arrays"); + return; + } + if (param.Size() < 1) { + error_params_insufficient(res); + continue; + } + if (!param[0].IsString()) { + error_type(res, "name", "string"); + continue; + } + + // get params + auto analog_name = param[0].GetString(); + + // write analog state + if (!this->write_analog_reset(analog_name)) { + error_unknown(res, "analog", analog_name); + continue; + } + } + } + + bool Analogs::write_analog(std::string name, float state) { + + // check analog cache + if (!this->analogs) { + return false; + } + + // find analog + for (auto &analog : *this->analogs) { + if (analog.getName() == name) { + analog.override_state = CLAMP(state, 0.f, 1.f); + analog.override_enabled = true; + return true; + } + } + + // unknown analog + return false; + } + + bool Analogs::write_analog_reset(std::string name) { + + // check analog cache + if (!analogs) { + return false; + } + + // find analog + for (auto &analog : *this->analogs) { + if (analog.getName() == name) { + analog.override_enabled = false; + return true; + } + } + + // unknown analog + return false; + } +} diff --git a/api/modules/analogs.h b/api/modules/analogs.h index a5ea21b..c6f93c7 100644 --- a/api/modules/analogs.h +++ b/api/modules/analogs.h @@ -1,28 +1,28 @@ -#pragma once - -#include -#include "api/module.h" -#include "api/request.h" -#include "cfg/api.h" - -namespace api::modules { - - class Analogs : public Module { - public: - Analogs(); - - private: - - // state - std::vector *analogs; - - // function definitions - void read(Request &req, Response &res); - void write(Request &req, Response &res); - void write_reset(Request &req, Response &res); - - // helper - bool write_analog(std::string name, float state); - bool write_analog_reset(std::string name); - }; -} +#pragma once + +#include +#include "api/module.h" +#include "api/request.h" +#include "cfg/api.h" + +namespace api::modules { + + class Analogs : public Module { + public: + Analogs(); + + private: + + // state + std::vector *analogs; + + // function definitions + void read(Request &req, Response &res); + void write(Request &req, Response &res); + void write_reset(Request &req, Response &res); + + // helper + bool write_analog(std::string name, float state); + bool write_analog_reset(std::string name); + }; +} diff --git a/api/modules/buttons.h b/api/modules/buttons.h index fb0b7f7..1a9a8a7 100644 --- a/api/modules/buttons.h +++ b/api/modules/buttons.h @@ -1,28 +1,28 @@ -#pragma once - -#include -#include "api/module.h" -#include "api/request.h" -#include "cfg/api.h" - -namespace api::modules { - - class Buttons : public Module { - public: - Buttons(); - - private: - - // state - std::vector