diff --git a/src/sys/nact.cpp b/src/sys/nact.cpp index 10784b6..708feed 100644 --- a/src/sys/nact.cpp +++ b/src/sys/nact.cpp @@ -117,20 +117,12 @@ void NACT::quit(int code) EMSCRIPTEN_KEEPALIVE // Prevent inlining, because this function is listed in ASYNCIFY_ADD void NACT::execute() { - if (!sco.is_addr_valid()) { - sys_error("Scenario error: invalid address %d:0x%x", sco.page(), sco.addr()); - return; - } - - if (game_id.sys_ver == 1 && sco.page() == 0 && sco.addr() == 2) { + if (game_id.sys_ver == 1 && sco.page() == 0 && sco.current_addr() == 2) { opening(); } - sco.skip_syseng_rev_marker(); - // 1コマンド実行 - sco.mark_cmd_start(); - uint8 cmd = sco.getd(); + uint8 cmd = sco.fetch_command(); if(set_palette && cmd != 'P') { // パレット設定が終わった @@ -323,7 +315,7 @@ void NACT::message(uint8 terminator) } } if (!ags->draw_menu) - msgskip->on_message(sco.page(), sco.addr()); + msgskip->on_message(sco.page(), sco.current_addr()); // TODO: Convert hankaku to zenkaku output_console(buf); diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp index 0a91494..9e93257 100644 --- a/src/sys/nact_sys1.cpp +++ b/src/sys/nact_sys1.cpp @@ -145,8 +145,7 @@ void NACT_Sys1::cmd_branch() if(!condition) { // 次の'}'命令までスキップする(ネストも考慮する) for(;;) { - sco.mark_cmd_start(); - uint8 cmd = sco.getd(); + uint8 cmd = sco.fetch_command(); if(cmd == '!') { int index = sco.getd(); @@ -785,7 +784,7 @@ void NACT_Sys1::cmd_q() FPUTW(0); FPUTW(mako->current_music); FPUTW(0); - FPUTW(sco.addr()); + FPUTW(sco.current_addr()); FPUTW(0); for(int i = 0; i < 512; i++) { FPUTW(var[i]); @@ -1294,7 +1293,7 @@ uint16 NACT_Sys1::cali() } } if (!ok) { - sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1309,10 +1308,10 @@ uint16 NACT_Sys1::cali2() } else if(0xc0 <= dat && dat <= 0xff) { val = ((dat & 0x3f) << 8) | sco.getd(); } else { - sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } if (sco.getd() != 0x7f) { - sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } return val; } diff --git a/src/sys/nact_sys2.cpp b/src/sys/nact_sys2.cpp index c1cfb4a..48f8854 100644 --- a/src/sys/nact_sys2.cpp +++ b/src/sys/nact_sys2.cpp @@ -80,8 +80,7 @@ void NACT_Sys2::cmd_branch() if(!condition) { // 次の'}'命令までスキップする(ネストも考慮する) for(;;) { - sco.mark_cmd_start(); - uint8 cmd = sco.getd(); + uint8 cmd = sco.fetch_command(); if(cmd == '!') { int index = sco.getd(); @@ -870,7 +869,7 @@ void NACT_Sys2::cmd_q() FPUTW(0); FPUTW(mako->current_music); FPUTW(0); - FPUTW(sco.addr()); + FPUTW(sco.current_addr()); FPUTW(0); for(int i = 0; i < 512; i++) { FPUTW(var[i]); @@ -1263,7 +1262,7 @@ uint16 NACT_Sys2::cali() } } if (!ok) { - sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1278,10 +1277,10 @@ uint16 NACT_Sys2::cali2() } else if(0xc0 <= dat && dat <= 0xff) { val = ((dat & 0x3f) << 8) | sco.getd(); } else { - sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } if (sco.getd() != 0x7f) { - sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } return val; } diff --git a/src/sys/nact_sys3.cpp b/src/sys/nact_sys3.cpp index c0c8cd0..48aa7ec 100644 --- a/src/sys/nact_sys3.cpp +++ b/src/sys/nact_sys3.cpp @@ -31,7 +31,7 @@ void NACT_Sys3::cmd_calc() void NACT_Sys3::cmd_branch() { int condition = cali(); - int t_addr = sco.addr() + 2; + int t_addr = sco.current_addr() + 2; int f_addr = sco.getw(); // sigmarion3 最適化誤爆の対策 @@ -823,7 +823,7 @@ void NACT_Sys3::cmd_q() FPUTW(0); FPUTW(mako->current_music); FPUTW(0); - FPUTW(sco.addr()); + FPUTW(sco.current_addr()); FPUTW(0); for(int i = 0; i < 512; i++) { FPUTW(var[i]); @@ -1428,7 +1428,7 @@ uint16 NACT_Sys3::cali() } } if (!ok) { - sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1443,10 +1443,10 @@ uint16 NACT_Sys3::cali2() } else if(0xc0 <= dat && dat <= 0xff) { val = ((dat & 0x3f) << 8) | sco.getd(); } else { - sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } if (sco.getd() != 0x7f) { - sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); + sys_error("cali2: invalid expression at %d:%04x", sco.page(), sco.cmd_addr()); } return val; } diff --git a/src/sys/scenario.cpp b/src/sys/scenario.cpp index 17a7614..c2176cb 100644 --- a/src/sys/scenario.cpp +++ b/src/sys/scenario.cpp @@ -3,6 +3,19 @@ #include "common.h" #include "encoding.h" +uint8_t Scenario::fetch_command() +{ + if (addr_ < 2 || static_cast(addr_) >= data_.size()) + sys_error("Scenario error: invalid address %d:%04x", page_, addr_); + + // Skip SysEng's "new style" marker + if (page_ == 0 && addr_ == 2 && data_[2] == 'R' && data_[3] == 'E' && data_[4] == 'V') + addr_ = 5; + + cmd_addr_ = addr_; + return getd(); +} + void Scenario::skip_syseng_string(Encoding *enc, uint8_t terminator) { for (uint8_t c = getd(); c != terminator; c = getd()) { @@ -14,15 +27,13 @@ void Scenario::skip_syseng_string(Encoding *enc, uint8_t terminator) void Scenario::get_syseng_string(char* buf, int size, Encoding *enc, uint8_t terminator) { - int start_addr = addr_; - int i = 0; for (uint8_t c = getd(); c != terminator; c = getd()) { if (c != '\\') ungetd(); int len = enc->mblen(ptr()); if (i + len >= size) - sys_error("String buffer overrun at %d:0x%x", page_, start_addr); + sys_error("String buffer overrun at %d:%04x", page_, cmd_addr_); memcpy(&buf[i], ptr(), len); i += len; skip(len); @@ -63,8 +74,8 @@ void Scenario::page_call(int target_page) [[noreturn]] void Scenario::unknown_command(uint8_t cmd) { if (cmd >= 0x20 && cmd < 0x7f) { - sys_error("Unknown Command: '%c' at %d:0x%d", cmd, page_, cmd_start_addr); + sys_error("Unknown Command: '%c' at %d:%04x", cmd, page_, cmd_addr_); } else { - sys_error("Unknown Command: %02x at %d:0x%d", cmd, page_, cmd_start_addr); + sys_error("Unknown Command: %02x at %d:%04x", cmd, page_, cmd_addr_); } } \ No newline at end of file diff --git a/src/sys/scenario.h b/src/sys/scenario.h index 3f33101..9f52891 100644 --- a/src/sys/scenario.h +++ b/src/sys/scenario.h @@ -14,7 +14,7 @@ public: void page_jump(int page, int addr) { data_ = adisk.load(page + 1); page_ = page; - addr_ = addr; + cmd_addr_ = addr_ = addr; } size_t size() const { return data_.size(); } uint8_t& operator[](int i) { return data_[i]; } @@ -22,18 +22,16 @@ public: int default_addr() { return data_[0] | data_[1] << 8; } int page() const { return page_; } - int addr() const { return addr_; } - bool is_addr_valid() const { - return addr_ >= 2 && static_cast(addr_) < data_.size(); - } - // Skip SysEng's "new style" marker - void skip_syseng_rev_marker() { - if (page_ == 0 && addr_ == 2 && data_[2] == 'R' && data_[3] == 'E' && data_[4] == 'V') - addr_ = 5; - } + // start address of the current command + int cmd_addr() const { return cmd_addr_; } + // current address, possibly in the middle of a command + int current_addr() const { return addr_; } - void jump_to(int addr) { addr_ = addr; } + void jump_to(int addr) { cmd_addr_ = addr_ = addr; } void skip(int n) { addr_ += n; } + + uint8_t fetch_command(); + uint8_t getd() { return data_[addr_++]; } uint16_t getw() { uint16_t w = data_[addr_++]; @@ -54,7 +52,6 @@ public: void page_stack_pop() { page_stack.pop_back(); } void page_stack_clear() { page_stack.clear(); } - void mark_cmd_start() { cmd_start_addr = addr_; } [[noreturn]] void unknown_command(uint8_t cmd); private: @@ -62,7 +59,7 @@ private: std::vector data_; int page_; int addr_; - int cmd_start_addr; + int cmd_addr_; std::vector label_stack; std::vector> page_stack; };