diff --git a/CMakeLists.txt b/CMakeLists.txt index 665cc58..20f09da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,6 +221,7 @@ target_sources(system3 PRIVATE src/sys/nact_sys1.cpp src/sys/nact_sys2.cpp src/sys/nact_sys3.cpp + src/sys/nact_text.cpp src/sys/nact_window.cpp src/sys/scenario.cpp ) diff --git a/src/sys/ags.cpp b/src/sys/ags.cpp index 2a22b99..c42ed69 100644 --- a/src/sys/ags.cpp +++ b/src/sys/ags.cpp @@ -189,36 +189,6 @@ AGS::AGS(const Config& config, const GameId& game_id) : game_id(game_id) // 画面選択 src_screen = dest_screen = 0; - // メッセージ表示 - text.line_space = 2; - text.font_size = 16; - if (game_id.sys_ver == 1) { - text.font_color = 15 + 16; - text.frame_color = 15 + 16; - text.back_color = 0 + 16; - } else { - text.font_color = 15; - text.frame_color = 15; - text.back_color = 0; - } - - // メニュー表示 - menu.reset_pos(2, 2); - menu.line_space = 4; - menu.font_size = 16; - if (game_id.sys_ver == 1) { - menu.font_color = 15 + 16; - menu.frame_color = 15 + 16; - menu.back_color = 0 + 16; - } else { - menu.font_color = 15; - menu.frame_color = 15; - menu.back_color = 0; - } - - draw_hankaku = false; - draw_menu = false; - // CG表示 cg_dest = std::nullopt; palette_bank = -1; diff --git a/src/sys/ags.h b/src/sys/ags.h index 1380e58..fa3885d 100644 --- a/src/sys/ags.h +++ b/src/sys/ags.h @@ -116,7 +116,7 @@ public: CG save_rect(int x, int y, int width, int height); void restore_rect(const CG& cg); - void draw_text(std::string_view string, bool text_wait = false); + int draw_text(int dest, int x, int y, std::u16string_view codes, int font_size, uint8 color); void load_cursor(int page, uint8_t flags); void select_cursor(); @@ -136,36 +136,6 @@ public: int window_width, window_height; int screen_width, screen_height; - struct TextContext { - SDL_Point pos; - int origin_x; - int line_space; - int font_size; - uint8_t font_color; - uint8_t frame_color; - uint8_t back_color; - int current_line_height; - - void reset_pos(int x, int y) { - pos.x = origin_x = x; - pos.y = y; - current_line_height = 0; - } - void newline() { - pos.x = origin_x; - pos.y += std::max(font_size, current_line_height) + line_space; - current_line_height = 0; - } - }; - // メッセージ表示 - TextContext text; - - // メニュー表示 - TextContext menu; - - bool draw_hankaku; - bool draw_menu; - // CG表示 std::optional cg_dest; std::unordered_set censor_list; diff --git a/src/sys/ags_text.cpp b/src/sys/ags_text.cpp index 30927da..7e160fe 100644 --- a/src/sys/ags_text.cpp +++ b/src/sys/ags_text.cpp @@ -8,363 +8,22 @@ #include #include #include "ags.h" -#include "nact.h" #include "encoding.h" -#include "texthook.h" namespace { bool antialias = true; -int convert_to_zenkaku(int code) -{ - switch(code) { - case u' ': return u' '; - case u'!': return u'!'; - case u'"': return u'”'; - case u'#': return u'#'; - case u'$': return u'$'; - case u'%': return u'%'; - case u'&': return u'&'; - case u'\'': return u'’'; - case u'(': return u'('; - case u')': return u')'; - case u'*': return u'*'; - case u'+': return u'+'; - case u',': return u','; - case u'-': return u'-'; - case u'.': return u'.'; - case u'/': return u'/'; - case u'0': return u'0'; - case u'1': return u'1'; - case u'2': return u'2'; - case u'3': return u'3'; - case u'4': return u'4'; - case u'5': return u'5'; - case u'6': return u'6'; - case u'7': return u'7'; - case u'8': return u'8'; - case u'9': return u'9'; - case u':': return u':'; - case u';': return u';'; - case u'<': return u'<'; - case u'=': return u'='; - case u'>': return u'>'; - case u'?': return u'?'; - case u'@': return u'@'; - case u'A': return u'A'; - case u'B': return u'B'; - case u'C': return u'C'; - case u'D': return u'D'; - case u'E': return u'E'; - case u'F': return u'F'; - case u'G': return u'G'; - case u'H': return u'H'; - case u'I': return u'I'; - case u'J': return u'J'; - case u'K': return u'K'; - case u'L': return u'L'; - case u'M': return u'M'; - case u'N': return u'N'; - case u'O': return u'O'; - case u'P': return u'P'; - case u'Q': return u'Q'; - case u'R': return u'R'; - case u'S': return u'S'; - case u'T': return u'T'; - case u'U': return u'U'; - case u'V': return u'V'; - case u'W': return u'W'; - case u'X': return u'X'; - case u'Y': return u'Y'; - case u'Z': return u'Z'; - case u'[': return u'['; - case u'\\': return u'¥'; - case u']': return u']'; - case u'^': return u'^'; - case u'_': return u'_'; - case u'`': return u'‘'; - case u'a': return u'a'; - case u'b': return u'b'; - case u'c': return u'c'; - case u'd': return u'd'; - case u'e': return u'e'; - case u'f': return u'f'; - case u'g': return u'g'; - case u'h': return u'h'; - case u'i': return u'i'; - case u'j': return u'j'; - case u'k': return u'k'; - case u'l': return u'l'; - case u'm': return u'm'; - case u'n': return u'n'; - case u'o': return u'o'; - case u'p': return u'p'; - case u'q': return u'q'; - case u'r': return u'r'; - case u's': return u's'; - case u't': return u't'; - case u'u': return u'u'; - case u'v': return u'v'; - case u'w': return u'w'; - case u'x': return u'x'; - case u'y': return u'y'; - case u'z': return u'z'; - case u'{': return u'{'; - case u'|': return u'|'; - case u'}': return u'}'; - case u'~': return u'~'; - case u'。': return u'。'; - case u'「': return u'「'; - case u'」': return u'」'; - case u'、': return u'、'; - case u'・': return u'・'; - case u'ヲ': return u'を'; - case u'ァ': return u'ぁ'; - case u'ィ': return u'ぃ'; - case u'ゥ': return u'ぅ'; - case u'ェ': return u'ぇ'; - case u'ォ': return u'ぉ'; - case u'ャ': return u'ゃ'; - case u'ュ': return u'ゅ'; - case u'ョ': return u'ょ'; - case u'ッ': return u'っ'; - case u'ー': return u'ー'; - case u'ア': return u'あ'; - case u'イ': return u'い'; - case u'ウ': return u'う'; - case u'エ': return u'え'; - case u'オ': return u'お'; - case u'カ': return u'か'; - case u'キ': return u'き'; - case u'ク': return u'く'; - case u'ケ': return u'け'; - case u'コ': return u'こ'; - case u'サ': return u'さ'; - case u'シ': return u'し'; - case u'ス': return u'す'; - case u'セ': return u'せ'; - case u'ソ': return u'そ'; - case u'タ': return u'た'; - case u'チ': return u'ち'; - case u'ツ': return u'つ'; - case u'テ': return u'て'; - case u'ト': return u'と'; - case u'ナ': return u'な'; - case u'ニ': return u'に'; - case u'ヌ': return u'ぬ'; - case u'ネ': return u'ね'; - case u'ノ': return u'の'; - case u'ハ': return u'は'; - case u'ヒ': return u'ひ'; - case u'フ': return u'ふ'; - case u'ヘ': return u'へ'; - case u'ホ': return u'ほ'; - case u'マ': return u'ま'; - case u'ミ': return u'み'; - case u'ム': return u'む'; - case u'メ': return u'め'; - case u'モ': return u'も'; - case u'ヤ': return u'や'; - case u'ユ': return u'ゆ'; - case u'ヨ': return u'よ'; - case u'ラ': return u'ら'; - case u'リ': return u'り'; - case u'ル': return u'る'; - case u'レ': return u'れ'; - case u'ロ': return u'ろ'; - case u'ワ': return u'わ'; - case u'ン': return u'ん'; - case u'゙': return u'゛'; - case u'゚': return u'゜'; - } - return code; -} - -int convert_to_hankaku(int code) -{ - switch(code) { - case u' ': return u' '; - case u'!': return u'!'; - case u'”': return u'"'; - case u'#': return u'#'; - case u'$': return u'$'; - case u'%': return u'%'; - case u'&': return u'&'; - case u'’': return u'\''; - case u'(': return u'('; - case u')': return u')'; - case u'*': return u'*'; - case u'+': return u'+'; - case u',': return u','; - case u'-': return u'-'; - case u'.': return u'.'; - case u'/': return u'/'; - case u'0': return u'0'; - case u'1': return u'1'; - case u'2': return u'2'; - case u'3': return u'3'; - case u'4': return u'4'; - case u'5': return u'5'; - case u'6': return u'6'; - case u'7': return u'7'; - case u'8': return u'8'; - case u'9': return u'9'; - case u':': return u':'; - case u';': return u';'; - case u'<': return u'<'; - case u'=': return u'='; - case u'>': return u'>'; - case u'?': return u'?'; - case u'@': return u'@'; - case u'A': return u'A'; - case u'B': return u'B'; - case u'C': return u'C'; - case u'D': return u'D'; - case u'E': return u'E'; - case u'F': return u'F'; - case u'G': return u'G'; - case u'H': return u'H'; - case u'I': return u'I'; - case u'J': return u'J'; - case u'K': return u'K'; - case u'L': return u'L'; - case u'M': return u'M'; - case u'N': return u'N'; - case u'O': return u'O'; - case u'P': return u'P'; - case u'Q': return u'Q'; - case u'R': return u'R'; - case u'S': return u'S'; - case u'T': return u'T'; - case u'U': return u'U'; - case u'V': return u'V'; - case u'W': return u'W'; - case u'X': return u'X'; - case u'Y': return u'Y'; - case u'Z': return u'Z'; - case u'[': return u'['; - case u'¥': return u'\\'; - case u']': return u']'; - case u'^': return u'^'; - case u'_': return u'_'; - case u'‘': return u'`'; - case u'a': return u'a'; - case u'b': return u'b'; - case u'c': return u'c'; - case u'd': return u'd'; - case u'e': return u'e'; - case u'f': return u'f'; - case u'g': return u'g'; - case u'h': return u'h'; - case u'i': return u'i'; - case u'j': return u'j'; - case u'k': return u'k'; - case u'l': return u'l'; - case u'm': return u'm'; - case u'n': return u'n'; - case u'o': return u'o'; - case u'p': return u'p'; - case u'q': return u'q'; - case u'r': return u'r'; - case u's': return u's'; - case u't': return u't'; - case u'u': return u'u'; - case u'v': return u'v'; - case u'w': return u'w'; - case u'x': return u'x'; - case u'y': return u'y'; - case u'z': return u'z'; - case u'{': return u'{'; - case u'|': return u'|'; - case u'}': return u'}'; - case u'~': return u'~'; - case u'。': return u'。'; - case u'「': return u'「'; - case u'」': return u'」'; - case u'、': return u'、'; - case u'・': return u'・'; - case u'ヲ': return u'を'; - case u'ァ': return u'ぁ'; - case u'ィ': return u'ぃ'; - case u'ゥ': return u'ぅ'; - case u'ェ': return u'ぇ'; - case u'ォ': return u'ぉ'; - case u'ャ': return u'ゃ'; - case u'ュ': return u'ゅ'; - case u'ョ': return u'ょ'; - case u'ッ': return u'っ'; - case u'ー': return u'ー'; - case u'ア': return u'あ'; - case u'イ': return u'い'; - case u'ウ': return u'う'; - case u'エ': return u'え'; - case u'オ': return u'お'; - case u'カ': return u'か'; - case u'キ': return u'き'; - case u'ク': return u'く'; - case u'ケ': return u'け'; - case u'コ': return u'こ'; - case u'サ': return u'さ'; - case u'シ': return u'し'; - case u'ス': return u'す'; - case u'セ': return u'せ'; - case u'ソ': return u'そ'; - case u'タ': return u'た'; - case u'チ': return u'ち'; - case u'ツ': return u'つ'; - case u'テ': return u'て'; - case u'ト': return u'と'; - case u'ナ': return u'な'; - case u'ニ': return u'に'; - case u'ヌ': return u'ぬ'; - case u'ネ': return u'ね'; - case u'ノ': return u'の'; - case u'ハ': return u'は'; - case u'ヒ': return u'ひ'; - case u'フ': return u'ふ'; - case u'ヘ': return u'へ'; - case u'ホ': return u'ほ'; - case u'マ': return u'ま'; - case u'ミ': return u'み'; - case u'ム': return u'む'; - case u'メ': return u'め'; - case u'モ': return u'も'; - case u'ヤ': return u'や'; - case u'ユ': return u'ゆ'; - case u'ヨ': return u'よ'; - case u'ラ': return u'ら'; - case u'リ': return u'り'; - case u'ル': return u'る'; - case u'レ': return u'れ'; - case u'ロ': return u'ろ'; - case u'ワ': return u'わ'; - case u'ン': return u'ん'; - case u'゙': return u'゛'; - case u'゚': return u'゜'; - } - return code; -} - } // namespace -void AGS::draw_text(std::string_view string, bool text_wait) +int AGS::draw_text(int dest, int x, int y, std::u16string_view codes, int font_size, uint8 color) { - if (string.empty()) - return; uint8 antialias_cache[256*7]; if (antialias) memset(antialias_cache, 0, 256); - TextContext& ctx = draw_menu ? menu : text; - int screen = draw_menu ? 2 : dest_screen; - int dest_x = ctx.pos.x; - int dest_y = ctx.pos.y; - if (ctx.current_line_height < ctx.font_size) - ctx.current_line_height = ctx.font_size; - TTF_Font* font = NULL; - switch (ctx.font_size) { + switch (font_size) { case 16: font = hFont16; break; case 24: font = hFont24; break; case 32: font = hFont32; break; @@ -374,29 +33,20 @@ void AGS::draw_text(std::string_view string, bool text_wait) int ascent = TTF_FontAscent(font); int descent = TTF_FontDescent(font); // Adjust dest_y if the font height is larger than the specified size. - dest_y -= (ascent - descent - ctx.font_size) / 2; - - while (!string.empty()) { - int code = g_nact->encoding->next_codepoint(string); - if(draw_hankaku) { - code = convert_to_hankaku(code); - } else { - code = convert_to_zenkaku(code); - } + int dest_y = y - (ascent - descent - font_size) / 2; + int dest_x = x; + for (char16_t code : codes) { // 文字出力 if (GAIJI_FIRST <= code && code <= GAIJI_LAST) { - // Use unadjusted dest_y here. - draw_gaiji(screen, dest_x, ctx.pos.y, gaiji[code - GAIJI_FIRST], ctx.font_size, ctx.font_color); - dest_x += ctx.font_size; + // Use unadjusted y here. + draw_gaiji(dest, dest_x, y, gaiji[code - GAIJI_FIRST], font_size, color); + dest_x += font_size; } else { - if (!draw_menu) - texthook_character(g_nact->get_scenario_page(), code); - if (antialias) - draw_char_antialias(screen, dest_x, dest_y, code, font, ctx.font_color, antialias_cache); + draw_char_antialias(dest, dest_x, dest_y, code, font, color, antialias_cache); else - draw_char(screen, dest_x, dest_y, code, font, ctx.font_color); + draw_char(dest, dest_x, dest_y, code, font, color); int miny, maxy, advance; TTF_GlyphMetrics(font, code, NULL, NULL, &miny, &maxy, &advance); @@ -405,22 +55,12 @@ void AGS::draw_text(std::string_view string, bool text_wait) if (maxy > ascent) ascent = maxy; dest_x += advance; } + } - if (!draw_menu && text_wait && code != ' ') { - // 画面更新 - if(screen == 0) - invalidate_screen(ctx.pos.x, dest_y, dest_x - ctx.pos.x, ascent - descent); - ctx.pos.x = dest_x; - // Wait - g_nact->text_wait(); - } - } - if (!draw_menu && !text_wait) { - // 画面更新 - if(screen == 0) - invalidate_screen(ctx.pos.x, dest_y, dest_x - ctx.pos.x, ascent - descent); - } - ctx.pos.x = dest_x; + // 画面更新 + if (dest == 0) + invalidate_screen(x, dest_y, dest_x - x, ascent - descent); + return dest_x; } void AGS::draw_char(int dest, int dest_x, int dest_y, uint16 code, TTF_Font* font, uint8 color) diff --git a/src/sys/nact.cpp b/src/sys/nact.cpp index 425def5..bcef158 100644 --- a/src/sys/nact.cpp +++ b/src/sys/nact.cpp @@ -71,7 +71,7 @@ NACT::NACT(const Config& config, const GameId& game_id) msgskip = new MsgSkip(); init_windows(); - ags->text.reset_pos(text_w[0].sx, text_w[0].sy + 2); + init_text(); SDL_Init(SDL_INIT_GAMECONTROLLER); for (int i = 0; i < SDL_NumJoysticks(); ++i) { @@ -326,9 +326,9 @@ void NACT::cmd_page_call() void NACT::cmd_set_menu() { - if(ags->draw_menu) { - ags->menu.newline(); - ags->draw_menu = false; + if (draw_menu) { + menu.newline(); + draw_menu = false; TRACE("$"); } else { @@ -336,7 +336,7 @@ void NACT::cmd_set_menu() clear_menu_window(); } menu_items.emplace_back(sco.getw()); - ags->draw_menu = true; + draw_menu = true; if (game_id.is(GameId::GAKUEN_SENKI)) menu_window = 2; @@ -478,7 +478,7 @@ void NACT::cmd_x() TRACE("X %d:", index); if(1 <= index && index <= 10) { - ags->draw_text(tvar[index - 1]); + draw_text(tvar[index - 1]); } } @@ -501,14 +501,14 @@ void NACT::message(uint8_t first_byte) buf[i] = '\0'; } - ags->draw_text(buf, text_wait_enb); + draw_text(buf, text_wait_enb); if (game_id.is_system1_dps()) { - if(!ags->draw_menu) { + if (!draw_menu) { text_refresh = false; } } - if (!ags->draw_menu) + if (!draw_menu) msgskip->on_message(sco.page(), sco.current_addr()); // TODO: Convert hankaku to zenkaku @@ -622,7 +622,7 @@ int NACT::menu_select(int num_items) get_menu_window_rect(menu_window, &sx, &sy, &ex, nullptr); int mx = ex - 16; int my = sy + 10; - int height = ags->menu.font_size + 4; + int height = menu.font_size + 4; int current_index = 0; set_cursor(mx, my); diff --git a/src/sys/nact.h b/src/sys/nact.h index 31bdc13..5c7f74e 100644 --- a/src/sys/nact.h +++ b/src/sys/nact.h @@ -7,8 +7,10 @@ #ifndef _NACT_H_ #define _NACT_H_ +#include #include #include +#include #include #include #include @@ -169,6 +171,36 @@ protected: void get_menu_window_rect(int index, int* sx, int* sy, int* ex, int* ey); int calculate_menu_max(int window); + struct TextContext { + SDL_Point pos; + int origin_x; + int line_space; + int font_size; + uint8_t font_color; + uint8_t frame_color; + uint8_t back_color; + int current_line_height; + + void reset_pos(int x, int y) { + pos.x = origin_x = x; + pos.y = y; + current_line_height = 0; + } + void newline() { + pos.x = origin_x; + pos.y += std::max(font_size, current_line_height) + line_space; + current_line_height = 0; + } + }; + TextContext text; + TextContext menu; + + bool draw_hankaku = false; + bool draw_menu = false; + + void init_text(); + void draw_text(std::string_view string, bool wait = false); + struct MenuItem { uint16_t addr; uint8_t verb; diff --git a/src/sys/nact_gakuenking.cpp b/src/sys/nact_gakuenking.cpp index d4cf048..fd71089 100644 --- a/src/sys/nact_gakuenking.cpp +++ b/src/sys/nact_gakuenking.cpp @@ -96,7 +96,7 @@ private: case 25: fixed_shapes = (param == 1); if (0 <= param && param <= 4) { - ags->menu.back_color = ags->text.back_color = + menu.back_color = text.back_color = (param == 1 || param == 2) ? 0 : 1; text_window = param + 1; open_text_window(text_window, false); @@ -105,7 +105,7 @@ private: case 26: if (0 <= param && param <= 4) menu_window = param + 1; - ags->menu.back_color = (param == 0) ? 1 : 0; + menu.back_color = (param == 0) ? 1 : 0; break; case 50: map_overview_rebuild_pending = true; @@ -161,10 +161,10 @@ private: map_overview_rebuild_pending = true; break; case 118: - ags->text.pos.x = param; + text.pos.x = param; break; case 119: - ags->text.pos.y = param; + text.pos.y = param; break; // --- Shared with generic System3 --- @@ -250,7 +250,7 @@ private: void cmd_p() override { int p1 = cali(); TRACE("P %d:", p1); - ags->text.font_color = p1; + text.font_color = p1; } // The per-character wait of Y 13 and Y 14, in 1/100 s units. @@ -1745,10 +1745,10 @@ private: if (credit_entries.empty()) return; - int saved_size = ags->text.font_size; - uint8_t saved_color = ags->text.font_color; - ags->text.font_size = 16; - ags->text.font_color = 15; + int saved_size = text.font_size; + uint8_t saved_color = text.font_color; + text.font_size = 16; + text.font_color = 15; clear_credit_column(); draw_credit_text(168, TOP_Y, credit_title, false); @@ -1774,23 +1774,23 @@ private: break; } - ags->text.font_size = saved_size; - ags->text.font_color = saved_color; + text.font_size = saved_size; + text.font_color = saved_color; } void clear_credit_column() { ags->box_fill(WORK_SCREEN, CREDIT_X1, 0, CREDIT_X2, 399, 0); } - void draw_credit_text(int x, int y, std::string_view text, bool hankaku) { + void draw_credit_text(int x, int y, std::string_view str, bool hankaku) { int saved_screen = ags->dest_screen; - bool saved_hankaku = ags->draw_hankaku; + bool saved_hankaku = draw_hankaku; ags->dest_screen = WORK_SCREEN; - ags->draw_hankaku = hankaku; - ags->text.pos.x = x; - ags->text.pos.y = y; - ags->draw_text(text); - ags->draw_hankaku = saved_hankaku; + draw_hankaku = hankaku; + text.pos.x = x; + text.pos.y = y; + draw_text(str); + draw_hankaku = saved_hankaku; ags->dest_screen = saved_screen; } @@ -1973,29 +1973,29 @@ private: void save_text_state(std::vector& block) { int off = SAVE_OFF_TEXT_STATE; - put_le16(block, off, ags->menu.font_size); - put_le16(block, off + 2, ags->text.font_size); + put_le16(block, off, menu.font_size); + put_le16(block, off + 2, text.font_size); put_le16(block, off + 4, ags->palette_bank == -1 ? 0 : ags->palette_bank); - put_le16(block, off + 6, ags->text.font_color); - put_le16(block, off + 8, ags->menu.font_color); - put_le16(block, off + 10, ags->menu.frame_color); - put_le16(block, off + 12, ags->menu.back_color); - put_le16(block, off + 14, ags->text.frame_color); - put_le16(block, off + 16, ags->text.back_color); + put_le16(block, off + 6, text.font_color); + put_le16(block, off + 8, menu.font_color); + put_le16(block, off + 10, menu.frame_color); + put_le16(block, off + 12, menu.back_color); + put_le16(block, off + 14, text.frame_color); + put_le16(block, off + 16, text.back_color); } void load_text_state(const std::vector& data) { int off = SAVE_OFF_TEXT_STATE; - ags->menu.font_size = get_le16(data, off); - ags->text.font_size = get_le16(data, off + 2); + menu.font_size = get_le16(data, off); + text.font_size = get_le16(data, off + 2); int bank = get_le16(data, off + 4); ags->palette_bank = bank ? bank : -1; - ags->text.font_color = get_le16(data, off + 6); - ags->menu.font_color = get_le16(data, off + 8); - ags->menu.frame_color = get_le16(data, off + 10); - ags->menu.back_color = get_le16(data, off + 12); - ags->text.frame_color = get_le16(data, off + 14); - ags->text.back_color = get_le16(data, off + 16); + text.font_color = get_le16(data, off + 6); + menu.font_color = get_le16(data, off + 8); + menu.frame_color = get_le16(data, off + 10); + menu.back_color = get_le16(data, off + 12); + text.frame_color = get_le16(data, off + 14); + text.back_color = get_le16(data, off + 16); } void save_call_stack(std::vector& block) { diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp index 88ab966..93445c4 100644 --- a/src/sys/nact_sys1.cpp +++ b/src/sys/nact_sys1.cpp @@ -193,14 +193,14 @@ top: int id[32], index = 0; clear_menu_window(); - ags->draw_menu = true; + draw_menu = true; if(cnt <= menu_max) { // 1ページ内に全て表示できる for(int i = 0; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i]); - ags->menu.newline(); + draw_text(caption_verb[i]); + menu.newline(); id[index++] = i; } } @@ -208,8 +208,8 @@ top: top2: for(int i = page; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i]); - ags->menu.newline(); + draw_text(caption_verb[i]); + menu.newline(); id[index++] = i; } page = i + 1; @@ -223,11 +223,11 @@ top2: goto top2; } // 次のページを追加 - ags->draw_text(strings.next_page); - ags->menu.newline(); + draw_text(strings.next_page); + menu.newline(); id[index++] = -1; } - ags->draw_menu = false; + draw_menu = false; int selection = menu_select(index); if (terminate) @@ -275,27 +275,27 @@ top: int id[32], index = 0; clear_menu_window(); - ags->draw_menu = true; + draw_menu = true; if(cnt <= menu_max - 1) { // 1ページ内に全て表示できる for(int i = 0; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i]); - ags->menu.newline(); + draw_text(caption_obj[i]); + menu.newline(); id[index++] = i; } } // 戻るを追加 - ags->draw_text(strings.back); - ags->menu.newline(); + draw_text(strings.back); + menu.newline(); id[index++] = 0; } else { top2: for(int i = page; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i]); - ags->menu.newline(); + draw_text(caption_obj[i]); + menu.newline(); id[index++] = i; } page = i + 1; @@ -309,16 +309,16 @@ top2: goto top2; } // 戻るを追加 - ags->draw_text(strings.back); - ags->menu.newline(); + draw_text(strings.back); + menu.newline(); id[index++] = 0; // 次のページを追加 - ags->draw_text(strings.next_page); - ags->menu.newline(); + draw_text(strings.next_page); + menu.newline(); id[index++] = -1; } - ags->draw_menu = false; + draw_menu = false; int selection = menu_select(index); if (terminate) @@ -358,7 +358,7 @@ void NACT_Sys1::cmd_p() { int param = sco.getd(); - ags->text.font_color = (uint8)((param & 0x7) + 16); + text.font_color = (uint8)((param & 0x7) + 16); TRACE("P %d:", param); } @@ -430,7 +430,7 @@ void NACT_Sys1::exec_y(int cmd, int param) } p++; } - ags->draw_text(&buf[p < 4 ? p : 4]); + draw_text(&buf[p < 4 ? p : 4]); } break; case 2: @@ -445,7 +445,7 @@ void NACT_Sys1::exec_y(int cmd, int param) RND = (param == 0 || param == 1) ? 0 : random(param); break; case 240: // System3-sdl2 extension - ags->draw_hankaku = (param == 1) ? true : false; + draw_hankaku = (param == 1) ? true : false; break; case 253: quit(0); @@ -597,7 +597,7 @@ public: { char buf[16]; snprintf(buf, sizeof(buf), "%d", param); - ags->draw_text(buf); + draw_text(buf); } break; case 4: @@ -788,18 +788,18 @@ public: } // 矢印を表示する - SDL_Point orig_pos = ags->text.pos; - int orig_color = ags->text.font_color; - ags->text.font_size = 24; - ags->text.font_color = 16; + SDL_Point orig_pos = text.pos; + int orig_color = text.font_color; + text.font_size = 24; + text.font_color = 16; - ags->text.pos.x = 456; - ags->text.pos.y = 103; - ags->draw_text(buf[param - 1]); + text.pos.x = 456; + text.pos.y = 103; + draw_text(buf[param - 1]); - ags->text.pos = orig_pos; - ags->text.font_size = 16; - ags->text.font_color = orig_color; + text.pos = orig_pos; + text.font_size = 16; + text.font_color = orig_color; } else if (cmd == 2) { if (param == 0) { // Clear the screen diff --git a/src/sys/nact_sys2.cpp b/src/sys/nact_sys2.cpp index 6e6155b..ede4b94 100644 --- a/src/sys/nact_sys2.cpp +++ b/src/sys/nact_sys2.cpp @@ -275,16 +275,16 @@ void NACT_Sys2::cmd_open_verb() int id[32], index = 0; clear_menu_window(); - ags->draw_menu = true; + draw_menu = true; for(int i = 0; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i]); - ags->menu.newline(); + draw_text(caption_verb[i]); + menu.newline(); id[index++] = i; } } - ags->draw_menu = false; + draw_menu = false; int selection = menu_select(index); if (terminate) @@ -326,20 +326,20 @@ void NACT_Sys2::cmd_open_obj(int verb) int id[32], index = 0; clear_menu_window(); - ags->draw_menu = true; + draw_menu = true; for(int i = 0; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i]); - ags->menu.newline(); + draw_text(caption_obj[i]); + menu.newline(); id[index++] = i; } } // 戻るを追加 - ags->draw_text(strings.back); - ags->menu.newline(); + draw_text(strings.back); + menu.newline(); id[index++] = 0; - ags->draw_menu = false; + draw_menu = false; int selection = menu_select(index); if (terminate) @@ -496,7 +496,7 @@ void NACT_Sys2::cmd_h() } } string[p++] = '\0'; - ags->draw_text(string); + draw_text(string); } void NACT_Sys2::cmd_i() @@ -587,7 +587,7 @@ void NACT_Sys2::cmd_p() int param = sco.getd(); if (!game_id.is(GameId::YAKATA2) && !game_id.is(GameId::DALK_HINT) && !game_id.is(GameId::RANCE3_HINT)) { - ags->text.font_color = (uint8)((param & 0x7) + 16); + text.font_color = (uint8)((param & 0x7) + 16); } TRACE("P %d:", param); @@ -746,10 +746,10 @@ void NACT_Sys2::cmd_y() RND = 1; break; case 25: - ags->menu.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + menu.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; break; case 26: - ags->text.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + text.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; break; case 27: { @@ -778,17 +778,17 @@ void NACT_Sys2::cmd_y() case 228: case 229: if(1 <= param && param <= 10) { - ags->draw_text(tvar[param - 1]); + draw_text(tvar[param - 1]); int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); if (padlen > 0) { char pad[10] = " "; pad[padlen] = '\0'; - ags->draw_text(pad); + draw_text(pad); } } break; case 240: // System3-sdl2 extension - ags->draw_hankaku = (param == 1) ? true : false; + draw_hankaku = (param == 1) ? true : false; break; case 252: RND = 8; diff --git a/src/sys/nact_sys3.cpp b/src/sys/nact_sys3.cpp index c3b7d8e..06afc37 100644 --- a/src/sys/nact_sys3.cpp +++ b/src/sys/nact_sys3.cpp @@ -105,16 +105,16 @@ void NACT_Sys3::cmd_open_verb() int id[32], index = 0; clear_menu_window(); - ags->draw_menu = true; + draw_menu = true; for(int i = 0; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i]); - ags->menu.newline(); + draw_text(caption_verb[i]); + menu.newline(); id[index++] = i; } } - ags->draw_menu = false; + draw_menu = false; int selection = menu_select(index); if (terminate) @@ -156,20 +156,20 @@ void NACT_Sys3::cmd_open_obj(int verb) int id[32], index = 0; clear_menu_window(); - ags->draw_menu = true; + draw_menu = true; for(int i = 0; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i]); - ags->menu.newline(); + draw_text(caption_obj[i]); + menu.newline(); id[index++] = i; } } // 戻るを追加 - ags->draw_text(strings.back); - ags->menu.newline(); + draw_text(strings.back); + menu.newline(); id[index++] = 0; - ags->draw_menu = false; + draw_menu = false; int selection = menu_select(index); if (terminate) @@ -299,7 +299,7 @@ void NACT_Sys3::cmd_h() } } string[p++] = '\0'; - ags->draw_text(string); + draw_text(string); } void NACT_Sys3::cmd_i() @@ -610,8 +610,8 @@ void NACT_Sys3::cmd_t() TRACE("T %d,%d:", x, y); // x方向はカラム単位で切り捨て - ags->text.pos.x = column ? x * 8 : x & 0xfff8; - ags->text.pos.y = y; + text.pos.x = column ? x * 8 : x & 0xfff8; + text.pos.y = y; } void NACT_Sys3::cmd_u() @@ -776,17 +776,17 @@ void NACT_Sys3::exec_y(int cmd, int param) case 24: break; case 25: - ags->menu.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + menu.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; break; case 26: - ags->text.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; + text.font_size = (param == 1) ? 16 : (param == 2) ? 24 : (param == 3) ? 32 : (param == 4) ? 48 : (param == 5) ? 64 : 16; break; case 27: tvar_maxlen = param; text_dialog(); break; case 28: - ags->text.line_space = (param == 0) ? 2 : 0; + text.line_space = (param == 0) ? 2 : 0; break; case 30: ags->src_screen = param ? 1 : 0; @@ -907,12 +907,12 @@ void NACT_Sys3::exec_y(int cmd, int param) case 228: case 229: { - ags->draw_text(tvar[param - 1]); + draw_text(tvar[param - 1]); int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); if (padlen > 0) { char pad[10] = " "; pad[padlen] = '\0'; - ags->draw_text(pad); + draw_text(pad); } } break; @@ -977,7 +977,7 @@ void NACT_Sys3::exec_y(int cmd, int param) } break; case 240: - ags->draw_hankaku = (param == 1) ? true : false; + draw_hankaku = (param == 1) ? true : false; break; case 241: break; @@ -1033,17 +1033,17 @@ void NACT_Sys3::cmd_z() if(cmd == 0) { ags->palette_bank = (uint8)(param & 0xff); } else if(cmd == 1) { - ags->text.font_color = (uint8)(param & 0xff); + text.font_color = (uint8)(param & 0xff); } else if(cmd == 2) { - ags->menu.font_color = (uint8)(param & 0xff); + menu.font_color = (uint8)(param & 0xff); } else if(cmd == 3) { - ags->menu.frame_color = (uint8)(param & 0xff); + menu.frame_color = (uint8)(param & 0xff); } else if(cmd == 4) { - ags->menu.back_color = (uint8)(param & 0xff); + menu.back_color = (uint8)(param & 0xff); } else if(cmd == 5) { - ags->text.frame_color = (uint8)(param & 0xff); + text.frame_color = (uint8)(param & 0xff); } else if(cmd == 6) { - ags->text.back_color = (uint8)(param & 0xff); + text.back_color = (uint8)(param & 0xff); } else if(cmd == 7) { ags->cursor_color = (uint8)(param & 0xff); } else if(101 <= cmd && cmd <= 199) { @@ -1195,15 +1195,15 @@ bool NACT_Sys3::k3_hack(const K3HackInfo* info_table) ags->draw_window( info->left - 6, info->top - 6, info->left + info->w * info->cols + 6, info->top + info->h + 6, - true, ags->menu.frame_color, ags->menu.back_color); - int orig_font_size = ags->text.font_size; - ags->text.pos.x = info->left; - ags->text.pos.y = info->top; - ags->text.font_size = info->w; - ags->draw_text("12345"); - ags->text.font_size = orig_font_size; + true, menu.frame_color, menu.back_color); + int orig_font_size = text.font_size; + text.pos.x = info->left; + text.pos.y = info->top; + text.font_size = info->w; + draw_text("12345"); + text.font_size = orig_font_size; int left = info->left + info->w * (var[info->var] - 1); - ags->box_line(0, left, info->top, left + info->w, info->top + info->h, ags->text.font_color); + ags->box_line(0, left, info->top, left + info->w, info->top + info->h, text.font_color); } // Only You: Prevents the cursor from being locked due to unselectable cells. @@ -1297,7 +1297,7 @@ public: void cmd_p() override { int p1 = cali(); TRACE("P %d:", p1); - ags->text.font_color = p1; + text.font_color = p1; } void cmd_t() override { diff --git a/src/sys/nact_text.cpp b/src/sys/nact_text.cpp new file mode 100644 index 0000000..a529145 --- /dev/null +++ b/src/sys/nact_text.cpp @@ -0,0 +1,417 @@ +/* + ALICE SOFT SYSTEM 3 for Win32 + + [ NACT - text ] +*/ + +#include +#include "nact.h" +#include "ags.h" +#include "encoding.h" +#include "texthook.h" + +namespace { + +int convert_to_zenkaku(int code) +{ + switch(code) { + case u' ': return u' '; + case u'!': return u'!'; + case u'"': return u'”'; + case u'#': return u'#'; + case u'$': return u'$'; + case u'%': return u'%'; + case u'&': return u'&'; + case u'\'': return u'’'; + case u'(': return u'('; + case u')': return u')'; + case u'*': return u'*'; + case u'+': return u'+'; + case u',': return u','; + case u'-': return u'-'; + case u'.': return u'.'; + case u'/': return u'/'; + case u'0': return u'0'; + case u'1': return u'1'; + case u'2': return u'2'; + case u'3': return u'3'; + case u'4': return u'4'; + case u'5': return u'5'; + case u'6': return u'6'; + case u'7': return u'7'; + case u'8': return u'8'; + case u'9': return u'9'; + case u':': return u':'; + case u';': return u';'; + case u'<': return u'<'; + case u'=': return u'='; + case u'>': return u'>'; + case u'?': return u'?'; + case u'@': return u'@'; + case u'A': return u'A'; + case u'B': return u'B'; + case u'C': return u'C'; + case u'D': return u'D'; + case u'E': return u'E'; + case u'F': return u'F'; + case u'G': return u'G'; + case u'H': return u'H'; + case u'I': return u'I'; + case u'J': return u'J'; + case u'K': return u'K'; + case u'L': return u'L'; + case u'M': return u'M'; + case u'N': return u'N'; + case u'O': return u'O'; + case u'P': return u'P'; + case u'Q': return u'Q'; + case u'R': return u'R'; + case u'S': return u'S'; + case u'T': return u'T'; + case u'U': return u'U'; + case u'V': return u'V'; + case u'W': return u'W'; + case u'X': return u'X'; + case u'Y': return u'Y'; + case u'Z': return u'Z'; + case u'[': return u'['; + case u'\\': return u'¥'; + case u']': return u']'; + case u'^': return u'^'; + case u'_': return u'_'; + case u'`': return u'‘'; + case u'a': return u'a'; + case u'b': return u'b'; + case u'c': return u'c'; + case u'd': return u'd'; + case u'e': return u'e'; + case u'f': return u'f'; + case u'g': return u'g'; + case u'h': return u'h'; + case u'i': return u'i'; + case u'j': return u'j'; + case u'k': return u'k'; + case u'l': return u'l'; + case u'm': return u'm'; + case u'n': return u'n'; + case u'o': return u'o'; + case u'p': return u'p'; + case u'q': return u'q'; + case u'r': return u'r'; + case u's': return u's'; + case u't': return u't'; + case u'u': return u'u'; + case u'v': return u'v'; + case u'w': return u'w'; + case u'x': return u'x'; + case u'y': return u'y'; + case u'z': return u'z'; + case u'{': return u'{'; + case u'|': return u'|'; + case u'}': return u'}'; + case u'~': return u'~'; + case u'。': return u'。'; + case u'「': return u'「'; + case u'」': return u'」'; + case u'、': return u'、'; + case u'・': return u'・'; + case u'ヲ': return u'を'; + case u'ァ': return u'ぁ'; + case u'ィ': return u'ぃ'; + case u'ゥ': return u'ぅ'; + case u'ェ': return u'ぇ'; + case u'ォ': return u'ぉ'; + case u'ャ': return u'ゃ'; + case u'ュ': return u'ゅ'; + case u'ョ': return u'ょ'; + case u'ッ': return u'っ'; + case u'ー': return u'ー'; + case u'ア': return u'あ'; + case u'イ': return u'い'; + case u'ウ': return u'う'; + case u'エ': return u'え'; + case u'オ': return u'お'; + case u'カ': return u'か'; + case u'キ': return u'き'; + case u'ク': return u'く'; + case u'ケ': return u'け'; + case u'コ': return u'こ'; + case u'サ': return u'さ'; + case u'シ': return u'し'; + case u'ス': return u'す'; + case u'セ': return u'せ'; + case u'ソ': return u'そ'; + case u'タ': return u'た'; + case u'チ': return u'ち'; + case u'ツ': return u'つ'; + case u'テ': return u'て'; + case u'ト': return u'と'; + case u'ナ': return u'な'; + case u'ニ': return u'に'; + case u'ヌ': return u'ぬ'; + case u'ネ': return u'ね'; + case u'ノ': return u'の'; + case u'ハ': return u'は'; + case u'ヒ': return u'ひ'; + case u'フ': return u'ふ'; + case u'ヘ': return u'へ'; + case u'ホ': return u'ほ'; + case u'マ': return u'ま'; + case u'ミ': return u'み'; + case u'ム': return u'む'; + case u'メ': return u'め'; + case u'モ': return u'も'; + case u'ヤ': return u'や'; + case u'ユ': return u'ゆ'; + case u'ヨ': return u'よ'; + case u'ラ': return u'ら'; + case u'リ': return u'り'; + case u'ル': return u'る'; + case u'レ': return u'れ'; + case u'ロ': return u'ろ'; + case u'ワ': return u'わ'; + case u'ン': return u'ん'; + case u'゙': return u'゛'; + case u'゚': return u'゜'; + } + return code; +} + +int convert_to_hankaku(int code) +{ + switch(code) { + case u' ': return u' '; + case u'!': return u'!'; + case u'”': return u'"'; + case u'#': return u'#'; + case u'$': return u'$'; + case u'%': return u'%'; + case u'&': return u'&'; + case u'’': return u'\''; + case u'(': return u'('; + case u')': return u')'; + case u'*': return u'*'; + case u'+': return u'+'; + case u',': return u','; + case u'-': return u'-'; + case u'.': return u'.'; + case u'/': return u'/'; + case u'0': return u'0'; + case u'1': return u'1'; + case u'2': return u'2'; + case u'3': return u'3'; + case u'4': return u'4'; + case u'5': return u'5'; + case u'6': return u'6'; + case u'7': return u'7'; + case u'8': return u'8'; + case u'9': return u'9'; + case u':': return u':'; + case u';': return u';'; + case u'<': return u'<'; + case u'=': return u'='; + case u'>': return u'>'; + case u'?': return u'?'; + case u'@': return u'@'; + case u'A': return u'A'; + case u'B': return u'B'; + case u'C': return u'C'; + case u'D': return u'D'; + case u'E': return u'E'; + case u'F': return u'F'; + case u'G': return u'G'; + case u'H': return u'H'; + case u'I': return u'I'; + case u'J': return u'J'; + case u'K': return u'K'; + case u'L': return u'L'; + case u'M': return u'M'; + case u'N': return u'N'; + case u'O': return u'O'; + case u'P': return u'P'; + case u'Q': return u'Q'; + case u'R': return u'R'; + case u'S': return u'S'; + case u'T': return u'T'; + case u'U': return u'U'; + case u'V': return u'V'; + case u'W': return u'W'; + case u'X': return u'X'; + case u'Y': return u'Y'; + case u'Z': return u'Z'; + case u'[': return u'['; + case u'¥': return u'\\'; + case u']': return u']'; + case u'^': return u'^'; + case u'_': return u'_'; + case u'‘': return u'`'; + case u'a': return u'a'; + case u'b': return u'b'; + case u'c': return u'c'; + case u'd': return u'd'; + case u'e': return u'e'; + case u'f': return u'f'; + case u'g': return u'g'; + case u'h': return u'h'; + case u'i': return u'i'; + case u'j': return u'j'; + case u'k': return u'k'; + case u'l': return u'l'; + case u'm': return u'm'; + case u'n': return u'n'; + case u'o': return u'o'; + case u'p': return u'p'; + case u'q': return u'q'; + case u'r': return u'r'; + case u's': return u's'; + case u't': return u't'; + case u'u': return u'u'; + case u'v': return u'v'; + case u'w': return u'w'; + case u'x': return u'x'; + case u'y': return u'y'; + case u'z': return u'z'; + case u'{': return u'{'; + case u'|': return u'|'; + case u'}': return u'}'; + case u'~': return u'~'; + case u'。': return u'。'; + case u'「': return u'「'; + case u'」': return u'」'; + case u'、': return u'、'; + case u'・': return u'・'; + case u'ヲ': return u'を'; + case u'ァ': return u'ぁ'; + case u'ィ': return u'ぃ'; + case u'ゥ': return u'ぅ'; + case u'ェ': return u'ぇ'; + case u'ォ': return u'ぉ'; + case u'ャ': return u'ゃ'; + case u'ュ': return u'ゅ'; + case u'ョ': return u'ょ'; + case u'ッ': return u'っ'; + case u'ー': return u'ー'; + case u'ア': return u'あ'; + case u'イ': return u'い'; + case u'ウ': return u'う'; + case u'エ': return u'え'; + case u'オ': return u'お'; + case u'カ': return u'か'; + case u'キ': return u'き'; + case u'ク': return u'く'; + case u'ケ': return u'け'; + case u'コ': return u'こ'; + case u'サ': return u'さ'; + case u'シ': return u'し'; + case u'ス': return u'す'; + case u'セ': return u'せ'; + case u'ソ': return u'そ'; + case u'タ': return u'た'; + case u'チ': return u'ち'; + case u'ツ': return u'つ'; + case u'テ': return u'て'; + case u'ト': return u'と'; + case u'ナ': return u'な'; + case u'ニ': return u'に'; + case u'ヌ': return u'ぬ'; + case u'ネ': return u'ね'; + case u'ノ': return u'の'; + case u'ハ': return u'は'; + case u'ヒ': return u'ひ'; + case u'フ': return u'ふ'; + case u'ヘ': return u'へ'; + case u'ホ': return u'ほ'; + case u'マ': return u'ま'; + case u'ミ': return u'み'; + case u'ム': return u'む'; + case u'メ': return u'め'; + case u'モ': return u'も'; + case u'ヤ': return u'や'; + case u'ユ': return u'ゆ'; + case u'ヨ': return u'よ'; + case u'ラ': return u'ら'; + case u'リ': return u'り'; + case u'ル': return u'る'; + case u'レ': return u'れ'; + case u'ロ': return u'ろ'; + case u'ワ': return u'わ'; + case u'ン': return u'ん'; + case u'゙': return u'゛'; + case u'゚': return u'゜'; + } + return code; +} + +} // namespace + +void NACT::init_text() +{ + text.reset_pos(text_w[0].sx, text_w[0].sy + 2); + text.line_space = 2; + text.font_size = 16; + if (game_id.sys_ver == 1) { + text.font_color = 15 + 16; + text.frame_color = 15 + 16; + text.back_color = 0 + 16; + } else { + text.font_color = 15; + text.frame_color = 15; + text.back_color = 0; + } + + menu.reset_pos(2, 2); + menu.line_space = 4; + menu.font_size = 16; + if (game_id.sys_ver == 1) { + menu.font_color = 15 + 16; + menu.frame_color = 15 + 16; + menu.back_color = 0 + 16; + } else { + menu.font_color = 15; + menu.frame_color = 15; + menu.back_color = 0; + } +} + +void NACT::draw_text(std::string_view string, bool wait) +{ + if (string.empty()) + return; + + TextContext& ctx = draw_menu ? menu : text; + int screen = draw_menu ? 2 : ags->dest_screen; + if (ctx.current_line_height < ctx.font_size) + ctx.current_line_height = ctx.font_size; + + std::u16string codes; + while (!string.empty()) { + int code = encoding->next_codepoint(string); + if (draw_hankaku) { + code = convert_to_hankaku(code); + } else { + code = convert_to_zenkaku(code); + } + if (!draw_menu && !(GAIJI_FIRST <= code && code <= GAIJI_LAST)) + texthook_character(sco.page(), code); + codes.push_back(code); + } + + if (draw_menu || !wait) { + ctx.pos.x = ags->draw_text(screen, ctx.pos.x, ctx.pos.y, codes, ctx.font_size, ctx.font_color); + return; + } + + // Typewriter effect. + std::u16string_view rest(codes); + for (;;) { + size_t next_nonspace = rest.find_first_not_of(u' '); + if (next_nonspace == std::u16string_view::npos) + break; + ctx.pos.x = ags->draw_text(screen, ctx.pos.x, ctx.pos.y, rest.substr(0, next_nonspace + 1), + ctx.font_size, ctx.font_color); + rest.remove_prefix(next_nonspace + 1); + text_wait(); + } + if (!rest.empty()) + ctx.pos.x = ags->draw_text(screen, ctx.pos.x, ctx.pos.y, rest, ctx.font_size, ctx.font_color); +} diff --git a/src/sys/nact_window.cpp b/src/sys/nact_window.cpp index efa1629..1dbb93f 100644 --- a/src/sys/nact_window.cpp +++ b/src/sys/nact_window.cpp @@ -128,20 +128,20 @@ void NACT::clear_text_window(int index, bool erase) if (erase) { if (w.frame && ags->is_faded()) { - ags->draw_window(w.sx - 8, w.sy - 8, w.ex + 8, w.ey + 8, true, ags->text.frame_color, ags->text.back_color); + ags->draw_window(w.sx - 8, w.sy - 8, w.ex + 8, w.ey + 8, true, text.frame_color, text.back_color); } else { - ags->box_fill(0, w.sx, w.sy, w.ex, w.ey, ags->text.back_color); + ags->box_fill(0, w.sx, w.sy, w.ex, w.ey, text.back_color); } } - ags->text.reset_pos(w.sx, w.sy + 2); + text.reset_pos(w.sx, w.sy + 2); } bool NACT::return_text_line(int index) { - ags->text.newline(); + text.newline(); // Return true if the next line exceeds the bottom of the window - return ags->text.pos.y + ags->text.font_size > text_w[index - 1].ey; + return text.pos.y + text.font_size > text_w[index - 1].ey; } void NACT::draw_push(int index) @@ -156,7 +156,7 @@ void NACT::draw_push(int index) Window& w = text_w[index - 1]; int x = w.ex - 16; int y = w.ey - 16; - ags->draw_gaiji(0, x, y, push_bitmap ? push_bitmap : builtin_bitmap, 16, ags->text.font_color); + ags->draw_gaiji(0, x, y, push_bitmap ? push_bitmap : builtin_bitmap, 16, text.font_color); ags->invalidate_screen(x, y, 16, 16); } @@ -181,12 +181,12 @@ void NACT::open_text_window(int index, bool erase) } if (erase) { - ags->draw_window(sx, sy, ex, ey, w.frame, ags->text.frame_color, ags->text.back_color); + ags->draw_window(sx, sy, ex, ey, w.frame, text.frame_color, text.back_color); } else if (w.save && w.window) { ags->restore_rect(w.window); } - ags->text.reset_pos(w.sx, w.sy + ags->text.line_space); + text.reset_pos(w.sx, w.sy + text.line_space); } void NACT::close_text_window(int index, bool update) @@ -208,14 +208,14 @@ void NACT::close_text_window(int index, bool update) } if (update) { - ags->text.reset_pos(w.sx, w.sy + ags->text.line_space); + text.reset_pos(w.sx, w.sy + text.line_space); } } void NACT::clear_menu_window() { - ags->box_fill(2, 0, 0, 639, 479, ags->menu.back_color); - ags->menu.reset_pos(2, 2); + ags->box_fill(2, 0, 0, 639, 479, menu.back_color); + menu.reset_pos(2, 2); } void NACT::open_menu_window(int index) @@ -224,7 +224,7 @@ void NACT::open_menu_window(int index) int sx = w.sx; int sy = w.sy; int ex = w.ex; - int ey = menu_fix ? w.ey : sy + ags->menu.pos.y - 3; + int ey = menu_fix ? w.ey : sy + menu.pos.y - 3; int width = ex - sx + 1; int height = ey - sy + 1; int wsx = sx - (w.frame ? 8 : 0); @@ -238,9 +238,9 @@ void NACT::open_menu_window(int index) w.screen = ags->save_rect(wsx, wsy, wwidth, wheight); } - ags->draw_window(wsx, wsy, wex, wey, w.frame, ags->menu.frame_color, ags->menu.back_color); + ags->draw_window(wsx, wsy, wex, wey, w.frame, menu.frame_color, menu.back_color); ags->copy_screen(2, 0, 0, 0, width - 1, height - 1, sx, sy); - ags->box_line(0, sx, sy, ex, sy + ags->menu.font_size + 3, ags->menu.frame_color); + ags->box_line(0, sx, sy, ex, sy + menu.font_size + 3, menu.frame_color); ags->invalidate_screen(wsx, wsy, wwidth, wheight); } @@ -250,12 +250,12 @@ void NACT::redraw_menu_window(int index, int selected) int sx = w.sx; int sy = w.sy; int ex = w.ex; - int ey = menu_fix ? w.ey : sy + ags->menu.pos.y - 3; + int ey = menu_fix ? w.ey : sy + menu.pos.y - 3; int width = ex - sx + 1; int height = ey - sy + 1; ags->copy_screen(2, 0, 0, 0, width - 1, height - 1, sx, sy); - ags->box_line(0, sx, sy + (ags->menu.font_size + 4) * selected, ex, sy + (ags->menu.font_size + 4) * (selected + 1) - 1, ags->menu.frame_color); + ags->box_line(0, sx, sy + (menu.font_size + 4) * selected, ex, sy + (menu.font_size + 4) * (selected + 1) - 1, menu.frame_color); ags->invalidate_screen(sx, sy, width, height); } @@ -281,24 +281,24 @@ int NACT::calculate_menu_max(int window) if (game_id.is(GameId::INTRUDER)) return 6; if (game_id.is(GameId::GAKUEN_SENKI)) - return (menu_w[window - 1].ey - menu_w[window - 1].sy) / (ags->menu.font_size + 4); + return (menu_w[window - 1].ey - menu_w[window - 1].sy) / (menu.font_size + 4); return 11; } void NACT::load_display_state(FILEIO* fio) { - ags->menu.font_size = fio->getw(); - ags->text.font_size = fio->getw(); + menu.font_size = fio->getw(); + text.font_size = fio->getw(); ags->palette_bank = fio->getw(); if (!ags->palette_bank) { ags->palette_bank = -1; } - ags->text.font_color = fio->getw(); - ags->menu.font_color = fio->getw(); - ags->menu.frame_color = fio->getw(); - ags->menu.back_color = fio->getw(); - ags->text.frame_color = fio->getw(); - ags->text.back_color = fio->getw(); + text.font_color = fio->getw(); + menu.font_color = fio->getw(); + menu.frame_color = fio->getw(); + menu.back_color = fio->getw(); + text.frame_color = fio->getw(); + text.back_color = fio->getw(); for (int i = 0; i < 10; i++) { int sx = fio->getw(); int sy = fio->getw(); @@ -325,15 +325,15 @@ void NACT::load_display_state(FILEIO* fio) void NACT::save_display_state(FILEIO* fio) { - fio->putw(ags->menu.font_size); - fio->putw(ags->text.font_size); + fio->putw(menu.font_size); + fio->putw(text.font_size); fio->putw(ags->palette_bank == -1 ? 0 : ags->palette_bank); - fio->putw(ags->text.font_color); - fio->putw(ags->menu.font_color); - fio->putw(ags->menu.frame_color); - fio->putw(ags->menu.back_color); - fio->putw(ags->text.frame_color); - fio->putw(ags->text.back_color); + fio->putw(text.font_color); + fio->putw(menu.font_color); + fio->putw(menu.frame_color); + fio->putw(menu.back_color); + fio->putw(text.frame_color); + fio->putw(text.back_color); for (int i = 0; i < 10; i++) { fio->putw(menu_w[i].sx); fio->putw(menu_w[i].sy);