Compare commits

...

10 Commits

Author SHA1 Message Date
bicarus-dev 537252440e signal: show Windows popup window on crash (#410)
## Link to GitHub Issue, if one exists
#345 

## Description of change
Show a MessageBox when signal detects a crash.

## Testing
Tested full screen and windowed games.
2025-10-31 20:54:56 -07:00
sp2xdev 13a0877d38 fix up deferred messages formatting 2025-10-28 16:49:14 -07:00
bicarus-dev 50691b79f1 troubleshooter: add cases for audio hook and dx9on12 (#408)
## Link to GitHub Issue, if one exists
#345

## Description of change
Add auto-troubleshooter messages for when audio hooks are disabled, and
when 9on12 is turned on by user.

## Testing
Manual verification
2025-10-28 16:29:49 -07:00
bicarus-dev ad229dabdb update build script (#407)
## Link to GitHub Issue, if one exists
n/a

## Description of change
Create a "full" version of the archive with api and extra binaries. The
normal archive remains in place with just src and stubs.
2025-10-27 23:00:32 -07:00
bicarus-dev bdff33a420 overlay: fix font loading (#406)
## Link to GitHub Issue, if one exists
n/a

## Description of change
Fix font loading - when the code was refactored in #286 I used the wrong
file extension for couple of them.
2025-10-20 00:53:28 -07:00
bicarus-dev 4b21821aa4 Introduce builds for Linux, split archive into release and extras (#405)
## Link to GitHub Issue, if one exists
n/a

## Description of change
Add a "Linux" variant of spicecfg/spice/spice64.exe - currently these
are the same as Windows binaries but built without dependency on
WinSCard, which makes it easier to run on WINE.

Split dist archive into two, move api and extras into the new extras
zip.

## Testing
I only checked to see that Linux variants run fine on Windows, and
checked with dumpbin to confirm that the dependency on winscard DLL is
removed. No official support will be provided for Linux builds.
2025-10-16 16:19:10 -07:00
bicarus-dev 6b47b5db50 iidx: set CONNECT_CAMERA env var even when iidx module is not enabled (#404)
## Link to GitHub Issue, if one exists
Fixes #403 

## Description of change
Set CONNECT_CAMERA env var even when iidx module is not enabled, so that
camhook can work without -iidx being set with real IO

## Testing
tested with emulated i/o and real i/o by user (see linked issue)
2025-10-15 13:50:12 -07:00
kazakhstan-sila a10ca5236b add option to remove winscard dependency (#400)
## Link to GitHub Issue, if one exists
n/a

## Description of change
Add CMake option to disable SCard functionality. Needed by some builds
of WINE, where distributor opted to not enable scard functionality for
whatever reason

## Testing
Building with `cmake -DWITH_SCARD=OFF` does not link against winscard
Building without this option at all links against winscard
2025-10-13 14:13:51 -07:00
bicarus-dev be2dab9a1a Image duplication for screen resize (#401)
## Link to GitHub Issue, if one exists
#399 

## Description of change
Add image duplication option to screen resize, allowing overflow images
to wrap around the other side.

## Testing
Tested with DDR, IIDX (windowed and full screen TDJ), SDVX (orientation
swap)
2025-10-12 20:34:45 -07:00
AllanCat 02711cdee1 Fixed an issue where ext (release_code) wasn't detected and replaced correctly when using user specified bootstrap.xml path. (#398)
## Link to GitHub Issue, if one exists
#0

## Description of change
The original launcher::detect_bootstrap_release_code() wasn't detecting
user specified bootstrap.xml path, and was causing issues for
patch_manager and other ext check spots prior to ea3 init (as ea3 does
proper path check itself).
I've added the user path check and proper xml parsing from
detect_gameversion().

## Testing
Tested with prop/bootstrap.xml presents.
Tested with prop/bootstrap.xml not presents and -b
/path/to/bootstrap.xml
2025-10-10 21:35:34 -07:00
19 changed files with 311 additions and 58 deletions
+65 -9
View File
@@ -357,12 +357,12 @@ set(SOURCE_FILES ${SOURCE_FILES}
external/cardio/cardio_runner.cpp external/cardio/cardio_runner.cpp
# external misc # external misc
external/scard/scard.cpp
external/stackwalker/stackwalker.cpp external/stackwalker/stackwalker.cpp
external/tinyxml2/tinyxml2.cpp external/tinyxml2/tinyxml2.cpp
external/http-parser/http_parser.c external/http-parser/http_parser.c
external/usbhidusage/usb-hid-usage.c external/usbhidusage/usb-hid-usage.c
external/toojpeg/toojpeg.cpp external/toojpeg/toojpeg.cpp
external/scard/scard.cpp
# games # games
games/game.cpp games/game.cpp
@@ -622,8 +622,9 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOUR
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES}) add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES})
target_link_libraries(spicetools_spice target_link_libraries(spicetools_spice
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
target_link_libraries(spicetools_spice PUBLIC winscard)
set_target_properties(spicetools_spice PROPERTIES PREFIX "") set_target_properties(spicetools_spice PROPERTIES PREFIX "")
set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice") set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice")
@@ -637,8 +638,9 @@ endif()
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES}) add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES})
target_link_libraries(spicetools_spice_laa target_link_libraries(spicetools_spice_laa
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
target_link_libraries(spicetools_spice_laa PUBLIC winscard)
set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "") set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "")
set_target_properties(spicetools_spice_laa PROPERTIES OUTPUT_NAME "spice_laa") set_target_properties(spicetools_spice_laa PROPERTIES OUTPUT_NAME "spice_laa")
target_compile_definitions(spicetools_spice_laa PRIVATE SPICE32_LARGE_ADDRESS_AWARE=1) target_compile_definitions(spicetools_spice_laa PRIVATE SPICE32_LARGE_ADDRESS_AWARE=1)
@@ -647,6 +649,22 @@ IF(NOT MSVC)
set_target_properties(spicetools_spice_laa PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32 -Wl,--large-address-aware") set_target_properties(spicetools_spice_laa PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32 -Wl,--large-address-aware")
endif() endif()
# spice_linux.exe
###########
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice_linux ${SOURCE_FILES} ${RESOURCE_FILES})
target_link_libraries(spicetools_spice_linux
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
set_target_properties(spicetools_spice_linux PROPERTIES PREFIX "")
set_target_properties(spicetools_spice_linux PROPERTIES OUTPUT_NAME "spice_linux")
target_compile_definitions(spicetools_spice_linux PRIVATE NO_SCARD=1 PRIVATE SPICE_LINUX=1)
IF(NOT MSVC)
set_target_properties(spicetools_spice_linux PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
endif()
# spice64.exe # spice64.exe
############# #############
@@ -655,9 +673,9 @@ add_executable(spicetools_spice64 ${SOURCE_FILES} ${RESOURCE_FILES})
# do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break # do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break
target_link_libraries(spicetools_spice64 target_link_libraries(spicetools_spice64
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp mfuuid strmiids dxva2 PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp mfuuid strmiids dxva2
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
target_link_libraries(spicetools_spice64 PUBLIC winscard)
set_target_properties(spicetools_spice64 PROPERTIES PREFIX "") set_target_properties(spicetools_spice64 PROPERTIES PREFIX "")
set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64") set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64")
target_compile_definitions(spicetools_spice64 PRIVATE SPICE64=1) target_compile_definitions(spicetools_spice64 PRIVATE SPICE64=1)
@@ -666,6 +684,25 @@ 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()
# spice64_linux.exe
#############
set(RESOURCE_FILES build/manifest.manifest build/manifest64.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice64_linux ${SOURCE_FILES} ${RESOURCE_FILES})
# do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break
target_link_libraries(spicetools_spice64_linux
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp mfuuid strmiids dxva2
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
set_target_properties(spicetools_spice64_linux PROPERTIES PREFIX "")
set_target_properties(spicetools_spice64_linux PROPERTIES OUTPUT_NAME "spice64_linux")
target_compile_definitions(spicetools_spice64_linux PRIVATE SPICE64=1)
target_compile_definitions(spicetools_spice64_linux PRIVATE NO_SCARD=1 PRIVATE SPICE_LINUX=1)
IF(NOT MSVC)
set_target_properties(spicetools_spice64_linux PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
endif()
# spicecfg.exe # spicecfg.exe
############## ##############
@@ -673,8 +710,9 @@ set(SOURCE_FILES ${SOURCE_FILES} launcher/options.h launcher/options.cpp)
set(RESOURCE_FILES cfg/manifest.manifest cfg/manifest.rc cfg/icon.rc cfg/Win32D.rc) set(RESOURCE_FILES cfg/manifest.manifest cfg/manifest.rc cfg/icon.rc cfg/Win32D.rc)
add_executable(spicetools_cfg WIN32 ${SOURCE_FILES} ${RESOURCE_FILES}) add_executable(spicetools_cfg WIN32 ${SOURCE_FILES} ${RESOURCE_FILES})
target_link_libraries(spicetools_cfg target_link_libraries(spicetools_cfg
PUBLIC ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp strmiids PUBLIC ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp strmiids
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features) PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
target_link_libraries(spicetools_cfg PUBLIC winscard)
set_target_properties(spicetools_cfg PROPERTIES PREFIX "") set_target_properties(spicetools_cfg PROPERTIES PREFIX "")
set_target_properties(spicetools_cfg PROPERTIES OUTPUT_NAME "spicecfg") set_target_properties(spicetools_cfg PROPERTIES OUTPUT_NAME "spicecfg")
target_compile_definitions(spicetools_cfg PRIVATE SPICETOOLS_SPICECFG_STANDALONE=1) target_compile_definitions(spicetools_cfg PRIVATE SPICETOOLS_SPICECFG_STANDALONE=1)
@@ -683,6 +721,24 @@ if(NOT MSVC)
set_target_properties(spicetools_cfg PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32") set_target_properties(spicetools_cfg PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
endif() endif()
# spicecfg_linux.exe
##############
set(SOURCE_FILES ${SOURCE_FILES} launcher/options.h launcher/options.cpp)
set(RESOURCE_FILES cfg/manifest.manifest cfg/manifest.rc cfg/icon.rc cfg/Win32D.rc)
add_executable(spicetools_cfg_linux WIN32 ${SOURCE_FILES} ${RESOURCE_FILES})
target_link_libraries(spicetools_cfg_linux
PUBLIC ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp strmiids
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
set_target_properties(spicetools_cfg_linux PROPERTIES PREFIX "")
set_target_properties(spicetools_cfg_linux PROPERTIES OUTPUT_NAME "spicecfg_linux")
target_compile_definitions(spicetools_cfg_linux PRIVATE SPICETOOLS_SPICECFG_STANDALONE=1)
target_compile_definitions(spicetools_cfg_linux PRIVATE NO_SCARD=1 PRIVATE SPICE_LINUX=1)
if(NOT MSVC)
set_target_properties(spicetools_cfg_linux PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
endif()
# stubs # stubs
####### #######
@@ -776,19 +832,19 @@ endif()
#################### ####################
# output config # output config
set_target_properties(spicetools_cfg set_target_properties(spicetools_cfg spicetools_cfg_linux
PROPERTIES PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools") RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools")
# output 32bit # output 32bit
set_target_properties(spicetools_spice spicetools_spice_laa spicetools_stubs_kbt spicetools_stubs_kld spicetools_stubs_cpusbxpkm set_target_properties(spicetools_spice spicetools_spice_laa spicetools_spice_linux 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"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32") RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32")
# output 64bit # output 64bit
set_target_properties(spicetools_spice64 spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvcuda spicetools_stubs_nvcuvid spicetools_stubs_nvEncodeAPI64 set_target_properties(spicetools_spice64 spicetools_spice64_linux spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvcuda spicetools_stubs_nvcuvid spicetools_stubs_nvEncodeAPI64
PROPERTIES PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive64" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive64"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/64" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/64"
+21 -8
View File
@@ -49,6 +49,7 @@ BUILDDIR_64_RELEASE="./cmake-build-release-64"
BUILDDIR_64_DEBUG="./cmake-build-debug-64" BUILDDIR_64_DEBUG="./cmake-build-debug-64"
DEBUG=0 DEBUG=0
OUTDIR="./bin/spice2x" OUTDIR="./bin/spice2x"
OUTDIR_EXTRAS="./bin/spice2x/extras"
# disabled UPX since it tends to falsely trigger malware detection # disabled UPX since it tends to falsely trigger malware detection
UPX_ENABLE=0 UPX_ENABLE=0
@@ -59,9 +60,10 @@ INCLUDE_SRC=1
DIST_ENABLE=1 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_NAME_EXTRAS="spice2x-$(date +%y)-$(date +%m)-$(date +%d)-full.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 spicetools_spice_laa spicetools_stubs_cpusbxpkm" TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_cfg_linux spicetools_spice spicetools_spice_laa spicetools_spice_linux 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 spicetools_spice64_linux"
# determine build type # determine build type
BUILD_TYPE="Release" BUILD_TYPE="Release"
@@ -179,11 +181,17 @@ fi
# copy to output directory # copy to output directory
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
rm -rf ${OUTDIR_EXTRAS}
mkdir -p ${OUTDIR_EXTRAS}
mkdir -p ${OUTDIR_EXTRAS}/largeaddressaware
mkdir -p ${OUTDIR_EXTRAS}/linux
if false # ((DEBUG > 0)) if false # ((DEBUG > 0))
then then
# debug files # debug files
@@ -204,11 +212,14 @@ then
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/spicecfg_linux.exe ${OUTDIR_EXTRAS}/linux/spicecfg.exe 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/spice_laa.exe ${OUTDIR_EXTRAS}/largeaddressaware/spice.exe 2>/dev/null
cp ${BUILDDIR_32}/spicetools/32/spice_linux.exe ${OUTDIR_EXTRAS}/linux/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
cp ${BUILDDIR_64}/spicetools/64/spice64_linux.exe ${OUTDIR_EXTRAS}/linux/spice64.exe 2>/dev/null
#cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null #cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null
#cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null #cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null
cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null
@@ -228,10 +239,10 @@ then
fi fi
# copy resources # copy resources
rm -rf ${OUTDIR}/api rm -rf ${OUTDIR_EXTRAS}/api
mkdir ${OUTDIR}/api mkdir ${OUTDIR_EXTRAS}/api
find ./api/resources/python -name "__pycache__" -exec rm -rf {} + find ./api/resources/python -name "__pycache__" -exec rm -rf {} +
cp -r ./api/resources/* ${OUTDIR}/api cp -r ./api/resources/* ${OUTDIR_EXTRAS}/api
# build distribution archive # build distribution archive
if ((DIST_ENABLE > 0)) if ((DIST_ENABLE > 0))
@@ -240,7 +251,9 @@ then
mkdir -p ${DIST_FOLDER} mkdir -p ${DIST_FOLDER}
rm -rf ${DIST_FOLDER}/${DIST_NAME} rm -rf ${DIST_FOLDER}/${DIST_NAME}
pushd ${OUTDIR}/.. > /dev/null pushd ${OUTDIR}/.. > /dev/null
zip -qrXT9 $OLDPWD/${DIST_FOLDER}/${DIST_NAME} . -z <<< "$DIST_COMMENT" zip -qrXT9 $OLDPWD/${DIST_FOLDER}/${DIST_NAME} spice2x -x "spice2x/extras/*" -z <<< "$DIST_COMMENT"
echo "Building extras..."
zip -qrXT9 $OLDPWD/${DIST_FOLDER}/${DIST_NAME_EXTRAS} spice2x -z <<< "$DIST_COMMENT"
popd > /dev/null popd > /dev/null
fi fi
+5
View File
@@ -87,6 +87,10 @@ namespace cfg {
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);
int duplicate = 0;
load_int_value(doc, root + prefix + "duplicate", duplicate);
scene.duplicate = static_cast<cfg::ScreenDuplicateMode>(duplicate);
} }
// windowed settings are always under game settings // windowed settings are always under game settings
@@ -201,6 +205,7 @@ namespace cfg {
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 + "duplicate").Set(doc, scene.duplicate);
} }
// windowed mode settings // windowed mode settings
+7
View File
@@ -14,12 +14,19 @@ namespace cfg {
ResizableFrame = 2 ResizableFrame = 2
}; };
enum ScreenDuplicateMode {
None = 0,
CopyLeft = 1,
CopyRight = 2,
};
struct fullscreen_setting { struct fullscreen_setting {
int offset_x = 0; int offset_x = 0;
int offset_y = 0; int offset_y = 0;
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;
ScreenDuplicateMode duplicate = ScreenDuplicateMode::None;
}; };
extern std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE; extern std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
+3
View File
@@ -23,6 +23,7 @@
* Modified version. * Modified version.
*/ */
#ifndef NO_SCARD
#include "scard.h" #include "scard.h"
#include <windows.h> #include <windows.h>
@@ -409,3 +410,5 @@ void scard_threadstart() {
void scard_fini() { void scard_fini() {
should_exit = true; should_exit = true;
} }
#endif
-12
View File
@@ -405,14 +405,6 @@ namespace games::iidx {
// init cfgmgr32 hooks // init cfgmgr32 hooks
cfgmgr32hook_init(avs::game::DLL_INSTANCE); cfgmgr32hook_init(avs::game::DLL_INSTANCE);
// report common errors on iidx31 and above
if (avs::game::is_ext(2023091500, MAXINT) && GRAPHICS_9_ON_12_STATE == DX9ON12_FORCE_ON) {
deferredlogs::defer_error_messages({
"common incompatibility with DX 9on12 + IIDX 31 and above",
" IIDX31+ is known to be incompatible with DX 9on12, leading to blank screen or crashes"
});
}
} }
void IIDXGame::pre_attach() { void IIDXGame::pre_attach() {
@@ -420,10 +412,6 @@ namespace games::iidx {
// environment variables must be set before the DLL is loaded as the VC++ runtime copies all // environment variables must be set before the DLL is loaded as the VC++ runtime copies all
// environment variables at startup // environment variables at startup
if (DISABLE_CAMS) {
SetEnvironmentVariable("CONNECT_CAMERA", "0");
}
if (SCREEN_MODE.has_value()) { if (SCREEN_MODE.has_value()) {
SetEnvironmentVariable("SCREEN_MODE", SCREEN_MODE.value().c_str()); SetEnvironmentVariable("SCREEN_MODE", SCREEN_MODE.value().c_str());
} }
@@ -238,14 +238,17 @@ static void log_create_device_failure(HRESULT hresult) {
} }
static bool is_dx9_on_12_enabled() { static bool is_dx9_on_12_enabled() {
bool result = false;
switch (GRAPHICS_9_ON_12_STATE) { switch (GRAPHICS_9_ON_12_STATE) {
case DX9ON12_FORCE_OFF: case DX9ON12_FORCE_OFF:
log_info("graphics::d3d9", "DirectX 9on12: forced OFF by user (-dx9on12)"); log_info("graphics::d3d9", "DirectX 9on12: forced OFF by user (-dx9on12)");
return false; result = false;
break;
case DX9ON12_FORCE_ON: case DX9ON12_FORCE_ON:
log_info("graphics::d3d9", "DirectX 9on12: forced ON by user (-9on12 or -dx9on12)"); log_info("graphics::d3d9", "DirectX 9on12: forced ON by user (-9on12 or -dx9on12)");
return true; result = true;
break;
case DX9ON12_AUTO: case DX9ON12_AUTO:
default: default:
@@ -253,14 +256,33 @@ static bool is_dx9_on_12_enabled() {
log_info( log_info(
"graphics::d3d9", "graphics::d3d9",
"DirectX 9on12: enabled automatically for current game (tip: use -dx9on12 to force on or off)"); "DirectX 9on12: enabled automatically for current game (tip: use -dx9on12 to force on or off)");
return true; result = true;
} else { } else {
log_info( log_info(
"graphics::d3d9", "graphics::d3d9",
"DirectX 9on12: disabled by default, using DX9 (tip: use -dx9on12 to force on or off)"); "DirectX 9on12: disabled by default, using DX9 (tip: use -dx9on12 to force on or off)");
return false; result = false;
} }
break;
} }
if (GRAPHICS_9_ON_12_STATE == DX9ON12_FORCE_ON) {
if (avs::game::is_model("LDJ") && avs::game::is_ext(2023091500, MAXINT)) {
deferredlogs::defer_error_messages({
"dx9on12 was force enabled by user (-dx9on12)",
" IIDX31+ is known to be incompatible with DX 9on12, leading to blank screen or crashes",
" try again with -dx9on12 option set to default value"
});
} else {
deferredlogs::defer_error_messages({
"dx9on12 was force enabled by user (-dx9on12)",
" not very game is compatible with this, and can lead to crashes",
" try without force enabling this if you are seeing issues"
});
}
}
return result;
} }
static IDirect3D9 *WINAPI Direct3DCreate9_hook(UINT SDKVersion) { static IDirect3D9 *WINAPI Direct3DCreate9_hook(UINT SDKVersion) {
@@ -733,6 +733,16 @@ void SurfaceHook(IDirect3DDevice9 *pReal) {
const int rectTop = param.BackBufferHeight; 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;
if (cfg::SCREENRESIZE->enable_screen_resize) {
RECT rect {
0,
0,
(LONG)topSurface_width,
(LONG)topSurface_height,
};
pReal->ColorFill(topSurface, &rect, D3DCOLOR_XRGB(0, 0, 0));
}
D3DLOCKED_RECT rect; D3DLOCKED_RECT rect;
HRESULT hr; HRESULT hr;
@@ -750,6 +760,7 @@ void SurfaceHook(IDirect3DDevice9 *pReal) {
(LONG)(rectLeft + w), (LONG)(rectLeft + w),
(LONG)(rectTop + h), (LONG)(rectTop + h),
}; };
if (GRAPHICS_FS_ORIENTATION_SWAP) { if (GRAPHICS_FS_ORIENTATION_SWAP) {
originRect.left = (topSurface_width / 2) - (GRAPHICS_FS_ORIGINAL_WIDTH / 2); originRect.left = (topSurface_width / 2) - (GRAPHICS_FS_ORIGINAL_WIDTH / 2);
originRect.top = (topSurface_height / 2) - (GRAPHICS_FS_ORIGINAL_HEIGHT / 2); originRect.top = (topSurface_height / 2) - (GRAPHICS_FS_ORIGINAL_HEIGHT / 2);
@@ -757,6 +768,21 @@ void SurfaceHook(IDirect3DDevice9 *pReal) {
originRect.bottom = originRect.top + GRAPHICS_FS_ORIGINAL_HEIGHT; originRect.bottom = originRect.top + GRAPHICS_FS_ORIGINAL_HEIGHT;
} }
bool duplicate = false;
RECT originRect2 = originRect;
if (cfg::SCREENRESIZE->enable_screen_resize) {
auto& scene = cfg::SCREENRESIZE->scene_settings[cfg::SCREENRESIZE->screen_resize_current_scene];
if (scene.duplicate == cfg::ScreenDuplicateMode::CopyLeft) {
duplicate = true;
originRect2.right = originRect.left;
originRect2.left = (LONG)(originRect2.left - (originRect.right - originRect.left));
} else if (scene.duplicate == cfg::ScreenDuplicateMode::CopyRight) {
duplicate = true;
originRect2.left = originRect.right;
originRect2.right = (LONG)(originRect2.left + (originRect.right - originRect.left));
}
}
// log_misc( // log_misc(
// "graphics::d3d9", "originRect: {} {} {} {}", // "graphics::d3d9", "originRect: {} {} {} {}",
// originRect.left, originRect.top, originRect.right, originRect.bottom); // originRect.left, originRect.top, originRect.right, originRect.bottom);
@@ -768,9 +794,21 @@ void SurfaceHook(IDirect3DDevice9 *pReal) {
if (hr != D3D_OK) { if (hr != D3D_OK) {
log_warning( log_warning(
"graphics::d3d9", "graphics::d3d9",
"SurfaceHook - StretchRect backbuffer failed, rect: {} {} {} {}", "SurfaceHook - StretchRect backbuffer failed for main image, rect: {} {} {} {}",
originRect.left, originRect.top, originRect.right, originRect.bottom); originRect.left, originRect.top, originRect.right, originRect.bottom);
} }
if (duplicate) {
hr = pReal->StretchRect(
backbuffer, nullptr,
topSurface, &originRect2,
D3DTEXF_LINEAR);
if (hr != D3D_OK) {
log_warning(
"graphics::d3d9",
"SurfaceHook - StretchRect backbuffer failed for the duplicate, rect: {} {} {} {}",
originRect2.left, originRect2.top, originRect2.right, originRect2.bottom);
}
}
topSurface->UnlockRect(); topSurface->UnlockRect();
// phase 2 - viewport calculation - do the actual zoom / offset math // phase 2 - viewport calculation - do the actual zoom / offset math
+34 -6
View File
@@ -20,7 +20,9 @@
#include "cfg/screen_resize.h" #include "cfg/screen_resize.h"
#include "easrv/easrv.h" #include "easrv/easrv.h"
#include "external/cardio/cardio_runner.h" #include "external/cardio/cardio_runner.h"
#ifndef NO_SCARD
#include "external/scard/scard.h" #include "external/scard/scard.h"
#endif
#include "games/game.h" #include "games/game.h"
#include "games/io.h" #include "games/io.h"
#include "games/bbc/bbc.h" #include "games/bbc/bbc.h"
@@ -263,7 +265,8 @@ int main_implementation(int argc, char *argv[]) {
// detect model used to load option overrides // detect model used to load option overrides
auto options_version = launcher::detect_gameversion( auto options_version = launcher::detect_gameversion(
LAUNCHER_OPTIONS->at(launcher::Options::PathToEa3Config).value LAUNCHER_OPTIONS->at(launcher::Options::PathToEa3Config).value,
LAUNCHER_OPTIONS->at(launcher::Options::PathToBootstrap).value
); );
if (!options_version.model.empty() && options_version.model.size() < 4) { if (!options_version.model.empty() && options_version.model.size() < 4) {
if (options_version.dest.size() == 1) { if (options_version.dest.size() == 1) {
@@ -479,6 +482,9 @@ int main_implementation(int argc, char *argv[]) {
// Disable legacy behaviour to avoid conflict // Disable legacy behaviour to avoid conflict
games::iidx::DISABLE_CAMS = true; games::iidx::DISABLE_CAMS = true;
} }
if (games::iidx::DISABLE_CAMS) {
SetEnvironmentVariable("CONNECT_CAMERA", "0");
}
if (options[launcher::Options::IIDXCamHookOverride].is_active()) { if (options[launcher::Options::IIDXCamHookOverride].is_active()) {
games::iidx::TDJ_CAMERA_OVERRIDE = options[launcher::Options::IIDXCamHookOverride].value_text(); games::iidx::TDJ_CAMERA_OVERRIDE = options[launcher::Options::IIDXCamHookOverride].value_text();
} }
@@ -816,6 +822,7 @@ int main_implementation(int argc, char *argv[]) {
for (auto &sextet : options[launcher::Options::SextetStreamPort].values_text()) { for (auto &sextet : options[launcher::Options::SextetStreamPort].values_text()) {
sextet_devices.emplace_back(sextet); sextet_devices.emplace_back(sextet);
} }
#ifndef NO_SCARD
if (options[launcher::Options::HIDSmartCard].value_bool()) { if (options[launcher::Options::HIDSmartCard].value_bool()) {
WINSCARD_CONFIG.cardinfo_callback = eamuse_scard_callback; WINSCARD_CONFIG.cardinfo_callback = eamuse_scard_callback;
scard_threadstart(); scard_threadstart();
@@ -835,6 +842,7 @@ int main_implementation(int argc, char *argv[]) {
WINSCARD_CONFIG.add_padding_to_felica = true; WINSCARD_CONFIG.add_padding_to_felica = true;
} }
} }
#endif
if (options[launcher::Options::CardIOHIDReaderOrderFlip].value_bool()) { if (options[launcher::Options::CardIOHIDReaderOrderFlip].value_bool()) {
CARDIO_RUNNER_FLIP = true; CARDIO_RUNNER_FLIP = true;
} }
@@ -938,6 +946,11 @@ int main_implementation(int argc, char *argv[]) {
} }
if (options[launcher::Options::DisableAudioHooks].value_bool()) { if (options[launcher::Options::DisableAudioHooks].value_bool()) {
hooks::audio::ENABLED = false; hooks::audio::ENABLED = false;
deferredlogs::defer_error_messages({
"audio hooks are forcibly disabled by user (-audiohookdisable)",
" having hooks disabled means some required audio fixes are not being applied",
" if you have audio-related crashes, you should try again after clearing this option"
});
} }
if (options[launcher::Options::spice2x_DisableVolumeHook].value_bool()) { if (options[launcher::Options::spice2x_DisableVolumeHook].value_bool()) {
hooks::audio::VOLUME_HOOK_ENABLED = false; hooks::audio::VOLUME_HOOK_ENABLED = false;
@@ -1200,15 +1213,28 @@ int main_implementation(int argc, char *argv[]) {
} }
// log // log
#ifdef SPICE64 #ifndef SPICE_LINUX
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)"); #ifdef SPICE64
#elif SPICE32_LARGE_ADDRESS_AWARE log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
log_info("launcher", "SpiceTools Bootstrap (x32) (Large Address Aware) (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
#else #else
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)"); #ifdef SPICE64
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x) for Linux");
#else
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x) for Linux");
#endif
#endif #endif
log_info("launcher", "{}", VERSION_STRING); log_info("launcher", "{}", VERSION_STRING);
// note: distribution of modified version of this software without providing source is GPLv3 license violation.
log_info("launcher", "spice2x is free & open source; if you paid money for it, you got scammed");
log_info("launcher", "visit https://spice2x.github.io to download the latest version for free");
// log command line arguments // log command line arguments
std::ostringstream arguments; std::ostringstream arguments;
for (auto &root_option : options) { for (auto &root_option : options) {
@@ -2314,8 +2340,10 @@ int main_implementation(int argc, char *argv[]) {
// debug hook // debug hook
debughook::detach(); debughook::detach();
#ifndef NO_SCARD
// scard // scard
scard_fini(); scard_fini();
#endif
// stop reader thread in case it was running // stop reader thread in case it was running
stop_reader_thread(); stop_reader_thread();
+34 -10
View File
@@ -6,6 +6,12 @@
#include <fstream> #include <fstream>
#ifdef NO_SCARD
#define WITH_SCARD 0
#else
#define WITH_SCARD 1
#endif
static const std::vector<std::string> CATEGORY_ORDER_API = { static const std::vector<std::string> CATEGORY_ORDER_API = {
"SpiceCompanion and API", "SpiceCompanion and API",
"API (Serial)", "API (Serial)",
@@ -1385,21 +1391,27 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.name = "scard", .name = "scard",
.desc = "Detects and uses HID smart card readers for card input. Developed for ACR122U reader", .desc = "Detects and uses HID smart card readers for card input. Developed for ACR122U reader",
.type = OptionType::Bool, .type = OptionType::Bool,
.hidden = !WITH_SCARD,
.category = "NFC Card Readers", .category = "NFC Card Readers",
.disabled = !WITH_SCARD,
}, },
{ {
.title = "HID SmartCard Order Flip", .title = "HID SmartCard Order Flip",
.name = "scardflip", .name = "scardflip",
.desc = "Flips the order of detection for P1/P2", .desc = "Flips the order of detection for P1/P2",
.type = OptionType::Bool, .type = OptionType::Bool,
.hidden = !WITH_SCARD,
.category = "NFC Card Readers", .category = "NFC Card Readers",
.disabled = !WITH_SCARD,
}, },
{ {
.title = "HID SmartCard Order Toggle", .title = "HID SmartCard Order Toggle",
.name = "scardtoggle", .name = "scardtoggle",
.desc = "Toggles reader between P1/P2 using the NumLock key state", .desc = "Toggles reader between P1/P2 using the NumLock key state",
.type = OptionType::Bool, .type = OptionType::Bool,
.hidden = !WITH_SCARD,
.category = "NFC Card Readers", .category = "NFC Card Readers",
.disabled = !WITH_SCARD,
}, },
{ {
// HIDSmartCardIdConvert // HIDSmartCardIdConvert
@@ -1413,12 +1425,14 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
"For example, abcd56780123 is converted to e00401abcd567801 on card in. This results in different card numbers so " "For example, abcd56780123 is converted to e00401abcd567801 on card in. This results in different card numbers so "
"be careful when connecting to servers!", "be careful when connecting to servers!",
.type = OptionType::Enum, .type = OptionType::Enum,
.hidden = !WITH_SCARD,
.category = "NFC Card Readers", .category = "NFC Card Readers",
.elements = { .elements = {
{"legacy", "Use cards as-is"}, {"legacy", "Use cards as-is"},
{"fix", "Fix bad cards only"}, {"fix", "Fix bad cards only"},
{"all", "Force all cards"}, {"all", "Force all cards"},
}, },
.disabled = !WITH_SCARD,
}, },
{ {
// SextetStreamPort // SextetStreamPort
@@ -2608,8 +2622,19 @@ std::vector<Option> launcher::merge_options(
return merged; return merged;
} }
std::string launcher::detect_bootstrap_release_code() { std::string launcher::detect_bootstrap_release_code(const std::string& bootstrap_user) {
std::string bootstrap_path = "prop/bootstrap.xml"; std::string bootstrap_path;
if (!bootstrap_user.empty()) {
bootstrap_path = bootstrap_user;
} else if (fileutils::file_exists("prop/bootstrap.xml")) {
bootstrap_path = "prop/bootstrap.xml";
}
if (bootstrap_path.empty()) {
log_warning("options", "unable to detect bootstrap.xml file");
return "";
}
// load XML // load XML
tinyxml2::XMLDocument bootstrap; tinyxml2::XMLDocument bootstrap;
@@ -2632,7 +2657,7 @@ std::string launcher::detect_bootstrap_release_code() {
return ""; return "";
} }
static launcher::GameVersion detect_gameversion_ident() { static launcher::GameVersion detect_gameversion_ident(const std::string& bootstrap_user) {
// detect ea3-ident path // detect ea3-ident path
std::string ident_path; std::string ident_path;
@@ -2678,7 +2703,7 @@ static launcher::GameVersion detect_gameversion_ident() {
auto node_ext = node_soft->FirstChildElement("ext"); auto node_ext = node_soft->FirstChildElement("ext");
if (node_ext) { if (node_ext) {
version.ext = node_ext->GetText(); version.ext = node_ext->GetText();
auto bootstrap_ext = launcher::detect_bootstrap_release_code(); auto bootstrap_ext = launcher::detect_bootstrap_release_code(bootstrap_user);
if (version.ext.size() != 10 && bootstrap_ext.size() == 10) { if (version.ext.size() != 10 && bootstrap_ext.size() == 10) {
version.ext = bootstrap_ext; version.ext = bootstrap_ext;
} else if (bootstrap_ext.size() == 10) { } else if (bootstrap_ext.size() == 10) {
@@ -2714,8 +2739,7 @@ static launcher::GameVersion detect_gameversion_ident() {
return launcher::GameVersion(); return launcher::GameVersion();
} }
launcher::GameVersion launcher::detect_gameversion(const std::string &ea3_user) { launcher::GameVersion launcher::detect_gameversion(const std::string &ea3_user, const std::string& bootstrap_user) {
// detect ea3-config path // detect ea3-config path
std::string ea3_path; std::string ea3_path;
if (!ea3_user.empty()) { if (!ea3_user.empty()) {
@@ -2729,7 +2753,7 @@ launcher::GameVersion launcher::detect_gameversion(const std::string &ea3_user)
} }
if (ea3_path.empty()) { if (ea3_path.empty()) {
log_warning("options", "unable to detect EA3 configuration file"); log_warning("options", "unable to detect EA3 configuration file");
return detect_gameversion_ident(); return detect_gameversion_ident(bootstrap_user);
} }
// load XML // load XML
@@ -2769,7 +2793,7 @@ launcher::GameVersion launcher::detect_gameversion(const std::string &ea3_user)
if (ea3_config.Parse(xml_str.c_str()) != tinyxml2::XML_SUCCESS) { if (ea3_config.Parse(xml_str.c_str()) != tinyxml2::XML_SUCCESS) {
// if we still failed, give up // if we still failed, give up
log_warning("options", "unable to parse fixed xml"); log_warning("options", "unable to parse fixed xml");
return detect_gameversion_ident(); return detect_gameversion_ident(bootstrap_user);
} }
} }
@@ -2800,7 +2824,7 @@ launcher::GameVersion launcher::detect_gameversion(const std::string &ea3_user)
auto node_ext = node_soft->FirstChildElement("ext"); auto node_ext = node_soft->FirstChildElement("ext");
if (node_ext) { if (node_ext) {
version.ext = node_ext->GetText(); version.ext = node_ext->GetText();
auto bootstrap_ext = launcher::detect_bootstrap_release_code(); auto bootstrap_ext = launcher::detect_bootstrap_release_code(bootstrap_user);
if (version.ext.size() != 10 && bootstrap_ext.size() == 10) { if (version.ext.size() != 10 && bootstrap_ext.size() == 10) {
version.ext = bootstrap_ext; version.ext = bootstrap_ext;
} else if (bootstrap_ext.size() == 10) { } else if (bootstrap_ext.size() == 10) {
@@ -2833,5 +2857,5 @@ launcher::GameVersion launcher::detect_gameversion(const std::string &ea3_user)
// error // error
log_warning("options", "unable to find /ea3/soft/model in {}", ea3_path); log_warning("options", "unable to find /ea3/soft/model in {}", ea3_path);
return detect_gameversion_ident(); return detect_gameversion_ident(bootstrap_user);
} }
+2 -2
View File
@@ -279,6 +279,6 @@ namespace launcher {
std::string ext; std::string ext;
}; };
std::string detect_bootstrap_release_code(); std::string detect_bootstrap_release_code(const std::string& bootstrap_user);
GameVersion detect_gameversion(const std::string& ea3_user); GameVersion detect_gameversion(const std::string& ea3_user, const std::string& bootstrap_user);
} }
+13
View File
@@ -1,5 +1,6 @@
#include "signal.h" #include "signal.h"
#include <future>
#include <exception> #include <exception>
#include <windows.h> #include <windows.h>
@@ -174,6 +175,18 @@ static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *Exception
log_warning("signal", "minidump creation function not available, skipping"); log_warning("signal", "minidump creation function not available, skipping");
} }
// reduce sleep time since we will wait for the user to acknowledge the popup
LOG_FATAL_SLEEP = 1;
// in 30 seconds, shut down (in case user can't dismiss popup)
const auto f = std::async(std::launch::async, [] {
std::this_thread::sleep_for(std::chrono::seconds(30));
log_fatal("signal", "end");
});
// this will stall all UI threads for this process
deferredlogs::show_popup_for_crash();
log_fatal("signal", "end"); log_fatal("signal", "end");
} }
+4 -3
View File
@@ -270,13 +270,14 @@ void overlay::SpiceOverlay::init() {
ImFontConfig config {}; ImFontConfig config {};
config.MergeMode = true; config.MergeMode = true;
log_misc("overlay", "loading fonts, failures are not fatal");
add_font("simsun.ttc", &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); add_font("simsun.ttc", &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
add_font("arial.ttc", &config, io.Fonts->GetGlyphRangesCyrillic()); add_font("arial.ttf", &config, io.Fonts->GetGlyphRangesCyrillic());
add_font("meiryu.ttc", &config, io.Fonts->GetGlyphRangesJapanese()); add_font("meiryu.ttc", &config, io.Fonts->GetGlyphRangesJapanese());
add_font("meiryo.ttc", &config, io.Fonts->GetGlyphRangesJapanese()); add_font("meiryo.ttc", &config, io.Fonts->GetGlyphRangesJapanese());
add_font("gulim.ttc", &config, io.Fonts->GetGlyphRangesKorean()); add_font("gulim.ttc", &config, io.Fonts->GetGlyphRangesKorean());
add_font("cordia.ttc", &config, io.Fonts->GetGlyphRangesThai()); add_font("cordia.ttf", &config, io.Fonts->GetGlyphRangesThai());
add_font("arial.ttc", &config, io.Fonts->GetGlyphRangesVietnamese()); add_font("arial.ttf", &config, io.Fonts->GetGlyphRangesVietnamese());
// add special font // add special font
if (avs::game::is_model("LDJ")) { if (avs::game::is_model("LDJ")) {
+19 -2
View File
@@ -556,9 +556,16 @@ namespace overlay::windows {
} }
// disclaimer // disclaimer
// note: distribution of modified version of this software without providing source is GPLv3 license violation.
ImGui::TextColored( ImGui::TextColored(
ImVec4(1, 0.5f, 0.5f, 1.f), ImVec4(1, 0.5f, 0.5f, 1.f),
"Do NOT stream or upload game data anywhere public! Support arcades when you can. Thanks."); "spice2x is free & open source; if you paid money for it, you got scammed.");
if (cfg::CONFIGURATOR_STANDALONE) {
ImGui::SameLine();
if (ImGui::TextLink(PROJECT_URL)) {
launch_shell(PROJECT_URL);
}
}
} }
void Config::build_buttons(const std::string &name, std::vector<Button> *buttons, int min, int max) { void Config::build_buttons(const std::string &name, std::vector<Button> *buttons, int min, int max) {
@@ -2904,13 +2911,20 @@ namespace overlay::windows {
} }
void Config::build_about() { void Config::build_about() {
#ifndef SPICE_LINUX
ImGui::TextUnformatted(std::string( ImGui::TextUnformatted(std::string(
"spice2x (a fork of SpiceTools)\r\n" "spice2x (a fork of SpiceTools)\r\n"
"=========================\r\n" + "=========================\r\n" +
to_string(VERSION_STRING)).c_str()); to_string(VERSION_STRING)).c_str());
#else
ImGui::TextUnformatted(std::string(
"spice2x (a fork of SpiceTools) for Linux\r\n"
"=========================\r\n" +
to_string(VERSION_STRING)).c_str());
#endif
ImGui::TextUnformatted(""); ImGui::TextUnformatted("");
if (ImGui::Button(PROJECT_URL)) { if (ImGui::TextLink(PROJECT_URL)) {
launch_shell(PROJECT_URL); launch_shell(PROJECT_URL);
} }
@@ -2971,6 +2985,7 @@ namespace overlay::windows {
void Config::build_menu(int *game_selected) { void Config::build_menu(int *game_selected) {
bool about_popup = false; bool about_popup = false;
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 1.0f));
if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenuBar()) {
// [spice2x] // [spice2x]
@@ -3031,6 +3046,8 @@ namespace overlay::windows {
ImGui::EndMenuBar(); ImGui::EndMenuBar();
} }
ImGui::PopStyleColor(); // ImGuiCol_PopupBg
// workaround for popups triggered by menu, see https://github.com/ocornut/imgui/issues/331 // workaround for popups triggered by menu, see https://github.com/ocornut/imgui/issues/331
if (about_popup) { if (about_popup) {
ImGui::OpenPopup("About##topbarpopup"); ImGui::OpenPopup("About##topbarpopup");
@@ -55,6 +55,7 @@ namespace overlay::windows {
scene.offset_y = 0; scene.offset_y = 0;
scene.scale_x = 1.f; scene.scale_x = 1.f;
scene.scale_y = 1.f; scene.scale_y = 1.f;
scene.duplicate = cfg::ScreenDuplicateMode::None;
} }
cfg::SCREENRESIZE->enable_window_resize = false; cfg::SCREENRESIZE->enable_window_resize = false;
@@ -149,6 +150,17 @@ namespace overlay::windows {
ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value."); ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value.");
} }
static const char* dupe_items[] = { "None", "Copy Left", "Copy Right" };
ImGui::Combo(
"Duplicate",
reinterpret_cast<int *>(&scene.duplicate),
dupe_items,
ARRAYSIZE(dupe_items));
ImGui::SameLine();
ImGui::HelpMarker(
"Show an identical copy of the image on the left or right, allowing you to achieve "
"wrap-around effect when an offset is set.");
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
+21
View File
@@ -72,4 +72,25 @@ namespace deferredlogs {
log_warning("troubleshooter", "{}", msg); log_warning("troubleshooter", "{}", msg);
}); });
} }
void show_popup_for_crash() {
static std::once_flag shown;
std::call_once(shown, []() {
const std::string title = "spice2x (" + to_string(VERSION_STRING_CFG) + ") - crash handler";
std::string text;
text += "Game has crashed.\n\n";
text += "Check log.txt and look for error messages near the end of file.\n\n";
text += "Unsure what to do next?\n";
text += " * update spice2x to the latest version\n";
text += " * check the FAQ on spice2x wiki on github\n";
text += " * do NOT screenshot this, instead, share log.txt with someone and ask for help\n\n";
text += "Press Enter, Esc, Alt+F4, or click OK to exit. Otherwise, game will close in 30 seconds.";
MessageBox(
nullptr,
text.c_str(),
title.c_str(),
MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
});
}
} }
+1
View File
@@ -11,4 +11,5 @@ namespace deferredlogs {
void defer_error_messages(std::initializer_list<std::string> messages); void defer_error_messages(std::initializer_list<std::string> messages);
void dump_to_logger(bool is_crash=false); void dump_to_logger(bool is_crash=false);
void show_popup_for_crash();
} }
+2
View File
@@ -1,5 +1,7 @@
#include "logging.h" #include "logging.h"
DWORD LOG_FATAL_SLEEP = 10000;
std::string_view log_get_datetime() { std::string_view log_get_datetime() {
return log_get_datetime(time(nullptr)); return log_get_datetime(time(nullptr));
} }
+3 -1
View File
@@ -71,6 +71,8 @@ struct fmt::formatter<fmt_hresult> {
} }
}; };
extern DWORD LOG_FATAL_SLEEP;
// misc log // misc log
#define LOG_FORMAT(level, module, fmt_str, ...) fmt::format(FMT_COMPILE("{}" fmt_str "\n"), \ #define LOG_FORMAT(level, module, fmt_str, ...) fmt::format(FMT_COMPILE("{}" fmt_str "\n"), \
fmt_log { std::time(nullptr), level, module }, ## __VA_ARGS__) fmt_log { std::time(nullptr), level, module }, ## __VA_ARGS__)
@@ -84,7 +86,7 @@ struct fmt::formatter<fmt_hresult> {
logger::push(LOG_FORMAT("F", module, format_str, ## __VA_ARGS__), logger::Style::RED); \ logger::push(LOG_FORMAT("F", module, format_str, ## __VA_ARGS__), logger::Style::RED); \
logger::push(LOG_FORMAT("F", "spice", "encountered a fatal error, you can close the window or press ctrl + c"), logger::Style::RED); \ logger::push(LOG_FORMAT("F", "spice", "encountered a fatal error, you can close the window or press ctrl + c"), logger::Style::RED); \
launcher::stop_subsystems(); \ launcher::stop_subsystems(); \
Sleep(10000); \ Sleep(LOG_FATAL_SLEEP); \
launcher::kill(); \ launcher::kill(); \
std::terminate(); \ std::terminate(); \
} ((void) 0 ) } ((void) 0 )