mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 14:50:41 -07:00
Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d0c38956bf | |||
| 77bca2baee | |||
| 46e8c8a5a5 | |||
| 4d58e5d080 | |||
| 168084d672 | |||
| 740ed90d95 | |||
| 61c17f15b4 | |||
| 99035f312f | |||
| aafc916bb6 | |||
| c5eb1e999b | |||
| 7c15452c1e | |||
| 4bc849ccdb | |||
| 58481a035b | |||
| 66b3de8e5c | |||
| 257afe0cd3 | |||
| aafea3b1c1 | |||
| 346a159157 | |||
| 54028d8cbb | |||
| 621b702ed4 | |||
| 26ea8a1b92 | |||
| 6e7bf99af8 | |||
| df9d9d8673 | |||
| b3cee1dfcc | |||
| f40c382903 | |||
| e4cfb808bf | |||
| 61d14a16e8 | |||
| 521e87ea41 | |||
| 2b735ffd55 | |||
| 4f72b0a98b | |||
| 474f5f5203 | |||
| 205cf29aff | |||
| bf9074a76e | |||
| 44e1edb50c | |||
| 41d0dce6e9 | |||
| 598422b701 | |||
| b58a1ccfcc | |||
| 60efd643d1 | |||
| 0596eeb6fe | |||
| 3d5c64feb7 | |||
| 610984f40e | |||
| 1e271b7352 | |||
| 07c78caf01 | |||
| d153209d8a | |||
| 48186245fe | |||
| f7c274591a | |||
| d1a20e58b6 | |||
| 1e02c31524 | |||
| 66fab48a5b | |||
| ae06652148 | |||
| bd6c8d3f3c | |||
| e88abec2a6 | |||
| 6de8b529d2 | |||
| 7301cdaa6c | |||
| 6969dfcdd1 | |||
| edaf5a386f | |||
| 302f08dd57 | |||
| 68f5a614ef | |||
| 5db43031f2 | |||
| 873ade757a | |||
| 3c8dc9de32 | |||
| 4694b59cec | |||
| 4f1ada7a2f | |||
| 104a9cbffd | |||
| 45a52cff90 |
@@ -0,0 +1,32 @@
|
|||||||
|
on: [push, pull_request]
|
||||||
|
name: Continuous Integration
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fw-ci:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ./src/spice2x
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set ccache environment variables
|
||||||
|
run: |
|
||||||
|
echo "CCACHE_DIR=${{ github.workspace }}/src/spice2x/.ccache" >> $GITHUB_ENV
|
||||||
|
- name: Install ccache
|
||||||
|
uses: hendrikmuhs/ccache-action@v1.2
|
||||||
|
- name: Calculate commit SHA
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
calculatedSha=$(git rev-parse --short ${{ github.sha }})
|
||||||
|
echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
|
||||||
|
- name: Compile
|
||||||
|
run: ./build_docker.sh
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: spice2x-ci-${{ env.COMMIT_SHORT_SHA }}
|
||||||
|
path: src/spice2x/bin
|
||||||
|
if-no-files-found: error
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
.vscode/*
|
||||||
|
|
||||||
|
# JetBrains IDEs
|
||||||
|
.idea
|
||||||
|
.idea_modules
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build*
|
||||||
|
|
||||||
|
# user config
|
||||||
|
build_all.local.sh
|
||||||
|
build_docker.local.sh
|
||||||
+8
-4
@@ -30,12 +30,11 @@ Do not change the names of options, buttons binds, analogs, etc - since they are
|
|||||||
* All currently supported games / versions must continue to work.
|
* All currently supported games / versions must continue to work.
|
||||||
* Backwards compatibility must be preserved, unless there is a really good reason to break it. This includes (but not limited to): global/local config files, command line parameters, game patches, device interop (e.g., card readers), and SpiceAPI / Companion interop.
|
* Backwards compatibility must be preserved, unless there is a really good reason to break it. This includes (but not limited to): global/local config files, command line parameters, game patches, device interop (e.g., card readers), and SpiceAPI / Companion interop.
|
||||||
* Reasonable level of compatibility with the last release of original spicetools is expected. The stated goal of spice2x is to be a drop-in replacement for spicetools.
|
* Reasonable level of compatibility with the last release of original spicetools is expected. The stated goal of spice2x is to be a drop-in replacement for spicetools.
|
||||||
* Simply put, if someone has an existing install of spicetools/spice2x, copying over new version of spice2x should not result in different behavior or loss of functionality.
|
* Simply put, if someone has an existing install of spicetools/spice2x, copying over new version of spice2x should not result in vastly different behavior or major loss of functionality.
|
||||||
* Make sure you compile with the included Docker script and ensure you do not introduce **any** new compiler warnings or build breaks. The Docker script is the standard build environment, your custom Linux build environment or MSVC can be used during development, but you must validate the final build using Docker.
|
* Make sure you compile with the included Docker script and ensure you do not introduce **any** new compiler warnings or build breaks. The Docker script is the standard build environment, your custom Linux build environment or MSVC can be used during development, but you must validate the final build using Docker.
|
||||||
* Do not submit snippets of code as a "patch". Exceptions can be made for trivial changes (correct a typo, fix a single line of code...), but otherwise, a successfully compiled & fully tested patch file is required when submitting for review.
|
|
||||||
* Do not make code changes in unrelated areas; i.e., do not run code linters and auto-formatters for parts of the code that you didn't modify.
|
* Do not make code changes in unrelated areas; i.e., do not run code linters and auto-formatters for parts of the code that you didn't modify.
|
||||||
* Try to submit smaller chunks of code, instead one gigantic patch. For example, don't submit a patch for "Improve feature XYZ"; instead, submit "Change how A works to prepare for feature XYZ" "Refactor B for feature XYZ" "Add feature B to enable feature XYZ".
|
* Try to submit smaller chunks of code, instead one gigantic patch. For example, don't submit a patch for "Improve feature XYZ"; instead, submit "Change how A works to prepare for feature XYZ" "Refactor B for feature XYZ" "Add feature B to enable feature XYZ".
|
||||||
* Write to the log for anything useful - it helps immensely with debugging post-mortem. At the same time though, avoid spamming the log for something trivial.
|
* Write to the log for anything useful - it helps immensely with troubleshooting and debugging. At the same time though, avoid spamming the log for something trivial.
|
||||||
|
|
||||||
### UI text
|
### UI text
|
||||||
spice2x has a global audience; majority of the user base do not speak English as their first language.
|
spice2x has a global audience; majority of the user base do not speak English as their first language.
|
||||||
@@ -44,7 +43,7 @@ Use simple English, avoid colloquialism, and use concise language, even if it's
|
|||||||
|
|
||||||
### Using OS APIs
|
### Using OS APIs
|
||||||
|
|
||||||
Avoid making permanent changes to user's OS configuration. For example, spice should not make a call to set power profile to Maximum Performance, or switch default audio device. Making the reverse call to restore settings on game shutdown is **not** good enough; there is no guarantee that spice will gracefully shutdown, since games (or spice) can crash. This is to avoid inadvertently putting user's PC into a bad state, which can be seen as malware-like behavior.
|
Avoid making permanent changes to user's OS configuration. For example, spice must not make a call to set power profile to Maximum Performance, or switch default audio device. Making the reverse call to restore settings on game shutdown is **not** good enough; there is no guarantee that spice will gracefully shutdown, since games (or spice) can crash. This is to avoid inadvertently putting user's PC into a bad state, which can be seen as malware-like behavior.
|
||||||
|
|
||||||
Watch out for legacy OS compatibility. Currently, the minimum support floor is Windows 7. If you use any Windows API, make sure it's supported in Windows 7. If you need to use API that is not present in Windows 7, you must not directly link against it, otherwise spice will fail to launch on older OSes. Take a look at Windows 8 touch code (win8.cpp) for examples on how to discover OS APIs via pointers.
|
Watch out for legacy OS compatibility. Currently, the minimum support floor is Windows 7. If you use any Windows API, make sure it's supported in Windows 7. If you need to use API that is not present in Windows 7, you must not directly link against it, otherwise spice will fail to launch on older OSes. Take a look at Windows 8 touch code (win8.cpp) for examples on how to discover OS APIs via pointers.
|
||||||
|
|
||||||
@@ -87,4 +86,9 @@ if (conditional)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* Please give [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) a read. A few things to point out in spice codebase:
|
||||||
|
* We don't use GSL.
|
||||||
|
* Don't throw exceptions.
|
||||||
|
* Stick to smart pointers. For interfacing with C Win32 API and raw buffers, use `unique_plain_ptr`.
|
||||||
|
* Writing in C is also completely acceptable.
|
||||||
* Other than that, there are no strict rules for code formatting, but please attempt to emulate the style around the code you are modifying.
|
* Other than that, there are no strict rules for code formatting, but please attempt to emulate the style around the code you are modifying.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
> * Please do note that this is a GPL v3.0 open source project.
|
> * Please do note that this is a GPL v3.0 open source project.
|
||||||
> * Please read the [CONTRIBUTING](https://github.com/spice2x/spice2x.github.io/blob/main/CONTRIBUTING.md) guide.
|
> * Please read the [CONTRIBUTING](https://github.com/spice2x/spice2x.github.io/blob/main/CONTRIBUTING.md) guide.
|
||||||
> * Maintainers reserve the right to reject or modify your submission without reason.
|
> * Maintainers reserve the right to reject or modify your submission without reason.
|
||||||
|
> * No new compiler warnings must be introduced. Check the CI build results.
|
||||||
>
|
>
|
||||||
> Feel free to remove this section after you have read it.
|
> Feel free to remove this section after you have read it.
|
||||||
|
|
||||||
@@ -12,8 +13,5 @@
|
|||||||
## Description of change
|
## Description of change
|
||||||
*what does this code do?*
|
*what does this code do?*
|
||||||
|
|
||||||
## Compiling
|
|
||||||
*you must be able to compile with the included Docker script with zero compiler warnings*
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
*how was the code tested?*
|
*how was the code tested?*
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ bin/**
|
|||||||
dist/**
|
dist/**
|
||||||
docker/**
|
docker/**
|
||||||
cmake-build*
|
cmake-build*
|
||||||
|
.ccache/**
|
||||||
@@ -16,4 +16,6 @@ build_docker.local.sh
|
|||||||
bin/*
|
bin/*
|
||||||
dist/*
|
dist/*
|
||||||
|
|
||||||
external/cv2pdb/*
|
external/cv2pdb/*
|
||||||
|
|
||||||
|
.ccache/*
|
||||||
+34
-12
@@ -124,8 +124,8 @@ else()
|
|||||||
# https://github.com/msys2/MINGW-packages/pull/6880
|
# 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,
|
# 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
|
# 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_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_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,--enable-stdcall-fixup")
|
||||||
|
|
||||||
# set visibility to hidden
|
# set visibility to hidden
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden")
|
||||||
@@ -160,8 +160,8 @@ else()
|
|||||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections")
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections")
|
||||||
|
|
||||||
# linker fix to load below 4GB
|
# 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_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_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,--enable-stdcall-fixup")
|
||||||
|
|
||||||
# set visibility to hidden
|
# set visibility to hidden
|
||||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fvisibility=hidden")
|
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fvisibility=hidden")
|
||||||
@@ -184,8 +184,8 @@ else()
|
|||||||
set(CMAKE_CXX_FLAGS_DEBUG "-gdwarf")
|
set(CMAKE_CXX_FLAGS_DEBUG "-gdwarf")
|
||||||
|
|
||||||
# linker fix to load below 4GB
|
# linker fix to load below 4GB
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
|
||||||
|
|
||||||
# enable debug symbols on level 3 and keep frame pointers
|
# 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_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer")
|
||||||
@@ -211,14 +211,12 @@ add_compile_definitions(
|
|||||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DACIOEMU_LOG")
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DACIOEMU_LOG")
|
||||||
|
|
||||||
# add project directory to include path so we can comfortably import
|
# 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 external libraries
|
||||||
add_subdirectory(external/fmt EXCLUDE_FROM_ALL)
|
add_subdirectory(external/fmt EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/discord-rpc EXCLUDE_FROM_ALL)
|
add_subdirectory(external/discord-rpc EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/hash-library EXCLUDE_FROM_ALL)
|
add_subdirectory(external/hash-library EXCLUDE_FROM_ALL)
|
||||||
add_compile_definitions(IMGUI_DISABLE_DEMO_WINDOWS)
|
|
||||||
add_compile_definitions(IMGUI_DISABLE_DEBUG_TOOLS)
|
|
||||||
add_subdirectory(external/imgui EXCLUDE_FROM_ALL)
|
add_subdirectory(external/imgui EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/minhook EXCLUDE_FROM_ALL)
|
add_subdirectory(external/minhook EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/cpu_features EXCLUDE_FROM_ALL)
|
add_subdirectory(external/cpu_features EXCLUDE_FROM_ALL)
|
||||||
@@ -516,7 +514,6 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
overlay/overlay.cpp
|
overlay/overlay.cpp
|
||||||
overlay/window.cpp
|
overlay/window.cpp
|
||||||
overlay/imgui/extensions.cpp
|
overlay/imgui/extensions.cpp
|
||||||
overlay/imgui/impl_dx9.cpp
|
|
||||||
overlay/imgui/impl_spice.cpp
|
overlay/imgui/impl_spice.cpp
|
||||||
overlay/imgui/impl_sw.cpp
|
overlay/imgui/impl_sw.cpp
|
||||||
overlay/windows/acio_status_buffers.cpp
|
overlay/windows/acio_status_buffers.cpp
|
||||||
@@ -610,6 +607,22 @@ IF(NOT MSVC)
|
|||||||
set_target_properties(spicetools_spice PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
set_target_properties(spicetools_spice PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
||||||
endif()
|
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
|
# spice64.exe
|
||||||
#############
|
#############
|
||||||
|
|
||||||
@@ -629,7 +642,6 @@ IF(NOT MSVC)
|
|||||||
set_target_properties(spicetools_spice64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
set_target_properties(spicetools_spice64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# spicecfg.exe
|
# spicecfg.exe
|
||||||
##############
|
##############
|
||||||
|
|
||||||
@@ -726,6 +738,16 @@ if(NOT MSVC)
|
|||||||
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# cpusbxpkm.dll (32 bit)
|
||||||
|
set(SOURCE_FILES stubs/cpusbxpkm.cpp)
|
||||||
|
add_library(spicetools_stubs_cpusbxpkm SHARED ${SOURCE_FILES} stubs/cpusbxpkm.def)
|
||||||
|
set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES PREFIX "")
|
||||||
|
set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES OUTPUT_NAME "cpusbxpkm")
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
||||||
|
endif()
|
||||||
|
|
||||||
# output directories
|
# output directories
|
||||||
####################
|
####################
|
||||||
|
|
||||||
@@ -735,7 +757,7 @@ set_target_properties(spicetools_cfg
|
|||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools")
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools")
|
||||||
|
|
||||||
# output 32bit
|
# 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 spicetools_stubs_cpusbxpkm
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive32"
|
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive32"
|
||||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32"
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32"
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
FROM spicetools/deps
|
FROM spicetools/deps
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
RUN chown user:user /src
|
|
||||||
USER user
|
COPY --from=gitroot . /src/.git
|
||||||
COPY --chown=user:user --from=gitroot . /src/.git
|
COPY . /src/src/spice2x
|
||||||
COPY --chown=user:user . /src/src/spice2x
|
|
||||||
WORKDIR /src/src/spice2x
|
WORKDIR /src/src/spice2x
|
||||||
CMD ["./build_all.sh"]
|
ENTRYPOINT ["./build_all.sh"]
|
||||||
|
|||||||
@@ -247,6 +247,25 @@ which also means that your hex edits are applicable directly.
|
|||||||
- sets the contents of the 16 segment display and disables writes from game
|
- sets the contents of the 16 segment display and disables writes from game
|
||||||
- ticker_reset()
|
- ticker_reset()
|
||||||
- re-enables writes from game
|
- re-enables writes from game
|
||||||
|
- tapeled_get(name: str, ...)
|
||||||
|
- returns a list containing a dict of the current tape LED states. The dict keys are:
|
||||||
|
- `Stage Left`
|
||||||
|
- `Stage Right`
|
||||||
|
- `Cabinet Left`
|
||||||
|
- `Cabinet Right`
|
||||||
|
- `Control Panel Under`
|
||||||
|
- `Ceiling Left`
|
||||||
|
- `Title Left`
|
||||||
|
- `Title Right`
|
||||||
|
- `Ceiling Right`
|
||||||
|
- `Touch Panel Left`
|
||||||
|
- `Touch Panel Right`
|
||||||
|
- `Side Panel Left Inner`
|
||||||
|
- `Side Panel Left Outer`
|
||||||
|
- `Side Panel Left`
|
||||||
|
- `Side Panel Right Outer`
|
||||||
|
- `Side Panel Right Inner`
|
||||||
|
- `Side Panel Right`
|
||||||
|
|
||||||
#### LCD
|
#### LCD
|
||||||
- info()
|
- info()
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
namespace acio {
|
namespace acio {
|
||||||
HINSTANCE DLL_INSTANCE = nullptr;
|
HINSTANCE DLL_INSTANCE = nullptr;
|
||||||
std::vector<acio::ACIOModule *> MODULES;
|
std::vector<acio::ACIOModule *> MODULES;
|
||||||
|
std::atomic<bool> IO_INIT_IN_PROGRESS = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -58,6 +59,7 @@ static inline acio::HookMode get_hookmode() {
|
|||||||
|
|
||||||
void acio::attach() {
|
void acio::attach() {
|
||||||
log_info("acio", "SpiceTools ACIO");
|
log_info("acio", "SpiceTools ACIO");
|
||||||
|
IO_INIT_IN_PROGRESS = true;
|
||||||
|
|
||||||
// load settings and instance
|
// load settings and instance
|
||||||
acio::DLL_INSTANCE = LoadLibraryA("libacio.dll");
|
acio::DLL_INSTANCE = LoadLibraryA("libacio.dll");
|
||||||
@@ -111,6 +113,8 @@ void acio::attach() {
|
|||||||
for (auto &module : MODULES) {
|
for (auto &module : MODULES) {
|
||||||
module->attach();
|
module->attach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IO_INIT_IN_PROGRESS = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void acio::attach_icca() {
|
void acio::attach_icca() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -11,6 +12,7 @@ namespace acio {
|
|||||||
// globals
|
// globals
|
||||||
extern HINSTANCE DLL_INSTANCE;
|
extern HINSTANCE DLL_INSTANCE;
|
||||||
extern std::vector<acio::ACIOModule *> MODULES;
|
extern std::vector<acio::ACIOModule *> MODULES;
|
||||||
|
extern std::atomic<bool> IO_INIT_IN_PROGRESS;
|
||||||
|
|
||||||
void attach();
|
void attach();
|
||||||
void attach_icca();
|
void attach_icca();
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_off() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f);
|
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;
|
return 1;
|
||||||
@@ -44,6 +49,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_on() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f);
|
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;
|
return 1;
|
||||||
@@ -55,6 +65,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_off() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f);
|
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;
|
return 1;
|
||||||
@@ -66,6 +81,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_on() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f);
|
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;
|
return 1;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace acio2emu {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IOBHandle::IOBHandle(std::wstring device) : device_(device) {
|
IOBHandle::IOBHandle(LPCWSTR device) : device_(device) {
|
||||||
nodes_[0] = std::make_unique<MasterNode>(this);
|
nodes_[0] = std::make_unique<MasterNode>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace acio2emu {
|
|||||||
void forward_packet_(const Packet &packet);
|
void forward_packet_(const Packet &packet);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IOBHandle(std::wstring device);
|
IOBHandle(LPCWSTR device);
|
||||||
|
|
||||||
bool register_node(std::unique_ptr<Node> node);
|
bool register_node(std::unique_ptr<Node> node);
|
||||||
int number_of_nodes() const;
|
int number_of_nodes() const;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ using namespace rapidjson;
|
|||||||
|
|
||||||
namespace api::modules {
|
namespace api::modules {
|
||||||
|
|
||||||
|
std::optional<uint32_t> CAPTURE_QUALITY;
|
||||||
|
std::optional<uint32_t> CAPTURE_DIVIDE;
|
||||||
|
|
||||||
static thread_local std::vector<uint8_t> CAPTURE_BUFFER;
|
static thread_local std::vector<uint8_t> CAPTURE_BUFFER;
|
||||||
|
|
||||||
Capture::Capture() : Module("capture") {
|
Capture::Capture() : Module("capture") {
|
||||||
@@ -44,12 +47,21 @@ namespace api::modules {
|
|||||||
int screen = 0;
|
int screen = 0;
|
||||||
int quality = 70;
|
int quality = 70;
|
||||||
int divide = 1;
|
int divide = 1;
|
||||||
if (req.params.Size() > 0 && req.params[0].IsUint())
|
if (req.params.Size() > 0 && req.params[0].IsUint()) {
|
||||||
screen = req.params[0].GetUint();
|
screen = req.params[0].GetUint();
|
||||||
if (req.params.Size() > 1 && req.params[1].IsUint())
|
}
|
||||||
|
|
||||||
|
if (CAPTURE_QUALITY.has_value()) {
|
||||||
|
quality = CAPTURE_QUALITY.value();
|
||||||
|
} else if (req.params.Size() > 1 && req.params[1].IsUint()) {
|
||||||
quality = req.params[1].GetUint();
|
quality = req.params[1].GetUint();
|
||||||
if (req.params.Size() > 2 && req.params[2].IsUint())
|
}
|
||||||
|
|
||||||
|
if (CAPTURE_DIVIDE.has_value()) {
|
||||||
|
divide = CAPTURE_DIVIDE.value();
|
||||||
|
} else if (req.params.Size() > 2 && req.params[2].IsUint()) {
|
||||||
divide = req.params[2].GetUint();
|
divide = req.params[2].GetUint();
|
||||||
|
}
|
||||||
|
|
||||||
// receive JPEG data
|
// receive JPEG data
|
||||||
uint64_t timestamp = 0;
|
uint64_t timestamp = 0;
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "api/module.h"
|
#include "api/module.h"
|
||||||
#include "api/request.h"
|
#include "api/request.h"
|
||||||
|
|
||||||
namespace api::modules {
|
namespace api::modules {
|
||||||
|
|
||||||
|
extern std::optional<uint32_t> CAPTURE_QUALITY;
|
||||||
|
extern std::optional<uint32_t> CAPTURE_DIVIDE;
|
||||||
|
|
||||||
class Capture : public Module {
|
class Capture : public Module {
|
||||||
public:
|
public:
|
||||||
Capture();
|
Capture();
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
#include "iidx.h"
|
#include "iidx.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
|
||||||
#include "games/iidx/iidx.h"
|
|
||||||
#include "external/rapidjson/document.h"
|
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
|
||||||
namespace api::modules {
|
namespace api::modules {
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
@@ -17,6 +13,11 @@ namespace api::modules {
|
|||||||
functions["ticker_get"] = std::bind(&IIDX::ticker_get, this, _1, _2);
|
functions["ticker_get"] = std::bind(&IIDX::ticker_get, this, _1, _2);
|
||||||
functions["ticker_set"] = std::bind(&IIDX::ticker_set, this, _1, _2);
|
functions["ticker_set"] = std::bind(&IIDX::ticker_set, this, _1, _2);
|
||||||
functions["ticker_reset"] = std::bind(&IIDX::ticker_reset, this, _1, _2);
|
functions["ticker_reset"] = std::bind(&IIDX::ticker_reset, this, _1, _2);
|
||||||
|
functions["tapeled_get"] = std::bind(&IIDX::tapeled_get, this, _1, _2);
|
||||||
|
|
||||||
|
for (auto &light : games::iidx::TAPELED_MAPPING) {
|
||||||
|
this->lights_by_names.emplace(light.lightName, light);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,4 +70,51 @@ namespace api::modules {
|
|||||||
// disable read only
|
// disable read only
|
||||||
games::iidx::IIDXIO_LED_TICKER_READONLY = false;
|
games::iidx::IIDXIO_LED_TICKER_READONLY = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tapeled_get()
|
||||||
|
* tapeled_get(name: str, ...)
|
||||||
|
*/
|
||||||
|
void IIDX::tapeled_get(Request &req, Response &res) {
|
||||||
|
Value response_object(kObjectType);
|
||||||
|
|
||||||
|
// all tape leds
|
||||||
|
if (req.params.Size() == 0) {
|
||||||
|
// Iterate through each device and dump its lights data into the response
|
||||||
|
for (const auto &mapping : games::iidx::TAPELED_MAPPING) {
|
||||||
|
copy_tapeled_data(res, response_object, mapping);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 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 (const auto &it = lights_by_names.find(name); it != lights_by_names.end()) {
|
||||||
|
const auto mapping = it->second.get();
|
||||||
|
copy_tapeled_data(res, response_object, mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.add_data(response_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IIDX::copy_tapeled_data(Response &res, Value &response_object, const tapeledutils::tape_led &mapping) {
|
||||||
|
// Create an array for the light state
|
||||||
|
Value light_state(kArrayType);
|
||||||
|
light_state.Reserve(mapping.data.capacity() * 3, res.doc()->GetAllocator());
|
||||||
|
for (const auto [r, g, b] : mapping.data) {
|
||||||
|
light_state.PushBack(r, res.doc()->GetAllocator());
|
||||||
|
light_state.PushBack(g, res.doc()->GetAllocator());
|
||||||
|
light_state.PushBack(b, res.doc()->GetAllocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't use StringRef here, turns some strings partially into null bytes for some reason
|
||||||
|
Value light_name(mapping.lightName.c_str(), res.doc()->GetAllocator());
|
||||||
|
response_object.AddMember(light_name, light_state, res.doc()->GetAllocator());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "api/module.h"
|
#include "api/module.h"
|
||||||
#include "api/request.h"
|
#include "api/request.h"
|
||||||
|
#include "games/iidx/iidx.h"
|
||||||
|
|
||||||
namespace api::modules {
|
namespace api::modules {
|
||||||
|
|
||||||
@@ -10,10 +11,16 @@ namespace api::modules {
|
|||||||
IIDX();
|
IIDX();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// state
|
||||||
|
robin_hood::unordered_map<std::string, std::reference_wrapper<tapeledutils::tape_led>> lights_by_names;
|
||||||
|
|
||||||
// function definitions
|
// function definitions
|
||||||
void ticker_get(Request &req, Response &res);
|
void ticker_get(Request &req, Response &res);
|
||||||
void ticker_set(Request &req, Response &res);
|
void ticker_set(Request &req, Response &res);
|
||||||
void ticker_reset(Request &req, Response &res);
|
void ticker_reset(Request &req, Response &res);
|
||||||
|
void tapeled_get(Request &req, Response &res);
|
||||||
|
|
||||||
|
// helper
|
||||||
|
void copy_tapeled_data(Response &res, rapidjson::Value &response_object, const tapeledutils::tape_led &mapping);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,3 +16,13 @@ def iidx_ticker_set(con: Connection, text: str):
|
|||||||
def iidx_ticker_reset(con: Connection):
|
def iidx_ticker_reset(con: Connection):
|
||||||
req = Request("iidx", "ticker_reset")
|
req = Request("iidx", "ticker_reset")
|
||||||
con.request(req)
|
con.request(req)
|
||||||
|
|
||||||
|
|
||||||
|
def iidx_tapeled_get(con: Connection, *light_names):
|
||||||
|
req = Request("iidx", "tapeled_get")
|
||||||
|
|
||||||
|
for light_name in light_names:
|
||||||
|
req.add_param(light_name)
|
||||||
|
|
||||||
|
res = con.request(req)
|
||||||
|
return res.get_data()
|
||||||
|
|||||||
@@ -76,18 +76,23 @@ namespace avs {
|
|||||||
const auto dll_path_s = dll_path.string();
|
const auto dll_path_s = dll_path.string();
|
||||||
log_info("avs-game", "DLL path: {}", dll_path_s.c_str());
|
log_info("avs-game", "DLL path: {}", dll_path_s.c_str());
|
||||||
|
|
||||||
if (MAX_PATH <= (dll_path_s.length() + 64)) {
|
// MAX_PATH is 260
|
||||||
|
if (130 <= dll_path_s.length()) {
|
||||||
log_warning(
|
log_warning(
|
||||||
"avs-game",
|
"avs-game",
|
||||||
"PATH TOO LONG WARNING\n\n\n"
|
"PATH TOO LONG WARNING\n\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"
|
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
||||||
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
"'{}' has a length of {}\n"
|
"The path '{}'\n"
|
||||||
"Most of these games will behave unexpectedly when the path is too long,\n"
|
" has a length of {}\n"
|
||||||
"often resulting in random crashes. Move the game contents to a directory\n"
|
"Most of these games may behave unexpectedly when the path is too\n"
|
||||||
"with shorter path.\n"
|
"long, often resulting in random crashes. Move the game contents to\n"
|
||||||
"-------------------------------------------------------------------\n\n\n",
|
"a directory with shorter path.\n"
|
||||||
|
"-------------------------------------------------------------------\n\n",
|
||||||
dll_path_s, dll_path_s.length());
|
dll_path_s, dll_path_s.length());
|
||||||
}
|
}
|
||||||
if (!fileutils::file_exists(dll_path)) {
|
if (!fileutils::file_exists(dll_path)) {
|
||||||
|
|||||||
Regular → Executable
+61
-27
@@ -19,6 +19,25 @@ function trap_error_exit {
|
|||||||
trap trap_error_dbg DEBUG
|
trap trap_error_dbg DEBUG
|
||||||
trap trap_error_exit EXIT
|
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
|
# settings
|
||||||
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
||||||
GIT_HEAD=$(git rev-parse HEAD || echo "none")
|
GIT_HEAD=$(git rev-parse HEAD || echo "none")
|
||||||
@@ -41,7 +60,7 @@ DIST_ENABLE=1
|
|||||||
DIST_FOLDER="./dist"
|
DIST_FOLDER="./dist"
|
||||||
DIST_NAME="spice2x-$(date +%y)-$(date +%m)-$(date +%d).zip"
|
DIST_NAME="spice2x-$(date +%y)-$(date +%m)-$(date +%d).zip"
|
||||||
DIST_COMMENT=${DIST_NAME}$'\n'"$GIT_BRANCH - $GIT_HEAD"$'\nThank you for playing.'
|
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_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice spicetools_spice_laa spicetools_stubs_cpusbxpkm"
|
||||||
TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvEncodeAPI64 spicetools_stubs_nvcuvid spicetools_stubs_nvcuda spicetools_spice64"
|
TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvEncodeAPI64 spicetools_stubs_nvcuvid spicetools_stubs_nvcuda spicetools_spice64"
|
||||||
|
|
||||||
# determine build type
|
# determine build type
|
||||||
@@ -57,7 +76,7 @@ then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# determine number of cores
|
# determine number of cores
|
||||||
CORES=$(awk '/^processor\t/ {cores[$NF]++} END {print length(cores)}' /proc/cpuinfo)
|
CORES=$(nproc)
|
||||||
|
|
||||||
# print information
|
# print information
|
||||||
echo ""
|
echo ""
|
||||||
@@ -74,34 +93,45 @@ echo "Build Type: $BUILD_TYPE"
|
|||||||
echo "Cores: $CORES"
|
echo "Cores: $CORES"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# 32 bit
|
if ((IGNORE_CACHE > 0))
|
||||||
echo "Building 32bit targets..."
|
|
||||||
echo "========================="
|
|
||||||
if ((CLEAN_BUILD > 0))
|
|
||||||
then
|
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
|
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
|
time (
|
||||||
echo ""
|
# 32 bit
|
||||||
echo "Building 64bit targets..."
|
echo "Building 32bit targets..."
|
||||||
echo "========================="
|
echo "========================="
|
||||||
if ((CLEAN_BUILD > 0))
|
if ((CLEAN_BUILD > 0))
|
||||||
then
|
then
|
||||||
rm -rf ${BUILDDIR_64}
|
rm -rf ${BUILDDIR_32}
|
||||||
fi
|
fi
|
||||||
mkdir -p ${BUILDDIR_64}
|
mkdir -p ${BUILDDIR_32}
|
||||||
pushd ${BUILDDIR_64} > /dev/null
|
pushd ${BUILDDIR_32} > /dev/null
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && make -j ${CORES} ${TARGETS_64}
|
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && ninja ${TARGETS_32}
|
||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
|
|
||||||
echo ""
|
# 64 bit
|
||||||
echo "Compilation process done :)"
|
echo ""
|
||||||
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
|
# generate PDBs
|
||||||
if false # ((DEBUG > 0))
|
if false # ((DEBUG > 0))
|
||||||
@@ -151,8 +181,9 @@ fi
|
|||||||
echo "Copy files to output directory..."
|
echo "Copy files to output directory..."
|
||||||
rm -rf ${OUTDIR}
|
rm -rf ${OUTDIR}
|
||||||
mkdir -p ${OUTDIR}
|
mkdir -p ${OUTDIR}
|
||||||
#mkdir -p ${OUTDIR}/stubs/32
|
mkdir -p ${OUTDIR}/stubs/32
|
||||||
mkdir -p ${OUTDIR}/stubs/64
|
mkdir -p ${OUTDIR}/stubs/64
|
||||||
|
mkdir -p ${OUTDIR}/extras/largeaddressaware
|
||||||
if false # ((DEBUG > 0))
|
if false # ((DEBUG > 0))
|
||||||
then
|
then
|
||||||
# debug files
|
# debug files
|
||||||
@@ -169,10 +200,12 @@ then
|
|||||||
#cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.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/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
#cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
|
#cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
|
#cp ${BUILDDIR_32}/spicetools/32/cpusbxpkm.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||||
else
|
else
|
||||||
# release files
|
# release files
|
||||||
cp ${BUILDDIR_32}/spicetools/spicecfg.exe ${OUTDIR} 2>/dev/null
|
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.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/kbt.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||||
#cp ${BUILDDIR_32}/spicetools/32/kld.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/spice64.exe ${OUTDIR} 2>/dev/null
|
||||||
@@ -181,6 +214,7 @@ else
|
|||||||
cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.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/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
|
cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
|
cp ${BUILDDIR_32}/spicetools/32/cpusbxpkm.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# pack source files to output directory
|
# pack source files to output directory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
docker build --pull external/docker -t spicetools/deps
|
docker build --pull external/docker -t spicetools/deps
|
||||||
docker build --build-context gitroot=%cd%/../../.git . -t spicetools/spice --no-cache
|
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 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 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\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
|
@REM external\cv2pdb\cv2pdb.exe bin\spice2x\spice.exe bin\spice2x\spice-pdb.exe bin\spice2x\spice-pdb.pdb
|
||||||
|
|||||||
Regular → Executable
+2
-4
@@ -1,6 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
export DOCKER_BUILDKIT=0
|
|
||||||
|
|
||||||
docker build --pull $PWD/external/docker -t spicetools/deps --platform linux/x86_64
|
docker build --pull $PWD/external/docker -t spicetools/deps --platform linux/x86_64
|
||||||
docker build --build-context gitroot=$PWD/../../.git . -t spicetools/spice:latest --no-cache
|
docker build --build-context gitroot=$PWD/../../.git . -t spicetools/spice:latest
|
||||||
docker run --rm -it -v $PWD/dist:/src/src/spice2x/dist -v $PWD/bin:/src/src/spice2x/bin spicetools/spice
|
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 "$@"
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
del /s /q .ccache
|
||||||
|
call build_docker.bat
|
||||||
+34
-4
@@ -1,5 +1,8 @@
|
|||||||
#include "api.h"
|
#include "api.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "launcher/superexit.h"
|
||||||
#include "rawinput/rawinput.h"
|
#include "rawinput/rawinput.h"
|
||||||
#include "rawinput/piuio.h"
|
#include "rawinput/piuio.h"
|
||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
@@ -64,18 +67,29 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
|
|||||||
auto current_button = &_button;
|
auto current_button = &_button;
|
||||||
auto alternatives = check_alts ? ¤t_button->getAlternatives() : nullptr;
|
auto alternatives = check_alts ? ¤t_button->getAlternatives() : nullptr;
|
||||||
unsigned int button_count = 0;
|
unsigned int button_count = 0;
|
||||||
|
std::optional<bool> window_has_focus;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
// naive behavior
|
// naive behavior
|
||||||
if (current_button->isNaive()) {
|
if (current_button->isNaive()) {
|
||||||
|
GameAPI::Buttons::State state;
|
||||||
|
auto vkey = current_button->getVKey();
|
||||||
|
|
||||||
|
// check for focus
|
||||||
|
if (vkey != INVALID_VKEY && rawinput::NAIVE_REQUIRE_FOCUS) {
|
||||||
|
if (!window_has_focus.has_value()) {
|
||||||
|
window_has_focus = superexit::has_focus();
|
||||||
|
}
|
||||||
|
if (!window_has_focus.value()) {
|
||||||
|
vkey = INVALID_VKEY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// read
|
// read
|
||||||
auto vkey = current_button->getVKey();
|
if (vkey == INVALID_VKEY) {
|
||||||
GameAPI::Buttons::State state;
|
|
||||||
if (vkey == 0xFF) {
|
|
||||||
state = BUTTON_NOT_PRESSED;
|
state = BUTTON_NOT_PRESSED;
|
||||||
} else {
|
} else {
|
||||||
state = (GetAsyncKeyState(current_button->getVKey()) & 0x8000) ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = (GetAsyncKeyState(vkey) & 0x8000) ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// invert
|
// invert
|
||||||
@@ -106,6 +120,16 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
|
|||||||
auto &devid = current_button->getDeviceIdentifier();
|
auto &devid = current_button->getDeviceIdentifier();
|
||||||
auto device = manager->devices_get(devid, false); // TODO: fix to update only
|
auto device = manager->devices_get(devid, false); // TODO: fix to update only
|
||||||
|
|
||||||
|
// check for focus
|
||||||
|
if (device && rawinput::RAWINPUT_REQUIRE_FOCUS) {
|
||||||
|
if (!window_has_focus.has_value()) {
|
||||||
|
window_has_focus = superexit::has_focus();
|
||||||
|
}
|
||||||
|
if (!window_has_focus.value()) {
|
||||||
|
device = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get state if device was marked as updated
|
// get state if device was marked as updated
|
||||||
GameAPI::Buttons::State state = current_button->getLastState();
|
GameAPI::Buttons::State state = current_button->getLastState();
|
||||||
double *last_up = nullptr;
|
double *last_up = nullptr;
|
||||||
@@ -571,6 +595,12 @@ float GameAPI::Analogs::getState(rawinput::Device *device, Analog &analog) {
|
|||||||
switch (device->type) {
|
switch (device->type) {
|
||||||
case rawinput::MOUSE: {
|
case rawinput::MOUSE: {
|
||||||
|
|
||||||
|
// check for focus
|
||||||
|
if (rawinput::NAIVE_REQUIRE_FOCUS && !superexit::has_focus()) {
|
||||||
|
value = analog.getLastState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// get mouse position
|
// get mouse position
|
||||||
auto mouse = device->mouseInfo;
|
auto mouse = device->mouseInfo;
|
||||||
long pos;
|
long pos;
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ std::string Button::getDisplayString(rawinput::RawInputManager* manager) {
|
|||||||
std::string vKeyString = fmt::format("{:#x}", vKey);
|
std::string vKeyString = fmt::format("{:#x}", vKey);
|
||||||
|
|
||||||
// device must be existing
|
// device must be existing
|
||||||
if (this->device_identifier.empty() && vKey == 0xFF) {
|
if (this->device_identifier.empty() && vKey == INVALID_VKEY) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,14 @@ enum ButtonAnalogType {
|
|||||||
|
|
||||||
extern const char *ButtonAnalogTypeStr[];
|
extern const char *ButtonAnalogTypeStr[];
|
||||||
|
|
||||||
|
constexpr unsigned short INVALID_VKEY = UINT16_C(0xFF);
|
||||||
|
|
||||||
class Button {
|
class Button {
|
||||||
private:
|
private:
|
||||||
std::vector<Button> alternatives;
|
std::vector<Button> alternatives;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string device_identifier = "";
|
std::string device_identifier = "";
|
||||||
unsigned short vKey = 0xFF;
|
unsigned short vKey = INVALID_VKEY;
|
||||||
ButtonAnalogType analog_type = BAT_NONE;
|
ButtonAnalogType analog_type = BAT_NONE;
|
||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
@@ -68,12 +70,12 @@ public:
|
|||||||
if (this->override_enabled) {
|
if (this->override_enabled) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this->vKey != 0xFF) {
|
if (this->vKey != INVALID_VKEY) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &alternative : this->alternatives) {
|
for (auto &alternative : this->alternatives) {
|
||||||
if (alternative.vKey != 0xFF) {
|
if (alternative.vKey != INVALID_VKEY) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +84,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void clearBindings() {
|
inline void clearBindings() {
|
||||||
vKey = 0xFF;
|
vKey = INVALID_VKEY;
|
||||||
alternatives.clear();
|
alternatives.clear();
|
||||||
device_identifier = "";
|
device_identifier = "";
|
||||||
analog_type = BAT_NONE;
|
analog_type = BAT_NONE;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public:
|
|||||||
std::string value;
|
std::string value;
|
||||||
std::vector<Option> alternatives;
|
std::vector<Option> alternatives;
|
||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
|
bool conflicting = false;
|
||||||
|
|
||||||
explicit Option(OptionDefinition definition, std::string value = "") :
|
explicit Option(OptionDefinition definition, std::string value = "") :
|
||||||
definition(std::move(definition)), value(std::move(value)) {
|
definition(std::move(definition)), value(std::move(value)) {
|
||||||
|
|||||||
@@ -15,12 +15,18 @@ namespace cfg {
|
|||||||
std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
|
std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
|
||||||
|
|
||||||
ScreenResize::ScreenResize() {
|
ScreenResize::ScreenResize() {
|
||||||
|
bool file_exists = false;
|
||||||
if (SCREEN_RESIZE_CFG_PATH_OVERRIDE.has_value()) {
|
if (SCREEN_RESIZE_CFG_PATH_OVERRIDE.has_value()) {
|
||||||
this->config_path = SCREEN_RESIZE_CFG_PATH_OVERRIDE.value();
|
this->config_path = SCREEN_RESIZE_CFG_PATH_OVERRIDE.value();
|
||||||
|
if (fileutils::file_exists(this->config_path)) {
|
||||||
|
log_info("ScreenResize", "loading config from: {}", this->config_path.string());
|
||||||
|
file_exists = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this->config_path = std::filesystem::path(_wgetenv(L"APPDATA")) / L"spicetools_screen_resize.json";
|
this->config_path =
|
||||||
|
fileutils::get_config_file_path("ScreenResize", "spicetools_screen_resize.json", &file_exists);
|
||||||
}
|
}
|
||||||
if (fileutils::file_exists(this->config_path)) {
|
if (file_exists) {
|
||||||
this->config_load();
|
this->config_load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,12 +35,6 @@ namespace cfg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScreenResize::config_load() {
|
void ScreenResize::config_load() {
|
||||||
if (SCREEN_RESIZE_CFG_PATH_OVERRIDE.has_value()) {
|
|
||||||
log_info("ScreenResize", "loading custom config: {}", this->config_path.string());
|
|
||||||
} else {
|
|
||||||
log_info("ScreenResize", "loading global config from APPDATA");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string config = fileutils::text_read(this->config_path);
|
std::string config = fileutils::text_read(this->config_path);
|
||||||
if (config.empty()) {
|
if (config.empty()) {
|
||||||
log_info("ScreenResize", "config is empty");
|
log_info("ScreenResize", "config is empty");
|
||||||
@@ -81,16 +81,12 @@ namespace cfg {
|
|||||||
load_bool_value(doc, root + "enable_linear_filter", this->enable_linear_filter);
|
load_bool_value(doc, root + "enable_linear_filter", this->enable_linear_filter);
|
||||||
for (size_t i = 0; i < std::size(this->scene_settings); i++) {
|
for (size_t i = 0; i < std::size(this->scene_settings); i++) {
|
||||||
auto& scene = this->scene_settings[i];
|
auto& scene = this->scene_settings[i];
|
||||||
std::string prefix = "";
|
const std::string prefix = fmt::format("scenes/{}/", i);
|
||||||
if (0 < i) {
|
|
||||||
prefix += fmt::format("scenes/{}/", i-1);
|
|
||||||
}
|
|
||||||
load_int_value(doc, root + prefix + "offset_x", scene.offset_x);
|
load_int_value(doc, root + prefix + "offset_x", scene.offset_x);
|
||||||
load_int_value(doc, root + prefix + "offset_y", scene.offset_y);
|
load_int_value(doc, root + prefix + "offset_y", scene.offset_y);
|
||||||
load_float_value(doc, root + prefix + "scale_x", scene.scale_x);
|
load_float_value(doc, root + prefix + "scale_x", scene.scale_x);
|
||||||
load_float_value(doc, root + prefix + "scale_y", scene.scale_y);
|
load_float_value(doc, root + prefix + "scale_y", scene.scale_y);
|
||||||
load_bool_value(doc, root + prefix + "keep_aspect_ratio", scene.keep_aspect_ratio);
|
load_bool_value(doc, root + prefix + "keep_aspect_ratio", scene.keep_aspect_ratio);
|
||||||
load_bool_value(doc, root + prefix + "centered", scene.centered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// windowed settings are always under game settings
|
// windowed settings are always under game settings
|
||||||
@@ -174,8 +170,6 @@ namespace cfg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScreenResize::config_save() {
|
void ScreenResize::config_save() {
|
||||||
log_info("ScreenResize", "saving config: {}", this->config_path.string());
|
|
||||||
|
|
||||||
rapidjson::Document doc;
|
rapidjson::Document doc;
|
||||||
std::string config = fileutils::text_read(this->config_path);
|
std::string config = fileutils::text_read(this->config_path);
|
||||||
if (!config.empty()) {
|
if (!config.empty()) {
|
||||||
@@ -201,16 +195,12 @@ namespace cfg {
|
|||||||
rapidjson::Pointer(root + "enable_linear_filter").Set(doc, this->enable_linear_filter);
|
rapidjson::Pointer(root + "enable_linear_filter").Set(doc, this->enable_linear_filter);
|
||||||
for (size_t i = 0; i < std::size(this->scene_settings); i++) {
|
for (size_t i = 0; i < std::size(this->scene_settings); i++) {
|
||||||
auto& scene = this->scene_settings[i];
|
auto& scene = this->scene_settings[i];
|
||||||
std::string prefix = "";
|
const std::string prefix = fmt::format("scenes/{}/", i);
|
||||||
if (0 < i) {
|
|
||||||
prefix += fmt::format("scenes/{}/", i-1);
|
|
||||||
}
|
|
||||||
rapidjson::Pointer(root + prefix + "offset_x").Set(doc, scene.offset_x);
|
rapidjson::Pointer(root + prefix + "offset_x").Set(doc, scene.offset_x);
|
||||||
rapidjson::Pointer(root + prefix + "offset_y").Set(doc, scene.offset_y);
|
rapidjson::Pointer(root + prefix + "offset_y").Set(doc, scene.offset_y);
|
||||||
rapidjson::Pointer(root + prefix + "scale_x").Set(doc, scene.scale_x);
|
rapidjson::Pointer(root + prefix + "scale_x").Set(doc, scene.scale_x);
|
||||||
rapidjson::Pointer(root + prefix + "scale_y").Set(doc, scene.scale_y);
|
rapidjson::Pointer(root + prefix + "scale_y").Set(doc, scene.scale_y);
|
||||||
rapidjson::Pointer(root + prefix + "keep_aspect_ratio").Set(doc, scene.keep_aspect_ratio);
|
rapidjson::Pointer(root + prefix + "keep_aspect_ratio").Set(doc, scene.keep_aspect_ratio);
|
||||||
rapidjson::Pointer(root + prefix + "centered").Set(doc, scene.centered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// windowed mode settings
|
// windowed mode settings
|
||||||
@@ -229,10 +219,10 @@ namespace cfg {
|
|||||||
doc.Accept(writer);
|
doc.Accept(writer);
|
||||||
|
|
||||||
// save to file
|
// save to file
|
||||||
if (fileutils::text_write(this->config_path, buffer.GetString())) {
|
if (fileutils::write_config_file("ScreenResize", this->config_path, buffer.GetString())) {
|
||||||
// this->config_dirty = false;
|
// this->config_dirty = false;
|
||||||
} else {
|
} else {
|
||||||
log_warning("ScreenResize", "unable to save config file to {}", this->config_path.string());
|
log_warning("ScreenResize", "unable to save config file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ namespace cfg {
|
|||||||
float scale_x = 1.0;
|
float scale_x = 1.0;
|
||||||
float scale_y = 1.0;
|
float scale_y = 1.0;
|
||||||
bool keep_aspect_ratio = true;
|
bool keep_aspect_ratio = true;
|
||||||
bool centered = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
|
extern std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
|
||||||
|
|||||||
@@ -1,3 +1,40 @@
|
|||||||
|
06/03/2025 [spice2x]
|
||||||
|
Add libshare-pj.dll to Gitadora patch import
|
||||||
|
Detect ACIO init failures
|
||||||
|
|
||||||
|
05/31/2025 [spice2x]
|
||||||
|
IIDX: fix windowed subscreen not accepting mouse clicks when
|
||||||
|
overlay is active
|
||||||
|
IIDX: tape LED over API
|
||||||
|
Option to make command line args take precedence
|
||||||
|
UI tweaks
|
||||||
|
|
||||||
|
05/09/2025 [spice2x]
|
||||||
|
Check for window focus when processing input (-inputfocus)
|
||||||
|
More options for IIDX/SDVX windowed subscreen
|
||||||
|
SpiceCompanion screen mirroring quality options
|
||||||
|
Various LovePlus improvements and fixes:
|
||||||
|
Allow camera access
|
||||||
|
Full screen mode
|
||||||
|
Add printer options
|
||||||
|
Add stub for printer DLL (cpusbxpkm.dll)
|
||||||
|
Logging improvements for better troubleshooting
|
||||||
|
|
||||||
|
04/25/2025 [spice2x]
|
||||||
|
LargeAddressAware variant of spice.exe for Metal Gear
|
||||||
|
Save new JSON config files to %appdata%/spice2x
|
||||||
|
Various bug fixes
|
||||||
|
|
||||||
|
04/08/2025 [spice2x]
|
||||||
|
Ensure rawinput touch is default for all games (-wintouch to override)
|
||||||
|
Various overlay UI fixes and improvements, update ImGui library
|
||||||
|
Add missing lights in Museca
|
||||||
|
|
||||||
|
03/29/2025 [spice2x]
|
||||||
|
Add SDVX landscape mode, -forceresswap option
|
||||||
|
Fix bugs in image scaler
|
||||||
|
Configurator UI tweaks
|
||||||
|
|
||||||
03/25/2025 [spice2x]
|
03/25/2025 [spice2x]
|
||||||
Add Mahjong Fight Girl support
|
Add Mahjong Fight Girl support
|
||||||
Add option for custom full screen resolution (-forceres)
|
Add option for custom full screen resolution (-forceres)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required (VERSION 3.2.0)
|
cmake_minimum_required (VERSION 3.12)
|
||||||
project (DiscordRPC)
|
project (DiscordRPC)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|||||||
+6
-14
@@ -1,25 +1,17 @@
|
|||||||
FROM archlinux:base
|
FROM ghcr.io/archlinux/archlinux:base-devel
|
||||||
|
|
||||||
RUN pacman --noconfirm -Syu gettext \
|
RUN pacman --noconfirm -Syu git \
|
||||||
base-devel \
|
|
||||||
git \
|
|
||||||
bash \
|
bash \
|
||||||
zip \
|
zip \
|
||||||
upx \
|
upx \
|
||||||
sudo \
|
ninja \
|
||||||
binutils \
|
|
||||||
file \
|
|
||||||
make \
|
|
||||||
gcc \
|
|
||||||
fakeroot \
|
|
||||||
diffutils \
|
|
||||||
cmake \
|
cmake \
|
||||||
awk \
|
|
||||||
unzip \
|
unzip \
|
||||||
mingw-w64-crt \
|
mingw-w64-crt \
|
||||||
mingw-w64-winpthreads \
|
mingw-w64-winpthreads \
|
||||||
mingw-w64-gcc \
|
mingw-w64-gcc \
|
||||||
mingw-w64-headers \
|
mingw-w64-headers \
|
||||||
mingw-w64-binutils
|
mingw-w64-binutils \
|
||||||
|
ccache
|
||||||
RUN useradd user -m && echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
RUN useradd user -m && echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||||
RUN su user -c "cd /tmp/ && git clone https://aur.archlinux.org/yay.git --depth=1 && cd yay && makepkg --noconfirm -si && yay --noconfirm -S mingw-w64-cmake"
|
RUN su user -c "cd /tmp/ && git clone https://aur.archlinux.org/yay-bin.git --depth=1 && cd yay-bin && makepkg --noconfirm -si && yay --noconfirm -S mingw-w64-cmake"
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
project(imgui CXX)
|
project(imgui CXX)
|
||||||
|
|
||||||
set(HASH_LIBRARY_HEADERS
|
set(HASH_LIBRARY_HEADERS
|
||||||
|
|||||||
+5
-3
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
project(imgui CXX)
|
project(imgui CXX)
|
||||||
|
|
||||||
# dear imgui uses the C++ virtual interfaces for DirectX
|
# dear imgui uses the C++ virtual interfaces for DirectX
|
||||||
@@ -8,7 +8,8 @@ set(IMGUI_HEADERS
|
|||||||
imconfig.h
|
imconfig.h
|
||||||
imgui.h
|
imgui.h
|
||||||
imgui_internal.h
|
imgui_internal.h
|
||||||
imgui_stdlib.h
|
backends/imgui_impl_dx9.h
|
||||||
|
misc/cpp/imgui_stdlib.h
|
||||||
)
|
)
|
||||||
set(IMGUI_SOURCES
|
set(IMGUI_SOURCES
|
||||||
imgui.cpp
|
imgui.cpp
|
||||||
@@ -16,7 +17,8 @@ set(IMGUI_SOURCES
|
|||||||
imgui_tables.cpp
|
imgui_tables.cpp
|
||||||
imgui_widgets.cpp
|
imgui_widgets.cpp
|
||||||
imgui_demo.cpp
|
imgui_demo.cpp
|
||||||
imgui_stdlib.cpp
|
backends/imgui_impl_dx9.cpp
|
||||||
|
misc/cpp/imgui_stdlib.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(imgui STATIC ${IMGUI_HEADERS} ${IMGUI_SOURCES})
|
add_library(imgui STATIC ${IMGUI_HEADERS} ${IMGUI_SOURCES})
|
||||||
|
|||||||
Vendored
+3
-3
@@ -22,14 +22,14 @@
|
|||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
|
||||||
#include "impl_dx9.h"
|
#include "imgui_impl_dx9.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
// DirectX
|
// DirectX
|
||||||
#include <d3d9.h>
|
#include <d3d9.h>
|
||||||
|
|
||||||
#include "external/imgui/imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
// allow std::min use
|
// allow std::min use
|
||||||
#ifdef min
|
#ifdef min
|
||||||
@@ -327,7 +327,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects() {
|
|||||||
if (g_FontTexture) {
|
if (g_FontTexture) {
|
||||||
g_FontTexture->Release();
|
g_FontTexture->Release();
|
||||||
g_FontTexture = NULL;
|
g_FontTexture = NULL;
|
||||||
ImGui::GetIO().Fonts->TexID = NULL;
|
ImGui::GetIO().Fonts->TexID = 0;
|
||||||
} // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
} // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||||
}
|
}
|
||||||
|
|
||||||
Vendored
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "external/imgui/imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
struct IDirect3DDevice9;
|
struct IDirect3DDevice9;
|
||||||
|
|
||||||
+33
-16
@@ -1,5 +1,5 @@
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||||
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -21,27 +21,29 @@
|
|||||||
|
|
||||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||||
//#define IMGUI_API __declspec( dllexport )
|
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
|
||||||
//#define IMGUI_API __declspec( dllimport )
|
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
|
||||||
|
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
|
||||||
|
|
||||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
|
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS.
|
||||||
|
|
||||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
|
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
|
||||||
|
|
||||||
//---- Don't implement some functions to reduce linkage requirements.
|
//---- Don't implement some functions to reduce linkage requirements.
|
||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||||
#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||||
@@ -49,8 +51,13 @@
|
|||||||
#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||||
|
|
||||||
|
//---- Enable Test Engine / Automation features.
|
||||||
|
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
|
||||||
|
|
||||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||||
|
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
||||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||||
|
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
|
||||||
|
|
||||||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||||
#define IMGUI_USE_BGRA_PACKED_COLOR
|
#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
@@ -58,16 +65,17 @@
|
|||||||
//---- Performance optimization for DX9
|
//---- Performance optimization for DX9
|
||||||
#define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
#define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
||||||
|
|
||||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||||
//#define IMGUI_USE_WCHAR32
|
//#define IMGUI_USE_WCHAR32
|
||||||
|
|
||||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled
|
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||||
|
|
||||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||||
@@ -78,6 +86,15 @@
|
|||||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||||
//#define IMGUI_ENABLE_FREETYPE
|
//#define IMGUI_ENABLE_FREETYPE
|
||||||
|
|
||||||
|
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
|
||||||
|
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||||
|
// - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg.
|
||||||
|
// - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions.
|
||||||
|
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
|
||||||
|
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||||
|
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
||||||
|
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||||
|
|
||||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||||
@@ -108,7 +125,7 @@
|
|||||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||||
//#define ImDrawCallback MyImDrawCallback
|
//#define ImDrawCallback MyImDrawCallback
|
||||||
|
|
||||||
//---- Debug Tools: Macro to break in Debugger
|
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||||
//#define IM_DEBUG_BREAK __debugbreak()
|
//#define IM_DEBUG_BREAK __debugbreak()
|
||||||
@@ -116,10 +133,10 @@
|
|||||||
//---- Debug Tools: Enable slower asserts
|
//---- Debug Tools: Enable slower asserts
|
||||||
//#define IMGUI_DEBUG_PARANOID
|
//#define IMGUI_DEBUG_PARANOID
|
||||||
|
|
||||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||||
/*
|
/*
|
||||||
namespace ImGui
|
namespace ImGui
|
||||||
{
|
{
|
||||||
void MyFunction(const char* name, const MyMatrix44& v);
|
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|||||||
Vendored
+4651
-2301
File diff suppressed because it is too large
Load Diff
Vendored
+1497
-902
File diff suppressed because it is too large
Load Diff
+3015
-663
File diff suppressed because it is too large
Load Diff
+621
-129
File diff suppressed because it is too large
Load Diff
+938
-658
File diff suppressed because it is too large
Load Diff
+584
-235
File diff suppressed because it is too large
Load Diff
+2536
-870
File diff suppressed because it is too large
Load Diff
+139
-107
@@ -2,8 +2,11 @@
|
|||||||
// This is a slightly modified version of stb_textedit.h 1.14.
|
// This is a slightly modified version of stb_textedit.h 1.14.
|
||||||
// Those changes would need to be pushed into nothings/stb:
|
// Those changes would need to be pushed into nothings/stb:
|
||||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000)
|
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
||||||
|
// - Added name to struct or it may be forward declared in our code.
|
||||||
|
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
|
||||||
// Grep for [DEAR IMGUI] to find the changes.
|
// Grep for [DEAR IMGUI] to find the changes.
|
||||||
|
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
||||||
|
|
||||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
||||||
// Development of this library was sponsored by RAD Game Tools
|
// Development of this library was sponsored by RAD Game Tools
|
||||||
@@ -30,7 +33,7 @@
|
|||||||
// DEPENDENCIES
|
// DEPENDENCIES
|
||||||
//
|
//
|
||||||
// Uses the C runtime function 'memmove', which you can override
|
// Uses the C runtime function 'memmove', which you can override
|
||||||
// by defining STB_TEXTEDIT_memmove before the implementation.
|
// by defining IMSTB_TEXTEDIT_memmove before the implementation.
|
||||||
// Uses no other functions. Performs no runtime allocations.
|
// Uses no other functions. Performs no runtime allocations.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@@ -40,7 +43,7 @@
|
|||||||
// 1.13 (2019-02-07) fix bug in undo size management
|
// 1.13 (2019-02-07) fix bug in undo size management
|
||||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||||
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
||||||
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
|
// 1.10 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
|
||||||
// 1.9 (2016-08-27) customizable move-by-word
|
// 1.9 (2016-08-27) customizable move-by-word
|
||||||
// 1.8 (2016-04-02) better keyboard handling when mouse button is down
|
// 1.8 (2016-04-02) better keyboard handling when mouse button is down
|
||||||
// 1.7 (2015-09-13) change y range handling in case baseline is non-0
|
// 1.7 (2015-09-13) change y range handling in case baseline is non-0
|
||||||
@@ -208,6 +211,7 @@
|
|||||||
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
||||||
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
|
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
|
||||||
|
// void stb_textedit_text(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int text_len)
|
||||||
//
|
//
|
||||||
// Each of these functions potentially updates the string and updates the
|
// Each of these functions potentially updates the string and updates the
|
||||||
// state.
|
// state.
|
||||||
@@ -242,7 +246,12 @@
|
|||||||
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
|
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
|
||||||
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
|
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
|
||||||
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
||||||
// anything other type you wante before including.
|
// anything other type you want before including.
|
||||||
|
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
||||||
|
// transformed into text and stb_textedit_text() is automatically called.
|
||||||
|
//
|
||||||
|
// text: [DEAR IMGUI] added 2024-09
|
||||||
|
// call this to text inputs sent to the textfield.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// When rendering, you can read the cursor position and selection state from
|
// When rendering, you can read the cursor position and selection state from
|
||||||
@@ -274,8 +283,8 @@
|
|||||||
////
|
////
|
||||||
////
|
////
|
||||||
|
|
||||||
#ifndef INCLUDE_STB_TEXTEDIT_H
|
#ifndef INCLUDE_IMSTB_TEXTEDIT_H
|
||||||
#define INCLUDE_STB_TEXTEDIT_H
|
#define INCLUDE_IMSTB_TEXTEDIT_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@@ -286,38 +295,38 @@
|
|||||||
// and undo state.
|
// and undo state.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
|
#ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT
|
||||||
#define STB_TEXTEDIT_UNDOSTATECOUNT 99
|
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
|
||||||
#endif
|
#endif
|
||||||
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
|
#ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT
|
||||||
#define STB_TEXTEDIT_UNDOCHARCOUNT 999
|
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
|
||||||
#endif
|
#endif
|
||||||
#ifndef STB_TEXTEDIT_CHARTYPE
|
#ifndef IMSTB_TEXTEDIT_CHARTYPE
|
||||||
#define STB_TEXTEDIT_CHARTYPE int
|
#define IMSTB_TEXTEDIT_CHARTYPE int
|
||||||
#endif
|
#endif
|
||||||
#ifndef STB_TEXTEDIT_POSITIONTYPE
|
#ifndef IMSTB_TEXTEDIT_POSITIONTYPE
|
||||||
#define STB_TEXTEDIT_POSITIONTYPE int
|
#define IMSTB_TEXTEDIT_POSITIONTYPE int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// private data
|
// private data
|
||||||
STB_TEXTEDIT_POSITIONTYPE where;
|
IMSTB_TEXTEDIT_POSITIONTYPE where;
|
||||||
STB_TEXTEDIT_POSITIONTYPE insert_length;
|
IMSTB_TEXTEDIT_POSITIONTYPE insert_length;
|
||||||
STB_TEXTEDIT_POSITIONTYPE delete_length;
|
IMSTB_TEXTEDIT_POSITIONTYPE delete_length;
|
||||||
int char_storage;
|
int char_storage;
|
||||||
} StbUndoRecord;
|
} StbUndoRecord;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// private data
|
// private data
|
||||||
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
|
StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT];
|
||||||
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
|
IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT];
|
||||||
short undo_point, redo_point;
|
short undo_point, redo_point;
|
||||||
int undo_char_point, redo_char_point;
|
int undo_char_point, redo_char_point;
|
||||||
} StbUndoState;
|
} StbUndoState;
|
||||||
|
|
||||||
typedef struct
|
typedef struct STB_TexteditState
|
||||||
{
|
{
|
||||||
/////////////////////
|
/////////////////////
|
||||||
//
|
//
|
||||||
@@ -371,7 +380,7 @@ typedef struct
|
|||||||
float ymin,ymax; // height of row above and below baseline
|
float ymin,ymax; // height of row above and below baseline
|
||||||
int num_chars;
|
int num_chars;
|
||||||
} StbTexteditRow;
|
} StbTexteditRow;
|
||||||
#endif //INCLUDE_STB_TEXTEDIT_H
|
#endif //INCLUDE_IMSTB_TEXTEDIT_H
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -384,11 +393,11 @@ typedef struct
|
|||||||
|
|
||||||
// implementation isn't include-guarded, since it might have indirectly
|
// implementation isn't include-guarded, since it might have indirectly
|
||||||
// included just the "header" portion
|
// included just the "header" portion
|
||||||
#ifdef STB_TEXTEDIT_IMPLEMENTATION
|
#ifdef IMSTB_TEXTEDIT_IMPLEMENTATION
|
||||||
|
|
||||||
#ifndef STB_TEXTEDIT_memmove
|
#ifndef IMSTB_TEXTEDIT_memmove
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#define STB_TEXTEDIT_memmove memmove
|
#define IMSTB_TEXTEDIT_memmove memmove
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -398,7 +407,7 @@ typedef struct
|
|||||||
//
|
//
|
||||||
|
|
||||||
// traverse the layout to locate the nearest character to a display position
|
// traverse the layout to locate the nearest character to a display position
|
||||||
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
||||||
{
|
{
|
||||||
StbTexteditRow r;
|
StbTexteditRow r;
|
||||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
@@ -437,13 +446,13 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
|||||||
if (x < r.x1) {
|
if (x < r.x1) {
|
||||||
// search characters in row for one that straddles 'x'
|
// search characters in row for one that straddles 'x'
|
||||||
prev_x = r.x0;
|
prev_x = r.x0;
|
||||||
for (k=0; k < r.num_chars; ++k) {
|
for (k=0; k < r.num_chars; k = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k) - i) {
|
||||||
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
|
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
|
||||||
if (x < prev_x+w) {
|
if (x < prev_x+w) {
|
||||||
if (x < prev_x+w/2)
|
if (x < prev_x+w/2)
|
||||||
return k+i;
|
return k+i;
|
||||||
else
|
else
|
||||||
return k+i+1;
|
return IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k);
|
||||||
}
|
}
|
||||||
prev_x += w;
|
prev_x += w;
|
||||||
}
|
}
|
||||||
@@ -458,7 +467,7 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// API click: on mouse down, move the cursor to the clicked location, and reset the selection
|
// API click: on mouse down, move the cursor to the clicked location, and reset the selection
|
||||||
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||||
{
|
{
|
||||||
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
|
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
|
||||||
// goes off the top or bottom of the text
|
// goes off the top or bottom of the text
|
||||||
@@ -476,7 +485,7 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
|
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
|
||||||
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||||
{
|
{
|
||||||
int p = 0;
|
int p = 0;
|
||||||
|
|
||||||
@@ -502,11 +511,11 @@ static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
|
|||||||
//
|
//
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||||
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||||
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
||||||
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
|
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
|
||||||
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
|
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -518,7 +527,7 @@ typedef struct
|
|||||||
|
|
||||||
// find the x/y location of a character, and remember info about the previous row in
|
// find the x/y location of a character, and remember info about the previous row in
|
||||||
// case we get a move-up event (for page up, we'll have to rescan)
|
// case we get a move-up event (for page up, we'll have to rescan)
|
||||||
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
|
static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line)
|
||||||
{
|
{
|
||||||
StbTexteditRow r;
|
StbTexteditRow r;
|
||||||
int prev_start = 0;
|
int prev_start = 0;
|
||||||
@@ -549,7 +558,10 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
|||||||
i += r.num_chars;
|
i += r.num_chars;
|
||||||
find->y += r.baseline_y_delta;
|
find->y += r.baseline_y_delta;
|
||||||
if (i == z) // [DEAR IMGUI]
|
if (i == z) // [DEAR IMGUI]
|
||||||
|
{
|
||||||
|
r.num_chars = 0; // [DEAR IMGUI]
|
||||||
break; // [DEAR IMGUI]
|
break; // [DEAR IMGUI]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
find->first_char = first = i;
|
find->first_char = first = i;
|
||||||
@@ -559,14 +571,14 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
|||||||
|
|
||||||
// now scan to find xpos
|
// now scan to find xpos
|
||||||
find->x = r.x0;
|
find->x = r.x0;
|
||||||
for (i=0; first+i < n; ++i)
|
for (i=0; first+i < n; i = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, first + i) - first)
|
||||||
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
|
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
|
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
|
||||||
|
|
||||||
// make the selection/cursor state valid if client altered the string
|
// make the selection/cursor state valid if client altered the string
|
||||||
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
@@ -580,7 +592,7 @@ static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete characters while updating undo
|
// delete characters while updating undo
|
||||||
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
|
static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
|
||||||
{
|
{
|
||||||
stb_text_makeundo_delete(str, state, where, len);
|
stb_text_makeundo_delete(str, state, where, len);
|
||||||
STB_TEXTEDIT_DELETECHARS(str, where, len);
|
STB_TEXTEDIT_DELETECHARS(str, where, len);
|
||||||
@@ -588,7 +600,7 @@ static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete the section
|
// delete the section
|
||||||
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
@@ -625,7 +637,7 @@ static void stb_textedit_move_to_first(STB_TexteditState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move cursor to last character of selection
|
// move cursor to last character of selection
|
||||||
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
stb_textedit_sortselection(state);
|
stb_textedit_sortselection(state);
|
||||||
@@ -636,14 +648,25 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [DEAR IMGUI]
|
||||||
|
// Functions must be implemented for UTF8 support
|
||||||
|
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
|
||||||
|
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
|
||||||
|
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
|
||||||
|
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1)
|
||||||
|
#endif
|
||||||
|
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
||||||
|
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||||
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
|
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
||||||
{
|
{
|
||||||
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
|
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
||||||
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
|
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||||
{
|
{
|
||||||
--c; // always move at least one character
|
--c; // always move at least one character
|
||||||
while( c >= 0 && !is_word_boundary( str, c ) )
|
while( c >= 0 && !is_word_boundary( str, c ) )
|
||||||
@@ -658,7 +681,7 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
|
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
|
||||||
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
|
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||||
{
|
{
|
||||||
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
++c; // always move at least one character
|
++c; // always move at least one character
|
||||||
@@ -685,7 +708,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// API cut: delete selection
|
// API cut: delete selection
|
||||||
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
stb_textedit_delete_selection(str,state); // implicitly clamps
|
||||||
@@ -696,7 +719,7 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// API paste: replace existing selection with passed-in text
|
// API paste: replace existing selection with passed-in text
|
||||||
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len)
|
||||||
{
|
{
|
||||||
// if there's a selection, the paste should delete it
|
// if there's a selection, the paste should delete it
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
@@ -716,36 +739,44 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
|
|||||||
#define STB_TEXTEDIT_KEYTYPE int
|
#define STB_TEXTEDIT_KEYTYPE int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
|
||||||
|
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||||
|
{
|
||||||
|
// can't add newline in single-line mode
|
||||||
|
if (text[0] == '\n' && state->single_line)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
||||||
|
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||||
|
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||||
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||||
|
state->cursor += text_len;
|
||||||
|
state->has_preferred_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||||
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||||
|
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||||
|
state->cursor += text_len;
|
||||||
|
state->has_preferred_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// API key: process a keyboard input
|
// API key: process a keyboard input
|
||||||
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
switch (key) {
|
switch (key) {
|
||||||
default: {
|
default: {
|
||||||
|
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
||||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
|
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
||||||
|
stb_textedit_text(str, state, &ch, 1);
|
||||||
// can't add newline in single-line mode
|
|
||||||
if (c == '\n' && state->single_line)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
|
||||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
|
||||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
|
||||||
++state->cursor;
|
|
||||||
state->has_preferred_x = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
|
||||||
stb_text_makeundo_insert(state, state->cursor, 1);
|
|
||||||
++state->cursor;
|
|
||||||
state->has_preferred_x = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -771,7 +802,7 @@ retry:
|
|||||||
stb_textedit_move_to_first(state);
|
stb_textedit_move_to_first(state);
|
||||||
else
|
else
|
||||||
if (state->cursor > 0)
|
if (state->cursor > 0)
|
||||||
--state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -780,7 +811,7 @@ retry:
|
|||||||
if (STB_TEXT_HAS_SELECTION(state))
|
if (STB_TEXT_HAS_SELECTION(state))
|
||||||
stb_textedit_move_to_last(str, state);
|
stb_textedit_move_to_last(str, state);
|
||||||
else
|
else
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
@@ -790,7 +821,7 @@ retry:
|
|||||||
stb_textedit_prep_selection_at_cursor(state);
|
stb_textedit_prep_selection_at_cursor(state);
|
||||||
// move selection left
|
// move selection left
|
||||||
if (state->select_end > 0)
|
if (state->select_end > 0)
|
||||||
--state->select_end;
|
state->select_end = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->select_end);
|
||||||
state->cursor = state->select_end;
|
state->cursor = state->select_end;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
@@ -840,7 +871,7 @@ retry:
|
|||||||
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
|
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
|
||||||
stb_textedit_prep_selection_at_cursor(state);
|
stb_textedit_prep_selection_at_cursor(state);
|
||||||
// move selection right
|
// move selection right
|
||||||
++state->select_end;
|
state->select_end = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->select_end);
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
state->cursor = state->select_end;
|
state->cursor = state->select_end;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
@@ -889,14 +920,14 @@ retry:
|
|||||||
x = row.x0;
|
x = row.x0;
|
||||||
for (i=0; i < row.num_chars; ++i) {
|
for (i=0; i < row.num_chars; ++i) {
|
||||||
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
||||||
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
|
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||||
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
|
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
x += dx;
|
x += dx;
|
||||||
if (x > goal_x)
|
if (x > goal_x)
|
||||||
break;
|
break;
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
}
|
}
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
|
|
||||||
@@ -951,14 +982,14 @@ retry:
|
|||||||
x = row.x0;
|
x = row.x0;
|
||||||
for (i=0; i < row.num_chars; ++i) {
|
for (i=0; i < row.num_chars; ++i) {
|
||||||
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
||||||
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
|
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||||
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
|
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
x += dx;
|
x += dx;
|
||||||
if (x > goal_x)
|
if (x > goal_x)
|
||||||
break;
|
break;
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
}
|
}
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
|
|
||||||
@@ -986,7 +1017,7 @@ retry:
|
|||||||
else {
|
else {
|
||||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
if (state->cursor < n)
|
if (state->cursor < n)
|
||||||
stb_textedit_delete(str, state, state->cursor, 1);
|
stb_textedit_delete(str, state, state->cursor, IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor) - state->cursor);
|
||||||
}
|
}
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
@@ -998,8 +1029,9 @@ retry:
|
|||||||
else {
|
else {
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
if (state->cursor > 0) {
|
if (state->cursor > 0) {
|
||||||
stb_textedit_delete(str, state, state->cursor-1, 1);
|
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||||
--state->cursor;
|
stb_textedit_delete(str, state, prev, state->cursor - prev);
|
||||||
|
state->cursor = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
@@ -1109,8 +1141,8 @@ retry:
|
|||||||
|
|
||||||
static void stb_textedit_flush_redo(StbUndoState *state)
|
static void stb_textedit_flush_redo(StbUndoState *state)
|
||||||
{
|
{
|
||||||
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
|
state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
|
||||||
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
|
state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// discard the oldest entry in the undo list
|
// discard the oldest entry in the undo list
|
||||||
@@ -1122,13 +1154,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
|||||||
int n = state->undo_rec[0].insert_length, i;
|
int n = state->undo_rec[0].insert_length, i;
|
||||||
// delete n characters from all other records
|
// delete n characters from all other records
|
||||||
state->undo_char_point -= n;
|
state->undo_char_point -= n;
|
||||||
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
|
||||||
for (i=0; i < state->undo_point; ++i)
|
for (i=0; i < state->undo_point; ++i)
|
||||||
if (state->undo_rec[i].char_storage >= 0)
|
if (state->undo_rec[i].char_storage >= 0)
|
||||||
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
|
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
|
||||||
}
|
}
|
||||||
--state->undo_point;
|
--state->undo_point;
|
||||||
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
|
IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1138,7 +1170,7 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
|||||||
// fill up even though the undo buffer didn't
|
// fill up even though the undo buffer didn't
|
||||||
static void stb_textedit_discard_redo(StbUndoState *state)
|
static void stb_textedit_discard_redo(StbUndoState *state)
|
||||||
{
|
{
|
||||||
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
|
int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1;
|
||||||
|
|
||||||
if (state->redo_point <= k) {
|
if (state->redo_point <= k) {
|
||||||
// if the k'th undo state has characters, clean those up
|
// if the k'th undo state has characters, clean those up
|
||||||
@@ -1146,7 +1178,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
|||||||
int n = state->undo_rec[k].insert_length, i;
|
int n = state->undo_rec[k].insert_length, i;
|
||||||
// move the remaining redo character data to the end of the buffer
|
// move the remaining redo character data to the end of the buffer
|
||||||
state->redo_char_point += n;
|
state->redo_char_point += n;
|
||||||
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
|
||||||
// adjust the position of all the other records to account for above memmove
|
// adjust the position of all the other records to account for above memmove
|
||||||
for (i=state->redo_point; i < k; ++i)
|
for (i=state->redo_point; i < k; ++i)
|
||||||
if (state->undo_rec[i].char_storage >= 0)
|
if (state->undo_rec[i].char_storage >= 0)
|
||||||
@@ -1154,12 +1186,12 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
|||||||
}
|
}
|
||||||
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
|
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
|
||||||
// [DEAR IMGUI]
|
// [DEAR IMGUI]
|
||||||
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
|
size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
|
||||||
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
|
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
|
||||||
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
|
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
|
||||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
|
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
|
||||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
|
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
|
||||||
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
|
IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
|
||||||
|
|
||||||
// now move redo_point to point to the new one
|
// now move redo_point to point to the new one
|
||||||
++state->redo_point;
|
++state->redo_point;
|
||||||
@@ -1173,32 +1205,32 @@ static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numch
|
|||||||
|
|
||||||
// if we have no free records, we have to make room, by sliding the
|
// if we have no free records, we have to make room, by sliding the
|
||||||
// existing records down
|
// existing records down
|
||||||
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
||||||
stb_textedit_discard_undo(state);
|
stb_textedit_discard_undo(state);
|
||||||
|
|
||||||
// if the characters to store won't possibly fit in the buffer, we can't undo
|
// if the characters to store won't possibly fit in the buffer, we can't undo
|
||||||
if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
|
if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||||
state->undo_point = 0;
|
state->undo_point = 0;
|
||||||
state->undo_char_point = 0;
|
state->undo_char_point = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we don't have enough free characters in the buffer, we have to make room
|
// if we don't have enough free characters in the buffer, we have to make room
|
||||||
while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
|
while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT)
|
||||||
stb_textedit_discard_undo(state);
|
stb_textedit_discard_undo(state);
|
||||||
|
|
||||||
return &state->undo_rec[state->undo_point++];
|
return &state->undo_rec[state->undo_point++];
|
||||||
}
|
}
|
||||||
|
|
||||||
static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
|
static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
|
||||||
{
|
{
|
||||||
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
|
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
|
||||||
if (r == NULL)
|
if (r == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
r->where = pos;
|
r->where = pos;
|
||||||
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
|
r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len;
|
||||||
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
|
r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len;
|
||||||
|
|
||||||
if (insert_len == 0) {
|
if (insert_len == 0) {
|
||||||
r->char_storage = -1;
|
r->char_storage = -1;
|
||||||
@@ -1210,7 +1242,7 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
StbUndoState *s = &state->undostate;
|
StbUndoState *s = &state->undostate;
|
||||||
StbUndoRecord u, *r;
|
StbUndoRecord u, *r;
|
||||||
@@ -1237,7 +1269,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
|||||||
// characters stored for *undoing* don't leave room for redo
|
// characters stored for *undoing* don't leave room for redo
|
||||||
// if the last is true, we have to bail
|
// if the last is true, we have to bail
|
||||||
|
|
||||||
if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
|
if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||||
// the undo records take up too much character space; there's no space to store the redo characters
|
// the undo records take up too much character space; there's no space to store the redo characters
|
||||||
r->insert_length = 0;
|
r->insert_length = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -1246,7 +1278,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
|||||||
// there's definitely room to store the characters eventually
|
// there's definitely room to store the characters eventually
|
||||||
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
|
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
|
||||||
// should never happen:
|
// should never happen:
|
||||||
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
||||||
return;
|
return;
|
||||||
// there's currently not enough room, so discard a redo record
|
// there's currently not enough room, so discard a redo record
|
||||||
stb_textedit_discard_redo(s);
|
stb_textedit_discard_redo(s);
|
||||||
@@ -1278,11 +1310,11 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
|||||||
s->redo_point--;
|
s->redo_point--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
{
|
{
|
||||||
StbUndoState *s = &state->undostate;
|
StbUndoState *s = &state->undostate;
|
||||||
StbUndoRecord *u, r;
|
StbUndoRecord *u, r;
|
||||||
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// we need to do two things: apply the redo record, and create an undo record
|
// we need to do two things: apply the redo record, and create an undo record
|
||||||
@@ -1334,20 +1366,20 @@ static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int le
|
|||||||
stb_text_createundo(&state->undostate, where, 0, length);
|
stb_text_createundo(&state->undostate, where, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
|
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
|
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
|
||||||
if (p) {
|
if (p) {
|
||||||
for (i=0; i < length; ++i)
|
for (i=0; i < length; ++i)
|
||||||
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
|
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
|
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
|
||||||
if (p) {
|
if (p) {
|
||||||
for (i=0; i < old_length; ++i)
|
for (i=0; i < old_length; ++i)
|
||||||
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
||||||
@@ -1359,8 +1391,8 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
|
|||||||
{
|
{
|
||||||
state->undostate.undo_point = 0;
|
state->undostate.undo_point = 0;
|
||||||
state->undostate.undo_char_point = 0;
|
state->undostate.undo_char_point = 0;
|
||||||
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
|
state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
|
||||||
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
|
state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
|
||||||
state->select_end = state->select_start = 0;
|
state->select_end = state->select_start = 0;
|
||||||
state->cursor = 0;
|
state->cursor = 0;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
@@ -1383,16 +1415,16 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl
|
|||||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
|
static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len)
|
||||||
{
|
{
|
||||||
return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
|
return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif//STB_TEXTEDIT_IMPLEMENTATION
|
#endif//IMSTB_TEXTEDIT_IMPLEMENTATION
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|||||||
+1
-1
@@ -656,7 +656,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
|
|||||||
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
|
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
|
||||||
// If skip != 0, this tells stb_truetype to skip any codepoints for which
|
// If skip != 0, this tells stb_truetype to skip any codepoints for which
|
||||||
// there is no corresponding glyph. If skip=0, which is the default, then
|
// there is no corresponding glyph. If skip=0, which is the default, then
|
||||||
// codepoints without a glyph recived the font's "missing character" glyph,
|
// codepoints without a glyph received the font's "missing character" glyph,
|
||||||
// typically an empty box by convention.
|
// typically an empty box by convention.
|
||||||
|
|
||||||
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
|
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
|
||||||
|
|||||||
Vendored
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
cmake_policy(SET CMP0069 NEW)
|
cmake_policy(SET CMP0069 NEW)
|
||||||
project(minhook)
|
project(minhook)
|
||||||
|
|
||||||
|
|||||||
@@ -409,50 +409,27 @@ namespace games::iidx {
|
|||||||
* 16 - side panel right - 183 bytes - 61 colors
|
* 16 - side panel right - 183 bytes - 61 colors
|
||||||
*
|
*
|
||||||
* data is stored in RGB order, 3 bytes per color
|
* data is stored in RGB order, 3 bytes per color
|
||||||
*
|
|
||||||
* TODO: expose this data via API
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// data mapping
|
|
||||||
static struct TapeLedMapping {
|
|
||||||
size_t data_size;
|
|
||||||
int index_r, index_g, index_b;
|
|
||||||
|
|
||||||
TapeLedMapping(size_t data_size, int index_r, int index_g, int index_b)
|
|
||||||
: data_size(data_size), index_r(index_r), index_g(index_g), index_b(index_b) {}
|
|
||||||
|
|
||||||
} mapping[] = {
|
|
||||||
{ 19, Lights::StageLeftAvgR, Lights::StageLeftAvgG, Lights::StageLeftAvgB },
|
|
||||||
{ 19, Lights::StageRightAvgR, Lights::StageRightAvgG, Lights::StageRightAvgB },
|
|
||||||
{ 45, Lights::CabinetLeftAvgR, Lights::CabinetLeftAvgG, Lights::CabinetLeftAvgB },
|
|
||||||
{ 45, Lights::CabinetRightAvgR, Lights::CabinetRightAvgG, Lights::CabinetRightAvgB },
|
|
||||||
{ 21, Lights::ControlPanelUnderAvgR, Lights::ControlPanelUnderAvgG, Lights::ControlPanelUnderAvgB },
|
|
||||||
{ 54, Lights::CeilingLeftAvgR, Lights::CeilingLeftAvgG, Lights::CeilingLeftAvgB },
|
|
||||||
{ 11, Lights::TitleLeftAvgR, Lights::TitleLeftAvgG, Lights::TitleLeftAvgB },
|
|
||||||
{ 11, Lights::TitleRightAvgR, Lights::TitleRightAvgG, Lights::TitleRightAvgB },
|
|
||||||
{ 54, Lights::CeilingRightAvgR, Lights::CeilingRightAvgG, Lights::CeilingRightAvgB },
|
|
||||||
{ 17, Lights::TouchPanelLeftAvgR, Lights::TouchPanelLeftAvgG, Lights::TouchPanelLeftAvgB },
|
|
||||||
{ 17, Lights::TouchPanelRightAvgR, Lights::TouchPanelRightAvgG, Lights::TouchPanelRightAvgB },
|
|
||||||
{ 68, Lights::SidePanelLeftInnerAvgR, Lights::SidePanelLeftInnerAvgG, Lights::SidePanelLeftInnerAvgB },
|
|
||||||
{ 68, Lights::SidePanelLeftOuterAvgR, Lights::SidePanelLeftOuterAvgG, Lights::SidePanelLeftOuterAvgB },
|
|
||||||
{ 61, Lights::SidePanelLeftAvgR, Lights::SidePanelLeftAvgG, Lights::SidePanelLeftAvgB },
|
|
||||||
{ 68, Lights::SidePanelRightOuterAvgR, Lights::SidePanelRightOuterAvgG, Lights::SidePanelRightOuterAvgB },
|
|
||||||
{ 68, Lights::SidePanelRightInnerAvgR, Lights::SidePanelRightInnerAvgG, Lights::SidePanelRightInnerAvgB },
|
|
||||||
{ 61, Lights::SidePanelRightAvgR, Lights::SidePanelRightAvgG, Lights::SidePanelRightAvgB },
|
|
||||||
};
|
|
||||||
|
|
||||||
// check index bounds
|
// check index bounds
|
||||||
if (tapeledutils::is_enabled() && index < std::size(mapping)) {
|
if (tapeledutils::is_enabled() && index < std::size(TAPELED_MAPPING)) {
|
||||||
auto &map = mapping[index];
|
auto &map = TAPELED_MAPPING[index];
|
||||||
|
const auto data_size = map.data.capacity();
|
||||||
|
|
||||||
// pick a color to use
|
// pick a color to use
|
||||||
const auto rgb = tapeledutils::pick_color_from_led_tape(data, map.data_size);
|
const auto rgb = tapeledutils::pick_color_from_led_tape(data, data_size);
|
||||||
|
|
||||||
// program the lights into API
|
// program the lights into API
|
||||||
auto &lights = get_lights();
|
auto &lights = get_lights();
|
||||||
GameAPI::Lights::writeLight(RI_MGR, lights[map.index_r], rgb.r);
|
GameAPI::Lights::writeLight(RI_MGR, lights[map.index_r], rgb.r);
|
||||||
GameAPI::Lights::writeLight(RI_MGR, lights[map.index_g], rgb.g);
|
GameAPI::Lights::writeLight(RI_MGR, lights[map.index_g], rgb.g);
|
||||||
GameAPI::Lights::writeLight(RI_MGR, lights[map.index_b], rgb.b);
|
GameAPI::Lights::writeLight(RI_MGR, lights[map.index_b], rgb.b);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < data_size; ++i) {
|
||||||
|
map.data[i].r = data[i * 3];
|
||||||
|
map.data[i].g = data[i * 3 + 1];
|
||||||
|
map.data[i].b = data[i * 3 + 2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (This != custom_node) {
|
if (This != custom_node) {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace games::iidx {
|
|||||||
static IIDXLocalCamera *front_camera = nullptr; // camera id #1
|
static IIDXLocalCamera *front_camera = nullptr; // camera id #1
|
||||||
std::vector<IIDXLocalCamera*> LOCAL_CAMERA_LIST = {};
|
std::vector<IIDXLocalCamera*> LOCAL_CAMERA_LIST = {};
|
||||||
static IDirect3DDeviceManager9 *s_pD3DManager = nullptr;
|
static IDirect3DDeviceManager9 *s_pD3DManager = nullptr;
|
||||||
std::filesystem::path CAMERA_CONFIG_PATH = std::filesystem::path(_wgetenv(L"APPDATA")) / L"spicetools_camera_control.json";
|
std::filesystem::path CAMERA_CONFIG_PATH;
|
||||||
bool CAMERA_READY = false;
|
bool CAMERA_READY = false;
|
||||||
|
|
||||||
bool parse_cmd_params() {
|
bool parse_cmd_params() {
|
||||||
@@ -493,7 +493,8 @@ namespace games::iidx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool camera_config_load() {
|
bool camera_config_load() {
|
||||||
log_info("iidx:camhook", "loading config");
|
CAMERA_CONFIG_PATH =
|
||||||
|
fileutils::get_config_file_path("iidx::camhook", "spicetools_camera_control.json");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// read config file
|
// read config file
|
||||||
@@ -651,9 +652,9 @@ namespace games::iidx {
|
|||||||
doc.Accept(writer);
|
doc.Accept(writer);
|
||||||
|
|
||||||
// save to file
|
// save to file
|
||||||
if (fileutils::text_write(CAMERA_CONFIG_PATH, buffer.GetString())) {
|
if (fileutils::write_config_file("iidx::camhook", CAMERA_CONFIG_PATH, buffer.GetString())) {
|
||||||
} else {
|
} else {
|
||||||
log_warning("iidx:camhook", "unable to save config file to {}", CAMERA_CONFIG_PATH.string());
|
log_warning("iidx:camhook", "unable to save config file");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include "util/sigscan.h"
|
#include "util/sigscan.h"
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
|
|
||||||
|
#include "external/robin_hood.h"
|
||||||
|
|
||||||
#include "bi2a.h"
|
#include "bi2a.h"
|
||||||
#include "bi2x_hook.h"
|
#include "bi2x_hook.h"
|
||||||
#include "ezusb.h"
|
#include "ezusb.h"
|
||||||
@@ -74,6 +76,26 @@ namespace games::iidx {
|
|||||||
bool IIDXIO_LED_TICKER_READONLY = false;
|
bool IIDXIO_LED_TICKER_READONLY = false;
|
||||||
std::mutex IIDX_LED_TICKER_LOCK;
|
std::mutex IIDX_LED_TICKER_LOCK;
|
||||||
|
|
||||||
|
tapeledutils::tape_led TAPELED_MAPPING[IIDX_TAPELED_TOTAL] = {
|
||||||
|
{ 19, Lights::StageLeftAvgR, Lights::StageLeftAvgG, Lights::StageLeftAvgB, "Stage Left" },
|
||||||
|
{ 19, Lights::StageRightAvgR, Lights::StageRightAvgG, Lights::StageRightAvgB, "Stage Right" },
|
||||||
|
{ 45, Lights::CabinetLeftAvgR, Lights::CabinetLeftAvgG, Lights::CabinetLeftAvgB, "Cabinet Left" },
|
||||||
|
{ 45, Lights::CabinetRightAvgR, Lights::CabinetRightAvgG, Lights::CabinetRightAvgB, "Cabinet Right" },
|
||||||
|
{ 21, Lights::ControlPanelUnderAvgR, Lights::ControlPanelUnderAvgG, Lights::ControlPanelUnderAvgB, "Control Panel Under" },
|
||||||
|
{ 54, Lights::CeilingLeftAvgR, Lights::CeilingLeftAvgG, Lights::CeilingLeftAvgB, "Ceiling Left" },
|
||||||
|
{ 11, Lights::TitleLeftAvgR, Lights::TitleLeftAvgG, Lights::TitleLeftAvgB, "Title Left" },
|
||||||
|
{ 11, Lights::TitleRightAvgR, Lights::TitleRightAvgG, Lights::TitleRightAvgB, "Title Right" },
|
||||||
|
{ 54, Lights::CeilingRightAvgR, Lights::CeilingRightAvgG, Lights::CeilingRightAvgB, "Ceiling Right" },
|
||||||
|
{ 17, Lights::TouchPanelLeftAvgR, Lights::TouchPanelLeftAvgG, Lights::TouchPanelLeftAvgB, "Touch Panel Left" },
|
||||||
|
{ 17, Lights::TouchPanelRightAvgR, Lights::TouchPanelRightAvgG, Lights::TouchPanelRightAvgB, "Touch Panel Right" },
|
||||||
|
{ 68, Lights::SidePanelLeftInnerAvgR, Lights::SidePanelLeftInnerAvgG, Lights::SidePanelLeftInnerAvgB, "Side Panel Left Inner" },
|
||||||
|
{ 68, Lights::SidePanelLeftOuterAvgR, Lights::SidePanelLeftOuterAvgG, Lights::SidePanelLeftOuterAvgB, "Side Panel Left Outer" },
|
||||||
|
{ 61, Lights::SidePanelLeftAvgR, Lights::SidePanelLeftAvgG, Lights::SidePanelLeftAvgB, "Side Panel Left" },
|
||||||
|
{ 68, Lights::SidePanelRightOuterAvgR, Lights::SidePanelRightOuterAvgG, Lights::SidePanelRightOuterAvgB, "Side Panel Right Outer" },
|
||||||
|
{ 68, Lights::SidePanelRightInnerAvgR, Lights::SidePanelRightInnerAvgG, Lights::SidePanelRightInnerAvgB, "Side Panel Right Inner" },
|
||||||
|
{ 61, Lights::SidePanelRightAvgR, Lights::SidePanelRightAvgG, Lights::SidePanelRightAvgB, "Side Panel Right" },
|
||||||
|
};
|
||||||
|
|
||||||
static LONG WINAPI RegOpenKeyA_hook(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult) {
|
static LONG WINAPI RegOpenKeyA_hook(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult) {
|
||||||
if (lpSubKey != nullptr && phkResult != nullptr) {
|
if (lpSubKey != nullptr && phkResult != nullptr) {
|
||||||
if (hKey == HKEY_LOCAL_MACHINE &&
|
if (hKey == HKEY_LOCAL_MACHINE &&
|
||||||
|
|||||||
@@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "games/game.h"
|
#include "games/game.h"
|
||||||
|
|
||||||
|
#include "external/robin_hood.h"
|
||||||
|
#include "util/tapeled.h"
|
||||||
|
|
||||||
namespace games::iidx {
|
namespace games::iidx {
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
@@ -30,6 +34,10 @@ namespace games::iidx {
|
|||||||
extern bool IIDXIO_LED_TICKER_READONLY;
|
extern bool IIDXIO_LED_TICKER_READONLY;
|
||||||
extern std::mutex IIDX_LED_TICKER_LOCK;
|
extern std::mutex IIDX_LED_TICKER_LOCK;
|
||||||
|
|
||||||
|
constexpr int IIDX_TAPELED_TOTAL = 17;
|
||||||
|
// data mapping
|
||||||
|
extern tapeledutils::tape_led TAPELED_MAPPING[IIDX_TAPELED_TOTAL];
|
||||||
|
|
||||||
class IIDXGame : public games::Game {
|
class IIDXGame : public games::Game {
|
||||||
public:
|
public:
|
||||||
IIDXGame();
|
IIDXGame();
|
||||||
|
|||||||
@@ -266,8 +266,8 @@ namespace games::iidx::poke {
|
|||||||
y *= rawinput::TOUCHSCREEN_RANGE_Y;
|
y *= rawinput::TOUCHSCREEN_RANGE_Y;
|
||||||
} else if (GRAPHICS_IIDX_WSUB) {
|
} else if (GRAPHICS_IIDX_WSUB) {
|
||||||
// Scale to windowed subscreen
|
// Scale to windowed subscreen
|
||||||
x *= GRAPHICS_IIDX_WSUB_WIDTH;
|
x *= GRAPHICS_WSUB_WIDTH;
|
||||||
y *= GRAPHICS_IIDX_WSUB_HEIGHT;
|
y *= GRAPHICS_WSUB_HEIGHT;
|
||||||
} else if (GENERIC_SUB_WINDOW_FULLSIZE || !overlay::OVERLAY->get_active()) {
|
} else if (GENERIC_SUB_WINDOW_FULLSIZE || !overlay::OVERLAY->get_active()) {
|
||||||
// Overlay is not present, scale to main screen
|
// Overlay is not present, scale to main screen
|
||||||
if (GRAPHICS_WINDOWED) {
|
if (GRAPHICS_WINDOWED) {
|
||||||
|
|||||||
@@ -461,18 +461,6 @@ namespace games {
|
|||||||
vkey_defaults.push_back(0xFF);
|
vkey_defaults.push_back(0xFF);
|
||||||
names.emplace_back("Force Exit Game");
|
names.emplace_back("Force Exit Game");
|
||||||
vkey_defaults.push_back(0xFF);
|
vkey_defaults.push_back(0xFF);
|
||||||
names.emplace_back("Navigator Activate");
|
|
||||||
vkey_defaults.push_back(0xFF);
|
|
||||||
names.emplace_back("Navigator Cancel");
|
|
||||||
vkey_defaults.push_back(0xFF);
|
|
||||||
names.emplace_back("Navigator Up");
|
|
||||||
vkey_defaults.push_back(0xFF);
|
|
||||||
names.emplace_back("Navigator Down");
|
|
||||||
vkey_defaults.push_back(0xFF);
|
|
||||||
names.emplace_back("Navigator Left");
|
|
||||||
vkey_defaults.push_back(0xFF);
|
|
||||||
names.emplace_back("Navigator Right");
|
|
||||||
vkey_defaults.push_back(0xFF);
|
|
||||||
names.emplace_back("Hotkey Enable 1");
|
names.emplace_back("Hotkey Enable 1");
|
||||||
vkey_defaults.push_back(0xFF);
|
vkey_defaults.push_back(0xFF);
|
||||||
names.emplace_back("Hotkey Enable 2");
|
names.emplace_back("Hotkey Enable 2");
|
||||||
|
|||||||
@@ -30,12 +30,6 @@ namespace games {
|
|||||||
ScreenResizeScene3,
|
ScreenResizeScene3,
|
||||||
ScreenResizeScene4,
|
ScreenResizeScene4,
|
||||||
SuperExit,
|
SuperExit,
|
||||||
NavigatorActivate,
|
|
||||||
NavigatorCancel,
|
|
||||||
NavigatorUp,
|
|
||||||
NavigatorDown,
|
|
||||||
NavigatorLeft,
|
|
||||||
NavigatorRight,
|
|
||||||
HotkeyEnable1,
|
HotkeyEnable1,
|
||||||
HotkeyEnable2,
|
HotkeyEnable2,
|
||||||
HotkeyToggle,
|
HotkeyToggle,
|
||||||
|
|||||||
@@ -13,10 +13,14 @@
|
|||||||
|
|
||||||
namespace games::loveplus {
|
namespace games::loveplus {
|
||||||
|
|
||||||
|
bool CAMERA_ENABLE = false;
|
||||||
|
|
||||||
// touch stuff
|
// touch stuff
|
||||||
static bool TOUCH_ENABLE = false;
|
static bool TOUCH_ENABLE = false;
|
||||||
static bool TOUCH_ATTACHED = false;
|
static bool TOUCH_ATTACHED = false;
|
||||||
|
|
||||||
|
static std::string lp_args = "-noWatchDog -noIOError -noIrda -notarget";
|
||||||
|
|
||||||
void touch_update() {
|
void touch_update() {
|
||||||
|
|
||||||
// check if touch enabled
|
// check if touch enabled
|
||||||
@@ -28,16 +32,15 @@ namespace games::loveplus {
|
|||||||
if (!TOUCH_ATTACHED) {
|
if (!TOUCH_ATTACHED) {
|
||||||
|
|
||||||
// Find the game window.
|
// Find the game window.
|
||||||
// We check the foreground window first, then fall back to searching for the window title
|
HWND wnd = FindProcessWindowBeginsWith("LovePlusAC");
|
||||||
// All game versions seem to have their model first in the window title
|
|
||||||
HWND wnd = GetForegroundWindow();
|
|
||||||
if (!string_begins_with(GetActiveWindowTitle(), "LovePlus")) {
|
|
||||||
wnd = FindWindowBeginsWith(avs::game::MODEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// attach touch hook
|
// attach touch hook
|
||||||
if (wnd) {
|
if (wnd) {
|
||||||
log_info("loveplus", "using window handle for touch: {}", fmt::ptr(wnd));
|
log_info(
|
||||||
|
"loveplus",
|
||||||
|
"using window handle for touch: {} ({})",
|
||||||
|
fmt::ptr(wnd),
|
||||||
|
get_window_title(wnd));
|
||||||
touch_create_wnd(wnd);
|
touch_create_wnd(wnd);
|
||||||
} else {
|
} else {
|
||||||
log_info("loveplus", "falling back to the DirectX window handle for touch");
|
log_info("loveplus", "falling back to the DirectX window handle for touch");
|
||||||
@@ -117,12 +120,26 @@ namespace games::loveplus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static LPSTR __stdcall GetCommandLineA_hook() {
|
static LPSTR __stdcall GetCommandLineA_hook() {
|
||||||
static std::string lp_args = "-win -noCamera -noWatchDog -noIOError -noIrda -notarget";
|
|
||||||
|
|
||||||
return lp_args.data();
|
return lp_args.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool lp_spam_remover(void *user, const std::string &data, logger::Style style, std::string &out) {
|
||||||
|
if (data.empty() || data[0] != '[') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (data.find("> [INFO] err_code: 0, err_title: , err_str:") != std::string::npos) {
|
||||||
|
out = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
LovePlusGame::LovePlusGame() : Game("LovePlus") {
|
LovePlusGame::LovePlusGame() : Game("LovePlus") {
|
||||||
|
logger::hook_add(lp_spam_remover, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
LovePlusGame::~LovePlusGame() {
|
||||||
|
logger::hook_remove(lp_spam_remover, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LovePlusGame::attach() {
|
void LovePlusGame::attach() {
|
||||||
@@ -157,9 +174,17 @@ namespace games::loveplus {
|
|||||||
HMODULE seteq = libutils::try_library("ad_hd_seteq_dll.dll");
|
HMODULE seteq = libutils::try_library("ad_hd_seteq_dll.dll");
|
||||||
detour::inline_hook((void *) SetEqualizer, libutils::try_proc(seteq, "SetEqualizer"));
|
detour::inline_hook((void *) SetEqualizer, libutils::try_proc(seteq, "SetEqualizer"));
|
||||||
|
|
||||||
|
// set up command line args
|
||||||
|
if (!CAMERA_ENABLE) {
|
||||||
|
lp_args += " -noCamera";
|
||||||
|
}
|
||||||
|
if (GRAPHICS_WINDOWED) {
|
||||||
|
lp_args += " -win";
|
||||||
|
}
|
||||||
// get command line hook
|
// get command line hook
|
||||||
HMODULE lpac = libutils::try_library("lpac.dll");
|
HMODULE lpac = libutils::try_library("lpac.dll");
|
||||||
detour::iat("GetCommandLineA", GetCommandLineA_hook, lpac);
|
detour::iat("GetCommandLineA", GetCommandLineA_hook, lpac);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LovePlusGame::detach() {
|
void LovePlusGame::detach() {
|
||||||
|
|||||||
@@ -4,12 +4,15 @@
|
|||||||
|
|
||||||
namespace games::loveplus {
|
namespace games::loveplus {
|
||||||
|
|
||||||
|
extern bool CAMERA_ENABLE;
|
||||||
|
|
||||||
// touch stuff
|
// touch stuff
|
||||||
void touch_update();
|
void touch_update();
|
||||||
|
|
||||||
class LovePlusGame : public games::Game {
|
class LovePlusGame : public games::Game {
|
||||||
public:
|
public:
|
||||||
LovePlusGame();
|
LovePlusGame();
|
||||||
|
virtual ~LovePlusGame() override;
|
||||||
virtual void attach() override;
|
virtual void attach() override;
|
||||||
virtual void detach() override;
|
virtual void detach() override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ std::vector<Light> &games::museca::get_lights() {
|
|||||||
|
|
||||||
GameAPI::Lights::sortLights(
|
GameAPI::Lights::sortLights(
|
||||||
&lights,
|
&lights,
|
||||||
|
"Start",
|
||||||
|
"Keypad",
|
||||||
"Title R",
|
"Title R",
|
||||||
"Title G",
|
"Title G",
|
||||||
"Title B",
|
"Title B",
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ namespace games::museca {
|
|||||||
// all lights in correct order
|
// all lights in correct order
|
||||||
namespace Lights {
|
namespace Lights {
|
||||||
enum {
|
enum {
|
||||||
|
Start,
|
||||||
|
Keypad,
|
||||||
TitleR,
|
TitleR,
|
||||||
TitleG,
|
TitleG,
|
||||||
TitleB,
|
TitleB,
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace games::qma {
|
|||||||
touch_attach_dx_hook();
|
touch_attach_dx_hook();
|
||||||
|
|
||||||
// cursor
|
// cursor
|
||||||
if (!is_touch_available()) {
|
if (!is_touch_available("QMATouchDevice::open")) {
|
||||||
ShowCursor(true);
|
ShowCursor(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ bool games::rb::ReflecBeatTouchDeviceHandle::open(LPCWSTR lpFileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show cursor on window if mouse is used
|
// show cursor on window if mouse is used
|
||||||
if (!is_touch_available()) {
|
if (!is_touch_available("ReflecBeatTouchDeviceHandle::open")) {
|
||||||
ShowCursor(TRUE);
|
ShowCursor(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public:
|
|||||||
touch_attach_dx_hook();
|
touch_attach_dx_hook();
|
||||||
|
|
||||||
// cursor
|
// cursor
|
||||||
if (!is_touch_available()) {
|
if (!is_touch_available("TwTouchDevice::open")) {
|
||||||
ShowCursor(true);
|
ShowCursor(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ namespace games::sdvx {
|
|||||||
enum SdvxOverlayPosition {
|
enum SdvxOverlayPosition {
|
||||||
SDVX_OVERLAY_TOP,
|
SDVX_OVERLAY_TOP,
|
||||||
SDVX_OVERLAY_MIDDLE,
|
SDVX_OVERLAY_MIDDLE,
|
||||||
SDVX_OVERLAY_BOTTOM
|
SDVX_OVERLAY_BOTTOM,
|
||||||
|
SDVX_OVERLAY_BOTTOM_LEFT,
|
||||||
|
SDVX_OVERLAY_BOTTOM_RIGHT
|
||||||
};
|
};
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ namespace games::shared {
|
|||||||
|
|
||||||
// error
|
// error
|
||||||
if (!clear) {
|
if (!clear) {
|
||||||
log_fatal("sdvx", "could not find path");
|
log_fatal("printer", "could not find path");
|
||||||
}
|
}
|
||||||
|
|
||||||
return "DUMMY";
|
return "DUMMY";
|
||||||
@@ -326,7 +326,7 @@ namespace games::shared {
|
|||||||
memcpy(image_data, pBandImage->baseAddr, (size_t) (image_width * image_height * 3));
|
memcpy(image_data, pBandImage->baseAddr, (size_t) (image_width * image_height * 3));
|
||||||
|
|
||||||
// convert BGR to RGB
|
// convert BGR to RGB
|
||||||
log_info("printer", "converting BGR to RGB...");
|
log_misc("printer", "converting BGR to RGB...");
|
||||||
for (int pixel = 0; pixel < image_width * image_height; pixel++) {
|
for (int pixel = 0; pixel < image_width * image_height; pixel++) {
|
||||||
int index = pixel * 3;
|
int index = pixel * 3;
|
||||||
uint8_t tmp = image_data[index];
|
uint8_t tmp = image_data[index];
|
||||||
@@ -334,25 +334,45 @@ namespace games::shared {
|
|||||||
image_data[index + 2] = tmp;
|
image_data[index + 2] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// flip horizontally
|
if (avs::game::is_model({"KLP", "KFC"})) {
|
||||||
for (int x = 0; x < image_width / 2; x++) {
|
// rotate image clockwise
|
||||||
for (int y = 0; y < image_height; y++) {
|
log_misc("printer", "rotate clockwise...");
|
||||||
int index1 = (y * image_width + x) * 3;
|
auto rotated = new uint8_t[image_width * image_height * 3];
|
||||||
int index2 = (y * image_width + image_width - x - 1) * 3;
|
for (int x = 0; x < image_width; x++) {
|
||||||
uint8_t r = image_data[index1 + 0];
|
for (int y = 0; y < image_height; y++) {
|
||||||
uint8_t g = image_data[index1 + 1];
|
int index1 = (y * image_width + x) * 3;
|
||||||
uint8_t b = image_data[index1 + 2];
|
int index2 = (x * image_height + y) * 3;
|
||||||
image_data[index1 + 0] = image_data[index2 + 0];
|
rotated[index2 + 0] = image_data[index1 + 0];
|
||||||
image_data[index1 + 1] = image_data[index2 + 1];
|
rotated[index2 + 1] = image_data[index1 + 1];
|
||||||
image_data[index1 + 2] = image_data[index2 + 2];
|
rotated[index2 + 2] = image_data[index1 + 2];
|
||||||
image_data[index2 + 0] = r;
|
}
|
||||||
image_data[index2 + 1] = g;
|
}
|
||||||
image_data[index2 + 2] = b;
|
delete[] image_data;
|
||||||
|
image_data = rotated;
|
||||||
|
std::swap(image_width, image_height);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// flip horizontally
|
||||||
|
log_misc("printer", "flip horizontally...");
|
||||||
|
for (int x = 0; x < image_width / 2; x++) {
|
||||||
|
for (int y = 0; y < image_height; y++) {
|
||||||
|
int index1 = (y * image_width + x) * 3;
|
||||||
|
int index2 = (y * image_width + image_width - x - 1) * 3;
|
||||||
|
uint8_t r = image_data[index1 + 0];
|
||||||
|
uint8_t g = image_data[index1 + 1];
|
||||||
|
uint8_t b = image_data[index1 + 2];
|
||||||
|
image_data[index1 + 0] = image_data[index2 + 0];
|
||||||
|
image_data[index1 + 1] = image_data[index2 + 1];
|
||||||
|
image_data[index1 + 2] = image_data[index2 + 2];
|
||||||
|
image_data[index2 + 0] = r;
|
||||||
|
image_data[index2 + 1] = g;
|
||||||
|
image_data[index2 + 2] = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate folders
|
// iterate folders
|
||||||
log_info("printer", "writing files...");
|
log_misc("printer", "writing files...");
|
||||||
for (const auto &path : PRINTER_PATH) {
|
for (const auto &path : PRINTER_PATH) {
|
||||||
for (const auto &format : PRINTER_FORMAT) {
|
for (const auto &format : PRINTER_FORMAT) {
|
||||||
|
|
||||||
|
|||||||
@@ -681,10 +681,27 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDevice(
|
|||||||
// dump presentation parameters
|
// dump presentation parameters
|
||||||
for (size_t i = 0; i < num_adapters; i++) {
|
for (size_t i = 0; i < num_adapters; i++) {
|
||||||
auto *params = &pPresentationParameters[i];
|
auto *params = &pPresentationParameters[i];
|
||||||
|
if (!GRAPHICS_WINDOWED && i == 0) {
|
||||||
if (!GRAPHICS_WINDOWED && i == 0 && GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
GRAPHICS_FS_ORIGINAL_WIDTH = params->BackBufferWidth;
|
||||||
params->BackBufferWidth = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
GRAPHICS_FS_ORIGINAL_HEIGHT = params->BackBufferHeight;
|
||||||
params->BackBufferHeight = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
log_misc("graphics::d3d9", "original resolution: {}x{}", GRAPHICS_FS_ORIGINAL_WIDTH, GRAPHICS_FS_ORIGINAL_HEIGHT);
|
||||||
|
if (GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
||||||
|
log_misc(
|
||||||
|
"graphics::d3d9",
|
||||||
|
"use custom resolution {}x{} => {}x{}",
|
||||||
|
params->BackBufferWidth, params->BackBufferHeight,
|
||||||
|
GRAPHICS_FS_CUSTOM_RESOLUTION.value().first,
|
||||||
|
GRAPHICS_FS_CUSTOM_RESOLUTION.value().second);
|
||||||
|
params->BackBufferWidth = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
||||||
|
params->BackBufferHeight = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
||||||
|
} else if (GRAPHICS_FS_ORIENTATION_SWAP) {
|
||||||
|
log_misc(
|
||||||
|
"graphics::d3d9",
|
||||||
|
"swap full orientation {}x{} => {}x{}",
|
||||||
|
params->BackBufferWidth, params->BackBufferHeight,
|
||||||
|
params->BackBufferHeight, params->BackBufferWidth);
|
||||||
|
std::swap(params->BackBufferWidth, params->BackBufferHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("graphics::d3d9",
|
log_info("graphics::d3d9",
|
||||||
@@ -852,10 +869,27 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDeviceEx(
|
|||||||
|
|
||||||
for (size_t i = 0; i < num_adapters; i++) {
|
for (size_t i = 0; i < num_adapters; i++) {
|
||||||
auto *params = &pPresentationParameters[i];
|
auto *params = &pPresentationParameters[i];
|
||||||
|
if (!GRAPHICS_WINDOWED && i == 0) {
|
||||||
if (!GRAPHICS_WINDOWED && i == 0 && GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
GRAPHICS_FS_ORIGINAL_WIDTH = params->BackBufferWidth;
|
||||||
params->BackBufferWidth = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
GRAPHICS_FS_ORIGINAL_HEIGHT = params->BackBufferHeight;
|
||||||
params->BackBufferHeight = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
log_misc("graphics::d3d9", "original resolution: {}x{}", GRAPHICS_FS_ORIGINAL_WIDTH, GRAPHICS_FS_ORIGINAL_HEIGHT);
|
||||||
|
if (GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
||||||
|
log_misc(
|
||||||
|
"graphics::d3d9",
|
||||||
|
"use custom resolution {}x{} => {}x{}",
|
||||||
|
params->BackBufferWidth, params->BackBufferHeight,
|
||||||
|
GRAPHICS_FS_CUSTOM_RESOLUTION.value().first,
|
||||||
|
GRAPHICS_FS_CUSTOM_RESOLUTION.value().second);
|
||||||
|
params->BackBufferWidth = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
||||||
|
params->BackBufferHeight = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
||||||
|
} else if (GRAPHICS_FS_ORIENTATION_SWAP) {
|
||||||
|
log_misc(
|
||||||
|
"graphics::d3d9",
|
||||||
|
"swap full orientation {}x{} => {}x{}",
|
||||||
|
params->BackBufferWidth, params->BackBufferHeight,
|
||||||
|
params->BackBufferHeight, params->BackBufferWidth);
|
||||||
|
std::swap(params->BackBufferWidth, params->BackBufferHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("graphics::d3d9",
|
log_info("graphics::d3d9",
|
||||||
@@ -882,9 +916,13 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDeviceEx(
|
|||||||
for (size_t i = 0; i < num_adapters; i++) {
|
for (size_t i = 0; i < num_adapters; i++) {
|
||||||
auto *fullscreen_display_mode = &pFullscreenDisplayMode[i];
|
auto *fullscreen_display_mode = &pFullscreenDisplayMode[i];
|
||||||
|
|
||||||
if (!GRAPHICS_WINDOWED && i == 0 && GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
if (!GRAPHICS_WINDOWED && i == 0) {
|
||||||
fullscreen_display_mode->Width = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
if (GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
||||||
fullscreen_display_mode->Height = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
fullscreen_display_mode->Width = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
||||||
|
fullscreen_display_mode->Height = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
||||||
|
} else if (GRAPHICS_FS_ORIENTATION_SWAP) {
|
||||||
|
std::swap(fullscreen_display_mode->Width, fullscreen_display_mode->Height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("graphics::d3d9",
|
log_info("graphics::d3d9",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "hooks/graphics/graphics.h"
|
#include "hooks/graphics/graphics.h"
|
||||||
#include "overlay/overlay.h"
|
#include "overlay/overlay.h"
|
||||||
#include "util/flags_helper.h"
|
#include "util/flags_helper.h"
|
||||||
|
#include "util/utils.h"
|
||||||
#include "cfg/screen_resize.h"
|
#include "cfg/screen_resize.h"
|
||||||
|
|
||||||
#include "d3d9_backend.h"
|
#include "d3d9_backend.h"
|
||||||
@@ -692,89 +693,181 @@ static IDirect3DSurface9 *backbuffer = nullptr;
|
|||||||
static LPDIRECT3DSWAPCHAIN9 mSwapChain = nullptr;
|
static LPDIRECT3DSWAPCHAIN9 mSwapChain = nullptr;
|
||||||
static IDirect3DTexture9* tex;
|
static IDirect3DTexture9* tex;
|
||||||
|
|
||||||
|
static UINT topSurface_width = 0;
|
||||||
|
static UINT topSurface_height = 0;
|
||||||
|
static float topSurface_aspect_ratio = 1.f;
|
||||||
|
|
||||||
void SurfaceHook(IDirect3DDevice9 *pReal) {
|
void SurfaceHook(IDirect3DDevice9 *pReal) {
|
||||||
// log_misc("graphics::d3d9", "SurfaceHook called");
|
|
||||||
D3DPRESENT_PARAMETERS param {};
|
D3DPRESENT_PARAMETERS param {};
|
||||||
|
|
||||||
pReal->GetSwapChain(0, &mSwapChain);
|
pReal->GetSwapChain(0, &mSwapChain);
|
||||||
mSwapChain->GetPresentParameters(¶m);
|
mSwapChain->GetPresentParameters(¶m);
|
||||||
|
|
||||||
|
// phase 0 - create a surface that has the same aspect ratio as the original back buffer
|
||||||
|
// but larger in size. this is needed to ensure that when the user zooms out, we have
|
||||||
|
// sufficient buffer space (black border) around the original image
|
||||||
|
//
|
||||||
|
// (only done once)
|
||||||
if (!topSurface) {
|
if (!topSurface) {
|
||||||
if (pReal->CreateTexture(4096, 4096, 1,
|
topSurface_width = param.BackBufferWidth * 3;
|
||||||
|
topSurface_height = param.BackBufferHeight * 3;
|
||||||
|
topSurface_aspect_ratio = (float)topSurface_width / (float)topSurface_height;
|
||||||
|
if (pReal->CreateTexture(topSurface_width, topSurface_height, 1,
|
||||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
||||||
D3DPOOL_DEFAULT, &tex, NULL) != D3D_OK) {
|
D3DPOOL_DEFAULT, &tex, NULL) != D3D_OK) {
|
||||||
log_misc("graphics::d3d9", "create texture failed");
|
log_warning("graphics::d3d9", "SurfaceHook - create texture failed");
|
||||||
|
|
||||||
}
|
}
|
||||||
log_misc("graphics::d3d9", "Backbuffer: {} {} {}",
|
|
||||||
param.BackBufferWidth, param.BackBufferHeight, param.BackBufferCount);
|
|
||||||
tex->GetSurfaceLevel(0, &topSurface);
|
|
||||||
|
|
||||||
|
log_misc(
|
||||||
|
"graphics::d3d9", "SurfaceHook - Backbuffer: {} {} {}",
|
||||||
|
param.BackBufferWidth, param.BackBufferHeight, param.BackBufferCount);
|
||||||
|
|
||||||
|
tex->GetSurfaceLevel(0, &topSurface);
|
||||||
if (mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer) != D3D_OK) {
|
if (mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer) != D3D_OK) {
|
||||||
log_misc("graphics::d3d9", "GetBackBuffer failed");
|
log_warning("graphics::d3d9", "SurfaceHook - GetBackBuffer failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int rectLeft = 1024;
|
// pre-calculate dimensions used for phase 1
|
||||||
const int rectTop = 576;
|
const int rectLeft = param.BackBufferWidth;
|
||||||
|
const int rectTop = param.BackBufferHeight;
|
||||||
const int w = param.BackBufferWidth;
|
const int w = param.BackBufferWidth;
|
||||||
const int h = param.BackBufferHeight;
|
const int h = param.BackBufferHeight;
|
||||||
|
|
||||||
D3DLOCKED_RECT rect;
|
D3DLOCKED_RECT rect;
|
||||||
|
HRESULT hr;
|
||||||
|
topSurface->LockRect(&rect, NULL, D3DLOCK_DONOTWAIT);
|
||||||
|
|
||||||
|
// phase 1 - copy the original back buffer onto the new surface.
|
||||||
|
// we draw it 1:1 in the center of the surface.
|
||||||
|
// if orientation is swapped, fix up the rect and draw it in the center.
|
||||||
|
//
|
||||||
|
// for this phase we always render with the same rect so that it's always overwritten
|
||||||
|
// by a new frame on the same spot.
|
||||||
|
RECT originRect {
|
||||||
|
rectLeft,
|
||||||
|
rectTop,
|
||||||
|
(LONG)(rectLeft + w),
|
||||||
|
(LONG)(rectTop + h),
|
||||||
|
};
|
||||||
|
if (GRAPHICS_FS_ORIENTATION_SWAP) {
|
||||||
|
originRect.left = (topSurface_width / 2) - (GRAPHICS_FS_ORIGINAL_WIDTH / 2);
|
||||||
|
originRect.top = (topSurface_height / 2) - (GRAPHICS_FS_ORIGINAL_HEIGHT / 2);
|
||||||
|
originRect.right = originRect.left + GRAPHICS_FS_ORIGINAL_WIDTH;
|
||||||
|
originRect.bottom = originRect.top + GRAPHICS_FS_ORIGINAL_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// log_misc(
|
||||||
|
// "graphics::d3d9", "originRect: {} {} {} {}",
|
||||||
|
// originRect.left, originRect.top, originRect.right, originRect.bottom);
|
||||||
|
|
||||||
|
hr = pReal->StretchRect(
|
||||||
|
backbuffer, nullptr,
|
||||||
|
topSurface, &originRect,
|
||||||
|
D3DTEXF_LINEAR);
|
||||||
|
if (hr != D3D_OK) {
|
||||||
|
log_warning(
|
||||||
|
"graphics::d3d9",
|
||||||
|
"SurfaceHook - StretchRect backbuffer failed, rect: {} {} {} {}",
|
||||||
|
originRect.left, originRect.top, originRect.right, originRect.bottom);
|
||||||
|
}
|
||||||
|
topSurface->UnlockRect();
|
||||||
|
|
||||||
|
// phase 2 - viewport calculation - do the actual zoom / offset math
|
||||||
|
// figure out what region of the surface to copy back to the back buffer.
|
||||||
RECT targetRect {
|
RECT targetRect {
|
||||||
rectLeft,
|
rectLeft,
|
||||||
rectTop,
|
rectTop,
|
||||||
(LONG)(rectLeft + w),
|
(LONG)(rectLeft + w),
|
||||||
(LONG)(rectTop + h),
|
(LONG)(rectTop + h),
|
||||||
};
|
};
|
||||||
|
if (cfg::SCREENRESIZE->enable_screen_resize) {
|
||||||
|
auto& scene = cfg::SCREENRESIZE->scene_settings[cfg::SCREENRESIZE->screen_resize_current_scene];
|
||||||
|
auto w_new = w / scene.scale_x;
|
||||||
|
auto h_new = h / scene.scale_y;
|
||||||
|
|
||||||
// stretch to add top/left offset to avoid going negative
|
// make sure the scaling is within bounds
|
||||||
topSurface->LockRect(&rect, NULL, D3DLOCK_DONOTWAIT);
|
if (cfg::SCREENRESIZE->client_keep_aspect_ratio) {
|
||||||
auto hr = pReal->StretchRect(
|
if (w_new > topSurface_width || h_new > topSurface_height) {
|
||||||
backbuffer, nullptr,
|
w_new = topSurface_width;
|
||||||
topSurface, &targetRect,
|
h_new = topSurface_height;
|
||||||
D3DTEXF_LINEAR);
|
}
|
||||||
|
} else {
|
||||||
|
w_new = MIN(w_new, topSurface_width);
|
||||||
|
h_new = MIN(h_new, topSurface_height);
|
||||||
|
}
|
||||||
|
|
||||||
if (hr != D3D_OK) {
|
targetRect.left = (topSurface_width / 2) - (w_new / 2) - scene.offset_x;
|
||||||
log_misc("graphics::d3d9", "StretchRect backbuffer failed");
|
targetRect.top = (topSurface_height / 2) - (h_new / 2) - scene.offset_y;
|
||||||
}
|
targetRect.right = targetRect.left + w_new;
|
||||||
topSurface->UnlockRect();
|
targetRect.bottom = targetRect.top + h_new;
|
||||||
|
|
||||||
// do the actual zoom / offset math
|
// boundary check to prevent StretchRect failures
|
||||||
auto& scene = cfg::SCREENRESIZE->scene_settings[cfg::SCREENRESIZE->screen_resize_current_scene];
|
if (targetRect.left < 0) {
|
||||||
if (scene.centered) {
|
targetRect.left = 0;
|
||||||
targetRect.right = (w + rectLeft) / scene.scale_x;
|
targetRect.right = w_new;
|
||||||
targetRect.bottom = (h + rectTop) / scene.scale_y;
|
} else if (targetRect.right > (LONG)topSurface_width) {
|
||||||
const LONG deltaH = ((targetRect.bottom - targetRect.top) - h) / 2;
|
targetRect.left = topSurface_width - w_new;
|
||||||
const LONG deltaW = ((targetRect.right - targetRect.left) - w) / 2;
|
targetRect.right = topSurface_width;
|
||||||
targetRect.top -= deltaH;
|
}
|
||||||
targetRect.bottom -= deltaH;
|
if (targetRect.top < 0) {
|
||||||
targetRect.left -= deltaW;
|
targetRect.top = 0;
|
||||||
targetRect.right -= deltaW;
|
targetRect.bottom = h_new;
|
||||||
} else {
|
} else if (targetRect.bottom > (LONG)topSurface_height) {
|
||||||
targetRect.left -= scene.offset_x;
|
targetRect.top = topSurface_height - h_new;
|
||||||
targetRect.top += scene.offset_y;
|
targetRect.bottom = topSurface_height;
|
||||||
targetRect.right = -scene.offset_x;
|
}
|
||||||
targetRect.right += (w + rectLeft) / scene.scale_x;
|
|
||||||
targetRect.bottom = scene.offset_y;
|
} else if (GRAPHICS_FS_ORIENTATION_SWAP) {
|
||||||
targetRect.bottom += (h + rectTop) / scene.scale_y;
|
// increase the viewport to fit the image on screen (effectively, zoom out a little)
|
||||||
|
if (GRAPHICS_FS_ORIGINAL_WIDTH < GRAPHICS_FS_ORIGINAL_HEIGHT) {
|
||||||
|
// portrait game on landscape display
|
||||||
|
// height should match the original image
|
||||||
|
targetRect.top = originRect.top;
|
||||||
|
targetRect.bottom = originRect.bottom;
|
||||||
|
|
||||||
|
// width of viewport should be wider, effectively shrinking the image on x-axis when rendered
|
||||||
|
const auto w_new = GRAPHICS_FS_ORIGINAL_HEIGHT * topSurface_aspect_ratio;
|
||||||
|
targetRect.left = (topSurface_width / 2) - (w_new / 2);
|
||||||
|
targetRect.right = targetRect.left + w_new;
|
||||||
|
} else {
|
||||||
|
// landscape game on portrait display
|
||||||
|
targetRect.left = originRect.left;
|
||||||
|
targetRect.right = originRect.right;
|
||||||
|
|
||||||
|
// height of viewport should be taller, effectively shrinking the image on y-axis when rendered
|
||||||
|
const auto h_new = GRAPHICS_FS_ORIGINAL_WIDTH / topSurface_aspect_ratio;
|
||||||
|
targetRect.top = (topSurface_height / 2) - (h_new / 2);
|
||||||
|
targetRect.bottom = targetRect.top + h_new;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw to back buffer
|
// log_misc("graphics::d3d9", "targetRect: {} {} {} {}",
|
||||||
|
// targetRect.left, targetRect.top, targetRect.right, targetRect.bottom);
|
||||||
|
|
||||||
|
// phase 3 - draw the surface to back buffer
|
||||||
backbuffer->LockRect(&rect, NULL, D3DLOCK_DONOTWAIT);
|
backbuffer->LockRect(&rect, NULL, D3DLOCK_DONOTWAIT);
|
||||||
|
bool use_linear_filter = true;
|
||||||
|
if (cfg::SCREENRESIZE->enable_screen_resize) {
|
||||||
|
use_linear_filter = cfg::SCREENRESIZE->enable_linear_filter;
|
||||||
|
}
|
||||||
hr = pReal->StretchRect(
|
hr = pReal->StretchRect(
|
||||||
topSurface, &targetRect,
|
topSurface, &targetRect,
|
||||||
backbuffer, nullptr,
|
backbuffer, nullptr,
|
||||||
cfg::SCREENRESIZE->enable_linear_filter ? D3DTEXF_LINEAR : D3DTEXF_NONE);
|
use_linear_filter ? D3DTEXF_LINEAR : D3DTEXF_NONE);
|
||||||
backbuffer->UnlockRect();
|
backbuffer->UnlockRect();
|
||||||
if (hr != D3D_OK) {
|
if (hr != D3D_OK) {
|
||||||
log_misc("graphics::d3d9", "StretchRect targetRect failed");
|
log_warning(
|
||||||
|
"graphics::d3d9",
|
||||||
|
"SurfaceHook - StretchRect targetRect failed, you must reset image scaling to default values! rect: {} {} {} {}",
|
||||||
|
targetRect.left, targetRect.top, targetRect.right, targetRect.bottom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::EndScene() {
|
HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::EndScene() {
|
||||||
WRAP_DEBUG;
|
WRAP_DEBUG;
|
||||||
|
|
||||||
if (cfg::SCREENRESIZE->enable_screen_resize) {
|
if (cfg::SCREENRESIZE->enable_screen_resize || GRAPHICS_FS_ORIENTATION_SWAP) {
|
||||||
SurfaceHook(pReal);
|
SurfaceHook(pReal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ bool GRAPHICS_9_ON_12_REQUESTED_BY_GAME = false;
|
|||||||
bool SUBSCREEN_FORCE_REDRAW = false;
|
bool SUBSCREEN_FORCE_REDRAW = false;
|
||||||
bool D3D9_DEVICE_HOOK_DISABLE = false;
|
bool D3D9_DEVICE_HOOK_DISABLE = false;
|
||||||
std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_FS_CUSTOM_RESOLUTION;
|
std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_FS_CUSTOM_RESOLUTION;
|
||||||
|
bool GRAPHICS_FS_ORIENTATION_SWAP = false;
|
||||||
|
uint32_t GRAPHICS_FS_ORIGINAL_WIDTH = 0;
|
||||||
|
uint32_t GRAPHICS_FS_ORIGINAL_HEIGHT = 0;
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
std::string GRAPHICS_DEVICEID = "PCI\\VEN_1002&DEV_7146";
|
std::string GRAPHICS_DEVICEID = "PCI\\VEN_1002&DEV_7146";
|
||||||
@@ -371,6 +374,27 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC
|
|||||||
if ((is_tdj_sub_window && GRAPHICS_IIDX_WSUB) || is_sdvx_sub_window) {
|
if ((is_tdj_sub_window && GRAPHICS_IIDX_WSUB) || is_sdvx_sub_window) {
|
||||||
dwStyle &= ~(WS_MAXIMIZEBOX);
|
dwStyle &= ~(WS_MAXIMIZEBOX);
|
||||||
}
|
}
|
||||||
|
if ((is_tdj_sub_window || is_sdvx_sub_window) && GRAPHICS_WSUB_BORDERLESS) {
|
||||||
|
dwStyle &= ~(WS_OVERLAPPEDWINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_sdvx_sub_window) {
|
||||||
|
graphics_load_windowed_subscreen_parameters();
|
||||||
|
if (GRAPHICS_WSUB_SIZE.has_value()) {
|
||||||
|
nWidth = GRAPHICS_WSUB_WIDTH;
|
||||||
|
nHeight = GRAPHICS_WSUB_HEIGHT;
|
||||||
|
} else {
|
||||||
|
GRAPHICS_WSUB_WIDTH = nWidth;
|
||||||
|
GRAPHICS_WSUB_HEIGHT = nHeight;
|
||||||
|
}
|
||||||
|
if (GRAPHICS_WSUB_POS.has_value()) {
|
||||||
|
x = GRAPHICS_WSUB_X;
|
||||||
|
y = GRAPHICS_WSUB_Y;
|
||||||
|
} else {
|
||||||
|
GRAPHICS_WSUB_X = x;
|
||||||
|
GRAPHICS_WSUB_Y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// call original
|
// call original
|
||||||
HWND result = CreateWindowExA_orig(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight,
|
HWND result = CreateWindowExA_orig(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight,
|
||||||
@@ -526,11 +550,11 @@ static BOOL WINAPI MoveWindow_hook(HWND hWnd, int X, int Y, int nWidth, int nHei
|
|||||||
|
|
||||||
dwStyle = GetWindowLongA(hWnd, GWL_STYLE);
|
dwStyle = GetWindowLongA(hWnd, GWL_STYLE);
|
||||||
|
|
||||||
SetRect(&rect, 0, 0, GRAPHICS_IIDX_WSUB_WIDTH, GRAPHICS_IIDX_WSUB_HEIGHT);
|
SetRect(&rect, 0, 0, GRAPHICS_WSUB_WIDTH, GRAPHICS_WSUB_HEIGHT);
|
||||||
AdjustWindowRect(&rect, dwStyle, 0);
|
AdjustWindowRect(&rect, dwStyle, 0);
|
||||||
|
|
||||||
X = GRAPHICS_IIDX_WSUB_X;
|
X = GRAPHICS_WSUB_X;
|
||||||
Y = GRAPHICS_IIDX_WSUB_Y;
|
Y = GRAPHICS_WSUB_Y;
|
||||||
|
|
||||||
nWidth = rect.right - rect.left;
|
nWidth = rect.right - rect.left;
|
||||||
nHeight = rect.bottom - rect.top;
|
nHeight = rect.bottom - rect.top;
|
||||||
@@ -862,6 +886,9 @@ void graphics_hook_subscreen_window(HWND hWnd) {
|
|||||||
WSUB_WNDPROC_ORIG = reinterpret_cast<WNDPROC>(GetWindowLongPtrA(hWnd, GWLP_WNDPROC));
|
WSUB_WNDPROC_ORIG = reinterpret_cast<WNDPROC>(GetWindowLongPtrA(hWnd, GWLP_WNDPROC));
|
||||||
SetWindowLongPtrA(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WsubWindowProc));
|
SetWindowLongPtrA(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WsubWindowProc));
|
||||||
}
|
}
|
||||||
|
if (GRAPHICS_WSUB_ALWAYS_ON_TOP) {
|
||||||
|
graphics_update_z_order(hWnd, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void graphics_screens_register(int screen) {
|
void graphics_screens_register(int screen) {
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ extern std::optional<int> GRAPHICS_FORCE_VSYNC_BUFFER;
|
|||||||
extern bool GRAPHICS_FORCE_SINGLE_ADAPTER;
|
extern bool GRAPHICS_FORCE_SINGLE_ADAPTER;
|
||||||
extern bool GRAPHICS_PREVENT_SECONDARY_WINDOW;
|
extern bool GRAPHICS_PREVENT_SECONDARY_WINDOW;
|
||||||
extern std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_FS_CUSTOM_RESOLUTION;
|
extern std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_FS_CUSTOM_RESOLUTION;
|
||||||
|
extern bool GRAPHICS_FS_ORIENTATION_SWAP;
|
||||||
|
extern uint32_t GRAPHICS_FS_ORIGINAL_WIDTH;
|
||||||
|
extern uint32_t GRAPHICS_FS_ORIGINAL_HEIGHT;
|
||||||
|
|
||||||
extern graphics_dx9on12_state GRAPHICS_9_ON_12_STATE;
|
extern graphics_dx9on12_state GRAPHICS_9_ON_12_STATE;
|
||||||
extern bool GRAPHICS_9_ON_12_REQUESTED_BY_GAME;
|
extern bool GRAPHICS_9_ON_12_REQUESTED_BY_GAME;
|
||||||
@@ -47,12 +50,14 @@ extern bool GRAPHICS_WINDOW_ALWAYS_ON_TOP;
|
|||||||
extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE;
|
extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE;
|
||||||
|
|
||||||
extern bool GRAPHICS_IIDX_WSUB;
|
extern bool GRAPHICS_IIDX_WSUB;
|
||||||
extern std::optional<std::string> GRAPHICS_IIDX_WSUB_SIZE;
|
extern std::optional<std::string> GRAPHICS_WSUB_SIZE;
|
||||||
extern std::optional<std::string> GRAPHICS_IIDX_WSUB_POS;
|
extern std::optional<std::string> GRAPHICS_WSUB_POS;
|
||||||
extern int GRAPHICS_IIDX_WSUB_WIDTH;
|
extern int GRAPHICS_WSUB_WIDTH;
|
||||||
extern int GRAPHICS_IIDX_WSUB_HEIGHT;
|
extern int GRAPHICS_WSUB_HEIGHT;
|
||||||
extern int GRAPHICS_IIDX_WSUB_X;
|
extern int GRAPHICS_WSUB_X;
|
||||||
extern int GRAPHICS_IIDX_WSUB_Y;
|
extern int GRAPHICS_WSUB_Y;
|
||||||
|
extern bool GRAPHICS_WSUB_BORDERLESS;
|
||||||
|
extern bool GRAPHICS_WSUB_ALWAYS_ON_TOP;
|
||||||
extern HWND TDJ_SUBSCREEN_WINDOW;
|
extern HWND TDJ_SUBSCREEN_WINDOW;
|
||||||
extern HWND SDVX_SUBSCREEN_WINDOW;
|
extern HWND SDVX_SUBSCREEN_WINDOW;
|
||||||
|
|
||||||
@@ -91,7 +96,7 @@ std::string graphics_screenshot_genpath();
|
|||||||
void graphics_windowed_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
void graphics_windowed_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
void graphics_capture_initial_window(HWND hWnd);
|
void graphics_capture_initial_window(HWND hWnd);
|
||||||
void graphics_update_window_style(HWND hWnd);
|
void graphics_update_window_style(HWND hWnd);
|
||||||
void graphics_update_z_order(HWND hWnd);
|
void graphics_update_z_order(HWND hWnd, bool always_on_top);
|
||||||
void graphics_move_resize_window(HWND hWnd);
|
void graphics_move_resize_window(HWND hWnd);
|
||||||
bool graphics_window_change_crashes_game();
|
bool graphics_window_change_crashes_game();
|
||||||
void graphics_load_windowed_subscreen_parameters();
|
void graphics_load_windowed_subscreen_parameters();
|
||||||
|
|||||||
@@ -26,12 +26,14 @@ bool GRAPHICS_WINDOW_BACKBUFFER_SCALE = false;
|
|||||||
|
|
||||||
// IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed
|
// IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed
|
||||||
bool GRAPHICS_IIDX_WSUB = false;
|
bool GRAPHICS_IIDX_WSUB = false;
|
||||||
std::optional<std::string> GRAPHICS_IIDX_WSUB_SIZE;
|
std::optional<std::string> GRAPHICS_WSUB_SIZE;
|
||||||
std::optional<std::string> GRAPHICS_IIDX_WSUB_POS;
|
std::optional<std::string> GRAPHICS_WSUB_POS;
|
||||||
int GRAPHICS_IIDX_WSUB_WIDTH = 1280;
|
int GRAPHICS_WSUB_WIDTH = 1280;
|
||||||
int GRAPHICS_IIDX_WSUB_HEIGHT = 720;
|
int GRAPHICS_WSUB_HEIGHT = 720;
|
||||||
int GRAPHICS_IIDX_WSUB_X = 0;
|
int GRAPHICS_WSUB_X = 0;
|
||||||
int GRAPHICS_IIDX_WSUB_Y = 0;
|
int GRAPHICS_WSUB_Y = 0;
|
||||||
|
bool GRAPHICS_WSUB_BORDERLESS = false;
|
||||||
|
bool GRAPHICS_WSUB_ALWAYS_ON_TOP = false;
|
||||||
|
|
||||||
// these flags are carefully constructed to ensure maximum compatibility
|
// these flags are carefully constructed to ensure maximum compatibility
|
||||||
// (e.g., DDR likes to hang when SetWindowPos is called with certain params)
|
// (e.g., DDR likes to hang when SetWindowPos is called with certain params)
|
||||||
@@ -108,7 +110,7 @@ void graphics_capture_initial_window(HWND hWnd) {
|
|||||||
}
|
}
|
||||||
if (cfg::SCREENRESIZE->window_always_on_top) {
|
if (cfg::SCREENRESIZE->window_always_on_top) {
|
||||||
log_info("graphics-windowed", "change window z-order - always on top");
|
log_info("graphics-windowed", "change window z-order - always on top");
|
||||||
graphics_update_z_order(hWnd);
|
graphics_update_z_order(hWnd, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure spicetouch coordinates are initialized
|
// ensure spicetouch coordinates are initialized
|
||||||
@@ -169,29 +171,29 @@ void graphics_load_windowed_subscreen_parameters() {
|
|||||||
|
|
||||||
log_debug("graphics-windowed", "graphics_load_windowed_subscreen_parameters called");
|
log_debug("graphics-windowed", "graphics_load_windowed_subscreen_parameters called");
|
||||||
|
|
||||||
if (GRAPHICS_IIDX_WSUB_SIZE.has_value()) {
|
if (GRAPHICS_WSUB_SIZE.has_value()) {
|
||||||
log_debug(
|
log_debug(
|
||||||
"graphics-windowed",
|
"graphics-windowed",
|
||||||
"graphics_load_windowed_parameters - load GRAPHICS_IIDX_WSUB_SIZE");
|
"graphics_load_windowed_parameters - load GRAPHICS_WSUB_SIZE");
|
||||||
|
|
||||||
std::pair<uint32_t, uint32_t> result;
|
std::pair<uint32_t, uint32_t> result;
|
||||||
if (parse_width_height(GRAPHICS_IIDX_WSUB_SIZE.value(), result)) {
|
if (parse_width_height(GRAPHICS_WSUB_SIZE.value(), result)) {
|
||||||
GRAPHICS_IIDX_WSUB_WIDTH = result.first;
|
GRAPHICS_WSUB_WIDTH = result.first;
|
||||||
GRAPHICS_IIDX_WSUB_HEIGHT = result.second;
|
GRAPHICS_WSUB_HEIGHT = result.second;
|
||||||
} else {
|
} else {
|
||||||
log_warning("graphics-windowed", "failed to parse -wsubsize");
|
log_warning("graphics-windowed", "failed to parse -wsubsize");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GRAPHICS_IIDX_WSUB_POS.has_value()) {
|
if (GRAPHICS_WSUB_POS.has_value()) {
|
||||||
log_debug(
|
log_debug(
|
||||||
"graphics-windowed",
|
"graphics-windowed",
|
||||||
"graphics_load_windowed_parameters - load GRAPHICS_IIDX_WSUB_POS");
|
"graphics_load_windowed_parameters - load GRAPHICS_WSUB_POS");
|
||||||
|
|
||||||
std::pair<uint32_t, uint32_t> result;
|
std::pair<uint32_t, uint32_t> result;
|
||||||
if (parse_width_height(GRAPHICS_IIDX_WSUB_POS.value(), result)) {
|
if (parse_width_height(GRAPHICS_WSUB_POS.value(), result)) {
|
||||||
GRAPHICS_IIDX_WSUB_X = result.first;
|
GRAPHICS_WSUB_X = result.first;
|
||||||
GRAPHICS_IIDX_WSUB_Y = result.second;
|
GRAPHICS_WSUB_Y = result.second;
|
||||||
} else {
|
} else {
|
||||||
log_warning("graphics-windowed", "failed to parse -wsubpos");
|
log_warning("graphics-windowed", "failed to parse -wsubpos");
|
||||||
}
|
}
|
||||||
@@ -398,7 +400,7 @@ void graphics_update_window_style(HWND hWnd) {
|
|||||||
log_debug("graphics-windowed", "graphics_update_window_style returned");
|
log_debug("graphics-windowed", "graphics_update_window_style returned");
|
||||||
}
|
}
|
||||||
|
|
||||||
void graphics_update_z_order(HWND hWnd) {
|
void graphics_update_z_order(HWND hWnd, bool always_on_top) {
|
||||||
if (!GRAPHICS_WINDOWED) {
|
if (!GRAPHICS_WINDOWED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -406,7 +408,7 @@ void graphics_update_z_order(HWND hWnd) {
|
|||||||
log_debug("graphics-windowed", "graphics_update_z_order called");
|
log_debug("graphics-windowed", "graphics_update_z_order called");
|
||||||
|
|
||||||
HWND insert_after = nullptr;
|
HWND insert_after = nullptr;
|
||||||
if (cfg::SCREENRESIZE->window_always_on_top) {
|
if (always_on_top) {
|
||||||
insert_after = HWND_TOPMOST;
|
insert_after = HWND_TOPMOST;
|
||||||
} else {
|
} else {
|
||||||
insert_after = HWND_NOTOPMOST;
|
insert_after = HWND_NOTOPMOST;
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ void networkhook_init() {
|
|||||||
strncpy(s_prefix, inet_ntoa(prefix), 16);
|
strncpy(s_prefix, inet_ntoa(prefix), 16);
|
||||||
|
|
||||||
// log preferences
|
// log preferences
|
||||||
log_info("network", "Network preferences: {}", s_network, s_subnet, s_prefix);
|
// log_info("network", "Network preferences: {}, {}, {}", s_network, s_subnet, s_prefix);
|
||||||
|
|
||||||
// GetAdaptersInfo hook
|
// GetAdaptersInfo hook
|
||||||
auto orig_addr = detour::iat_try(
|
auto orig_addr = detour::iat_try(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <cfg/configurator.h>
|
#include <cfg/configurator.h>
|
||||||
|
|
||||||
|
#include "api/modules/capture.h"
|
||||||
#include "acio/acio.h"
|
#include "acio/acio.h"
|
||||||
#include "acio/icca/icca.h"
|
#include "acio/icca/icca.h"
|
||||||
#include "api/controller.h"
|
#include "api/controller.h"
|
||||||
@@ -124,6 +125,8 @@ std::string LOG_FILE_PATH = "";
|
|||||||
int LAUNCHER_ARGC = 0;
|
int LAUNCHER_ARGC = 0;
|
||||||
char **LAUNCHER_ARGV = nullptr;
|
char **LAUNCHER_ARGV = nullptr;
|
||||||
std::unique_ptr<std::vector<Option>> LAUNCHER_OPTIONS;
|
std::unique_ptr<std::vector<Option>> LAUNCHER_OPTIONS;
|
||||||
|
|
||||||
|
std::mutex CARD_OVERRIDES_LOCK;
|
||||||
std::string CARD_OVERRIDES[2];
|
std::string CARD_OVERRIDES[2];
|
||||||
|
|
||||||
// sub-systems
|
// sub-systems
|
||||||
@@ -217,6 +220,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
bool attach_qks = false;
|
bool attach_qks = false;
|
||||||
bool attach_mfg = false;
|
bool attach_mfg = false;
|
||||||
bool attach_museca = false;
|
bool attach_museca = false;
|
||||||
|
bool show_cursor_if_no_touch = false;
|
||||||
|
|
||||||
// misc settings
|
// misc settings
|
||||||
size_t user_heap_size = 0;
|
size_t user_heap_size = 0;
|
||||||
@@ -240,6 +244,11 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
// parse arguments
|
// parse arguments
|
||||||
LAUNCHER_OPTIONS = launcher::parse_options(argc, argv);
|
LAUNCHER_OPTIONS = launcher::parse_options(argc, argv);
|
||||||
|
|
||||||
|
// command line override (must be done before merging options with cfg)
|
||||||
|
if (LAUNCHER_OPTIONS->at(launcher::Options::OptionConflictResolution).value_bool()) {
|
||||||
|
launcher::USE_CMD_OVERRIDE = true;
|
||||||
|
}
|
||||||
|
|
||||||
// determine config file path - must be done before anything else
|
// determine config file path - must be done before anything else
|
||||||
const auto &cfg_path = LAUNCHER_OPTIONS->at(launcher::Options::ConfigurationPath);
|
const auto &cfg_path = LAUNCHER_OPTIONS->at(launcher::Options::ConfigurationPath);
|
||||||
if (cfg_path.is_active()) {
|
if (cfg_path.is_active()) {
|
||||||
@@ -281,6 +290,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
cfg::CONFIGURATOR_TYPE = cfg::ConfigType::Config;
|
cfg::CONFIGURATOR_TYPE = cfg::ConfigType::Config;
|
||||||
cfg_run = true;
|
cfg_run = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::EAmusementEmulation].value_bool() &&
|
if (options[launcher::Options::EAmusementEmulation].value_bool() &&
|
||||||
options[launcher::Options::ServiceURL].is_active() &&
|
options[launcher::Options::ServiceURL].is_active() &&
|
||||||
!cfg::CONFIGURATOR_STANDALONE) {
|
!cfg::CONFIGURATOR_STANDALONE) {
|
||||||
@@ -367,15 +377,6 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
GRAPHICS_FORCE_SINGLE_ADAPTER = false;
|
GRAPHICS_FORCE_SINGLE_ADAPTER = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::FullscreenResolution].is_active()) {
|
|
||||||
std::pair<uint32_t, uint32_t> result;
|
|
||||||
if (parse_width_height(options[launcher::Options::FullscreenResolution].value_text(), result)) {
|
|
||||||
GRAPHICS_FS_CUSTOM_RESOLUTION = result;
|
|
||||||
} else {
|
|
||||||
log_warning("launcher", "failed to parse -forceres");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options[launcher::Options::spice2x_NvapiProfile].value_bool() && !cfg::CONFIGURATOR_STANDALONE) {
|
if (options[launcher::Options::spice2x_NvapiProfile].value_bool() && !cfg::CONFIGURATOR_STANDALONE) {
|
||||||
nvapi::ADD_PROFILE = true;
|
nvapi::ADD_PROFILE = true;
|
||||||
}
|
}
|
||||||
@@ -448,7 +449,12 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_TOP;
|
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_TOP;
|
||||||
} else if (txt == "center") {
|
} else if (txt == "center") {
|
||||||
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_MIDDLE;
|
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_MIDDLE;
|
||||||
|
} else if (txt == "bottomleft") {
|
||||||
|
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_BOTTOM_LEFT;
|
||||||
|
} else if (txt == "bottomright") {
|
||||||
|
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_BOTTOM_RIGHT;
|
||||||
}
|
}
|
||||||
|
// else - bottom
|
||||||
}
|
}
|
||||||
if (options[launcher::Options::spice2x_SDVXSubRedraw].value_bool()) {
|
if (options[launcher::Options::spice2x_SDVXSubRedraw].value_bool()) {
|
||||||
SUBSCREEN_FORCE_REDRAW = true;
|
SUBSCREEN_FORCE_REDRAW = true;
|
||||||
@@ -662,21 +668,42 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::SDVXPrinterEmulation].value_bool()) {
|
if (options[launcher::Options::SDVXPrinterEmulation].value_bool()) {
|
||||||
attach_cpusbxpkm_printer = true;
|
attach_cpusbxpkm_printer = true;
|
||||||
}
|
}
|
||||||
if (options[launcher::Options::SDVXPrinterOutputOverwrite].value_bool()) {
|
|
||||||
|
// printer overwrite
|
||||||
|
if (options[launcher::Options::SDVXPrinterOutputOverwrite].value_bool() ||
|
||||||
|
options[launcher::Options::LovePlusPrinterOutputOverwrite].value_bool()) {
|
||||||
games::shared::PRINTER_OVERWRITE_FILE = true;
|
games::shared::PRINTER_OVERWRITE_FILE = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printer output path
|
||||||
for (auto &path : options[launcher::Options::SDVXPrinterOutputPath].values_text()) {
|
for (auto &path : options[launcher::Options::SDVXPrinterOutputPath].values_text()) {
|
||||||
games::shared::PRINTER_PATH.push_back(path);
|
games::shared::PRINTER_PATH.push_back(path);
|
||||||
}
|
}
|
||||||
|
for (auto &path : options[launcher::Options::LovePlusPrinterOutputPath].values_text()) {
|
||||||
|
games::shared::PRINTER_PATH.push_back(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// printer file format
|
||||||
for (auto &path : options[launcher::Options::SDVXPrinterOutputFormat].values_text()) {
|
for (auto &path : options[launcher::Options::SDVXPrinterOutputFormat].values_text()) {
|
||||||
games::shared::PRINTER_FORMAT.push_back(path);
|
games::shared::PRINTER_FORMAT.push_back(path);
|
||||||
}
|
}
|
||||||
|
for (auto &path : options[launcher::Options::LovePlusPrinterOutputFormat].values_text()) {
|
||||||
|
games::shared::PRINTER_FORMAT.push_back(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// printer JPG quality
|
||||||
if (options[launcher::Options::SDVXPrinterJPGQuality].is_active()) {
|
if (options[launcher::Options::SDVXPrinterJPGQuality].is_active()) {
|
||||||
games::shared::PRINTER_JPG_QUALITY = options[launcher::Options::SDVXPrinterJPGQuality].value_uint32();
|
games::shared::PRINTER_JPG_QUALITY = options[launcher::Options::SDVXPrinterJPGQuality].value_uint32();
|
||||||
|
} else if (options[launcher::Options::LovePlusPrinterJPGQuality].is_active()) {
|
||||||
|
games::shared::PRINTER_JPG_QUALITY = options[launcher::Options::LovePlusPrinterJPGQuality].value_uint32();
|
||||||
}
|
}
|
||||||
if (options[launcher::Options::SDVXPrinterOutputClear].value_bool()) {
|
|
||||||
|
// printer output clear
|
||||||
|
if (options[launcher::Options::SDVXPrinterOutputClear].value_bool() ||
|
||||||
|
options[launcher::Options::LovePlusPrinterOutputClear].value_bool()) {
|
||||||
games::shared::PRINTER_CLEAR = true;
|
games::shared::PRINTER_CLEAR = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::HTTP11].is_active()) {
|
if (options[launcher::Options::HTTP11].is_active()) {
|
||||||
avs::ea3::HTTP11 = options[launcher::Options::HTTP11].value_uint32();
|
avs::ea3::HTTP11 = options[launcher::Options::HTTP11].value_uint32();
|
||||||
}
|
}
|
||||||
@@ -747,9 +774,11 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
SetDllDirectoryW(MODULE_PATH.c_str());
|
SetDllDirectoryW(MODULE_PATH.c_str());
|
||||||
}
|
}
|
||||||
if (options[launcher::Options::Player1Card].is_active()) {
|
if (options[launcher::Options::Player1Card].is_active()) {
|
||||||
|
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||||
CARD_OVERRIDES[0] = options[launcher::Options::Player1Card].value_text();
|
CARD_OVERRIDES[0] = options[launcher::Options::Player1Card].value_text();
|
||||||
}
|
}
|
||||||
if (options[launcher::Options::Player2Card].is_active()) {
|
if (options[launcher::Options::Player2Card].is_active()) {
|
||||||
|
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||||
CARD_OVERRIDES[1] = options[launcher::Options::Player2Card].value_text();
|
CARD_OVERRIDES[1] = options[launcher::Options::Player2Card].value_text();
|
||||||
}
|
}
|
||||||
if (options[launcher::Options::Player1PinMacro].is_active()) {
|
if (options[launcher::Options::Player1PinMacro].is_active()) {
|
||||||
@@ -812,6 +841,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::AdapterSubnet].is_active()) {
|
if (options[launcher::Options::AdapterSubnet].is_active()) {
|
||||||
NETWORK_SUBNET = options[launcher::Options::AdapterSubnet].value_text();
|
NETWORK_SUBNET = options[launcher::Options::AdapterSubnet].value_text();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::APITCPPort].is_active()) {
|
if (options[launcher::Options::APITCPPort].is_active()) {
|
||||||
api_enable = true;
|
api_enable = true;
|
||||||
api_port = options[launcher::Options::APITCPPort].value_uint32();
|
api_port = options[launcher::Options::APITCPPort].value_uint32();
|
||||||
@@ -834,6 +864,13 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::APIDebugMode].value_bool()) {
|
if (options[launcher::Options::APIDebugMode].value_bool()) {
|
||||||
api_debug = true;
|
api_debug = true;
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::APIScreenMirrorQuality].is_active()) {
|
||||||
|
api::modules::CAPTURE_QUALITY = options[launcher::Options::APIScreenMirrorQuality].value_uint32();
|
||||||
|
}
|
||||||
|
if (options[launcher::Options::APIScreenMirrorDivide].is_active()) {
|
||||||
|
api::modules::CAPTURE_DIVIDE = options[launcher::Options::APIScreenMirrorDivide].value_uint32();
|
||||||
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::DisableDebugHooks].value_bool()) {
|
if (options[launcher::Options::DisableDebugHooks].value_bool()) {
|
||||||
debughook::DEBUGHOOK_LOGGING = false;
|
debughook::DEBUGHOOK_LOGGING = false;
|
||||||
}
|
}
|
||||||
@@ -975,12 +1012,24 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool();
|
GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool();
|
||||||
GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool();
|
GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool();
|
||||||
|
|
||||||
// IIDX Windowed Subscreen
|
// IIDX/SDVX Windowed Subscreen
|
||||||
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) {
|
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) {
|
||||||
GRAPHICS_IIDX_WSUB_SIZE = options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].value_text();
|
GRAPHICS_WSUB_SIZE = options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].value_text();
|
||||||
|
} else if (options[launcher::Options::SDVXWindowedSubscreenSize].is_active()) {
|
||||||
|
GRAPHICS_WSUB_SIZE = options[launcher::Options::SDVXWindowedSubscreenSize].value_text();
|
||||||
}
|
}
|
||||||
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].is_active()) {
|
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].is_active()) {
|
||||||
GRAPHICS_IIDX_WSUB_POS = options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].value_text();
|
GRAPHICS_WSUB_POS = options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].value_text();
|
||||||
|
} else if (options[launcher::Options::SDVXWindowedSubscreenPosition].is_active()) {
|
||||||
|
GRAPHICS_WSUB_POS = options[launcher::Options::SDVXWindowedSubscreenPosition].value_text();
|
||||||
|
}
|
||||||
|
if (options[launcher::Options::IIDXWindowedSubscreenBorderless].value_bool() ||
|
||||||
|
options[launcher::Options::SDVXWindowedSubscreenBorderless].value_bool()) {
|
||||||
|
GRAPHICS_WSUB_BORDERLESS = true;
|
||||||
|
}
|
||||||
|
if (options[launcher::Options::IIDXWindowedSubscreenAlwaysOnTop].value_bool() ||
|
||||||
|
options[launcher::Options::SDVXWindowedSubscreenAlwaysOnTop].value_bool()) {
|
||||||
|
GRAPHICS_WSUB_ALWAYS_ON_TOP = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::spice2x_JubeatLegacyTouch].value_bool()) {
|
if (options[launcher::Options::spice2x_JubeatLegacyTouch].value_bool()) {
|
||||||
@@ -1055,6 +1104,17 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::spice2x_EnableSMXDedicab].value_bool()) {
|
if (options[launcher::Options::spice2x_EnableSMXDedicab].value_bool()) {
|
||||||
rawinput::ENABLE_SMX_DEDICAB = true;
|
rawinput::ENABLE_SMX_DEDICAB = true;
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::InputRequiresFocus].is_active()) {
|
||||||
|
const auto &text = options[launcher::Options::InputRequiresFocus].value_text();
|
||||||
|
if (text == "always") {
|
||||||
|
rawinput::NAIVE_REQUIRE_FOCUS = true;
|
||||||
|
rawinput::RAWINPUT_REQUIRE_FOCUS = true;
|
||||||
|
} else if (text == "never") {
|
||||||
|
rawinput::NAIVE_REQUIRE_FOCUS = false;
|
||||||
|
rawinput::RAWINPUT_REQUIRE_FOCUS = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::MidiAlgoVer].is_active()) {
|
if (options[launcher::Options::MidiAlgoVer].is_active()) {
|
||||||
if (options[launcher::Options::MidiAlgoVer].value_text() == "legacy") {
|
if (options[launcher::Options::MidiAlgoVer].value_text() == "legacy") {
|
||||||
midi_algo = rawinput::MidiNoteAlgorithm::LEGACY;
|
midi_algo = rawinput::MidiNoteAlgorithm::LEGACY;
|
||||||
@@ -1076,6 +1136,10 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
rawinput::MIDI_NOTE_SUSTAIN = options[launcher::Options::MidiNoteSustain].value_uint32();
|
rawinput::MIDI_NOTE_SUSTAIN = options[launcher::Options::MidiNoteSustain].value_uint32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options[launcher::Options::LovePlusCamEnable].value_bool()) {
|
||||||
|
games::loveplus::CAMERA_ENABLE = true;
|
||||||
|
}
|
||||||
|
|
||||||
// API debugging
|
// API debugging
|
||||||
if (api_debug && !cfg::CONFIGURATOR_STANDALONE) {
|
if (api_debug && !cfg::CONFIGURATOR_STANDALONE) {
|
||||||
API_CONTROLLER = std::make_unique<api::Controller>(api_port, api_pass, api_pretty);
|
API_CONTROLLER = std::make_unique<api::Controller>(api_port, api_pass, api_pretty);
|
||||||
@@ -1117,6 +1181,8 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
// log
|
// log
|
||||||
#ifdef SPICE64
|
#ifdef SPICE64
|
||||||
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
|
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
|
||||||
|
#elif SPICE32_LARGE_ADDRESS_AWARE
|
||||||
|
log_info("launcher", "SpiceTools Bootstrap (x32) (Large Address Aware) (spice2x)");
|
||||||
#else
|
#else
|
||||||
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)");
|
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)");
|
||||||
#endif
|
#endif
|
||||||
@@ -1160,6 +1226,64 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
log_info("launcher", "arguments:\n{}", arguments.str());
|
log_info("launcher", "arguments:\n{}", arguments.str());
|
||||||
|
|
||||||
|
// print out conflicts
|
||||||
|
size_t conflicts = 0;
|
||||||
|
for (const auto &option : options) {
|
||||||
|
if (option.conflicting && option.get_definition().type != OptionType::Bool) {
|
||||||
|
conflicts += 1;
|
||||||
|
if (launcher::USE_CMD_OVERRIDE) {
|
||||||
|
log_warning(
|
||||||
|
"launcher",
|
||||||
|
"multiple values for -{}, command line args take precedence: {}",
|
||||||
|
option.get_definition().name,
|
||||||
|
option.value);
|
||||||
|
} else {
|
||||||
|
log_warning(
|
||||||
|
"launcher",
|
||||||
|
"multiple values for -{}, spicecfg values take precedence: {}",
|
||||||
|
option.get_definition().name,
|
||||||
|
option.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (conflicts) {
|
||||||
|
if (launcher::USE_CMD_OVERRIDE) {
|
||||||
|
log_info(
|
||||||
|
"launcher",
|
||||||
|
"user specified -cmdoverride, therefore command line args took precedence over spicecfg");
|
||||||
|
} else {
|
||||||
|
log_warning(
|
||||||
|
"launcher",
|
||||||
|
"spicecfg values take precedence over command line args; to change this behavior, use -cmdoverride");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options[launcher::Options::FullscreenResolution].is_active()) {
|
||||||
|
std::pair<uint32_t, uint32_t> result;
|
||||||
|
if (parse_width_height(options[launcher::Options::FullscreenResolution].value_text(), result)) {
|
||||||
|
GRAPHICS_FS_CUSTOM_RESOLUTION = result;
|
||||||
|
} else {
|
||||||
|
log_warning("launcher", "failed to parse -forceres");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDVXFullscreenLandscape disabled due to it messing with in-game camera angle
|
||||||
|
// FullscreenOrientationFlip continues to live on, however.
|
||||||
|
if (options[launcher::Options::SDVXFullscreenLandscape].value_bool()) {
|
||||||
|
log_fatal("launcher", "-sdvxlandscape removed due to a camera bug in SDVX!");
|
||||||
|
}
|
||||||
|
// if (options[launcher::Options::SDVXFullscreenLandscape].value_bool() && !GRAPHICS_WINDOWED) {
|
||||||
|
// #if SPICE64
|
||||||
|
// GRAPHICS_FS_ORIENTATION_SWAP = true;
|
||||||
|
// #else
|
||||||
|
// log_warning("launcher", "-sdvxlandscape is not supported in 32-bit SDVX, ignoring...");
|
||||||
|
// #endif
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (options[launcher::Options::FullscreenOrientationFlip].value_bool() && !GRAPHICS_WINDOWED) {
|
||||||
|
GRAPHICS_FS_ORIENTATION_SWAP = true;
|
||||||
|
}
|
||||||
|
|
||||||
// deleted options
|
// deleted options
|
||||||
if (options[launcher::Options::OpenKFControl].value_bool()) {
|
if (options[launcher::Options::OpenKFControl].value_bool()) {
|
||||||
log_fatal("launcher", "KFControl has been removed from spice2x; please use an older version.");
|
log_fatal("launcher", "KFControl has been removed from spice2x; please use an older version.");
|
||||||
@@ -1275,11 +1399,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
avs::game::DLL_NAME = "system.dll";
|
avs::game::DLL_NAME = "system.dll";
|
||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_shogikai = true;
|
attach_shogikai = true;
|
||||||
|
show_cursor_if_no_touch = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1322,12 +1442,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// game crash fix
|
// game crash fix
|
||||||
easrv_maint = false;
|
easrv_maint = false;
|
||||||
|
show_cursor_if_no_touch = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1442,12 +1557,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
avs::game::DLL_NAME = "nostalgia.dll";
|
avs::game::DLL_NAME = "nostalgia.dll";
|
||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_nostalgia = true;
|
attach_nostalgia = true;
|
||||||
|
show_cursor_if_no_touch = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1553,12 +1663,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
avs::game::DLL_NAME = "arknck.dll";
|
avs::game::DLL_NAME = "arknck.dll";
|
||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_we = true;
|
attach_we = true;
|
||||||
|
show_cursor_if_no_touch = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1591,10 +1696,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
avs::game::DLL_NAME = "kamunity.dll";
|
avs::game::DLL_NAME = "kamunity.dll";
|
||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_ccj = true;
|
attach_ccj = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
show_cursor_if_no_touch = true;
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1603,10 +1705,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
avs::game::DLL_NAME = "kamunity.dll";
|
avs::game::DLL_NAME = "kamunity.dll";
|
||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_qks = true;
|
attach_qks = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
show_cursor_if_no_touch = true;
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1616,10 +1715,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_mfg = true;
|
attach_mfg = true;
|
||||||
launcher::signal::USE_VEH_WORKAROUND = true;
|
launcher::signal::USE_VEH_WORKAROUND = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
show_cursor_if_no_touch = true;
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1628,10 +1724,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
avs::game::DLL_NAME = "kamunity.dll";
|
avs::game::DLL_NAME = "kamunity.dll";
|
||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_bc = true;
|
attach_bc = true;
|
||||||
// automatically show cursor when no touchscreen is available
|
show_cursor_if_no_touch = true;
|
||||||
if (!is_touch_available()) {
|
|
||||||
GRAPHICS_SHOW_CURSOR = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1810,6 +1903,22 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
exit(spicecfg_run(sextet_devices));
|
exit(spicecfg_run(sextet_devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log some DLLs found in path (purely for troubleshooting purposes to detect
|
||||||
|
// dxvk, ForceD3D9On12, ifs_layeredfs, etc)
|
||||||
|
libutils::warn_if_dll_exists("d3d8.dll");
|
||||||
|
libutils::warn_if_dll_exists("d3d9.dll");
|
||||||
|
libutils::warn_if_dll_exists("d3d10core.dll");
|
||||||
|
libutils::warn_if_dll_exists("d3d11.dll");
|
||||||
|
libutils::warn_if_dll_exists("d3d12.dll");
|
||||||
|
libutils::warn_if_dll_exists("dxgi.dll");
|
||||||
|
libutils::warn_if_dll_exists("opengl32.dll");
|
||||||
|
libutils::warn_if_dll_exists("nvcuda.dll");
|
||||||
|
libutils::warn_if_dll_exists("nvcuvid.dll");
|
||||||
|
libutils::warn_if_dll_exists("nvEncodeAPI64.dll");
|
||||||
|
|
||||||
|
// complain loudly & early about dll load ordering issue
|
||||||
|
libutils::check_duplicate_dlls();
|
||||||
|
|
||||||
// print cpu features
|
// print cpu features
|
||||||
if (!cfg::CONFIGURATOR_STANDALONE && dump_sysinfo) {
|
if (!cfg::CONFIGURATOR_STANDALONE && dump_sysinfo) {
|
||||||
cpuutils::print_cpu_features();
|
cpuutils::print_cpu_features();
|
||||||
@@ -1827,6 +1936,11 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
// print devices
|
// print devices
|
||||||
RI_MGR->devices_print();
|
RI_MGR->devices_print();
|
||||||
|
|
||||||
|
// for certain games, show cursor if no touch is available (must be called after RI_MGR is available)
|
||||||
|
if (show_cursor_if_no_touch && !is_touch_available("launcher::main_implementation")) {
|
||||||
|
GRAPHICS_SHOW_CURSOR = true;
|
||||||
|
}
|
||||||
|
|
||||||
// cardio
|
// cardio
|
||||||
if (cardio_enabled) {
|
if (cardio_enabled) {
|
||||||
cardio_runner_start(true);
|
cardio_runner_start(true);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ static const std::vector<std::string> CATEGORY_ORDER_BASIC = {
|
|||||||
"Network",
|
"Network",
|
||||||
"Overlay",
|
"Overlay",
|
||||||
"Graphics (Common)",
|
"Graphics (Common)",
|
||||||
|
"Graphics (Full Screen)",
|
||||||
"Graphics (Windowed)",
|
"Graphics (Windowed)",
|
||||||
"Audio",
|
"Audio",
|
||||||
};
|
};
|
||||||
@@ -42,6 +43,8 @@ static const std::vector<std::string> CATEGORY_ORDER_NONE = {
|
|||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool launcher::USE_CMD_OVERRIDE = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Option Definitions
|
* Option Definitions
|
||||||
* Be aware that the order must be the same as in the enum launcher::Options!
|
* Be aware that the order must be the same as in the enum launcher::Options!
|
||||||
@@ -80,6 +83,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Network",
|
.category = "Network",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// ServiceURL
|
||||||
.title = "EA Service URL",
|
.title = "EA Service URL",
|
||||||
.name = "url",
|
.name = "url",
|
||||||
.desc = "Sets a custom service URL override",
|
.desc = "Sets a custom service URL override",
|
||||||
@@ -141,6 +145,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Graphics (Windowed)",
|
.category = "Graphics (Windowed)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// InjectHook
|
||||||
.title = "Inject DLL Hooks",
|
.title = "Inject DLL Hooks",
|
||||||
.name = "k",
|
.name = "k",
|
||||||
.desc = "Multiple files are allowed; use multiple -k flags, or in SpiceCfg, separate by "
|
.desc = "Multiple files are allowed; use multiple -k flags, or in SpiceCfg, separate by "
|
||||||
@@ -151,6 +156,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Common",
|
.category = "Common",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// EarlyInjectHook
|
||||||
.title = "Inject Early DLL Hooks",
|
.title = "Inject Early DLL Hooks",
|
||||||
.name = "z",
|
.name = "z",
|
||||||
.desc = "Equivalent to 'Inject DLL Hooks' option, but ensures hooks are injected before "
|
.desc = "Equivalent to 'Inject DLL Hooks' option, but ensures hooks are injected before "
|
||||||
@@ -185,9 +191,12 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
{
|
{
|
||||||
.title = "Monitor",
|
.title = "Monitor",
|
||||||
.name = "monitor",
|
.name = "monitor",
|
||||||
.desc = "Sets the display that the game will be opened in, for multiple monitors",
|
.desc = "Sets the display that the game will be opened in, for multiple monitors.\n\n"
|
||||||
|
"0 is the primary monitor, 1 is the second monitor, and so on.\n\n"
|
||||||
|
"Not all games will respect this. Does not work at all with multi-monitor games like TDJ/UFC. "
|
||||||
|
"Disable Full Screen Optimizations for best results",
|
||||||
.type = OptionType::Integer,
|
.type = OptionType::Integer,
|
||||||
.category = "Graphics (Common)",
|
.category = "Graphics (Full Screen)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Only Use One Monitor",
|
.title = "Only Use One Monitor",
|
||||||
@@ -195,7 +204,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.desc = "Force the graphics device to be opened utilizing only one adapter in multi-monitor systems.\n\n"
|
.desc = "Force the graphics device to be opened utilizing only one adapter in multi-monitor systems.\n\n"
|
||||||
"May cause unstable framerate and desyncs, especially if monitors have different refresh rates!",
|
"May cause unstable framerate and desyncs, especially if monitors have different refresh rates!",
|
||||||
.type = OptionType::Bool,
|
.type = OptionType::Bool,
|
||||||
.category = "Graphics (Common)",
|
.category = "Graphics (Full Screen)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Force Refresh Rate",
|
.title = "Force Refresh Rate",
|
||||||
@@ -211,10 +220,23 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.desc =
|
.desc =
|
||||||
"For full screen mode, forcibly set a custom resolution.\n\n"
|
"For full screen mode, forcibly set a custom resolution.\n\n"
|
||||||
"Works great for some games, but can COMPLETELY BREAK other games - YMMV!\n\n"
|
"Works great for some games, but can COMPLETELY BREAK other games - YMMV!\n\n"
|
||||||
|
"If you are using -forceresswap/-sdvxlandscape, put the TARGET monitor resolution in this field.\n\n"
|
||||||
"This should only be used as last resort if your GPU/monitor can't display the resolution required by the game",
|
"This should only be used as last resort if your GPU/monitor can't display the resolution required by the game",
|
||||||
.type = OptionType::Text,
|
.type = OptionType::Text,
|
||||||
.setting_name = "1280,720",
|
.setting_name = "1280,720",
|
||||||
.category = "Graphics (Common)"
|
.category = "Graphics (Full Screen)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// FullscreenOrientationFlip
|
||||||
|
.title = "Full Screen Orientation Swap",
|
||||||
|
.name = "forceresswap",
|
||||||
|
.desc =
|
||||||
|
"Allows you to play portrait games in in landscape (and vice versa) by transposing resolution and applying image scaling.\n\n"
|
||||||
|
"Works great for some games, but can COMPLETELY BREAK other games - YMMV!\n\n"
|
||||||
|
"Strongly consider combining this with -forceres option to render at monitor native resolution\n\n"
|
||||||
|
"WARNING: for SDVX, this messes with camera angle for note lanes, causing it to be zoomed out!",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.category = "Graphics (Full Screen)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Graphics9On12
|
// Graphics9On12
|
||||||
@@ -289,6 +311,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
"Force the use of an adapter with the specified network. Must also provide -subnet",
|
"Force the use of an adapter with the specified network. Must also provide -subnet",
|
||||||
.type = OptionType::Text,
|
.type = OptionType::Text,
|
||||||
.category = "Network Adapters",
|
.category = "Network Adapters",
|
||||||
|
.sensitive = true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Preferred NetAdapter Subnet",
|
.title = "Preferred NetAdapter Subnet",
|
||||||
@@ -650,6 +673,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Game Options (Advanced)",
|
.category = "Game Options (Advanced)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// SDVXPrinterOutputPath
|
||||||
.title = "SDVX Printer Output Path",
|
.title = "SDVX Printer Output Path",
|
||||||
.name = "printerpath",
|
.name = "printerpath",
|
||||||
.desc = "Path to folder where images will be stored",
|
.desc = "Path to folder where images will be stored",
|
||||||
@@ -674,9 +698,10 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Game Options (Advanced)",
|
.category = "Game Options (Advanced)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// SDVXPrinterOutputFormat
|
||||||
.title = "SDVX Printer Output Format",
|
.title = "SDVX Printer Output Format",
|
||||||
.name = "printerformat",
|
.name = "printerformat",
|
||||||
.desc = "Path to folder where images will be stored",
|
.desc = "File format for printer output",
|
||||||
.type = OptionType::Text,
|
.type = OptionType::Text,
|
||||||
.setting_name = "(png/bmp/tga/jpg)",
|
.setting_name = "(png/bmp/tga/jpg)",
|
||||||
.game_name = "Sound Voltex",
|
.game_name = "Sound Voltex",
|
||||||
@@ -745,7 +770,13 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.type = OptionType::Enum,
|
.type = OptionType::Enum,
|
||||||
.game_name = "Sound Voltex",
|
.game_name = "Sound Voltex",
|
||||||
.category = "Overlay",
|
.category = "Overlay",
|
||||||
.elements = {{"top", ""}, {"center", ""}, {"bottom", ""}},
|
.elements = {
|
||||||
|
{"top", ""},
|
||||||
|
{"center", ""},
|
||||||
|
{"bottom", ""},
|
||||||
|
{"bottomleft", "for landscape"},
|
||||||
|
{"bottomright", "for landscape"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// spice2x_SDVXSubRedraw
|
// spice2x_SDVXSubRedraw
|
||||||
@@ -1065,7 +1096,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.title = "Screen Resize Config Path",
|
.title = "Screen Resize Config Path",
|
||||||
.name = "resizecfgpath",
|
.name = "resizecfgpath",
|
||||||
.desc = "Sets a custom file path for screen resize config file. "
|
.desc = "Sets a custom file path for screen resize config file. "
|
||||||
"If left empty, %appdata%\\spicetools_screen_resize.json will be used",
|
"If left empty, %appdata%\\spice2x\\spicetools_screen_resize.json will be used",
|
||||||
.type = OptionType::Text,
|
.type = OptionType::Text,
|
||||||
.category = "Paths",
|
.category = "Paths",
|
||||||
},
|
},
|
||||||
@@ -1074,7 +1105,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.title = "Patch Manager Config Path",
|
.title = "Patch Manager Config Path",
|
||||||
.name = "patchcfgpath",
|
.name = "patchcfgpath",
|
||||||
.desc = "Sets a custom file path for patch manager config file. Can be used to manage 'profiles' for auto-patches. "
|
.desc = "Sets a custom file path for patch manager config file. Can be used to manage 'profiles' for auto-patches. "
|
||||||
"If left empty, %appdata%\\spicetools_patch_manager.json will be used",
|
"If left empty, %appdata%\\spice2x\\spicetools_patch_manager.json will be used",
|
||||||
.type = OptionType::Text,
|
.type = OptionType::Text,
|
||||||
.category = "Paths",
|
.category = "Paths",
|
||||||
},
|
},
|
||||||
@@ -1170,6 +1201,28 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.type = OptionType::Bool,
|
.type = OptionType::Bool,
|
||||||
.category = "API (Dev)",
|
.category = "API (Dev)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// APIScreenMirrorQuality
|
||||||
|
.title = "API Screen Mirror Quality Override",
|
||||||
|
.name = "apiscreenq",
|
||||||
|
.desc = "JPEG compression level of mirrored images, overriding any client request. "
|
||||||
|
"Value must be between 0 (poor quality) and 100 (best quality), inclusive. Default: 70",
|
||||||
|
.type = OptionType::Integer,
|
||||||
|
.setting_name = "(0-100)",
|
||||||
|
.category = "SpiceCompanion and API",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// APIScreenMirrorDivide
|
||||||
|
.title = "API Screen Mirror Divide Override",
|
||||||
|
.name = "apiscreendiv",
|
||||||
|
.desc = "Divide value of mirrored images, overriding any client request. "
|
||||||
|
"Divide of 1 means send every pixel, 2 means every other pixel, 3 means every third pixel, and so on; "
|
||||||
|
"increasing the value drastically reduces transfer size at the cost of image quality. "
|
||||||
|
"Value must be 1 or greater. Default: 1",
|
||||||
|
.type = OptionType::Integer,
|
||||||
|
.setting_name = "1",
|
||||||
|
.category = "SpiceCompanion and API",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.title = "Enable All IO Modules",
|
.title = "Enable All IO Modules",
|
||||||
.name = "io",
|
.name = "io",
|
||||||
@@ -1265,6 +1318,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Touch Parameters",
|
.category = "Touch Parameters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// ICCAReaderPort
|
||||||
.title = "ICCA Reader Port",
|
.title = "ICCA Reader Port",
|
||||||
.name = "reader",
|
.name = "reader",
|
||||||
.desc = "Connects to and uses a ICCA on a given COM port",
|
.desc = "Connects to and uses a ICCA on a given COM port",
|
||||||
@@ -1341,6 +1395,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// SextetStreamPort
|
||||||
.title = "SextetStream Port",
|
.title = "SextetStream Port",
|
||||||
.name = "sextet",
|
.name = "sextet",
|
||||||
.desc = "Use a SextetStream device on a given COM port",
|
.desc = "Use a SextetStream device on a given COM port",
|
||||||
@@ -1819,6 +1874,24 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.game_name = "Beatmania IIDX",
|
.game_name = "Beatmania IIDX",
|
||||||
.category = "Graphics (Windowed)",
|
.category = "Graphics (Windowed)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// IIDXWindowedSubscreenBorderless
|
||||||
|
.title = "IIDX Windowed Subscreen Borderless",
|
||||||
|
.name = "iidxwsubborderless",
|
||||||
|
.desc = "Remove window decoration from windowed subscreen",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "Beatmania IIDX",
|
||||||
|
.category = "Graphics (Windowed)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// IIDXWindowedSubscreenAlwaysOnTop
|
||||||
|
.title = "IIDX Windowed Subscreen Always On Top",
|
||||||
|
.name = "iidxwsubtop",
|
||||||
|
.desc = "Keep windowed subscreen on top",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "Beatmania IIDX",
|
||||||
|
.category = "Graphics (Windowed)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// spice2x_JubeatLegacyTouch
|
// spice2x_JubeatLegacyTouch
|
||||||
.title = "JB Legacy Touch Targets",
|
.title = "JB Legacy Touch Targets",
|
||||||
@@ -2025,6 +2098,20 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.game_name = "Sound Voltex",
|
.game_name = "Sound Voltex",
|
||||||
.category = "Game Options",
|
.category = "Game Options",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// SDVXFullscreenLandscape
|
||||||
|
.title = "(DISABLED) SDVX Landscape Mode (SDVX5+)",
|
||||||
|
.name = "sdvxlandscape",
|
||||||
|
.desc =
|
||||||
|
"Option HIDDEN and DISABLED due to it affecting in-game camera angle for displaying lanes.\n\n"
|
||||||
|
"Allows you to play in landscape by transposing resolution and applying image scaling.\n\n"
|
||||||
|
"Works only for SDVX5 and above! This is identical to -forceresswap.\n\n"
|
||||||
|
"Will launch at 1080p by default; strongly consider combining this with -forceres option to render at monitor native resolution",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.hidden = true,
|
||||||
|
.game_name = "Sound Voltex",
|
||||||
|
.category = "Game Options",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// spice2x_EnableSMXStage
|
// spice2x_EnableSMXStage
|
||||||
.title = "StepManiaX Stage Lighting Support",
|
.title = "StepManiaX Stage Lighting Support",
|
||||||
@@ -2092,6 +2179,23 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.setting_name = "20",
|
.setting_name = "20",
|
||||||
.category = "I/O Options",
|
.category = "I/O Options",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// InputRequiresFocus
|
||||||
|
.title = "Input Requires Focus",
|
||||||
|
.name = "inputfocus",
|
||||||
|
.desc =
|
||||||
|
"Determine input behavior when game window is not in focus.\n\n"
|
||||||
|
"never: allow input regardless of focus\n"
|
||||||
|
"naive (default): only naive bindings check for window focus, rawinput binds are always allowed\n"
|
||||||
|
"always: only process input when window is in focus",
|
||||||
|
.type = OptionType::Enum,
|
||||||
|
.category = "I/O Options",
|
||||||
|
.elements = {
|
||||||
|
{"never", ""},
|
||||||
|
{"naive", ""},
|
||||||
|
{"always", ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// NostalgiaPoke
|
// NostalgiaPoke
|
||||||
.title = "Nost Screen Poke",
|
.title = "Nost Screen Poke",
|
||||||
@@ -2116,7 +2220,108 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
{"2", "double buffer"},
|
{"2", "double buffer"},
|
||||||
{"3", "triple buffer"},
|
{"3", "triple buffer"},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
// SDVXWindowedSubscreenSize
|
||||||
|
.title = "SDVX Windowed Subscreen Size",
|
||||||
|
.name = "sdvxwsubsize",
|
||||||
|
.desc = "Size of the subscreen window. Defaults to (1920,1080)",
|
||||||
|
.type = OptionType::Text,
|
||||||
|
.setting_name = "1920,1080",
|
||||||
|
.game_name = "Sound Voltex",
|
||||||
|
.category = "Graphics (Windowed)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// SDVXWindowedSubscreenPosition
|
||||||
|
.title = "SDVX Windowed Subscreen Position",
|
||||||
|
.name = "sdvxwsubpos",
|
||||||
|
.desc = "Initial position of the subscreen window. Defaults to (0,0)",
|
||||||
|
.type = OptionType::Text,
|
||||||
|
.setting_name = "0,0",
|
||||||
|
.game_name = "Sound Voltex",
|
||||||
|
.category = "Graphics (Windowed)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// SDVXWindowedSubscreenBorderless
|
||||||
|
.title = "SDVX Windowed Subscreen Borderless",
|
||||||
|
.name = "sdvxwsubborderless",
|
||||||
|
.desc = "Remove window decoration from windowed subscreen",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "Sound Voltex",
|
||||||
|
.category = "Graphics (Windowed)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// SDVXWindowedSubscreenAlwaysOnTop
|
||||||
|
.title = "SDVX Windowed Subscreen Always On Top",
|
||||||
|
.name = "sdvxwsubtop",
|
||||||
|
.desc = "Keep windowed subscreen on top",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "Sound Voltex",
|
||||||
|
.category = "Graphics (Windowed)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// LovePlusCamEnable
|
||||||
|
.title = "LovePlus Camera Enable",
|
||||||
|
.name = "lovepluscam",
|
||||||
|
.desc = "Allow game to access camera; camera must be compatible with game",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "LovePlus",
|
||||||
|
.category = "Game Options",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// LovePlusPrinterOutputPath
|
||||||
|
.title = "LovePlus Printer Output Path",
|
||||||
|
.name = "lpprinterpath",
|
||||||
|
.desc = "Path to folder where images will be stored",
|
||||||
|
.type = OptionType::Text,
|
||||||
|
.game_name = "LovePlus",
|
||||||
|
.category = "Game Options (Advanced)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.title = "LovePlus Printer Output Clear",
|
||||||
|
.name = "lpprinterclear",
|
||||||
|
.desc = "Clean up saved images in the output directory on startup",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "LovePlus",
|
||||||
|
.category = "Game Options (Advanced)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.title = "LovePlus Printer Output Overwrite",
|
||||||
|
.name = "lpprinteroverwrite",
|
||||||
|
.desc = "Always overwrite the same file in output directory",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "LovePlus",
|
||||||
|
.category = "Game Options (Advanced)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// LovePlusPrinterOutputFormat
|
||||||
|
.title = "LovePlus Printer Output Format",
|
||||||
|
.name = "lpprinterformat",
|
||||||
|
.desc = "File format for printer output",
|
||||||
|
.type = OptionType::Text,
|
||||||
|
.setting_name = "(png/bmp/tga/jpg)",
|
||||||
|
.game_name = "LovePlus",
|
||||||
|
.category = "Game Options (Advanced)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.title = "LovePlus Printer JPG Quality",
|
||||||
|
.name = "lpprinterjpgquality",
|
||||||
|
.desc = "Quality setting in percent if JPG format is used",
|
||||||
|
.type = OptionType::Integer,
|
||||||
|
.setting_name = "(0-100)",
|
||||||
|
.game_name = "LovePlus",
|
||||||
|
.category = "Game Options (Advanced)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// OptionConflictResolution
|
||||||
|
.title = "Command Line Args Override",
|
||||||
|
.name = "cmdoverride",
|
||||||
|
.desc = "By default, option values in spicecfg take precedence over command-line args, for legacy compat.\n"
|
||||||
|
"When this is specified in command line, command-line args take precedence instead",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.category = "Development",
|
||||||
|
.disabled = true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<std::string> &launcher::get_categories(Options::OptionsCategory category) {
|
const std::vector<std::string> &launcher::get_categories(Options::OptionsCategory category) {
|
||||||
@@ -2298,12 +2503,25 @@ std::vector<Option> launcher::merge_options(
|
|||||||
auto &new_option = merged.emplace_back(option.get_definition(), "");
|
auto &new_option = merged.emplace_back(option.get_definition(), "");
|
||||||
new_option.disabled = true;
|
new_option.disabled = true;
|
||||||
|
|
||||||
for (auto &value : option.values()) {
|
if (USE_CMD_OVERRIDE) {
|
||||||
new_option.value_add(value);
|
// command-line arguments take precedence (opt-in)
|
||||||
}
|
for (auto &value : override.values()) {
|
||||||
for (auto &value : override.values()) {
|
new_option.value_add(value);
|
||||||
new_option.value_add(value);
|
}
|
||||||
|
for (auto &value : option.values()) {
|
||||||
|
new_option.value_add(value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// spicecfg options take precedence (default)
|
||||||
|
// this sucks, but it's the default for legacy spicetools compat
|
||||||
|
for (auto &value : option.values()) {
|
||||||
|
new_option.value_add(value);
|
||||||
|
}
|
||||||
|
for (auto &value : override.values()) {
|
||||||
|
new_option.value_add(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
new_option.conflicting = true;
|
||||||
} else {
|
} else {
|
||||||
auto &new_option = merged.emplace_back(override.get_definition(), "");
|
auto &new_option = merged.emplace_back(override.get_definition(), "");
|
||||||
new_option.disabled = true;
|
new_option.disabled = true;
|
||||||
@@ -2319,7 +2537,6 @@ std::vector<Option> launcher::merge_options(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return merged;
|
return merged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace launcher {
|
|||||||
GraphicsForceSingleAdapter,
|
GraphicsForceSingleAdapter,
|
||||||
GraphicsForceRefresh,
|
GraphicsForceRefresh,
|
||||||
FullscreenResolution,
|
FullscreenResolution,
|
||||||
|
FullscreenOrientationFlip,
|
||||||
Graphics9On12,
|
Graphics9On12,
|
||||||
spice2x_Dx9On12,
|
spice2x_Dx9On12,
|
||||||
NoLegacy,
|
NoLegacy,
|
||||||
@@ -135,6 +136,8 @@ namespace launcher {
|
|||||||
APISerialBaud,
|
APISerialBaud,
|
||||||
APIPretty,
|
APIPretty,
|
||||||
APIDebugMode,
|
APIDebugMode,
|
||||||
|
APIScreenMirrorQuality,
|
||||||
|
APIScreenMirrorDivide,
|
||||||
EnableAllIOModules,
|
EnableAllIOModules,
|
||||||
EnableACIOModule,
|
EnableACIOModule,
|
||||||
EnableICCAModule,
|
EnableICCAModule,
|
||||||
@@ -206,6 +209,8 @@ namespace launcher {
|
|||||||
WindowForceScaling,
|
WindowForceScaling,
|
||||||
spice2x_IIDXWindowedSubscreenSize,
|
spice2x_IIDXWindowedSubscreenSize,
|
||||||
spice2x_IIDXWindowedSubscreenPosition,
|
spice2x_IIDXWindowedSubscreenPosition,
|
||||||
|
IIDXWindowedSubscreenBorderless,
|
||||||
|
IIDXWindowedSubscreenAlwaysOnTop,
|
||||||
spice2x_JubeatLegacyTouch,
|
spice2x_JubeatLegacyTouch,
|
||||||
spice2x_RBTouchScale,
|
spice2x_RBTouchScale,
|
||||||
spice2x_AsioForceUnload,
|
spice2x_AsioForceUnload,
|
||||||
@@ -222,13 +227,26 @@ namespace launcher {
|
|||||||
spice2x_NoNVAPI,
|
spice2x_NoNVAPI,
|
||||||
spice2x_NoD3D9DeviceHook,
|
spice2x_NoD3D9DeviceHook,
|
||||||
spice2x_SDVXNoSub,
|
spice2x_SDVXNoSub,
|
||||||
|
SDVXFullscreenLandscape,
|
||||||
spice2x_EnableSMXStage,
|
spice2x_EnableSMXStage,
|
||||||
spice2x_EnableSMXDedicab,
|
spice2x_EnableSMXDedicab,
|
||||||
IIDXRecQuality,
|
IIDXRecQuality,
|
||||||
MidiAlgoVer,
|
MidiAlgoVer,
|
||||||
MidiNoteSustain,
|
MidiNoteSustain,
|
||||||
|
InputRequiresFocus,
|
||||||
NostalgiaPoke,
|
NostalgiaPoke,
|
||||||
ForceBackBufferCount,
|
ForceBackBufferCount,
|
||||||
|
SDVXWindowedSubscreenSize,
|
||||||
|
SDVXWindowedSubscreenPosition,
|
||||||
|
SDVXWindowedSubscreenBorderless,
|
||||||
|
SDVXWindowedSubscreenAlwaysOnTop,
|
||||||
|
LovePlusCamEnable,
|
||||||
|
LovePlusPrinterOutputPath,
|
||||||
|
LovePlusPrinterOutputClear,
|
||||||
|
LovePlusPrinterOutputOverwrite,
|
||||||
|
LovePlusPrinterOutputFormat,
|
||||||
|
LovePlusPrinterJPGQuality,
|
||||||
|
OptionConflictResolution,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class OptionsCategory {
|
enum class OptionsCategory {
|
||||||
@@ -240,6 +258,8 @@ namespace launcher {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern bool USE_CMD_OVERRIDE;
|
||||||
|
|
||||||
const std::vector<std::string> &get_categories(Options::OptionsCategory category);
|
const std::vector<std::string> &get_categories(Options::OptionsCategory category);
|
||||||
const std::vector<OptionDefinition> &get_option_definitions();
|
const std::vector<OptionDefinition> &get_option_definitions();
|
||||||
std::unique_ptr<std::vector<Option>> parse_options(int argc, char *argv[]);
|
std::unique_ptr<std::vector<Option>> parse_options(int argc, char *argv[]);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <dbghelp.h>
|
#include <dbghelp.h>
|
||||||
|
|
||||||
|
#include "acio/acio.h"
|
||||||
#include "external/stackwalker/stackwalker.h"
|
#include "external/stackwalker/stackwalker.h"
|
||||||
#include "hooks/libraryhook.h"
|
#include "hooks/libraryhook.h"
|
||||||
#include "launcher/shutdown.h"
|
#include "launcher/shutdown.h"
|
||||||
@@ -97,6 +98,19 @@ static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *Exception
|
|||||||
// print signal
|
// print signal
|
||||||
log_warning("signal", "exception raised: {}", exception_code(ExceptionRecord));
|
log_warning("signal", "exception raised: {}", exception_code(ExceptionRecord));
|
||||||
|
|
||||||
|
// check ACIO init failures
|
||||||
|
if (acio::IO_INIT_IN_PROGRESS) {
|
||||||
|
log_warning(
|
||||||
|
"signal",
|
||||||
|
"exception raised during ACIO init, this usually happens when a third party application interferes with hooks");
|
||||||
|
log_warning(
|
||||||
|
"signal",
|
||||||
|
" please check for the following, disable them, and try launching the game again:");
|
||||||
|
log_warning(
|
||||||
|
"signal",
|
||||||
|
" RivaTuner Statistics Server (RTSS), MSI Afterburner, kernel mode anti-cheat");
|
||||||
|
}
|
||||||
|
|
||||||
// walk the exception chain
|
// walk the exception chain
|
||||||
struct _EXCEPTION_RECORD *record_cause = ExceptionRecord->ExceptionRecord;
|
struct _EXCEPTION_RECORD *record_cause = ExceptionRecord->ExceptionRecord;
|
||||||
while (record_cause != nullptr) {
|
while (record_cause != nullptr) {
|
||||||
|
|||||||
+17
-13
@@ -66,7 +66,7 @@ bool eamuse_get_card(int active_count, int unit_id, uint8_t *card) {
|
|||||||
if (CARD_INSERT_UID_ENABLE[index]) {
|
if (CARD_INSERT_UID_ENABLE[index]) {
|
||||||
CARD_INSERT_UID_ENABLE[index] = false;
|
CARD_INSERT_UID_ENABLE[index] = false;
|
||||||
memcpy(card, CARD_INSERT_UID[index], 8);
|
memcpy(card, CARD_INSERT_UID[index], 8);
|
||||||
log_info("eamuse", "Inserted card from reader {}: {}", index, bin2hex(card, 8));
|
log_info("eamuse", "[P{}] Inserted card from reader: {}", index+1, bin2hex(card, 8));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,35 +83,40 @@ bool eamuse_get_card(int active_count, int unit_id, uint8_t *card) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card, int index) {
|
bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card, int index) {
|
||||||
|
// do a quick copy under lock
|
||||||
|
std::unique_lock<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||||
|
const auto card_override = CARD_OVERRIDES[index];
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
// Check if card overrides are present
|
// Check if card overrides are present
|
||||||
if (!CARD_OVERRIDES[index].empty()) {
|
if (!card_override.empty()) {
|
||||||
|
|
||||||
// Override is present
|
// Override is present
|
||||||
for (int n = 0; n < 16; n++) {
|
for (int n = 0; n < 16; n++) {
|
||||||
char c = CARD_OVERRIDES[index].c_str()[n];
|
char c = card_override.c_str()[n];
|
||||||
bool digit = c >= '0' && c <= '9';
|
bool digit = c >= '0' && c <= '9';
|
||||||
bool character_big = c >= 'A' && c <= 'F';
|
bool character_big = c >= 'A' && c <= 'F';
|
||||||
bool character_small = c >= 'a' && c <= 'f';
|
bool character_small = c >= 'a' && c <= 'f';
|
||||||
if (!digit && !character_big && !character_small) {
|
if (!digit && !character_big && !character_small) {
|
||||||
log_warning("eamuse",
|
log_warning("eamuse",
|
||||||
"{} card override contains an invalid character sequence at byte {} (16 characters, 0-9/A-F only)",
|
"{} card override contains an invalid character sequence at byte {} (16 characters, 0-9/A-F only)",
|
||||||
CARD_OVERRIDES[index], n);
|
card_override, n);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Log info
|
// Log info
|
||||||
log_info("eamuse", "Inserted card override: {}", CARD_OVERRIDES[index]);
|
log_info("eamuse", "[P{}] Inserted card override: {}", index+1, card_override);
|
||||||
|
|
||||||
// Card is valid, convert and set it.
|
// Card is valid, convert and set it.
|
||||||
hex2bin(CARD_OVERRIDES[index].c_str(), card);
|
hex2bin(card_override.c_str(), card);
|
||||||
|
|
||||||
// cache it for auto-insert
|
// cache it for auto-insert
|
||||||
if (AUTO_INSERT_CARD[index] && !AUTO_INSERT_CARD_CACHED[index]) {
|
// always overwrite from overrides since override may have changed by user in card manager
|
||||||
|
if (AUTO_INSERT_CARD[index]) {
|
||||||
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
|
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
|
||||||
AUTO_INSERT_CARD_CACHED[index] = true;
|
AUTO_INSERT_CARD_CACHED[index] = true;
|
||||||
log_info("eamuse", "Auto card insert - caching this card in memory: {}", CARD_OVERRIDES[index]);
|
log_info("eamuse", "[P{}] Auto card insert - caching this card override in memory: {}", index+1, card_override);
|
||||||
}
|
}
|
||||||
|
|
||||||
// success
|
// success
|
||||||
@@ -162,7 +167,7 @@ bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// info
|
// info
|
||||||
log_info("eamuse", "Inserted {}: {}", path.string(), buffer);
|
log_info("eamuse", "[P{}] Inserted {}: {}", index+1, path.string(), buffer);
|
||||||
|
|
||||||
// convert hex to bytes
|
// convert hex to bytes
|
||||||
hex2bin(buffer, card);
|
hex2bin(buffer, card);
|
||||||
@@ -171,7 +176,7 @@ bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card,
|
|||||||
if (AUTO_INSERT_CARD[index] && !AUTO_INSERT_CARD_CACHED[index]) {
|
if (AUTO_INSERT_CARD[index] && !AUTO_INSERT_CARD_CACHED[index]) {
|
||||||
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
|
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
|
||||||
AUTO_INSERT_CARD_CACHED[index] = true;
|
AUTO_INSERT_CARD_CACHED[index] = true;
|
||||||
log_info("eamuse", "Auto card insert - caching this card in memory: {}", buffer);
|
log_info("eamuse", "[P{}] Auto card insert - caching this card from file in memory: {}", index+1, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// success
|
// success
|
||||||
@@ -211,7 +216,6 @@ bool eamuse_card_insert_consume(int active_count, int unit_id) {
|
|||||||
if (!CARD_INSERT[index]) {
|
if (!CARD_INSERT[index]) {
|
||||||
eamuse_card_insert(index);
|
eamuse_card_insert(index);
|
||||||
// not logging anything here to prevent spam
|
// not logging anything here to prevent spam
|
||||||
// log_info("eamuse", "Automatic card insert on {}/{} (-autocard)", unit_id + 1, active_count);
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -223,7 +227,7 @@ bool eamuse_card_insert_consume(int active_count, int unit_id) {
|
|||||||
auto offset = unit_id * games::KeypadButtons::Size;
|
auto offset = unit_id * games::KeypadButtons::Size;
|
||||||
if ((CARD_INSERT[index] && fabs(get_performance_seconds() - CARD_INSERT_TIME[index]) < CARD_INSERT_TIMEOUT)
|
if ((CARD_INSERT[index] && fabs(get_performance_seconds() - CARD_INSERT_TIME[index]) < CARD_INSERT_TIMEOUT)
|
||||||
|| GameAPI::Buttons::getState(RI_MGR, keypad_buttons->at(games::KeypadButtons::InsertCard + offset))) {
|
|| GameAPI::Buttons::getState(RI_MGR, keypad_buttons->at(games::KeypadButtons::InsertCard + offset))) {
|
||||||
log_info("eamuse", "Card insert on {}/{}", unit_id + 1, active_count);
|
log_info("eamuse", "[P{}] Card insert on reader (total active count: {})", unit_id+1, active_count);
|
||||||
CARD_INSERT[index] = false;
|
CARD_INSERT[index] = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "external/scard/scard.h"
|
#include "external/scard/scard.h"
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ enum eam_io_keypad_scan_code {
|
|||||||
EAM_IO_INSERT = 13, /* SpiceTools Extension */
|
EAM_IO_INSERT = 13, /* SpiceTools Extension */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern std::mutex CARD_OVERRIDES_LOCK;
|
||||||
extern std::string CARD_OVERRIDES[2];
|
extern std::string CARD_OVERRIDES[2];
|
||||||
extern bool AUTO_INSERT_CARD[2];
|
extern bool AUTO_INSERT_CARD[2];
|
||||||
extern float AUTO_INSERT_CARD_COOLDOWN;
|
extern float AUTO_INSERT_CARD_COOLDOWN;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace wintouchemu {
|
|||||||
bool LOG_FPS = false;
|
bool LOG_FPS = false;
|
||||||
|
|
||||||
static inline bool is_emu_enabled() {
|
static inline bool is_emu_enabled() {
|
||||||
return FORCE || !is_touch_available() || GRAPHICS_SHOW_CURSOR;
|
return FORCE || !is_touch_available("wintouchemu::is_emu_enabled") || GRAPHICS_SHOW_CURSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static decltype(GetSystemMetrics) *GetSystemMetrics_orig = nullptr;
|
static decltype(GetSystemMetrics) *GetSystemMetrics_orig = nullptr;
|
||||||
|
|||||||
@@ -6,36 +6,61 @@
|
|||||||
|
|
||||||
namespace ImGui {
|
namespace ImGui {
|
||||||
|
|
||||||
|
const auto fg = ImVec4(0.910f, 0.914f, 0.922f, 1.0f);
|
||||||
|
const auto bg = ImVec4(0.192f, 0.212f, 0.220f, 1.0f);
|
||||||
|
|
||||||
|
void HelpTooltip(const char* desc) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Border, bg);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_BorderShadow, bg);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, bg);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, fg);
|
||||||
|
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||||
|
ImGui::TextUnformatted(desc);
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
|
||||||
|
ImGui::PopStyleColor(4);
|
||||||
|
}
|
||||||
|
|
||||||
void HelpMarker(const char* desc) {
|
void HelpMarker(const char* desc) {
|
||||||
ImGui::TextDisabled("(?)");
|
ImGui::TextDisabled("(?)");
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
HelpTooltip(desc);
|
||||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
|
||||||
ImGui::TextUnformatted(desc);
|
|
||||||
ImGui::PopTextWrapPos();
|
|
||||||
ImGui::EndTooltip();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WarnTooltip(const char* desc, const char* warn) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Border, bg);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_BorderShadow, bg);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, bg);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, fg);
|
||||||
|
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||||
|
if (desc && desc[0]) {
|
||||||
|
ImGui::TextUnformatted(desc);
|
||||||
|
ImGui::TextUnformatted("");
|
||||||
|
}
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 0.f, 1.f));
|
||||||
|
if (warn && warn[0]) {
|
||||||
|
ImGui::TextUnformatted("WARNING:");
|
||||||
|
ImGui::TextUnformatted(warn);
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
|
||||||
|
ImGui::PopStyleColor(4);
|
||||||
|
}
|
||||||
|
|
||||||
void WarnMarker(const char* desc, const char* warn) {
|
void WarnMarker(const char* desc, const char* warn) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImVec4(1.f, 1.f, 0.f, 1.f));
|
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImVec4(1.f, 1.f, 0.f, 1.f));
|
||||||
ImGui::TextDisabled("(!)");
|
ImGui::TextDisabled("(!)");
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
WarnTooltip(desc, warn);
|
||||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
|
||||||
if (desc) {
|
|
||||||
ImGui::TextUnformatted(desc);
|
|
||||||
ImGui::TextUnformatted("");
|
|
||||||
}
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 0.f, 1.f));
|
|
||||||
if (warn) {
|
|
||||||
ImGui::TextUnformatted("WARNING:");
|
|
||||||
ImGui::TextUnformatted(warn);
|
|
||||||
}
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
ImGui::PopTextWrapPos();
|
|
||||||
ImGui::EndTooltip();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
namespace ImGui {
|
namespace ImGui {
|
||||||
|
|
||||||
|
void HelpTooltip(const char* desc);
|
||||||
void HelpMarker(const char* desc);
|
void HelpMarker(const char* desc);
|
||||||
|
void WarnTooltip(const char* desc, const char* warn);
|
||||||
void WarnMarker(const char* desc, const char* warn);
|
void WarnMarker(const char* desc, const char* warn);
|
||||||
void DummyMarker();
|
void DummyMarker();
|
||||||
void Knob(float fraction, float size, float thickness = 2.f,
|
void Knob(float fraction, float size, float thickness = 2.f,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "cfg/configurator.h"
|
||||||
#include "games/io.h"
|
#include "games/io.h"
|
||||||
#include "launcher/launcher.h"
|
#include "launcher/launcher.h"
|
||||||
#include "launcher/superexit.h"
|
#include "launcher/superexit.h"
|
||||||
@@ -11,6 +12,17 @@
|
|||||||
#include "touch/touch.h"
|
#include "touch/touch.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
|
#include "hooks/graphics/graphics.h"
|
||||||
|
|
||||||
|
#if !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) || \
|
||||||
|
!defined(IMGUI_DISABLE_DEFAULT_ALLOCATORS) || \
|
||||||
|
!defined(IMGUI_USE_BGRA_PACKED_COLOR) || \
|
||||||
|
!defined(IMGUI_HAS_VIEWPORT) || \
|
||||||
|
!defined(IMGUI_HAS_DOCK) || \
|
||||||
|
!defined(IMGUI_DISABLE_DEMO_WINDOWS) || \
|
||||||
|
defined(IMGUI_DISABLE_DEBUG_TOOLS)
|
||||||
|
#error "fix imconfig.h after updating imgui version"
|
||||||
|
#endif
|
||||||
|
|
||||||
// state
|
// state
|
||||||
static HWND g_hWnd = nullptr;
|
static HWND g_hWnd = nullptr;
|
||||||
@@ -42,6 +54,7 @@ bool ImGui_ImplSpice_Init(HWND hWnd) {
|
|||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
|
||||||
io.BackendPlatformName = "imgui_impl_spice";
|
io.BackendPlatformName = "imgui_impl_spice";
|
||||||
|
io.ConfigErrorRecoveryEnableTooltip = true;
|
||||||
|
|
||||||
// keyboard mapping
|
// keyboard mapping
|
||||||
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
|
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
|
||||||
@@ -59,7 +72,7 @@ bool ImGui_ImplSpice_Init(HWND hWnd) {
|
|||||||
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
|
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
|
||||||
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
|
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
|
||||||
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
|
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
|
||||||
io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN;
|
io.KeyMap[ImGuiKey_KeypadEnter] = VK_RETURN;
|
||||||
io.KeyMap[ImGuiKey_A] = 'A';
|
io.KeyMap[ImGuiKey_A] = 'A';
|
||||||
io.KeyMap[ImGuiKey_C] = 'C';
|
io.KeyMap[ImGuiKey_C] = 'C';
|
||||||
io.KeyMap[ImGuiKey_V] = 'V';
|
io.KeyMap[ImGuiKey_V] = 'V';
|
||||||
@@ -163,10 +176,22 @@ static void ImGui_ImplSpice_UpdateMousePos() {
|
|||||||
static_cast<int>(pos.y / io.DisplaySize.y * window_size.y));
|
static_cast<int>(pos.y / io.DisplaySize.y * window_size.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto active_window = ::GetForegroundWindow();
|
||||||
|
|
||||||
|
// if the main focus is a windowed subscreen, put the imgui cursor in a place that won't
|
||||||
|
// trigger any overlay, don't process anything else
|
||||||
|
const auto is_windowed_subscreen =
|
||||||
|
(GRAPHICS_IIDX_WSUB && active_window == TDJ_SUBSCREEN_WINDOW) ||
|
||||||
|
(active_window == SDVX_SUBSCREEN_WINDOW);
|
||||||
|
if (is_windowed_subscreen) {
|
||||||
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// set mouse position
|
// set mouse position
|
||||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
POINT pos;
|
POINT pos;
|
||||||
if (HWND active_window = ::GetForegroundWindow()) {
|
if (active_window) {
|
||||||
if (active_window == g_hWnd
|
if (active_window == g_hWnd
|
||||||
|| ::IsChild(active_window, g_hWnd)
|
|| ::IsChild(active_window, g_hWnd)
|
||||||
|| ::IsChild(g_hWnd, active_window)
|
|| ::IsChild(g_hWnd, active_window)
|
||||||
@@ -196,7 +221,7 @@ static void ImGui_ImplSpice_UpdateMousePos() {
|
|||||||
static size_t delay_touch = 0;
|
static size_t delay_touch = 0;
|
||||||
static size_t delay_touch_target = 2;
|
static size_t delay_touch_target = 2;
|
||||||
static DWORD last_touch_id = ~0u;
|
static DWORD last_touch_id = ~0u;
|
||||||
if (!touch_points.empty()) {
|
if (!touch_points.empty() && !is_windowed_subscreen) {
|
||||||
|
|
||||||
// use the first touch point
|
// use the first touch point
|
||||||
auto &tp = touch_points[0];
|
auto &tp = touch_points[0];
|
||||||
@@ -349,27 +374,6 @@ void ImGui_ImplSpice_NewFrame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// navigator input
|
|
||||||
auto buttons = games::get_buttons_overlay(eamuse_get_game());
|
|
||||||
if (buttons && (!overlay::OVERLAY || overlay::OVERLAY->hotkeys_triggered())) {
|
|
||||||
struct {
|
|
||||||
size_t index;
|
|
||||||
Button &btn;
|
|
||||||
} NAV_MAPPING[] = {
|
|
||||||
{ ImGuiNavInput_Activate, buttons->at(games::OverlayButtons::NavigatorActivate )},
|
|
||||||
{ ImGuiNavInput_Cancel, buttons->at(games::OverlayButtons::NavigatorCancel) },
|
|
||||||
{ ImGuiNavInput_DpadUp, buttons->at(games::OverlayButtons::NavigatorUp) },
|
|
||||||
{ ImGuiNavInput_DpadDown, buttons->at(games::OverlayButtons::NavigatorDown) },
|
|
||||||
{ ImGuiNavInput_DpadLeft, buttons->at(games::OverlayButtons::NavigatorLeft) },
|
|
||||||
{ ImGuiNavInput_DpadRight, buttons->at(games::OverlayButtons::NavigatorRight) },
|
|
||||||
};
|
|
||||||
for (auto mapping : NAV_MAPPING) {
|
|
||||||
if (GameAPI::Buttons::getState(RI_MGR, mapping.btn)) {
|
|
||||||
io.NavInputs[mapping.index] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set mouse wheel
|
// set mouse wheel
|
||||||
auto mouse_diff = mouse_wheel - mouse_wheel_last;
|
auto mouse_diff = mouse_wheel - mouse_wheel_last;
|
||||||
mouse_wheel_last = mouse_wheel;
|
mouse_wheel_last = mouse_wheel;
|
||||||
@@ -378,10 +382,27 @@ void ImGui_ImplSpice_NewFrame() {
|
|||||||
// update OS mouse position
|
// update OS mouse position
|
||||||
ImGui_ImplSpice_UpdateMousePos();
|
ImGui_ImplSpice_UpdateMousePos();
|
||||||
|
|
||||||
// update OS mouse cursor with the cursor requested by imgui
|
if (cfg::CONFIGURATOR_STANDALONE) {
|
||||||
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
// if cursor is inside the client area, always set the OS cursor to what ImGui wants
|
||||||
if (g_LastMouseCursor != mouse_cursor) {
|
// this is to deal with cases where mouse cursor changes outside the client rect and comes
|
||||||
g_LastMouseCursor = mouse_cursor;
|
// back into the window
|
||||||
ImGui_ImplSpice_UpdateMouseCursor();
|
// i'm sure there might be better ways to deal with this but this works so whatever, right?
|
||||||
|
RECT client_rect;
|
||||||
|
if (GetClientRect(g_hWnd, &client_rect)) {
|
||||||
|
POINT cursor;
|
||||||
|
if (GetCursorPos(&cursor) && ScreenToClient(g_hWnd, &cursor)) {
|
||||||
|
if (client_rect.left < cursor.x && cursor.x < client_rect.right &&
|
||||||
|
client_rect.top < cursor.y && cursor.y < client_rect.bottom) {
|
||||||
|
ImGui_ImplSpice_UpdateMouseCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// update OS mouse cursor with the cursor requested by imgui
|
||||||
|
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||||
|
if (g_LastMouseCursor != mouse_cursor) {
|
||||||
|
g_LastMouseCursor = mouse_cursor;
|
||||||
|
ImGui_ImplSpice_UpdateMouseCursor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -678,7 +678,7 @@ void bind_imgui_painting()
|
|||||||
int font_width, font_height;
|
int font_width, font_height;
|
||||||
io.Fonts->GetTexDataAsAlpha8(&tex_data, &font_width, &font_height);
|
io.Fonts->GetTexDataAsAlpha8(&tex_data, &font_width, &font_height);
|
||||||
const auto texture = new Texture{tex_data, font_width, font_height};
|
const auto texture = new Texture{tex_data, font_width, font_height};
|
||||||
io.Fonts->TexID = texture;
|
io.Fonts->TexID = reinterpret_cast<ImTextureID>(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Stats s_stats; // TODO: pass as an argument?
|
static Stats s_stats; // TODO: pass as an argument?
|
||||||
|
|||||||
@@ -7,14 +7,12 @@
|
|||||||
#include "hooks/graphics/graphics.h"
|
#include "hooks/graphics/graphics.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "touch/touch.h"
|
#include "touch/touch.h"
|
||||||
|
#include "util/fileutils.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/resutils.h"
|
#include "util/resutils.h"
|
||||||
#include "build/resource.h"
|
#include "build/resource.h"
|
||||||
|
|
||||||
#include "imgui/impl_dx9.h"
|
#include "external/imgui/backends/imgui_impl_dx9.h"
|
||||||
#include "imgui/impl_spice.h"
|
|
||||||
#include "imgui/impl_sw.h"
|
|
||||||
#include "overlay/imgui/impl_dx9.h"
|
|
||||||
#include "overlay/imgui/impl_spice.h"
|
#include "overlay/imgui/impl_spice.h"
|
||||||
#include "overlay/imgui/impl_sw.h"
|
#include "overlay/imgui/impl_sw.h"
|
||||||
|
|
||||||
@@ -62,6 +60,7 @@ namespace overlay {
|
|||||||
std::mutex OVERLAY_MUTEX;
|
std::mutex OVERLAY_MUTEX;
|
||||||
std::unique_ptr<overlay::SpiceOverlay> OVERLAY = nullptr;
|
std::unique_ptr<overlay::SpiceOverlay> OVERLAY = nullptr;
|
||||||
ImFont* DSEG_FONT = nullptr;
|
ImFont* DSEG_FONT = nullptr;
|
||||||
|
bool SHOW_DEBUG_LOG_WINDOW = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ImGui_Alloc(size_t sz, void *user_data) {
|
static void *ImGui_Alloc(size_t sz, void *user_data) {
|
||||||
@@ -242,13 +241,20 @@ void overlay::SpiceOverlay::init() {
|
|||||||
io.UserData = this;
|
io.UserData = this;
|
||||||
io.ConfigFlags = ImGuiConfigFlags_NavEnableKeyboard
|
io.ConfigFlags = ImGuiConfigFlags_NavEnableKeyboard
|
||||||
| ImGuiConfigFlags_NavEnableGamepad
|
| ImGuiConfigFlags_NavEnableGamepad
|
||||||
| ImGuiConfigFlags_NavEnableSetMousePos
|
| ImGuiConfigFlags_NavEnableSetMousePos;
|
||||||
| ImGuiConfigFlags_DockingEnable
|
|
||||||
| ImGuiConfigFlags_ViewportsEnable;
|
if (!cfg::CONFIGURATOR_STANDALONE) {
|
||||||
if (is_touch_available()) {
|
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||||
|
}
|
||||||
|
if (is_touch_available("SpiceOverlay::init")) {
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen;
|
io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// temporarily turn this off as it can cause crashes during font load failures
|
||||||
|
// turns back on in ImGui_ImplSpice_Init
|
||||||
|
io.ConfigErrorRecoveryEnableTooltip = false;
|
||||||
|
|
||||||
io.MouseDrawCursor = !GRAPHICS_SHOW_CURSOR;
|
io.MouseDrawCursor = !GRAPHICS_SHOW_CURSOR;
|
||||||
|
|
||||||
// disable config
|
// disable config
|
||||||
@@ -263,20 +269,14 @@ void overlay::SpiceOverlay::init() {
|
|||||||
// add fallback fonts for missing glyph ranges
|
// add fallback fonts for missing glyph ranges
|
||||||
ImFontConfig config {};
|
ImFontConfig config {};
|
||||||
config.MergeMode = true;
|
config.MergeMode = true;
|
||||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\simsun.ttc)",
|
|
||||||
13.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
add_font("simsun.ttc", &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\arial.ttf)",
|
add_font("arial.ttc", &config, io.Fonts->GetGlyphRangesCyrillic());
|
||||||
13.0f, &config, io.Fonts->GetGlyphRangesCyrillic());
|
add_font("meiryu.ttc", &config, io.Fonts->GetGlyphRangesJapanese());
|
||||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\meiryu.ttc)",
|
add_font("meiryo.ttc", &config, io.Fonts->GetGlyphRangesJapanese());
|
||||||
13.0f, &config, io.Fonts->GetGlyphRangesJapanese());
|
add_font("gulim.ttc", &config, io.Fonts->GetGlyphRangesKorean());
|
||||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\meiryo.ttc)",
|
add_font("cordia.ttc", &config, io.Fonts->GetGlyphRangesThai());
|
||||||
13.0f, &config, io.Fonts->GetGlyphRangesJapanese());
|
add_font("arial.ttc", &config, io.Fonts->GetGlyphRangesVietnamese());
|
||||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\gulim.ttc)",
|
|
||||||
13.0f, &config, io.Fonts->GetGlyphRangesKorean());
|
|
||||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\cordia.ttf)",
|
|
||||||
13.0f, &config, io.Fonts->GetGlyphRangesThai());
|
|
||||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\arial.ttf)",
|
|
||||||
13.0f, &config, io.Fonts->GetGlyphRangesVietnamese());
|
|
||||||
|
|
||||||
// add special font
|
// add special font
|
||||||
if (avs::game::is_model("LDJ")) {
|
if (avs::game::is_model("LDJ")) {
|
||||||
@@ -458,6 +458,10 @@ void overlay::SpiceOverlay::new_frame() {
|
|||||||
window->build();
|
window->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SHOW_DEBUG_LOG_WINDOW) {
|
||||||
|
ImGui::ShowDebugLogWindow(&SHOW_DEBUG_LOG_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
// end frame
|
// end frame
|
||||||
ImGui::EndFrame();
|
ImGui::EndFrame();
|
||||||
}
|
}
|
||||||
@@ -693,3 +697,21 @@ uint32_t *overlay::SpiceOverlay::sw_get_pixel_data(int *width, int *height) {
|
|||||||
*height = this->pixel_data_height;
|
*height = this->pixel_data_height;
|
||||||
return &this->pixel_data[0];
|
return &this->pixel_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void overlay::SpiceOverlay::add_font(const char* font, ImFontConfig* config, const ImWchar* glyphs) {
|
||||||
|
CHAR fonts_dir[MAX_PATH];
|
||||||
|
ExpandEnvironmentStringsA(R"(%SYSTEMROOT%\Fonts\)", fonts_dir, MAX_PATH);
|
||||||
|
std::filesystem::path full_path = fonts_dir;
|
||||||
|
full_path += font;
|
||||||
|
|
||||||
|
if (fileutils::file_exists(full_path)) {
|
||||||
|
log_misc("overlay", "loading font: {}", full_path.string());
|
||||||
|
ImGui::GetIO().Fonts->AddFontFromFileTTF(
|
||||||
|
full_path.string().c_str(),
|
||||||
|
13.0f,
|
||||||
|
config,
|
||||||
|
glyphs);
|
||||||
|
} else {
|
||||||
|
log_misc("overlay", "font not found: {}", full_path.string());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ namespace overlay {
|
|||||||
extern bool AUTO_SHOW_KEYPAD_P2;
|
extern bool AUTO_SHOW_KEYPAD_P2;
|
||||||
extern bool USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT;
|
extern bool USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT;
|
||||||
extern bool FPS_SHOULD_FLIP;
|
extern bool FPS_SHOULD_FLIP;
|
||||||
|
extern bool SHOW_DEBUG_LOG_WINDOW;
|
||||||
|
|
||||||
class SpiceOverlay {
|
class SpiceOverlay {
|
||||||
public:
|
public:
|
||||||
@@ -128,6 +129,7 @@ namespace overlay {
|
|||||||
bool hotkey_toggle_last = false;
|
bool hotkey_toggle_last = false;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void add_font(const char* font, ImFontConfig* config, const ImWchar* glyphs);
|
||||||
};
|
};
|
||||||
|
|
||||||
// global
|
// global
|
||||||
|
|||||||
@@ -99,10 +99,9 @@ void overlay::Window::build() {
|
|||||||
for (auto &child : this->children) {
|
for (auto &child : this->children) {
|
||||||
child->build();
|
child->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// end window
|
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
// end window
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
if (this->remove_window_padding) {
|
if (this->remove_window_padding) {
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "external/imgui/imgui.h"
|
#include "external/imgui/imgui.h"
|
||||||
#include "external/imgui/imgui_stdlib.h"
|
#include "external/imgui/misc/cpp/imgui_stdlib.h"
|
||||||
#include "overlay.h"
|
#include "overlay.h"
|
||||||
|
|
||||||
namespace overlay {
|
namespace overlay {
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
#include "external/rapidjson/document.h"
|
#include "external/rapidjson/document.h"
|
||||||
#include "external/rapidjson/prettywriter.h"
|
#include "external/rapidjson/prettywriter.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
|
#include "misc/clipboard.h"
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
#include "cfg/configurator.h"
|
#include "cfg/configurator.h"
|
||||||
|
#include "overlay/imgui/extensions.h"
|
||||||
|
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
@@ -27,19 +29,76 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->toggle_button = games::OverlayButtons::ToggleCardManager;
|
this->toggle_button = games::OverlayButtons::ToggleCardManager;
|
||||||
this->config_path = std::filesystem::path(_wgetenv(L"APPDATA")) / L"spicetools_card_manager.json";
|
|
||||||
if (fileutils::file_exists(this->config_path)) {
|
bool file_exists = false;
|
||||||
|
this->config_path =
|
||||||
|
fileutils::get_config_file_path("cardmanager", "spicetools_card_manager.json", &file_exists);
|
||||||
|
if (file_exists) {
|
||||||
this->config_load();
|
this->config_load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load -card0 / -card1
|
||||||
|
// -card0 / -card1 override
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||||
|
if (!CARD_OVERRIDES[0].empty()) {
|
||||||
|
const CardEntry card0 = {
|
||||||
|
.name = "P1 Default (-card0)",
|
||||||
|
.id = CARD_OVERRIDES[0],
|
||||||
|
.search_string = "p1 default (-card0)",
|
||||||
|
.read_only = true,
|
||||||
|
.color = {0.9f, 0.9f, 0.9f}
|
||||||
|
};
|
||||||
|
card_cmd_overrides[0].emplace(card0);
|
||||||
|
this->loaded_card[0] = card0;
|
||||||
|
}
|
||||||
|
if (eamuse_get_game_keypads() > 1 && !CARD_OVERRIDES[1].empty()) {
|
||||||
|
const CardEntry card1 = {
|
||||||
|
.name = "P2 Default (-card1)",
|
||||||
|
.id = CARD_OVERRIDES[1],
|
||||||
|
.search_string = "p2 default (-card1)",
|
||||||
|
.read_only = true,
|
||||||
|
.color = {0.9f, 0.9f, 0.9f}
|
||||||
|
};
|
||||||
|
card_cmd_overrides[1].emplace(card1);
|
||||||
|
this->loaded_card[1] = card1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardManager::~CardManager() {
|
CardManager::~CardManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardManager::build_content() {
|
void CardManager::build_content() {
|
||||||
ImGui::SeparatorText("Selected card");
|
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Active card overrides");
|
||||||
build_card();
|
ImGui::SameLine();
|
||||||
ImGui::SeparatorText("Available cards");
|
ImGui::HelpMarker(
|
||||||
|
"Click to insert card now, or press Insert Card key. Auto Card Insert will also use these cards.\n\n"
|
||||||
|
"If no override is set, pressing Insert Card will read from card0.txt / card1.txt.");
|
||||||
|
if (ImGui::BeginTable("CardSetTable", eamuse_get_game_keypads() > 1 ? 2 : 1, ImGuiTableFlags_SizingFixedFit)) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("Player 1");
|
||||||
|
if (eamuse_get_game_keypads() > 1) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("Player 2");
|
||||||
|
}
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
if (eamuse_get_game_keypads() > (int)i) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (build_card(i) && this->loaded_card[i].has_value()) {
|
||||||
|
insert_card_over_api(i, this->loaded_card[i].value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Available cards");
|
||||||
build_card_list();
|
build_card_list();
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
@@ -48,44 +107,13 @@ namespace overlay::windows {
|
|||||||
build_card_editor();
|
build_card_editor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardManager::build_card() {
|
bool CardManager::build_card(int reader) {
|
||||||
ImGui::BeginDisabled(this->current_card == nullptr);
|
ImGui::PushID(reader);
|
||||||
// insert P1 button
|
bool clicked = false;
|
||||||
if (ImGui::Button("Insert P1")) {
|
if (this->loaded_card[reader].has_value()) {
|
||||||
const auto card = this->current_card;
|
const auto &card = this->loaded_card[reader].value();
|
||||||
uint8_t card_bin[8];
|
const ImVec4 color(card.color[0], card.color[1], card.color[2], 1.f);
|
||||||
if (card && card->id.length() == 16 && hex2bin(card->id.c_str(), card_bin)) {
|
float bg_luminance = (0.299f * card.color[0] + 0.587 * card.color[1] + 0.114 * card.color[2]);
|
||||||
eamuse_card_insert(0, card_bin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert P2 button
|
|
||||||
if (eamuse_get_game_keypads() > 1) {
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Insert P2")) {
|
|
||||||
const auto card = this->current_card;
|
|
||||||
uint8_t card_bin[8];
|
|
||||||
if (card && card->id.length() == 16 && hex2bin(card->id.c_str(), card_bin)) {
|
|
||||||
eamuse_card_insert(1, card_bin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// edit selected card
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Edit Card")) {
|
|
||||||
open_card_editor();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndDisabled();
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// card ui
|
|
||||||
if (this->current_card) {
|
|
||||||
const auto card = this->current_card;
|
|
||||||
const ImVec4 color(card->color[0], card->color[1], card->color[2], 1.f);
|
|
||||||
float bg_luminance = (0.299f * card->color[0] + 0.587 * card->color[1] + 0.114 * card->color[2]);
|
|
||||||
|
|
||||||
// text color
|
// text color
|
||||||
ImVec4 text_color;
|
ImVec4 text_color;
|
||||||
@@ -101,22 +129,25 @@ namespace overlay::windows {
|
|||||||
ImGui::PushStyleColor(ImGuiCol_Text, text_color);
|
ImGui::PushStyleColor(ImGuiCol_Text, text_color);
|
||||||
if (ImGui::Button(fmt::format(
|
if (ImGui::Button(fmt::format(
|
||||||
" {} \n {} {} {} {} ",
|
" {} \n {} {} {} {} ",
|
||||||
card->name.empty() ? "<blank>" : card->name.substr(0, 19),
|
card.name.empty() ? "<blank>" : card.name.substr(0, 19),
|
||||||
card->id.substr(0, 4).c_str(),
|
card.id.substr(0, 4).c_str(),
|
||||||
card->id.substr(4, 4).c_str(),
|
card.id.substr(4, 4).c_str(),
|
||||||
card->id.substr(8, 4).c_str(),
|
card.id.substr(8, 4).c_str(),
|
||||||
card->id.substr(12, 4).c_str()
|
card.id.substr(12, 4).c_str()
|
||||||
).c_str())) {
|
).c_str())) {
|
||||||
|
|
||||||
open_card_editor();
|
clicked = true;
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor(4);
|
ImGui::PopStyleColor(4);
|
||||||
} else {
|
} else {
|
||||||
ImGui::BeginDisabled();
|
ImGui::BeginDisabled();
|
||||||
ImGui::Button(" <No card> \n xxxx xxxx xxxx xxxx ");
|
ImGui::Button(" (No override set) \n"
|
||||||
|
" xxxx xxxx xxxx xxxx ");
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::PopStyleColor(4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
return clicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardManager::open_card_editor() {
|
void CardManager::open_card_editor() {
|
||||||
@@ -140,13 +171,18 @@ namespace overlay::windows {
|
|||||||
this->card_buffer,
|
this->card_buffer,
|
||||||
std::size(this->card_buffer),
|
std::size(this->card_buffer),
|
||||||
ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
|
ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
|
||||||
|
ImGui::EndDisabled();
|
||||||
if (this->current_card == nullptr) {
|
if (this->current_card == nullptr) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Generate")) {
|
if (ImGui::Button("Generate")) {
|
||||||
generate_ea_card(this->card_buffer);
|
generate_ea_card(this->card_buffer);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Copy")) {
|
||||||
|
clipboard::copy_text(this->current_card->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
|
||||||
|
|
||||||
// name field
|
// name field
|
||||||
ImGui::InputTextWithHint("Card Name", "Main Card",
|
ImGui::InputTextWithHint("Card Name", "Main Card",
|
||||||
@@ -171,6 +207,18 @@ namespace overlay::windows {
|
|||||||
this->current_card->color[1] = this->color_buffer[1];
|
this->current_card->color[1] = this->color_buffer[1];
|
||||||
this->current_card->color[2] = this->color_buffer[2];
|
this->current_card->color[2] = this->color_buffer[2];
|
||||||
generate_search_string(this->current_card);
|
generate_search_string(this->current_card);
|
||||||
|
|
||||||
|
// ensure loaded cards are kept up to date
|
||||||
|
// note: does not handle cases where multiple cards have the same ID
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
if (this->loaded_card[i].has_value() &&
|
||||||
|
!this->loaded_card[i].value().read_only &&
|
||||||
|
this->loaded_card[i].value().id == this->current_card->id) {
|
||||||
|
this->loaded_card[i] = *this->current_card;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// create a new card
|
// create a new card
|
||||||
CardEntry card {
|
CardEntry card {
|
||||||
@@ -211,14 +259,54 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardManager::build_card_selectable(CardEntry &card) {
|
||||||
|
// generate card name
|
||||||
|
std::string card_name = "";
|
||||||
|
if (card.id.length() == 16) {
|
||||||
|
card_name += card.id.substr(0, 4);
|
||||||
|
card_name += " ";
|
||||||
|
card_name += card.id.substr(4, 4);
|
||||||
|
card_name += " ";
|
||||||
|
card_name += card.id.substr(8, 4);
|
||||||
|
card_name += " ";
|
||||||
|
card_name += card.id.substr(12, 4);
|
||||||
|
} else {
|
||||||
|
card_name += card.id;
|
||||||
|
}
|
||||||
|
if (!card.name.empty()) {
|
||||||
|
card_name += " - ";
|
||||||
|
card_name += card.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PushID(&card);
|
||||||
|
|
||||||
|
// color button
|
||||||
|
ImVec4 color(card.color[0], card.color[1], card.color[2], 1.f);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color);
|
||||||
|
ImGui::SmallButton(" ");
|
||||||
|
ImGui::PopStyleColor(3);
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// selectable item
|
||||||
|
if (ImGui::Selectable(card_name.c_str(), this->current_card == &card)) {
|
||||||
|
this->current_card = &card;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
void CardManager::build_card_list() {
|
void CardManager::build_card_list() {
|
||||||
|
|
||||||
// search for card
|
// search for card
|
||||||
//
|
//
|
||||||
// setting ImGuiInputTextFlags_CallbackCharFilter and pressing escape doesn't cause below
|
// setting ImGuiInputTextFlags_CallbackCharFilter and pressing escape doesn't cause below
|
||||||
// to return true, making it necessary to provide a callback...
|
// to return true, making it necessary to provide a callback...
|
||||||
ImGui::SetNextItemWidth(220);
|
ImGui::SetNextItemWidth(240);
|
||||||
if (ImGui::InputTextWithHint("", "Type here to search..", &this->search_filter)) {
|
if (ImGui::InputTextWithHint("", "Type here to search..", &this->search_filter)) {
|
||||||
|
this->current_card = nullptr;
|
||||||
this->search_filter_in_lower_case = strtolower(this->search_filter);
|
this->search_filter_in_lower_case = strtolower(this->search_filter);
|
||||||
}
|
}
|
||||||
if (!this->search_filter.empty()) {
|
if (!this->search_filter.empty()) {
|
||||||
@@ -227,11 +315,49 @@ namespace overlay::windows {
|
|||||||
this->search_filter.clear();
|
this->search_filter.clear();
|
||||||
this->search_filter_in_lower_case.clear();
|
this->search_filter_in_lower_case.clear();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
|
// toolbar
|
||||||
// move selected up/down the list
|
|
||||||
ImGui::BeginDisabled(this->current_card == nullptr);
|
// set card as p1/p2
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
if (eamuse_get_game_keypads() > (int)i) {
|
||||||
|
if (i != 0) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
ImGui::PushID(i);
|
||||||
|
ImGui::BeginDisabled(this->current_card == nullptr);
|
||||||
|
if (ImGui::Button(i == 0 ? "Load P1" : "Load P2") && this->current_card) {
|
||||||
|
this->loaded_card[i] = *this->current_card;
|
||||||
|
log_info(
|
||||||
|
"cardmanager",
|
||||||
|
"[P{}] update override and insert card: {} ({})",
|
||||||
|
i+1,
|
||||||
|
this->current_card->id,
|
||||||
|
this->current_card->name
|
||||||
|
);
|
||||||
|
|
||||||
|
// update override
|
||||||
|
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||||
|
CARD_OVERRIDES[i] = this->current_card->id;
|
||||||
|
|
||||||
|
// insert card over api
|
||||||
|
insert_card_over_api(i, this->loaded_card[i].value());
|
||||||
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// edit selected card
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::BeginDisabled(this->current_card == nullptr || this->current_card->read_only);
|
||||||
|
if (ImGui::Button("Edit")) {
|
||||||
|
open_card_editor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// move selected up/down the list
|
||||||
|
if (this->search_filter.empty()) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Move Up")) {
|
if (ImGui::Button("Move Up")) {
|
||||||
for (auto it = this->cards.begin(); it != this->cards.end(); ++it) {
|
for (auto it = this->cards.begin(); it != this->cards.end(); ++it) {
|
||||||
@@ -254,60 +380,37 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
|
||||||
}
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
// cards list
|
// cards list
|
||||||
// use all available vertical space, minus height of buttons, minus separator
|
// use all available vertical space, minus height footer (a row of buttons and separator)
|
||||||
if (ImGui::BeginChild(
|
if (ImGui::BeginChild(
|
||||||
"cards",
|
"cards",
|
||||||
ImVec2(0, ImGui::GetContentRegionAvail().y - ImGui::GetFrameHeightWithSpacing() - 8.f))) {
|
ImVec2(0, ImGui::GetContentRegionAvail().y - ImGui::GetFrameHeightWithSpacing() - 8.f))) {
|
||||||
|
|
||||||
|
// -card0 / -card1 override
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
if (card_cmd_overrides[i].has_value()) {
|
||||||
|
build_card_selectable(card_cmd_overrides[i].value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cards from card manager JSON
|
||||||
for (auto &card : this->cards) {
|
for (auto &card : this->cards) {
|
||||||
|
|
||||||
// get card name
|
|
||||||
std::string card_name = "";
|
|
||||||
if (card.id.length() == 16) {
|
|
||||||
card_name += card.id.substr(0, 4);
|
|
||||||
card_name += " ";
|
|
||||||
card_name += card.id.substr(4, 4);
|
|
||||||
card_name += " ";
|
|
||||||
card_name += card.id.substr(8, 4);
|
|
||||||
card_name += " ";
|
|
||||||
card_name += card.id.substr(12, 4);
|
|
||||||
} else {
|
|
||||||
card_name += card.id;
|
|
||||||
}
|
|
||||||
if (!card.name.empty()) {
|
|
||||||
card_name += " - ";
|
|
||||||
card_name += card.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this->search_filter_in_lower_case.empty() && !card.search_string.empty()) {
|
if (!this->search_filter_in_lower_case.empty() && !card.search_string.empty()) {
|
||||||
const bool matched =
|
const bool matched =
|
||||||
card.search_string.find(this->search_filter_in_lower_case) != std::string::npos;
|
card.search_string.find(this->search_filter_in_lower_case) != std::string::npos;
|
||||||
|
|
||||||
if (!matched) {
|
if (!matched) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw entry
|
build_card_selectable(card);
|
||||||
ImGui::PushID(&card);
|
|
||||||
|
|
||||||
ImVec4 color(card.color[0], card.color[1], card.color[2], 1.f);
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color);
|
|
||||||
ImGui::SmallButton(" ");
|
|
||||||
ImGui::PopStyleColor(3);
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Selectable(card_name.c_str(), this->current_card == &card)) {
|
|
||||||
this->current_card = &card;
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@@ -334,8 +437,6 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CardManager::config_load() {
|
void CardManager::config_load() {
|
||||||
log_info("cardmanager", "loading config");
|
|
||||||
|
|
||||||
// clear cards
|
// clear cards
|
||||||
this->cards.clear();
|
this->cards.clear();
|
||||||
|
|
||||||
@@ -466,10 +567,10 @@ namespace overlay::windows {
|
|||||||
doc.Accept(writer);
|
doc.Accept(writer);
|
||||||
|
|
||||||
// save to file
|
// save to file
|
||||||
if (fileutils::text_write(this->config_path, buffer.GetString())) {
|
if (fileutils::write_config_file("cardmanager", this->config_path, buffer.GetString())) {
|
||||||
this->config_dirty = false;
|
this->config_dirty = false;
|
||||||
} else {
|
} else {
|
||||||
log_warning("cardmanager", "unable to save config file to {}", this->config_path.string());
|
log_warning("cardmanager", "unable to save config file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,4 +605,11 @@ namespace overlay::windows {
|
|||||||
this->color_buffer[1] = g / 255.f;
|
this->color_buffer[1] = g / 255.f;
|
||||||
this->color_buffer[2] = b / 255.f;
|
this->color_buffer[2] = b / 255.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardManager::insert_card_over_api(int reader, CardEntry &card) {
|
||||||
|
uint8_t card_bin[8];
|
||||||
|
if (card.id.length() == 16 && hex2bin(card.id.c_str(), card_bin)) {
|
||||||
|
eamuse_card_insert(reader, card_bin);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "overlay/window.h"
|
#include "overlay/window.h"
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ namespace overlay::windows {
|
|||||||
std::string name = "unnamed";
|
std::string name = "unnamed";
|
||||||
std::string id = "E004010000000000";
|
std::string id = "E004010000000000";
|
||||||
std::string search_string = "";
|
std::string search_string = "";
|
||||||
|
bool read_only = false;
|
||||||
float color[3] {};
|
float color[3] {};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,7 +31,10 @@ namespace overlay::windows {
|
|||||||
char name_buffer[65] {};
|
char name_buffer[65] {};
|
||||||
char card_buffer[17] {};
|
char card_buffer[17] {};
|
||||||
float color_buffer[3] {};
|
float color_buffer[3] {};
|
||||||
|
|
||||||
|
std::optional<CardEntry> card_cmd_overrides[2];
|
||||||
|
|
||||||
|
std::optional<CardEntry> loaded_card[2];
|
||||||
CardEntry *current_card = nullptr;
|
CardEntry *current_card = nullptr;
|
||||||
|
|
||||||
std::string search_filter = "";
|
std::string search_filter = "";
|
||||||
@@ -41,10 +46,13 @@ namespace overlay::windows {
|
|||||||
void generate_search_string(CardEntry *card);
|
void generate_search_string(CardEntry *card);
|
||||||
void generate_random_color();
|
void generate_random_color();
|
||||||
|
|
||||||
void build_card();
|
bool build_card(int reader);
|
||||||
void open_card_editor();
|
void open_card_editor();
|
||||||
void build_card_editor();
|
void build_card_editor();
|
||||||
void build_card_list();
|
void build_card_list();
|
||||||
|
void build_card_selectable(CardEntry &card);
|
||||||
void build_footer();
|
void build_footer();
|
||||||
|
|
||||||
|
void insert_card_over_api(int reader, CardEntry &card);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1896
-1881
File diff suppressed because it is too large
Load Diff
@@ -95,7 +95,7 @@ namespace overlay::windows {
|
|||||||
void build_about();
|
void build_about();
|
||||||
void build_licenses();
|
void build_licenses();
|
||||||
void build_launcher();
|
void build_launcher();
|
||||||
void launch_shell(LPCSTR app, LPCSTR file);
|
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
|
||||||
|
|
||||||
static void build_page_selector(int *page);
|
static void build_page_selector(int *page);
|
||||||
void build_menu(int *game_selected);
|
void build_menu(int *game_selected);
|
||||||
|
|||||||
@@ -178,9 +178,11 @@ namespace overlay::windows {
|
|||||||
static_cast<int>(ImGui::GetIO().DisplaySize.x),
|
static_cast<int>(ImGui::GetIO().DisplaySize.x),
|
||||||
static_cast<int>(ImGui::GetIO().DisplaySize.y));
|
static_cast<int>(ImGui::GetIO().DisplaySize.y));
|
||||||
|
|
||||||
// removed for size (along with setting IMGUI_DISABLE_DEMO_WINDOWS
|
if (ImGui::Button("ImGui Debug Log")) {
|
||||||
// and IMGUI_DISABLE_DEBUG_TOOLS) - saves about 300kb in each
|
overlay::SHOW_DEBUG_LOG_WINDOW = !overlay::SHOW_DEBUG_LOG_WINDOW;
|
||||||
// binary
|
}
|
||||||
|
|
||||||
|
// removed for size (IMGUI_DISABLE_DEMO_WINDOWS)
|
||||||
|
|
||||||
// metrics button
|
// metrics button
|
||||||
// this->metrics_open |= ImGui::Button("Metrics Window");
|
// this->metrics_open |= ImGui::Button("Metrics Window");
|
||||||
@@ -749,7 +751,7 @@ namespace overlay::windows {
|
|||||||
if (ImGui::CollapsingHeader("Touch")) {
|
if (ImGui::CollapsingHeader("Touch")) {
|
||||||
|
|
||||||
// status
|
// status
|
||||||
ImGui::Text("Status: %s", is_touch_available() ? "available" : "unavailable");
|
ImGui::Text("Status: %s", is_touch_available("Control::touch_view") ? "available" : "unavailable");
|
||||||
|
|
||||||
// touch points
|
// touch points
|
||||||
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ namespace overlay::windows {
|
|||||||
bottom_right.x += overlay_content_top_left.x;
|
bottom_right.x += overlay_content_top_left.x;
|
||||||
bottom_right.y += overlay_content_top_left.y;
|
bottom_right.y += overlay_content_top_left.y;
|
||||||
ImGui::GetBackgroundDrawList()->AddImage(
|
ImGui::GetBackgroundDrawList()->AddImage(
|
||||||
reinterpret_cast<void *>(this->texture),
|
reinterpret_cast<ImTextureID>(this->texture),
|
||||||
overlay_content_top_left,
|
overlay_content_top_left,
|
||||||
bottom_right);
|
bottom_right);
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace overlay::windows {
|
|||||||
{"arkmmd.dll", {"gamemmd.dll"}},
|
{"arkmmd.dll", {"gamemmd.dll"}},
|
||||||
{"arkklp.dll", {"lpac.dll"}},
|
{"arkklp.dll", {"lpac.dll"}},
|
||||||
{"arknck.dll", {"weac.dll"}},
|
{"arknck.dll", {"weac.dll"}},
|
||||||
{"gdxg.dll", {"game.dll"}}
|
{"gdxg.dll", {"game.dll", "libshare-pj.dll"}}
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t url_recent_idx = -1;
|
static size_t url_recent_idx = -1;
|
||||||
@@ -151,7 +151,7 @@ namespace overlay::windows {
|
|||||||
url_fetch_errors += fmt::format("WinHttpSendRequest failed: {}\n", gle);
|
url_fetch_errors += fmt::format("WinHttpSendRequest failed: {}\n", gle);
|
||||||
if (gle == 12175) {
|
if (gle == 12175) {
|
||||||
url_fetch_errors += "\nThis is ERROR_WINHTTP_SECURE_FAILURE - most likely TLS 1.1 / TLS 1.2 error on old OS versions.\n\n";
|
url_fetch_errors += "\nThis is ERROR_WINHTTP_SECURE_FAILURE - most likely TLS 1.1 / TLS 1.2 error on old OS versions.\n\n";
|
||||||
url_fetch_errors += "Look up MSDN article on 'Update to enable TLS 1.1 and TLS 1.2 as default secure protocols in WinHTTP in Windows' for a fix.";
|
url_fetch_errors += "Look up MSDN article on 'Update to enable TLS 1.1 and TLS 1.2 as default secure protocols in WinHTTP in Windows' for a fix.\n";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ namespace overlay::windows {
|
|||||||
statusCode,
|
statusCode,
|
||||||
netutils::http_status_reason_phrase(statusCode));
|
netutils::http_status_reason_phrase(statusCode));
|
||||||
if (statusCode == 404) {
|
if (statusCode == 404) {
|
||||||
url_fetch_errors += "(Patch server did not find any patches for this game version)";
|
url_fetch_errors += "(Patch server did not find any patches for this game version)\n";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,8 @@ namespace overlay::windows {
|
|||||||
this->config_path = PATCH_MANAGER_CFG_PATH_OVERRIDE.value();
|
this->config_path = PATCH_MANAGER_CFG_PATH_OVERRIDE.value();
|
||||||
log_info("patchmanager", "using custom config file path: {}", this->config_path.string().c_str());
|
log_info("patchmanager", "using custom config file path: {}", this->config_path.string().c_str());
|
||||||
} else {
|
} else {
|
||||||
this->config_path = std::filesystem::path(_wgetenv(L"APPDATA")) / L"spicetools_patch_manager.json";
|
this->config_path =
|
||||||
|
fileutils::get_config_file_path("patchmanager", "spicetools_patch_manager.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ldr_registered) {
|
if (!ldr_registered) {
|
||||||
@@ -550,7 +551,7 @@ namespace overlay::windows {
|
|||||||
ImGui::Text("Failed to import patches from URL.");
|
ImGui::Text("Failed to import patches from URL.");
|
||||||
if (!url_fetch_errors.empty()) {
|
if (!url_fetch_errors.empty()) {
|
||||||
ImGui::TextUnformatted("");
|
ImGui::TextUnformatted("");
|
||||||
ImGui::PushTextWrapPos(ImGui::GetIO().DisplaySize.x * 0.5);
|
ImGui::PushTextWrapPos(ImGui::GetIO().DisplaySize.x * 0.7);
|
||||||
ImGui::TextUnformatted(url_fetch_errors.c_str());
|
ImGui::TextUnformatted(url_fetch_errors.c_str());
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
}
|
}
|
||||||
@@ -558,6 +559,12 @@ namespace overlay::windows {
|
|||||||
if (ImGui::Button("OK")) {
|
if (ImGui::Button("OK")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
if (!url_fetch_errors.empty()) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Copy Error")) {
|
||||||
|
clipboard::copy_text(url_fetch_errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,17 +656,9 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
// first column, part 1: help / caution marker
|
// first column, part 1: help / caution marker
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
const std::string description = patch.description;
|
if (!patch.caution.empty()) {
|
||||||
const std::string caution = patch.caution;
|
|
||||||
if (!description.empty() && !caution.empty()) {
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::WarnMarker(description.c_str(), caution.c_str());
|
ImGui::WarnMarker(patch.description.c_str(), patch.caution.c_str());
|
||||||
} else if (!description.empty()) {
|
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
ImGui::HelpMarker(description.c_str());
|
|
||||||
} else if (!caution.empty()) {
|
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
ImGui::WarnMarker(nullptr, caution.c_str());
|
|
||||||
} else {
|
} else {
|
||||||
ImGui::DummyMarker();
|
ImGui::DummyMarker();
|
||||||
}
|
}
|
||||||
@@ -705,6 +704,11 @@ namespace overlay::windows {
|
|||||||
if (style_color_pushed) {
|
if (style_color_pushed) {
|
||||||
ImGui::PopStyleColor(style_color_pushed);
|
ImGui::PopStyleColor(style_color_pushed);
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
show_patch_tooltip(patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// show range after label for integer patches
|
||||||
if (patch.type == PatchType::Integer) {
|
if (patch.type == PatchType::Integer) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
auto& numpatch = patch.patch_number;
|
auto& numpatch = patch.patch_number;
|
||||||
@@ -741,6 +745,9 @@ namespace overlay::windows {
|
|||||||
patch.last_status = is_patch_active(patch);
|
patch.last_status = is_patch_active(patch);
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
show_patch_tooltip(patch);
|
||||||
|
}
|
||||||
|
|
||||||
// second column, part 2: additional options UI (dropdown, text input)
|
// second column, part 2: additional options UI (dropdown, text input)
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -767,6 +774,9 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
show_patch_tooltip(patch);
|
||||||
|
}
|
||||||
} else if (patch.type == PatchType::Integer) {
|
} else if (patch.type == PatchType::Integer) {
|
||||||
ImGui::SetNextItemWidth(200.0f);
|
ImGui::SetNextItemWidth(200.0f);
|
||||||
auto& numpatch = patch.patch_number;
|
auto& numpatch = patch.patch_number;
|
||||||
@@ -780,6 +790,9 @@ namespace overlay::windows {
|
|||||||
apply_patch(patch, true);
|
apply_patch(patch, true);
|
||||||
config_dirty = true;
|
config_dirty = true;
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
show_patch_tooltip(patch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (patch_status == PatchStatus::Disabled) {
|
} else if (patch_status == PatchStatus::Disabled) {
|
||||||
ImGui::SetNextItemWidth(200.0f);
|
ImGui::SetNextItemWidth(200.0f);
|
||||||
@@ -794,6 +807,9 @@ namespace overlay::windows {
|
|||||||
ImGui::InputInt("##dummy_int_input", &patch.patch_number.value);
|
ImGui::InputInt("##dummy_int_input", &patch.patch_number.value);
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
show_patch_tooltip(patch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
@@ -822,6 +838,14 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PatchManager::show_patch_tooltip(const PatchData& patch) {
|
||||||
|
if (!patch.caution.empty()) {
|
||||||
|
ImGui::WarnTooltip(patch.description.c_str(), patch.caution.c_str());
|
||||||
|
} else if (!patch.description.empty()) {
|
||||||
|
ImGui::HelpTooltip(patch.description.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PatchManager::hard_apply_patches() {
|
void PatchManager::hard_apply_patches() {
|
||||||
std::vector<std::string> written_list;
|
std::vector<std::string> written_list;
|
||||||
for (auto& patch : patches) {
|
for (auto& patch : patches) {
|
||||||
@@ -1104,7 +1128,7 @@ namespace overlay::windows {
|
|||||||
doc.Accept(writer);
|
doc.Accept(writer);
|
||||||
|
|
||||||
// save to file
|
// save to file
|
||||||
if (fileutils::text_write(config_path, buffer.GetString())) {
|
if (fileutils::write_config_file("patchmanager", config_path, buffer.GetString())) {
|
||||||
config_dirty = false;
|
config_dirty = false;
|
||||||
} else {
|
} else {
|
||||||
log_warning("patchmanager", "unable to save config file");
|
log_warning("patchmanager", "unable to save config file");
|
||||||
@@ -1500,16 +1524,44 @@ namespace overlay::windows {
|
|||||||
try {
|
try {
|
||||||
auto patches_json = getFromUrl(dll_name, json_path);
|
auto patches_json = getFromUrl(dll_name, json_path);
|
||||||
if (!patches_json.empty()) {
|
if (!patches_json.empty()) {
|
||||||
if (!fileutils::dir_exists(LOCAL_PATCHES_PATH))
|
|
||||||
|
// see if this is valid JSON
|
||||||
|
Document doc_temp;
|
||||||
|
doc_temp.Parse(patches_json.c_str());
|
||||||
|
const auto error = doc_temp.GetParseError();
|
||||||
|
if (error) {
|
||||||
|
log_warning(
|
||||||
|
"patchmanager",
|
||||||
|
"remotely fetched JSON file parse error: {}",
|
||||||
|
rapidjson::GetParseError_En(error));
|
||||||
|
url_fetch_errors += fmt::format(
|
||||||
|
"Invalid JSON received from remote URL.\n"
|
||||||
|
"Your DLL version might not be supported.\n"
|
||||||
|
"URL: {}\n"
|
||||||
|
"JSON Parse Error: {}\n",
|
||||||
|
json_path,
|
||||||
|
rapidjson::GetParseError_En(error));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
log_info("patchmanager", "remotely fetched JSON was successfully parsed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create patches dir
|
||||||
|
if (!fileutils::dir_exists(LOCAL_PATCHES_PATH)) {
|
||||||
fileutils::dir_create(LOCAL_PATCHES_PATH);
|
fileutils::dir_create(LOCAL_PATCHES_PATH);
|
||||||
|
}
|
||||||
|
// save to file
|
||||||
std::filesystem::path save_path = LOCAL_PATCHES_PATH / (identifier + ".json");
|
std::filesystem::path save_path = LOCAL_PATCHES_PATH / (identifier + ".json");
|
||||||
fileutils::text_write(save_path, patches_json);
|
fileutils::text_write(save_path, patches_json);
|
||||||
|
log_info("patchmanager", "remotely fetched JSON saved to: {}", save_path.string());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
log_warning("patchmanager", "failed to fetch patches JSON for {}", dll_name);
|
log_warning("patchmanager", "failed to fetch patches JSON for {}", dll_name);
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
log_warning("patchmanager", "exception occurred while loading remote patches JSON for {}: {}", dll_name, e.what());
|
log_warning("patchmanager", "exception occurred while loading remote patches JSON for {}: {}", dll_name, e.what());
|
||||||
|
url_fetch_errors += fmt::format(
|
||||||
|
"Exception while loading remote patches for {}: {}\n", dll_name, e.what());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1593,6 +1645,8 @@ namespace overlay::windows {
|
|||||||
std::string first_id = get_game_identifier(MODULE_PATH / firstDll);
|
std::string first_id = get_game_identifier(MODULE_PATH / firstDll);
|
||||||
std::filesystem::path firstPath = fmt::format("patches/{}.json", first_id);
|
std::filesystem::path firstPath = fmt::format("patches/{}.json", first_id);
|
||||||
|
|
||||||
|
log_misc("patchmanager", "patch identifier of {}: {}", firstDll, first_id);
|
||||||
|
|
||||||
auto extraDlls = getExtraDlls(firstDll);
|
auto extraDlls = getExtraDlls(firstDll);
|
||||||
std::erase_if(extraDlls, [](const std::string& dll) {
|
std::erase_if(extraDlls, [](const std::string& dll) {
|
||||||
auto identifier = get_game_identifier(MODULE_PATH / dll);
|
auto identifier = get_game_identifier(MODULE_PATH / dll);
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ namespace overlay::windows {
|
|||||||
std::function<bool(const PatchData&)> filter = std::function<bool(const PatchData&)>(),
|
std::function<bool(const PatchData&)> filter = std::function<bool(const PatchData&)>(),
|
||||||
std::string pe_identifier_for_patch = "");
|
std::string pe_identifier_for_patch = "");
|
||||||
|
|
||||||
|
void show_patch_tooltip(const PatchData& patch);
|
||||||
};
|
};
|
||||||
|
|
||||||
PatchStatus is_patch_active(PatchData &patch);
|
PatchStatus is_patch_active(PatchData &patch);
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ namespace overlay::windows {
|
|||||||
for (size_t i = 0; i < std::size(cfg::SCREENRESIZE->scene_settings); i++) {
|
for (size_t i = 0; i < std::size(cfg::SCREENRESIZE->scene_settings); i++) {
|
||||||
auto& scene = cfg::SCREENRESIZE->scene_settings[i];
|
auto& scene = cfg::SCREENRESIZE->scene_settings[i];
|
||||||
scene.keep_aspect_ratio = true;
|
scene.keep_aspect_ratio = true;
|
||||||
scene.centered = true;
|
|
||||||
scene.offset_x = 0;
|
scene.offset_x = 0;
|
||||||
scene.offset_y = 0;
|
scene.offset_y = 0;
|
||||||
scene.scale_x = 1.f;
|
scene.scale_x = 1.f;
|
||||||
@@ -126,21 +125,28 @@ namespace overlay::windows {
|
|||||||
auto& scene = cfg::SCREENRESIZE->scene_settings[cfg::SCREENRESIZE->screen_resize_current_scene];
|
auto& scene = cfg::SCREENRESIZE->scene_settings[cfg::SCREENRESIZE->screen_resize_current_scene];
|
||||||
|
|
||||||
// general settings
|
// general settings
|
||||||
ImGui::Checkbox("Centered", &scene.centered);
|
ImGui::InputInt("X Offset", &scene.offset_x);
|
||||||
if (!scene.centered) {
|
ImGui::SameLine();
|
||||||
ImGui::InputInt("X Offset", &scene.offset_x);
|
ImGui::HelpMarker("Hint: ctrl + click on +/- buttons to move quickly.");
|
||||||
ImGui::InputInt("Y Offset", &scene.offset_y);
|
ImGui::InputInt("Y Offset", &scene.offset_y);
|
||||||
}
|
ImGui::SameLine();
|
||||||
|
ImGui::HelpMarker("Hint: ctrl + click on +/- buttons to move quickly.");
|
||||||
|
|
||||||
// aspect ratio
|
// aspect ratio
|
||||||
ImGui::Checkbox("Keep Aspect Ratio", &scene.keep_aspect_ratio);
|
ImGui::Checkbox("Keep Aspect Ratio", &scene.keep_aspect_ratio);
|
||||||
if (scene.keep_aspect_ratio) {
|
if (scene.keep_aspect_ratio) {
|
||||||
if (ImGui::SliderFloat("Scale", &scene.scale_x, 0.65f, 2.0f)) {
|
if (ImGui::SliderFloat("Scale", &scene.scale_x, 0.5f, 2.5f)) {
|
||||||
scene.scale_y = scene.scale_x;
|
scene.scale_y = scene.scale_x;
|
||||||
}
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value.");
|
||||||
} else {
|
} else {
|
||||||
ImGui::SliderFloat("Width Scale", &scene.scale_x, 0.65f, 2.0f);
|
ImGui::SliderFloat("Width Scale", &scene.scale_x, 0.5f, 2.5f);
|
||||||
ImGui::SliderFloat("Height Scale", &scene.scale_y, 0.65f, 2.0f);
|
ImGui::SameLine();
|
||||||
|
ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value.");
|
||||||
|
ImGui::SliderFloat("Height Scale", &scene.scale_y, 0.5f, 2.5f);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
@@ -167,8 +173,8 @@ namespace overlay::windows {
|
|||||||
"Change window decoration. Resizable Window may not cause your mouse cursor to change, "
|
"Change window decoration. Resizable Window may not cause your mouse cursor to change, "
|
||||||
"but you can still drag to resize. Disabled for some games due to incompatibility.");
|
"but you can still drag to resize. Disabled for some games due to incompatibility.");
|
||||||
|
|
||||||
if (ImGui::Checkbox("Always on Top", &cfg::SCREENRESIZE->window_always_on_top) ) {
|
if (ImGui::Checkbox("Always On Top", &cfg::SCREENRESIZE->window_always_on_top) ) {
|
||||||
graphics_update_z_order(window);
|
graphics_update_z_order(window, cfg::SCREENRESIZE->window_always_on_top);
|
||||||
}
|
}
|
||||||
ImGui::BeginDisabled();
|
ImGui::BeginDisabled();
|
||||||
ImGui::Checkbox("Forced Render Scaling", &GRAPHICS_WINDOW_BACKBUFFER_SCALE);
|
ImGui::Checkbox("Forced Render Scaling", &GRAPHICS_WINDOW_BACKBUFFER_SCALE);
|
||||||
|
|||||||
@@ -23,11 +23,35 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
const auto padding = ImGui::GetFrameHeight() / 2;
|
const auto padding = ImGui::GetFrameHeight() / 2;
|
||||||
|
|
||||||
this->init_size = ImVec2(ImGui::GetIO().DisplaySize.x - (padding * 2), 0.f);
|
switch (games::sdvx::OVERLAY_POS) {
|
||||||
this->init_size.y = (this->init_size.x * 9 / 16) + ImGui::GetFrameHeight();
|
case games::sdvx::SDVX_OVERLAY_BOTTOM_LEFT:
|
||||||
|
case games::sdvx::SDVX_OVERLAY_BOTTOM_RIGHT:
|
||||||
|
this->init_size.x = (ImGui::GetIO().DisplaySize.x - (ImGui::GetIO().DisplaySize.y * 9 / 16)) / 2 - padding;
|
||||||
|
this->init_size.y = (this->init_size.x * 9 / 16) + ImGui::GetFrameHeight();
|
||||||
|
break;
|
||||||
|
case games::sdvx::SDVX_OVERLAY_TOP:
|
||||||
|
case games::sdvx::SDVX_OVERLAY_BOTTOM:
|
||||||
|
case games::sdvx::SDVX_OVERLAY_MIDDLE:
|
||||||
|
default:
|
||||||
|
this->init_size = ImVec2(ImGui::GetIO().DisplaySize.x - (padding * 2), 0.f);
|
||||||
|
this->init_size.y = (this->init_size.x * 9 / 16) + ImGui::GetFrameHeight();
|
||||||
|
if (GRAPHICS_FS_ORIENTATION_SWAP) {
|
||||||
|
this->init_size.x /= 2;
|
||||||
|
this->init_size.y /= 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
this->init_pos = ImVec2(ImGui::GetIO().DisplaySize.x / 2 - this->init_size.x / 2, 0);
|
this->init_pos = ImVec2(ImGui::GetIO().DisplaySize.x / 2 - this->init_size.x / 2, 0);
|
||||||
switch (games::sdvx::OVERLAY_POS) {
|
switch (games::sdvx::OVERLAY_POS) {
|
||||||
|
case games::sdvx::SDVX_OVERLAY_BOTTOM_LEFT:
|
||||||
|
this->init_pos.x = 0;
|
||||||
|
this->init_pos.y = ImGui::GetIO().DisplaySize.y - this->init_size.y;
|
||||||
|
break;
|
||||||
|
case games::sdvx::SDVX_OVERLAY_BOTTOM_RIGHT:
|
||||||
|
this->init_pos.x = ImGui::GetIO().DisplaySize.x - this->init_size.x;
|
||||||
|
this->init_pos.y = ImGui::GetIO().DisplaySize.y - this->init_size.y;
|
||||||
|
break;
|
||||||
case games::sdvx::SDVX_OVERLAY_TOP:
|
case games::sdvx::SDVX_OVERLAY_TOP:
|
||||||
this->init_pos.y = padding;
|
this->init_pos.y = padding;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ namespace rawinput {
|
|||||||
int TOUCHSCREEN_RANGE_X = 0;
|
int TOUCHSCREEN_RANGE_X = 0;
|
||||||
int TOUCHSCREEN_RANGE_Y = 0;
|
int TOUCHSCREEN_RANGE_Y = 0;
|
||||||
bool DUMP_HID_DEVICES_TO_LOG = false;
|
bool DUMP_HID_DEVICES_TO_LOG = false;
|
||||||
|
bool NAIVE_REQUIRE_FOCUS = true;
|
||||||
|
bool RAWINPUT_REQUIRE_FOCUS = false;
|
||||||
|
|
||||||
// set this to something slightly longer than 16.67ms (60Hz) so that I/O can pick it up
|
// set this to something slightly longer than 16.67ms (60Hz) so that I/O can pick it up
|
||||||
// this may need to be adjusted for each game in the future if there is a game that polls less
|
// this may need to be adjusted for each game in the future if there is a game that polls less
|
||||||
@@ -494,7 +496,7 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
|||||||
// get string index
|
// get string index
|
||||||
ULONG string_index = 0;
|
ULONG string_index = 0;
|
||||||
if (button_caps.IsStringRange && button_caps.Range.StringMin != 0) {
|
if (button_caps.IsStringRange && button_caps.Range.StringMin != 0) {
|
||||||
string_index = button_caps.Range.StringMin + static_cast<ULONG>(button_output_caps_list.size()) - 1;
|
string_index = button_caps.Range.StringMin + static_cast<ULONG>(button_output_caps_names.size());
|
||||||
}
|
}
|
||||||
else if (!button_caps.IsStringRange && button_caps.NotRange.StringIndex != 0) {
|
else if (!button_caps.IsStringRange && button_caps.NotRange.StringIndex != 0) {
|
||||||
string_index = button_caps.NotRange.StringIndex;
|
string_index = button_caps.NotRange.StringIndex;
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ namespace rawinput {
|
|||||||
|
|
||||||
extern uint32_t MIDI_NOTE_SUSTAIN;
|
extern uint32_t MIDI_NOTE_SUSTAIN;
|
||||||
|
|
||||||
|
extern bool NAIVE_REQUIRE_FOCUS;
|
||||||
|
extern bool RAWINPUT_REQUIRE_FOCUS;
|
||||||
|
|
||||||
struct DeviceCallback {
|
struct DeviceCallback {
|
||||||
void *data;
|
void *data;
|
||||||
std::function<void(void*, Device*)> f;
|
std::function<void(void*, Device*)> f;
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#define EXPORT __declspec(dllexport)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Error_NoError = 0,
|
||||||
|
Error_DeviceNotFound = 100,
|
||||||
|
Error_Busy,
|
||||||
|
Error_Printing_Busy,
|
||||||
|
Error_Printing_Ready,
|
||||||
|
Error_PortBusy,
|
||||||
|
Error_GetCPDIDinfo,
|
||||||
|
Error_PrinterBusy,
|
||||||
|
Error_FuncParamError = 201,
|
||||||
|
Error_MemAllocError,
|
||||||
|
Error_Timeout,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9CheckPaperRemain(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9CheckPrinter(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9CheckPrintEnd(uint32_t p1, void *p2, void *p3) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9GetFWInfo(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9GetMediaType(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9GetTempInfo(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9GetTotalPrintCount(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9PreHeat(void *p1) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9PrintJobCancel(void *p1) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9PrintOut(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPU9SetPrintParameter2(void *p1, void *p2) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPUASendImage(void *p1, void *p2, void *p3, void *p4) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPUASendImagePrint(
|
||||||
|
void *p1, void *p2, void *p3, bool p4, void *p5, int32_t p6, void *p7) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPUASendImagePrint2(
|
||||||
|
void *p1, void *p2, void *p3, bool p4, bool p5, void *p6, int32_t p7, void *p8) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPUASetPrintParameter(void *p1, void *p2, bool p3, void *p4, void *p5) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t EXPORT __stdcall CPUXSearchPrinters(void *p1, void *p2, int32_t p3, void *p4) {
|
||||||
|
return Error_FuncParamError;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void EXPORT __stdcall CPUXInit() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user