From c94de456b56a2f4628e515d3ce1e609a48bd0748 Mon Sep 17 00:00:00 2001 From: "[ ]" <[ ]> Date: Wed, 7 May 2025 00:25:31 +0900 Subject: [PATCH] Update to spice2x-25-04-25 (pre-apply) > broken commit --- .dockerignore | 1 + .gitignore | 4 +- CMakeLists.txt | 249 +- Dockerfile | 9 +- README.md | 20 +- acio/acio.cpp | 3 + acio/bi2a/bi2a.cpp | 290 +- acio/bmpu/bmpu.cpp | 20 + acio/icca/icca.cpp | 59 +- acio/mdxf/mdxf.cpp | 84 +- acio/module.h | 1 + acio/panb/panb.cpp | 119 +- acio2emu/firmware/bi2x.cpp | 2 +- acioemu/acioemu.cpp | 4 + acioemu/acioemu.h | 1 + acioemu/handle.cpp | 9 +- acioemu/handle.h | 6 +- acioemu/icca.cpp | 72 +- acioemu/icca.h | 2 + api/controller.cpp | 4 + api/modules/control.cpp | 30 +- api/modules/ddr.cpp | 54 + api/modules/ddr.h | 17 + api/modules/lights.cpp | 128 +- api/modules/lights.h | 4 + api/modules/resize.cpp | 53 + api/modules/resize.h | 18 + api/modules/touch.cpp | 6 + api/resources/lua/README.md | 15 - api/resources/lua/boot_iidx_tt_lights.lua | 113 - api/resources/lua/config_example.lua | 57 - api/resources/python/spiceapi/__init__.py | 1 + api/resources/python/spiceapi/lights.py | 10 +- api/resources/python/spiceapi/resize.py | 12 + api/resources/python/spiceremote.py | 63 +- avs/automap.cpp | 2 +- avs/core.cpp | 38 +- avs/core.h | 3 +- avs/ea3.cpp | 18 + avs/game.cpp | 31 +- build_all.sh | 109 +- build_docker.bat | 4 +- build_docker.sh | 6 +- build_msvc.py | 85 - build_release.bat | 2 + cfg/analog.cpp | 128 +- cfg/analog.h | 61 +- cfg/api.cpp | 408 +- cfg/button.cpp | 164 +- cfg/button.h | 14 + cfg/config.cpp | 119 +- cfg/config.h | 4 +- cfg/configurator.cpp | 8 - cfg/configurator.h | 3 +- cfg/configurator_wnd.cpp | 6 +- cfg/light.cpp | 20 + cfg/option.cpp | 13 + cfg/option.h | 14 +- cfg/screen_resize.cpp | 63 +- cfg/screen_resize.h | 22 +- changelog.txt | 396 +- easrv/easrv.cpp | 3 + external/LuaBridge.h | 8614 ------ external/cardio/cardio_runner.cpp | 12 +- external/cardio/cardio_runner.h | 1 + external/cpu_features/.clang-format | 4 + external/cpu_features/.dockerignore | 36 + external/cpu_features/.gitignore | 19 + external/cpu_features/.grenrc.yml | 21 + external/cpu_features/BUILD.bazel | 378 + external/cpu_features/CMakeLists.txt | 302 + external/cpu_features/CONTRIBUTING.md | 23 + external/cpu_features/LICENSE | 230 + external/cpu_features/README.md | 282 + external/cpu_features/WORKSPACE | 19 + .../cmake/CpuFeaturesConfig.cmake.in | 3 + .../cmake/CpuFeaturesNdkCompatConfig.cmake.in | 3 + external/cpu_features/cmake/README.md | 30 + external/cpu_features/cmake/ci/Makefile | 252 + external/cpu_features/cmake/ci/README.md | 40 + external/cpu_features/cmake/ci/doc/docker.dot | 64 + external/cpu_features/cmake/ci/doc/docker.svg | 312 + .../cmake/ci/doc/generate_image.sh | 7 + .../cmake/ci/docker/amd64/Dockerfile | 48 + .../cmake/ci/docker/toolchain/Dockerfile | 34 + .../cmake/ci/sample/CMakeLists.txt | 22 + .../cpu_features/cmake/ci/sample/main.cpp | 11 + .../cmake/ci/vagrant/freebsd/Vagrantfile | 107 + .../cmake/googletest.CMakeLists.txt.in | 15 + .../include/cpu_features_cache_info.h | 54 + .../include/cpu_features_macros.h | 388 + .../cpu_features/include/cpuinfo_aarch64.h | 301 + external/cpu_features/include/cpuinfo_arm.h | 121 + .../cpu_features/include/cpuinfo_loongarch.h | 77 + external/cpu_features/include/cpuinfo_mips.h | 74 + external/cpu_features/include/cpuinfo_ppc.h | 149 + external/cpu_features/include/cpuinfo_riscv.h | 72 + external/cpu_features/include/cpuinfo_s390x.h | 108 + external/cpu_features/include/cpuinfo_x86.h | 295 + .../cpu_features/include/internal/bit_utils.h | 40 + .../cpu_features/include/internal/cpuid_x86.h | 37 + .../include/internal/filesystem.h | 39 + .../cpu_features/include/internal/hwcaps.h | 277 + .../include/internal/stack_line_reader.h | 49 + .../include/internal/string_view.h | 110 + .../include/internal/windows_utils.h | 70 + external/cpu_features/src/copy.inl | 19 + .../cpu_features/src/define_introspection.inl | 86 + .../src/define_introspection_and_hwcaps.inl | 26 + external/cpu_features/src/equals.inl | 22 + external/cpu_features/src/filesystem.c | 62 + external/cpu_features/src/hwcaps.c | 169 + .../src/impl_aarch64__base_implementation.inl | 118 + .../src/impl_aarch64_linux_or_android.c | 79 + .../src/impl_aarch64_macos_or_iphone.c | 88 + .../cpu_features/src/impl_aarch64_windows.c | 138 + .../src/impl_arm_linux_or_android.c | 212 + .../cpu_features/src/impl_loongarch_linux.c | 89 + .../src/impl_mips_linux_or_android.c | 93 + external/cpu_features/src/impl_ppc_linux.c | 163 + external/cpu_features/src/impl_riscv_linux.c | 111 + external/cpu_features/src/impl_s390x_linux.c | 120 + .../src/impl_x86__base_implementation.inl | 2069 ++ external/cpu_features/src/impl_x86_freebsd.c | 68 + .../src/impl_x86_linux_or_android.c | 58 + external/cpu_features/src/impl_x86_macos.c | 57 + external/cpu_features/src/impl_x86_windows.c | 58 + external/cpu_features/src/stack_line_reader.c | 132 + external/cpu_features/src/string_view.c | 192 + .../src/utils/list_cpu_features.c | 470 + external/cv2pdb/.gitignore | 9 - external/cv2pdb/README.md | 36 - external/discord-rpc/.clang-format | 1 - external/discord-rpc/CMakeLists.txt | 2 +- external/docker/Dockerfile | 19 +- external/fmt/include/fmt/core.h | 5 + external/hash-library/CMakeLists.txt | 2 +- external/headsocket.h | 2 +- external/imgui/CMakeLists.txt | 6 +- .../imgui/backends/imgui_impl_dx9.cpp | 6 +- .../imgui/backends/imgui_impl_dx9.h | 2 +- external/imgui/imconfig.h | 49 +- external/imgui/imgui.cpp | 6950 +++-- external/imgui/imgui.h | 2399 +- external/imgui/imgui_demo.cpp | 3678 ++- external/imgui/imgui_draw.cpp | 750 +- external/imgui/imgui_internal.h | 1596 +- external/imgui/imgui_tables.cpp | 819 +- external/imgui/imgui_widgets.cpp | 3406 ++- external/imgui/imstb_textedit.h | 246 +- external/imgui/imstb_truetype.h | 2 +- external/imgui/misc/cpp/imgui_stdlib.cpp | 85 + external/imgui/misc/cpp/imgui_stdlib.h | 21 + .../layeredfs/3rd_party/GuillotineBinPack.cpp | 643 - .../layeredfs/3rd_party/GuillotineBinPack.h | 134 - external/layeredfs/3rd_party/Rect.cpp | 51 - external/layeredfs/3rd_party/Rect.h | 94 - external/layeredfs/3rd_party/lodepng.cpp | 6488 ----- external/layeredfs/3rd_party/lodepng.h | 2020 -- external/layeredfs/3rd_party/rapidxml.hpp | 2596 -- .../layeredfs/3rd_party/rapidxml_print.hpp | 446 - external/layeredfs/3rd_party/stb_dxt.cpp | 37 - external/layeredfs/3rd_party/stb_dxt.h | 1043 - external/layeredfs/LICENSE | 9 - external/layeredfs/config.cpp | 38 - external/layeredfs/config.h | 13 - external/layeredfs/hook.cpp | 847 - external/layeredfs/hook.h | 14 - external/layeredfs/modpath_handler.cpp | 227 - external/layeredfs/modpath_handler.h | 29 - external/layeredfs/texture_packer.cpp | 69 - external/layeredfs/texture_packer.h | 35 - external/layeredfs/utils.cpp | 185 - external/layeredfs/utils.h | 28 - external/lua/CMakeLists.txt | 48 - external/lua/README | 6 - external/lua/src/Makefile | 222 - external/lua/src/lapi.c | 1455 - external/lua/src/lapi.h | 49 - external/lua/src/lauxlib.c | 1105 - external/lua/src/lauxlib.h | 293 - external/lua/src/lbaselib.c | 559 - external/lua/src/lcode.c | 1814 -- external/lua/src/lcode.h | 104 - external/lua/src/lcorolib.c | 210 - external/lua/src/lctype.c | 64 - external/lua/src/lctype.h | 101 - external/lua/src/ldblib.c | 483 - external/lua/src/ldebug.c | 877 - external/lua/src/ldebug.h | 63 - external/lua/src/ldo.c | 963 - external/lua/src/ldo.h | 79 - external/lua/src/ldump.c | 226 - external/lua/src/lfunc.c | 294 - external/lua/src/lfunc.h | 64 - external/lua/src/lgc.c | 1728 -- external/lua/src/lgc.h | 189 - external/lua/src/linit.c | 65 - external/lua/src/liolib.c | 828 - external/lua/src/ljumptab.h | 112 - external/lua/src/llex.c | 581 - external/lua/src/llex.h | 91 - external/lua/src/llimits.h | 353 - external/lua/src/lmathlib.c | 764 - external/lua/src/lmem.c | 201 - external/lua/src/lmem.h | 93 - external/lua/src/loadlib.c | 762 - external/lua/src/lobject.c | 592 - external/lua/src/lobject.h | 800 - external/lua/src/lopcodes.c | 104 - external/lua/src/lopcodes.h | 392 - external/lua/src/lopnames.h | 103 - external/lua/src/loslib.c | 430 - external/lua/src/lparser.c | 1956 -- external/lua/src/lparser.h | 171 - external/lua/src/lprefix.h | 45 - external/lua/src/lstate.c | 439 - external/lua/src/lstate.h | 404 - external/lua/src/lstring.c | 273 - external/lua/src/lstring.h | 57 - external/lua/src/lstrlib.c | 1817 -- external/lua/src/ltable.c | 971 - external/lua/src/ltable.h | 66 - external/lua/src/ltablib.c | 429 - external/lua/src/ltm.c | 271 - external/lua/src/ltm.h | 103 - external/lua/src/lua.c | 659 - external/lua/src/lua.h | 518 - external/lua/src/lua.hpp | 9 - external/lua/src/luac.c | 724 - external/lua/src/luaconf.h | 790 - external/lua/src/lualib.h | 52 - external/lua/src/lundump.c | 333 - external/lua/src/lundump.h | 36 - external/lua/src/lutf8lib.c | 289 - external/lua/src/lvm.c | 1836 -- external/lua/src/lvm.h | 136 - external/lua/src/lzio.c | 68 - external/lua/src/lzio.h | 66 - external/minhook/CMakeLists.txt | 2 +- external/nvapi/License.txt | 67 + external/nvapi/NvApiDriverSettings.h | 1198 + external/nvapi/nvapi.h | 22606 ++++++++++++++++ external/nvapi/nvapi_lite_common.h | 652 + external/nvapi/nvapi_lite_d3dext.h | 191 + external/nvapi/nvapi_lite_salend.h | 816 + external/nvapi/nvapi_lite_salstart.h | 821 + external/nvapi/nvapi_lite_sli.h | 255 + external/nvapi/nvapi_lite_stereo.h | 600 + external/nvapi/nvapi_lite_surround.h | 103 + external/nvenc/nvEncodeAPI.h | 4529 ++++ external/openvr/.gitattributes | 42 - external/openvr/.gitignore | 1 - external/openvr/CMakeLists.txt | 97 - external/openvr/LICENSE | 27 - external/openvr/README.md | 13 - external/openvr/headers/openvr.h | 5624 ---- external/openvr/headers/openvr_capi.h | 3117 --- external/openvr/headers/openvr_driver.h | 4212 --- external/openvr/src/CMakeLists.txt | 118 - external/openvr/src/Info.plist | 18 - external/openvr/src/README | 39 - external/openvr/src/ivrclientcore.h | 35 - external/openvr/src/json/json-forwards.h | 284 - external/openvr/src/json/json.h | 2077 -- external/openvr/src/jsoncpp.cpp | 5267 ---- external/openvr/src/openvr.pc.in | 11 - external/openvr/src/openvr_api_public.cpp | 353 - .../openvr/src/vrcommon/dirtools_public.cpp | 101 - .../openvr/src/vrcommon/dirtools_public.h | 17 - .../src/vrcommon/envvartools_public.cpp | 88 - .../openvr/src/vrcommon/envvartools_public.h | 8 - .../openvr/src/vrcommon/hmderrors_public.cpp | 338 - .../openvr/src/vrcommon/hmderrors_public.h | 6 - .../openvr/src/vrcommon/pathtools_public.cpp | 994 - .../openvr/src/vrcommon/pathtools_public.h | 153 - .../src/vrcommon/sharedlibtools_public.cpp | 63 - .../src/vrcommon/sharedlibtools_public.h | 12 - .../openvr/src/vrcommon/strtools_public.cpp | 609 - .../openvr/src/vrcommon/strtools_public.h | 154 - .../src/vrcommon/vrpathregistry_public.cpp | 483 - .../src/vrcommon/vrpathregistry_public.h | 52 - external/rapidjson/document.h | 4 +- external/scard/scard.cpp | 70 +- external/scard/scard.h | 3 + external/tinyxml2/tinyxml2.cpp | 44 +- external/tinyxml2/tinyxml2.h | 5 +- games/bbc/bbc.cpp | 7 + games/bbc/io.cpp | 10 + games/bbc/io.h | 1 + games/bc/bc.cpp | 16 + games/bc/io.cpp | 21 + games/bc/io.h | 9 + games/bc/node.h | 7 + games/ccj/bi2x_hook.cpp | 624 + games/ccj/bi2x_hook.h | 5 + games/ccj/ccj.cpp | 112 + games/ccj/ccj.h | 16 + games/ccj/io.cpp | 81 + games/ccj/io.h | 59 + games/ccj/trackball.cpp | 268 + games/ccj/trackball.h | 12 + games/ddr/ddr.cpp | 56 + games/ddr/ddr.h | 6 + games/ddr/io.cpp | 93 +- games/ddr/io.h | 99 + games/ddr/p4io/p4io.cpp | 352 + games/ddr/p4io/p4io.h | 36 + games/drs/drs.cpp | 192 +- games/drs/drs.h | 32 +- games/drs/io.cpp | 36 +- games/drs/io.h | 17 + games/ftt/io.cpp | 9 + games/ftt/io.h | 1 + games/gitadora/gitadora.cpp | 50 +- games/gitadora/gitadora.h | 18 +- games/gitadora/io.cpp | 102 +- games/gitadora/io.h | 98 +- games/hpm/io.cpp | 8 + games/hpm/io.h | 1 + games/iidx/bi2a.cpp | 5 + games/iidx/bi2x.cpp | 5 + games/iidx/bi2x_hook.cpp | 32 +- games/iidx/camera.cpp | 668 + games/iidx/camera.h | 24 + games/iidx/iidx.cpp | 387 +- games/iidx/iidx.h | 9 + games/iidx/io.cpp | 12 + games/iidx/io.h | 1 + games/iidx/legacy_camera.cpp | 235 + games/iidx/legacy_camera.h | 5 + games/iidx/local_camera.cpp | 872 + games/iidx/local_camera.h | 187 + games/iidx/mf_wrappers.cpp | 116 + games/iidx/mf_wrappers.h | 30 + games/iidx/poke.cpp | 345 + games/iidx/poke.h | 6 + games/io.cpp | 71 +- games/io.h | 17 +- games/jb/io.cpp | 12 + games/jb/io.h | 1 + games/jb/jb.cpp | 21 + games/jb/jb.h | 1 + games/mfg/bi2a_hook.cpp | 385 + games/mfg/bi2a_hook.h | 5 + games/mfg/io.cpp | 22 + games/mfg/io.h | 18 + games/mfg/mfg.cpp | 74 + games/mfg/mfg.h | 18 + games/museca/io.cpp | 12 + games/museca/io.h | 3 + games/museca/museca.cpp | 18 + games/museca/museca.h | 13 + games/nost/io.cpp | 116 +- games/nost/io.h | 101 +- games/nost/nost.cpp | 18 +- games/nost/nost.h | 4 + games/nost/poke.cpp | 204 + games/nost/poke.h | 6 + games/pcm/pcm.cpp | 54 +- games/popn/io.cpp | 13 +- games/popn/io.h | 4 + games/popn/popn.cpp | 27 +- games/qks/bi2x_hook.cpp | 605 + games/qks/bi2x_hook.h | 7 + games/qks/io.cpp | 29 + games/qks/io.h | 24 + games/qks/qks.cpp | 124 + games/qks/qks.h | 16 + games/qma/qma.cpp | 2 +- games/rb/rb.h | 2 + games/rb/touch.cpp | 2 +- games/sc/sc.cpp | 2 +- games/sdvx/bi2x_hook.cpp | 39 +- games/sdvx/io.cpp | 14 + games/sdvx/io.h | 1 + games/sdvx/sdvx.cpp | 101 +- games/sdvx/sdvx.h | 6 +- hooks/audio/audio.cpp | 37 +- hooks/audio/audio.h | 5 + hooks/audio/audio_private.h | 3 + .../mmdevice/audio_endpoint_volume.cpp | 112 + .../backends/mmdevice/audio_endpoint_volume.h | 43 + hooks/audio/backends/mmdevice/device.cpp | 5 + .../backends/mmdevice/device_enumerator.cpp | 36 +- .../backends/wasapi/low_latency_client.cpp | 153 + .../backends/wasapi/low_latency_client.h | 22 + hooks/audio/implementations/asio.cpp | 8 + hooks/avshook.cpp | 47 +- hooks/devicehook.cpp | 70 +- hooks/devicehook.h | 6 + hooks/graphics/backends/d3d9/d3d9_backend.cpp | 281 +- hooks/graphics/backends/d3d9/d3d9_device.cpp | 176 +- hooks/graphics/graphics.cpp | 266 +- hooks/graphics/graphics.h | 33 +- hooks/graphics/graphics_windowed.cpp | 83 +- hooks/graphics/nvapi_hook.cpp | 59 + hooks/graphics/nvapi_hook.h | 6 + hooks/graphics/nvenc_hook.cpp | 175 + hooks/graphics/nvenc_hook.h | 7 + hooks/lang.cpp | 27 + hooks/networkhook.cpp | 11 +- hooks/winuser.cpp | 23 + hooks/winuser.h | 5 + launcher/launcher.cpp | 696 +- launcher/options.cpp | 1040 +- launcher/options.h | 71 +- launcher/richpresence.cpp | 51 +- launcher/shutdown.cpp | 11 +- launcher/signal.cpp | 3 +- launcher/signal.h | 1 + launcher/superexit.cpp | 27 +- licenses.txt | 745 +- misc/clipboard.cpp | 42 + misc/clipboard.h | 2 + misc/device.cpp | 30 +- misc/eamuse.cpp | 202 +- misc/eamuse.h | 16 +- misc/extdev.cpp | 297 +- misc/vrutil.cpp | 120 - misc/vrutil.h | 139 - misc/wintouchemu.cpp | 92 +- misc/wintouchemu.h | 2 +- nvapi/nvapi.cpp | 313 + nvapi/nvapi.h | 10 + overlay/imgui/extensions.cpp | 65 +- overlay/imgui/extensions.h | 4 + overlay/imgui/impl_spice.cpp | 86 +- overlay/imgui/impl_sw.cpp | 2 +- overlay/overlay.cpp | 225 +- overlay/overlay.h | 21 +- overlay/window.cpp | 5 +- overlay/window.h | 1 + overlay/windows/camera_control.cpp | 216 + overlay/windows/camera_control.h | 24 + overlay/windows/card_manager.cpp | 537 +- overlay/windows/card_manager.h | 33 +- overlay/windows/config.cpp | 3776 ++- overlay/windows/config.h | 32 +- overlay/windows/control.cpp | 30 +- overlay/windows/drs_dancefloor.cpp | 66 + overlay/windows/drs_dancefloor.h | 20 + overlay/windows/exitprompt.cpp | 139 + overlay/windows/exitprompt.h | 21 + overlay/windows/fps.cpp | 3 +- overlay/windows/fps.h | 2 + overlay/windows/generic_sub.cpp | 53 +- overlay/windows/generic_sub.h | 14 + overlay/windows/iidx_sub.cpp | 22 +- overlay/windows/iopanel_gfdm.cpp | 26 +- overlay/windows/iopanel_gfdm.h | 5 + overlay/windows/keypad.cpp | 33 + overlay/windows/keypad.h | 2 + overlay/windows/kfcontrol.cpp | 1449 - overlay/windows/kfcontrol.h | 125 - overlay/windows/midi.cpp | 4 +- overlay/windows/patch_manager.cpp | 2746 +- overlay/windows/patch_manager.h | 105 +- overlay/windows/screen_resize.cpp | 153 +- overlay/windows/screen_resize.h | 3 + overlay/windows/sdvx_sub.cpp | 41 +- overlay/windows/vr.cpp | 218 - overlay/windows/vr.h | 17 - rawinput/device.h | 37 +- rawinput/hotplug.cpp | 2 +- rawinput/rawinput.cpp | 363 +- rawinput/rawinput.h | 23 +- rawinput/sextet.h | 1 + rawinput/smx.cpp | 83 + rawinput/smx.h | 48 + rawinput/smxdedicab.cpp | 97 + rawinput/smxdedicab.h | 22 + rawinput/smxstage.cpp | 62 + rawinput/smxstage.h | 30 + reader/reader.cpp | 4 +- readme.txt | 19 +- script/api/analogs.cpp | 73 - script/api/analogs.h | 7 - script/api/buttons.cpp | 82 - script/api/buttons.h | 7 - script/api/capture.cpp | 53 - script/api/capture.h | 7 - script/api/card.cpp | 28 - script/api/card.h | 7 - script/api/coin.cpp | 38 - script/api/coin.h | 7 - script/api/control.cpp | 121 - script/api/control.h | 7 - script/api/drs.cpp | 21 - script/api/drs.h | 7 - script/api/iidx.cpp | 46 - script/api/iidx.h | 7 - script/api/info.cpp | 68 - script/api/info.h | 7 - script/api/keypads.cpp | 114 - script/api/keypads.h | 7 - script/api/lcd.cpp | 28 - script/api/lcd.h | 7 - script/api/lights.cpp | 91 - script/api/lights.h | 7 - script/api/memory.cpp | 143 - script/api/memory.h | 7 - script/api/touch.cpp | 67 - script/api/touch.h | 7 - script/instance.cpp | 133 - script/instance.h | 39 - script/lib.cpp | 155 - script/lib.h | 7 - script/manager.cpp | 122 - script/manager.h | 13 - stubs/nvEncodeAPI64.cpp | 16 + stubs/nvEncodeAPI64.def | 3 + stubs/nvcuda.cpp | 88 + stubs/nvcuda.def | 22 + stubs/nvcuvid.cpp | 75 + stubs/nvcuvid.def | 14 + touch/touch.cpp | 93 +- touch/touch.h | 4 +- touch/touch_indicators.cpp | 57 + touch/touch_indicators.h | 5 + util/cpuutils.cpp | 256 +- util/cpuutils.h | 10 + util/crypt.h | 1 + util/execexe.cpp | 180 + util/execexe.h | 38 + util/fileutils.cpp | 64 + util/fileutils.h | 4 + util/libutils.cpp | 64 +- util/libutils.h | 2 + util/logging.h | 4 +- util/netutils.cpp | 89 + util/netutils.h | 1 + util/nt_loader.h | 46 + util/sigscan.cpp | 138 + util/sigscan.h | 36 + util/sysutils.cpp | 276 + util/sysutils.h | 10 + util/tapeled.cpp | 79 + util/tapeled.h | 26 + util/unity_player.cpp | 84 + util/unity_player.h | 9 + util/utils.cpp | 48 + util/utils.h | 44 + 543 files changed, 78491 insertions(+), 91698 deletions(-) create mode 100644 api/modules/ddr.cpp create mode 100644 api/modules/ddr.h create mode 100644 api/modules/resize.cpp create mode 100644 api/modules/resize.h delete mode 100644 api/resources/lua/README.md delete mode 100644 api/resources/lua/boot_iidx_tt_lights.lua delete mode 100644 api/resources/lua/config_example.lua create mode 100644 api/resources/python/spiceapi/resize.py mode change 100644 => 100755 build_all.sh mode change 100644 => 100755 build_docker.sh delete mode 100644 build_msvc.py create mode 100644 build_release.bat delete mode 100644 external/LuaBridge.h create mode 100644 external/cpu_features/.clang-format create mode 100644 external/cpu_features/.dockerignore create mode 100644 external/cpu_features/.gitignore create mode 100644 external/cpu_features/.grenrc.yml create mode 100644 external/cpu_features/BUILD.bazel create mode 100644 external/cpu_features/CMakeLists.txt create mode 100644 external/cpu_features/CONTRIBUTING.md create mode 100644 external/cpu_features/LICENSE create mode 100644 external/cpu_features/README.md create mode 100644 external/cpu_features/WORKSPACE create mode 100644 external/cpu_features/cmake/CpuFeaturesConfig.cmake.in create mode 100644 external/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in create mode 100644 external/cpu_features/cmake/README.md create mode 100644 external/cpu_features/cmake/ci/Makefile create mode 100644 external/cpu_features/cmake/ci/README.md create mode 100644 external/cpu_features/cmake/ci/doc/docker.dot create mode 100644 external/cpu_features/cmake/ci/doc/docker.svg create mode 100644 external/cpu_features/cmake/ci/doc/generate_image.sh create mode 100644 external/cpu_features/cmake/ci/docker/amd64/Dockerfile create mode 100644 external/cpu_features/cmake/ci/docker/toolchain/Dockerfile create mode 100644 external/cpu_features/cmake/ci/sample/CMakeLists.txt create mode 100644 external/cpu_features/cmake/ci/sample/main.cpp create mode 100644 external/cpu_features/cmake/ci/vagrant/freebsd/Vagrantfile create mode 100644 external/cpu_features/cmake/googletest.CMakeLists.txt.in create mode 100644 external/cpu_features/include/cpu_features_cache_info.h create mode 100644 external/cpu_features/include/cpu_features_macros.h create mode 100644 external/cpu_features/include/cpuinfo_aarch64.h create mode 100644 external/cpu_features/include/cpuinfo_arm.h create mode 100644 external/cpu_features/include/cpuinfo_loongarch.h create mode 100644 external/cpu_features/include/cpuinfo_mips.h create mode 100644 external/cpu_features/include/cpuinfo_ppc.h create mode 100644 external/cpu_features/include/cpuinfo_riscv.h create mode 100644 external/cpu_features/include/cpuinfo_s390x.h create mode 100644 external/cpu_features/include/cpuinfo_x86.h create mode 100644 external/cpu_features/include/internal/bit_utils.h create mode 100644 external/cpu_features/include/internal/cpuid_x86.h create mode 100644 external/cpu_features/include/internal/filesystem.h create mode 100644 external/cpu_features/include/internal/hwcaps.h create mode 100644 external/cpu_features/include/internal/stack_line_reader.h create mode 100644 external/cpu_features/include/internal/string_view.h create mode 100644 external/cpu_features/include/internal/windows_utils.h create mode 100644 external/cpu_features/src/copy.inl create mode 100644 external/cpu_features/src/define_introspection.inl create mode 100644 external/cpu_features/src/define_introspection_and_hwcaps.inl create mode 100644 external/cpu_features/src/equals.inl create mode 100644 external/cpu_features/src/filesystem.c create mode 100644 external/cpu_features/src/hwcaps.c create mode 100644 external/cpu_features/src/impl_aarch64__base_implementation.inl create mode 100644 external/cpu_features/src/impl_aarch64_linux_or_android.c create mode 100644 external/cpu_features/src/impl_aarch64_macos_or_iphone.c create mode 100644 external/cpu_features/src/impl_aarch64_windows.c create mode 100644 external/cpu_features/src/impl_arm_linux_or_android.c create mode 100644 external/cpu_features/src/impl_loongarch_linux.c create mode 100644 external/cpu_features/src/impl_mips_linux_or_android.c create mode 100644 external/cpu_features/src/impl_ppc_linux.c create mode 100644 external/cpu_features/src/impl_riscv_linux.c create mode 100644 external/cpu_features/src/impl_s390x_linux.c create mode 100644 external/cpu_features/src/impl_x86__base_implementation.inl create mode 100644 external/cpu_features/src/impl_x86_freebsd.c create mode 100644 external/cpu_features/src/impl_x86_linux_or_android.c create mode 100644 external/cpu_features/src/impl_x86_macos.c create mode 100644 external/cpu_features/src/impl_x86_windows.c create mode 100644 external/cpu_features/src/stack_line_reader.c create mode 100644 external/cpu_features/src/string_view.c create mode 100644 external/cpu_features/src/utils/list_cpu_features.c delete mode 100644 external/cv2pdb/.gitignore delete mode 100644 external/cv2pdb/README.md rename overlay/imgui/impl_dx9.cpp => external/imgui/backends/imgui_impl_dx9.cpp (99%) rename overlay/imgui/impl_dx9.h => external/imgui/backends/imgui_impl_dx9.h (96%) create mode 100644 external/imgui/misc/cpp/imgui_stdlib.cpp create mode 100644 external/imgui/misc/cpp/imgui_stdlib.h delete mode 100644 external/layeredfs/3rd_party/GuillotineBinPack.cpp delete mode 100644 external/layeredfs/3rd_party/GuillotineBinPack.h delete mode 100644 external/layeredfs/3rd_party/Rect.cpp delete mode 100644 external/layeredfs/3rd_party/Rect.h delete mode 100644 external/layeredfs/3rd_party/lodepng.cpp delete mode 100644 external/layeredfs/3rd_party/lodepng.h delete mode 100644 external/layeredfs/3rd_party/rapidxml.hpp delete mode 100644 external/layeredfs/3rd_party/rapidxml_print.hpp delete mode 100644 external/layeredfs/3rd_party/stb_dxt.cpp delete mode 100644 external/layeredfs/3rd_party/stb_dxt.h delete mode 100644 external/layeredfs/LICENSE delete mode 100644 external/layeredfs/config.cpp delete mode 100644 external/layeredfs/config.h delete mode 100644 external/layeredfs/hook.cpp delete mode 100644 external/layeredfs/hook.h delete mode 100644 external/layeredfs/modpath_handler.cpp delete mode 100644 external/layeredfs/modpath_handler.h delete mode 100644 external/layeredfs/texture_packer.cpp delete mode 100644 external/layeredfs/texture_packer.h delete mode 100644 external/layeredfs/utils.cpp delete mode 100644 external/layeredfs/utils.h delete mode 100644 external/lua/CMakeLists.txt delete mode 100644 external/lua/README delete mode 100644 external/lua/src/Makefile delete mode 100644 external/lua/src/lapi.c delete mode 100644 external/lua/src/lapi.h delete mode 100644 external/lua/src/lauxlib.c delete mode 100644 external/lua/src/lauxlib.h delete mode 100644 external/lua/src/lbaselib.c delete mode 100644 external/lua/src/lcode.c delete mode 100644 external/lua/src/lcode.h delete mode 100644 external/lua/src/lcorolib.c delete mode 100644 external/lua/src/lctype.c delete mode 100644 external/lua/src/lctype.h delete mode 100644 external/lua/src/ldblib.c delete mode 100644 external/lua/src/ldebug.c delete mode 100644 external/lua/src/ldebug.h delete mode 100644 external/lua/src/ldo.c delete mode 100644 external/lua/src/ldo.h delete mode 100644 external/lua/src/ldump.c delete mode 100644 external/lua/src/lfunc.c delete mode 100644 external/lua/src/lfunc.h delete mode 100644 external/lua/src/lgc.c delete mode 100644 external/lua/src/lgc.h delete mode 100644 external/lua/src/linit.c delete mode 100644 external/lua/src/liolib.c delete mode 100644 external/lua/src/ljumptab.h delete mode 100644 external/lua/src/llex.c delete mode 100644 external/lua/src/llex.h delete mode 100644 external/lua/src/llimits.h delete mode 100644 external/lua/src/lmathlib.c delete mode 100644 external/lua/src/lmem.c delete mode 100644 external/lua/src/lmem.h delete mode 100644 external/lua/src/loadlib.c delete mode 100644 external/lua/src/lobject.c delete mode 100644 external/lua/src/lobject.h delete mode 100644 external/lua/src/lopcodes.c delete mode 100644 external/lua/src/lopcodes.h delete mode 100644 external/lua/src/lopnames.h delete mode 100644 external/lua/src/loslib.c delete mode 100644 external/lua/src/lparser.c delete mode 100644 external/lua/src/lparser.h delete mode 100644 external/lua/src/lprefix.h delete mode 100644 external/lua/src/lstate.c delete mode 100644 external/lua/src/lstate.h delete mode 100644 external/lua/src/lstring.c delete mode 100644 external/lua/src/lstring.h delete mode 100644 external/lua/src/lstrlib.c delete mode 100644 external/lua/src/ltable.c delete mode 100644 external/lua/src/ltable.h delete mode 100644 external/lua/src/ltablib.c delete mode 100644 external/lua/src/ltm.c delete mode 100644 external/lua/src/ltm.h delete mode 100644 external/lua/src/lua.c delete mode 100644 external/lua/src/lua.h delete mode 100644 external/lua/src/lua.hpp delete mode 100644 external/lua/src/luac.c delete mode 100644 external/lua/src/luaconf.h delete mode 100644 external/lua/src/lualib.h delete mode 100644 external/lua/src/lundump.c delete mode 100644 external/lua/src/lundump.h delete mode 100644 external/lua/src/lutf8lib.c delete mode 100644 external/lua/src/lvm.c delete mode 100644 external/lua/src/lvm.h delete mode 100644 external/lua/src/lzio.c delete mode 100644 external/lua/src/lzio.h create mode 100644 external/nvapi/License.txt create mode 100644 external/nvapi/NvApiDriverSettings.h create mode 100644 external/nvapi/nvapi.h create mode 100644 external/nvapi/nvapi_lite_common.h create mode 100644 external/nvapi/nvapi_lite_d3dext.h create mode 100644 external/nvapi/nvapi_lite_salend.h create mode 100644 external/nvapi/nvapi_lite_salstart.h create mode 100644 external/nvapi/nvapi_lite_sli.h create mode 100644 external/nvapi/nvapi_lite_stereo.h create mode 100644 external/nvapi/nvapi_lite_surround.h create mode 100644 external/nvenc/nvEncodeAPI.h delete mode 100644 external/openvr/.gitattributes delete mode 100644 external/openvr/.gitignore delete mode 100644 external/openvr/CMakeLists.txt delete mode 100644 external/openvr/LICENSE delete mode 100644 external/openvr/README.md delete mode 100644 external/openvr/headers/openvr.h delete mode 100644 external/openvr/headers/openvr_capi.h delete mode 100644 external/openvr/headers/openvr_driver.h delete mode 100644 external/openvr/src/CMakeLists.txt delete mode 100644 external/openvr/src/Info.plist delete mode 100644 external/openvr/src/README delete mode 100644 external/openvr/src/ivrclientcore.h delete mode 100644 external/openvr/src/json/json-forwards.h delete mode 100644 external/openvr/src/json/json.h delete mode 100644 external/openvr/src/jsoncpp.cpp delete mode 100644 external/openvr/src/openvr.pc.in delete mode 100644 external/openvr/src/openvr_api_public.cpp delete mode 100644 external/openvr/src/vrcommon/dirtools_public.cpp delete mode 100644 external/openvr/src/vrcommon/dirtools_public.h delete mode 100644 external/openvr/src/vrcommon/envvartools_public.cpp delete mode 100644 external/openvr/src/vrcommon/envvartools_public.h delete mode 100644 external/openvr/src/vrcommon/hmderrors_public.cpp delete mode 100644 external/openvr/src/vrcommon/hmderrors_public.h delete mode 100644 external/openvr/src/vrcommon/pathtools_public.cpp delete mode 100644 external/openvr/src/vrcommon/pathtools_public.h delete mode 100644 external/openvr/src/vrcommon/sharedlibtools_public.cpp delete mode 100644 external/openvr/src/vrcommon/sharedlibtools_public.h delete mode 100644 external/openvr/src/vrcommon/strtools_public.cpp delete mode 100644 external/openvr/src/vrcommon/strtools_public.h delete mode 100644 external/openvr/src/vrcommon/vrpathregistry_public.cpp delete mode 100644 external/openvr/src/vrcommon/vrpathregistry_public.h create mode 100644 games/ccj/bi2x_hook.cpp create mode 100644 games/ccj/bi2x_hook.h create mode 100644 games/ccj/ccj.cpp create mode 100644 games/ccj/ccj.h create mode 100644 games/ccj/io.cpp create mode 100644 games/ccj/io.h create mode 100644 games/ccj/trackball.cpp create mode 100644 games/ccj/trackball.h create mode 100644 games/ddr/p4io/p4io.cpp create mode 100644 games/ddr/p4io/p4io.h create mode 100644 games/iidx/camera.cpp create mode 100644 games/iidx/camera.h create mode 100644 games/iidx/legacy_camera.cpp create mode 100644 games/iidx/legacy_camera.h create mode 100644 games/iidx/local_camera.cpp create mode 100644 games/iidx/local_camera.h create mode 100644 games/iidx/mf_wrappers.cpp create mode 100644 games/iidx/mf_wrappers.h create mode 100644 games/iidx/poke.cpp create mode 100644 games/iidx/poke.h create mode 100644 games/mfg/bi2a_hook.cpp create mode 100644 games/mfg/bi2a_hook.h create mode 100644 games/mfg/io.cpp create mode 100644 games/mfg/io.h create mode 100644 games/mfg/mfg.cpp create mode 100644 games/mfg/mfg.h create mode 100644 games/museca/museca.cpp create mode 100644 games/museca/museca.h create mode 100644 games/nost/poke.cpp create mode 100644 games/nost/poke.h create mode 100644 games/qks/bi2x_hook.cpp create mode 100644 games/qks/bi2x_hook.h create mode 100644 games/qks/io.cpp create mode 100644 games/qks/io.h create mode 100644 games/qks/qks.cpp create mode 100644 games/qks/qks.h create mode 100644 hooks/audio/backends/mmdevice/audio_endpoint_volume.cpp create mode 100644 hooks/audio/backends/mmdevice/audio_endpoint_volume.h create mode 100644 hooks/audio/backends/wasapi/low_latency_client.cpp create mode 100644 hooks/audio/backends/wasapi/low_latency_client.h create mode 100644 hooks/graphics/nvapi_hook.cpp create mode 100644 hooks/graphics/nvapi_hook.h create mode 100644 hooks/graphics/nvenc_hook.cpp create mode 100644 hooks/graphics/nvenc_hook.h create mode 100644 hooks/winuser.cpp create mode 100644 hooks/winuser.h delete mode 100644 misc/vrutil.cpp delete mode 100644 misc/vrutil.h create mode 100644 nvapi/nvapi.cpp create mode 100644 nvapi/nvapi.h create mode 100644 overlay/windows/camera_control.cpp create mode 100644 overlay/windows/camera_control.h create mode 100644 overlay/windows/drs_dancefloor.cpp create mode 100644 overlay/windows/drs_dancefloor.h create mode 100644 overlay/windows/exitprompt.cpp create mode 100644 overlay/windows/exitprompt.h delete mode 100644 overlay/windows/kfcontrol.cpp delete mode 100644 overlay/windows/kfcontrol.h delete mode 100644 overlay/windows/vr.cpp delete mode 100644 overlay/windows/vr.h create mode 100644 rawinput/smx.cpp create mode 100644 rawinput/smx.h create mode 100644 rawinput/smxdedicab.cpp create mode 100644 rawinput/smxdedicab.h create mode 100644 rawinput/smxstage.cpp create mode 100644 rawinput/smxstage.h delete mode 100644 script/api/analogs.cpp delete mode 100644 script/api/analogs.h delete mode 100644 script/api/buttons.cpp delete mode 100644 script/api/buttons.h delete mode 100644 script/api/capture.cpp delete mode 100644 script/api/capture.h delete mode 100644 script/api/card.cpp delete mode 100644 script/api/card.h delete mode 100644 script/api/coin.cpp delete mode 100644 script/api/coin.h delete mode 100644 script/api/control.cpp delete mode 100644 script/api/control.h delete mode 100644 script/api/drs.cpp delete mode 100644 script/api/drs.h delete mode 100644 script/api/iidx.cpp delete mode 100644 script/api/iidx.h delete mode 100644 script/api/info.cpp delete mode 100644 script/api/info.h delete mode 100644 script/api/keypads.cpp delete mode 100644 script/api/keypads.h delete mode 100644 script/api/lcd.cpp delete mode 100644 script/api/lcd.h delete mode 100644 script/api/lights.cpp delete mode 100644 script/api/lights.h delete mode 100644 script/api/memory.cpp delete mode 100644 script/api/memory.h delete mode 100644 script/api/touch.cpp delete mode 100644 script/api/touch.h delete mode 100644 script/instance.cpp delete mode 100644 script/instance.h delete mode 100644 script/lib.cpp delete mode 100644 script/lib.h delete mode 100644 script/manager.cpp delete mode 100644 script/manager.h create mode 100644 stubs/nvEncodeAPI64.cpp create mode 100644 stubs/nvEncodeAPI64.def create mode 100644 stubs/nvcuda.cpp create mode 100644 stubs/nvcuda.def create mode 100644 stubs/nvcuvid.cpp create mode 100644 stubs/nvcuvid.def create mode 100644 touch/touch_indicators.cpp create mode 100644 touch/touch_indicators.h create mode 100644 util/execexe.cpp create mode 100644 util/execexe.h create mode 100644 util/nt_loader.h create mode 100644 util/sysutils.cpp create mode 100644 util/sysutils.h create mode 100644 util/tapeled.cpp create mode 100644 util/tapeled.h create mode 100644 util/unity_player.cpp create mode 100644 util/unity_player.h diff --git a/.dockerignore b/.dockerignore index 852f8ce..e2cfd15 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,3 +2,4 @@ bin/** dist/** docker/** cmake-build* +.ccache/** \ No newline at end of file diff --git a/.gitignore b/.gitignore index 268577f..07a2a7a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ build_docker.local.sh bin/* dist/* -external/cv2pdb/* \ No newline at end of file +external/cv2pdb/* + +.ccache/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fbd1d8..a8db848 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.9) +cmake_minimum_required(VERSION 3.12) cmake_policy(SET CMP0069 NEW) project(spicetools) include(CheckIPOSupported) @@ -14,7 +14,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) add_compile_definitions(RAPIDJSON_HAS_STDSTRING) if(MSVC) - # disable intermediate manifest set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /manifest:no") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /manifest:no") @@ -34,27 +33,53 @@ if(MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DYNAMICBASE:NO") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DYNAMICBASE:NO") - # use statically linked runtime - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - set(CompilerFlags - CMAKE_CXX_FLAGS - CMAKE_CXX_FLAGS_DEBUG - CMAKE_CXX_FLAGS_RELEASE - CMAKE_C_FLAGS - CMAKE_C_FLAGS_DEBUG - CMAKE_C_FLAGS_RELEASE - ) - foreach(CompilerFlag ${CompilerFlags}) - string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") - endforeach() + set(USE_STATIC_MSVCRT ON CACHE BOOL "If enabled, will force the use of static crt instead of dynamic") - # enable PDB generation with Release builds - if(CMAKE_BUILD_TYPE MATCHES "Release") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF") + if(USE_STATIC_MSVCRT) + # use statically linked runtime + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + set(CompilerFlags + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE + ) + + foreach(CompilerFlag ${CompilerFlags}) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + endforeach() endif() + + # disable C4996 "The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name" warning + add_compile_options("/wd4996") + + # cleanup windows.h includes + add_compile_options("/DNOMINMAX") + + # cleanup weird types + add_compile_options("/DWINBOOL=BOOL") + + # add support for the deprecated std::result_of in c++20 + add_compile_options("/D_HAS_DEPRECATED_RESULT_OF") + + # enable build paralellization + add_compile_options("/MP") + + # enable edit and continue in Debug + add_compile_options("$<$:/ZI>") + add_link_options("$<$:/SAFESEH:NO>") + + # enable fast pdb generation in debug + add_link_options("$<$:/DEBUG:FASTLINK>") + + # enable pdb generation for release builds + add_compile_options("$<$:/Zi>") + add_link_options("$<$:/DEBUG:FULL>") + + # enable COMDAT folding for even smaller release builds + add_link_options("$<$:/OPT:ICF>") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # disable warnings about using non _s variants like strncpy add_compile_definitions(_CRT_SECURE_NO_WARNINGS) @@ -94,8 +119,13 @@ else() # hide ident strings set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-ident -ffunction-sections -fdata-sections") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-ident -ffunction-sections -fdata-sections") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections") + + # a change in the linker caused the executable to be loaded above 4GB base virtual address + # https://github.com/msys2/MINGW-packages/pull/6880 + # some games crash if some DLLS load above 4GB VA, so manually set base address to standard 32-bit VA, + # and might as well double make sure ASLR is disabled here + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000") # set visibility to hidden set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden") @@ -106,8 +136,8 @@ else() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s") # performance - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -pipe") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -pipe") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2 -pipe") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -pipe") # ensure frame pointers are enabled set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-omit-frame-pointer") @@ -128,8 +158,10 @@ else() # hide ident strings set(CMAKE_C_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections") + + # linker fix to load below 4GB + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000") # set visibility to hidden set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fvisibility=hidden") @@ -151,6 +183,10 @@ else() set(CMAKE_C_FLAGS_DEBUG "-gdwarf") set(CMAKE_CXX_FLAGS_DEBUG "-gdwarf") + # linker fix to load below 4GB + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000") + # enable debug symbols on level 3 and keep frame pointers set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer") @@ -169,14 +205,13 @@ endif() add_compile_definitions( WIN32_LEAN_AND_MEAN _WIN32_IE=0x0400 - OPENVR_BUILD_STATIC ) # acioemu log #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DACIOEMU_LOG") # add project directory to include path so we can comfortably import -include_directories(${spicetools_SOURCE_DIR}) +include_directories(${spicetools_SOURCE_DIR} ${spicetools_SOURCE_DIR}/external/imgui) # add external libraries add_subdirectory(external/fmt EXCLUDE_FROM_ALL) @@ -184,18 +219,16 @@ add_subdirectory(external/discord-rpc EXCLUDE_FROM_ALL) add_subdirectory(external/hash-library EXCLUDE_FROM_ALL) add_subdirectory(external/imgui EXCLUDE_FROM_ALL) add_subdirectory(external/minhook EXCLUDE_FROM_ALL) -add_subdirectory(external/openvr EXCLUDE_FROM_ALL) -add_subdirectory(external/lua EXCLUDE_FROM_ALL) +add_subdirectory(external/cpu_features EXCLUDE_FROM_ALL) # set link time optimizations (disabled for Debug builds for speed, disabled # for RelWithDebInfo builds due to "lto1: error: two or more sections for" # errors) check_ipo_supported() -if(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo" OR CMAKE_BUILD_TYPE MATCHES "Debug") - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE) -else() - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) -endif() +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_DEBUG OFF) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO OFF) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL ON) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON) # resources ########### @@ -266,6 +299,8 @@ set(SOURCE_FILES ${SOURCE_FILES} api/serial.cpp api/modules/drs.cpp api/modules/lcd.cpp + api/modules/ddr.cpp + api/modules/resize.cpp # avs avs/core.cpp @@ -297,17 +332,6 @@ set(SOURCE_FILES ${SOURCE_FILES} # external asio external/asio/asiolist.cpp - # external layeredfs - external/layeredfs/config.cpp - external/layeredfs/hook.cpp - external/layeredfs/modpath_handler.cpp - external/layeredfs/texture_packer.cpp - external/layeredfs/utils.cpp - external/layeredfs/3rd_party/GuillotineBinPack.cpp - external/layeredfs/3rd_party/lodepng.cpp - external/layeredfs/3rd_party/Rect.cpp - external/layeredfs/3rd_party/stb_dxt.cpp - # external cardio external/cardio/cardio_hid.cpp external/cardio/cardio_window.cpp @@ -335,10 +359,15 @@ set(SOURCE_FILES ${SOURCE_FILES} games/hpm/io.cpp games/iidx/iidx.cpp games/iidx/io.cpp + games/iidx/poke.cpp games/iidx/bi2a.cpp games/iidx/bi2x.cpp games/iidx/bi2x_hook.cpp games/iidx/ezusb.cpp + games/iidx/legacy_camera.cpp + games/iidx/local_camera.cpp + games/iidx/camera.cpp + games/iidx/mf_wrappers.cpp games/sdvx/bi2x_hook.cpp games/sdvx/sdvx.cpp games/sdvx/io.cpp @@ -347,6 +376,7 @@ set(SOURCE_FILES ${SOURCE_FILES} games/jb/io.cpp games/nost/nost.cpp games/nost/io.cpp + games/nost/poke.cpp games/gitadora/gitadora.cpp games/gitadora/io.cpp games/mga/mga.cpp @@ -362,6 +392,7 @@ set(SOURCE_FILES ${SOURCE_FILES} games/rf3d/rf3d.cpp games/rf3d/io.cpp games/museca/io.cpp + games/museca/museca.cpp games/dea/dea.cpp games/dea/io.cpp games/qma/qma.cpp @@ -372,6 +403,8 @@ set(SOURCE_FILES ${SOURCE_FILES} games/ddr/p3io/p3io.cpp games/ddr/p3io/sate.cpp games/ddr/p3io/usbmem.cpp + games/ddr/p4io/p4io.cpp + games/ddr/p4io/p4io.h games/mfc/mfc.cpp games/mfc/io.cpp games/ftt/ftt.cpp @@ -400,12 +433,23 @@ set(SOURCE_FILES ${SOURCE_FILES} games/onpara/touchpanel.cpp games/bc/bc.cpp games/bc/io.cpp + games/ccj/ccj.cpp + games/ccj/io.cpp + games/ccj/bi2x_hook.cpp + games/ccj/trackball.cpp + games/qks/qks.cpp + games/qks/io.cpp + games/qks/bi2x_hook.cpp + games/mfg/mfg.cpp + games/mfg/io.cpp + games/mfg/bi2a_hook.cpp # hooks hooks/audio/audio.cpp hooks/audio/buffer.cpp hooks/audio/util.cpp hooks/audio/backends/dsound/dsound_backend.cpp + hooks/audio/backends/mmdevice/audio_endpoint_volume.cpp hooks/audio/backends/mmdevice/device.cpp hooks/audio/backends/mmdevice/device_enumerator.cpp hooks/audio/backends/wasapi/audio_client.cpp @@ -414,6 +458,7 @@ set(SOURCE_FILES ${SOURCE_FILES} hooks/audio/backends/wasapi/dummy_audio_clock.cpp hooks/audio/backends/wasapi/dummy_audio_render_client.cpp hooks/audio/backends/wasapi/dummy_audio_session_control.cpp + hooks/audio/backends/wasapi/low_latency_client.cpp hooks/audio/backends/wasapi/util.cpp hooks/audio/implementations/asio.cpp hooks/audio/implementations/wave_out.cpp @@ -423,6 +468,8 @@ set(SOURCE_FILES ${SOURCE_FILES} hooks/devicehook.cpp hooks/graphics/graphics.cpp hooks/graphics/graphics_windowed.cpp + hooks/graphics/nvapi_hook.cpp + hooks/graphics/nvenc_hook.cpp hooks/graphics/backends/d3d9/d3d9_backend.cpp hooks/graphics/backends/d3d9/d3d9_device.cpp hooks/graphics/backends/d3d9/d3d9_fake_swapchain.cpp @@ -439,6 +486,7 @@ set(SOURCE_FILES ${SOURCE_FILES} hooks/setupapihook.cpp hooks/sleephook.cpp hooks/unisintrhook.cpp + hooks/winuser.cpp # launcher launcher/launcher.cpp @@ -457,18 +505,21 @@ set(SOURCE_FILES ${SOURCE_FILES} misc/extdev.cpp misc/sciunit.cpp misc/sde.cpp - misc/vrutil.cpp misc/wintouchemu.cpp + # nvapi + nvapi/nvapi.cpp + # overlay overlay/overlay.cpp overlay/window.cpp overlay/imgui/extensions.cpp - overlay/imgui/impl_dx9.cpp overlay/imgui/impl_spice.cpp overlay/imgui/impl_sw.cpp overlay/windows/acio_status_buffers.cpp + overlay/windows/camera_control.cpp overlay/windows/card_manager.cpp + overlay/windows/drs_dancefloor.cpp overlay/windows/screen_resize.cpp overlay/windows/sdvx_sub.cpp overlay/windows/config.cpp @@ -483,11 +534,9 @@ set(SOURCE_FILES ${SOURCE_FILES} overlay/windows/iopanel_gfdm.cpp overlay/windows/iopanel_iidx.cpp overlay/windows/keypad.cpp - overlay/windows/kfcontrol.cpp overlay/windows/log.cpp overlay/windows/midi.cpp overlay/windows/patch_manager.cpp - overlay/windows/vr.cpp overlay/windows/wnd_manager.cpp # rawinput @@ -496,6 +545,12 @@ set(SOURCE_FILES ${SOURCE_FILES} rawinput/piuio.cpp rawinput/touch.cpp rawinput/hotplug.cpp + rawinput/smx.cpp + rawinput/smx.h + rawinput/smxstage.cpp + rawinput/smxstage.h + rawinput/smxdedicab.cpp + rawinput/smxdedicab.h # reader reader/reader.cpp @@ -503,30 +558,12 @@ set(SOURCE_FILES ${SOURCE_FILES} reader/structuredmessage.cpp reader/crypt.cpp - # script - script/api/analogs.cpp - script/api/buttons.cpp - script/api/capture.cpp - script/api/card.cpp - script/api/coin.cpp - script/api/control.cpp - script/api/drs.cpp - script/api/iidx.cpp - script/api/info.cpp - script/api/keypads.cpp - script/api/lcd.cpp - script/api/lights.cpp - script/api/memory.cpp - script/api/touch.cpp - script/instance.cpp - script/lib.cpp - script/manager.cpp - # stubs stubs/stubs.cpp # touch touch/touch.cpp + touch/touch_indicators.cpp touch/win7.cpp touch/win8.cpp @@ -539,6 +576,7 @@ set(SOURCE_FILES ${SOURCE_FILES} util/libutils.cpp util/fileutils.cpp util/resutils.cpp + util/unity_player.cpp util/utils.cpp util/memutils.cpp util/rc4.cpp @@ -546,17 +584,22 @@ set(SOURCE_FILES ${SOURCE_FILES} util/time.cpp util/cpuutils.cpp util/netutils.cpp + util/sysutils.cpp util/lz77.cpp + util/tapeled.cpp + util/execexe.cpp ) +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES}) + # spice.exe ########### set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES}) target_link_libraries(spicetools_spice - PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard - PRIVATE fmt-header-only discord-rpc imgui hash-library minhook openvr_api lua_static imm32 dwmapi) + PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp + PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) set_target_properties(spicetools_spice PROPERTIES PREFIX "") set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice") @@ -564,14 +607,33 @@ IF(NOT MSVC) set_target_properties(spicetools_spice PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32") endif() +# spice_laa.exe +########### + +set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) +add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES}) +target_link_libraries(spicetools_spice_laa + PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp + PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) +set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "") +set_target_properties(spicetools_spice_laa PROPERTIES OUTPUT_NAME "spice_laa") +target_compile_definitions(spicetools_spice_laa PRIVATE SPICE32_LARGE_ADDRESS_AWARE=1) + +IF(NOT MSVC) + set_target_properties(spicetools_spice_laa PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32 -Wl,--large-address-aware") +endif() + # spice64.exe ############# set(RESOURCE_FILES build/manifest.manifest build/manifest64.rc build/icon.rc cfg/Win32D.rc) add_executable(spicetools_spice64 ${SOURCE_FILES} ${RESOURCE_FILES}) + +# do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break target_link_libraries(spicetools_spice64 - PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard - PRIVATE fmt-header-only discord-rpc imgui hash-library minhook openvr_api64 lua_static imm32 dwmapi) + PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp mfuuid strmiids dxva2 + PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) + set_target_properties(spicetools_spice64 PROPERTIES PREFIX "") set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64") target_compile_definitions(spicetools_spice64 PRIVATE SPICE64=1) @@ -580,7 +642,6 @@ IF(NOT MSVC) set_target_properties(spicetools_spice64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64") endif() - # spicecfg.exe ############## @@ -588,8 +649,8 @@ set(SOURCE_FILES ${SOURCE_FILES} launcher/options.h launcher/options.cpp) set(RESOURCE_FILES cfg/manifest.manifest cfg/manifest.rc cfg/icon.rc cfg/Win32D.rc) add_executable(spicetools_cfg WIN32 ${SOURCE_FILES} ${RESOURCE_FILES}) target_link_libraries(spicetools_cfg - PUBLIC ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard - PRIVATE fmt-header-only discord-rpc imgui hash-library minhook openvr_api lua_static imm32 dwmapi) + PUBLIC ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp strmiids + PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) set_target_properties(spicetools_cfg PROPERTIES PREFIX "") set_target_properties(spicetools_cfg PROPERTIES OUTPUT_NAME "spicecfg") target_compile_definitions(spicetools_cfg PRIVATE SPICETOOLS_SPICECFG_STANDALONE=1) @@ -647,6 +708,36 @@ if(NOT MSVC) set_target_properties(spicetools_stubs_kld64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64") endif() +# nvcuda.dll +set(SOURCE_FILES stubs/nvcuda.cpp) +add_library(spicetools_stubs_nvcuda SHARED ${SOURCE_FILES} stubs/nvcuda.def) +set_target_properties(spicetools_stubs_nvcuda PROPERTIES PREFIX "") +set_target_properties(spicetools_stubs_nvcuda PROPERTIES OUTPUT_NAME "nvcuda") + +if(NOT MSVC) + set_target_properties(spicetools_stubs_nvcuda PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64") +endif() + +# nvcuvid.dll +set(SOURCE_FILES stubs/nvcuvid.cpp) +add_library(spicetools_stubs_nvcuvid SHARED ${SOURCE_FILES} stubs/nvcuvid.def) +set_target_properties(spicetools_stubs_nvcuvid PROPERTIES PREFIX "") +set_target_properties(spicetools_stubs_nvcuvid PROPERTIES OUTPUT_NAME "nvcuvid") + +if(NOT MSVC) + set_target_properties(spicetools_stubs_nvcuvid PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64") +endif() + +# nvEncodeAPI64.dll +set(SOURCE_FILES stubs/nvEncodeAPI64.cpp) +add_library(spicetools_stubs_nvEncodeAPI64 SHARED ${SOURCE_FILES} stubs/nvEncodeAPI64.def) +set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES PREFIX "") +set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES OUTPUT_NAME "nvEncodeAPI64") + +if(NOT MSVC) + set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64") +endif() + # output directories #################### @@ -656,14 +747,14 @@ set_target_properties(spicetools_cfg RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools") # output 32bit -set_target_properties(spicetools_spice spicetools_stubs_kbt spicetools_stubs_kld +set_target_properties(spicetools_spice spicetools_spice_laa spicetools_stubs_kbt spicetools_stubs_kld PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive32" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32") # output 64bit -set_target_properties(spicetools_spice64 spicetools_stubs_kbt64 spicetools_stubs_kld64 +set_target_properties(spicetools_spice64 spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvcuda spicetools_stubs_nvcuvid spicetools_stubs_nvEncodeAPI64 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive64" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/64" diff --git a/Dockerfile b/Dockerfile index 0300cf9..6472577 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM spicetools/deps WORKDIR /src -RUN chown user:user /src -USER user -COPY --chown=user:user . /src -CMD ./build_all.sh + +COPY --from=gitroot . /src/.git +COPY . /src/src/spice2x +WORKDIR /src/src/spice2x +ENTRYPOINT ["./build_all.sh"] diff --git a/README.md b/README.md index a555a36..e7c754d 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ If you need more examples, you can check the example code. "id": 1, "module": "card", "function": "insert", - "params": [0, "E004000000000000"] + "params": [0, "E004010000000000"] } ``` #### Response @@ -181,6 +181,12 @@ All of those three modules have equally named methods for you to call. - removes the override value from the objects specified by name - if no names were passed, all overrides will be removed +##### Additional API for lights +- read(name: string, ...) + - same as read(), but you can specify light names +- write_reset(name: str, ...) + - same as write_reset(), but it accepts a flat list of strings + #### Touch - read() - returns an array of state objects containing id, x and y @@ -246,6 +252,18 @@ which also means that your hex edits are applicable directly. - info() - returns information about the serial LCD controller some games use +#### Resize +- image_resize_enable(enable: bool) + - enables or disables image resize state +- image_resize_set_scene(scene: int) + - sets the active scene for image resize state; set to 0 to disable resize + +## Native wrapper libraries +Spicetools provides wrapper libraries in: Arduino, C++, Dart, and Python. +Python is the only one that is fully spec compliant. +Other libraries may be missing features and contain bugs; please feel free to +contribute code to fill the gaps if you work on a project using these libraries. + ## License Unless otherwise noted, all files are licensed under the GPLv3. See the LICENSE file for the full license text. diff --git a/acio/acio.cpp b/acio/acio.cpp index 4fcd566..2ae28f4 100644 --- a/acio/acio.cpp +++ b/acio/acio.cpp @@ -70,6 +70,9 @@ void acio::attach() { libraryhook_hook_library("libacioex.dll", acio::DLL_INSTANCE); libraryhook_hook_library("libacio_ex.dll", acio::DLL_INSTANCE); libraryhook_hook_library("libacio_old.dll", acio::DLL_INSTANCE); + // libacioEx.dll for Road Fighters 3D + // needed as comparisons in LoadLibrary hooks are case-sensitive + libraryhook_hook_library("libacioEx.dll", acio::DLL_INSTANCE); libraryhook_enable(avs::game::DLL_INSTANCE); // get hook mode diff --git a/acio/bi2a/bi2a.cpp b/acio/bi2a/bi2a.cpp index 1198473..68b2235 100644 --- a/acio/bi2a/bi2a.cpp +++ b/acio/bi2a/bi2a.cpp @@ -2,6 +2,7 @@ #include "avs/game.h" #include "games/ddr/io.h" +#include "games/ddr/ddr.h" #include "games/sdvx/sdvx.h" #include "games/sdvx/io.h" #include "games/drs/io.h" @@ -9,6 +10,7 @@ #include "misc/eamuse.h" #include "util/logging.h" #include "util/utils.h" +#include "util/tapeled.h" using namespace GameAPI; @@ -399,6 +401,148 @@ static long __cdecl ac_io_bi2a_control_led_bright(size_t index, uint8_t brightne if (light.light2 >= 0) { Lights::writeLight(RI_MGR, lights[light.light2], brightness / light.max); } + + // DANCERUSH + } else if (avs::game::is_model("REC")) { + + /* + * Control R G B + * ============================== + * CARD UNIT 13 14 15 + * TITLE PANEL 28 29 30 + * MONITOR SIDE LEFT (tape LED - see ac_io_bi2a_control_tapeled_bright) + * MONITOR SIDE RIGHT (tape LED - see ac_io_bi2a_control_tapeled_bright) + * + * Values go up to 127. + * + * Control Index + * ================== + * 1P LEFT 11 + * 1P RIGHT 12 + * 1P UP 9 + * 1P DOWN 10 + * 1P START 8 + * 2P LEFT 19 + * 2P RIGHT 20 + * 2P UP 17 + * 2P DOWN 18 + * 2P START 16 + * + * Values go up to 127. + */ + + static const struct { + int light; + float max; + } mapping[] = { + { -1, 0 }, // 0 + { -1, 0 }, // 1 + { -1, 0 }, // 2 + { -1, 0 }, // 3 + { -1, 0 }, // 4 + { -1, 0 }, // 5 + { -1, 0 }, // 6 + { -1, 0 }, // 7 + { games::drs::Lights::P1_START, 127 }, // 8 + { games::drs::Lights::P1_MENU_UP, 127 }, // 9 + { games::drs::Lights::P1_MENU_DOWN, 127 }, // 10 + { games::drs::Lights::P1_MENU_LEFT, 127 }, // 11 + { games::drs::Lights::P1_MENU_RIGHT, 127 }, // 12 + { games::drs::Lights::CARD_READER_R, 127 }, // 13 + { games::drs::Lights::CARD_READER_G, 127 }, // 14 + { games::drs::Lights::CARD_READER_B, 127 }, // 15 + { games::drs::Lights::P2_START, 127 }, // 16 + { games::drs::Lights::P2_MENU_UP, 127 }, // 17 + { games::drs::Lights::P2_MENU_DOWN, 127 }, // 18 + { games::drs::Lights::P2_MENU_LEFT, 127 }, // 19 + { games::drs::Lights::P2_MENU_RIGHT, 127 }, // 20 + { -1, 0 }, // 21 + { -1, 0 }, // 22 + { -1, 0 }, // 23 + { -1, 0 }, // 24 + { -1, 0 }, // 25 + { -1, 0 }, // 26 + { -1, 0 }, // 27 + { games::drs::Lights::TITLE_PANEL_R, 127 }, // 28 + { games::drs::Lights::TITLE_PANEL_G, 127 }, // 29 + { games::drs::Lights::TITLE_PANEL_B, 127 }, // 30 + }; + + // ignore index out of range + if (index > std::size(mapping)) { + return true; + } + + // get lights + auto &lights = games::drs::get_lights(); + + // get light from mapping + auto light = mapping[index]; + + // write lights + if (light.light >= 0) { + Lights::writeLight(RI_MGR, lights[light.light], brightness / light.max); + } else { + log_warning("drs", "light unset {} {}", index, (int) brightness); + } + + // DanceDanceRevolution + } else if (avs::game::is_model("MDX")) { + + static const struct { + int light; + float max; + } mapping[] = { + { -1, 0 }, // 0 + { -1, 0 }, // 1 + { -1, 0 }, // 2 + { -1, 0 }, // 3 + { -1, 0 }, // 4 + { -1, 0 }, // 5 + { -1, 0 }, // 6 + { -1, 0 }, // 7 + { games::ddr::Lights::GOLD_P1_MENU_START, 127 }, // 8 + { games::ddr::Lights::GOLD_P1_MENU_UP, 127 }, // 9 + { games::ddr::Lights::GOLD_P1_MENU_DOWN, 127 }, // 10 + { games::ddr::Lights::GOLD_P1_MENU_LEFT, 127 }, // 11 + { games::ddr::Lights::GOLD_P1_MENU_RIGHT, 127 }, // 12 + { games::ddr::Lights::GOLD_P1_CARD_UNIT_R, 127 }, // 13 + { games::ddr::Lights::GOLD_P1_CARD_UNIT_G, 127 }, // 14 + { games::ddr::Lights::GOLD_P1_CARD_UNIT_B, 127 }, // 15 + { games::ddr::Lights::GOLD_P2_MENU_START, 127 }, // 16 + { games::ddr::Lights::GOLD_P2_MENU_UP, 127 }, // 17 + { games::ddr::Lights::GOLD_P2_MENU_DOWN, 127 }, // 18 + { games::ddr::Lights::GOLD_P2_MENU_LEFT, 127 }, // 19 + { games::ddr::Lights::GOLD_P2_MENU_RIGHT, 127 }, // 20 + { games::ddr::Lights::GOLD_P2_CARD_UNIT_R, 0 }, // 21 + { games::ddr::Lights::GOLD_P2_CARD_UNIT_G, 0 }, // 22 + { games::ddr::Lights::GOLD_P2_CARD_UNIT_B, 0 }, // 23 + { -1, 0 }, // 24 + { -1, 0 }, // 25 + { -1, 0 }, // 26 + { -1, 0 }, // 27 + { games::ddr::Lights::GOLD_TITLE_PANEL_LEFT, 0 }, // 28 + { games::ddr::Lights::GOLD_TITLE_PANEL_CENTER, 0 }, // 29 + { games::ddr::Lights::GOLD_TITLE_PANEL_RIGHT, 0 }, // 30 + { games::ddr::Lights::GOLD_P1_WOOFER_CORNER, 0 }, // 31 + { games::ddr::Lights::GOLD_P2_WOOFER_CORNER, 0 } // 32 + }; + + // ignore index out of range + if (index > std::size(mapping)) { + return true; + } + + // get lights + auto &lights = games::ddr::get_lights(); + + // get light from mapping + auto light = mapping[index]; + + // write lights + if (light.light >= 0) { + Lights::writeLight(RI_MGR, lights[light.light], brightness / light.max); + } } // return success @@ -443,7 +587,7 @@ static bool __cdecl ac_io_bi2a_tapeled_init_is_finished() { 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) { + if (x_sz != DRS_TAPELED_COLS || y_sz != DRS_TAPELED_ROWS) { log_fatal("drs", "DRS tapeled wrong dimensions"); } @@ -458,9 +602,151 @@ static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_s return true; } -// TODO: this controls the upright RGB bars on the sides +// TODO: DRS tape lights 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) { + + if (!tapeledutils::is_enabled()) { + return true; + } + + if (avs::game::is_model("MDX")) { + + /* + * r, g, b values range from [0-255] + * bank always seems to be [0] + * + * [off1.off2] [LEDs] [tape name] + * 0.0 25 P1 Foot Up (0.0 to 0.24, inclusive) + * 0.25 25 P1 Foot Right + * 1.0 25 P1 Foot Left + * 1.25 25 P1 Foot Down + * + * 2.0 25 P2 Foot Up + * 2.25 25 P2 Foot Right + * 3.0 25 P2 Foot Left + * 3.25 25 P2 Foot Down + * + * 5.0 50 Top Panel + * 6.0 50 Monitor side left + * 7.0 50 Monitor side right + */ + + // In order to set the data that can be output via Spice API, we first + // need to figure out which device in our buffers this data belongs to + int device = -1; + if (off1 == 0) { + if (off2 < 25) device = 0; // P1 Foot Up + else device = 1; // P1 Foot Right + } else if (off1 == 1) { + if (off2 < 25) device = 2; // P1 Foot Left + else device = 3; // P1 Foot Down + } else if (off1 == 2) { + if (off2 < 25) device = 4; // P2 Foot Up + else device = 5; // P2 Foot Right + } else if (off1 == 3) { + if (off2 < 25) device = 6; // P2 Foot Left + else device = 7; // P2 Foot Down + } else if (off1 >= 5 && off1 <= 7) { + device = off1 + 3; // Top Panel / Monitor Side Left / Monitor Side Right + } + + if (device != -1) { + // We subtract 25 from off2 to get the device's LED index, if it's for one of the + // arrow panels that is on the latter half of the logical strip + size_t subtractor = 0; + if (off1 <= 3 && off2 >= 25) { + subtractor = 25; + } + size_t led_index = off2 - subtractor; + + games::ddr::DDR_TAPELEDS[device][led_index][0] = r; + games::ddr::DDR_TAPELEDS[device][led_index][1] = g; + games::ddr::DDR_TAPELEDS[device][led_index][2] = b; + } + + static struct TapeLedMapping { + bool split; // true == 50 LEDs for one light, false == 25 for two lights + uint8_t index_r0, index_g0, index_b0; + uint8_t index_r1, index_g1, index_b1; + size_t index_for_avg0 = UINT8_MAX; + size_t index_for_avg1 = UINT8_MAX; + + TapeLedMapping( + uint8_t index_r0, uint8_t index_g0, uint8_t index_b0, + uint8_t index_r1, uint8_t index_g1, uint8_t index_b1) + : index_r0(index_r0), index_g0(index_g0), index_b0(index_b0), + index_r1(index_r1), index_g1(index_g1), index_b1(index_b1) { + + split = (index_r1 != UINT8_MAX); + if (split) { + index_for_avg0 = tapeledutils::get_led_index_using_avg_algo(25); + index_for_avg1 = index_for_avg0 + 25; + } else { + index_for_avg0 = tapeledutils::get_led_index_using_avg_algo(50); + index_for_avg1 = -1; + } + } + + } mapping[] = { + { + games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_B, + games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_B + }, + { + games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_B, + games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_B + }, + { + games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_B, + games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_B + }, + { + games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_B, + games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_B + }, + { + games::ddr::Lights::GOLD_TOP_PANEL_AVG_R, games::ddr::Lights::GOLD_TOP_PANEL_AVG_G, games::ddr::Lights::GOLD_TOP_PANEL_AVG_B, + UINT8_MAX, UINT8_MAX, UINT8_MAX + }, + { + UINT8_MAX, UINT8_MAX, UINT8_MAX, + UINT8_MAX, UINT8_MAX, UINT8_MAX + }, + { + games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_R, games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_G, games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_B, + UINT8_MAX, UINT8_MAX, UINT8_MAX + }, + { + games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_R, games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_G, games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_B, + UINT8_MAX, UINT8_MAX, UINT8_MAX + }, + }; + + if (off1 < std::size(mapping)) { + auto &map = mapping[off1]; + + size_t off2_match = -1; + if (!map.split || off2 < 25) { + off2_match = map.index_for_avg0; + } else { + off2_match = map.index_for_avg1; + } + if (off2_match == off2 && map.index_r0 != UINT8_MAX) { + auto &lights = games::ddr::get_lights(); + if (!map.split || off2 < 25) { + Lights::writeLight(RI_MGR, lights[map.index_r0], r / 255.f); + Lights::writeLight(RI_MGR, lights[map.index_g0], g / 255.f); + Lights::writeLight(RI_MGR, lights[map.index_b0], b / 255.f); + } else { + Lights::writeLight(RI_MGR, lights[map.index_r1], r / 255.f); + Lights::writeLight(RI_MGR, lights[map.index_g1], g / 255.f); + Lights::writeLight(RI_MGR, lights[map.index_b1], b / 255.f); + } + } + } + } + return true; } diff --git a/acio/bmpu/bmpu.cpp b/acio/bmpu/bmpu.cpp index c3e1f16..e8ccb5f 100644 --- a/acio/bmpu/bmpu.cpp +++ b/acio/bmpu/bmpu.cpp @@ -33,6 +33,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_off() { if (avs::game::is_model("KDM")) { auto &lights = games::dea::get_lights(); Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f); + + // MUSECA + } else if (avs::game::is_model("PIX")) { + auto &lights = games::museca::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 0.f); } return 1; @@ -44,6 +49,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_on() { if (avs::game::is_model("KDM")) { auto &lights = games::dea::get_lights(); Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f); + + // MUSECA + } else if (avs::game::is_model("PIX")) { + auto &lights = games::museca::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 1.f); } return 1; @@ -55,6 +65,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_off() { if (avs::game::is_model("KDM")) { auto &lights = games::dea::get_lights(); Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f); + + // MUSECA + } else if (avs::game::is_model("PIX")) { + auto &lights = games::museca::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 0.f); } return 1; @@ -66,6 +81,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_on() { if (avs::game::is_model("KDM")) { auto &lights = games::dea::get_lights(); Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f); + + // MUSECA + } else if (avs::game::is_model("PIX")) { + auto &lights = games::museca::get_lights(); + Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 1.f); } return 1; diff --git a/acio/icca/icca.cpp b/acio/icca/icca.cpp index 6477031..82d3b4f 100644 --- a/acio/icca/icca.cpp +++ b/acio/icca/icca.cpp @@ -25,6 +25,13 @@ struct ICCA_STATUS { uint32_t key_edge; uint32_t key_level; }; +struct ICCA_STATUS_LA9 { + uint8_t status_code; + uint8_t card_in; + uint8_t uid[8]; + uint8_t error; + uint8_t uid2[8]; +}; static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes"); enum ICCA_WORKFLOW { @@ -52,6 +59,7 @@ struct ICCA_UNIT { char key_serial = 0; bool uid_skip = false; bool initialized = false; + int felica_retries = 0; }; static ICCA_UNIT ICCA_UNITS[2] {}; static bool IS_LAST_CARD_FELICA = false; @@ -88,14 +96,25 @@ static inline void update_card(int unit_id) { // eamio keypress int index = unit_id > 0 && icca_get_active_count() > 1 ? 1 : 0; bool kb_insert_press = (eamuse_get_keypad_state(index) & (1 << EAM_IO_INSERT)) > 0; + static bool kb_insert_press_old[2] = {false, false}; // get unit ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; + const bool card_presented = eamuse_card_insert_consume(icca_get_active_count(), unit_id); + const bool key_pressed = (kb_insert_press && !kb_insert_press_old[unit_id]); + + // beatstream and nostalgia have logic that requires ac_io_icca_get_uid_felica to return the + // exact same card number multiple times in a row in order for the card number to be read... + // for whatever reason setting this to 3-4 doesn't work the very first time the game boots up + // so we use 10 just to be safe + const bool need_felica_retries = avs::game::is_model({"NBT", "PAN"}); + if (need_felica_retries && (card_presented || key_pressed)) { + unit->felica_retries = 10; + } + // check for card insert - static bool kb_insert_press_old[2] = {false, false}; - if (eamuse_card_insert_consume(icca_get_active_count(), unit_id) || - (kb_insert_press && !kb_insert_press_old[unit_id])) { + if (card_presented || key_pressed || (0 < unit->felica_retries)) { if (!unit->card_cmd_pressed) { unit->card_cmd_pressed = true; if (unit->state == GET_USERID || unit->state == CLOSE_EJECT || unit->state == STEP) { @@ -288,17 +307,29 @@ static char __cdecl ac_io_icca_get_status(void *a1, void *a2) { // funny workaround if (acio::ICCA_COMPAT_ACTIVE) { + if (avs::game::is_model("LA9")) { + auto p = (ICCA_STATUS*) status; - // the struct is different (28 bytes instead of 24) but nobody ain't got time for that - auto p = (ICCA_STATUS*) status; - p->error = p->key_level << 16; - p->front_sensor = p->uid[0]; - p->rear_sensor = p->uid[1]; - for (size_t i = 2; i < sizeof(p->uid); i++) { - p->uid[i - 2] = p->uid[i]; + ICCA_STATUS_LA9 p_la9; + p_la9.status_code = unit->state; + p_la9.card_in = unit->card_in; + memcpy(p_la9.uid, p->uid, sizeof(p_la9.uid)); + p_la9.error = p->error; + memcpy(p_la9.uid2, p->uid, sizeof(p_la9.uid)); + + memcpy(status, &p_la9, sizeof(ICCA_STATUS_LA9)); + } else { + // the struct is different (28 bytes instead of 24) but nobody ain't got time for that + auto p = (ICCA_STATUS*) status; + p->error = p->key_level << 16; + p->front_sensor = p->uid[0]; + p->rear_sensor = p->uid[1]; + for (size_t i = 2; i < sizeof(p->uid); i++) { + p->uid[i - 2] = p->uid[i]; + } + p->uid[sizeof(p->uid) - 2] = 0; + p->uid[sizeof(p->uid) - 1] = 0; } - p->uid[sizeof(p->uid) - 2] = 0; - p->uid[sizeof(p->uid) - 1] = 0; } return 1; @@ -330,6 +361,10 @@ static char __cdecl ac_io_icca_get_uid_felica(int unit_id, char *card) { card[8] = (char) (felica ? 1 : 0); IS_LAST_CARD_FELICA = felica; + if (0 < unit->felica_retries) { + unit->felica_retries--; + } + // check for error return unit->state != ERR_GETUID; } diff --git a/acio/mdxf/mdxf.cpp b/acio/mdxf/mdxf.cpp index 6f57674..8fe81d2 100644 --- a/acio/mdxf/mdxf.cpp +++ b/acio/mdxf/mdxf.cpp @@ -16,13 +16,26 @@ static uint8_t COUNTER = 0; // buffers #pragma pack(push, 1) static struct { - uint8_t STATUS_BUFFER_17[7][STATUS_BUFFER_SIZE] {}; - uint8_t STATUS_BUFFER_18[7][STATUS_BUFFER_SIZE] {}; + uint8_t STATUS_BUFFER_P1[7][STATUS_BUFFER_SIZE] {}; + uint8_t STATUS_BUFFER_P2[7][STATUS_BUFFER_SIZE] {}; } BUFFERS {}; #pragma pack(pop) static bool STATUS_BUFFER_FREEZE = false; +typedef uint64_t (__cdecl *ARK_GET_TICK_TIME64_T)(); + +static uint64_t arkGetTickTime64() { + static ARK_GET_TICK_TIME64_T getTickTime64 = + (ARK_GET_TICK_TIME64_T)GetProcAddress(avs::game::DLL_INSTANCE, "arkGetTickTime64"); + if (getTickTime64 == nullptr) { + // this works on 32-bit versions of avs, but not on 64. + // it's better than nothing though. + return timeGetTime(); + } + return getTickTime64(); +} + /* * Implementations */ @@ -33,13 +46,13 @@ static bool __cdecl ac_io_mdxf_get_control_status_buffer(int node, void *buffer, if (avs::game::is_model("MDX")) { // get buffer index - auto i = (COUNTER + a3) % std::size(BUFFERS.STATUS_BUFFER_17); + auto i = (COUNTER + a3) % std::size(BUFFERS.STATUS_BUFFER_P1); // copy buffer - if (node == 17) { - memcpy(buffer, BUFFERS.STATUS_BUFFER_17[i], STATUS_BUFFER_SIZE); - } else if (node == 18) { - memcpy(buffer, BUFFERS.STATUS_BUFFER_18[i], STATUS_BUFFER_SIZE); + if (node == 17 || node == 25) { + memcpy(buffer, BUFFERS.STATUS_BUFFER_P1[i], STATUS_BUFFER_SIZE); + } else if (node == 18 || node == 26) { + memcpy(buffer, BUFFERS.STATUS_BUFFER_P2[i], STATUS_BUFFER_SIZE); } else { // fill with zeros on unknown node @@ -52,16 +65,49 @@ static bool __cdecl ac_io_mdxf_get_control_status_buffer(int node, void *buffer, return true; } -static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2, uint8_t a3) { - // TODO(felix): DDR BIO2 lights +static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2, uint8_t value) { + if (avs::game::is_model("MDX")) { + static const struct { + int a2[4]; + } mapping[] = { + { + // a1 == 17 + { + games::ddr::Lights::GOLD_P1_STAGE_UP_RIGHT, + games::ddr::Lights::GOLD_P1_STAGE_DOWN_LEFT, + games::ddr::Lights::GOLD_P1_STAGE_UP_LEFT, + games::ddr::Lights::GOLD_P1_STAGE_DOWN_RIGHT + } + }, + { + // a1 == 18 + { + games::ddr::Lights::GOLD_P2_STAGE_UP_RIGHT, + games::ddr::Lights::GOLD_P2_STAGE_DOWN_LEFT, + games::ddr::Lights::GOLD_P2_STAGE_UP_LEFT, + games::ddr::Lights::GOLD_P2_STAGE_DOWN_RIGHT + } + } + }; + if ((a1 == 17 || a1 == 18) && (a2 < 4)) { + // get light from mapping + const auto light = mapping[a1 - 17].a2[a2]; + // get lights + auto &lights = games::ddr::get_lights(); + + // write lights + GameAPI::Lights::writeLight(RI_MGR, lights[light], value / 128.f); + } + } + return true; } static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) { // increase counter - COUNTER = (COUNTER + 1) % std::size(BUFFERS.STATUS_BUFFER_17); + COUNTER = (COUNTER + 1) % std::size(BUFFERS.STATUS_BUFFER_P1); // check freeze if (STATUS_BUFFER_FREEZE) { @@ -72,10 +118,12 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) { uint8_t *buffer = nullptr; switch (node) { case 17: - buffer = BUFFERS.STATUS_BUFFER_17[COUNTER]; + case 25: + buffer = BUFFERS.STATUS_BUFFER_P1[COUNTER]; break; case 18: - buffer = BUFFERS.STATUS_BUFFER_18[COUNTER]; + case 26: + buffer = BUFFERS.STATUS_BUFFER_P2[COUNTER]; break; default: @@ -92,13 +140,13 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) { // FOOT UP = bit 36-39 = byte 4, bit 4-7 // FOOT RIGHT = bit 40-43 = byte 5, bit 0-3 // FOOT LEFT = bit 44-47 = byte 5, bit 4-7 - static const size_t buttons_17[] = { + static const size_t buttons_p1[] = { games::ddr::Buttons::P1_PANEL_UP, games::ddr::Buttons::P1_PANEL_DOWN, games::ddr::Buttons::P1_PANEL_LEFT, games::ddr::Buttons::P1_PANEL_RIGHT, }; - static const size_t buttons_18[] = { + static const size_t buttons_p2[] = { games::ddr::Buttons::P2_PANEL_UP, games::ddr::Buttons::P2_PANEL_DOWN, games::ddr::Buttons::P2_PANEL_LEFT, @@ -109,13 +157,17 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) { const size_t *button_map = nullptr; switch (node) { case 17: - button_map = &buttons_17[0]; + case 25: + button_map = &buttons_p1[0]; break; case 18: - button_map = &buttons_18[0]; + case 26: + button_map = &buttons_p2[0]; break; } + *(uint64_t*)&buffer[0x18] = arkGetTickTime64(); + // get buttons auto &buttons = games::ddr::get_buttons(); diff --git a/acio/module.h b/acio/module.h index da07c09..2d35175 100644 --- a/acio/module.h +++ b/acio/module.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include diff --git a/acio/panb/panb.cpp b/acio/panb/panb.cpp index b499660..188a17f 100644 --- a/acio/panb/panb.cpp +++ b/acio/panb/panb.cpp @@ -6,6 +6,11 @@ #include "util/logging.h" #include "avs/game.h" +// std::min +#ifdef min +#undef min +#endif + using namespace GameAPI; // static stuff @@ -79,6 +84,32 @@ static bool __cdecl ac_io_panb_start_auto_input() { return true; } +static uint8_t panb_get_button_velocity(Button button, Button button_soft, Button button_medium, Button button_hard) { + const auto velocity = Buttons::getVelocity(RI_MGR, button); + const auto velocity_soft = Buttons::getVelocity(RI_MGR, button_soft); + const auto velocity_medium = Buttons::getVelocity(RI_MGR, button_medium); + const auto velocity_hard = Buttons::getVelocity(RI_MGR, button_hard); + + // note that the digital values have been obtained via trial-and-error in recital mode + // based on Op3: + // * soft presses glow blue, should trigger Elegant in blue sections + // * hard presses glow red/orange, should trigger Elegant in yellow sections + // * default (medium) presses glow green, triggers Elegant in both blue and yellow sections + + // digital-only values + if (velocity_hard > 0.f) { + // do NOT use 15 here!! 14 properly registers as a hard press, but 15 does not + return 14; + } else if (velocity_medium > 0.f) { + return 11; + } else if (velocity_soft > 0.f) { + return 1; + } + + // digital or midi (velocity-sensitive) values + return std::min((uint8_t)(velocity * 15.999f), (uint8_t)14); +} + static bool __cdecl ac_io_panb_update_control_status_buffer() { // check freeze @@ -107,6 +138,7 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() { auto &analogs = games::nost::get_analogs(); // mappings + // "normal" buttons - these are velocity sensitive (digital or MIDI) static const size_t button_mapping[] = { games::nost::Buttons::Key1, games::nost::Buttons::Key2, games::nost::Buttons::Key3, games::nost::Buttons::Key4, @@ -123,6 +155,60 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() { games::nost::Buttons::Key25, games::nost::Buttons::Key26, games::nost::Buttons::Key27, games::nost::Buttons::Key28, }; + + // soft (digital) button - always registers as soft press + static const size_t soft_button_mapping[] = { + games::nost::Buttons::Key1Soft, games::nost::Buttons::Key2Soft, + games::nost::Buttons::Key3Soft, games::nost::Buttons::Key4Soft, + games::nost::Buttons::Key5Soft, games::nost::Buttons::Key6Soft, + games::nost::Buttons::Key7Soft, games::nost::Buttons::Key8Soft, + games::nost::Buttons::Key9Soft, games::nost::Buttons::Key10Soft, + games::nost::Buttons::Key11Soft, games::nost::Buttons::Key12Soft, + games::nost::Buttons::Key13Soft, games::nost::Buttons::Key14Soft, + games::nost::Buttons::Key15Soft, games::nost::Buttons::Key16Soft, + games::nost::Buttons::Key17Soft, games::nost::Buttons::Key18Soft, + games::nost::Buttons::Key19Soft, games::nost::Buttons::Key20Soft, + games::nost::Buttons::Key21Soft, games::nost::Buttons::Key22Soft, + games::nost::Buttons::Key23Soft, games::nost::Buttons::Key24Soft, + games::nost::Buttons::Key25Soft, games::nost::Buttons::Key26Soft, + games::nost::Buttons::Key27Soft, games::nost::Buttons::Key28Soft, + }; + + // medium (digital) button - always registers as medium press + static const size_t medium_button_mapping[] = { + games::nost::Buttons::Key1Medium, games::nost::Buttons::Key2Medium, + games::nost::Buttons::Key3Medium, games::nost::Buttons::Key4Medium, + games::nost::Buttons::Key5Medium, games::nost::Buttons::Key6Medium, + games::nost::Buttons::Key7Medium, games::nost::Buttons::Key8Medium, + games::nost::Buttons::Key9Medium, games::nost::Buttons::Key10Medium, + games::nost::Buttons::Key11Medium, games::nost::Buttons::Key12Medium, + games::nost::Buttons::Key13Medium, games::nost::Buttons::Key14Medium, + games::nost::Buttons::Key15Medium, games::nost::Buttons::Key16Medium, + games::nost::Buttons::Key17Medium, games::nost::Buttons::Key18Medium, + games::nost::Buttons::Key19Medium, games::nost::Buttons::Key20Medium, + games::nost::Buttons::Key21Medium, games::nost::Buttons::Key22Medium, + games::nost::Buttons::Key23Medium, games::nost::Buttons::Key24Medium, + games::nost::Buttons::Key25Medium, games::nost::Buttons::Key26Medium, + games::nost::Buttons::Key27Medium, games::nost::Buttons::Key28Medium, + }; + + // hard (digital) button - always registers as hard press + static const size_t hard_button_mapping[] = { + games::nost::Buttons::Key1Hard, games::nost::Buttons::Key2Hard, + games::nost::Buttons::Key3Hard, games::nost::Buttons::Key4Hard, + games::nost::Buttons::Key5Hard, games::nost::Buttons::Key6Hard, + games::nost::Buttons::Key7Hard, games::nost::Buttons::Key8Hard, + games::nost::Buttons::Key9Hard, games::nost::Buttons::Key10Hard, + games::nost::Buttons::Key11Hard, games::nost::Buttons::Key12Hard, + games::nost::Buttons::Key13Hard, games::nost::Buttons::Key14Hard, + games::nost::Buttons::Key15Hard, games::nost::Buttons::Key16Hard, + games::nost::Buttons::Key17Hard, games::nost::Buttons::Key18Hard, + games::nost::Buttons::Key19Hard, games::nost::Buttons::Key20Hard, + games::nost::Buttons::Key21Hard, games::nost::Buttons::Key22Hard, + games::nost::Buttons::Key23Hard, games::nost::Buttons::Key24Hard, + games::nost::Buttons::Key25Hard, games::nost::Buttons::Key26Hard, + games::nost::Buttons::Key27Hard, games::nost::Buttons::Key28Hard, + }; static const size_t analog_mapping[] = { games::nost::Analogs::Key1, games::nost::Analogs::Key2, games::nost::Analogs::Key3, games::nost::Analogs::Key4, @@ -148,23 +234,38 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() { uint8_t state1 = 0; // check analogs + // + // while 15 is technically allowed by the I/O board & is recognized correctly in test + // menu, when you play recital mode, 15 fails to register Elegant in yellow sections. + // therefore, cap the value at 14. tested with Nostroller. auto &analog0 = analogs.at(analog_mapping[key_pair * 2 + 0]); auto &analog1 = analogs.at(analog_mapping[key_pair * 2 + 1]); if (analog0.isSet()) { - state0 = (uint8_t) (Analogs::getState(RI_MGR, analog0) * 15.999f); + state0 = std::min((uint8_t)(Analogs::getState(RI_MGR, analog0) * 15.999f), (uint8_t)14); } if (analog1.isSet()) { - state1 = (uint8_t) (Analogs::getState(RI_MGR, analog1) * 15.999f); + state1 = std::min((uint8_t)(Analogs::getState(RI_MGR, analog1) * 15.999f), (uint8_t)14); } - // check buttons - auto velocity0 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 0])); - auto velocity1 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 1])); - if (velocity0 > 0.f) { - state0 = (uint8_t) (velocity0 * 15.999f); + // check digital buttons + const auto button0 = panb_get_button_velocity( + buttons.at(button_mapping[key_pair * 2 + 0]), + buttons.at(soft_button_mapping[key_pair * 2 + 0]), + buttons.at(medium_button_mapping[key_pair * 2 + 0]), + buttons.at(hard_button_mapping[key_pair * 2 + 0]) + ); + if (button0 > 0) { + state0 = button0; } - if (velocity1 > 0.f) { - state1 = (uint8_t) (velocity1 * 15.999f); + + const auto button1 = panb_get_button_velocity( + buttons.at(button_mapping[key_pair * 2 + 1]), + buttons.at(soft_button_mapping[key_pair * 2 + 1]), + buttons.at(medium_button_mapping[key_pair * 2 + 1]), + buttons.at(hard_button_mapping[key_pair * 2 + 1]) + ); + if (button1 > 0) { + state1 = button1; } // build value diff --git a/acio2emu/firmware/bi2x.cpp b/acio2emu/firmware/bi2x.cpp index 123751c..bd287f6 100644 --- a/acio2emu/firmware/bi2x.cpp +++ b/acio2emu/firmware/bi2x.cpp @@ -44,7 +44,7 @@ namespace acio2emu::firmware { break; case 785: { // write output - auto count = write_output(std::span{cur.base(), static_cast(in.payload.end() - cur)}); + auto count = write_output(std::span{&*cur, static_cast(in.payload.end() - cur)}); if (count < 0) { return false; } diff --git a/acioemu/acioemu.cpp b/acioemu/acioemu.cpp index be452ef..658cbc3 100644 --- a/acioemu/acioemu.cpp +++ b/acioemu/acioemu.cpp @@ -108,6 +108,10 @@ std::optional ACIOEmu::read() { return this->response_buffer->get(); } +size_t ACIOEmu::bytes_available() { + return this->response_buffer->size(); +} + void ACIOEmu::msg_parse() { #ifdef ACIOEMU_LOG diff --git a/acioemu/acioemu.h b/acioemu/acioemu.h index b9f597c..57328e0 100644 --- a/acioemu/acioemu.h +++ b/acioemu/acioemu.h @@ -28,5 +28,6 @@ namespace acioemu { void write(uint8_t byte); std::optional read(); + size_t bytes_available(); }; } diff --git a/acioemu/handle.cpp b/acioemu/handle.cpp index c8d8841..4ebe3ea 100644 --- a/acioemu/handle.cpp +++ b/acioemu/handle.cpp @@ -4,8 +4,9 @@ #include "rawinput/rawinput.h" #include "util/utils.h" -acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort) { +acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort, uint8_t iccaNodeCount) { this->com_port = lpCOMPort; + this->icca_node_count = iccaNodeCount; } bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) { @@ -16,7 +17,7 @@ bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) { log_info("acioemu", "Opened {} (ACIO)", ws2s(com_port)); // ACIO device - acio_emu.add_device(new acioemu::ICCADevice(false, true, 2)); + acio_emu.add_device(new acioemu::ICCADevice(false, true, icca_node_count)); return true; } @@ -62,6 +63,10 @@ int acioemu::ACIOHandle::device_io( return -1; } +size_t acioemu::ACIOHandle::bytes_available() { + return acio_emu.bytes_available(); +} + bool acioemu::ACIOHandle::close() { log_info("acioemu", "Closed {} (ACIO)", ws2s(com_port)); diff --git a/acioemu/handle.h b/acioemu/handle.h index a1fd9cc..5caa3d7 100644 --- a/acioemu/handle.h +++ b/acioemu/handle.h @@ -9,10 +9,12 @@ namespace acioemu { private: LPCWSTR com_port; + uint8_t icca_node_count; + acioemu::ACIOEmu acio_emu; public: - ACIOHandle(LPCWSTR lpCOMPort); + ACIOHandle(LPCWSTR lpCOMPort, uint8_t iccaNodeCount = 2); bool open(LPCWSTR lpFileName) override; @@ -23,6 +25,8 @@ namespace acioemu { int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize) override; + size_t bytes_available() override; + bool close() override; }; } diff --git a/acioemu/icca.cpp b/acioemu/icca.cpp index 2fbc36d..2733aa7 100644 --- a/acioemu/icca.cpp +++ b/acioemu/icca.cpp @@ -8,6 +8,10 @@ using namespace acioemu; +namespace acioemu { + bool ICCA_DEVICE_HACK = false; +} + ICCADevice::ICCADevice(bool flip_order, bool keypad_thread, uint8_t node_count) { // init defaults @@ -98,11 +102,13 @@ bool ICCADevice::parse_msg(MessageData *msg_in, // send version data auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE); if ( - avs::game::is_model({"LDJ", "TBS"}) || + avs::game::is_model({"LDJ", "TBS", "UJK"}) || // SDVX Valkyrie cabinet mode (avs::game::is_model("KFC") && (avs::game::SPEC[0] == 'G' || avs::game::SPEC[0] == 'H')) ) { this->set_version(msg, 0x3, 0, 1, 7, 0, "ICCA"); + } else if (avs::game::is_model({"VFG"})) { + this->set_version(msg, 0x3, 0, 1, 7, 0, "ICCB"); } else { this->set_version(msg, 0x3, 0, 1, 6, 0, "ICCA"); } @@ -327,6 +333,9 @@ bool ICCADevice::parse_msg(MessageData *msg_in, } case ACIO_CMD_STARTUP: case ACIO_CMD_CLEAR: + case 0x30: // GetBoardProductNumber + case 0x31: // GetMicomInfo + case 0x3A: // ??? case 0x0116: // ??? case 0x0120: // ??? case 0xFF: // BROADCAST @@ -385,19 +394,48 @@ void ICCADevice::update_card(int unit) { static int KEYPAD_EAMUSE_MAPPING[] = { 0, 1, 5, 9, 2, 6, 10, 3, 7, 11, 8, 4 }; + +// map for KEYPAD_KEY_CODES: +// 7 8 9 | 800 8000 8 +// 4 5 6 | 400 4000 4 +// 1 2 3 | 200 2000 2 +// 0 00 . | 100 1000 1 static int KEYPAD_KEY_CODES[]{ - 0x100, - 0x200, - 0x2000, - 2, - 0x400, - 0x4000, - 4, - 0x800, - 0x8000, - 8, - 1, - 0x1000 + 0x100, // 0 + 0x200, // 1 + 0x2000, // 2 + 2, // 3 + 0x400, // 4 + 0x4000, // 5 + 4, // 6 + 0x800, // 7 + 0x8000, // 8 + 8, // 9 + 1, // . + 0x1000 // 00 +}; + +// map for KEYPAD_KEY_CODES_ALT: +// 7 8 9 | 8 80 800 +// 4 5 6 | 4 40 400 +// 1 2 3 | 2 20 200 +// 0 00 . | 1 10 100 +// +// note that the only game that needs this (SDVX VM) does not accept decimal, +// so that key is untested +static int KEYPAD_KEY_CODES_ALT[]{ + 1, // 0 + 2, // 1 + 0x20, // 2 + 0x200, // 3 + 4, // 4 + 0x40, // 5 + 0x400, // 6 + 8, // 7 + 0x80, // 8 + 0x800, // 9 + 0x100, // . + 0x10 // 00 }; static uint8_t KEYPAD_KEY_CODE_NUMS[]{ 0, 1, 5, 9, 2, 6, 10, 3, 7, 11, 8, 4 @@ -421,7 +459,13 @@ void ICCADevice::update_keypad(int unit, bool update_edge) { // check if pressed if (eamu_state & (1 << KEYPAD_EAMUSE_MAPPING[i])) { - this->keypad[unit] |= KEYPAD_KEY_CODES[i]; + + if (ICCA_DEVICE_HACK) { + this->keypad[unit] |= KEYPAD_KEY_CODES_ALT[i]; + } else { + this->keypad[unit] |= KEYPAD_KEY_CODES[i]; + } + if (!this->keypad_last[unit][i] && update_edge) { this->keydown[unit] = (this->keypad_capture[unit] << 4) | KEYPAD_KEY_CODE_NUMS[n]; this->keypad_last[unit][i] = true; diff --git a/acioemu/icca.h b/acioemu/icca.h index f7d3aea..2ca83be 100644 --- a/acioemu/icca.h +++ b/acioemu/icca.h @@ -11,6 +11,8 @@ #include "reader/crypt.h" namespace acioemu { + extern bool ICCA_DEVICE_HACK; + class ICCADevice : public ACIODeviceEmu { private: bool type_new; diff --git a/api/controller.cpp b/api/controller.cpp index 300923a..1c08e38 100644 --- a/api/controller.cpp +++ b/api/controller.cpp @@ -18,6 +18,7 @@ #include "modules/capture.h" #include "modules/coin.h" #include "modules/control.h" +#include "modules/ddr.h" #include "modules/drs.h" #include "modules/iidx.h" #include "modules/info.h" @@ -26,6 +27,7 @@ #include "modules/lights.h" #include "modules/memory.h" #include "modules/touch.h" +#include "modules/resize.h" #include "request.h" #include "response.h" @@ -393,6 +395,7 @@ void Controller::init_state(api::ClientState *state) { state->modules.push_back(new modules::Capture()); state->modules.push_back(new modules::Coin()); state->modules.push_back(new modules::Control()); + state->modules.push_back(new modules::DDR()); state->modules.push_back(new modules::DRS()); state->modules.push_back(new modules::IIDX()); state->modules.push_back(new modules::Info()); @@ -401,6 +404,7 @@ void Controller::init_state(api::ClientState *state) { state->modules.push_back(new modules::Lights()); state->modules.push_back(new modules::Memory()); state->modules.push_back(new modules::Touch()); + state->modules.push_back(new modules::Resize()); } void Controller::free_state(api::ClientState *state) { diff --git a/api/modules/control.cpp b/api/modules/control.cpp index b5e1326..346c5f8 100644 --- a/api/modules/control.cpp +++ b/api/modules/control.cpp @@ -27,34 +27,6 @@ namespace api::modules { { SIGTERM, "SIGTERM" }, }; - static inline bool acquire_shutdown_privs() { - - // check if already acquired - static bool acquired = false; - if (acquired) - return true; - - // get process token - HANDLE hToken; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - return false; - - // get the LUID for the shutdown privilege - TOKEN_PRIVILEGES tkp; - LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); - tkp.PrivilegeCount = 1; - tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - // get the shutdown privilege for this process - AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); - - // check for error - bool success = GetLastError() == ERROR_SUCCESS; - if (success) - acquired = true; - return success; - } - Control::Control() : Module("control", true) { functions["raise"] = std::bind(&Control::raise, this, _1, _2); functions["exit"] = std::bind(&Control::exit, this, _1, _2); @@ -150,7 +122,7 @@ namespace api::modules { return error(res, "Unable to acquire shutdown privileges"); // exit windows - if (!ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, + if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_HYBRID_SHUTDOWN | EWX_FORCE, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_MAINTENANCE)) return error(res, "Unable to shutdown system"); diff --git a/api/modules/ddr.cpp b/api/modules/ddr.cpp new file mode 100644 index 0000000..2c3f3fe --- /dev/null +++ b/api/modules/ddr.cpp @@ -0,0 +1,54 @@ +#include "ddr.h" +#include +#include "external/rapidjson/document.h" +#include "games/ddr/ddr.h" + +using namespace std::placeholders; +using namespace rapidjson; + +namespace api::modules { + + DDR::DDR() : Module("ddr") { + functions["tapeled_get"] = std::bind(&DDR::tapeled_get, this, _1, _2); + } + + /** + * Allows fetching of the RGB LED strips that are gold cabinets, via SpiceAPI + */ + void DDR::tapeled_get(Request &req, Response &res) { + static const char* device_names[11] = { + "p1_foot_up", + "p1_foot_right", + "p1_foot_left", + "p1_foot_down", + "p2_foot_up", + "p2_foot_right", + "p2_foot_left", + "p2_foot_down", + "top_panel", + "monitor_left", + "monitor_right" + }; + + Value response_object(kObjectType); + + // Iterate through each device and dump its lights data into the response + for (size_t device = 0; device < 11; device++) { + size_t num_leds = 25; + if (device > 7) + num_leds = 50; + + Value light_state(kArrayType); + light_state.Reserve(num_leds * 3, res.doc()->GetAllocator()); + for (size_t led = 0; led < num_leds; led++) { + light_state.PushBack(games::ddr::DDR_TAPELEDS[device][led][0], res.doc()->GetAllocator()); + light_state.PushBack(games::ddr::DDR_TAPELEDS[device][led][1], res.doc()->GetAllocator()); + light_state.PushBack(games::ddr::DDR_TAPELEDS[device][led][2], res.doc()->GetAllocator()); + } + + response_object.AddMember(StringRef(device_names[device]), light_state, res.doc()->GetAllocator()); + } + + res.add_data(response_object); + } +} diff --git a/api/modules/ddr.h b/api/modules/ddr.h new file mode 100644 index 0000000..95ed300 --- /dev/null +++ b/api/modules/ddr.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include "api/module.h" +#include "api/request.h" + +namespace api::modules { + + class DDR : public Module { + public: + DDR(); + + private: + // function definitions + void tapeled_get(Request &req, Response &res); + }; +} diff --git a/api/modules/lights.cpp b/api/modules/lights.cpp index b09c680..749b0af 100644 --- a/api/modules/lights.cpp +++ b/api/modules/lights.cpp @@ -1,5 +1,7 @@ #include "lights.h" #include +#include + #include "external/rapidjson/document.h" #include "misc/eamuse.h" #include "cfg/light.h" @@ -17,11 +19,16 @@ namespace api::modules { functions["read"] = std::bind(&Lights::read, this, _1, _2); functions["write"] = std::bind(&Lights::write, this, _1, _2); functions["write_reset"] = std::bind(&Lights::write_reset, this, _1, _2); - lights = games::get_lights(eamuse_get_game()); + + this->lights = games::get_lights(eamuse_get_game()); + for (auto &light : *this->lights) { + this->lights_by_names.emplace(light.getName(), light); + } } /** * read() + * read(name: str, ...) */ void Lights::read(api::Request &req, Response &res) { @@ -30,17 +37,39 @@ namespace api::modules { return; } - // add state for each light - for (auto &light : *this->lights) { - Value state(kArrayType); - Value light_name(light.getName().c_str(), res.doc()->GetAllocator()); - Value light_state(GameAPI::Lights::readLight(RI_MGR, light)); - Value light_enabled(light.override_enabled); - state.PushBack(light_name, res.doc()->GetAllocator()); - state.PushBack(light_state, res.doc()->GetAllocator()); - state.PushBack(light_enabled, res.doc()->GetAllocator()); - res.add_data(state); + // all lights for this game + if (req.params.Size() == 0) { + // add state for each light + for (auto &light : *this->lights) { + get_light(light, res); + } + + return; } + + // specified light names + for (Value ¶m : req.params.GetArray()) { + // check params + if (!param.IsString()) { + error_type(res, "name", "string"); + return; + } + const auto name = param.GetString(); + if (this->lights_by_names.contains(name)) { + get_light(this->lights_by_names.at(name).get(), res); + } + } + } + + void Lights::get_light(Light &light, Response &res) { + Value state(kArrayType); + Value light_name(light.getName().c_str(), res.doc()->GetAllocator()); + Value light_state(GameAPI::Lights::readLight(RI_MGR, light)); + Value light_enabled(light.override_enabled); + state.PushBack(light_name, res.doc()->GetAllocator()); + state.PushBack(light_state, res.doc()->GetAllocator()); + state.PushBack(light_enabled, res.doc()->GetAllocator()); + res.add_data(state); } /** @@ -88,6 +117,7 @@ namespace api::modules { /** * write_reset() + * write_reset(name: str, ...) * write_reset([name: str], ...) */ void Lights::write_reset(Request &req, Response &res) { @@ -104,7 +134,12 @@ namespace api::modules { if (params.Size() == 0) { if (lights != nullptr) { for (auto &light : *this->lights) { - light.override_enabled = false; + if (light.override_enabled) { + if (cfg::CONFIGURATOR_STANDALONE) { + GameAPI::Lights::writeLight(RI_MGR, light, light.last_state); + } + light.override_enabled = false; + } } } return; @@ -112,26 +147,28 @@ namespace api::modules { // loop parameters for (Value ¶m : req.params.GetArray()) { + const char* light_name = nullptr; // check params - if (!param.IsArray()) { - error(res, "parameters must be arrays"); - return; + if (param.IsArray()) { + if (param.Size() < 1) { + error_params_insufficient(res); + continue; + } + if (!param[0].IsString()) { + error_type(res, "name", "string"); + continue; + } + // get params + light_name = param[0].GetString(); + } else if (param.IsString()) { + light_name = param.GetString(); + } else { + error(res, "parameters must be arrays or strings"); } - if (param.Size() < 1) { - error_params_insufficient(res); - continue; - } - if (!param[0].IsString()) { - error_type(res, "name", "string"); - continue; - } - - // get params - auto light_name = param[0].GetString(); // write analog state - if (!this->write_light_reset(light_name)) { + if (light_name && !this->write_light_reset(light_name)) { error_unknown(res, "analog", light_name); continue; } @@ -146,16 +183,20 @@ namespace api::modules { } // find light - for (auto &light : *this->lights) { - if (light.getName() == name) { - light.override_state = CLAMP(state, 0.f, 1.f); - light.override_enabled = true; - return true; - } - } + if (this->lights_by_names.contains(name)) { + auto &light = this->lights_by_names.at(name).get(); + light.override_state = CLAMP(state, 0.f, 1.f); + light.override_enabled = true; - // unknown light - return false; + if (cfg::CONFIGURATOR_STANDALONE) { + GameAPI::Lights::writeLight(RI_MGR, light, state); + } + + return true; + } else { + // unknown light + return false; + } } bool Lights::write_light_reset(std::string name) { @@ -166,14 +207,13 @@ namespace api::modules { } // find light - for (auto &light : *this->lights) { - if (light.getName() == name) { - light.override_enabled = false; - return true; - } + if (this->lights_by_names.contains(name)) { + auto &light = this->lights_by_names.at(name).get(); + light.override_enabled = false; + return true; + } else { + // unknown light + return false; } - - // unknown light - return false; } } diff --git a/api/modules/lights.h b/api/modules/lights.h index b174210..b020f35 100644 --- a/api/modules/lights.h +++ b/api/modules/lights.h @@ -1,6 +1,8 @@ #pragma once #include +#include + #include "api/module.h" #include "api/request.h" #include "cfg/api.h" @@ -15,6 +17,7 @@ namespace api::modules { // state std::vector *lights; + robin_hood::unordered_map> lights_by_names; // function definitions void read(Request &req, Response &res); @@ -22,6 +25,7 @@ namespace api::modules { void write_reset(Request &req, Response &res); // helper + void get_light(Light &light, Response &res); bool write_light(std::string name, float state); bool write_light_reset(std::string name); }; diff --git a/api/modules/resize.cpp b/api/modules/resize.cpp new file mode 100644 index 0000000..84e70e5 --- /dev/null +++ b/api/modules/resize.cpp @@ -0,0 +1,53 @@ +#include "resize.h" +#include "external/rapidjson/document.h" +#include "cfg/screen_resize.h" + +using namespace std::placeholders; +using namespace rapidjson; + +namespace api::modules { + + static thread_local std::vector CAPTURE_BUFFER; + + Resize::Resize() : Module("resize") { + functions["image_resize_enable"] = std::bind(&Resize::image_resize_enable, this, _1, _2); + functions["image_resize_set_scene"] = std::bind(&Resize::image_resize_set_scene, this, _1, _2); + } + + /** + * image_resize_enable(enable: bool) + */ + void Resize::image_resize_enable(Request &req, Response &res) { + if (req.params.Size() < 1) { + return error_params_insufficient(res); + } + if (!req.params[0].IsBool()) { + return error_type(res, "enable", "bool"); + } + + cfg::SCREENRESIZE->enable_screen_resize = req.params[0].GetBool(); + } + + /** + * image_resize_set_scene(scene: int) + */ + void Resize::image_resize_set_scene(Request &req, Response &res) { + if (req.params.Size() < 1) { + return error_params_insufficient(res); + } + if (!req.params[0].IsInt()) { + return error_type(res, "scene", "int"); + } + + const auto scene = req.params[0].GetInt(); + if (scene < 0 || (int)std::size(cfg::SCREENRESIZE->scene_settings) < scene) { + return error(res, "invalid scene number"); + } + if (scene == 0) { + cfg::SCREENRESIZE->enable_screen_resize = false; + } else { + cfg::SCREENRESIZE->enable_screen_resize = true; + cfg::SCREENRESIZE->screen_resize_current_scene = scene - 1; + } + } +} diff --git a/api/modules/resize.h b/api/modules/resize.h new file mode 100644 index 0000000..ca6f1da --- /dev/null +++ b/api/modules/resize.h @@ -0,0 +1,18 @@ +#pragma once + +#include "api/module.h" +#include "api/request.h" + +namespace api::modules { + + class Resize : public Module { + public: + Resize(); + + private: + + // function definitions + void image_resize_enable(Request &req, Response &res); + void image_resize_set_scene(Request &req, Response &res); + }; +} diff --git a/api/modules/touch.cpp b/api/modules/touch.cpp index 7358311..ca7eba2 100644 --- a/api/modules/touch.cpp +++ b/api/modules/touch.cpp @@ -4,6 +4,7 @@ #include "external/rapidjson/document.h" #include "avs/game.h" +#include "hooks/graphics/graphics.h" #include "misc/eamuse.h" #include "launcher/launcher.h" #include "touch/touch.h" @@ -18,7 +19,12 @@ namespace api::modules { Touch::Touch() : Module("touch") { is_sdvx = avs::game::is_model("KFC"); + is_tdj_fhd = (avs::game::is_model("LDJ") && games::iidx::is_tdj_fhd()); + // special case: when windowed subscreen is in use, use the original coords + if (GRAPHICS_IIDX_WSUB) { + is_tdj_fhd = false; + } functions["read"] = std::bind(&Touch::read, this, _1, _2); functions["write"] = std::bind(&Touch::write, this, _1, _2); diff --git a/api/resources/lua/README.md b/api/resources/lua/README.md deleted file mode 100644 index d88ca17..0000000 --- a/api/resources/lua/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Lua Scripting -Supported version: Lua 5.4.3 -No proper documentation yet. Check the example scripts if you need this! -For undocumented functions you can find the definitions in the source code (script/api/*.cpp). -They are very similar to what the network API provides. - -# Automatic Execution -Create a "scripts" folder next to spice and put your scripts in there (subfolders allowed). -The prefix specifies when the script will be called: - -- `boot_*`: executed on game boot -- `shutdown_*`: executed on game end -- `config_*`: executed when you start spicecfg (mostly for debugging/tests) - -Example: "scripts/boot_patch.py" would be called on game boot. diff --git a/api/resources/lua/boot_iidx_tt_lights.lua b/api/resources/lua/boot_iidx_tt_lights.lua deleted file mode 100644 index aeaa2e7..0000000 --- a/api/resources/lua/boot_iidx_tt_lights.lua +++ /dev/null @@ -1,113 +0,0 @@ --- example script for light effects on IIDX TT stab movement --- create a folder called "script" next to spice and put me in there --------------------------------------------------------------------------------- - --- settings -tt_duration = 0.25 -zero_duration = 0.3141592 -loop_delta = 1 / 240 -curve_pow = 1 / 4 -col_r = 1.0 -col_g = 0.0 -col_b = 0.0 -light_p1_r = "Side Panel Left Avg R" -light_p1_g = "Side Panel Left Avg G" -light_p1_b = "Side Panel Left Avg B" -light_p2_r = "Side Panel Right Avg R" -light_p2_g = "Side Panel Right Avg G" -light_p2_b = "Side Panel Right Avg B" - --- wait for game -while not analogs.read()["Turntable P1"] do yield() end - --- initial state -tt1_last = tonumber(analogs.read()["Turntable P1"].state) -tt2_last = tonumber(analogs.read()["Turntable P2"].state) -tt1_diff_last = 0 -tt2_diff_last = 0 -tt1_trigger = 0 -tt2_trigger = 0 -tt1_zero_elapsed = 0 -tt2_zero_elapsed = 0 - --- main loop -while true do - - -- read state - tt1 = tonumber(analogs.read()["Turntable P1"].state) - tt2 = tonumber(analogs.read()["Turntable P2"].state) - time_cur = time() - - -- calculate difference - tt1_diff = tt1 - tt1_last - tt2_diff = tt2 - tt2_last - - -- fix wrap around - if math.abs(tt1_diff) > 0.5 then tt1_diff = 0 end - if math.abs(tt2_diff) > 0.5 then tt2_diff = 0 end - - -- trigger on movement start and direction changes - if (tt1_diff_last == 0 and tt1_diff ~= 0) - or (tt1_diff_last > 0 and tt1_diff < 0) - or (tt1_diff_last < 0 and tt1_diff > 0) then - tt1_trigger = time_cur - end - if (tt2_diff_last == 0 and tt2_diff ~= 0) - or (tt2_diff_last > 0 and tt2_diff < 0) - or (tt2_diff_last < 0 and tt2_diff > 0) then - tt2_trigger = time_cur - end - - -- light effects when last trigger is still active - if time_cur - tt1_trigger < tt_duration then - brightness = 1 - ((time_cur - tt1_trigger) / tt_duration) ^ curve_pow - lights.write({[light_p1_r]={state=brightness*col_r}}) - lights.write({[light_p1_g]={state=brightness*col_g}}) - lights.write({[light_p1_b]={state=brightness*col_b}}) - else - lights.write_reset(light_p1_r) - lights.write_reset(light_p1_g) - lights.write_reset(light_p1_b) - end - if time_cur - tt2_trigger < tt_duration then - brightness = 1 - ((time_cur - tt2_trigger) / tt_duration) ^ curve_pow - lights.write({[light_p2_r]={state=brightness*col_r}}) - lights.write({[light_p2_g]={state=brightness*col_g}}) - lights.write({[light_p2_b]={state=brightness*col_b}}) - else - lights.write_reset(light_p2_r) - lights.write_reset(light_p2_g) - lights.write_reset(light_p2_b) - end - - -- flush HID light output - lights.update() - - -- turntable movement detection - -- doesn't set the diff back to zero unless enough time has passed - if tt1_diff == 0 then - tt1_zero_elapsed = tt1_zero_elapsed + loop_delta - if tt1_zero_elapsed >= zero_duration then - tt1_diff_last = tt1_diff - end - else - tt1_zero_elapsed = 0 - tt1_diff_last = tt1_diff - end - if tt2_diff == 0 then - tt2_zero_elapsed = tt2_zero_elapsed + loop_delta - if tt2_zero_elapsed >= zero_duration then - tt2_diff_last = tt2_diff - end - else - tt2_zero_elapsed = 0 - tt2_diff_last = tt2_diff - end - - -- remember state - tt1_last = tt1 - tt2_last = tt2 - - -- loop end - sleep(loop_delta) -end diff --git a/api/resources/lua/config_example.lua b/api/resources/lua/config_example.lua deleted file mode 100644 index ae09b55..0000000 --- a/api/resources/lua/config_example.lua +++ /dev/null @@ -1,57 +0,0 @@ --- script examples --- no proper documentation yet --- create a folder called "script" next to spice and put me in there --- then open the config and if needed select IIDX for the demo --------------------------------------------------------------------------------- - --- sleep for 0.2 seconds -sleep(0.2) - --- log functions -log_misc("example misc") -log_info("example info") -log_warning("example warning") ---log_fatal("this would terminate") - --- print time -log_info(time()) - --- show message box -msgbox("You are running the example script! Select IIDX if not already done.") - --- wait until analog is available -while not analogs.read()["Turntable P1"] do yield() end - --- write button state -buttons.write({["P1 Start"]={state=1}}) - --- write analog state -analogs.write({["Turntable P1"]={state=0.33}}) - --- write light state -lights.write({["P2 Start"]={state=0.8}}) - --- import other libraries in "script" folder ---local example = require('script.example') - --- demo -while true do - - -- analog animation - analogs.write({["Turntable P2"]={state=math.abs(math.sin(time()))}}) - - -- button blink - if math.cos(time() * 10) > 0 then - buttons.write({["P1 1"]={state=1}}) - else - buttons.write({["P1 1"]={state=0}}) - end - - -- flush HID light output - lights.update() - - -- check for keyboard press - if GetAsyncKeyState(0x20) > 0 then - msgbox("You pressed space!") - end -end diff --git a/api/resources/python/spiceapi/__init__.py b/api/resources/python/spiceapi/__init__.py index 5cd290a..b7fe465 100644 --- a/api/resources/python/spiceapi/__init__.py +++ b/api/resources/python/spiceapi/__init__.py @@ -12,3 +12,4 @@ from .keypads import * from .lights import * from .memory import * from .touch import * +from .resize import * \ No newline at end of file diff --git a/api/resources/python/spiceapi/lights.py b/api/resources/python/spiceapi/lights.py index 038373d..dba33f3 100644 --- a/api/resources/python/spiceapi/lights.py +++ b/api/resources/python/spiceapi/lights.py @@ -2,8 +2,14 @@ from .connection import Connection from .request import Request -def lights_read(con: Connection): - res = con.request(Request("lights", "read")) +def lights_read(con: Connection, light_names=None): + req = Request("lights", "read") + + if light_names: + for light_name in light_names: + req.add_param(light_name) + + res = con.request(req) return res.get_data() diff --git a/api/resources/python/spiceapi/resize.py b/api/resources/python/spiceapi/resize.py new file mode 100644 index 0000000..92f585e --- /dev/null +++ b/api/resources/python/spiceapi/resize.py @@ -0,0 +1,12 @@ +from .connection import Connection +from .request import Request + +def image_resize_enable(con: Connection, enable: bool): + req = Request("resize", "image_resize_enable") + req.add_param(enable) + con.request(req) + +def image_resize_set_scene(con: Connection, scene: int): + req = Request("resize", "image_resize_set_scene") + req.add_param(scene) + con.request(req) diff --git a/api/resources/python/spiceremote.py b/api/resources/python/spiceremote.py index 3db10f9..52e37f1 100644 --- a/api/resources/python/spiceremote.py +++ b/api/resources/python/spiceremote.py @@ -179,7 +179,7 @@ class ControlTab(ttk.Frame): self.card_lbl = ttk.Label(self.card, text="Card") self.card_lbl.grid(row=0, columnspan=2) self.card_entry = ttk.Entry(self.card) - self.card_entry.insert(tk.END, "E004000000000000") + self.card_entry.insert(tk.END, "E004010000000000") self.card_entry.grid(row=1, columnspan=2, sticky=NSEW, padx=2, pady=2) self.card_insert_p1 = ttk.Button(self.card, text="Insert P1", command=self.action_insert_p1) self.card_insert_p1.grid(row=2, column=0, sticky=NSEW, padx=2, pady=2) @@ -397,6 +397,65 @@ class LightsTab(ttk.Frame): # set text self.txt_lights.set_text(txt) +class ResizeTab(ttk.Frame): + """Resize tab.""" + + def __init__(self, app, parent, **kwargs): + + # init frame + ttk.Frame.__init__(self, parent, **kwargs) + self.app = app + self.parent = parent + + # scale grid + self.columnconfigure(0, weight=1) + + # image resize + self.resize = ttk.Frame(self, padding=(8, 8, 8, 8)) + self.resize.grid(row=0, column=0, sticky=tk.E+tk.W) + self.resize.columnconfigure(0, weight=1) + self.resize.columnconfigure(1, weight=1) + self.resize_lbl = ttk.Label(self.resize, text="Image Resize") + self.resize_lbl.grid(row=0, columnspan=2) + + self.resize_off = ttk.Button(self.resize, text="Disable", command=self.action_resize_false) + self.resize_off.grid(row=2, column=0, sticky=NSEW, padx=2, pady=2) + + self.resize_on = ttk.Button(self.resize, text="Enable", command=self.action_resize_on) + self.resize_on.grid(row=2, column=1, sticky=NSEW, padx=2, pady=2) + + self.resize_scene_1 = ttk.Button(self.resize, text="Scene 1", command=self.action_resize_scene_1) + self.resize_scene_1.grid(row=3, column=0, sticky=NSEW, padx=2, pady=2) + self.resize_scene_2 = ttk.Button(self.resize, text="Scene 2", command=self.action_resize_scene_2) + self.resize_scene_2.grid(row=3, column=1, sticky=NSEW, padx=2, pady=2) + self.resize_scene_3 = ttk.Button(self.resize, text="Scene 3", command=self.action_resize_scene_3) + self.resize_scene_3.grid(row=4, column=0, sticky=NSEW, padx=2, pady=2) + self.resize_scene_4 = ttk.Button(self.resize, text="Scene 4", command=self.action_resize_scene_4) + self.resize_scene_4.grid(row=4, column=1, sticky=NSEW, padx=2, pady=2) + + @api_action + def action_resize_on(self): + spiceapi.image_resize_enable(self.app.connection, True) + + @api_action + def action_resize_false(self): + spiceapi.image_resize_enable(self.app.connection, False) + + @api_action + def action_resize_scene_1(self): + spiceapi.image_resize_set_scene(self.app.connection, 1) + + @api_action + def action_resize_scene_2(self): + spiceapi.image_resize_set_scene(self.app.connection, 2) + + @api_action + def action_resize_scene_3(self): + spiceapi.image_resize_set_scene(self.app.connection, 3) + + @api_action + def action_resize_scene_4(self): + spiceapi.image_resize_set_scene(self.app.connection, 4) class MainApp(ttk.Frame): """The main application frame.""" @@ -419,6 +478,8 @@ class MainApp(ttk.Frame): self.tabs.add(self.tab_analogs, text="Analogs") self.tab_lights = LightsTab(self, self.tabs) self.tabs.add(self.tab_lights, text="Lights") + self.tab_resize = ResizeTab(self, self.tabs) + self.tabs.add(self.tab_resize, text="Resize") self.tab_manual = ManualTab(self, self.tabs) self.tabs.add(self.tab_manual, text="Manual") self.tabs.pack(expand=True, fill=tk.BOTH) diff --git a/avs/automap.cpp b/avs/automap.cpp index 54fdba4..8f2fe43 100644 --- a/avs/automap.cpp +++ b/avs/automap.cpp @@ -471,7 +471,7 @@ namespace avs::automap { ENABLED = true; // check if optional imports are supported for this avs version - if (!avs::core::property_node_read) { + if (!avs::core::property_node_read || !avs::core::property_get_error) { log_fatal("automap", "missing optional avs imports which are required for this module to work"); } diff --git a/avs/core.cpp b/avs/core.cpp index c31de64..32d000b 100644 --- a/avs/core.cpp +++ b/avs/core.cpp @@ -334,8 +334,12 @@ namespace avs { .avs_fs_close = "XC0bbe97000119", .avs_fs_dump_mountpoint = "XC0bbe970000c5", .avs_fs_mount = "XC0bbe97000099", + .avs_fs_fstat = "XC0bbe970000ce", .avs_fs_lstat = "XC0bbe9700005f", + .avs_fs_read = "XC0bbe97000134", .avs_fs_opendir = "XC0bbe970000db", + .property_file_write = "property_file_write", // not found + .property_get_error = "property_get_error", // not found .avs_net_add_protocol = "XC0bbe97000124", .avs_net_del_protocol = "XC0bbe97000026", .avs_net_addrinfobyaddr = "XC0bbe970000a4", @@ -1360,9 +1364,11 @@ namespace avs { fclose(file); // error checking - auto err = avs::core::property_get_error(property); - if (err > 0) { - log_fatal("avs-core", "failed to read config file ({}): {}", filename, error_str(err)); + if (avs::core::property_get_error) { + auto err = avs::core::property_get_error(property); + if (err > 0) { + log_fatal("avs-core", "failed to read config file ({}): {}", filename, error_str(err)); + } } // return value @@ -1467,7 +1473,7 @@ namespace avs { } } - bool load_dll() { + void load_dll() { log_info("avs-core", "loading DLL"); // detect DLL name @@ -1479,12 +1485,30 @@ namespace avs { #else DLL_NAME = "libavs-win32.dll"; #endif + + if (!fileutils::file_exists(MODULE_PATH / DLL_NAME)) { + std::string info_str { fmt::format( + "\n\n" + "Failed to find critical avs DLL on disk (avs2-core.dll OR {})\n" + "Looked in the following directory: {}\n" + "\n" + "One of these is required to boot the game. Spice found neither of them. You do not need both, just one, next to your game DLL.\n" + "\n" + "HOW TO FIX:\n" + " * Avoid manually specifying DLL path (-exec) and module directory (-modules); let spice2x auto-detect unless you have a good reason not to\n" + " * Ensure you do NOT have multiple copies of the game DLLs (e.g., in contents and in contents\\modules)\n" + " * It's also possible that you have incomplete game data\n" + " * Do NOT copy over random DLLs from another game installation; DLL must match game version\n" + "\n" + , DLL_NAME, MODULE_PATH.string()) }; + log_fatal("avs-ea3", "{}", info_str); + } } // load library - DLL_INSTANCE = libutils::load_library(MODULE_PATH / DLL_NAME, false); + DLL_INSTANCE = libutils::load_library(MODULE_PATH / DLL_NAME); if (!DLL_INSTANCE) { - return false; + return; } // check by version string if obtained @@ -1709,7 +1733,7 @@ namespace avs { } // success - return true; + return; } static void create_dir( diff --git a/avs/core.h b/avs/core.h index 2f7adf2..50644fa 100644 --- a/avs/core.h +++ b/avs/core.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -448,7 +449,7 @@ namespace avs { // functions void set_default_heap_size(const std::string &dll_name); void create_log(); - bool load_dll(); + void load_dll(); void boot(); void copy_defaults(); void shutdown(); diff --git a/avs/ea3.cpp b/avs/ea3.cpp index cf485ce..58598b4 100644 --- a/avs/ea3.cpp +++ b/avs/ea3.cpp @@ -133,6 +133,24 @@ namespace avs { #else DLL_NAME = "libavs-win32-ea3.dll"; #endif + + if (!fileutils::file_exists(MODULE_PATH / DLL_NAME)) { + std::string info_str { fmt::format( + "\n\n" + "Failed to find critical ea3 DLL on disk (avs2-ea3.dll OR {})\n" + "Looked in the following directory: {}\n" + "\n" + "One of these is required to boot the game. Spice found neither of them. You do not need both, just one, next to your game DLL.\n" + "\n" + "HOW TO FIX:\n" + " * Avoid manually specifying DLL path (-exec) and module directory (-modules); let spice2x auto-detect unless you have a good reason not to\n" + " * Ensure you do NOT have multiple copies of the game DLLs (e.g., in contents and in contents\\modules)\n" + " * It's also possible that you have incomplete game data\n" + " * Do NOT copy over random DLLs from another game installation; DLL must match game version\n" + "\n" + , DLL_NAME, MODULE_PATH.string()) }; + log_fatal("avs-ea3", "{}", info_str); + } } // load library diff --git a/avs/game.cpp b/avs/game.cpp index e9c3796..ca5c1a2 100644 --- a/avs/game.cpp +++ b/avs/game.cpp @@ -72,8 +72,35 @@ namespace avs { log_info("avs-game", "loading DLL '{}'", DLL_NAME); // load game instance - if (fileutils::verify_header_pe(MODULE_PATH / DLL_NAME)) { - DLL_INSTANCE = libutils::load_library(MODULE_PATH / DLL_NAME); + const auto dll_path = MODULE_PATH / DLL_NAME; + const auto dll_path_s = dll_path.string(); + log_info("avs-game", "DLL path: {}", dll_path_s.c_str()); + + // MAX_PATH is 260 + if (130 <= dll_path_s.length()) { + log_warning( + "avs-game", + "PATH TOO LONG WARNING\n\n\n" + "-------------------------------------------------------------------\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + "WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n" + " PATH TOO LONG \n" + "WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + "The path '{}'\n" + " has a length of {}\n" + "Most of these games may behave unexpectedly when the path is too\n" + "long, often resulting in random crashes. Move the game contents to\n" + "a directory with shorter path.\n" + "-------------------------------------------------------------------\n\n", + dll_path_s, dll_path_s.length()); + } + if (!fileutils::file_exists(dll_path)) { + log_warning("avs-game", "game DLL could not be found on disk: {}", dll_path.string().c_str()); + log_warning("avs-game", "double check -exec and -modules parameters; unless you know what you're doing, leave them blank"); + } + if (fileutils::verify_header_pe(dll_path)) { + DLL_INSTANCE = libutils::load_library(dll_path); } // load entry points diff --git a/build_all.sh b/build_all.sh old mode 100644 new mode 100755 index b1de981..713512a --- a/build_all.sh +++ b/build_all.sh @@ -19,6 +19,25 @@ function trap_error_exit { trap trap_error_dbg DEBUG trap trap_error_exit EXIT +IGNORE_CACHE=0 + +# Parse options +while getopts "ih" opt; do + case $opt in + i) IGNORE_CACHE=1 ;; + h) + echo "Usage: $0 [-i]" + echo " -i: Ignore build cache" + echo " -h: Show this help" + exit 0 + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac +done + # settings GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none") GIT_HEAD=$(git rev-parse HEAD || echo "none") @@ -41,8 +60,8 @@ DIST_ENABLE=1 DIST_FOLDER="./dist" DIST_NAME="spice2x-$(date +%y)-$(date +%m)-$(date +%d).zip" DIST_COMMENT=${DIST_NAME}$'\n'"$GIT_BRANCH - $GIT_HEAD"$'\nThank you for playing.' -TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice" -TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_spice64" +TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice spicetools_spice_laa" +TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvEncodeAPI64 spicetools_stubs_nvcuvid spicetools_stubs_nvcuda spicetools_spice64" # determine build type BUILD_TYPE="Release" @@ -57,7 +76,7 @@ then fi # determine number of cores -CORES=$(awk '/^processor\t/ {cores[$NF]++} END {print length(cores)}' /proc/cpuinfo) +CORES=$(nproc) # print information echo "" @@ -74,34 +93,45 @@ echo "Build Type: $BUILD_TYPE" echo "Cores: $CORES" echo "" -# 32 bit -echo "Building 32bit targets..." -echo "=========================" -if ((CLEAN_BUILD > 0)) +if ((IGNORE_CACHE > 0)) then - rm -rf ${BUILDDIR_32} + echo "Ignoring build cache..." +else + export CCACHE_DIR="$(pwd)/.ccache" + export CMAKE_CXX_COMPILER_LAUNCHER=ccache + export CMAKE_C_COMPILER_LAUNCHER=ccache fi -mkdir -p ${BUILDDIR_32} -pushd ${BUILDDIR_32} > /dev/null -cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && make -j ${CORES} ${TARGETS_32} -popd > /dev/null -# 64 bit -echo "" -echo "Building 64bit targets..." -echo "=========================" -if ((CLEAN_BUILD > 0)) -then - rm -rf ${BUILDDIR_64} -fi -mkdir -p ${BUILDDIR_64} -pushd ${BUILDDIR_64} > /dev/null -cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && make -j ${CORES} ${TARGETS_64} -popd > /dev/null +time ( + # 32 bit + echo "Building 32bit targets..." + echo "=========================" + if ((CLEAN_BUILD > 0)) + then + rm -rf ${BUILDDIR_32} + fi + mkdir -p ${BUILDDIR_32} + pushd ${BUILDDIR_32} > /dev/null + cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && ninja ${TARGETS_32} + popd > /dev/null -echo "" -echo "Compilation process done :)" -echo "===========================" + # 64 bit + echo "" + echo "Building 64bit targets..." + echo "=========================" + if ((CLEAN_BUILD > 0)) + then + rm -rf ${BUILDDIR_64} + fi + mkdir -p ${BUILDDIR_64} + pushd ${BUILDDIR_64} > /dev/null + cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && ninja ${TARGETS_64} + popd > /dev/null + + echo "" + echo "Compilation process done :)" + echo "===========================" +) # generate PDBs if false # ((DEBUG > 0)) @@ -152,7 +182,8 @@ echo "Copy files to output directory..." rm -rf ${OUTDIR} mkdir -p ${OUTDIR} #mkdir -p ${OUTDIR}/stubs/32 -#mkdir -p ${OUTDIR}/stubs/64 +mkdir -p ${OUTDIR}/stubs/64 +mkdir -p ${OUTDIR}/extras/largeaddressaware if false # ((DEBUG > 0)) then # debug files @@ -166,28 +197,22 @@ then cp ${BUILDDIR_64}/spicetools/64/spice64-pdb.pdb ${OUTDIR} 2>/dev/null #cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null #cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null + #cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null + #cp ${BUILDDIR_64}/spicetools/64/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null + #cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null else # release files cp ${BUILDDIR_32}/spicetools/spicecfg.exe ${OUTDIR} 2>/dev/null cp ${BUILDDIR_32}/spicetools/32/spice.exe ${OUTDIR} 2>/dev/null + cp ${BUILDDIR_32}/spicetools/32/spice_laa.exe ${OUTDIR}/extras/largeaddressaware/spice.exe 2>/dev/null #cp ${BUILDDIR_32}/spicetools/32/kbt.dll ${OUTDIR}/stubs/32 2>/dev/null #cp ${BUILDDIR_32}/spicetools/32/kld.dll ${OUTDIR}/stubs/32 2>/dev/null cp ${BUILDDIR_64}/spicetools/64/spice64.exe ${OUTDIR} 2>/dev/null #cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null #cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null -fi - -# compress using UPX -if ((UPX_ENABLE > 0 && DEBUG == 0)) -then - echo "Processing files with UPX..." - upx ${UPX_FLAGS} ${OUTDIR}/spicecfg.exe > /dev/null - upx ${UPX_FLAGS} ${OUTDIR}/spice.exe > /dev/null - #upx ${UPX_FLAGS} ${OUTDIR}/stubs/32/kbt.dll > /dev/null - #upx ${UPX_FLAGS} ${OUTDIR}/stubs/32/kld.dll > /dev/null - upx ${UPX_FLAGS} ${OUTDIR}/spice64.exe > /dev/null - #upx ${UPX_FLAGS} ${OUTDIR}/stubs/64/kbt.dll > /dev/null - #upx ${UPX_FLAGS} ${OUTDIR}/stubs/64/kld.dll > /dev/null + cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null + cp ${BUILDDIR_64}/spicetools/64/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null + cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null fi # pack source files to output directory @@ -196,7 +221,7 @@ mkdir -p ${OUTDIR}/src if ((INCLUDE_SRC > 0)) then echo "Generating source file archive..." - git archive --format tar.gz --prefix=spice2x/ HEAD > ${OUTDIR}/src/spice2x-${GIT_BRANCH}.tar.gz 2>/dev/null || \ + git archive --format tar.gz --prefix=spice2x/ HEAD ./ > ${OUTDIR}/src/spice2x-${GIT_BRANCH}.tar.gz 2>/dev/null || \ echo "WARNING: Couldn't get git to create the archive. Is this a git repository?" fi diff --git a/build_docker.bat b/build_docker.bat index 4d0d2a3..7072a75 100644 --- a/build_docker.bat +++ b/build_docker.bat @@ -1,6 +1,6 @@ docker build --pull external/docker -t spicetools/deps -docker build . -t spicetools/spice --no-cache -docker run --rm -it -v %cd%/dist:/src/dist -v %cd%/bin:/src/bin spicetools/spice +docker build --build-context gitroot=%cd%/../../.git . -t spicetools/spice +docker run --rm -it -v %cd%/dist:/src/src/spice2x/dist -v %cd%/bin:/src/src/spice2x/bin -v %cd%/.ccache:/src/src/spice2x/.ccache spicetools/spice %* @REM to generate PDBs, set DEBUG to 1 in build_all.sh, place cv2pdb in external\cv2pdb, and run below @REM external\cv2pdb\cv2pdb.exe bin\spice2x\spicecfg.exe bin\spice2x\spicecfg-pdb.exe bin\spice2x\spicecfg-pdb.pdb @REM external\cv2pdb\cv2pdb.exe bin\spice2x\spice.exe bin\spice2x\spice-pdb.exe bin\spice2x\spice-pdb.pdb diff --git a/build_docker.sh b/build_docker.sh old mode 100644 new mode 100755 index 6d63f7e..f47ca69 --- a/build_docker.sh +++ b/build_docker.sh @@ -1,6 +1,4 @@ #!/bin/bash -export DOCKER_BUILDKIT=0 - docker build --pull $PWD/external/docker -t spicetools/deps --platform linux/x86_64 -docker build . -t spicetools/spice:latest --no-cache -docker run --rm -it -v $PWD/dist:/src/dist -v $PWD/bin:/src/bin spicetools/spice +docker build --build-context gitroot=$PWD/../../.git . -t spicetools/spice:latest +docker run --rm -v $PWD/dist:/src/src/spice2x/dist -v $PWD/bin:/src/src/spice2x/bin -v $PWD/.ccache:/src/src/spice2x/.ccache spicetools/spice "$@" diff --git a/build_msvc.py b/build_msvc.py deleted file mode 100644 index e09c831..0000000 --- a/build_msvc.py +++ /dev/null @@ -1,85 +0,0 @@ -from typing import Dict, List - -import argparse -import os -import subprocess - - -def get_vs_installation_path() -> str: - program_files_x86 = os.environ["ProgramFiles(x86)"] - process = subprocess.run( - [f"{program_files_x86}\\Microsoft Visual Studio\\Installer\\vswhere.exe", "-prerelease", "-latest", "-property", - "installationPath"], - capture_output=True, check=True, encoding="utf-8") - - return process.stdout.strip() - - -def source_bat(bat_file: str, arch: str) -> Dict[str, str]: - interesting = {"INCLUDE", "LIB", "LIBPATH", "PATH"} - result = {} - - process = subprocess.Popen(f"\"{bat_file}\" {arch} & set", stdout=subprocess.PIPE, shell=True, encoding="utf-8") - (out, err) = process.communicate() - - if err is not None: - raise Exception(err) - - for line in out.split("\n"): - if '=' not in line: - continue - - key, value = line.strip().split('=', 1) - key = key.upper() - - if key in interesting: - result[key] = value - - return result - - -def run_build(build_dir: str, build_type: str, build_targets: List[str], build_env: Dict[str, str]): - os.makedirs(build_dir, exist_ok=True) - - subprocess.check_call(["cmake.exe", f"-DCMAKE_BUILD_TYPE={build_type}", "-GNinja", ".."], cwd=build_dir, - env=build_env, shell=True) - subprocess.check_call(["ninja.exe"] + build_targets, cwd=build_dir, env=build_env, shell=True) - - -def main(): - parser = argparse.ArgumentParser(description='Build SpiceTools with MSVC') - parser.add_argument('--build-type', type=str, default='Release', help='CMake build type') - - args = parser.parse_args() - - build_dir = args.build_type.lower() - parent_env = {key: os.environ[key] for key in os.environ} - - vs_installation_path = get_vs_installation_path() - bat_file = f"{vs_installation_path}\\VC\\Auxiliary\\Build\\vcvarsall.bat" - print(bat_file) - - # parent_env["CC"] = "clang" - # parent_env["CXX"] = "clang++" - - print("Building spice64") - - env_64 = source_bat(bat_file, "x64") - env_64_merged = parent_env.copy() - env_64_merged.update(env_64) - - run_build(f"cmake-build-{build_dir}-64", args.build_type, - ["spicetools_stubs_kbt64", "spicetools_stubs_kld64", "spicetools_spice64"], env_64_merged) - - print("Building spice") - - env_32 = source_bat(bat_file, "x86") - env_32_merged = parent_env.copy() - env_32_merged.update(env_32) - - run_build(f"cmake-build-{build_dir}-32", args.build_type, - ["spicetools_stubs_kbt", "spicetools_stubs_kld", "spicetools_cfg", "spicetools_spice"], env_32_merged) - - -if __name__ == "__main__": - main() diff --git a/build_release.bat b/build_release.bat new file mode 100644 index 0000000..111e908 --- /dev/null +++ b/build_release.bat @@ -0,0 +1,2 @@ +del /s /q .ccache +call build_docker.bat \ No newline at end of file diff --git a/cfg/analog.cpp b/cfg/analog.cpp index 0aee08f..44abb41 100644 --- a/cfg/analog.cpp +++ b/cfg/analog.cpp @@ -55,20 +55,39 @@ std::string Analog::getDisplayString(rawinput::RawInputManager *manager) { } case rawinput::MIDI: { auto midi = device->midiInfo; + // update strings in button.cpp as well if (index < midi->controls_precision.size()) { - return "MIDI PREC " + indexString + " (" + device->desc + ")"; + const int channel = (index / 32) + 1; + const int cc_index = (index % 32); + return fmt::format("MIDI Prec Ctrl Ch.{} CC#{} ({})", channel, cc_index, device->desc); } else if (index < midi->controls_precision.size() + midi->controls_single.size()) { - return "MIDI CTRL " + indexString + " (" + device->desc + ")"; + const int index_rel = index - midi->controls_precision.size(); + const int channel = (index_rel / 44) + 1; + int cc_index = (index_rel % 44); + if (cc_index < 26) { + cc_index += 0x46; // single byte range + } else { + cc_index = cc_index - 26 + 0x66; // undefined single byte range + } + return fmt::format("MIDI Ctrl Ch.{} CC#{} ({})", channel, cc_index, device->desc); } else if (index < midi->controls_precision.size() + midi->controls_single.size() + midi->controls_onoff.size()) { - return "MIDI ONOFF " + indexString + " (" + device->desc + ")"; - } else if (index == midi->controls_precision.size() + midi->controls_single.size() - + midi->controls_onoff.size()) + const int index_rel = index - midi->controls_precision.size() - midi->controls_single.size(); + const int channel = (index_rel / 6) + 1; + const int cc_index = (index_rel % 6) + 0x40; + return fmt::format("MIDI OnOff Ch.{} CC#{} ({})", channel, cc_index, device->desc); + } else if (index < + midi->controls_precision.size() + midi->controls_single.size() + midi->controls_onoff.size() + midi->pitch_bend.size()) { - return "MIDI Pitch Bend (" + device->desc + ")"; + const int index_rel = + index - + midi->controls_precision.size() - + midi->controls_single.size() - + midi->controls_onoff.size(); + return fmt::format("MIDI Pitch Ch.{} ({})", index_rel + 1, device->desc); } else { - return "MIDI Unknown " + indexString + " (" + device->desc + ")"; + return "MIDI Unknown Index " + indexString + " (" + device->desc + ")"; } } case rawinput::DESTROYED: @@ -158,3 +177,98 @@ float Analog::normalizeAngle(float rads) { } return angle; } + +float Analog::applyMultiplier(float value) { + if (1 < this->multiplier) { + // multiplier - just multiply the value and take the decimal part + return normalizeAnalogValue(value * this->multiplier); + } else if (this->multiplier < -1) { + const unsigned short number_of_divisions = -this->multiplier; + // divisor - need to take care of over/underflow + if (0.75f < this->divisor_previous_value && value < 0.25f) { + this->divisor_region = (this->divisor_region + 1) % number_of_divisions; + } else if (this->divisor_previous_value < 0.25f && 0.75f < value) { + if (1 <= this->divisor_region) { + this->divisor_region -= 1; + } else { + this->divisor_region = number_of_divisions - 1; + } + } + this->divisor_previous_value = value; + return ((float)this->divisor_region + value) / (float)number_of_divisions; + } else { + // multiplier in [-1, 1] range is just treated as 1 + return value; + } +} + +float Analog::normalizeAnalogValue(float value) { + // effectively the same as fmodf(value, 1.f) + // for small values, this is MUCH faster than fmodf. + float new_value = value; + while (new_value > 1.f) { + new_value -= 1.f; + } + while (new_value < 0.f) { + new_value += 1.f; + } + return new_value; +} + +float Analog::applyDeadzone(float raw_value) { + float value = raw_value; + const auto deadzone = this->getDeadzone(); + if (deadzone > 0) { + + // calculate values + const auto delta = value - 0.5f; + const auto dtlen = 1.f - deadzone; + + // check mirror + if (this->getDeadzoneMirror()) { + + // deadzone on the edges + if (dtlen != 0.f) { + value = std::max(0.f, std::min(1.f, 0.5f + (delta / dtlen))); + } else { + value = 0.5f; + } + + } else { + + // deadzone around the middle + const auto limit = deadzone * 0.5f; + if (dtlen != 0.f) { + if (delta > limit) { + value = std::min(1.f, 0.5f + std::max(0.f, (delta - limit) / dtlen)); + } else if (delta < -limit) { + value = std::max(0.f, 0.5f + std::min(0.f, (delta + limit) / dtlen)); + } else { + value = 0.5f; + } + } else { + value = 0.5f; + } + } + + } else if (deadzone < 0) { + + // invert for mirror + if (this->getDeadzoneMirror()) { + value = 1.f - value; + } + + // deadzone from minimum value + if (deadzone > -1 && value > -deadzone) { + value = std::min(1.f, (value + deadzone) / (1.f + deadzone)); + } else { + value = 0.f; + } + + // revert value for mirror + if (this->getDeadzoneMirror()) { + value = 1.f - value; + } + } + return value; +} \ No newline at end of file diff --git a/cfg/analog.h b/cfg/analog.h index 2a04f3f..16c8f80 100644 --- a/cfg/analog.h +++ b/cfg/analog.h @@ -3,6 +3,7 @@ #include #include #include +#include #define ANALOG_HISTORY_CNT 10 #define M_TAU (2 * M_PI) @@ -22,7 +23,7 @@ class Analog { private: std::string name; std::string device_identifier = ""; - unsigned short index = 0xFF; + unsigned short index = USHRT_MAX; float sensitivity = 1.f; float deadzone = 0.f; bool deadzone_mirror = false; @@ -30,7 +31,7 @@ private: float last_state = 0.5f; bool sensitivity_set = false; bool deadzone_set = false; - + // smoothing function bool smoothing = false; std::array vector_history; @@ -41,8 +42,22 @@ private: float previous_raw_rads = 0.f; float adjusted_rads = 0.f; + // multiplier/divisor + int multiplier = 1; + float divisor_previous_value = 0.5f; + unsigned short divisor_region = 0; + + // relative input mode + float absolute_value_for_rel_mode = 0.5f; + bool relative_mode = false; + + // circular buffer (delayed input) + int delay_buffer_depth = 0; + std::queue delay_buffer; + float calculateAngularDifference(float old_rads, float new_rads); float normalizeAngle(float rads); + float normalizeAnalogValue(float value); public: @@ -57,6 +72,8 @@ public: std::string getDisplayString(rawinput::RawInputManager* manager); float getSmoothedValue(float raw_rads); float applyAngularSensitivity(float raw_rads); + float applyMultiplier(float raw_value); + float applyDeadzone(float raw_value); inline bool isSet() { if (this->override_enabled) { @@ -72,6 +89,9 @@ public: setDeadzone(0.f); invert = false; smoothing = false; + setMultiplier(1); + setRelativeMode(false); + setDelayBufferDepth(0); } inline const std::string &getName() const { @@ -144,6 +164,16 @@ public: this->smoothing = smoothing; } + inline int getMultiplier() const { + return this->multiplier; + } + + inline void setMultiplier(int multiplier) { + this->multiplier = multiplier; + this->divisor_region = 0; + this->divisor_previous_value = 0.5f; + } + inline float getLastState() const { return this->last_state; } @@ -151,4 +181,31 @@ public: inline void setLastState(float last_state) { this->last_state = last_state; } + + inline bool isRelativeMode() const { + return this->relative_mode; + } + + inline void setRelativeMode(bool relative_mode) { + this->relative_mode = relative_mode; + this->absolute_value_for_rel_mode = 0.5f; + } + + inline float getAbsoluteValue(float relative_delta) { + this->absolute_value_for_rel_mode = + normalizeAnalogValue(this->absolute_value_for_rel_mode + relative_delta); + return this->absolute_value_for_rel_mode; + } + + inline int getDelayBufferDepth() const { + return this->delay_buffer_depth; + } + + inline void setDelayBufferDepth(int depth) { + this->delay_buffer_depth = depth; + } + + inline std::queue &getDelayBuffer() { + return this->delay_buffer; + } }; diff --git a/cfg/api.cpp b/cfg/api.cpp index 357b4a4..ace41c4 100644 --- a/cfg/api.cpp +++ b/cfg/api.cpp @@ -17,6 +17,8 @@ std::vector