From da91f107794636d02b39e4a1abacfc7ba55719a2 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 11 Sep 2021 11:10:02 +0900 Subject: [PATCH] Allow overriding hard-coded strings by system3.ini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some strings ("戻る" and "次のページ" in menu, character names in DPS) are not included in game files but are hard-coded in the executable. Now those strings can be overridden by adding [string] section to system3.ini. For example, system3.ini for English translation of DPS may look like this: [config] game = dps title = D.P.S - Dream Program System [string] back = Back next_page = Next Page dps_custom = Custom dps_linus = Linus dps_katsumi = Katsumi dps_yumiko = Yumiko dps_itsumi = Itsumi dps_hitomi = Hitomi dps_mariko = Mariko --- src/CMakeLists.txt | 1 - src/config.cpp | 53 ++++++++++++++++++++++++++++++++++++++++ src/config.h | 21 ++++++++++++++-- src/sys/localization.cpp | 30 ----------------------- src/sys/localization.h | 19 -------------- src/sys/nact.cpp | 2 +- src/sys/nact.h | 8 ++++-- src/sys/nact_sys1.cpp | 17 ++++++++----- src/sys/nact_sys2.cpp | 2 +- src/sys/nact_sys3.cpp | 2 +- 10 files changed, 92 insertions(+), 63 deletions(-) delete mode 100644 src/sys/localization.cpp delete mode 100644 src/sys/localization.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6d9b81b..f3f2928 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -163,7 +163,6 @@ target_sources(system3 PRIVATE sys/nact_sys1.cpp sys/nact_sys2.cpp sys/nact_sys3.cpp - sys/localization.cpp ) target_compile_definitions(system3 PRIVATE diff --git a/src/config.cpp b/src/config.cpp index d8ba996..77946f3 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -10,6 +10,7 @@ #else #include #endif +#include "encoding.h" #define INIFILENAME "system3.ini" @@ -53,6 +54,13 @@ std::pair parse_keyval(char *line) return { trim(line), trim(eq + 1) }; } +void init_string(std::string& s, Encoding* encoding, const char *dflt) +{ + char *encoded = encoding->fromUtf8(s.empty() ? dflt : s.c_str()); + s = encoded; + free(encoded); +} + } // namespace Config::Config(int argc, char *argv[]) @@ -97,6 +105,7 @@ void Config::load_ini() enum { NO_SECTION, CONFIG, + STRING, } current_section = NO_SECTION; char line[256]; @@ -109,6 +118,8 @@ void Config::load_ini() if (sscanf(line, "[%[^]]]", val)) { if (strcasecmp(val, "config") == 0) current_section = CONFIG; + else if (strcasecmp(val, "string") == 0) + current_section = STRING; else WARNING(INIFILENAME ":%d Unknown section \"%s\"", lineno, val); } else if (current_section == CONFIG) { @@ -136,9 +147,51 @@ void Config::load_ini() title = val; else WARNING(INIFILENAME ":%d unknown key '%s'", lineno, key); + } else if (current_section == STRING) { + char *key, *val; + std::tie(key, val) = parse_keyval(line); + if (!key && !is_empty_line(line)) { + WARNING(INIFILENAME ":%d parse error", lineno); + continue; + } + if (!strcasecmp(key, "back")) + strings.back = val; + else if (!strcasecmp(key, "next_page")) + strings.next_page = val; + else if (!strcasecmp(key, "dps_custom")) + strings.dps_custom = val; + else if (!strcasecmp(key, "dps_linus")) + strings.dps_linus = val; + else if (!strcasecmp(key, "dps_katsumi")) + strings.dps_katsumi = val; + else if (!strcasecmp(key, "dps_yumiko")) + strings.dps_yumiko = val; + else if (!strcasecmp(key, "dps_itsumi")) + strings.dps_itsumi = val; + else if (!strcasecmp(key, "dps_hitomi")) + strings.dps_hitomi = val; + else if (!strcasecmp(key, "dps_mariko")) + strings.dps_mariko = val; + else + WARNING(INIFILENAME ":%d unknown key '%s'", lineno, key); } else if (!is_empty_line(line)) { WARNING(INIFILENAME ":%d parse error", lineno); } } fclose(fp); } + +Strings Config::get_strings(Encoding* encoding, bool english) const +{ + Strings strs = strings; + init_string(strs.back, encoding, english ? "Back" : u8"戻る"); + init_string(strs.next_page, encoding, english ? "Next Page" : u8"次のページ"); + init_string(strs.dps_custom, encoding, u8"カスタム"); + init_string(strs.dps_linus, encoding, u8"リーナス"); + init_string(strs.dps_katsumi, encoding, u8"かつみ"); + init_string(strs.dps_yumiko, encoding, u8"由美子"); + init_string(strs.dps_itsumi, encoding, u8"いつみ"); + init_string(strs.dps_hitomi, encoding, u8"ひとみ"); + init_string(strs.dps_mariko, encoding, u8"真理子"); + return strs; +} diff --git a/src/config.h b/src/config.h index 90ccbc8..25f0bc6 100644 --- a/src/config.h +++ b/src/config.h @@ -3,8 +3,25 @@ #include +class Encoding; + +struct Strings { + std::string back; + std::string next_page; + std::string dps_custom; + std::string dps_linus; + std::string dps_katsumi; + std::string dps_yumiko; + std::string dps_itsumi; + std::string dps_hitomi; + std::string dps_mariko; +}; + struct Config { public: + Config(int argc, char *argv[]); + Strings get_strings(Encoding* encoding, bool english) const; + std::string font_file; std::string game_id; std::string encoding; @@ -14,10 +31,10 @@ struct Config { bool use_fm = false; bool no_antialias = false; - Config(int argc, char *argv[]); - private: void load_ini(); + + Strings strings; }; #endif // CONFIG_H_ diff --git a/src/sys/localization.cpp b/src/sys/localization.cpp deleted file mode 100644 index e813314..0000000 --- a/src/sys/localization.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "localization.h" -#include "encoding.h" - -Strings::Strings(Language lang, Encoding* encoding) -{ - switch (lang) { - case JAPANESE: - back = encoding->fromUtf8(u8"戻る"); - next_page = encoding->fromUtf8(u8"次のページ"); - dps_initial_tvars[0] = encoding->fromUtf8(u8"カスタム"); - dps_initial_tvars[1] = encoding->fromUtf8(u8"リーナス"); - dps_initial_tvars[2] = encoding->fromUtf8(u8"かつみ"); - dps_initial_tvars[3] = encoding->fromUtf8(u8"由美子"); - dps_initial_tvars[4] = encoding->fromUtf8(u8"いつみ"); - dps_initial_tvars[5] = encoding->fromUtf8(u8"ひとみ"); - dps_initial_tvars[6] = encoding->fromUtf8(u8"真理子"); - break; - case ENGLISH: - back = "Back"; - next_page = "Next Page"; - dps_initial_tvars[0] = "Custom"; - dps_initial_tvars[1] = "Linus"; - dps_initial_tvars[2] = "Katsumi"; - dps_initial_tvars[3] = "Yumiko"; - dps_initial_tvars[4] = "Itsumi"; - dps_initial_tvars[5] = "Hitomi"; - dps_initial_tvars[6] = "Mariko"; - break; - } -} diff --git a/src/sys/localization.h b/src/sys/localization.h deleted file mode 100644 index e4ab3c0..0000000 --- a/src/sys/localization.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _LOCALIZATION_H_ -#define _LOCALIZATION_H_ - -class Encoding; - -enum Language { - JAPANESE = 0, - ENGLISH = 1, -}; - -struct Strings { - Strings(Language lang, Encoding* encoding); - - const char* back; - const char* next_page; - const char* dps_initial_tvars[7]; -}; - -#endif // _LOCALIZATION_H_ diff --git a/src/sys/nact.cpp b/src/sys/nact.cpp index 21aeb6a..9142f49 100644 --- a/src/sys/nact.cpp +++ b/src/sys/nact.cpp @@ -25,7 +25,7 @@ NACT::NACT(int sys_ver, uint32 crc32_a, uint32 crc32_b, const Config& config) crc32_b(crc32_b), config(config), encoding(Encoding::create(get_encoding_name())), - strings(get_language(), encoding.get()) + strings(config.get_strings(encoding.get(), get_language() == ENGLISH)) { platform_initialize(); diff --git a/src/sys/nact.h b/src/sys/nact.h index e99f459..f8693be 100644 --- a/src/sys/nact.h +++ b/src/sys/nact.h @@ -11,7 +11,7 @@ #include #include #include "../common.h" -#include "localization.h" +#include "config.h" #define RND var[ 0] #define D01 var[ 1] @@ -84,7 +84,11 @@ class AGS; class MAKO; class MsgSkip; class Encoding; -struct Config; + +enum Language { + JAPANESE = 0, + ENGLISH = 1, +}; class NACT { diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp index 196065c..7f04d8d 100644 --- a/src/sys/nact_sys1.cpp +++ b/src/sys/nact_sys1.cpp @@ -75,8 +75,13 @@ NACT_Sys1::NACT_Sys1(uint32 crc32_a, uint32 crc32_b, const Config& config) //case CRC32_DPS_SG2: case CRC32_DPS_SG3: text_refresh = false; - for (int i = 0; i < 7; i++) - strcpy(tvar[i], strings.dps_initial_tvars[i]); + strcpy(tvar[0], strings.dps_custom.c_str()); + strcpy(tvar[1], strings.dps_linus.c_str()); + strcpy(tvar[2], strings.dps_katsumi.c_str()); + strcpy(tvar[3], strings.dps_yumiko.c_str()); + strcpy(tvar[4], strings.dps_itsumi.c_str()); + strcpy(tvar[5], strings.dps_hitomi.c_str()); + strcpy(tvar[6], strings.dps_mariko.c_str()); break; case CRC32_INTRUDER: paint_x = paint_y = map_page = 0; @@ -419,7 +424,7 @@ top2: // 次のページを追加 ags->menu_dest_x = 2; ags->menu_dest_y += 2; - ags->draw_text(strings.next_page); + ags->draw_text(strings.next_page.c_str()); id[index++] = -1; ags->menu_dest_y += ags->menu_font_size + 2; } @@ -490,7 +495,7 @@ top: // 戻るを追加 ags->menu_dest_x = 2; ags->menu_dest_y += 2; - ags->draw_text(strings.back); + ags->draw_text(strings.back.c_str()); id[index++] = 0; ags->menu_dest_y += ags->menu_font_size + 2; } else { @@ -516,14 +521,14 @@ top2: // 戻るを追加 ags->menu_dest_x = 2; ags->menu_dest_y += 2; - ags->draw_text(strings.back); + ags->draw_text(strings.back.c_str()); id[index++] = 0; ags->menu_dest_y += ags->menu_font_size + 2; // 次のページを追加 ags->menu_dest_x = 2; ags->menu_dest_y += 2; - ags->draw_text(strings.next_page); + ags->draw_text(strings.next_page.c_str()); id[index++] = -1; ags->menu_dest_y += ags->menu_font_size + 2; } diff --git a/src/sys/nact_sys2.cpp b/src/sys/nact_sys2.cpp index 7a16b0d..cb818d2 100644 --- a/src/sys/nact_sys2.cpp +++ b/src/sys/nact_sys2.cpp @@ -490,7 +490,7 @@ void NACT_Sys2::cmd_open_obj(int verb) // 戻るを追加 ags->menu_dest_x = 2; ags->menu_dest_y += 2; - ags->draw_text(strings.back); + ags->draw_text(strings.back.c_str()); id[index++] = 0; ags->menu_dest_y += ags->menu_font_size + 2; ags->draw_menu = false; diff --git a/src/sys/nact_sys3.cpp b/src/sys/nact_sys3.cpp index 810cdea..3dd5173 100644 --- a/src/sys/nact_sys3.cpp +++ b/src/sys/nact_sys3.cpp @@ -265,7 +265,7 @@ void NACT_Sys3::cmd_open_obj(int verb) // 戻るを追加 ags->menu_dest_x = 2; ags->menu_dest_y += 2; - ags->draw_text(strings.back); + ags->draw_text(strings.back.c_str()); id[index++] = 0; ags->menu_dest_y += ags->menu_font_size + 2; ags->draw_menu = false;