From 5483d1932fd87aeb237b0392945e07842505d85b Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 8 Dec 2024 22:50:10 +0900 Subject: [PATCH] Introduce Scenario class --- CMakeLists.txt | 1 + src/sys/nact.cpp | 80 +++++-------------- src/sys/nact.h | 20 +---- src/sys/nact_sys1.cpp | 178 ++++++++++++++++++++---------------------- src/sys/nact_sys2.cpp | 170 +++++++++++++++++++--------------------- src/sys/nact_sys3.cpp | 114 +++++++++++++-------------- src/sys/scenario.cpp | 30 +++++++ src/sys/scenario.h | 53 +++++++++++++ 8 files changed, 329 insertions(+), 317 deletions(-) create mode 100644 src/sys/scenario.cpp create mode 100644 src/sys/scenario.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bc4c73..d9b63ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,6 +174,7 @@ target_sources(system3 PRIVATE src/sys/nact_sys1.cpp src/sys/nact_sys2.cpp src/sys/nact_sys3.cpp + src/sys/scenario.cpp ) if(NINTENDO_SWITCH) diff --git a/src/sys/nact.cpp b/src/sys/nact.cpp index 8b97e3a..7367c69 100644 --- a/src/sys/nact.cpp +++ b/src/sys/nact.cpp @@ -53,14 +53,12 @@ NACT::NACT(int sys_ver, uint32 crc32_a, uint32 crc32_b, const Config& config) // ADISK.DAT if (crc32_a == CRC32_PROG_OMAKE) - adisk.open("AGAME.DAT"); + sco.open("AGAME.DAT"); else - adisk.open("ADISK.DAT"); + sco.open("ADISK.DAT"); // シナリオ管理 - load_scenario(0); - scenario_page = 0; - scenario_addr = 2; + sco.page_jump(0, 2); label_depth = page_depth = 0; // 変数初期化 @@ -152,25 +150,20 @@ void NACT::quit(int code) EMSCRIPTEN_KEEPALIVE // Prevent inlining, because this function is listed in ASYNCIFY_ADD void NACT::execute() { - // アドレスの確認 - if (scenario_addr < 2 || scenario_addr >= static_cast(scenario_data.size())) { - fatal("Scenario error"); + if (!sco.is_addr_valid()) { + fatal("Scenario error: invalid address %d:0x%x", sco.page(), sco.addr()); return; } - if(sys_ver == 1 && scenario_page == 0 && scenario_addr == 2) { + if(sys_ver == 1 && sco.page() == 0 && sco.addr() == 2) { opening(); } - // Skip SysEng's "new style" marker - if (scenario_page == 0 && scenario_addr == 2 && - memcmp(&scenario_data[2], "REV", 3) == 0) { - scenario_addr = 5; - } + sco.skip_syseng_rev_marker(); // 1コマンド実行 - prev_addr = scenario_addr; - uint8 cmd = getd(); + prev_addr = sco.addr(); + uint8 cmd = sco.getd(); if(set_palette && cmd != 'P') { // パレット設定が終わった @@ -179,7 +172,7 @@ void NACT::execute() } if(verb_obj && cmd != '[' && cmd != ':') { // 動詞-目的語メニューの表示 - scenario_addr--; + sco.ungetd(); cmd_open_verb(); return; } @@ -297,58 +290,31 @@ void NACT::execute() break; default: if (is_message(cmd)) { - ungetd(); + sco.ungetd(); message(0); } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); + fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); + fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); } break; } } -void NACT::skip_string(uint8 terminator) -{ - for (uint8 c = getd(); c != terminator; c = getd()) { - if (c != '\\') - ungetd(); - scenario_addr += encoding->mblen(&scenario_data[scenario_addr]); - } -} - -void NACT::get_string(char* buf, int size, uint8 terminator) -{ - int start_addr = scenario_addr; - - int i = 0; - for (uint8 c = getd(); c != terminator; c = getd()) { - if (c != '\\') - ungetd(); - int len = encoding->mblen(&scenario_data[scenario_addr]); - if (i + len >= size) - fatal("String buffer overrun. page = %d, addr = %d", scenario_page, start_addr); - memcpy(&buf[i], &scenario_data[scenario_addr], len); - i += len; - scenario_addr += len; - } - buf[i] = '\0'; -} - void NACT::message(uint8 terminator) { char buf[200]; if (terminator) { // SysEng - get_string(buf, sizeof(buf), terminator); + sco.get_syseng_string(buf, sizeof(buf), encoding.get(), terminator); } else { - uint8* begin = &scenario_data[scenario_addr]; - uint8* p = begin; + const uint8* begin = sco.ptr(); + const uint8* p = begin; while (is_message(*p)) p += encoding->mblen(p); int len = p - begin; - scenario_addr += len; + sco.skip(len); - strncpy(buf, reinterpret_cast(begin), len); + strncpy(buf, reinterpret_cast(begin), len); buf[len] = '\0'; } @@ -360,7 +326,7 @@ void NACT::message(uint8 terminator) } } if (!ags->draw_menu) - msgskip->on_message(scenario_page, scenario_addr); + msgskip->on_message(sco.page(), sco.addr()); // TODO: Convert hankaku to zenkaku output_console(buf); @@ -384,14 +350,6 @@ void NACT::text_wait() } } -void NACT::load_scenario(int page) -{ - scenario_data = adisk.load(page + 1); - if (scenario_data.empty()) { - fatal("Cannot load scenario %d", page); - } -} - // 下位関数 int NACT::menu_select(int num_items) diff --git a/src/sys/nact.h b/src/sys/nact.h index dd73504..74f4e5f 100644 --- a/src/sys/nact.h +++ b/src/sys/nact.h @@ -14,6 +14,7 @@ #include "../common.h" #include "config.h" #include "dri.h" +#include "scenario.h" #define RND var[ 0] #define D01 var[ 1] @@ -110,16 +111,12 @@ protected: // コマンドパーサ void execute(); - void load_scenario(int page); - - Dri adisk; // シナリオデータ - std::vector scenario_data; + Scenario sco; // アドレス、ページ管理 - int scenario_addr, prev_addr; - int scenario_page; + int prev_addr; int label_depth; int label_stack[MAX_STACK]; int page_depth; @@ -214,16 +211,7 @@ protected: // 下位関数 virtual uint16 cali() = 0; virtual uint16 cali2() = 0; - uint8 getd() { return scenario_data[scenario_addr++]; } - uint16 getw() { - uint16 val = scenario_data[scenario_addr] | (scenario_data[scenario_addr + 1] << 8); - scenario_addr += 2; - return val; - } - void ungetd() { scenario_addr--; } bool is_message(uint8_t c) { return c == ' ' || c & 0x80; } - void skip_string(uint8 terminator); - void get_string(char* buf, int size, uint8 terminator); uint16 random(uint16 range); uint32 seed; @@ -285,7 +273,7 @@ public: // デバッグログ void output_console(const char *format, ...); - int get_scenario_page() const { return scenario_page; } + int get_scenario_page() const { return sco.page(); } [[noreturn]] void fatal(const char* msg, ...); diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp index db03402..ea4c279 100644 --- a/src/sys/nact_sys1.cpp +++ b/src/sys/nact_sys1.cpp @@ -125,11 +125,11 @@ void NACT_Sys1::opening() void NACT_Sys1::cmd_calc() { - int index = getd(); + int index = sco.getd(); if(0x80 <= index && index <= 0xbf) { index &= 0x3f; } else { - index = ((index & 0x3f) << 8) | getd(); + index = ((index & 0x3f) << 8) | sco.getd(); } var[index] = cali(); @@ -145,13 +145,13 @@ void NACT_Sys1::cmd_branch() if(!condition) { // 次の'}'命令までスキップする(ネストも考慮する) for(;;) { - prev_addr = scenario_addr; - uint8 cmd = getd(); + prev_addr = sco.addr(); + uint8 cmd = sco.getd(); if(cmd == '!') { - int index = getd(); + int index = sco.getd(); if(!(0x80 <= index && index <= 0xbf)) { - getd(); + sco.getd(); } cali(); } else if(cmd == '{') { @@ -164,29 +164,29 @@ void NACT_Sys1::cmd_branch() break; } } else if(cmd == '@') { - getw(); + sco.getw(); } else if(cmd == '\\') { - getw(); + sco.getw(); } else if(cmd == '&') { cali(); } else if(cmd == '%') { cali(); } else if(cmd == '$') { if(!set_menu) { - getw(); + sco.getw(); set_menu = true; } else { set_menu = false; } } else if(cmd == '[') { - getd(); - getd(); - getw(); + sco.getd(); + sco.getd(); + sco.getw(); } else if(cmd == ':') { cali(); - getd(); - getd(); - getw(); + sco.getd(); + sco.getd(); + sco.getw(); } else if(cmd == ']') { } else if(cmd == 'A') { @@ -194,22 +194,22 @@ void NACT_Sys1::cmd_branch() } else if(cmd == 'F') { } else if(cmd == 'G') { - getd(); + sco.getd(); } else if(cmd == 'L') { - getd(); + sco.getd(); } else if(cmd == 'P') { - getd(); + sco.getd(); } else if(cmd == 'Q') { - getd(); + sco.getd(); } else if(cmd == 'R') { } else if(cmd == 'S') { - getd(); + sco.getd(); } else if(cmd == 'U') { - getd(); - getd(); + sco.getd(); + sco.getd(); } else if(cmd == 'X') { - getd(); + sco.getd(); } else if(cmd == 'Y') { cali(); cali(); @@ -217,14 +217,14 @@ void NACT_Sys1::cmd_branch() cali(); cali(); } else if (cmd == '\'' || cmd == '"') { // SysEng - skip_string(cmd); + sco.skip_string(encoding.get(), cmd); } else if (is_message(cmd)) { - ungetd(); - scenario_addr += encoding->mblen(&scenario_data[scenario_addr]); + sco.ungetd(); + sco.skip(encoding->mblen(sco.ptr())); } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); + fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); + fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); } } } @@ -234,15 +234,15 @@ void NACT_Sys1::cmd_branch() void NACT_Sys1::cmd_label_jump() { - int next_addr = getw(); - scenario_addr = next_addr; + int next_addr = sco.getw(); + sco.jump_to(next_addr); output_console("\n@%x:", next_addr); } void NACT_Sys1::cmd_label_call() { - int next_addr = getw(); + int next_addr = sco.getw(); output_console("\n\\%x:", next_addr); @@ -252,19 +252,17 @@ void NACT_Sys1::cmd_label_call() // fatal_error = true; return; } - scenario_addr = label_stack[--label_depth]; + sco.jump_to(label_stack[--label_depth]); } else { - label_stack[label_depth++] = scenario_addr; - scenario_addr = next_addr; + label_stack[label_depth++] = sco.addr(); + sco.jump_to(next_addr); } } void NACT_Sys1::cmd_page_jump() { int next_page = cali(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = 2; + sco.page_jump(next_page, 2); output_console("\n&%d:", next_page); } @@ -284,13 +282,11 @@ void NACT_Sys1::cmd_page_call() next_page = page_stack[--page_depth]; next_addr = addr_stack[page_depth]; } else { - page_stack[page_depth] = scenario_page; - addr_stack[page_depth++] = scenario_addr; + page_stack[page_depth] = sco.page(); + addr_stack[page_depth++] = sco.addr(); next_addr = 2; } - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; + sco.page_jump(next_page, next_addr); } void NACT_Sys1::cmd_set_menu() @@ -306,7 +302,7 @@ void NACT_Sys1::cmd_set_menu() ags->clear_menu_window(); ags->menu_dest_y = 0; } - menu_addr[menu_index++] = getw(); + menu_addr[menu_index++] = sco.getw(); ags->menu_dest_x = 2; ags->menu_dest_y += 2; ags->draw_menu = true; @@ -323,7 +319,7 @@ void NACT_Sys1::cmd_open_menu() output_console("\n]"); if(!menu_index) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); return; } @@ -338,16 +334,16 @@ void NACT_Sys1::cmd_open_menu() return; if (selection != -1) { - scenario_addr = menu_addr[selection]; + sco.jump_to(menu_addr[selection]); } menu_index = 0; } void NACT_Sys1::cmd_set_verbobj() { - int verb = getd(); - int obj = getd(); - int addr = getw(); + int verb = sco.getd(); + int obj = sco.getd(); + int addr = sco.getw(); menu_addr[menu_index] = addr; menu_verb[menu_index] = verb; @@ -360,9 +356,9 @@ void NACT_Sys1::cmd_set_verbobj() void NACT_Sys1::cmd_set_verbobj2() { int condition = cali(); - int verb = getd(); - int obj = getd(); - int addr = getw(); + int verb = sco.getd(); + int obj = sco.getd(); + int addr = sco.getw(); if(condition) { menu_addr[menu_index] = addr; @@ -450,7 +446,7 @@ top2: return; if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); } else if(id[selection] == -1) { goto top; } else { @@ -483,12 +479,12 @@ void NACT_Sys1::cmd_open_obj(int verb) } // 目的語がない場合 if(chk[0] && cnt == 1) { - scenario_addr = addr[0]; + sco.jump_to(addr[0]); return; } // 以後、obj=0は戻るとして扱う chk[0] = 0; - addr[0] = scenario_data[0] | (scenario_data[1] << 8); + addr[0] = sco.default_addr(); top: // メニュー項目の準備 @@ -556,11 +552,11 @@ top2: return; if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); } else if(id[selection] == -1) { goto top; } else { - scenario_addr = addr[id[selection]]; + sco.jump_to(addr[id[selection]]); } } @@ -609,31 +605,31 @@ void NACT_Sys1::cmd_a() void NACT_Sys1::cmd_b() { // 未使用 - fatal("Unknown Command: 'B' at page = %d, addr = %d", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("Unknown Command: 'E' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_f() { output_console("\nF"); - scenario_addr = 2; + sco.jump_to(2); } void NACT_Sys1::cmd_g() { - int page = getd(); + int page = sco.getd(); output_console("\nG %d:", page); @@ -659,30 +655,30 @@ void NACT_Sys1::cmd_g() void NACT_Sys1::cmd_h() { // 未使用 - fatal("Unknown Command: 'H' at page = %d, addr = %d", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("Unknown Command: 'K' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_l() { - int index = getd(); + int index = sco.getd(); output_console("\nL %d:", index); @@ -771,9 +767,7 @@ void NACT_Sys1::cmd_l() } fio.reset(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; + sco.page_jump(next_page, next_addr); mako->play_music(next_music); } @@ -783,24 +777,24 @@ void NACT_Sys1::cmd_l() void NACT_Sys1::cmd_m() { // 未使用 - fatal("Unknown Command: 'M' at page = %d, addr = %d", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("Unknown Command: 'O' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_p() { - int param = getd(); + int param = sco.getd(); ags->text_font_color = (uint8)((param & 0x7) + 16); @@ -829,7 +823,7 @@ void NACT_Sys1::cmd_q() '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' }; - int index = getd(); + int index = sco.getd(); output_console("\nQ %d:", index); @@ -844,13 +838,13 @@ void NACT_Sys1::cmd_q() int p = 0; FWRITE(header, 112); - FPUTW(scenario_page + 1); + FPUTW(sco.page() + 1); FPUTW(0); FPUTW(0); // cg no? FPUTW(0); FPUTW(mako->current_music); FPUTW(0); - FPUTW(scenario_addr); + FPUTW(sco.addr()); FPUTW(0); for(int i = 0; i < 512; i++) { FPUTW(var[i]); @@ -917,7 +911,7 @@ void NACT_Sys1::cmd_r() void NACT_Sys1::cmd_s() { - int page = getd(); + int page = sco.getd(); output_console("\nS %d:", page); @@ -931,13 +925,13 @@ void NACT_Sys1::cmd_s() void NACT_Sys1::cmd_t() { // 未使用 - fatal("Unknown Command: 'T' at page = %d, addr = %d", scenario_page, prev_addr); + fatal("Unknown Command: 'T' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_u() { - int page = getd(); - int transparent = getd(); + int page = sco.getd(); + int transparent = sco.getd(); output_console("\nU %d,%d:", page, transparent); @@ -955,18 +949,18 @@ void NACT_Sys1::cmd_u() void NACT_Sys1::cmd_v() { // 未使用 - fatal("Unknown Command: 'V' at page = %d, addr = %d", scenario_page, prev_addr); + fatal("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", scenario_page, prev_addr); + fatal("Unknown Command: 'W' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys1::cmd_x() { - int index = getd(); + int index = sco.getd(); output_console("\nX %d:", index); @@ -1309,15 +1303,15 @@ uint16 NACT_Sys1::cali() bool ok = false; while(p > 0) { - uint8 dat = getd(); + uint8 dat = sco.getd(); // 除算はサポートしない? if(0x80 <= dat && dat <= 0xbf) { cali[p++] = var[dat & 0x3f]; } else if(0xc0 <= dat && dat <= 0xff) { - cali[p++] = var[((dat & 0x3f) << 8) | getd()]; + cali[p++] = var[((dat & 0x3f) << 8) | sco.getd()]; } else if(0x00 <= dat && dat <= 0x3f) { - cali[p++] = ((dat & 0x3f) << 8) | getd(); + cali[p++] = ((dat & 0x3f) << 8) | sco.getd(); } else if(0x40 <= dat && dat <= 0x77) { cali[p++] = dat & 0x3f; } else if(dat == 0x78) { @@ -1359,7 +1353,7 @@ uint16 NACT_Sys1::cali() } } if (!ok) { - fatal("cali: invalid expression at %d:%04x", scenario_page, scenario_addr); + fatal("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1367,17 +1361,17 @@ uint16 NACT_Sys1::cali() uint16 NACT_Sys1::cali2() { uint16 val = 0; - uint16 dat = getd(); + uint16 dat = sco.getd(); if(0x80 <= dat && dat <= 0xbf) { val = dat & 0x3f; } else if(0xc0 <= dat && dat <= 0xff) { - val = ((dat & 0x3f) << 8) | getd(); + val = ((dat & 0x3f) << 8) | sco.getd(); } else { - fatal("cali2: invalid expression at %d:%04x", scenario_page, scenario_addr); + fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } - if(getd() != 0x7f) { - fatal("cali2: invalid expression at %d:%04x", scenario_page, scenario_addr); + if (sco.getd() != 0x7f) { + fatal("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 acf7a16..859f6df 100644 --- a/src/sys/nact_sys2.cpp +++ b/src/sys/nact_sys2.cpp @@ -65,11 +65,11 @@ NACT_Sys2::NACT_Sys2(uint32 crc32_a, uint32 crc32_b, const Config& config) void NACT_Sys2::cmd_calc() { - int index = getd(); + int index = sco.getd(); if(0x80 <= index && index <= 0xbf) { index &= 0x3f; } else { - index = ((index & 0x3f) << 8) | getd(); + index = ((index & 0x3f) << 8) | sco.getd(); } var[index] = cali(); @@ -85,13 +85,13 @@ void NACT_Sys2::cmd_branch() if(!condition) { // 次の'}'命令までスキップする(ネストも考慮する) for(;;) { - prev_addr = scenario_addr; - uint8 cmd = getd(); + prev_addr = sco.addr(); + uint8 cmd = sco.getd(); if(cmd == '!') { - int index = getd(); + int index = sco.getd(); if(!(0x80 <= index && index <= 0xbf)) { - getd(); + sco.getd(); } cali(); } else if(cmd == '{') { @@ -104,29 +104,29 @@ void NACT_Sys2::cmd_branch() break; } } else if(cmd == '@') { - getw(); + sco.getw(); } else if(cmd == '\\') { - getw(); + sco.getw(); } else if(cmd == '&') { cali(); } else if(cmd == '%') { cali(); } else if(cmd == '$') { if(!set_menu) { - getw(); + sco.getw(); set_menu = true; } else { set_menu = false; } } else if(cmd == '[') { - getd(); - getd(); - getw(); + sco.getd(); + sco.getd(); + sco.getw(); } else if(cmd == ':') { cali(); - getd(); - getd(); - getw(); + sco.getd(); + sco.getd(); + sco.getw(); } else if(cmd == ']') { } else if(cmd == 'A') { @@ -157,12 +157,12 @@ void NACT_Sys2::cmd_branch() } else if(cmd == 'G') { cali(); } else if(cmd == 'H') { - getd(); + sco.getd(); cali(); } else if(cmd == 'I') { cali(); cali(); -// getd(); +// sco.getd(); cali(); } else if(cmd == 'J') { cali(); @@ -170,14 +170,14 @@ void NACT_Sys2::cmd_branch() } else if(cmd == 'K') { } else if(cmd == 'L') { - getd(); + sco.getd(); } else if(cmd == 'M') { - uint8 val = getd(); + uint8 val = sco.getd(); if (val == '\'' || val == '"') { // SysEng - skip_string(val); + sco.skip_string(encoding.get(), val); } else { while (val != ':') - val = getd(); + val = sco.getd(); } } else if(cmd == 'N') { cali(); @@ -187,13 +187,13 @@ void NACT_Sys2::cmd_branch() cali(); cali(); } else if(cmd == 'P') { - getd(); + sco.getd(); } else if(cmd == 'Q') { - getd(); + sco.getd(); } else if(cmd == 'R') { } else if(cmd == 'S') { - getd(); + sco.getd(); } else if(cmd == 'T') { cali(); cali(); @@ -203,8 +203,8 @@ void NACT_Sys2::cmd_branch() cali(); cali(); } else { - getd(); - getd(); + sco.getd(); + sco.getd(); } } else if(cmd == 'V') { #if 1 @@ -247,7 +247,7 @@ void NACT_Sys2::cmd_branch() cali(); cali(); } else if(cmd == 'X') { - getd(); + sco.getd(); } else if(cmd == 'Y') { cali(); cali(); @@ -255,14 +255,14 @@ void NACT_Sys2::cmd_branch() cali(); cali(); } else if (cmd == '\'' || cmd == '"') { // SysEng - skip_string(cmd); + sco.skip_string(encoding.get(), cmd); } else if (is_message(cmd)) { - ungetd(); - scenario_addr += encoding->mblen(&scenario_data[scenario_addr]); + sco.ungetd(); + sco.skip(encoding->mblen(sco.ptr())); } else if (cmd >= 0x20 && cmd < 0x7f) { - fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, scenario_page, prev_addr); + fatal("Unknown Command: '%c' at page = %d, addr = %d", cmd, sco.page(), prev_addr); } else { - fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, scenario_page, prev_addr); + fatal("Unknown Command: %02x at page = %d, addr = %d", cmd, sco.page(), prev_addr); } } } @@ -272,15 +272,15 @@ void NACT_Sys2::cmd_branch() void NACT_Sys2::cmd_label_jump() { - int next_addr = getw(); - scenario_addr = next_addr; + int next_addr = sco.getw(); + sco.jump_to(next_addr); output_console("\n@%x:", next_addr); } void NACT_Sys2::cmd_label_call() { - int next_addr = getw(); + int next_addr = sco.getw(); output_console("\n\\%x:", next_addr); @@ -290,19 +290,17 @@ void NACT_Sys2::cmd_label_call() // fatal_error = true; return; } - scenario_addr = label_stack[--label_depth]; + sco.jump_to(label_stack[--label_depth]); } else { - label_stack[label_depth++] = scenario_addr; - scenario_addr = next_addr; + label_stack[label_depth++] = sco.addr(); + sco.jump_to(next_addr); } } void NACT_Sys2::cmd_page_jump() { int next_page = cali(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = 2; + sco.page_jump(next_page, 2); output_console("\n&%d:", next_page); } @@ -322,13 +320,11 @@ void NACT_Sys2::cmd_page_call() next_page = page_stack[--page_depth]; next_addr = addr_stack[page_depth]; } else { - page_stack[page_depth] = scenario_page; - addr_stack[page_depth++] = scenario_addr; + page_stack[page_depth] = sco.page(); + addr_stack[page_depth++] = sco.addr(); next_addr = 2; } - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; + sco.page_jump(next_page, next_addr); } void NACT_Sys2::cmd_set_menu() @@ -344,7 +340,7 @@ void NACT_Sys2::cmd_set_menu() ags->clear_menu_window(); ags->menu_dest_y = 0; } - menu_addr[menu_index++] = getw(); + menu_addr[menu_index++] = sco.getw(); ags->menu_dest_x = 2; ags->menu_dest_y += 2; ags->draw_menu = true; @@ -358,7 +354,7 @@ void NACT_Sys2::cmd_open_menu() output_console("\n]"); if(!menu_index) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); return; } @@ -367,16 +363,16 @@ void NACT_Sys2::cmd_open_menu() return; if (selection != -1) { - scenario_addr = menu_addr[selection]; + sco.jump_to(menu_addr[selection]); } menu_index = 0; } void NACT_Sys2::cmd_set_verbobj() { - int verb = getd(); - int obj = getd(); - int addr = getw(); + int verb = sco.getd(); + int obj = sco.getd(); + int addr = sco.getw(); menu_addr[menu_index] = addr; menu_verb[menu_index] = verb; @@ -389,9 +385,9 @@ void NACT_Sys2::cmd_set_verbobj() void NACT_Sys2::cmd_set_verbobj2() { int condition = cali(); - int verb = getd(); - int obj = getd(); - int addr = getw(); + int verb = sco.getd(); + int obj = sco.getd(); + int addr = sco.getw(); if(condition) { menu_addr[menu_index] = addr; @@ -440,7 +436,7 @@ void NACT_Sys2::cmd_open_verb() return; if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); } else { cmd_open_obj(id[selection]); } @@ -464,12 +460,12 @@ void NACT_Sys2::cmd_open_obj(int verb) } // 目的語がない場合 if(chk[0]) { - scenario_addr = addr[0]; + sco.jump_to(addr[0]); return; } // 以後、obj=0は戻るとして扱う chk[0] = 0; - addr[0] = scenario_data[0] | (scenario_data[1] << 8); + addr[0] = sco.default_addr(); // メニュー項目の準備 int id[32], index = 0; @@ -500,9 +496,9 @@ void NACT_Sys2::cmd_open_obj(int verb) return; if(selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); } else { - scenario_addr = addr[id[selection]]; + sco.jump_to(addr[id[selection]]); } } @@ -647,7 +643,7 @@ void NACT_Sys2::cmd_f() { output_console("\nF"); - scenario_addr = 2; + sco.jump_to(2); } void NACT_Sys2::cmd_g() @@ -676,7 +672,7 @@ void NACT_Sys2::cmd_g() void NACT_Sys2::cmd_h() { - int length = getd(); + int length = sco.getd(); int val = cali(); output_console("\nH %d,%d:", length, val); @@ -719,7 +715,7 @@ void NACT_Sys2::cmd_i() { int p1 = cali(); int p2 = cali(); -// int p3 = getd(); +// int p3 = sco.getd(); int p3 = cali(); output_console("\nI %d,%d,%d:", p1, p2, p3); @@ -741,7 +737,7 @@ void NACT_Sys2::cmd_k() void NACT_Sys2::cmd_l() { - int index = getd(); + int index = sco.getd(); output_console("\nL %d:", index); @@ -830,9 +826,7 @@ void NACT_Sys2::cmd_l() } fio.reset(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; + sco.page_jump(next_page, next_addr); mako->play_music(next_music); } @@ -843,14 +837,14 @@ void NACT_Sys2::cmd_m() { char string[33]; - int d = getd(); + int d = sco.getd(); if (d == '\'' || d == '"') { // SysEng - get_string(string, sizeof(string), d); + sco.get_syseng_string(string, sizeof(string), encoding.get(), d); } else { int p = 0; while(d != ':') { string[p++] = d; - d = getd(); + d = sco.getd(); } string[p] = '\0'; } @@ -888,7 +882,7 @@ void NACT_Sys2::cmd_o() void NACT_Sys2::cmd_p() { - int param = getd(); + int param = sco.getd(); if(crc32_a != CRC32_YAKATA2 && crc32_a != CRC32_DALK_HINT && crc32_a != CRC32_RANCE3_HINT) { ags->text_font_color = (uint8)((param & 0x7) + 16); @@ -919,7 +913,7 @@ void NACT_Sys2::cmd_q() '4', ' ', 'A', 'L', 'I', 'C', 'E', '-', 'S', 'O', 'F', 'T', ' ', ' ', ' ', ' ' }; - int index = getd(); + int index = sco.getd(); output_console("\nQ %d:", index); @@ -934,13 +928,13 @@ void NACT_Sys2::cmd_q() int p = 0; FWRITE(header, 112); - FPUTW(scenario_page + 1); + FPUTW(sco.page() + 1); FPUTW(0); FPUTW(0); // cg no? FPUTW(0); FPUTW(mako->current_music); FPUTW(0); - FPUTW(scenario_addr); + FPUTW(sco.addr()); FPUTW(0); for(int i = 0; i < 512; i++) { FPUTW(var[i]); @@ -1007,7 +1001,7 @@ void NACT_Sys2::cmd_r() void NACT_Sys2::cmd_s() { - int page = getd(); + int page = sco.getd(); output_console("\nS %d:", page); @@ -1035,8 +1029,8 @@ void NACT_Sys2::cmd_u() page = cali(); transparent = cali(); } else { - page = getd(); - transparent = getd(); + page = sco.getd(); + transparent = sco.getd(); } output_console("\nU %d,%d:", page, transparent); @@ -1046,7 +1040,7 @@ void NACT_Sys2::cmd_u() void NACT_Sys2::cmd_v() { - int cmd = getd(); + int cmd = sco.getd(); int p01 = cali(); int p02 = cali(); int p03 = cali(); @@ -1095,7 +1089,7 @@ void NACT_Sys2::cmd_w() void NACT_Sys2::cmd_x() { - int index = getd(); + int index = sco.getd(); output_console("\nX %d:", index); @@ -1277,14 +1271,14 @@ uint16 NACT_Sys2::cali() bool ok = false; while(p > 0) { - uint8 dat = getd(); + uint8 dat = sco.getd(); if(0x80 <= dat && dat <= 0xbf) { cali[p++] = var[dat & 0x3f]; } else if(0xc0 <= dat && dat <= 0xff) { - cali[p++] = var[((dat & 0x3f) << 8) | getd()]; + cali[p++] = var[((dat & 0x3f) << 8) | sco.getd()]; } else if(0x00 <= dat && dat <= 0x3f) { - cali[p++] = ((dat & 0x3f) << 8) | getd(); + cali[p++] = ((dat & 0x3f) << 8) | sco.getd(); } else if(0x40 <= dat && dat <= 0x76) { cali[p++] = dat & 0x3f; } else if(dat == 0x77) { @@ -1333,7 +1327,7 @@ uint16 NACT_Sys2::cali() } } if (!ok) { - fatal("cali: invalid expression at %d:%04x", scenario_page, scenario_addr); + fatal("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1341,17 +1335,17 @@ uint16 NACT_Sys2::cali() uint16 NACT_Sys2::cali2() { uint16 val = 0; - uint16 dat = getd(); + uint16 dat = sco.getd(); if(0x80 <= dat && dat <= 0xbf) { val = dat & 0x3f; } else if(0xc0 <= dat && dat <= 0xff) { - val = ((dat & 0x3f) << 8) | getd(); + val = ((dat & 0x3f) << 8) | sco.getd(); } else { - fatal("cali2: invalid expression at %d:%04x", scenario_page, scenario_addr); + fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } - if(getd() != 0x7f) { - fatal("cali2: invalid expression at %d:%04x", scenario_page, scenario_addr); + if (sco.getd() != 0x7f) { + fatal("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 5ae4afd..2285f03 100644 --- a/src/sys/nact_sys3.cpp +++ b/src/sys/nact_sys3.cpp @@ -22,11 +22,11 @@ NACT_Sys3::NACT_Sys3(uint32 crc32_a, uint32 crc32_b, const Config& config) void NACT_Sys3::cmd_calc() { - int index = getd(); + int index = sco.getd(); if(0x80 <= index && index <= 0xbf) { index &= 0x3f; } else { - index = ((index & 0x3f) << 8) | getd(); + index = ((index & 0x3f) << 8) | sco.getd(); } var[index] = cali(); @@ -36,26 +36,26 @@ void NACT_Sys3::cmd_calc() void NACT_Sys3::cmd_branch() { int condition = cali(); - int t_addr = scenario_addr + 2; - int f_addr = getw(); + int t_addr = sco.addr() + 2; + int f_addr = sco.getw(); // sigmarion3 最適化誤爆の対策 - scenario_addr = condition ? t_addr : f_addr; + sco.jump_to(condition ? t_addr : f_addr); output_console("\n{%d: T:%4x, F:%4x", condition, t_addr, f_addr); } void NACT_Sys3::cmd_label_jump() { - int next_addr = getw(); - scenario_addr = next_addr; + int next_addr = sco.getw(); + sco.jump_to(next_addr); output_console("\n@%x:", next_addr); } void NACT_Sys3::cmd_label_call() { - int next_addr = getw(); + int next_addr = sco.getw(); output_console("\n\\%x:", next_addr); @@ -65,19 +65,17 @@ void NACT_Sys3::cmd_label_call() // fatal_error = true; return; } - scenario_addr = label_stack[--label_depth]; + sco.jump_to(label_stack[--label_depth]); } else { - label_stack[label_depth++] = scenario_addr; - scenario_addr = next_addr; + label_stack[label_depth++] = sco.addr(); + sco.jump_to(next_addr); } } void NACT_Sys3::cmd_page_jump() { int next_page = cali(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = 2; + sco.page_jump(next_page, 2); output_console("\n&%d:", next_page); } @@ -97,13 +95,11 @@ void NACT_Sys3::cmd_page_call() next_page = page_stack[--page_depth]; next_addr = addr_stack[page_depth]; } else { - page_stack[page_depth] = scenario_page; - addr_stack[page_depth++] = scenario_addr; + page_stack[page_depth] = sco.page(); + addr_stack[page_depth++] = sco.addr(); next_addr = 2; } - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; + sco.page_jump(next_page, next_addr); } void NACT_Sys3::cmd_set_menu() @@ -119,7 +115,7 @@ void NACT_Sys3::cmd_set_menu() ags->clear_menu_window(); ags->menu_dest_y = 0; } - menu_addr[menu_index++] = getw(); + menu_addr[menu_index++] = sco.getw(); ags->menu_dest_x = 2; ags->menu_dest_y += 2; ags->draw_menu = true; @@ -133,7 +129,7 @@ void NACT_Sys3::cmd_open_menu() output_console("\n]"); if(!menu_index) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); return; } @@ -142,16 +138,16 @@ void NACT_Sys3::cmd_open_menu() return; if(index != -1) { - scenario_addr = menu_addr[index]; + sco.jump_to(menu_addr[index]); } menu_index = 0; } void NACT_Sys3::cmd_set_verbobj() { - int verb = getd(); - int obj = getd(); - int addr = getw(); + int verb = sco.getd(); + int obj = sco.getd(); + int addr = sco.getw(); menu_addr[menu_index] = addr; menu_verb[menu_index] = verb; @@ -164,9 +160,9 @@ void NACT_Sys3::cmd_set_verbobj() void NACT_Sys3::cmd_set_verbobj2() { int condition = cali(); - int verb = getd(); - int obj = getd(); - int addr = getw(); + int verb = sco.getd(); + int obj = sco.getd(); + int addr = sco.getw(); if(condition) { menu_addr[menu_index] = addr; @@ -215,7 +211,7 @@ void NACT_Sys3::cmd_open_verb() return; if (selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); } else { cmd_open_obj(id[selection]); } @@ -239,12 +235,12 @@ void NACT_Sys3::cmd_open_obj(int verb) } // 目的語がない場合 if(chk[0]) { - scenario_addr = addr[0]; + sco.jump_to(addr[0]); return; } // 以後、obj=0は戻るとして扱う chk[0] = 0; - addr[0] = scenario_data[0] | (scenario_data[1] << 8); + addr[0] = sco.default_addr(); // メニュー項目の準備 int id[32], index = 0; @@ -275,9 +271,9 @@ void NACT_Sys3::cmd_open_obj(int verb) return; if (selection == -1) { - scenario_addr = scenario_data[0] | (scenario_data[1] << 8); + sco.jump_to(sco.default_addr()); } else { - scenario_addr = addr[id[selection]]; + sco.jump_to(addr[id[selection]]); } } @@ -321,7 +317,7 @@ void NACT_Sys3::cmd_a() void NACT_Sys3::cmd_b() { - int cmd = getd(); + int cmd = sco.getd(); int index = cali(); int p1 = cali(); int p2 = cali(); @@ -390,7 +386,7 @@ void NACT_Sys3::cmd_b() void NACT_Sys3::cmd_d() { // 未使用 - fatal("Unknown Command: 'D' at page = %d, addr = %d", scenario_page, prev_addr); + fatal("Unknown Command: 'D' at page = %d, addr = %d", sco.page(), prev_addr); } void NACT_Sys3::cmd_e() @@ -415,7 +411,7 @@ void NACT_Sys3::cmd_f() { output_console("\nF"); - scenario_addr = 2; + sco.jump_to(2); } void NACT_Sys3::cmd_g() @@ -429,7 +425,7 @@ void NACT_Sys3::cmd_g() void NACT_Sys3::cmd_h() { - int length = getd(); + int length = sco.getd(); int val = cali(); output_console("\nH %d,%d:", length, val); @@ -507,7 +503,7 @@ void NACT_Sys3::cmd_j() void NACT_Sys3::cmd_k() { - int cmd = getd(), val; + int cmd = sco.getd(), val; output_console("\nK %d:", cmd); @@ -699,9 +695,7 @@ void NACT_Sys3::cmd_l() } fio.reset(); - load_scenario(next_page); - scenario_page = next_page; - scenario_addr = next_addr; + sco.page_jump(next_page, next_addr); mako->play_music(next_music); } @@ -722,14 +716,14 @@ void NACT_Sys3::cmd_m() { char string[22]; - int d = getd(); + int d = sco.getd(); if (d == '\'' || d == '"') { // SysEng - get_string(string, sizeof(string), d); + sco.get_syseng_string(string, sizeof(string), encoding.get(), d); } else { int p = 0; while(d != ':') { string[p++] = d; - d = getd(); + d = sco.getd(); } string[p] = '\0'; } @@ -739,7 +733,7 @@ void NACT_Sys3::cmd_m() if(1 <= tvar_index && tvar_index <= 10) { memcpy(tvar[tvar_index - 1], string, 22); } else if(tvar_index == 31) { - adisk.open(string); + sco.open(string); } else if(tvar_index == 32) { ags->set_cg_file(string); } else if(tvar_index == 33) { @@ -753,7 +747,7 @@ void NACT_Sys3::cmd_m() void NACT_Sys3::cmd_n() { - int cmd = getd(); + int cmd = sco.getd(); int src = cali(); int dest = cali(); @@ -883,13 +877,13 @@ void NACT_Sys3::cmd_q() int p = 0; FWRITE(header, 112); - FPUTW(scenario_page + 1); + FPUTW(sco.page() + 1); FPUTW(0); FPUTW(0); // cg no? FPUTW(0); FPUTW(mako->current_music); FPUTW(0); - FPUTW(scenario_addr); + FPUTW(sco.addr()); FPUTW(0); for(int i = 0; i < 512; i++) { FPUTW(var[i]); @@ -956,7 +950,7 @@ void NACT_Sys3::cmd_r() void NACT_Sys3::cmd_s() { - int page = getd(); + int page = sco.getd(); output_console("\nS %d:", page); @@ -1030,7 +1024,7 @@ void NACT_Sys3::cmd_w() void NACT_Sys3::cmd_x() { - int index = getd(); + int index = sco.getd(); output_console("\nX %d:", index); @@ -1438,14 +1432,14 @@ uint16 NACT_Sys3::cali() bool ok = false; while(p > 0) { - uint8 dat = getd(); + uint8 dat = sco.getd(); if(0x80 <= dat && dat <= 0xbf) { cali[p++] = var[dat & 0x3f]; } else if(0xc0 <= dat && dat <= 0xff) { - cali[p++] = var[((dat & 0x3f) << 8) | getd()]; + cali[p++] = var[((dat & 0x3f) << 8) | sco.getd()]; } else if(0x00 <= dat && dat <= 0x3f) { - cali[p++] = ((dat & 0x3f) << 8) | getd(); + cali[p++] = ((dat & 0x3f) << 8) | sco.getd(); } else if(0x40 <= dat && dat <= 0x76) { cali[p++] = dat & 0x3f; } else if(dat == 0x77) { @@ -1494,7 +1488,7 @@ uint16 NACT_Sys3::cali() } } if (!ok) { - fatal("cali: invalid expression at %d:%04x", scenario_page, scenario_addr); + fatal("cali: invalid expression at %d:%04x", sco.page(), sco.addr()); } return (uint16)(cali[1] & 0xffff); } @@ -1502,17 +1496,17 @@ uint16 NACT_Sys3::cali() uint16 NACT_Sys3::cali2() { uint16 val = 0; - uint16 dat = getd(); + uint16 dat = sco.getd(); if(0x80 <= dat && dat <= 0xbf) { val = dat & 0x3f; } else if(0xc0 <= dat && dat <= 0xff) { - val = ((dat & 0x3f) << 8) | getd(); + val = ((dat & 0x3f) << 8) | sco.getd(); } else { - fatal("cali2: invalid expression at %d:%04x", scenario_page, scenario_addr); + fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } - if(getd() != 0x7f) { - fatal("cali2: invalid expression at %d:%04x", scenario_page, scenario_addr); + if (sco.getd() != 0x7f) { + fatal("cali2: invalid expression at %d:%04x", sco.page(), sco.addr()); } return val; } @@ -1561,7 +1555,7 @@ bool NACT_Sys3::k3_hack(const K3HackInfo* info_table) { const K3HackInfo* info; for (info = info_table; info->page >= 0; info++) { - if (scenario_page == info->page) + if (sco.page() == info->page) break; } if (info->page < 0) diff --git a/src/sys/scenario.cpp b/src/sys/scenario.cpp new file mode 100644 index 0000000..73d2b42 --- /dev/null +++ b/src/sys/scenario.cpp @@ -0,0 +1,30 @@ +#include "scenario.h" +#include +#include "encoding.h" + +void Scenario::skip_string(Encoding *enc, uint8_t terminator) +{ + for (uint8_t c = getd(); c != terminator; c = getd()) { + if (c != '\\') + ungetd(); + skip(enc->mblen(ptr())); + } +} + +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 - 1) { + memcpy(&buf[i], ptr(), len); + i += len; + } + skip(len); + } + buf[i] = '\0'; +} diff --git a/src/sys/scenario.h b/src/sys/scenario.h new file mode 100644 index 0000000..bca384a --- /dev/null +++ b/src/sys/scenario.h @@ -0,0 +1,53 @@ +#ifndef _SCENARIO_H_ +#define _SCENARIO_H_ + +#include +#include +#include "dri.h" + +class Encoding; + +class Scenario { +public: + void open(const char* file_name) { adisk.open(file_name); } + void page_jump(int page, int addr) { + data_ = adisk.load(page + 1); + page_ = page; + addr_ = addr; + } + size_t size() const { return data_.size(); } + uint8_t& operator[](int i) { return data_[i]; } + const uint8_t* ptr() const { return &data_[addr_]; } + 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; + } + + void jump_to(int addr) { addr_ = addr; } + void skip(int n) { addr_ += n; } + uint8_t getd() { return data_[addr_++]; } + uint16_t getw() { + uint16_t w = data_[addr_++]; + w |= data_[addr_++] << 8; + return w; + } + void ungetd() { addr_--; } + void skip_string(Encoding *enc, uint8_t terminator); + void get_syseng_string(char* buf, int size, Encoding *enc, uint8_t terminator); + +private: + Dri adisk; + std::vector data_; + int page_; + int addr_; +}; + +#endif // _SCENARIO_H_