ddr: check for common DLL errors (#355)

## Link to GitHub Issue, if one exists
#345 

## Description of change
Check if the path to codecs directory contains non-ASCII characters, and
display a giant warning. This is to help with troubleshooting, since
registration of xactengine silently fails (creates a bad registry entry)
if the path contains non-ASCII chars.

Log the size of codec DLLs, and log any failures from `regsvr32`.

Detect the case where user specified `-exec gamemdx.dll` for DDR which
seems to be a common pitfall. This doesn't work because gamemdx.dll does
not have a DLL entry, but for some reason people are really tempted to
do this.

## Testing
Validated the error cases.
This commit is contained in:
bicarus-dev
2025-08-18 00:00:38 -07:00
committed by GitHub
parent 5c7ad0d51e
commit 1dfcf8c087
2 changed files with 54 additions and 6 deletions
+18 -2
View File
@@ -80,7 +80,7 @@ namespace avs {
if (130 <= dll_path_s.length()) { if (130 <= dll_path_s.length()) {
log_warning( log_warning(
"avs-game", "avs-game",
"PATH TOO LONG WARNING\n\n\n" "PATH TOO LONG WARNING\n\n"
"-------------------------------------------------------------------\n" "-------------------------------------------------------------------\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n" "WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
@@ -95,10 +95,26 @@ namespace avs {
"-------------------------------------------------------------------\n\n", "-------------------------------------------------------------------\n\n",
dll_path_s, dll_path_s.length()); dll_path_s, dll_path_s.length());
} }
// ddr gamemdx.dll user error
if (avs::game::is_model("MDX") && DLL_NAME == "gamemdx.dll") {
log_fatal(
"ddr",
"BAD GAME DLL ERROR\n\n"
"!!! !!!\n"
"!!! -exec gamemdx.dll was specified !!!\n"
"!!! this is the wrong DLL; the game will not load !!!\n"
"!!! remove -exec argument and try again. !!!\n"
"!!! !!!\n"
);
}
// file not found on disk
if (!fileutils::file_exists(dll_path)) { if (!fileutils::file_exists(dll_path)) {
log_warning("avs-game", "game DLL could not be found on disk: {}", dll_path.string().c_str()); log_warning("avs-game", "game DLL could not be found on disk: {}", dll_path.string().c_str());
log_warning("avs-game", "double check -exec and -modules parameters; unless you know what you're doing, leave them blank"); log_warning("avs-game", "double check -exec and -modules parameters; unless you know what you're doing, leave them blank");
} }
if (fileutils::verify_header_pe(dll_path)) { if (fileutils::verify_header_pe(dll_path)) {
DLL_INSTANCE = libutils::load_library(dll_path); DLL_INSTANCE = libutils::load_library(dll_path);
} }
@@ -106,7 +122,7 @@ namespace avs {
// load entry points // load entry points
dll_entry_init = (ENTRY_INIT_T) libutils::get_proc(DLL_INSTANCE, ENTRY_INIT_NAME); dll_entry_init = (ENTRY_INIT_T) libutils::get_proc(DLL_INSTANCE, ENTRY_INIT_NAME);
dll_entry_main = (ENTRY_MAIN_T) libutils::get_proc(DLL_INSTANCE, ENTRY_MAIN_NAME); dll_entry_main = (ENTRY_MAIN_T) libutils::get_proc(DLL_INSTANCE, ENTRY_MAIN_NAME);
log_info("avs-game", "loaded successfully ({})", fmt::ptr(DLL_INSTANCE)); log_info("avs-game", "loaded {} successfully ({})", DLL_NAME, fmt::ptr(DLL_INSTANCE));
} }
bool entry_init(char *sid_code, void *app_param) { bool entry_init(char *sid_code, void *app_param) {
+36 -4
View File
@@ -50,6 +50,15 @@ namespace games::ddr {
return SendMessage_real(hWnd, Msg, wParam, lParam); return SendMessage_real(hWnd, Msg, wParam, lParam);
} }
bool contains_only_ascii(const std::string& str) {
for (auto c: str) {
if (static_cast<unsigned char>(c) > 127) {
return false;
}
}
return true;
}
DDRGame::DDRGame() : Game("Dance Dance Revolution") { DDRGame::DDRGame() : Game("Dance Dance Revolution") {
} }
@@ -82,7 +91,7 @@ namespace games::ddr {
continue; continue;
} }
log_info("ddr", "found DLL: {}", filename.string()); log_info("ddr", "found DLL: {}, size: {} bytes", filename.string(), file.file_size());
if (filename == "k-clvsd.dll" || filename.string().find("xactengine") == 0) { if (filename == "k-clvsd.dll" || filename.string().find("xactengine") == 0) {
const std::wstring wcmd = L"regsvr32.exe /s \"" + file.path().wstring() + L"\""; const std::wstring wcmd = L"regsvr32.exe /s \"" + file.path().wstring() + L"\"";
const std::string cmd = "regsvr32.exe /s \"" + file.path().string() + "\""; const std::string cmd = "regsvr32.exe /s \"" + file.path().string() + "\"";
@@ -92,7 +101,23 @@ namespace games::ddr {
result = _wsystem(wcmd.c_str()); result = _wsystem(wcmd.c_str());
}); });
t.join(); t.join();
log_info("ddr", "`{}` returned {}", cmd, result);
if (result == 0) {
log_info("ddr", "`{}` returned {}", cmd, result);
} else {
log_warning("ddr", "`{}` failed, returned {}", cmd, result);
}
if (!contains_only_ascii(file.path().string())) {
log_warning(
"ddr",
"BAD PATH ERROR\n\n\n"
"!!! !!!\n"
"!!! filesystem path to codec contains non-ASCII characters! !!!\n"
"!!! this may cause the game to crash! !!!\n"
"!!! !!!\n"
);
}
} }
} }
} }
@@ -134,8 +159,15 @@ namespace games::ddr {
); );
} }
if (!cfg::CONFIGURATOR_STANDALONE && !NO_CODEC_REGISTRATION) { if (!cfg::CONFIGURATOR_STANDALONE) {
this->register_codecs(); if (!NO_CODEC_REGISTRATION) {
this->register_codecs();
} else {
log_warning(
"ddr",
"skipping codec registration (-ddrnocodec), "
"game may crash if you didn't register codecs before launching the game");
}
} }
} }