mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 205cf29aff | |||
| bf9074a76e | |||
| 44e1edb50c | |||
| 41d0dce6e9 | |||
| 598422b701 | |||
| b58a1ccfcc | |||
| 60efd643d1 | |||
| 0596eeb6fe | |||
| 3d5c64feb7 |
@@ -13,6 +13,11 @@ jobs:
|
||||
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: |
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
> * 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.
|
||||
> * 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.
|
||||
|
||||
@@ -12,8 +13,5 @@
|
||||
## Description of change
|
||||
*what does this code do?*
|
||||
|
||||
## Compiling
|
||||
*you must be able to compile with the included Docker script with zero compiler warnings*
|
||||
|
||||
## Testing
|
||||
*how was the code tested?*
|
||||
|
||||
@@ -2,3 +2,4 @@ bin/**
|
||||
dist/**
|
||||
docker/**
|
||||
cmake-build*
|
||||
.ccache/**
|
||||
@@ -16,4 +16,6 @@ build_docker.local.sh
|
||||
bin/*
|
||||
dist/*
|
||||
|
||||
external/cv2pdb/*
|
||||
external/cv2pdb/*
|
||||
|
||||
.ccache/*
|
||||
@@ -607,6 +607,22 @@ IF(NOT MSVC)
|
||||
set_target_properties(spicetools_spice PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
||||
endif()
|
||||
|
||||
# spice_laa.exe
|
||||
###########
|
||||
|
||||
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
|
||||
add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES})
|
||||
target_link_libraries(spicetools_spice_laa
|
||||
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp
|
||||
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
|
||||
set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "")
|
||||
set_target_properties(spicetools_spice_laa PROPERTIES OUTPUT_NAME "spice_laa")
|
||||
target_compile_definitions(spicetools_spice_laa PRIVATE SPICE32_LARGE_ADDRESS_AWARE=1)
|
||||
|
||||
IF(NOT MSVC)
|
||||
set_target_properties(spicetools_spice_laa PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32 -Wl,--large-address-aware")
|
||||
endif()
|
||||
|
||||
# spice64.exe
|
||||
#############
|
||||
|
||||
@@ -626,7 +642,6 @@ IF(NOT MSVC)
|
||||
set_target_properties(spicetools_spice64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||
endif()
|
||||
|
||||
|
||||
# spicecfg.exe
|
||||
##############
|
||||
|
||||
@@ -732,7 +747,7 @@ set_target_properties(spicetools_cfg
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools")
|
||||
|
||||
# output 32bit
|
||||
set_target_properties(spicetools_spice spicetools_stubs_kbt spicetools_stubs_kld
|
||||
set_target_properties(spicetools_spice spicetools_spice_laa spicetools_stubs_kbt spicetools_stubs_kld
|
||||
PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive32"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32"
|
||||
|
||||
@@ -4,4 +4,4 @@ WORKDIR /src
|
||||
COPY --from=gitroot . /src/.git
|
||||
COPY . /src/src/spice2x
|
||||
WORKDIR /src/src/spice2x
|
||||
CMD ["./build_all.sh"]
|
||||
ENTRYPOINT ["./build_all.sh"]
|
||||
|
||||
@@ -76,18 +76,23 @@ namespace avs {
|
||||
const auto dll_path_s = dll_path.string();
|
||||
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(
|
||||
"avs-game",
|
||||
"PATH TOO LONG WARNING\n\n\n"
|
||||
"-------------------------------------------------------------------\n"
|
||||
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
||||
" PATH TOO LONG \n"
|
||||
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
||||
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||
"'{}' has a length of {}\n"
|
||||
"Most of these games will behave unexpectedly when the path is too long,\n"
|
||||
"often resulting in random crashes. Move the game contents to a directory\n"
|
||||
"with shorter path.\n"
|
||||
"-------------------------------------------------------------------\n\n\n",
|
||||
"The path '{}'\n"
|
||||
" has a length of {}\n"
|
||||
"Most of these games may behave unexpectedly when the path is too\n"
|
||||
"long, often resulting in random crashes. Move the game contents to\n"
|
||||
"a directory with shorter path.\n"
|
||||
"-------------------------------------------------------------------\n\n",
|
||||
dll_path_s, dll_path_s.length());
|
||||
}
|
||||
if (!fileutils::file_exists(dll_path)) {
|
||||
|
||||
@@ -19,6 +19,25 @@ function trap_error_exit {
|
||||
trap trap_error_dbg DEBUG
|
||||
trap trap_error_exit EXIT
|
||||
|
||||
IGNORE_CACHE=0
|
||||
|
||||
# Parse options
|
||||
while getopts "ih" opt; do
|
||||
case $opt in
|
||||
i) IGNORE_CACHE=1 ;;
|
||||
h)
|
||||
echo "Usage: $0 [-i]"
|
||||
echo " -i: Ignore build cache"
|
||||
echo " -h: Show this help"
|
||||
exit 0
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: -$OPTARG" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# settings
|
||||
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
||||
GIT_HEAD=$(git rev-parse HEAD || echo "none")
|
||||
@@ -41,7 +60,7 @@ DIST_ENABLE=1
|
||||
DIST_FOLDER="./dist"
|
||||
DIST_NAME="spice2x-$(date +%y)-$(date +%m)-$(date +%d).zip"
|
||||
DIST_COMMENT=${DIST_NAME}$'\n'"$GIT_BRANCH - $GIT_HEAD"$'\nThank you for playing.'
|
||||
TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice"
|
||||
TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice spicetools_spice_laa"
|
||||
TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvEncodeAPI64 spicetools_stubs_nvcuvid spicetools_stubs_nvcuda spicetools_spice64"
|
||||
|
||||
# determine build type
|
||||
@@ -74,6 +93,15 @@ echo "Build Type: $BUILD_TYPE"
|
||||
echo "Cores: $CORES"
|
||||
echo ""
|
||||
|
||||
if ((IGNORE_CACHE > 0))
|
||||
then
|
||||
echo "Ignoring build cache..."
|
||||
else
|
||||
export CCACHE_DIR="$(pwd)/.ccache"
|
||||
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
export CMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
fi
|
||||
|
||||
time (
|
||||
# 32 bit
|
||||
echo "Building 32bit targets..."
|
||||
@@ -155,6 +183,7 @@ rm -rf ${OUTDIR}
|
||||
mkdir -p ${OUTDIR}
|
||||
#mkdir -p ${OUTDIR}/stubs/32
|
||||
mkdir -p ${OUTDIR}/stubs/64
|
||||
mkdir -p ${OUTDIR}/extras/largeaddressaware
|
||||
if false # ((DEBUG > 0))
|
||||
then
|
||||
# debug files
|
||||
@@ -175,6 +204,7 @@ else
|
||||
# release files
|
||||
cp ${BUILDDIR_32}/spicetools/spicecfg.exe ${OUTDIR} 2>/dev/null
|
||||
cp ${BUILDDIR_32}/spicetools/32/spice.exe ${OUTDIR} 2>/dev/null
|
||||
cp ${BUILDDIR_32}/spicetools/32/spice_laa.exe ${OUTDIR}/extras/largeaddressaware/spice.exe 2>/dev/null
|
||||
#cp ${BUILDDIR_32}/spicetools/32/kbt.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||
#cp ${BUILDDIR_32}/spicetools/32/kld.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||
cp ${BUILDDIR_64}/spicetools/64/spice64.exe ${OUTDIR} 2>/dev/null
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
docker build --pull external/docker -t spicetools/deps
|
||||
docker build --build-context gitroot=%cd%/../../.git . -t spicetools/spice --no-cache
|
||||
docker run --rm -it -v %cd%/dist:/src/src/spice2x/dist -v %cd%/bin:/src/src/spice2x/bin spicetools/spice
|
||||
docker build --build-context gitroot=%cd%/../../.git . -t spicetools/spice
|
||||
docker run --rm -it -v %cd%/dist:/src/src/spice2x/dist -v %cd%/bin:/src/src/spice2x/bin -v %cd%/.ccache:/src/src/spice2x/.ccache spicetools/spice %*
|
||||
@REM to generate PDBs, set DEBUG to 1 in build_all.sh, place cv2pdb in external\cv2pdb, and run below
|
||||
@REM external\cv2pdb\cv2pdb.exe bin\spice2x\spicecfg.exe bin\spice2x\spicecfg-pdb.exe bin\spice2x\spicecfg-pdb.pdb
|
||||
@REM external\cv2pdb\cv2pdb.exe bin\spice2x\spice.exe bin\spice2x\spice-pdb.exe bin\spice2x\spice-pdb.pdb
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
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 run --rm -v $PWD/dist:/src/src/spice2x/dist -v $PWD/bin:/src/src/spice2x/bin spicetools/spice
|
||||
docker build --build-context gitroot=$PWD/../../.git . -t spicetools/spice:latest
|
||||
docker run --rm -v $PWD/dist:/src/src/spice2x/dist -v $PWD/bin:/src/src/spice2x/bin -v $PWD/.ccache:/src/src/spice2x/.ccache spicetools/spice "$@"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
del /s /q .ccache
|
||||
call build_docker.bat
|
||||
@@ -15,12 +15,18 @@ namespace cfg {
|
||||
std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
|
||||
|
||||
ScreenResize::ScreenResize() {
|
||||
bool file_exists = false;
|
||||
if (SCREEN_RESIZE_CFG_PATH_OVERRIDE.has_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 {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -29,12 +35,6 @@ namespace cfg {
|
||||
}
|
||||
|
||||
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);
|
||||
if (config.empty()) {
|
||||
log_info("ScreenResize", "config is empty");
|
||||
@@ -170,8 +170,6 @@ namespace cfg {
|
||||
}
|
||||
|
||||
void ScreenResize::config_save() {
|
||||
log_info("ScreenResize", "saving config: {}", this->config_path.string());
|
||||
|
||||
rapidjson::Document doc;
|
||||
std::string config = fileutils::text_read(this->config_path);
|
||||
if (!config.empty()) {
|
||||
@@ -221,10 +219,10 @@ namespace cfg {
|
||||
doc.Accept(writer);
|
||||
|
||||
// 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;
|
||||
} else {
|
||||
log_warning("ScreenResize", "unable to save config file to {}", this->config_path.string());
|
||||
log_warning("ScreenResize", "unable to save config file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
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
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ RUN pacman --noconfirm -Syu git \
|
||||
mingw-w64-winpthreads \
|
||||
mingw-w64-gcc \
|
||||
mingw-w64-headers \
|
||||
mingw-w64-binutils
|
||||
mingw-w64-binutils \
|
||||
ccache
|
||||
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-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)
|
||||
|
||||
set(HASH_LIBRARY_HEADERS
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
project(minhook)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace games::iidx {
|
||||
static IIDXLocalCamera *front_camera = nullptr; // camera id #1
|
||||
std::vector<IIDXLocalCamera*> LOCAL_CAMERA_LIST = {};
|
||||
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 parse_cmd_params() {
|
||||
@@ -493,7 +493,8 @@ namespace games::iidx {
|
||||
}
|
||||
|
||||
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 {
|
||||
// read config file
|
||||
@@ -651,9 +652,9 @@ namespace games::iidx {
|
||||
doc.Accept(writer);
|
||||
|
||||
// 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 {
|
||||
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;
|
||||
|
||||
@@ -1118,6 +1118,8 @@ int main_implementation(int argc, char *argv[]) {
|
||||
// log
|
||||
#ifdef SPICE64
|
||||
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
|
||||
#elif SPICE32_LARGE_ADDRESS_AWARE
|
||||
log_info("launcher", "SpiceTools Bootstrap (x32) (Large Address Aware) (spice2x)");
|
||||
#else
|
||||
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)");
|
||||
#endif
|
||||
@@ -1170,13 +1172,17 @@ int main_implementation(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
// // SDVXFullscreenLandscape disabled due to it messing with in-game camera angle
|
||||
// // FullscreenOrientationFlip continues to live on, however.
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
@@ -1800,6 +1806,9 @@ int main_implementation(int argc, char *argv[]) {
|
||||
exit(spicecfg_run(sextet_devices));
|
||||
}
|
||||
|
||||
// complain loudly & early about dll load ordering issue
|
||||
libutils::check_duplicate_dlls();
|
||||
|
||||
// print cpu features
|
||||
if (!cfg::CONFIGURATOR_STANDALONE && dump_sysinfo) {
|
||||
cpuutils::print_cpu_features();
|
||||
|
||||
@@ -228,7 +228,8 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.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",
|
||||
"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)"
|
||||
},
|
||||
@@ -1087,7 +1088,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.title = "Screen Resize Config Path",
|
||||
.name = "resizecfgpath",
|
||||
.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,
|
||||
.category = "Paths",
|
||||
},
|
||||
@@ -1096,7 +1097,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.title = "Patch Manager Config Path",
|
||||
.name = "patchcfgpath",
|
||||
.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,
|
||||
.category = "Paths",
|
||||
},
|
||||
@@ -2049,15 +2050,17 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
},
|
||||
{
|
||||
// SDVXFullscreenLandscape
|
||||
.title = "SDVX Landscape Mode (SDVX5+)",
|
||||
.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"
|
||||
.category = "Game Options",
|
||||
},
|
||||
{
|
||||
// spice2x_EnableSMXStage
|
||||
|
||||
@@ -29,8 +29,11 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -434,8 +437,6 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
void CardManager::config_load() {
|
||||
log_info("cardmanager", "loading config");
|
||||
|
||||
// clear cards
|
||||
this->cards.clear();
|
||||
|
||||
@@ -566,10 +567,10 @@ namespace overlay::windows {
|
||||
doc.Accept(writer);
|
||||
|
||||
// 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;
|
||||
} else {
|
||||
log_warning("cardmanager", "unable to save config file to {}", this->config_path.string());
|
||||
log_warning("cardmanager", "unable to save config file");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,8 @@ namespace overlay::windows {
|
||||
this->config_path = PATCH_MANAGER_CFG_PATH_OVERRIDE.value();
|
||||
log_info("patchmanager", "using custom config file path: {}", this->config_path.string().c_str());
|
||||
} 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) {
|
||||
@@ -1127,7 +1128,7 @@ namespace overlay::windows {
|
||||
doc.Accept(writer);
|
||||
|
||||
// save to file
|
||||
if (fileutils::text_write(config_path, buffer.GetString())) {
|
||||
if (fileutils::write_config_file("patchmanager", config_path, buffer.GetString())) {
|
||||
config_dirty = false;
|
||||
} else {
|
||||
log_warning("patchmanager", "unable to save config file");
|
||||
|
||||
@@ -494,7 +494,7 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
||||
// get string index
|
||||
ULONG string_index = 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) {
|
||||
string_index = button_caps.NotRange.StringIndex;
|
||||
|
||||
@@ -264,3 +264,53 @@ std::vector<uint8_t> *fileutils::bin_read(const std::filesystem::path &path) {
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::filesystem::path fileutils::get_config_file_path(const std::string module, const std::string filename, bool* file_exists) {
|
||||
// try %appdata%\spice2x path first, if it exists
|
||||
const auto appdata_spice2x = std::filesystem::path(_wgetenv(L"APPDATA")) / "spice2x" / filename;
|
||||
if (fileutils::file_exists(appdata_spice2x)) {
|
||||
log_info(module, "loading config from %appdata%\\spice2x\\{}", filename);
|
||||
if (file_exists) {
|
||||
*file_exists = true;
|
||||
}
|
||||
return appdata_spice2x;
|
||||
}
|
||||
|
||||
// fallback to older %appdata% path (older spice2x or mainline spicetools), if it exists
|
||||
const auto appdata = std::filesystem::path(_wgetenv(L"APPDATA")) / filename;
|
||||
if (fileutils::file_exists(appdata)) {
|
||||
log_info(module, "loading config from %appdata%\\{}", filename);
|
||||
if (file_exists) {
|
||||
*file_exists = true;
|
||||
}
|
||||
return appdata;
|
||||
}
|
||||
|
||||
// prefer new path if no existing file found
|
||||
if (file_exists) {
|
||||
*file_exists = false;
|
||||
}
|
||||
return appdata_spice2x;
|
||||
}
|
||||
|
||||
bool fileutils::write_config_file(const std::string_view &module, const std::filesystem::path path, std::string text) {
|
||||
// attempt to undo %appdata% expansion to hide user name
|
||||
const auto appdata = std::filesystem::path(_wgetenv(L"APPDATA")).string();
|
||||
auto censored = path.string();
|
||||
const auto substr_offset = censored.find(appdata);
|
||||
if (substr_offset != std::string::npos) {
|
||||
censored.replace(substr_offset, appdata.length(), "%appdata%");
|
||||
}
|
||||
|
||||
// create directory path up to where the config file lives
|
||||
if (!path.parent_path().empty() && !std::filesystem::exists(path.parent_path())) {
|
||||
log_misc(module, "creating directory path to config file: {}", censored);
|
||||
if (!fileutils::dir_create_recursive(path.parent_path())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// save file
|
||||
log_info(module, "saving config file: {}", censored);
|
||||
return fileutils::text_write(path, text);
|
||||
}
|
||||
@@ -33,4 +33,7 @@ namespace fileutils {
|
||||
std::string text_read(const std::filesystem::path &file_path);
|
||||
bool bin_write(const std::filesystem::path &path, uint8_t *data, size_t len);
|
||||
std::vector<uint8_t> *bin_read(const std::filesystem::path &path);
|
||||
|
||||
std::filesystem::path get_config_file_path(const std::string module, const std::string filename, bool* file_exists=nullptr);
|
||||
bool write_config_file(const std::string_view &module, const std::filesystem::path path, std::string text);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "logging.h"
|
||||
#include "utils.h"
|
||||
#include "peb.h"
|
||||
#include "util/fileutils.h"
|
||||
|
||||
std::filesystem::path libutils::module_file_name(HMODULE module) {
|
||||
std::wstring buf;
|
||||
@@ -323,3 +324,35 @@ intptr_t libutils::offset2rva(const std::filesystem::path &path, intptr_t offset
|
||||
|
||||
return rva;
|
||||
}
|
||||
|
||||
void libutils::check_duplicate_dlls() {
|
||||
const auto &spice_bin_path = libutils::module_file_name(nullptr).parent_path();
|
||||
if (MODULE_PATH == spice_bin_path) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &file : std::filesystem::directory_iterator(MODULE_PATH)) {
|
||||
const auto &filename = file.path().filename();
|
||||
const auto extension = strtolower(filename.extension().string());
|
||||
|
||||
if (extension == ".dll" &&
|
||||
fileutils::file_exists(spice_bin_path / filename)) {
|
||||
log_warning(
|
||||
"libutils",
|
||||
"DLL CONFLICT WARNING\n\n\n"
|
||||
"-------------------------------------------------------------------\n"
|
||||
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
||||
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||
"{} exists in BOTH of these directories:\n\n"
|
||||
" 1. {}\n"
|
||||
" 2. {}\n\n"
|
||||
"due to Windows DLL load order rules, #1 will load instead of #2.\n"
|
||||
"this has unintended consequences and may crash your game!\n"
|
||||
"resolve the conflict by deleting the stale copy of the DLL\n"
|
||||
"-------------------------------------------------------------------\n\n\n",
|
||||
filename.string(),
|
||||
(spice_bin_path / filename).string(),
|
||||
(MODULE_PATH / filename).string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,8 @@ namespace libutils {
|
||||
return try_library(module_name.c_str());
|
||||
}
|
||||
|
||||
void check_duplicate_dlls();
|
||||
|
||||
// get module handle helpers
|
||||
HMODULE get_module(const char *module_name);
|
||||
HMODULE try_module(const char *module_name);
|
||||
|
||||
Reference in New Issue
Block a user