mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 88ec6dbcee | |||
| 1b614c94a7 | |||
| 37c5913f69 | |||
| 2eca668593 | |||
| aec1da9d16 | |||
| 548b441f1f | |||
| 98bc285d98 | |||
| 553c180bee | |||
| 537252440e | |||
| 13a0877d38 | |||
| 50691b79f1 | |||
| ad229dabdb | |||
| bdff33a420 | |||
| 4b21821aa4 | |||
| 6b47b5db50 | |||
| a10ca5236b | |||
| be2dab9a1a | |||
| 02711cdee1 | |||
| c6b10402f4 | |||
| 58ea6ce17e | |||
| 8cc00c371a | |||
| 8e2985d8d0 | |||
| 8d3b15641f | |||
| 033e9f926a | |||
| da58503b47 | |||
| cffee2b7f8 | |||
| 32801319fa | |||
| afbe013811 | |||
| 862e4717f6 | |||
| d3fa27ae4a | |||
| b487cf2bcf | |||
| 0fc3aa5818 | |||
| 276874f882 | |||
| 1fdd270480 | |||
| 07cb6048a0 | |||
| 61d79f76b2 |
@@ -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
|
||||||
@@ -610,6 +610,8 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
util/lz77.cpp
|
util/lz77.cpp
|
||||||
util/tapeled.cpp
|
util/tapeled.cpp
|
||||||
util/execexe.cpp
|
util/execexe.cpp
|
||||||
|
util/dependencies.cpp
|
||||||
|
util/deferlog.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES})
|
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES})
|
||||||
@@ -620,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")
|
||||||
|
|
||||||
@@ -635,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)
|
||||||
@@ -645,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
|
||||||
#############
|
#############
|
||||||
|
|
||||||
@@ -653,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)
|
||||||
@@ -664,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
|
||||||
##############
|
##############
|
||||||
|
|
||||||
@@ -671,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)
|
||||||
@@ -681,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
|
||||||
#######
|
#######
|
||||||
|
|
||||||
@@ -774,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"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "external/robin_hood.h"
|
#include "external/robin_hood.h"
|
||||||
#include "launcher/logger.h"
|
#include "launcher/logger.h"
|
||||||
#include "launcher/signal.h"
|
#include "launcher/signal.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
@@ -1502,7 +1503,8 @@ namespace avs {
|
|||||||
" * Do NOT copy over random DLLs from another game installation; DLL must match game version\n"
|
" * Do NOT copy over random DLLs from another game installation; DLL must match game version\n"
|
||||||
"\n"
|
"\n"
|
||||||
, DLL_NAME, MODULE_PATH.string()) };
|
, DLL_NAME, MODULE_PATH.string()) };
|
||||||
log_fatal("avs-ea3", "{}", info_str);
|
log_warning("avs-ea3", "{}", info_str);
|
||||||
|
log_fatal("avs-ea3", "Failed to find critical avs DLL on disk (avs2-core.dll OR {})", DLL_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1739,8 +1741,12 @@ namespace avs {
|
|||||||
|
|
||||||
static void avs_dir_err(const std::filesystem::path &src_path)
|
static void avs_dir_err(const std::filesystem::path &src_path)
|
||||||
{
|
{
|
||||||
launcher::signal::AVS_DIR_CREATION_FAILURE = TRUE;
|
deferredlogs::defer_error_messages({
|
||||||
launcher::signal::AVS_SRC_PATH = src_path.string();
|
"AVS filesystem initialization failure was previously detected during boot!",
|
||||||
|
fmt::format(" ERROR: directory could not be created: {}", src_path.string().c_str()),
|
||||||
|
fmt::format(" if you see a crash, it may have been caused by bad <mounttable> contents in {}", avs::core::CFG_PATH.c_str()),
|
||||||
|
" fix the XML file and try again"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_avs_dir(
|
static void create_avs_dir(
|
||||||
@@ -1934,6 +1940,7 @@ namespace avs {
|
|||||||
static const char *LOG_LEVELS[] = { "disable", "fatal", "warning", "info", "misc", "all" };
|
static const char *LOG_LEVELS[] = { "disable", "fatal", "warning", "info", "misc", "all" };
|
||||||
char current_log_level_buffer[32] { 0 };
|
char current_log_level_buffer[32] { 0 };
|
||||||
uint32_t current_log_level = 0;
|
uint32_t current_log_level = 0;
|
||||||
|
std::string log_level_as_str;
|
||||||
|
|
||||||
if (VERSION == AVSLEGACY || VERSION == AVS21360) {
|
if (VERSION == AVSLEGACY || VERSION == AVS21360) {
|
||||||
auto level_node = property_search(config, config_node, "/log/level");
|
auto level_node = property_search(config, config_node, "/log/level");
|
||||||
@@ -1949,6 +1956,7 @@ namespace avs {
|
|||||||
{
|
{
|
||||||
if (current_log_level < std::size(LOG_LEVELS)) {
|
if (current_log_level < std::size(LOG_LEVELS)) {
|
||||||
log_info("avs-core", "log level: {}", LOG_LEVELS[current_log_level]);
|
log_info("avs-core", "log level: {}", LOG_LEVELS[current_log_level]);
|
||||||
|
log_level_as_str = LOG_LEVELS[current_log_level];
|
||||||
} else {
|
} else {
|
||||||
log_fatal("avs-core", "log level ({}) is invalid!", current_log_level);
|
log_fatal("avs-core", "log level ({}) is invalid!", current_log_level);
|
||||||
}
|
}
|
||||||
@@ -1968,7 +1976,7 @@ namespace avs {
|
|||||||
level_node = property_node_create(config, config_node, NODE_TYPE_str, "/log/level",
|
level_node = property_node_create(config, config_node, NODE_TYPE_str, "/log/level",
|
||||||
LOG_LEVELS[current_log_level]);
|
LOG_LEVELS[current_log_level]);
|
||||||
} else {
|
} else {
|
||||||
log_fatal("avs-core", "log level ({}) is invalid!", current_log_level);
|
log_fatal("avs-core", "log level ({}) is invalid! *", current_log_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1981,12 +1989,27 @@ namespace avs {
|
|||||||
if (property_node_refer(config, config_node, "/log/level",
|
if (property_node_refer(config, config_node, "/log/level",
|
||||||
NODE_TYPE_str, current_log_level_buffer, sizeof(current_log_level_buffer)) > 0)
|
NODE_TYPE_str, current_log_level_buffer, sizeof(current_log_level_buffer)) > 0)
|
||||||
{
|
{
|
||||||
log_info("avs-core", "log level: {}", current_log_level_buffer);
|
log_info("avs-core", "log level: {} *", current_log_level_buffer);
|
||||||
|
log_level_as_str = current_log_level_buffer;
|
||||||
} else {
|
} else {
|
||||||
log_warning("avs-core", "log level: unknown");
|
log_warning("avs-core", "log level: unknown *");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (log_level_as_str == "disable" ||
|
||||||
|
log_level_as_str == "fatal" ||
|
||||||
|
log_level_as_str == "warning" ||
|
||||||
|
log_level_as_str == "info") {
|
||||||
|
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
fmt::format(
|
||||||
|
"log level is set to `{}` (either in avs-config.xml or using -loglevel)", log_level_as_str),
|
||||||
|
" this log file may have omitted important error messages from the game",
|
||||||
|
" if you are troubleshooting crashes or failures, it is recommended that you",
|
||||||
|
" set AVS Log Level (-loglevel) option to `all`",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// fix time offset
|
// fix time offset
|
||||||
auto t_now = std::time(nullptr);
|
auto t_now = std::time(nullptr);
|
||||||
auto tm_now = *std::gmtime(&t_now);
|
auto tm_now = *std::gmtime(&t_now);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ namespace avs {
|
|||||||
int HTTP11 = -1;
|
int HTTP11 = -1;
|
||||||
int URL_SLASH = -1;
|
int URL_SLASH = -1;
|
||||||
int PCB_TYPE = -1;
|
int PCB_TYPE = -1;
|
||||||
|
bool EA3_DEBUG_VERBOSE = false;
|
||||||
|
|
||||||
// handle
|
// handle
|
||||||
std::string VERSION_STR = "unknown";
|
std::string VERSION_STR = "unknown";
|
||||||
@@ -149,7 +150,9 @@ namespace avs {
|
|||||||
" * Do NOT copy over random DLLs from another game installation; DLL must match game version\n"
|
" * Do NOT copy over random DLLs from another game installation; DLL must match game version\n"
|
||||||
"\n"
|
"\n"
|
||||||
, DLL_NAME, MODULE_PATH.string()) };
|
, DLL_NAME, MODULE_PATH.string()) };
|
||||||
log_fatal("avs-ea3", "{}", info_str);
|
|
||||||
|
log_warning("avs-ea3", "{}", info_str);
|
||||||
|
log_fatal("avs-ea3", "Failed to find critical ea3 DLL on disk (avs2-ea3.dll OR {})", DLL_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,6 +415,11 @@ namespace avs {
|
|||||||
log_fatal("avs-ea3", "no PCBID set (try using -p to specify PCBID)");
|
log_fatal("avs-ea3", "no PCBID set (try using -p to specify PCBID)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove <debug> since it can expose pcbid in logged requests
|
||||||
|
if (!EA3_DEBUG_VERBOSE) {
|
||||||
|
avs::core::property_search_remove_safe(ea3_config, nullptr, "/ea3/debug/verbose");
|
||||||
|
}
|
||||||
|
|
||||||
// remember IDs
|
// remember IDs
|
||||||
char pcbid_buffer[256] { 0 };
|
char pcbid_buffer[256] { 0 };
|
||||||
char accountid_buffer[256] { 0 };
|
char accountid_buffer[256] { 0 };
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace avs {
|
|||||||
extern int HTTP11;
|
extern int HTTP11;
|
||||||
extern int URL_SLASH;
|
extern int URL_SLASH;
|
||||||
extern int PCB_TYPE;
|
extern int PCB_TYPE;
|
||||||
|
extern bool EA3_DEBUG_VERBOSE;
|
||||||
|
|
||||||
// handle
|
// handle
|
||||||
extern std::string VERSION_STR;
|
extern std::string VERSION_STR;
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ namespace avs {
|
|||||||
|
|
||||||
// ddr gamemdx.dll user error
|
// ddr gamemdx.dll user error
|
||||||
if (avs::game::is_model("MDX") && DLL_NAME == "gamemdx.dll") {
|
if (avs::game::is_model("MDX") && DLL_NAME == "gamemdx.dll") {
|
||||||
log_fatal(
|
log_warning(
|
||||||
"ddr",
|
"ddr",
|
||||||
"BAD GAME DLL ERROR\n\n"
|
"BAD GAME DLL ERROR\n\n"
|
||||||
"!!! !!!\n"
|
"!!! !!!\n"
|
||||||
@@ -107,6 +107,7 @@ namespace avs {
|
|||||||
"!!! remove -exec argument and try again. !!!\n"
|
"!!! remove -exec argument and try again. !!!\n"
|
||||||
"!!! !!!\n"
|
"!!! !!!\n"
|
||||||
);
|
);
|
||||||
|
log_fatal("ddr", "BAD GAME DLL ERROR (don't use -exec gamemdx.dll, that's the wrong DLL)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// file not found on disk
|
// file not found on disk
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#define IDC_STATIC -1
|
#define IDC_STATIC -1
|
||||||
#define IDD_DIALOG1 129
|
#define IDD_DIALOG1 129
|
||||||
#define IDR_CHANGELOG 130
|
|
||||||
#define IDR_LICENSES 131
|
#define IDR_LICENSES 131
|
||||||
#define IDR_PATCHES 132
|
#define IDR_PATCHES 132
|
||||||
#define IDR_README 133
|
#define IDR_README 133
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
del /s /q .ccache
|
del /s /q .ccache
|
||||||
|
del /s /q dist
|
||||||
call build_docker.bat
|
call build_docker.bat
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
IDR_CHANGELOG RCDATA "../changelog.txt"
|
|
||||||
IDR_LICENSES RCDATA "../licenses.txt"
|
IDR_LICENSES RCDATA "../licenses.txt"
|
||||||
IDR_PATCHES RCDATA "../build/patches.json"
|
IDR_PATCHES RCDATA "../build/patches.json"
|
||||||
IDR_README RCDATA "../readme.txt"
|
IDR_README RCDATA "../readme.txt"
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IDR_CHANGELOG 130
|
|
||||||
#define IDR_LICENSES 131
|
#define IDR_LICENSES 131
|
||||||
#define IDR_PATCHES 132
|
#define IDR_PATCHES 132
|
||||||
#define IDR_README 133
|
#define IDR_README 133
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -1,764 +0,0 @@
|
|||||||
09/28/2025 [spice2x]
|
|
||||||
IIDX: auto apply ASIO compatibility fix for IIDX32+
|
|
||||||
Misc diagnosability updates
|
|
||||||
|
|
||||||
09/22/2025 [spice2x]
|
|
||||||
Add Polaris Chord lights
|
|
||||||
Add boot.dll to Gitadora patches target
|
|
||||||
Misc fixes
|
|
||||||
|
|
||||||
09/20/2025 [spice2x]
|
|
||||||
Polaris Chord support for knobs/turntables/mouse as fader input
|
|
||||||
Misc fixes
|
|
||||||
|
|
||||||
09/18/2025 [spice2x]
|
|
||||||
Polaris Chord windowed mode fixes
|
|
||||||
UI tweaks
|
|
||||||
|
|
||||||
09/17/2025 [spice2x]
|
|
||||||
Polaris Chord I/O fixes, language shim
|
|
||||||
|
|
||||||
09/16/2025 [spice2x]
|
|
||||||
Add Polaris Chord support
|
|
||||||
Tweak ImGUI theme
|
|
||||||
|
|
||||||
08/21/2025 [spice2x]
|
|
||||||
DDR: check for common DLL errors
|
|
||||||
Supply default PCBID if absent
|
|
||||||
Rearrange options
|
|
||||||
|
|
||||||
08/17/2025 [spice2x]
|
|
||||||
DDR: fix codec registration failure when path contains spaces
|
|
||||||
|
|
||||||
08/11/2025 [spice2x]
|
|
||||||
SDVX: fix camera hook, remove -sdvxdisablecams
|
|
||||||
DDR: automatically register codecs in com folder on boot
|
|
||||||
|
|
||||||
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]
|
|
||||||
Add Mahjong Fight Girl support
|
|
||||||
Add option for custom full screen resolution (-forceres)
|
|
||||||
|
|
||||||
03/24/2025 [spice2x]
|
|
||||||
Auto PIN entry
|
|
||||||
Multiple scenes for image resize
|
|
||||||
API: add resize function, lights.read can now filter lights by name
|
|
||||||
Fix DLL hooks not receiving command-line arguments
|
|
||||||
|
|
||||||
03/16/2025 [spice2x]
|
|
||||||
Fix clipboard copy function truncating last character of string
|
|
||||||
|
|
||||||
03/03/2025 [spice2x]
|
|
||||||
IIDX: add workaround for REVERB EX filter missing in Windows 11 update
|
|
||||||
|
|
||||||
02/25/2025 [spice2x]
|
|
||||||
Add -vsyncbuffer option for forcing double/triple buffering
|
|
||||||
|
|
||||||
02/22/2025 [spice2x]
|
|
||||||
Add -windowscale option for resizing DX9 backbuffer dimensions
|
|
||||||
|
|
||||||
01/26/2025 [spice2x]
|
|
||||||
Expanded main menu in overlay (default bind: esc key)
|
|
||||||
Nostalgia: touch and swipe gestures (-nostpoke)
|
|
||||||
Jubeat: detect root directory boot failure
|
|
||||||
Add "Any Direction" analog type for button binding
|
|
||||||
|
|
||||||
01/16/2025 [spice2x]
|
|
||||||
More MIDI improvements:
|
|
||||||
use v2_drum algorithm instead of v2 by default for drummania & FTT
|
|
||||||
threshold setting for CC when mapped as a button (hi-hat pedals)
|
|
||||||
sustain duration applied to CC OnOff controls (sustain pedals)
|
|
||||||
Nostalgia, Beatstream: fix EA card insertion issue
|
|
||||||
CCJ, QKS: translate some windowed mode settings to Unity engine
|
|
||||||
Fix DEBUG build
|
|
||||||
|
|
||||||
01/08/2025 [spice2x]
|
|
||||||
Better MIDI support; significant improvements for drums
|
|
||||||
Fix various UI bugs in Buttons / Analog tabs
|
|
||||||
Nostalgia: fix velocity handling for MIDI input
|
|
||||||
Show camera names in camera control overlay
|
|
||||||
Game exit dialog (default: Escape key)
|
|
||||||
Button layout help text in Buttons tab
|
|
||||||
|
|
||||||
12/31/2024 [spice2x]
|
|
||||||
Fix videos not playing in Unity-based games
|
|
||||||
Dump audio device info in wrapped WASAPI handler
|
|
||||||
Update DLL load failure message
|
|
||||||
|
|
||||||
12/30/2024 [spice2x]
|
|
||||||
Busou Shinki: Show Cursor option now properly shows cursor in game
|
|
||||||
IIDX: add IIDX NVENC Quality option (-iidxreccqp)
|
|
||||||
IIDX: always enable NVENC hook, not just when -iidx is set
|
|
||||||
IIDX: add help text to keypad overlay in TDJ mode
|
|
||||||
Busou Shinki, QKS, CCJ: Only show cursor by default if no touchscreen detected
|
|
||||||
Ignore invalid HID devices with bad device path
|
|
||||||
|
|
||||||
12/13/2024 [spice2x]
|
|
||||||
Improve error messages for DLL load failures
|
|
||||||
Load cardio module in spicecfg
|
|
||||||
|
|
||||||
12/06/2024 [spice2x]
|
|
||||||
Clean up seldom used features (VR, Lua scripting, layeredfs, KFControl)
|
|
||||||
New card scanner section in Cards tab
|
|
||||||
Add -scardfix option for converting NFC cards into E00401 format
|
|
||||||
Add system information logging, controlled by -sysdump option
|
|
||||||
|
|
||||||
11/20/2024 [spice2x]
|
|
||||||
DRS: add subscreen overlay window (dance floor tape LED display)
|
|
||||||
IIDX: TDJ cam selection options for users with 3+ cameras
|
|
||||||
(-iidxtdjcamhooktop /-iidxtdjcamhookfront)
|
|
||||||
IIDX/SDVX: move some options to Advanced tab
|
|
||||||
Update -nvprofile to set V-Sync settings as Application Controlled
|
|
||||||
|
|
||||||
10/29/2024 [spice2x]
|
|
||||||
(IIDX31+) apply signature patch to force WASAPI by default; use -iidxsounddevice to override
|
|
||||||
Fix SDVX EG song search when using Japanese touch keyboard (when OS is not ja-JP)
|
|
||||||
Nostalgia I/O improvements
|
|
||||||
Expose DDR Gold cabinet tape LEDs via Spice API
|
|
||||||
|
|
||||||
10/14/2024 [spice2x]
|
|
||||||
Apply patches earlier, on DLL load notification
|
|
||||||
SMX dedicab lights improvements
|
|
||||||
|
|
||||||
10/12/2024 [spice2x]
|
|
||||||
SMX dedicab lights support (requires forked SMX.dll - see Issue #228)
|
|
||||||
Option to show FPS overlay on top left (-fpsflip)
|
|
||||||
Allow TDJ camhook to load without -iidx (for cabs)
|
|
||||||
|
|
||||||
09/21/2024 [spice2x]
|
|
||||||
Add Inject Early DLL Hooks option (-z)
|
|
||||||
|
|
||||||
09/14/2024 [spice2x]
|
|
||||||
Add Patch Manager Config Path (-patchcfgpath) option
|
|
||||||
Vertical/horizontal flip for TDJ cam hook
|
|
||||||
Fix mouse button behavior when left/right buttons are swapped
|
|
||||||
|
|
||||||
08/24/2024 [spice2x]
|
|
||||||
Fix Patch Manager failing to import patches when modules path is Unicode
|
|
||||||
|
|
||||||
08/22/2024 [spice2x]
|
|
||||||
UI update for Card Manager in overlay
|
|
||||||
|
|
||||||
08/12/2024 [spice2x]
|
|
||||||
IIDX TDJ camera - bug fixes
|
|
||||||
Prevent users from accidentally enabling -cfg and -kfcontrol in spicecfg
|
|
||||||
|
|
||||||
08/07/2024 [spice2x]
|
|
||||||
IIDX TDJ camera improvements - draw modes (stretch/crop), bug fixes
|
|
||||||
|
|
||||||
08/06/2024 [spice2x]
|
|
||||||
IIDX TDJ camera improvements
|
|
||||||
Automatic cropping for 16:9 resolutions
|
|
||||||
Toggle to keep or override camera parameters
|
|
||||||
Fix Unicode path handling for config files
|
|
||||||
|
|
||||||
08/03/2024 [spice2x]
|
|
||||||
IIDX TDJ camera improvements
|
|
||||||
Camera control overlay (check Overlay tab)
|
|
||||||
Hardware acceleration for camera rendering
|
|
||||||
IIDX TDJ play record improvements
|
|
||||||
NVENC hooks have been added to fix crash on song start; -nod3d9devhook
|
|
||||||
is no longer required
|
|
||||||
|
|
||||||
07/29/2024 [spice2x]
|
|
||||||
Fix IIDX TDJ not launching in fullscreen with two monitors
|
|
||||||
|
|
||||||
07/28/2024 [spice2x]
|
|
||||||
Add more DLL support for -iidxtdjcamhook
|
|
||||||
Add -iidxtdjcamhookratio and -iidxtdjcamhookoffset
|
|
||||||
|
|
||||||
07/25/2024 [spice2x]
|
|
||||||
Add -iidxtdjcamhook option for webcam support in TDJ
|
|
||||||
|
|
||||||
07/17/2024 [spice2x]
|
|
||||||
Disable touch feedback indicators
|
|
||||||
Bug fixes
|
|
||||||
|
|
||||||
07/15/2024 [spice2x]
|
|
||||||
Fix touch and touch emulation in wintouch-based games (Nostalgia, BeatStream...)
|
|
||||||
Fix misaligned SpiceCompanion touches on windowed TDJ subscreen
|
|
||||||
Improvements to TDJ poke feature
|
|
||||||
|
|
||||||
07/13/2024 [spice2x]
|
|
||||||
Fix windowed TDJ subscreen not accepting mouse clicks after card in
|
|
||||||
Allow windowed TDJ/UFC subscreen to minimize, but not close
|
|
||||||
|
|
||||||
07/10/2024 [spice2x]
|
|
||||||
Better gfdm XG2 and XG3 support
|
|
||||||
IIDX TDJ windowed mode rendering improvements
|
|
||||||
IIDX TDJ subscreen poke feature
|
|
||||||
CardIO NumLock toggle option
|
|
||||||
Patch manager UI tweaks
|
|
||||||
|
|
||||||
07/06/2024 [spice2x]
|
|
||||||
Reliability improvements for config file saving
|
|
||||||
Experimental and incomplete support for gfdm XG3
|
|
||||||
Option to specify path for screen resize config
|
|
||||||
Reflec Beat: fix being unable to type into overlay
|
|
||||||
|
|
||||||
07/03/2024 [spice2x]
|
|
||||||
Fix SMX stage compatibility
|
|
||||||
Patch manager: log header in patches JSON, better error handling
|
|
||||||
|
|
||||||
06/26/2024 [spice2x]
|
|
||||||
Fix MDX-003 not retrieving patches from online source
|
|
||||||
|
|
||||||
06/22/2024 [spice2x]
|
|
||||||
Reliability & performance improvements for auto-card-insert
|
|
||||||
Update -sdvxnosub to prevent creation of subscreen in windowed mode
|
|
||||||
Bug fixes
|
|
||||||
|
|
||||||
06/20/2024 [spice2x]
|
|
||||||
Improve experience for windowed SDVX UFC (always launch subscreen window)
|
|
||||||
Add Delay option in analog binds
|
|
||||||
Fix pop'n soft-lock with auto card insert
|
|
||||||
Fix -graphics-single-adapter not working in Beatstream/Nostalgia
|
|
||||||
|
|
||||||
06/14/2024 [spice2x]
|
|
||||||
Improve experience for touch-enabled games in windowed mode (SpiceTouch)
|
|
||||||
|
|
||||||
06/08/2024 [spice2x]
|
|
||||||
Patch manager bug fixes
|
|
||||||
|
|
||||||
06/03/2024 [spice2x]
|
|
||||||
Fix patch status not being saved properly
|
|
||||||
Search tab for finding options
|
|
||||||
|
|
||||||
06/02/2024 [spice2x]
|
|
||||||
Fix BBC and Museca hang on boot when COM ports are present
|
|
||||||
Deprecate -iidxtdjw (use -iidxtdj and -w together instead)
|
|
||||||
|
|
||||||
05/31/2024 [spice2x]
|
|
||||||
Redesign patches tab
|
|
||||||
Bug fixes for patches.json parsing
|
|
||||||
|
|
||||||
05/29/2024 [spice2x]
|
|
||||||
Add support for "number" patch type
|
|
||||||
History for remote patch URLs
|
|
||||||
|
|
||||||
05/28/2024 [spice2x]
|
|
||||||
Update -iidxtdjw to hide useless second window
|
|
||||||
|
|
||||||
05/27/2024 [spice2x]
|
|
||||||
Fix -apiserial crashing when -apiserialbaud is not provided
|
|
||||||
Suppress "failed to acquire subscreen" error when not relevant
|
|
||||||
|
|
||||||
05/22/2024 [spice2x]
|
|
||||||
Add caution string to patches.json format
|
|
||||||
Paste from clipboard button for URL patches import
|
|
||||||
|
|
||||||
05/12/2024 [spice2x]
|
|
||||||
Disable URL patch importing in-game
|
|
||||||
UI tweaks for importing patches
|
|
||||||
|
|
||||||
05/05/2024 [spice2x]
|
|
||||||
UI tweaks for importing patches
|
|
||||||
Add aliases for arguments with -sp2x prefix
|
|
||||||
|
|
||||||
05/04/2024 [spice2x]
|
|
||||||
New patch JSON format, importing patches from URL
|
|
||||||
Add Process Efficiency Class option for hetero CPUs
|
|
||||||
|
|
||||||
04/29/2024 [spice2x]
|
|
||||||
Move -vr to be DANCERUSH only option
|
|
||||||
Fix being unable to type into overlay when -nolegacy is on
|
|
||||||
|
|
||||||
04/08/2024 [spice2x]
|
|
||||||
Fix Discord rich presence app IDs
|
|
||||||
|
|
||||||
03/31/2024 [spice2x]
|
|
||||||
Fix IC CARD UNIT ERROR in UFC when COM ports are present
|
|
||||||
|
|
||||||
03/24/2024 [spice2x]
|
|
||||||
Fix Ongaku Paradise crash on boot due to VFS redirection
|
|
||||||
Address all compiler warnings
|
|
||||||
|
|
||||||
03/17/2024 [spice2x]
|
|
||||||
SMX pad lights output
|
|
||||||
Fix DDR pad input for P4IO / BIO2
|
|
||||||
Option aliases for IIDX/SDVX subscreen disable
|
|
||||||
|
|
||||||
03/16/2024 [spice2x]
|
|
||||||
I/O for DDR white cabinet type (P4IO)
|
|
||||||
Remove background animation from configurator
|
|
||||||
Compiler updates
|
|
||||||
|
|
||||||
03/06/2024 [spice2x]
|
|
||||||
Lights output for DDR gold cabinet type
|
|
||||||
|
|
||||||
02/13/2024 [spice2x]
|
|
||||||
Fix lights not updating over API in configurator
|
|
||||||
CCJ mouse trackball improvements
|
|
||||||
Make IIDX/SDVX native touch the default when -sp2x-nod3d9devhook is on
|
|
||||||
Remove log spam in IIDX
|
|
||||||
|
|
||||||
02/02/2024 [spice2x]
|
|
||||||
Add missing NVCUDA stubs for cuStreamCreate and cuStreamDestroy_v2
|
|
||||||
|
|
||||||
02/01/2024 [spice2x]
|
|
||||||
QuizKnock STADIUM support
|
|
||||||
Busou Shinki analog joystick support
|
|
||||||
|
|
||||||
01/30/2024 [spice2x]
|
|
||||||
Add woofer lights to popn HD mode
|
|
||||||
Prevent crash when both -graphics-force-single-adapter and
|
|
||||||
-sp2x-nod3d9devhook are enabled
|
|
||||||
|
|
||||||
01/27/2024 [spice2x]
|
|
||||||
Add Disable D3D9 Device Hook option (-sp2x-nod3d9devhook)
|
|
||||||
|
|
||||||
01/20/2024 [spice2x]
|
|
||||||
Force Exit overlay hotkey
|
|
||||||
Improve Low Latency Audio to work with more games
|
|
||||||
Charge Machine I/O fixes
|
|
||||||
UI tweaks (API tab, Development tab)
|
|
||||||
|
|
||||||
01/07/2024 [spice2x]
|
|
||||||
Chase Chase Jokers improvements (trackball and vsync fix)
|
|
||||||
|
|
||||||
01/06/2024 [spice2x]
|
|
||||||
Chase Chase Jokers improvements (cmd line args, trackball sensitivity)
|
|
||||||
|
|
||||||
01/05/2024 [spice2x]
|
|
||||||
Chase Chase Jokers support
|
|
||||||
|
|
||||||
01/01/2024 [spice2x]
|
|
||||||
UI tweaks - menu bar in configurator window
|
|
||||||
IIDX: scan for SOUND_OUTPUT_DEVICE in binary and log message
|
|
||||||
Switch from -Ofast to -O2
|
|
||||||
Remove ImGui demo and debug files from release (reduced binary size)
|
|
||||||
|
|
||||||
12/30/2023 [spice2x]
|
|
||||||
Add NVAPI Block option (-sp2x-nonvapi)
|
|
||||||
SDVX: Auto Card Insert disables itself after a timeout to prevent soft lock
|
|
||||||
|
|
||||||
12/27/2023 [spice2x]
|
|
||||||
Prevent SDVX from dumping PATH variable to log
|
|
||||||
Stubs for NVIDIA DLLs (nvcuda.dll, nvcuvid.dll, nvEncodeAPI64.dll)
|
|
||||||
UI tweaks
|
|
||||||
|
|
||||||
12/25/2023 [spice2x]
|
|
||||||
Fix Lock Cursor option not updating capture area in windowed mode
|
|
||||||
Update TDJ rom file hooks
|
|
||||||
|
|
||||||
12/23/2023 [spice2x]
|
|
||||||
Remove the need for hex edits to fix note scroll speed in SDVX VM on NVIDIA
|
|
||||||
Improvements to -graphics-force-refresh
|
|
||||||
|
|
||||||
12/22/2023 [spice2x]
|
|
||||||
HID analog relative axis mode
|
|
||||||
Automatic process affinity fix for Gitadora
|
|
||||||
Fix -cfgpath option not working
|
|
||||||
Buttons tab UI fix for Bind Many
|
|
||||||
|
|
||||||
12/18/2023 [spice2x]
|
|
||||||
Fix Road Fighters 3D I/O error on boot
|
|
||||||
|
|
||||||
12/17/2023 [spice2x]
|
|
||||||
Integer multiplier / divisor for HID analog
|
|
||||||
(alternative to existing sensitivity option)
|
|
||||||
|
|
||||||
12/15/2023 [spice2x]
|
|
||||||
Add hooks to prevent display scaling changes when SDVX launches
|
|
||||||
|
|
||||||
12/12/2023 [spice2x]
|
|
||||||
Add support for keypad in SDVX UFC/VM mode
|
|
||||||
New DX9on12 flag with more options (-sp2x-dx9on12, replaces -9on12)
|
|
||||||
|
|
||||||
12/11/2023 [spice2x]
|
|
||||||
Fix crash at launch on AMD/Intel GPUs when nvapi DLL is present
|
|
||||||
|
|
||||||
12/09/2023 [spice2x]
|
|
||||||
Lights output for Gitadora
|
|
||||||
Lights output for DRS
|
|
||||||
Tape LED averaging algorithm option (-sp2x-tapeledalgo)
|
|
||||||
Fix occasional crash on shutdown
|
|
||||||
|
|
||||||
11/23/2023 [spice2x]
|
|
||||||
Low latency shared audio option (-sp2x-lowlatencysharedaudio)
|
|
||||||
Automatic dev/raw/* folder creation for popn19-21
|
|
||||||
Move overlay bindings to Overlay tab
|
|
||||||
|
|
||||||
11/17/2023 [spice2x]
|
|
||||||
Use E00401 prefix for card number generation
|
|
||||||
Volume API hooks to prevent audio volume change (enabled by default)
|
|
||||||
Small UI tweaks
|
|
||||||
|
|
||||||
11/15/2023 [spice2x]
|
|
||||||
Automatic card insert option (-sp2x-autocard)
|
|
||||||
Dump CPU features to log on startup
|
|
||||||
|
|
||||||
11/12/2023 [spice2x]
|
|
||||||
Fix crash in some games caused by linker changes in 2022
|
|
||||||
(Gitadora Exchain and older, Bone Eater, etc)
|
|
||||||
Add IIDX native touch option (-sp2x-iidxnativetouch)
|
|
||||||
Fix V-Sync issues with auto-screen-orientation
|
|
||||||
|
|
||||||
11/04/2023 [spice2x]
|
|
||||||
Option for NVIDIA GPU optimization (-sp2x-nvprofile)
|
|
||||||
SmartCard fixes (for -scardflip and -scardtoggle)
|
|
||||||
Small reorganization of options in configurator
|
|
||||||
|
|
||||||
10/30/2023 [spice2x]
|
|
||||||
Add touch input support for DRS
|
|
||||||
Add TDJ Windowed mode for IIDX (-sp2x-iidxtdjw)
|
|
||||||
Fix -iidxasio not working in some versions of IIDX
|
|
||||||
|
|
||||||
10/22/2023 [spice2x]
|
|
||||||
Add E-spec I/O emulation for IIDX 30+
|
|
||||||
Fix IIDX TDJ launching at 60Hz for some users
|
|
||||||
Add workaround for buggy ASIO drivers that lock up on close
|
|
||||||
Hide Insert Card overlay by default, add option to show it again
|
|
||||||
|
|
||||||
09/29/2023 [spice2x]
|
|
||||||
Fix subscreen not updating in certain versions of EG.
|
|
||||||
Detect long paths and log a warning message.
|
|
||||||
|
|
||||||
06/08/2023 [spice2x]
|
|
||||||
Improved touch support for Jubeat and Reflec Beat.
|
|
||||||
|
|
||||||
04/23/2023 [spice2x]
|
|
||||||
Update -iidxsounddevice to automatically pick a value (wasapi in most cases)
|
|
||||||
|
|
||||||
04/21/2023 [spice2x]
|
|
||||||
Fix spicecfg not launching in some specific cases
|
|
||||||
|
|
||||||
04/20/2023 [spice2x]
|
|
||||||
Update font for IIDX segment display
|
|
||||||
New option: auto show FPS window
|
|
||||||
|
|
||||||
04/16/2023 [spice2x]
|
|
||||||
New feature: window resize. Added new options to change window size and
|
|
||||||
position on launch. Screen Resize window (F11) also updated with new
|
|
||||||
controls
|
|
||||||
Screen Resize settings are now per-game
|
|
||||||
Misc bug fixes
|
|
||||||
|
|
||||||
04/09/2023 [spice2x]
|
|
||||||
Add IIDX LED ticker (segment display) as subscreen overlay for LDJ
|
|
||||||
Add I/O panel window for all games, special support for IIDX, DDR, GFDM
|
|
||||||
Add options to automatically show certain windows on game launch
|
|
||||||
|
|
||||||
04/03/2023 [spice2x]
|
|
||||||
Move/resize for IIDX/SDVX subscreen overlay window
|
|
||||||
New options to control subscreen overlay window
|
|
||||||
Turn common config mistakes into fatal error messages
|
|
||||||
Various bug fixes for touch handling
|
|
||||||
Revert "pop'n launching at desktop refresh rate" hack from 03/30/2023
|
|
||||||
|
|
||||||
03/30/2023 [spice2x]
|
|
||||||
New option: IIDX Force Definition Type HD (720p)
|
|
||||||
New option: process priority
|
|
||||||
Fix pop'n launching at desktop refresh rate
|
|
||||||
Lower logger thread priority to reduce stutters
|
|
||||||
Misc bug fixes
|
|
||||||
|
|
||||||
03/25/2023 [spice2x]
|
|
||||||
Screen Resize UI update (F11)
|
|
||||||
FPS UI update (F12)
|
|
||||||
New option: processor affinity
|
|
||||||
Misc bug fixes
|
|
||||||
|
|
||||||
03/20/2023 [spice2x]
|
|
||||||
ASIO device override for SDVX (experimental)
|
|
||||||
Fix subscreen overlay for SDVX in Valkyrie mode using BI2X I/O
|
|
||||||
Update text for touch and audio config options
|
|
||||||
UI tweaks and minor bug fixes
|
|
||||||
|
|
||||||
03/17/2023 [spice2x]
|
|
||||||
Disable UPX (file sizes will be larger)
|
|
||||||
Fix regression from 2022 that prevented early patches
|
|
||||||
from being loaded properly (such as audio hex edits)
|
|
||||||
New option: HID lighting brightness
|
|
||||||
New option: display auto-rotate direction
|
|
||||||
New option: custom sleep duration
|
|
||||||
|
|
||||||
03/15/2023 [spice2x]
|
|
||||||
Improve IIDX TT+/- handling (allow alternate key bind)
|
|
||||||
Fix SpiceCompanion touch targets for TDJ FHD
|
|
||||||
Config UI tweaks
|
|
||||||
|
|
||||||
03/13/2023 [spice2x]
|
|
||||||
Fix TDJ FHD launching at wrong refresh rate
|
|
||||||
New IIDX/SDVX options for TT/knob sensitivity when using digital input
|
|
||||||
|
|
||||||
03/12/2023 [spice2x]
|
|
||||||
Fix mouse input for SDVX EG subscreen overlay
|
|
||||||
New unified layout for Options tab
|
|
||||||
Allow multiple DLLs in Inject Hook field
|
|
||||||
|
|
||||||
03/11/2023 [spice2x]
|
|
||||||
Beginning of spice2x fork, based on another fork
|
|
||||||
Ensure TDJ mode runs at 1080p@120Hz for newer games
|
|
||||||
Fix IIDX subscreen overlay in FHD mode
|
|
||||||
Gracefully deal with bad ea3-config.xml
|
|
||||||
|
|
||||||
04/02/2022 - Add lua scripting
|
|
||||||
Add button edit dialog
|
|
||||||
Add button debounce/invert settings
|
|
||||||
Add bind many function
|
|
||||||
Misc bug fixes
|
|
||||||
12/28/2021 - Add DirectX 9On12 wrapper option
|
|
||||||
Add analog deadzone settings
|
|
||||||
Fix SSL handshaking failed issue
|
|
||||||
Misc bug fixes
|
|
||||||
12/19/2021 - Force single graphics adapter option
|
|
||||||
Performance improvements
|
|
||||||
Misc bug fixes
|
|
||||||
10/12/2021 - Ongaku Paradise support
|
|
||||||
Fixed memory leak in Windows 8+ touch handler
|
|
||||||
Fix Gitadora two channel fix for Nextage
|
|
||||||
Fix Charge Machine touch window position
|
|
||||||
IIDX 19 support
|
|
||||||
04/02/2021 - Charge Machine support
|
|
||||||
Fix "unsupported fs type" endless loop
|
|
||||||
Misc bug fixes
|
|
||||||
03/01/2021 - Add DDR HD speaker lights
|
|
||||||
Automatic /dev/nvram and /dev/raw creation for AVS 2.17 and later
|
|
||||||
Fix FlexASIO crash introduced in previous release
|
|
||||||
Fix overlay crash from ImGui navigation button handling
|
|
||||||
Fix AVS configuration reading with binary files
|
|
||||||
Add AVS VFS drive remapping for E: and F:
|
|
||||||
Improve XP compatibility
|
|
||||||
Force dummy audio when using ASIO backend
|
|
||||||
Misc bug fixes
|
|
||||||
12/30/2020 - Metal Gear Arcade lights and fixes
|
|
||||||
Misc bug fixes
|
|
||||||
12/11/2020 - Fix patch manager crashing on invalid address
|
|
||||||
Automatic /dev/nvram and /dev/raw creation for AVS 2.16 and prior
|
|
||||||
Analog sensitivity improvements
|
|
||||||
Locale improvements
|
|
||||||
Misc bug fixes
|
|
||||||
10/27/2020 - Screen Capture support
|
|
||||||
IIDX TDJ support
|
|
||||||
Updated patches
|
|
||||||
Misc bug fixes
|
|
||||||
10/13/2020 - Configurator patches tab
|
|
||||||
KFControl fix cursor wrap
|
|
||||||
Screen resize window
|
|
||||||
Misc bug fixes
|
|
||||||
10/03/2020 - Add KFControl
|
|
||||||
Misc bug fixes
|
|
||||||
09/27/2020 - Reflec limelight & colette (LBR) support
|
|
||||||
LovePlus lights support
|
|
||||||
Fix module loading when spice(64).exe is outside contents
|
|
||||||
Ignore touchpad HID devices in touchscreen detection
|
|
||||||
Keypad bindings
|
|
||||||
SSL support
|
|
||||||
Analog knob preview
|
|
||||||
06/15/2020 - QMA physical keyboard support
|
|
||||||
Misc bug fixes
|
|
||||||
05/19/2020 - Alternate audio backends for exclusive-mode applications
|
|
||||||
Fix screenshot handler crash in KMA and LMA
|
|
||||||
MessageBox hooks (stops fullscreen windows from losing focus)
|
|
||||||
04/25/2020 - pop'n music 19 & 20 support
|
|
||||||
DDR X2 support
|
|
||||||
pop'n & HPM HDMI fix
|
|
||||||
Misc additions, fixes
|
|
||||||
03/13/2020 - Misc bug fixes and improvements
|
|
||||||
03/10/2020 - Winning Eleven support
|
|
||||||
03/04/2020 - Tenkaichi Shogikai support
|
|
||||||
Otoca D'or support
|
|
||||||
Misc bug fixes
|
|
||||||
02/29/2020 - MIDI hotplugging / overlay
|
|
||||||
Misc bug fixes
|
|
||||||
02/04/2020 - Configurator options tab
|
|
||||||
Overlay button bindings
|
|
||||||
Card generator
|
|
||||||
Misc bug fixes
|
|
||||||
01/22/2020 - Audio improvements
|
|
||||||
SDVX print overwrite option
|
|
||||||
PNM HD/SD options
|
|
||||||
Window icons
|
|
||||||
Misc improvements
|
|
||||||
01/11/2020 - New Config Utility (F4)
|
|
||||||
Audio Hooks
|
|
||||||
Misc bug fixes
|
|
||||||
01/03/2020 - DANCERUSH STARDOM support
|
|
||||||
Chinese SDVX support
|
|
||||||
Nostalgia OP2 support
|
|
||||||
LayeredFS now complete
|
|
||||||
Misc bug fixes
|
|
||||||
11/26/2019 - LayeredFS integration
|
|
||||||
Misc bug fixes
|
|
||||||
11/17/2019 - Screenshots (PrtScr Key)
|
|
||||||
DLL Architecture detection
|
|
||||||
SCard Felica support
|
|
||||||
Improve MIDI performance
|
|
||||||
Fix bt5api error handling
|
|
||||||
Fix XP support
|
|
||||||
11/05/2019 - Gitadora XG3 support
|
|
||||||
Guitar motor support
|
|
||||||
Gitadora cabinet setting
|
|
||||||
DDR HD->SD light support
|
|
||||||
ESP8266/NodeMCU API support
|
|
||||||
Misc bug fixes
|
|
||||||
10/13/2019 - Serial API support
|
|
||||||
Fullscreen monitor setting
|
|
||||||
Misc bug fixes
|
|
||||||
09/30/2019 - Fixed verbose D3D9 logging
|
|
||||||
MiniMaid support
|
|
||||||
EA-Dev functions
|
|
||||||
Metal Gear bug fixes
|
|
||||||
09/26/2019 - Steel Chronicle support
|
|
||||||
ACIO buffer view/editor
|
|
||||||
Misc bug fixes
|
|
||||||
09/21/2019 - IIDX Effector View
|
|
||||||
Performance improvements
|
|
||||||
PCBID now hidden in log file
|
|
||||||
Misc bug fixes
|
|
||||||
09/16/2019 - Introducing SpiceOverlay
|
|
||||||
- Virtual Keypads/Cards
|
|
||||||
- Patch Manager
|
|
||||||
- FPS/Log/Control Windows
|
|
||||||
Pop'n Music fancy window mode
|
|
||||||
Optional app-config.xml
|
|
||||||
Misc improvements
|
|
||||||
Misc bug fixes
|
|
||||||
09/09/2019 - DDR BIO2 support
|
|
||||||
NVIDIA Optimus support
|
|
||||||
Reflec Beat faster loading
|
|
||||||
Performance improvements
|
|
||||||
Misc bug fixes
|
|
||||||
08/24/2019 - Automatic G-Sync disable
|
|
||||||
Fixed Scotto inverted keypad
|
|
||||||
Fixed SDVX Gen1 input drops
|
|
||||||
Performance improvements
|
|
||||||
08/19/2019 - Scotto support
|
|
||||||
Mahjong Fight Club support
|
|
||||||
FutureTomTom Kinect fix
|
|
||||||
Fixed AVS heap size defaults
|
|
||||||
Fixed signal hook crash
|
|
||||||
Fixed early boot logging
|
|
||||||
08/14/2019 - HELLO! Pop'n Music lights
|
|
||||||
Improve performance
|
|
||||||
08/13/2019 - Add -cfgpath option
|
|
||||||
Misc additions/fixes
|
|
||||||
08/10/2019 - HELLO! Pop'n Music support
|
|
||||||
LovePlus support
|
|
||||||
Discord Rich Presence support
|
|
||||||
API shutdown/reboot
|
|
||||||
Add -nolegacy option
|
|
||||||
Colored logging
|
|
||||||
07/31/2019 - QMA windowed mode fix
|
|
||||||
QMA network check fix
|
|
||||||
Logging improvements
|
|
||||||
07/22/2019 - DDR SD mode reader fix
|
|
||||||
Misc bugs fixed with ACIO
|
|
||||||
Beatstream lights/mouse
|
|
||||||
Beatstream -ea support
|
|
||||||
07/19/2019 - FutureTomTom support
|
|
||||||
Reflec Beat lights
|
|
||||||
Dance Evolution lights
|
|
||||||
Nostalgia lights
|
|
||||||
SuperExit on ALT-F4
|
|
||||||
07/16/2019 - Hook DLLs load earlier
|
|
||||||
Heap size argument alias
|
|
||||||
API restart function
|
|
||||||
SmartEA cmd line option
|
|
||||||
Reader keypad support
|
|
||||||
Initial MFC support
|
|
||||||
Misc bug fixes
|
|
||||||
06/22/2019 - Touchpad button binding fix
|
|
||||||
MIDI buttons/analogs support
|
|
||||||
Misc bug fixes
|
|
||||||
05/18/2019 - API WebSocket support
|
|
||||||
05/16/2019 - Device Hotplugging
|
|
||||||
USB-Stick card inserts
|
|
||||||
Cursor capture fix
|
|
||||||
EA server fix for old AVS
|
|
||||||
05/07/2019 - Reflec 1 support
|
|
||||||
Gitadora custom PCBID
|
|
||||||
Touchscreen improvements
|
|
||||||
Touchscreen support on XP
|
|
||||||
Higher RB input polling rate
|
|
||||||
L/R-Shift/Control support
|
|
||||||
04/13/2019 - DDR SD Mode lights
|
|
||||||
Sextet (LIT Board) support
|
|
||||||
PIUIO hardware support
|
|
||||||
Windowed mode improvements
|
|
||||||
03/14/2019 - IIDX API module
|
|
||||||
EA server maintenance toggle
|
|
||||||
SDVX BI2A support
|
|
||||||
02/19/2019 - Network API server
|
|
||||||
Run outside of modules dir
|
|
||||||
Misc bug fixes
|
|
||||||
01/27/2019 - Jubeat Knit support
|
|
||||||
Quiz Magic Academy support
|
|
||||||
Museca/Jubeat lights
|
|
||||||
Smartcard NumLock toggle
|
|
||||||
01/11/2019 - Open Source!
|
|
||||||
Jubeat Copious support
|
|
||||||
Bishi Bashi Channel support
|
|
||||||
PacDrive/PocketVoltex support
|
|
||||||
KBT/KLD now are optional
|
|
||||||
Stacktraces, quiet crash
|
|
||||||
Huge code refactoring
|
|
||||||
Stability improvements/fixes
|
|
||||||
11/03/2018 - IIDX 25 (io, cams, light)
|
|
||||||
IIDX effector bindings
|
|
||||||
HID lighting output support
|
|
||||||
Button Multibinding
|
|
||||||
HID readers e.g. zyp's cardio
|
|
||||||
Bug fixes as usual
|
|
||||||
08/17/2018 - DDR X3, Nostalgia, Network
|
|
||||||
06/25/2018 - HID smartcard readers
|
|
||||||
06/10/2018 - DDR support
|
|
||||||
06/07/2018 - Gitadora/HID/EA bug fixes
|
|
||||||
05/18/2018 - Gitadora and MIDI devices
|
|
||||||
05/07/2018 - Support for hat switches
|
|
||||||
04/21/2018 - Card path configuration
|
|
||||||
04/09/2018 - HID/Analog/RawInput support
|
|
||||||
03/13/2018 - SDVX printer, felica, BT5API
|
|
||||||
01/23/2018 - MUSECA analog slowdown, fixes
|
|
||||||
01/21/2018 - Many fixed bugs/crashes
|
|
||||||
11/15/2017 - Fixed the MUSECA sound issue
|
|
||||||
11/14/2017 - Added MUSECA, Pop'n Music
|
|
||||||
Wavepass reader support
|
|
||||||
09/11/2017 - Added Road Fighters 3D
|
|
||||||
08/29/2017 - Custom modules path,
|
|
||||||
UAC admin manifest, netfix
|
|
||||||
08/28/2017 - Bug fixes
|
|
||||||
08/21/2017 - 64bit builds, beatstream
|
|
||||||
More command line options
|
|
||||||
07/28/2017 - Fixed I/O for IIDX and SDVX
|
|
||||||
07/26/2017 - Configuration Tool, Jubeat
|
|
||||||
Touch module, more options
|
|
||||||
06/01/2017 - Added DEA support
|
|
||||||
05/31/2017 - Public release
|
|
||||||
Vendored
+3
@@ -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
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ namespace games::ddr {
|
|||||||
|
|
||||||
void DDRGame::pre_attach() {
|
void DDRGame::pre_attach() {
|
||||||
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::is_model("TDX")) {
|
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::is_model("TDX")) {
|
||||||
log_fatal(
|
log_warning(
|
||||||
"ddr",
|
"ddr",
|
||||||
"BAD MODEL NAME ERROR\n\n\n"
|
"BAD MODEL NAME ERROR\n\n\n"
|
||||||
"!!! model name set to TDX, this is WRONG and will break your game !!!\n"
|
"!!! model name set to TDX, this is WRONG and will break your game !!!\n"
|
||||||
@@ -136,6 +136,8 @@ namespace games::ddr {
|
|||||||
"!!! !!!\n"
|
"!!! !!!\n"
|
||||||
"!!! model name set to TDX, this is WRONG and will break your game !!!\n\n\n"
|
"!!! model name set to TDX, this is WRONG and will break your game !!!\n\n\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
log_fatal("ddr", "BAD MODEL NAME ERROR - TDX specified, should be MDX instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::DEST[0] == 'U') {
|
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::DEST[0] == 'U') {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "misc/wintouchemu.h"
|
#include "misc/wintouchemu.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/memutils.h"
|
#include "util/memutils.h"
|
||||||
@@ -235,7 +236,7 @@ namespace games::iidx {
|
|||||||
out.clear();
|
out.clear();
|
||||||
return true;
|
return true;
|
||||||
} else if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
} else if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
||||||
launcher::signal::SUPERSTEP_SOUND_ERROR = TRUE;
|
deferredlogs::defer_error_messages(deferredlogs::SUPERSTEP_SOUND_ERROR_MESSAGE);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -411,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());
|
||||||
}
|
}
|
||||||
@@ -431,7 +428,7 @@ namespace games::iidx {
|
|||||||
|
|
||||||
// check bad model name
|
// check bad model name
|
||||||
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::is_model("TDJ")) {
|
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::is_model("TDJ")) {
|
||||||
log_fatal(
|
log_warning(
|
||||||
"iidx",
|
"iidx",
|
||||||
"BAD MODEL NAME ERROR\n\n\n"
|
"BAD MODEL NAME ERROR\n\n\n"
|
||||||
"!!! model name set to TDJ, this is WRONG and will break your game !!!\n"
|
"!!! model name set to TDJ, this is WRONG and will break your game !!!\n"
|
||||||
@@ -449,6 +446,8 @@ namespace games::iidx {
|
|||||||
"!!! !!!\n"
|
"!!! !!!\n"
|
||||||
"!!! model name set to TDJ, this is WRONG and will break your game !!!\n\n\n"
|
"!!! model name set to TDJ, this is WRONG and will break your game !!!\n\n\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
log_fatal("iidx", "BAD MODEL NAME ERROR - TDJ specified, must be LDJ instead");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ namespace games::jb {
|
|||||||
const auto current_path = std::filesystem::current_path();
|
const auto current_path = std::filesystem::current_path();
|
||||||
log_misc("jubeat", "current working directory: {}", current_path.string());
|
log_misc("jubeat", "current working directory: {}", current_path.string());
|
||||||
if (current_path.parent_path() == current_path.root_path()) {
|
if (current_path.parent_path() == current_path.root_path()) {
|
||||||
log_fatal(
|
log_warning(
|
||||||
"jubeat",
|
"jubeat",
|
||||||
"\n\nInvalid path error; jubeat cannot run from a directory in the drive root\n"
|
"\n\nInvalid path error; jubeat cannot run from a directory in the drive root\n"
|
||||||
"The game will overflow the stack and silently fail to boot\n\n"
|
"The game will overflow the stack and silently fail to boot\n\n"
|
||||||
@@ -179,6 +179,10 @@ namespace games::jb {
|
|||||||
"To fix this, create a new directory and move ALL game files there.\n\n"
|
"To fix this, create a new directory and move ALL game files there.\n\n"
|
||||||
"Your current working directory: {}\n",
|
"Your current working directory: {}\n",
|
||||||
current_path.string());
|
current_path.string());
|
||||||
|
|
||||||
|
log_fatal(
|
||||||
|
"jubeat",
|
||||||
|
"Invalid path error; jubeat cannot run from a directory in the drive root");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,6 +288,21 @@ namespace games::mfc {
|
|||||||
MFCGame::MFCGame() : Game("Mahjong Fight Club") {
|
MFCGame::MFCGame() : Game("Mahjong Fight Club") {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool spam_remover(void *user, const std::string &data, logger::Style style, std::string &out) {
|
||||||
|
if (data.empty() || data[0] != '[') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (data.find("W:mutex: lock: mid 00000000 != AVS_DTYPE_MUTEX") != std::string::npos) {
|
||||||
|
out = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (data.find("W:mutex: unlock: mid 00000000 != AVS_DTYPE_MUTEX") != std::string::npos) {
|
||||||
|
out = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void MFCGame::attach() {
|
void MFCGame::attach() {
|
||||||
Game::attach();
|
Game::attach();
|
||||||
|
|
||||||
@@ -308,6 +323,13 @@ namespace games::mfc {
|
|||||||
auto allinone_module = libutils::try_module("allinone.dll");
|
auto allinone_module = libutils::try_module("allinone.dll");
|
||||||
auto system_module = libutils::try_module("system.dll");
|
auto system_module = libutils::try_module("system.dll");
|
||||||
|
|
||||||
|
// Mahjong Fight Club - 2025?
|
||||||
|
// they removed allinone.dll and moved i/o into system.dll
|
||||||
|
if (allinone_module == nullptr) {
|
||||||
|
log_misc("mfc", "using system.dll instead of allinone.dll for i/o hooks");
|
||||||
|
allinone_module = system_module;
|
||||||
|
}
|
||||||
|
|
||||||
// network fix
|
// network fix
|
||||||
detour::iat_try("?nic_dhcp_maybe_exist@@YAEXZ", nic_dhcp_maybe_exist, system_module);
|
detour::iat_try("?nic_dhcp_maybe_exist@@YAEXZ", nic_dhcp_maybe_exist, system_module);
|
||||||
|
|
||||||
@@ -378,5 +400,7 @@ namespace games::mfc {
|
|||||||
detour::inline_hook((void *) mouse_utl_step, libutils::try_proc(
|
detour::inline_hook((void *) mouse_utl_step, libutils::try_proc(
|
||||||
allinone_module, "?mouse_utl_step@@YAXXZ"));
|
allinone_module, "?mouse_utl_step@@YAXXZ"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger::hook_add(spam_remover, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace games::pcm {
|
|||||||
static double BILL_DELAY = 2.0;
|
static double BILL_DELAY = 2.0;
|
||||||
|
|
||||||
static int bill_kind = 0;
|
static int bill_kind = 0;
|
||||||
|
static int accept_bill_kind = 0;
|
||||||
|
|
||||||
static int __cdecl BillVali_GetEscrowBillKind() {
|
static int __cdecl BillVali_GetEscrowBillKind() {
|
||||||
return bill_kind;
|
return bill_kind;
|
||||||
@@ -74,6 +75,12 @@ namespace games::pcm {
|
|||||||
BILL_IN_TIME = get_performance_seconds();
|
BILL_IN_TIME = get_performance_seconds();
|
||||||
} else if ((BILL_IN_TIME != 0) && ((BILL_IN_TIME + BILL_DELAY) <= get_performance_seconds())) {
|
} else if ((BILL_IN_TIME != 0) && ((BILL_IN_TIME + BILL_DELAY) <= get_performance_seconds())) {
|
||||||
BILL_IN_TIME = 0;
|
BILL_IN_TIME = 0;
|
||||||
|
|
||||||
|
if (accept_bill_kind != 0 && accept_bill_kind != bill_kind) {
|
||||||
|
bill_kind = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (bill_kind) {
|
switch (bill_kind) {
|
||||||
case 1:
|
case 1:
|
||||||
return 1;
|
return 1;
|
||||||
@@ -98,7 +105,8 @@ namespace games::pcm {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __cdecl BillVali_SetAcceptBill(int) {
|
static bool __cdecl BillVali_SetAcceptBill(int a1) {
|
||||||
|
accept_bill_kind = a1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,5 +156,13 @@ namespace games::pcm {
|
|||||||
system, "?GetEscrowBillKind@GsBillVali@@SAHXZ"));
|
system, "?GetEscrowBillKind@GsBillVali@@SAHXZ"));
|
||||||
detour::inline_hook(BillVali_SetAcceptBill, libutils::try_proc(
|
detour::inline_hook(BillVali_SetAcceptBill, libutils::try_proc(
|
||||||
system, "?SetAcceptBill@GsBillVali@@SA_NH@Z"));
|
system, "?SetAcceptBill@GsBillVali@@SA_NH@Z"));
|
||||||
|
|
||||||
|
// NOTE: for 2024091200 or newer
|
||||||
|
detour::inline_hook(BillVali_ReceiveBill, libutils::try_proc(
|
||||||
|
system, "?ReceiveBill@GsBillVali@@SA_NXZ"));
|
||||||
|
detour::inline_hook(BillVali_GetEscrowBillKind, libutils::try_proc(
|
||||||
|
system, "?GetEscrowBillKind@GsBillVali@@SA?AW4E_BILLKIND@@XZ"));
|
||||||
|
detour::inline_hook(BillVali_SetAcceptBill, libutils::try_proc(
|
||||||
|
system, "?SetAcceptBill@GsBillVali@@SA_NW4E_BILLKIND@@@Z"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "hooks/sleephook.h"
|
#include "hooks/sleephook.h"
|
||||||
#include "hooks/winuser.h"
|
#include "hooks/winuser.h"
|
||||||
#include "touch/touch.h"
|
#include "touch/touch.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/sigscan.h"
|
#include "util/sigscan.h"
|
||||||
@@ -211,7 +212,16 @@ namespace games::sdvx {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
||||||
launcher::signal::SUPERSTEP_SOUND_ERROR = TRUE;
|
deferredlogs::defer_error_messages(deferredlogs::SUPERSTEP_SOUND_ERROR_MESSAGE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (data.find("W:ea3-pos: ea3_report_posev: no such node:") != std::string::npos) {
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
"bad prop\\ea3-config.xml detected by game",
|
||||||
|
std::string(" ") + data,
|
||||||
|
" this will most likely cause Server Busy errors in certain conditions",
|
||||||
|
" follow the FAQ to fix your ea3-config.xml and try again"
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -267,7 +277,7 @@ namespace games::sdvx {
|
|||||||
AUTO_INSERT_CARD_COOLDOWN = 15.f;
|
AUTO_INSERT_CARD_COOLDOWN = 15.f;
|
||||||
// check bad model name
|
// check bad model name
|
||||||
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::is_model("UFC")) {
|
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::is_model("UFC")) {
|
||||||
log_fatal(
|
log_warning(
|
||||||
"sdvx",
|
"sdvx",
|
||||||
"BAD MODEL NAME ERROR\n\n\n"
|
"BAD MODEL NAME ERROR\n\n\n"
|
||||||
"!!! model name set to UFC, this is WRONG and will break your game !!!\n"
|
"!!! model name set to UFC, this is WRONG and will break your game !!!\n"
|
||||||
@@ -277,6 +287,9 @@ namespace games::sdvx {
|
|||||||
"!!! !!!\n"
|
"!!! !!!\n"
|
||||||
"!!! model name set to UFC, this is WRONG and will break your game !!!\n\n\n"
|
"!!! model name set to UFC, this is WRONG and will break your game !!!\n\n\n"
|
||||||
);
|
);
|
||||||
|
log_fatal(
|
||||||
|
"sdvx",
|
||||||
|
"BAD MODEL NAME ERROR - model name set to UFC, must be KFC instead");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,14 @@
|
|||||||
#include "hooks/graphics/graphics.h"
|
#include "hooks/graphics/graphics.h"
|
||||||
#include "launcher/launcher.h"
|
#include "launcher/launcher.h"
|
||||||
#include "launcher/options.h"
|
#include "launcher/options.h"
|
||||||
|
#include "launcher/signal.h"
|
||||||
#include "launcher/shutdown.h"
|
#include "launcher/shutdown.h"
|
||||||
#include "misc/clipboard.h"
|
#include "misc/clipboard.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "misc/wintouchemu.h"
|
#include "misc/wintouchemu.h"
|
||||||
#include "overlay/overlay.h"
|
#include "overlay/overlay.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/flags_helper.h"
|
#include "util/flags_helper.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
@@ -203,15 +205,50 @@ static std::string presentation_interval2s(UINT presentation_interval) {
|
|||||||
|
|
||||||
static void update_backbuffer_dimensions(D3DPRESENT_PARAMETERS *params);
|
static void update_backbuffer_dimensions(D3DPRESENT_PARAMETERS *params);
|
||||||
|
|
||||||
|
static void log_create_device_failure(HRESULT hresult) {
|
||||||
|
// only print once since some games will try CreateDevice multiple times on failure
|
||||||
|
static std::once_flag printed;
|
||||||
|
std::call_once(printed, [hresult]() {
|
||||||
|
// special case for popn
|
||||||
|
if (avs::game::is_model("M39")) {
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
fmt::format("D3D9 CreateDevice/CreateDeviceEx failed with {:#x}!", (UINT)hresult),
|
||||||
|
" possible popn music HD mode resolution issue",
|
||||||
|
" popn HD mode launches at 1360x768 (and NOT 1366x768) which is often",
|
||||||
|
" unsupported by many monitors; here are some possible workarounds:",
|
||||||
|
" * enable GPU resolution scaling in your GPU settings",
|
||||||
|
" * use Force Full Screen Resolution option, combined with image scaling (F11)",
|
||||||
|
" * run in windowed mode",
|
||||||
|
" * run in SD mode"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
fmt::format("D3D9 CreateDevice/CreateDeviceEx failed with {:#x}!", (UINT)hresult),
|
||||||
|
" this is a common graphics / monitor issue",
|
||||||
|
" * double check any graphics options you configured in spicecfg",
|
||||||
|
" * double check that your monitor supports the resolution + refresh rate",
|
||||||
|
" combination that the game requires",
|
||||||
|
" * enable GPU-side resolution scaling in your GPU options as needed",
|
||||||
|
" * if you have three or more monitors, try unplugging them down to one or two,",
|
||||||
|
" or enable -graphics-force-single-adapter option",
|
||||||
|
" * failing all that, see if enabling windowed mode helps"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
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:
|
||||||
@@ -219,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) {
|
||||||
@@ -775,6 +831,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDevice(
|
|||||||
|
|
||||||
// log error
|
// log error
|
||||||
log_info("graphics::d3d9", "IDirect3D9::CreateDevice failed, hr={}", FMT_HRESULT(ret));
|
log_info("graphics::d3d9", "IDirect3D9::CreateDevice failed, hr={}", FMT_HRESULT(ret));
|
||||||
|
log_create_device_failure(ret);
|
||||||
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
||||||
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
||||||
|
|
||||||
@@ -994,6 +1051,8 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDeviceEx(
|
|||||||
|
|
||||||
// log error
|
// log error
|
||||||
log_warning("graphics::d3d9", "CreateDeviceEx failed, hr={}", FMT_HRESULT(result));
|
log_warning("graphics::d3d9", "CreateDeviceEx failed, hr={}", FMT_HRESULT(result));
|
||||||
|
log_create_device_failure(result);
|
||||||
|
|
||||||
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
||||||
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -97,6 +99,7 @@
|
|||||||
#include "touch/touch.h"
|
#include "touch/touch.h"
|
||||||
#include "util/cpuutils.h"
|
#include "util/cpuutils.h"
|
||||||
#include "util/crypt.h"
|
#include "util/crypt.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
@@ -262,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) {
|
||||||
@@ -295,22 +299,6 @@ 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() &&
|
|
||||||
options[launcher::Options::ServiceURL].is_active() &&
|
|
||||||
!cfg::CONFIGURATOR_STANDALONE) {
|
|
||||||
log_fatal(
|
|
||||||
"launcher",
|
|
||||||
"BAD EAMUSE SETTINGS ERROR\n\n\n"
|
|
||||||
"-------------------------------------------------------------------\n"
|
|
||||||
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
|
||||||
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
|
||||||
"A service URL is set **AND** E-Amusement emulation is enabled.\n"
|
|
||||||
"Either remove the service URL, or disable E-Amusement emulation.\n"
|
|
||||||
"Otherwise you may experience problems logging in.\n"
|
|
||||||
"-------------------------------------------------------------------\n\n\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (options[launcher::Options::EAmusementEmulation].value_bool()) {
|
if (options[launcher::Options::EAmusementEmulation].value_bool()) {
|
||||||
avs::ea3::URL_SLASH = 1;
|
avs::ea3::URL_SLASH = 1;
|
||||||
easrv_port = 8080;
|
easrv_port = 8080;
|
||||||
@@ -365,6 +353,9 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::VerboseAVSLogging].value_bool()) {
|
if (options[launcher::Options::VerboseAVSLogging].value_bool()) {
|
||||||
hooks::avs::config::LOG = true;
|
hooks::avs::config::LOG = true;
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::AllowEA3Verbose].value_bool()) {
|
||||||
|
avs::ea3::EA3_DEBUG_VERBOSE = true;
|
||||||
|
}
|
||||||
if (options[launcher::Options::spice2x_AutoOrientation].is_active()) {
|
if (options[launcher::Options::spice2x_AutoOrientation].is_active()) {
|
||||||
GRAPHICS_ADJUST_ORIENTATION =
|
GRAPHICS_ADJUST_ORIENTATION =
|
||||||
(graphics_orientation)options[launcher::Options::spice2x_AutoOrientation].value_uint32();
|
(graphics_orientation)options[launcher::Options::spice2x_AutoOrientation].value_uint32();
|
||||||
@@ -475,6 +466,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();
|
||||||
}
|
}
|
||||||
@@ -812,6 +806,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();
|
||||||
@@ -831,6 +826,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;
|
||||||
}
|
}
|
||||||
@@ -934,6 +930,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;
|
||||||
@@ -1196,15 +1197,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) {
|
||||||
@@ -1248,18 +1262,19 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
for (const auto &option : options) {
|
for (const auto &option : options) {
|
||||||
if (option.conflicting && option.get_definition().type != OptionType::Bool) {
|
if (option.conflicting && option.get_definition().type != OptionType::Bool) {
|
||||||
conflicts += 1;
|
conflicts += 1;
|
||||||
|
const auto& value = option.get_definition().sensitive ? "*****" : option.value;
|
||||||
if (launcher::USE_CMD_OVERRIDE) {
|
if (launcher::USE_CMD_OVERRIDE) {
|
||||||
log_warning(
|
log_warning(
|
||||||
"launcher",
|
"launcher",
|
||||||
"multiple values for -{}, command line args take precedence: {}",
|
"multiple values for -{}, command line args take precedence: {}",
|
||||||
option.get_definition().name,
|
option.get_definition().name,
|
||||||
option.value);
|
value);
|
||||||
} else {
|
} else {
|
||||||
log_warning(
|
log_warning(
|
||||||
"launcher",
|
"launcher",
|
||||||
"multiple values for -{}, spicecfg values take precedence: {}",
|
"multiple values for -{}, spicecfg values take precedence: {}",
|
||||||
option.get_definition().name,
|
option.get_definition().name,
|
||||||
option.value);
|
value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1288,6 +1303,25 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options[launcher::Options::EAmusementEmulation].value_bool() &&
|
||||||
|
options[launcher::Options::ServiceURL].is_active() &&
|
||||||
|
!cfg::CONFIGURATOR_STANDALONE) {
|
||||||
|
log_warning(
|
||||||
|
"launcher",
|
||||||
|
"BAD EAMUSE SETTINGS ERROR\n\n\n"
|
||||||
|
"-------------------------------------------------------------------\n"
|
||||||
|
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
||||||
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
|
"A service URL is set **AND** E-Amusement emulation is enabled.\n"
|
||||||
|
"Either remove the service URL, or disable E-Amusement emulation.\n"
|
||||||
|
"Otherwise you may experience problems logging in.\n"
|
||||||
|
"-------------------------------------------------------------------\n\n\n"
|
||||||
|
);
|
||||||
|
log_fatal(
|
||||||
|
"launcher",
|
||||||
|
"BAD EAMUSE SETTINGS ERROR: both -ea and -url are set");
|
||||||
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::FullscreenResolution].is_active()) {
|
if (options[launcher::Options::FullscreenResolution].is_active()) {
|
||||||
std::pair<uint32_t, uint32_t> result;
|
std::pair<uint32_t, uint32_t> result;
|
||||||
if (parse_width_height(options[launcher::Options::FullscreenResolution].value_text(), result)) {
|
if (parse_width_height(options[launcher::Options::FullscreenResolution].value_text(), result)) {
|
||||||
@@ -1372,7 +1406,11 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
log_info("launcher", "loading early hook DLL {}", hook);
|
log_info("launcher", "loading early hook DLL {}", hook);
|
||||||
HMODULE module;
|
HMODULE module;
|
||||||
if (!(module = libutils::try_library(hook))) {
|
if (!(module = libutils::try_library(hook))) {
|
||||||
log_warning("launcher", "failed to load early hook {}", hook);
|
log_warning("launcher", "failed to load early hook {}: {}", hook, get_last_error_string());
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
fmt::format("failed to load early hook {}:", hook),
|
||||||
|
fmt::format(" {}", get_last_error_string())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1639,6 +1677,14 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
attach_io = true;
|
attach_io = true;
|
||||||
attach_mfc = true;
|
attach_mfc = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Mahjong Fight Club - 2025?
|
||||||
|
// they removed allinone.dll and moved i/o into system.dll
|
||||||
|
} else if (check_dll("system.dll") && fileutils::file_exists("data/mfc.ini")) {
|
||||||
|
avs::game::DLL_NAME = "system.dll";
|
||||||
|
attach_io = true;
|
||||||
|
attach_mfc = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FutureTomTom
|
// FutureTomTom
|
||||||
@@ -1783,7 +1829,7 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
// usage error
|
// usage error
|
||||||
if (!cfg::CONFIGURATOR_STANDALONE
|
if (!cfg::CONFIGURATOR_STANDALONE
|
||||||
&& (!CHECK_DLL_IGNORE_ARCH)) {
|
&& (!CHECK_DLL_IGNORE_ARCH)) {
|
||||||
log_fatal(
|
log_warning(
|
||||||
"launcher",
|
"launcher",
|
||||||
"module auto detection failed!\n\n"
|
"module auto detection failed!\n\n"
|
||||||
"This usually means one of the following:\n\n"
|
"This usually means one of the following:\n\n"
|
||||||
@@ -1791,6 +1837,8 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
" 2. XML files in prop directory are malformed or missing, or\n"
|
" 2. XML files in prop directory are malformed or missing, or\n"
|
||||||
" 3. You passed in invalid options (usually, path overrides like -exec)\n\n"
|
" 3. You passed in invalid options (usually, path overrides like -exec)\n\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
log_fatal("launcher", "module auto detection failed, see log.txt for troubleshooting");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2152,7 +2200,11 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
log_info("launcher", "loading hook DLL {}", hook);
|
log_info("launcher", "loading hook DLL {}", hook);
|
||||||
HMODULE module;
|
HMODULE module;
|
||||||
if (!(module = libutils::try_library(hook))) {
|
if (!(module = libutils::try_library(hook))) {
|
||||||
log_warning("launcher", "failed to load hook {}", hook);
|
log_warning("launcher", "failed to load hook {}: {}", hook, get_last_error_string());
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
fmt::format("failed to load hook {}:", hook),
|
||||||
|
fmt::format(" {}", get_last_error_string())
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
bt5api_hook(module);
|
bt5api_hook(module);
|
||||||
}
|
}
|
||||||
@@ -2161,9 +2213,13 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
// layeredfs
|
// layeredfs
|
||||||
if (fileutils::dir_exists("data_mods") &&
|
if (fileutils::dir_exists("data_mods") &&
|
||||||
GetModuleHandleA("ifs_hook.dll") == nullptr) {
|
GetModuleHandleA("ifs_hook.dll") == nullptr) {
|
||||||
log_warning("launcher", "data_mods directory was found, but ifs_hook.dll is not present; your mods will not load");
|
log_warning("launcher", "data_mods directory found, but ifs_hook.dll is not present; mods will not load");
|
||||||
log_warning("launcher", "to fix this, download ifs_layeredfs and add it as a DLL hook (-k)");
|
deferredlogs::defer_error_messages({
|
||||||
log_warning("launcher", "https://github.com/mon/ifs_layeredfs");
|
"data_mods directory was found, but ifs_hook.dll is not present",
|
||||||
|
" your mods will not load",
|
||||||
|
" to fix this, download ifs_layeredfs and add it as a DLL hook (-k)",
|
||||||
|
" https://github.com/mon/ifs_layeredfs"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply patches
|
// apply patches
|
||||||
@@ -2298,8 +2354,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();
|
||||||
|
|||||||
@@ -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)",
|
||||||
@@ -359,7 +365,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.name = "r",
|
.name = "r",
|
||||||
.desc = "Set custom SOFTID override",
|
.desc = "Set custom SOFTID override",
|
||||||
.type = OptionType::Text,
|
.type = OptionType::Text,
|
||||||
.category = "Network (Development)",
|
.category = "Development",
|
||||||
.sensitive = true,
|
.sensitive = true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -554,10 +560,11 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Game Options",
|
.category = "Game Options",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "IIDX BIO2 Firmware",
|
.title = "IIDX BIO2 Firmware Update",
|
||||||
.name = "iidxbio2fw",
|
.name = "iidxbio2fw",
|
||||||
.desc = "Enables BIO2 firmware updates",
|
.desc = "Enables BIO2 firmware updates. WARNING - can cause semi-permanent change to your I/O board",
|
||||||
.type = OptionType::Bool,
|
.type = OptionType::Bool,
|
||||||
|
.hidden = true,
|
||||||
.game_name = "Beatmania IIDX",
|
.game_name = "Beatmania IIDX",
|
||||||
.category = "Game Options (Advanced)",
|
.category = "Game Options (Advanced)",
|
||||||
},
|
},
|
||||||
@@ -1135,11 +1142,11 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Path Overrides",
|
.category = "Path Overrides",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Intel SDE Folder",
|
.title = "Intel SDE",
|
||||||
.name = "sde",
|
.name = "sde",
|
||||||
.desc = "Path to Intel SDE kit path for automatic attaching",
|
.desc = "Path to Intel SDE kit path for automatic attaching",
|
||||||
.type = OptionType::Text,
|
.type = OptionType::Text,
|
||||||
.category = "Path Overrides",
|
.category = "Development",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "ea3-config.xml Override",
|
.title = "ea3-config.xml Override",
|
||||||
@@ -1384,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
|
||||||
@@ -1412,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
|
||||||
@@ -1544,10 +1559,13 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.title = "Spice Audio Hook Backend",
|
.title = "Spice Audio Hook Backend",
|
||||||
.name = "audiobackend",
|
.name = "audiobackend",
|
||||||
.desc = "Selects the audio backend to use when spice audio hook is enabled, overriding exclusive WASAPI. "
|
.desc = "Selects the audio backend to use when spice audio hook is enabled, overriding exclusive WASAPI. "
|
||||||
" Does nothing for games that do not output to exclusive WASAPI",
|
"Does nothing for games that do not output to exclusive WASAPI",
|
||||||
.type = OptionType::Enum,
|
.type = OptionType::Enum,
|
||||||
.category = "Audio",
|
.category = "Audio",
|
||||||
.elements = {{"asio", "ASIO"}, {"waveout", "waveOut"}},
|
.elements = {
|
||||||
|
{"asio", "ASIO"},
|
||||||
|
{"waveout", "broken, do not use"}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Spice Audio Hook ASIO Driver ID",
|
.title = "Spice Audio Hook ASIO Driver ID",
|
||||||
@@ -1672,6 +1690,16 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.type = OptionType::Bool,
|
.type = OptionType::Bool,
|
||||||
.category = "Debug Log",
|
.category = "Debug Log",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// AllowEA3Verbose
|
||||||
|
.title = "Allow EA3 Verbose Debug Logging",
|
||||||
|
.name = "ea3verbose",
|
||||||
|
.desc = "This option is only useful for network developers; leave this OFF.\n\n"
|
||||||
|
"By default, ea3/debug/verbose node is removed by spice to prevent exposing PCBID in the logs. "
|
||||||
|
"When this is enabled, ea3/debug/verbose node in the XML will be kept and exposed to the game",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.category = "Debug Log",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.title = "Disable Colored Output",
|
.title = "Disable Colored Output",
|
||||||
.name = "nocolor",
|
.name = "nocolor",
|
||||||
@@ -2375,7 +2403,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.type = OptionType::Bool,
|
.type = OptionType::Bool,
|
||||||
.category = "Development",
|
.category = "Development",
|
||||||
.disabled = true,
|
.disabled = true,
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<std::string> &launcher::get_categories(Options::OptionsCategory category) {
|
const std::vector<std::string> &launcher::get_categories(Options::OptionsCategory category) {
|
||||||
@@ -2594,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;
|
||||||
@@ -2618,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;
|
||||||
@@ -2664,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) {
|
||||||
@@ -2700,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()) {
|
||||||
@@ -2715,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
|
||||||
@@ -2755,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2786,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) {
|
||||||
@@ -2819,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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ namespace launcher {
|
|||||||
DebugCreateFile,
|
DebugCreateFile,
|
||||||
VerboseGraphicsLogging,
|
VerboseGraphicsLogging,
|
||||||
VerboseAVSLogging,
|
VerboseAVSLogging,
|
||||||
|
AllowEA3Verbose,
|
||||||
DisableColoredOutput,
|
DisableColoredOutput,
|
||||||
DisableACPHook,
|
DisableACPHook,
|
||||||
DisableSignalHandling,
|
DisableSignalHandling,
|
||||||
@@ -278,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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "easrv/easrv.h"
|
#include "easrv/easrv.h"
|
||||||
#include "rawinput/rawinput.h"
|
#include "rawinput/rawinput.h"
|
||||||
#include "hooks/audio/audio.h"
|
#include "hooks/audio/audio.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
|
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
@@ -21,6 +22,9 @@ namespace launcher {
|
|||||||
// therefore, subsystems need to be guarded against multiple unload attempts
|
// therefore, subsystems need to be guarded against multiple unload attempts
|
||||||
log_info("launcher", "stopping subsystems");
|
log_info("launcher", "stopping subsystems");
|
||||||
|
|
||||||
|
// before shutting down logger, dump any deferred log messages
|
||||||
|
deferredlogs::dump_to_logger();
|
||||||
|
|
||||||
// flush/stop logger
|
// flush/stop logger
|
||||||
logger::stop();
|
logger::stop();
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
|
|
||||||
|
#include <future>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <dbghelp.h>
|
#include <dbghelp.h>
|
||||||
|
|
||||||
#include "avs/core.h"
|
|
||||||
#include "acio/acio.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"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
@@ -29,11 +30,6 @@ namespace launcher::signal {
|
|||||||
// settings
|
// settings
|
||||||
bool DISABLE = false;
|
bool DISABLE = false;
|
||||||
bool USE_VEH_WORKAROUND = false;
|
bool USE_VEH_WORKAROUND = false;
|
||||||
|
|
||||||
// states
|
|
||||||
bool SUPERSTEP_SOUND_ERROR = false;
|
|
||||||
bool AVS_DIR_CREATION_FAILURE = false;
|
|
||||||
std::string AVS_SRC_PATH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define V(variant) case variant: return #variant
|
#define V(variant) case variant: return #variant
|
||||||
@@ -103,37 +99,33 @@ 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));
|
||||||
|
|
||||||
|
switch (ExceptionRecord->ExceptionCode) {
|
||||||
|
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
"illegal instruction exception:",
|
||||||
|
" either your CPU is too old (e.g., does not support SSE4.2 or AVX2 ",
|
||||||
|
" but perhaps the game requires it); or, a bad patch was applied."
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// check ACIO init failures
|
// check ACIO init failures
|
||||||
if (acio::IO_INIT_IN_PROGRESS) {
|
if (acio::IO_INIT_IN_PROGRESS) {
|
||||||
log_warning(
|
deferredlogs::defer_error_messages({
|
||||||
"signal",
|
"exception raised during ACIO init, this usually happens when ",
|
||||||
"exception raised during ACIO init, this usually happens when a third party application interferes with hooks");
|
" a third party application interferes with hooks",
|
||||||
log_warning(
|
" please check for the following, disable them, and try launching the game again:",
|
||||||
"signal",
|
" * RivaTuner Statistics Server (RTSS)",
|
||||||
" please check for the following, disable them, and try launching the game again:");
|
" * MSI Afterburner",
|
||||||
log_warning(
|
" * kernel mode anti-cheat"
|
||||||
"signal",
|
});
|
||||||
" RivaTuner Statistics Server (RTSS), MSI Afterburner, kernel mode anti-cheat");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (launcher::signal::SUPERSTEP_SOUND_ERROR) {
|
// dump deferred logs BEFORE stack trace since some errors cause stack trace logic to hang
|
||||||
log_warning("signal", "audio initialization error was previously detected during boot!");
|
// (e.g., ACIO init hang due to RTSS)
|
||||||
log_warning("signal", " (W:SuperstepSound: Audio device is not available!!!)");
|
deferredlogs::dump_to_logger(true);
|
||||||
log_warning("signal", " this crash is most likely related to audio init failure");
|
|
||||||
log_warning("signal", " fix your audio device, double check your audio options/patches, and try again");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (launcher::signal::AVS_DIR_CREATION_FAILURE) {
|
|
||||||
log_warning("signal",
|
|
||||||
"AVS filesystem initialization failure was previously detected during boot!");
|
|
||||||
log_warning("signal",
|
|
||||||
" ERROR: directory could not be created: {}",
|
|
||||||
launcher::signal::AVS_SRC_PATH.c_str());
|
|
||||||
log_warning("signal",
|
|
||||||
" this crash may have been caused by bad <mounttable> contents in {}",
|
|
||||||
avs::core::CFG_PATH.c_str());
|
|
||||||
log_warning("signal", " fix the XML file and try again");
|
|
||||||
}
|
|
||||||
|
|
||||||
// walk the exception chain
|
// walk the exception chain
|
||||||
struct _EXCEPTION_RECORD *record_cause = ExceptionRecord->ExceptionRecord;
|
struct _EXCEPTION_RECORD *record_cause = ExceptionRecord->ExceptionRecord;
|
||||||
@@ -183,6 +175,9 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this will stall all UI threads for this process
|
||||||
|
show_popup_for_crash();
|
||||||
|
|
||||||
log_fatal("signal", "end");
|
log_fatal("signal", "end");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace launcher::signal {
|
namespace launcher::signal {
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
extern bool DISABLE;
|
extern bool DISABLE;
|
||||||
extern bool USE_VEH_WORKAROUND;
|
extern bool USE_VEH_WORKAROUND;
|
||||||
extern bool SUPERSTEP_SOUND_ERROR;
|
|
||||||
extern bool AVS_DIR_CREATION_FAILURE;
|
|
||||||
extern std::string AVS_XML_PATH;
|
|
||||||
extern std::string AVS_SRC_PATH;
|
|
||||||
|
|
||||||
//void print_stacktrace();
|
|
||||||
void attach();
|
void attach();
|
||||||
void init();
|
void init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
@@ -2633,17 +2640,16 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
// check hidden option
|
// check hidden option
|
||||||
if (!this->options_show_hidden && option.value.empty()) {
|
if (!this->options_show_hidden && option.value.empty()) {
|
||||||
|
|
||||||
// skip hidden entries
|
// skip hidden entries
|
||||||
if (definition.hidden) {
|
if (definition.hidden) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// check for game exclusivity
|
|
||||||
if (!definition.game_name.empty()) {
|
// check for game exclusivity
|
||||||
if (definition.game_name != this->games_selected_name) {
|
if (!definition.game_name.empty()) {
|
||||||
continue;
|
if (definition.game_name != this->games_selected_name) {
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2905,26 +2911,28 @@ 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::TextLink(PROJECT_URL)) {
|
||||||
if (ImGui::Button(PROJECT_URL)) {
|
|
||||||
launch_shell(PROJECT_URL);
|
launch_shell(PROJECT_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TextUnformatted("");
|
ImGui::TextUnformatted("");
|
||||||
ImGui::TextUnformatted(std::string(
|
ImGui::TextUnformatted(resutil::load_file_string_crlf(IDR_README).c_str());
|
||||||
resutil::load_file_string_crlf(IDR_README) +
|
ImGui::TextUnformatted("");
|
||||||
"\r\n" +
|
ImGui::TextUnformatted("");
|
||||||
"Changelog (Highlights):\r\n" +
|
ImGui::TextUnformatted("Licenses:");
|
||||||
resutil::load_file_string_crlf(IDR_CHANGELOG)).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::build_licenses() {
|
|
||||||
ImGui::TextUnformatted(resutil::load_file_string_crlf(IDR_LICENSES).c_str());
|
ImGui::TextUnformatted(resutil::load_file_string_crlf(IDR_LICENSES).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2977,7 +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;
|
||||||
bool licenses_popup = false;
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 1.0f));
|
||||||
if (ImGui::BeginMenuBar()) {
|
if (ImGui::BeginMenuBar()) {
|
||||||
|
|
||||||
// [spice2x]
|
// [spice2x]
|
||||||
@@ -2987,9 +2995,6 @@ namespace overlay::windows {
|
|||||||
if (ImGui::MenuItem("spice2x.github.io")) {
|
if (ImGui::MenuItem("spice2x.github.io")) {
|
||||||
launch_shell(PROJECT_URL);
|
launch_shell(PROJECT_URL);
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Licenses")) {
|
|
||||||
licenses_popup = true;
|
|
||||||
}
|
|
||||||
if (ImGui::MenuItem("About")) {
|
if (ImGui::MenuItem("About")) {
|
||||||
about_popup = true;
|
about_popup = true;
|
||||||
}
|
}
|
||||||
@@ -3041,13 +3046,12 @@ 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");
|
||||||
}
|
}
|
||||||
if (licenses_popup) {
|
|
||||||
ImGui::OpenPopup("Licenses##topbarpopup");
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw popups
|
// draw popups
|
||||||
{
|
{
|
||||||
@@ -3066,13 +3070,6 @@ namespace overlay::windows {
|
|||||||
this->build_about();
|
this->build_about();
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
ImGui::SetNextWindowSize(popup_size, ImGuiCond_Appearing);
|
|
||||||
ImGui::SetNextWindowPos(popup_pos, ImGuiCond_Appearing);
|
|
||||||
bool unused_open3 = true;
|
|
||||||
if (ImGui::BeginPopupModal("Licenses##topbarpopup", &unused_open3)) {
|
|
||||||
this->build_licenses();
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ namespace overlay::windows {
|
|||||||
void build_options(
|
void build_options(
|
||||||
std::vector<Option> *options, const std::string &category, const std::string *filter=nullptr);
|
std::vector<Option> *options, const std::string &category, const std::string *filter=nullptr);
|
||||||
void build_about();
|
void build_about();
|
||||||
void build_licenses();
|
|
||||||
void build_launcher();
|
void build_launcher();
|
||||||
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
|
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ namespace overlay::windows {
|
|||||||
raw_input_view();
|
raw_input_view();
|
||||||
touch_view();
|
touch_view();
|
||||||
lcd_view();
|
lcd_view();
|
||||||
about_view();
|
|
||||||
ddr_timing_view();
|
ddr_timing_view();
|
||||||
iidx_effectors_view();
|
iidx_effectors_view();
|
||||||
}
|
}
|
||||||
@@ -788,27 +787,6 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Control::about_view() {
|
|
||||||
if (ImGui::CollapsingHeader("About")) {
|
|
||||||
if (ImGui::TreeNode("Changelog")) {
|
|
||||||
ImGui::Separator();
|
|
||||||
if (ImGui::BeginChild("changelog", ImVec2(400, 400))) {
|
|
||||||
ImGui::TextUnformatted(resutil::load_file_string(IDR_CHANGELOG).c_str());
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
|
||||||
if (ImGui::TreeNode("Licenses")) {
|
|
||||||
ImGui::Separator();
|
|
||||||
if (ImGui::BeginChild("changelog", ImVec2(400, 400), false,
|
|
||||||
ImGuiWindowFlags_HorizontalScrollbar
|
|
||||||
| ImGuiWindowFlags_AlwaysHorizontalScrollbar)) {
|
|
||||||
ImGui::TextUnformatted(resutil::load_file_string(IDR_LICENSES).c_str());
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Control::ddr_timing_view() {
|
void Control::ddr_timing_view() {
|
||||||
if (avs::game::is_model("MDX") && ImGui::CollapsingHeader("DDR Timing")) {
|
if (avs::game::is_model("MDX") && ImGui::CollapsingHeader("DDR Timing")) {
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ developers when you can. Sources should be included, have fun!
|
|||||||
|
|
||||||
spice2x fork maintainers:
|
spice2x fork maintainers:
|
||||||
* sp2xdev team
|
* sp2xdev team
|
||||||
|
* the lab
|
||||||
|
|
||||||
SpiceTools original contributors:
|
SpiceTools original contributors:
|
||||||
* cube, felix, dinsfire, nolm, s2, crazyredmachine (jotaro44), mon, nibs
|
* cube, felix, dinsfire, nolm, s2, crazyredmachine (jotaro44), mon, nibs
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include "build/defs.h"
|
||||||
|
#include "deferlog.h"
|
||||||
|
#include "util/logging.h"
|
||||||
|
|
||||||
|
namespace deferredlogs {
|
||||||
|
|
||||||
|
const std::initializer_list<std::string> SUPERSTEP_SOUND_ERROR_MESSAGE = {
|
||||||
|
"audio initialization error was previously detected during boot!",
|
||||||
|
" this crash is most likely related to audio init failure",
|
||||||
|
" * check if the default audio device has changed",
|
||||||
|
" * fix your audio device settings (e.g., sample rate)",
|
||||||
|
" * double check your spice audio options and patches"
|
||||||
|
};
|
||||||
|
|
||||||
|
std::mutex deferred_errors_mutex;
|
||||||
|
std::vector<std::vector<std::string>> deferred_errors;
|
||||||
|
|
||||||
|
void defer_error_messages(std::initializer_list<std::string> messages) {
|
||||||
|
std::lock_guard<std::mutex> lock(deferred_errors_mutex);
|
||||||
|
deferred_errors.emplace_back(messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_to_logger(bool is_crash) {
|
||||||
|
static std::once_flag printed;
|
||||||
|
std::call_once(printed, [is_crash]() {
|
||||||
|
|
||||||
|
// move to a local vector under lock first
|
||||||
|
// this is to avoid holding a lock while emitting to the logger, which may deadlock
|
||||||
|
// due to recursive calls (e.g., via log hooks used for failure detection which then
|
||||||
|
// again calls into defer_error_messages), and std::mutex cannot be acquired recursively
|
||||||
|
std::vector<std::vector<std::string>> errors;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(deferred_errors_mutex);
|
||||||
|
if (deferred_errors.empty() && !is_crash) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
errors = std::move(deferred_errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string msg;
|
||||||
|
msg += "\n\n";
|
||||||
|
msg += "/-------------------------- spice2x auto-troubleshooter -----------------------\\\n";
|
||||||
|
msg += "\n";
|
||||||
|
msg += " spice2x version: " + to_string(VERSION_STRING_CFG) + "\n";
|
||||||
|
msg += "\n";
|
||||||
|
|
||||||
|
if (is_crash) {
|
||||||
|
msg += " the game has crashed\n";
|
||||||
|
msg += " share this entire log file with someone for troubleshooting (log.txt)\n";
|
||||||
|
msg += " spice will also attempt to create a minidump (minidump.dmp)\n";
|
||||||
|
msg += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto messages : errors) {
|
||||||
|
for (auto message : messages) {
|
||||||
|
msg += " " + message + "\n";
|
||||||
|
}
|
||||||
|
msg += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += " unsure what to do next?\n";
|
||||||
|
msg += " * update to the latest version:\n";
|
||||||
|
msg += " https://github.com/spice2x/spice2x.github.io/releases/latest\n";
|
||||||
|
msg += " * check the FAQ:\n";
|
||||||
|
msg += " https://github.com/spice2x/spice2x.github.io/wiki/Known-issues\n";
|
||||||
|
msg += "\n";
|
||||||
|
msg += "\\------------------------- spice2x auto-troubleshooter ------------------------/\n";
|
||||||
|
|
||||||
|
log_warning("troubleshooter", "{}", msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
|
namespace deferredlogs {
|
||||||
|
|
||||||
|
// some shared error messages
|
||||||
|
extern const std::initializer_list<std::string> SUPERSTEP_SOUND_ERROR_MESSAGE;
|
||||||
|
|
||||||
|
void defer_error_messages(std::initializer_list<std::string> messages);
|
||||||
|
void dump_to_logger(bool is_crash=false);
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
#include <set>
|
||||||
|
#include "logging.h"
|
||||||
|
#include "libutils.h"
|
||||||
|
#include "scope_guard.h"
|
||||||
|
#include "dependencies.h"
|
||||||
|
|
||||||
|
using loader_hint = std::tuple<std::string, std::string, std::string>;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// list of commonly missing dependencies and tips on where to get them
|
||||||
|
std::vector<loader_hint> hints = {
|
||||||
|
{
|
||||||
|
"msvcr100.dll",
|
||||||
|
"Visual Studio 2010 (VC++ 10.0) SP1 Redistributable",
|
||||||
|
"Download and install VisualCppRedist_AIO_x86_x64.exe from https://github.com/abbodi1406/vcredist/releases/latest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"d3dx9_43.dll",
|
||||||
|
"DirectX End-User Runtimes",
|
||||||
|
"Download and install from https://www.microsoft.com/en-us/download/details.aspx?id=35"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nvEncodeAPI64.dll",
|
||||||
|
"NVIDIA Graphics Driver",
|
||||||
|
"For non-NVIDIA GPUs, copy the stub file from the spice2x release .zip.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nvcuda.dll",
|
||||||
|
"NVIDIA Graphics Driver",
|
||||||
|
"For non-NVIDIA GPUs, copy the stub file from the spice2x release .zip.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nvcuvid.dll",
|
||||||
|
"NVIDIA Graphics Driver",
|
||||||
|
"For non-NVIDIA GPUs, copy the stub file from the spice2x release .zip.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cpusbxpkm.dll",
|
||||||
|
"LovePlus Printer DLL",
|
||||||
|
"Copy the stub file from the spice2x release .zip.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<std::wstring> failed = {};
|
||||||
|
|
||||||
|
auto read_imports(const std::filesystem::path& path) -> std::vector<std::filesystem::path> {
|
||||||
|
auto result = std::vector<std::filesystem::path> {};
|
||||||
|
auto const file = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
|
|
||||||
|
if (file == INVALID_HANDLE_VALUE) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const file_ = scope_guard { [file] { CloseHandle(file); } };
|
||||||
|
auto const mapping = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||||
|
|
||||||
|
if (!mapping) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const mapping_ = scope_guard { [mapping] { CloseHandle(mapping); } };
|
||||||
|
auto const view = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
|
||||||
|
|
||||||
|
if (!view) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const view_ = scope_guard { [view] { UnmapViewOfFile(view); } };
|
||||||
|
auto const dos = static_cast<PIMAGE_DOS_HEADER>(view);
|
||||||
|
|
||||||
|
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const base = static_cast<std::uint8_t*>(view);
|
||||||
|
auto const nt = reinterpret_cast<PIMAGE_NT_HEADERS>(base + dos->e_lfanew);
|
||||||
|
|
||||||
|
if (nt->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const imports = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||||
|
|
||||||
|
if (imports.VirtualAddress == 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto desc = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(base + libutils::rva2offset(nt, imports.VirtualAddress));
|
||||||
|
|
||||||
|
while (desc->Name != 0) {
|
||||||
|
auto const filename = reinterpret_cast<char*>(base + libutils::rva2offset(nt, desc->Name));
|
||||||
|
auto entry_path = path.parent_path().append(filename);
|
||||||
|
|
||||||
|
// try to use library in the same directory if one exists
|
||||||
|
// otherwise, assume system library and use filename only
|
||||||
|
if (!std::filesystem::exists(entry_path)) {
|
||||||
|
entry_path = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.emplace_back(entry_path);
|
||||||
|
desc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace dependencies {
|
||||||
|
auto walk(const std::filesystem::path& path, const std::string& prefix) -> bool {
|
||||||
|
// try to load the library -- skip walking if it loads successfully
|
||||||
|
if (auto const module = LoadLibraryW(path.c_str())) {
|
||||||
|
FreeLibrary(module);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const error = GetLastError();
|
||||||
|
auto const filename = path.filename().string();
|
||||||
|
|
||||||
|
log_misc("dependencies", "{}{}", prefix + (prefix.empty() ? "": "|-- "), filename);
|
||||||
|
|
||||||
|
if (failed.contains(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed.insert(path);
|
||||||
|
|
||||||
|
auto const dependencies = read_imports(path);
|
||||||
|
auto const next_prefix = prefix + (prefix.empty() ? " ": "| ");
|
||||||
|
|
||||||
|
if (!dependencies.empty()) {
|
||||||
|
for (auto const& item : dependencies) {
|
||||||
|
walk(item, next_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& [dll, name, hint] : hints) {
|
||||||
|
if (_stricmp(dll.c_str(), filename.c_str()) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning("dependencies", "{}|-- [!] {}", next_prefix, name.c_str());
|
||||||
|
log_warning("dependencies", "{}|-- {}", next_prefix, hint.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning("dependencies", "{}|-- [!] The library could not be loaded. ({})", next_prefix, error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace dependencies {
|
||||||
|
auto walk(const std::filesystem::path& path, const std::string& prefix = "") -> bool;
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "peb.h"
|
#include "peb.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
|
#include "util/dependencies.h"
|
||||||
|
|
||||||
std::filesystem::path libutils::module_file_name(HMODULE module) {
|
std::filesystem::path libutils::module_file_name(HMODULE module) {
|
||||||
std::wstring buf;
|
std::wstring buf;
|
||||||
@@ -42,7 +43,8 @@ static inline void load_library_fail(const std::string &file_name, bool fatal) {
|
|||||||
" b. http://www.dependencywalker.com/ (for old OS) \n"
|
" b. http://www.dependencywalker.com/ (for old OS) \n"
|
||||||
, file_name) };
|
, file_name) };
|
||||||
if (fatal) {
|
if (fatal) {
|
||||||
log_fatal("libutils", "{}", info_str);
|
log_warning("libutils", "{}", info_str);
|
||||||
|
log_fatal("libutils", "DLL failed to load: {}, see log.txt for troubleshooting", file_name);
|
||||||
} else {
|
} else {
|
||||||
log_warning("libutils", "{}", info_str);
|
log_warning("libutils", "{}", info_str);
|
||||||
}
|
}
|
||||||
@@ -65,6 +67,7 @@ HMODULE libutils::load_library(const std::filesystem::path &path, bool fatal) {
|
|||||||
|
|
||||||
if (!module) {
|
if (!module) {
|
||||||
log_warning("libutils", "'{}' couldn't be loaded: {}", path.string(), get_last_error_string());
|
log_warning("libutils", "'{}' couldn't be loaded: {}", path.string(), get_last_error_string());
|
||||||
|
dependencies::walk(path);
|
||||||
load_library_fail(path.filename().string(), fatal);
|
load_library_fail(path.filename().string(), fatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
#include "build/defs.h"
|
||||||
|
#include "hooks/graphics/graphics.h"
|
||||||
|
|
||||||
std::string_view log_get_datetime() {
|
std::string_view log_get_datetime() {
|
||||||
return log_get_datetime(time(nullptr));
|
return log_get_datetime(time(nullptr));
|
||||||
@@ -12,3 +18,66 @@ std::string_view log_get_datetime(std::time_t now) {
|
|||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void show_popup(const std::string text) {
|
||||||
|
static std::once_flag shown;
|
||||||
|
std::call_once(shown, [text]() {
|
||||||
|
|
||||||
|
// minimize all windows
|
||||||
|
// only needed because in multi-monitor full screen games, MessageBox fails to show above the game
|
||||||
|
for (auto &hwnd : GRAPHICS_WINDOWS) {
|
||||||
|
ShowWindow(hwnd, SW_FORCEMINIMIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// schedule a worker to terminate the game in 30 seconds in case user can't dismiss UI
|
||||||
|
std::atomic_bool cancel_popup = false;
|
||||||
|
auto worker = std::async(std::launch::async, [&cancel_popup]{
|
||||||
|
for (int ms = 300; ms > 0; ms--) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
if (cancel_popup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
launcher::stop_subsystems();
|
||||||
|
launcher::kill();
|
||||||
|
std::terminate();
|
||||||
|
});
|
||||||
|
|
||||||
|
// MessageBox will block until user presses OK
|
||||||
|
const std::string title = "spice2x (" + to_string(VERSION_STRING_CFG) + ")";
|
||||||
|
MessageBox(
|
||||||
|
nullptr,
|
||||||
|
text.c_str(),
|
||||||
|
title.c_str(),
|
||||||
|
MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
|
||||||
|
|
||||||
|
// cancel the worker since the user acknowledged the popup
|
||||||
|
cancel_popup = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_popup_for_crash() {
|
||||||
|
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 github wiki\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.";
|
||||||
|
show_popup(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_popup_for_fatal_error(std::string message) {
|
||||||
|
std::string text;
|
||||||
|
text += "A fatal error was encountered. For details, check log.txt.\n\n";
|
||||||
|
text += "----------------------------------------------------------\n";
|
||||||
|
text += message;
|
||||||
|
text += "----------------------------------------------------------\n\n";
|
||||||
|
text += "Unsure what to do next?\n";
|
||||||
|
text += " * update spice2x to the latest version\n";
|
||||||
|
text += " * check the FAQ on spice2x github wiki\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.";
|
||||||
|
show_popup(text);
|
||||||
|
}
|
||||||
@@ -71,20 +71,28 @@ struct fmt::formatter<fmt_hresult> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void show_popup_for_crash();
|
||||||
|
void show_popup_for_fatal_error(std::string message);
|
||||||
|
|
||||||
// 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__)
|
||||||
|
|
||||||
|
#define LOG_FORMAT_POPUP(module, fmt_str, ...) fmt::format(FMT_COMPILE("{}: " fmt_str "\n"), module, ## __VA_ARGS__)
|
||||||
|
|
||||||
#define log_misc(module, format_str, ...) logger::push( \
|
#define log_misc(module, format_str, ...) logger::push( \
|
||||||
LOG_FORMAT("M", module, format_str, ## __VA_ARGS__), logger::Style::GREY)
|
LOG_FORMAT("M", module, format_str, ## __VA_ARGS__), logger::Style::GREY)
|
||||||
|
|
||||||
#define log_info(module, format_str, ...) logger::push( \
|
#define log_info(module, format_str, ...) logger::push( \
|
||||||
LOG_FORMAT("I", module, format_str, ## __VA_ARGS__), logger::Style::DEFAULT)
|
LOG_FORMAT("I", module, format_str, ## __VA_ARGS__), logger::Style::DEFAULT)
|
||||||
|
|
||||||
#define log_warning(module, format_str, ...) logger::push( \
|
#define log_warning(module, format_str, ...) logger::push( \
|
||||||
LOG_FORMAT("W", module, format_str, ## __VA_ARGS__), logger::Style::YELLOW)
|
LOG_FORMAT("W", module, format_str, ## __VA_ARGS__), logger::Style::YELLOW)
|
||||||
|
|
||||||
#define log_fatal(module, format_str, ...) { \
|
#define log_fatal(module, format_str, ...) { \
|
||||||
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); \
|
show_popup_for_fatal_error(LOG_FORMAT_POPUP(module, format_str, ## __VA_ARGS__)); \
|
||||||
launcher::stop_subsystems(); \
|
launcher::stop_subsystems(); \
|
||||||
Sleep(10000); \
|
|
||||||
launcher::kill(); \
|
launcher::kill(); \
|
||||||
std::terminate(); \
|
std::terminate(); \
|
||||||
} ((void) 0 )
|
} ((void) 0 )
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class scope_guard {
|
||||||
|
private:
|
||||||
|
std::function<void()> f;
|
||||||
|
public:
|
||||||
|
explicit scope_guard(std::function<void()>&& f) : f(std::move(f)) {}
|
||||||
|
~scope_guard() {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_guard(const scope_guard&) = delete;
|
||||||
|
scope_guard& operator=(const scope_guard&) = delete;
|
||||||
|
|
||||||
|
scope_guard(scope_guard&&) = delete;
|
||||||
|
scope_guard& operator=(scope_guard&&) = delete;
|
||||||
|
};
|
||||||
@@ -283,7 +283,8 @@ static inline std::string get_last_error_string() {
|
|||||||
LPSTR messageBuffer = nullptr;
|
LPSTR messageBuffer = nullptr;
|
||||||
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||||
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||||
nullptr,
|
nullptr,
|
||||||
error,
|
error,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
@@ -292,7 +293,12 @@ static inline std::string get_last_error_string() {
|
|||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
// return as string
|
// return as string
|
||||||
std::string message(messageBuffer, size);
|
std::string message;
|
||||||
|
if (size == 0) {
|
||||||
|
message = fmt::format("(Win32 error {})", error);
|
||||||
|
} else {
|
||||||
|
message = fmt::format("{}(Win32 error {})", messageBuffer, error);
|
||||||
|
}
|
||||||
LocalFree(messageBuffer);
|
LocalFree(messageBuffer);
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
|
|||||||
Reference in New Issue
Block a user