diff --git a/src/common.h b/src/common.h index c07252f..09a1d32 100644 --- a/src/common.h +++ b/src/common.h @@ -36,6 +36,8 @@ typedef int32_t int32; SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) #define NOTICE SDL_Log +[[noreturn]] void sys_error(const char* format, ...); + #ifndef WIN32 #define _MAX_PATH PATH_MAX diff --git a/src/sdlmain.cpp b/src/sdlmain.cpp index 321b6d5..196af19 100644 --- a/src/sdlmain.cpp +++ b/src/sdlmain.cpp @@ -119,6 +119,16 @@ int main(int argc, char *argv[]) return exit_code; } +[[noreturn]] void sys_error(const char* format, ...) { + char buf[512]; + va_list args; + va_start(args, format); + vsnprintf(buf, sizeof buf, format, args); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Fatal Error: %s", buf); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3", buf, g_window); + exit(1); +} + #ifdef __EMSCRIPTEN__ extern "C" diff --git a/src/sys/ags.cpp b/src/sys/ags.cpp index 91ec1e8..8993be5 100644 --- a/src/sys/ags.cpp +++ b/src/sys/ags.cpp @@ -100,11 +100,11 @@ AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false) if (!config.font_file.empty()) { rw_font = open_file(config.font_file.c_str()); if (!rw_font) - parent->fatal("Cannot open font file %s", config.font_file.c_str()); + sys_error("Cannot open font file %s", config.font_file.c_str()); } else { rw_font = open_resource(FONT_RESOURCE_NAME, "fonts"); if (!rw_font) - parent->fatal("Cannot open default font"); + sys_error("Cannot open default font"); } hFont16 = TTF_OpenFontRW(rw_font, 0, 16); SDL_RWseek(rw_font, 0, SEEK_SET); @@ -116,7 +116,7 @@ AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false) SDL_RWseek(rw_font, 0, SEEK_SET); hFont64 = TTF_OpenFontRW(rw_font, 0, 64); if (!hFont16 || !hFont24 || !hFont32 || !hFont48 || !hFont64) { - parent->fatal("TTF_OpenFontRW failed: %s", TTF_GetError()); + sys_error("TTF_OpenFontRW failed: %s", TTF_GetError()); } if (config.no_antialias) ags_setAntialiasedStringMode(0); diff --git a/src/sys/nact.cpp b/src/sys/nact.cpp index 7367c69..68c71ea 100644 --- a/src/sys/nact.cpp +++ b/src/sys/nact.cpp @@ -37,7 +37,7 @@ NACT::NACT(int sys_ver, uint32 crc32_a, uint32 crc32_b, const Config& config) char string[MAX_CAPTION]; fio->ag00_gets(string, MAX_CAPTION); if (sscanf_s(string, "%d,%d,%d,%d", &d0, &d1, &d2, &d3) != 4) - fatal("AG00.DAT: parse error"); + sys_error("AG00.DAT: parse error"); for(int i = 0; i < d1; i++) { // 動詞の読み込み fio->ag00_gets(string, MAX_CAPTION); @@ -151,7 +151,7 @@ EMSCRIPTEN_KEEPALIVE // Prevent inlining, because this function is listed in AS void NACT::execute() { if (!sco.is_addr_valid()) { - fatal("Scenario error: invalid address %d:0x%x", sco.page(), sco.addr()); + sys_error("Scenario error: invalid address %d:0x%x", sco.page(), sco.addr()); return; } @@ -293,9 +293,9 @@ void NACT::execute() sco.ungetd(); message(0); } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); + sys_error("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); + sys_error("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); } break; } @@ -502,16 +502,6 @@ void NACT::select_cursor() ags->select_cursor(); } -[[noreturn]] void NACT::fatal(const char* format, ...) { - char buf[512]; - va_list args; - va_start(args, format); - vsnprintf(buf, sizeof buf, format, args); - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Fatal Error: %s", buf); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3", buf, g_window); - exit(1); -} - NACT* NACT::create(const Config& config) { uint32 crc32_a = NACT::calc_crc32("ADISK.DAT", config.game_id); uint32 crc32_b = NACT::calc_crc32("BDISK.DAT", config.game_id); diff --git a/src/sys/nact.h b/src/sys/nact.h index 74f4e5f..01ae4e2 100644 --- a/src/sys/nact.h +++ b/src/sys/nact.h @@ -275,8 +275,6 @@ public: int get_scenario_page() const { return sco.page(); } - [[noreturn]] void fatal(const char* msg, ...); - private: void pump_events(); bool handle_platform_event(const SDL_Event& e); diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp index ea4c279..e80999e 100644 --- a/src/sys/nact_sys1.cpp +++ b/src/sys/nact_sys1.cpp @@ -222,9 +222,9 @@ void NACT_Sys1::cmd_branch() sco.ungetd(); sco.skip(encoding->mblen(sco.ptr())); } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); + sys_error("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); + sys_error("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); } } } @@ -605,19 +605,19 @@ void NACT_Sys1::cmd_a() void NACT_Sys1::cmd_b() { // 未使用 - fatal("Unknown Command: 'B' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'B' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_d() { // 未使用 - fatal("Unknown Command: 'D' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'D' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_e() { // 未使用 - fatal("Unknown Command: 'E' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'E' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_f() @@ -655,25 +655,25 @@ void NACT_Sys1::cmd_g() void NACT_Sys1::cmd_h() { // 未使用 - fatal("Unknown Command: 'H' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'H' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_i() { // 未使用 - fatal("Unknown Command: 'I' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'I' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_j() { // 未使用 - fatal("Unknown Command: 'J' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'J' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_k() { // 未使用 - fatal("Unknown Command: 'K' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'K' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_l() @@ -777,19 +777,19 @@ void NACT_Sys1::cmd_l() void NACT_Sys1::cmd_m() { // 未使用 - fatal("Unknown Command: 'M' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'M' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_n() { // 未使用 - fatal("Unknown Command: 'N' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'N' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_o() { // 未使用 - fatal("Unknown Command: 'O' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'O' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_p() @@ -925,7 +925,7 @@ void NACT_Sys1::cmd_s() void NACT_Sys1::cmd_t() { // 未使用 - fatal("Unknown Command: 'T' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'T' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_u() @@ -949,13 +949,13 @@ void NACT_Sys1::cmd_u() void NACT_Sys1::cmd_v() { // 未使用 - fatal("Unknown Command: 'V' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'V' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_w() { // 未使用 - fatal("Unknown Command: 'W' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'W' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_x() @@ -1353,7 +1353,7 @@ uint16 NACT_Sys1::cali() } } if (!ok) { - fatal("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1368,10 +1368,10 @@ uint16 NACT_Sys1::cali2() } else if(0xc0 <= dat && dat <= 0xff) { val = ((dat & 0x3f) << 8) | sco.getd(); } else { - fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } if (sco.getd() != 0x7f) { - fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } return val; } diff --git a/src/sys/nact_sys2.cpp b/src/sys/nact_sys2.cpp index 859f6df..348e693 100644 --- a/src/sys/nact_sys2.cpp +++ b/src/sys/nact_sys2.cpp @@ -260,9 +260,9 @@ void NACT_Sys2::cmd_branch() sco.ungetd(); sco.skip(encoding->mblen(sco.ptr())); } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); + sys_error("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); + sys_error("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); } } } @@ -1327,7 +1327,7 @@ uint16 NACT_Sys2::cali() } } if (!ok) { - fatal("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1342,10 +1342,10 @@ uint16 NACT_Sys2::cali2() } else if(0xc0 <= dat && dat <= 0xff) { val = ((dat & 0x3f) << 8) | sco.getd(); } else { - fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } if (sco.getd() != 0x7f) { - fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } return val; } diff --git a/src/sys/nact_sys3.cpp b/src/sys/nact_sys3.cpp index 2285f03..07716b8 100644 --- a/src/sys/nact_sys3.cpp +++ b/src/sys/nact_sys3.cpp @@ -386,7 +386,7 @@ void NACT_Sys3::cmd_b() void NACT_Sys3::cmd_d() { // 未使用 - fatal("Unknown Command: 'D' at page = %d, addr = %d", sco.page(), prev_addr); + sys_error("Unknown Command: 'D' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys3::cmd_e() @@ -1488,7 +1488,7 @@ uint16 NACT_Sys3::cali() } } if (!ok) { - fatal("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1503,10 +1503,10 @@ uint16 NACT_Sys3::cali2() } else if(0xc0 <= dat && dat <= 0xff) { val = ((dat & 0x3f) << 8) | sco.getd(); } else { - fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } if (sco.getd() != 0x7f) { - fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } return val; } diff --git a/src/sys/scenario.cpp b/src/sys/scenario.cpp index 73d2b42..9a70aae 100644 --- a/src/sys/scenario.cpp +++ b/src/sys/scenario.cpp @@ -1,5 +1,6 @@ #include "scenario.h" #include +#include "common.h" #include "encoding.h" void Scenario::skip_string(Encoding *enc, uint8_t terminator) @@ -20,10 +21,10 @@ void Scenario::get_syseng_string(char* buf, int size, Encoding *enc, uint8_t ter if (c != '\\') ungetd(); int len = enc->mblen(ptr()); - if (i + len < size - 1) { - memcpy(&buf[i], ptr(), len); - i += len; - } + if (i + len >= size) + sys_error("String buffer overrun at %d:0x%x", page(), start_addr); + memcpy(&buf[i], ptr(), len); + i += len; skip(len); } buf[i] = '\0'; diff --git a/src/win/mako.cpp b/src/win/mako.cpp index ca72cd5..8015789 100644 --- a/src/win/mako.cpp +++ b/src/win/mako.cpp @@ -52,7 +52,7 @@ class MCIThread { public: MCIThread(NACT* nact, HWND hwnd_notify) : hwnd_notify(hwnd_notify) { if (!_beginthreadex(NULL, 0, &MCIThread::run, this, 0, &thread_id)) - nact->fatal("Cannot create thread: %s", strerror(errno)); + sys_error("Cannot create thread: %s", strerror(errno)); } bool post_message(UINT msg, WPARAM wparam, LPARAM lparam) { @@ -235,7 +235,7 @@ MAKO::MAKO(NACT* parent, const Config& config) : SDL_SysWMinfo info; SDL_VERSION(&info.version); if (!SDL_GetWindowWMInfo(g_window, &info)) - parent->fatal("SDL_GetWindowWMInfo failed: %s", SDL_GetError()); + sys_error("SDL_GetWindowWMInfo failed: %s", SDL_GetError()); mci_thread = new MCIThread(parent, info.info.win.window); midi = std::make_unique(config.midi_device);