Compare commits

..

5 Commits

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

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

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

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

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

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

## Description of change
Fix font loading - when the code was refactored in #286 I used the wrong
file extension for couple of them.
2025-10-20 00:53:28 -07:00
11 changed files with 95 additions and 27 deletions
+4 -9
View File
@@ -49,7 +49,7 @@ BUILDDIR_64_RELEASE="./cmake-build-release-64"
BUILDDIR_64_DEBUG="./cmake-build-debug-64"
DEBUG=0
OUTDIR="./bin/spice2x"
OUTDIR_EXTRAS="./bin/spice2x_extras"
OUTDIR_EXTRAS="./bin/spice2x/extras"
# disabled UPX since it tends to falsely trigger malware detection
UPX_ENABLE=0
@@ -60,8 +60,8 @@ INCLUDE_SRC=1
DIST_ENABLE=1
DIST_FOLDER="./dist"
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_NAME_EXTRAS="spice2x-$(date +%y)-$(date +%m)-$(date +%d)-extras.zip"
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 spicetools_spice64_linux"
@@ -231,14 +231,11 @@ fi
# pack source files to output directory
rm -rf ${OUTDIR}/src
mkdir -p ${OUTDIR}/src
rm -rf ${OUTDIR_EXTRAS}/src
mkdir -p ${OUTDIR_EXTRAS}/src
if ((INCLUDE_SRC > 0))
then
echo "Generating source file archive..."
git archive --format tar.gz --prefix=spice2x/ HEAD ./ > ${OUTDIR}/src/spice2x-${GIT_BRANCH}.tar.gz 2>/dev/null || \
echo "WARNING: Couldn't get git to create the archive. Is this a git repository?"
cp -r ${OUTDIR}/src/* ${OUTDIR_EXTRAS}/src
fi
# copy resources
@@ -254,11 +251,9 @@ then
mkdir -p ${DIST_FOLDER}
rm -rf ${DIST_FOLDER}/${DIST_NAME}
pushd ${OUTDIR}/.. > /dev/null
zip -qrXT9 $OLDPWD/${DIST_FOLDER}/${DIST_NAME} spice2x -z <<< "$DIST_COMMENT"
popd > /dev/null
zip -qrXT9 $OLDPWD/${DIST_FOLDER}/${DIST_NAME} spice2x -x "spice2x/extras/*" -z <<< "$DIST_COMMENT"
echo "Building extras..."
pushd ${OUTDIR_EXTRAS}/.. > /dev/null
zip -qrXT9 $OLDPWD/${DIST_FOLDER}/${DIST_NAME_EXTRAS} spice2x_extras -z <<< "$DIST_COMMENT"
zip -qrXT9 $OLDPWD/${DIST_FOLDER}/${DIST_NAME_EXTRAS} spice2x -z <<< "$DIST_COMMENT"
popd > /dev/null
fi
-8
View File
@@ -405,14 +405,6 @@ namespace games::iidx {
// init cfgmgr32 hooks
cfgmgr32hook_init(avs::game::DLL_INSTANCE);
// report common errors on iidx31 and above
if (avs::game::is_ext(2023091500, MAXINT) && GRAPHICS_9_ON_12_STATE == DX9ON12_FORCE_ON) {
deferredlogs::defer_error_messages({
"common incompatibility with DX 9on12 + IIDX 31 and above",
" IIDX31+ is known to be incompatible with DX 9on12, leading to blank screen or crashes"
});
}
}
void IIDXGame::pre_attach() {
@@ -238,14 +238,17 @@ static void log_create_device_failure(HRESULT hresult) {
}
static bool is_dx9_on_12_enabled() {
bool result = false;
switch (GRAPHICS_9_ON_12_STATE) {
case DX9ON12_FORCE_OFF:
log_info("graphics::d3d9", "DirectX 9on12: forced OFF by user (-dx9on12)");
return false;
result = false;
break;
case DX9ON12_FORCE_ON:
log_info("graphics::d3d9", "DirectX 9on12: forced ON by user (-9on12 or -dx9on12)");
return true;
result = true;
break;
case DX9ON12_AUTO:
default:
@@ -253,14 +256,33 @@ static bool is_dx9_on_12_enabled() {
log_info(
"graphics::d3d9",
"DirectX 9on12: enabled automatically for current game (tip: use -dx9on12 to force on or off)");
return true;
result = true;
} else {
log_info(
"graphics::d3d9",
"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) {
+9
View File
@@ -946,6 +946,11 @@ int main_implementation(int argc, char *argv[]) {
}
if (options[launcher::Options::DisableAudioHooks].value_bool()) {
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()) {
hooks::audio::VOLUME_HOOK_ENABLED = false;
@@ -1226,6 +1231,10 @@ int main_implementation(int argc, char *argv[]) {
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
std::ostringstream arguments;
for (auto &root_option : options) {
+13
View File
@@ -1,5 +1,6 @@
#include "signal.h"
#include <future>
#include <exception>
#include <windows.h>
@@ -174,6 +175,18 @@ static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *Exception
log_warning("signal", "minidump creation function not available, skipping");
}
// reduce sleep time since we will wait for the user to acknowledge the popup
LOG_FATAL_SLEEP = 1;
// in 30 seconds, shut down (in case user can't dismiss popup)
const auto f = std::async(std::launch::async, [] {
std::this_thread::sleep_for(std::chrono::seconds(30));
log_fatal("signal", "end");
});
// this will stall all UI threads for this process
deferredlogs::show_popup_for_crash();
log_fatal("signal", "end");
}
+4 -3
View File
@@ -270,13 +270,14 @@ void overlay::SpiceOverlay::init() {
ImFontConfig config {};
config.MergeMode = true;
log_misc("overlay", "loading fonts, failures are not fatal");
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("meiryo.ttc", &config, io.Fonts->GetGlyphRangesJapanese());
add_font("gulim.ttc", &config, io.Fonts->GetGlyphRangesKorean());
add_font("cordia.ttc", &config, io.Fonts->GetGlyphRangesThai());
add_font("arial.ttc", &config, io.Fonts->GetGlyphRangesVietnamese());
add_font("cordia.ttf", &config, io.Fonts->GetGlyphRangesThai());
add_font("arial.ttf", &config, io.Fonts->GetGlyphRangesVietnamese());
// add special font
if (avs::game::is_model("LDJ")) {
+12 -2
View File
@@ -556,9 +556,16 @@ namespace overlay::windows {
}
// disclaimer
// note: distribution of modified version of this software without providing source is GPLv3 license violation.
ImGui::TextColored(
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) {
@@ -2917,7 +2924,7 @@ namespace overlay::windows {
#endif
ImGui::TextUnformatted("");
if (ImGui::Button(PROJECT_URL)) {
if (ImGui::TextLink(PROJECT_URL)) {
launch_shell(PROJECT_URL);
}
@@ -2978,6 +2985,7 @@ namespace overlay::windows {
void Config::build_menu(int *game_selected) {
bool about_popup = false;
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 1.0f));
if (ImGui::BeginMenuBar()) {
// [spice2x]
@@ -3038,6 +3046,8 @@ namespace overlay::windows {
ImGui::EndMenuBar();
}
ImGui::PopStyleColor(); // ImGuiCol_PopupBg
// workaround for popups triggered by menu, see https://github.com/ocornut/imgui/issues/331
if (about_popup) {
ImGui::OpenPopup("About##topbarpopup");
+21
View File
@@ -72,4 +72,25 @@ namespace deferredlogs {
log_warning("troubleshooter", "{}", msg);
});
}
void show_popup_for_crash() {
static std::once_flag shown;
std::call_once(shown, []() {
const std::string title = "spice2x (" + to_string(VERSION_STRING_CFG) + ") - crash handler";
std::string text;
text += "Game has crashed.\n\n";
text += "Check log.txt and look for error messages near the end of file.\n\n";
text += "Unsure what to do next?\n";
text += " * update spice2x to the latest version\n";
text += " * check the FAQ on spice2x wiki on github\n";
text += " * do NOT screenshot this, instead, share log.txt with someone and ask for help\n\n";
text += "Press Enter, Esc, Alt+F4, or click OK to exit. Otherwise, game will close in 30 seconds.";
MessageBox(
nullptr,
text.c_str(),
title.c_str(),
MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
});
}
}
+1
View File
@@ -11,4 +11,5 @@ namespace deferredlogs {
void defer_error_messages(std::initializer_list<std::string> messages);
void dump_to_logger(bool is_crash=false);
void show_popup_for_crash();
}
+2
View File
@@ -1,5 +1,7 @@
#include "logging.h"
DWORD LOG_FATAL_SLEEP = 10000;
std::string_view log_get_datetime() {
return log_get_datetime(time(nullptr));
}
+3 -1
View File
@@ -71,6 +71,8 @@ struct fmt::formatter<fmt_hresult> {
}
};
extern DWORD LOG_FATAL_SLEEP;
// misc log
#define LOG_FORMAT(level, module, fmt_str, ...) fmt::format(FMT_COMPILE("{}" fmt_str "\n"), \
fmt_log { std::time(nullptr), level, module }, ## __VA_ARGS__)
@@ -84,7 +86,7 @@ struct fmt::formatter<fmt_hresult> {
logger::push(LOG_FORMAT("F", module, format_str, ## __VA_ARGS__), logger::Style::RED); \
logger::push(LOG_FORMAT("F", "spice", "encountered a fatal error, you can close the window or press ctrl + c"), logger::Style::RED); \
launcher::stop_subsystems(); \
Sleep(10000); \
Sleep(LOG_FATAL_SLEEP); \
launcher::kill(); \
std::terminate(); \
} ((void) 0 )