Files
spice2x.github.io/src/spice2x/avs/game.cpp
T
bicarus-dev 98bc285d98 logger: show message popup for log_fatal (#412)
## Link to GitHub Issue, if one exists
#410 

## Description of change
When raising fatal errors via `log_fatal`, also show a modal popup.

Update instances of `log_fatal` where the message was too long to fit.

## Testing
Tested various failure conditions.
2025-11-01 13:41:58 -07:00

154 lines
5.8 KiB
C++

#include "game.h"
#include "launcher/launcher.h"
#include "util/fileutils.h"
#include "util/libutils.h"
#include "util/logging.h"
namespace avs {
namespace game {
// function names
const char ENTRY_INIT_NAME[] = "dll_entry_init";
const char ENTRY_MAIN_NAME[] = "dll_entry_main";
// functions
typedef bool (*ENTRY_INIT_T)(char *, void *);
typedef void (*ENTRY_MAIN_T)(void);
ENTRY_INIT_T dll_entry_init;
ENTRY_MAIN_T dll_entry_main;
// properties
char MODEL[4] = {'0', '0', '0', '\x00'};
char DEST[2] = {'0', '\x00'};
char SPEC[2] = {'0', '\x00'};
char REV[2] = {'0', '\x00'};
char EXT[11] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '\x00'};
// handle
HINSTANCE DLL_INSTANCE;
std::string DLL_NAME;
bool is_model(const char *model) {
return _stricmp(MODEL, model) == 0;
}
bool is_model(const char *model, const char *ext) {
return is_model(model) && is_ext(ext);
}
bool is_model(const std::initializer_list<const char *> model_list) {
for (auto &model : model_list) {
if (is_model(model)) {
return true;
}
}
return false;
}
bool is_ext(const char *ext) {
return _stricmp(EXT, ext) == 0;
}
bool is_ext(int datecode_min, int datecode_max) {
// range check
long datecode = strtol(EXT, NULL, 10);
return datecode_min <= datecode && datecode <= datecode_max;
}
std::string get_identifier() {
return fmt::format("{}:{}:{}:{}:{}",
avs::game::MODEL,
avs::game::DEST,
avs::game::SPEC,
avs::game::REV,
avs::game::EXT);
}
void load_dll() {
log_info("avs-game", "loading DLL '{}'", DLL_NAME);
// load game instance
const auto dll_path = MODULE_PATH / DLL_NAME;
const auto dll_path_s = dll_path.string();
log_info("avs-game", "DLL path: {}", dll_path_s.c_str());
// MAX_PATH is 260
if (130 <= dll_path_s.length()) {
log_warning(
"avs-game",
"PATH TOO LONG WARNING\n\n"
"-------------------------------------------------------------------\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
" PATH TOO LONG \n"
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
"The path '{}'\n"
" has a length of {}\n"
"Most of these games may behave unexpectedly when the path is too\n"
"long, often resulting in random crashes. Move the game contents to\n"
"a directory with shorter path.\n"
"-------------------------------------------------------------------\n\n",
dll_path_s, dll_path_s.length());
}
// ddr gamemdx.dll user error
if (avs::game::is_model("MDX") && DLL_NAME == "gamemdx.dll") {
log_warning(
"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"
);
log_fatal("ddr", "BAD GAME DLL ERROR (don't use -exec gamemdx.dll, that's the wrong DLL)");
}
// file not found on disk
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", "double check -exec and -modules parameters; unless you know what you're doing, leave them blank");
}
if (fileutils::verify_header_pe(dll_path)) {
DLL_INSTANCE = libutils::load_library(dll_path);
}
// load entry points
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);
log_info("avs-game", "loaded {} successfully ({})", DLL_NAME, fmt::ptr(DLL_INSTANCE));
}
bool entry_init(char *sid_code, void *app_param) {
auto current_entry_init = (ENTRY_INIT_T) libutils::get_proc(DLL_INSTANCE, ENTRY_INIT_NAME);
if (dll_entry_init != current_entry_init) {
log_info("avs-game", "dll_entry_init is hooked");
dll_entry_init = current_entry_init;
}
return dll_entry_init(sid_code, app_param);
}
void entry_main() {
auto current_entry_main = (ENTRY_MAIN_T) libutils::get_proc(DLL_INSTANCE, ENTRY_MAIN_NAME);
if (dll_entry_main != current_entry_main) {
log_info("avs-game", "dll_entry_main is hooked");
dll_entry_main = current_entry_main;
}
dll_entry_main();
}
}
}