/*! * @file FontUtils.cpp * * Code for handling text and strings in Jak 1's "large font" format. * * MAKE SURE THIS FILE IS ENCODED IN UTF-8!!! The various strings here depend on it. * Always verify the encoding if string detection suddenly goes awry. */ #include "FontUtils.h" #include #include #include "string_util.h" #include "common/util/Assert.h" #include "fmt/core.h" #include "fmt/format.h" const std::unordered_map sTextVerEnumMap = { {"jak1-v1", GameTextVersion::JAK1_V1}, {"jak1-v2", GameTextVersion::JAK1_V2}, {"jak2", GameTextVersion::JAK2}, {"jak3", GameTextVersion::JAK3}}; const std::string& get_text_version_name(GameTextVersion version) { for (auto& [name, ver] : sTextVerEnumMap) { if (ver == version) { return name; } } throw std::runtime_error(fmt::format("invalid text version {}", fmt::underlying(version))); } GameTextVersion get_text_version_from_name(const std::string& name) { return sTextVerEnumMap.at(name); } GameTextFontBank::GameTextFontBank(GameTextVersion version, std::vector* encode_info, std::vector* replace_info, std::unordered_set* passthrus) : m_version(version), m_encode_info(encode_info), m_replace_info(replace_info), m_passthrus(passthrus) { std::sort( m_encode_info->begin(), m_encode_info->end(), [](const EncodeInfo& a, const EncodeInfo& b) { return a.bytes.size() > b.bytes.size(); }); std::sort( m_replace_info->begin(), m_replace_info->end(), [](const ReplaceInfo& a, const ReplaceInfo& b) { return a.from.size() > b.from.size(); }); } /*! * Finds a remap info that best matches the byte sequence (is the longest match). */ const EncodeInfo* GameTextFontBank::find_encode_to_utf8(const char* in) const { const EncodeInfo* best_info = nullptr; for (auto& info : *m_encode_info) { if (info.bytes.size() == 0) continue; bool found = true; for (int i = 0; found && i < (int)info.bytes.size(); ++i) { if (uint8_t(in[i]) != info.bytes.at(i)) { found = false; } } if (found && (!best_info || info.chars.length() > best_info->chars.length())) { best_info = &info; } } return best_info; } /*! * Finds a remap info that best matches the character sequence (is the longest match). */ const EncodeInfo* GameTextFontBank::find_encode_to_game(const std::string& in, int off) const { const EncodeInfo* best_info = nullptr; for (auto& info : *m_encode_info) { if (info.chars.length() == 0) continue; bool found = true; for (int i = 0; found && i < (int)info.chars.length() && i + off < (int)in.size(); ++i) { if (in.at(i + off) != info.chars.at(i)) { found = false; } } if (found && (!best_info || info.chars.length() > best_info->chars.length())) { best_info = &info; } } return best_info; } /*! * Finds a remap info that best matches the character sequence (is the longest match). */ const ReplaceInfo* GameTextFontBank::find_replace_to_utf8(const std::string& in, int off) const { const ReplaceInfo* best_info = nullptr; for (auto& info : *m_replace_info) { if (info.from.empty() || in.size() - off < info.from.size()) continue; bool found = memcmp(in.data() + off, info.from.data(), info.from.size()) == 0; if (found && (!best_info || info.from.length() > best_info->from.length())) { best_info = &info; } } return best_info; } /*! * Finds a remap info that best matches the character sequence (is the longest match). */ const ReplaceInfo* GameTextFontBank::find_replace_to_game(const std::string& in, int off) const { const ReplaceInfo* best_info = nullptr; for (auto& info : *m_replace_info) { if (info.to.empty() || in.size() - off < info.to.size()) continue; bool found = memcmp(in.data() + off, info.to.data(), info.to.size()) == 0; if (found && (!best_info || info.to.length() > best_info->to.length())) { best_info = &info; } } return best_info; } /*! * Try to replace specific substrings with better variants. * These are for hiding confusing text transforms. */ std::string GameTextFontBank::replace_to_utf8(std::string& str) const { std::string newstr; for (int i = 0; i < (int)str.length();) { auto remap = find_replace_to_utf8(str, i); if (!remap) { newstr.push_back(str.at(i)); i += 1; } else { for (auto b : remap->to) { newstr.push_back(b); } i += remap->from.length(); } } str = newstr; return str; } std::string GameTextFontBank::replace_to_game(std::string& str) const { std::string newstr; for (int i = 0; i < (int)str.length();) { auto remap = find_replace_to_game(str, i); if (!remap) { newstr.push_back(str.at(i)); i += 1; } else { for (auto b : remap->from) { newstr.push_back(b); } i += remap->to.length(); } } str = newstr; return str; } std::string GameTextFontBank::encode_utf8_to_game(std::string& str) const { std::string newstr; for (int i = 0; i < (int)str.length();) { auto remap = find_encode_to_game(str, i); if (!remap) { newstr.push_back(str.at(i)); i += 1; } else { for (auto b : remap->bytes) { newstr.push_back(b); } i += remap->chars.length(); } } str = newstr; return str; } /*! * Turn a normal readable string into a string readable in the in-game font encoding and converts * \cXX escape sequences */ // NOTE - the convert_utf8_to_game function is really really slow (about 80-90% of the // time loading the text files) // TODO - improve that as a follow up sometime in the future std::string GameTextFontBank::convert_utf8_to_game(std::string str, bool escape) const { std::string newstr; if (escape) { for (size_t i = 0; i < str.size(); ++i) { auto c = str.at(i); if (c == '"') { newstr.push_back('"'); i += 1; } else if (c == '\\') { if (i + 1 >= str.size()) { throw std::runtime_error("incomplete string escape code"); } auto p = str.at(i + 1); if (p == 'c') { if (i + 3 >= str.size()) { throw std::runtime_error("incomplete string escape code"); } auto first = str.at(i + 2); auto second = str.at(i + 3); if (!str_util::hex_char(first) || !str_util::hex_char(second)) { throw std::runtime_error("invalid character escape hex number"); } char hex_num[3] = {first, second, '\0'}; std::size_t end = 0; auto value = std::stoul(hex_num, &end, 16); if (end != 2) { throw std::runtime_error("invalid character escape"); } ASSERT(value < 256); newstr.push_back(char(value)); i += 3; } else if (p == '"' || p == '\\') { newstr.push_back(p); i += 1; } else { throw std::runtime_error( fmt::format("unknown string escape code '{}' (0x{:x})", p, u32(p))); } } else { newstr.push_back(c); } } } else { newstr = str; } replace_to_game(newstr); encode_utf8_to_game(newstr); return newstr; } bool GameTextFontBank::valid_char_range(const char in) const { if (m_version == GameTextVersion::JAK1_V1 || m_version == GameTextVersion::JAK1_V2) { return ((in >= '0' && in <= '9') || (in >= 'A' && in <= 'Z') || m_passthrus->find(in) != m_passthrus->end()) && in != '\\'; } else if (m_version == GameTextVersion::JAK2 || m_version == GameTextVersion::JAK3 || m_version == GameTextVersion::JAKX) { return ((in >= '0' && in <= '9') || (in >= 'A' && in <= 'Z') || (in >= 'a' && in <= 'z') || m_passthrus->find(in) != m_passthrus->end()) && in != '\\'; } return false; } /*! * Convert a string from the game-text font encoding to something normal. * Unprintable characters become escape sequences, including tab and newline. */ std::string GameTextFontBank::convert_game_to_utf8(const char* in) const { std::string temp; std::string result; while (*in) { auto remap = find_encode_to_utf8(in); if (remap != nullptr) { temp.append(remap->chars); in += remap->bytes.size() - 1; } else if (valid_char_range(*in) || *in == '\n' || *in == '\t' || *in == '\\' || *in == '\"') { temp.push_back(*in); } else { temp += fmt::format("\\c{:02x}", uint8_t(*in)); } in++; } replace_to_utf8(temp); for (size_t i = 0; i < temp.length(); ++i) { auto c = temp.at(i); if (c == '\n') { result += "\\n"; } else if (c == '\t') { result += "\\t"; } else if (c == '\\') { if (i < temp.length() - 1 && temp.at(i + 1) == 'c') { result.push_back(c); } else { result += "\\\\"; } } else if (c == '"') { result += "\\\""; } else { result.push_back(c); } } return replace_to_utf8(result); } static std::vector s_encode_info_null = {}; static std::vector s_replace_info_null = {}; /*! * =========================== * GAME TEXT FONT BANK - JAK 1 * =========================== * This font is used in: * - Jak & Daxter: The Precursor Legacy (Black Label) */ static std::unordered_set s_passthrus_jak1 = {'~', ' ', ',', '.', '-', '+', '(', ')', '!', ':', '?', '=', '%', '*', '/', '#', ';', '<', '>', '@', '[', '_'}; static std::vector s_encode_info_jak1 = { // random {"ˇ", {0x10}}, // caron {"`", {0x11}}, // grave accent {"'", {0x12}}, // apostrophe {"^", {0x13}}, // circumflex {"", {0x14}}, // tilde {"¨", {0x15}}, // umlaut {"º", {0x16}}, // numero/overring {"¡", {0x17}}, // inverted exclamation mark {"¿", {0x18}}, // inverted question mark {"海", {0x1a}}, // umi {"Æ", {0x1b}}, // aesc {"界", {0x1c}}, // kai {"Ç", {0x1d}}, // c-cedilla {"学", {0x1e}}, // gaku {"ß", {0x1f}}, // eszett {"ワ", {0x24}}, // wa {"ヲ", {0x26}}, // wo {"ン", {0x27}}, // -n {"岩", {0x5c}}, // iwa {"旧", {0x5d}}, // kyuu {"空", {0x5e}}, // sora //{"掘", {0x5f}}, // horu {"ヮ", {0x60}}, // -wa {"撃", {0x61}}, // utsu {"賢", {0x62}}, // kashikoi {"湖", {0x63}}, // mizuumi {"口", {0x64}}, // kuchi {"行", {0x65}}, // iku {"合", {0x66}}, // ai {"士", {0x67}}, // shi {"寺", {0x68}}, // tera {"山", {0x69}}, // yama {"者", {0x6a}}, // mono {"所", {0x6b}}, // tokoro {"書", {0x6c}}, // kaku {"小", {0x6d}}, // shou {"沼", {0x6e}}, // numa {"上", {0x6f}}, // ue {"城", {0x70}}, // shiro {"場", {0x71}}, // ba {"出", {0x72}}, // shutsu {"闇", {0x73}}, // yami {"遺", {0x74}}, // nokosu {"黄", {0x75}}, // ki {"屋", {0x76}}, // ya {"下", {0x77}}, // shita {"家", {0x78}}, // ie {"火", {0x79}}, // hi {"花", {0x7a}}, // hana {"レ", {0x7b}}, // re {"Œ", {0x7c}}, // oe {"ロ", {0x7d}}, // ro {"青", {0x7f}}, // ao {"・", {0x90}}, // nakaguro {"゛", {0x91}}, // dakuten {"゜", {0x92}}, // handakuten {"ー", {0x93}}, // chouompu {"『", {0x94}}, // nijuukagikakko left {"』", {0x95}}, // nijuukagikakko right // hiragana {"ぁ", {0x96}}, // -a {"あ", {0x97}}, // a {"ぃ", {0x98}}, // -i {"い", {0x99}}, // i {"ぅ", {0x9a}}, // -u {"う", {0x9b}}, // u {"ぇ", {0x9c}}, // -e {"え", {0x9d}}, // e {"ぉ", {0x9e}}, // -o {"お", {0x9f}}, // o {"か", {0xa0}}, // ka {"き", {0xa1}}, // ki {"く", {0xa2}}, // ku {"け", {0xa3}}, // ke {"こ", {0xa4}}, // ko {"さ", {0xa5}}, // sa {"し", {0xa6}}, // shi {"す", {0xa7}}, // su {"せ", {0xa8}}, // se {"そ", {0xa9}}, // so {"た", {0xaa}}, // ta {"ち", {0xab}}, // chi {"っ", {0xac}}, // sokuon {"つ", {0xad}}, // tsu {"て", {0xae}}, // te {"と", {0xaf}}, // to {"な", {0xb0}}, // na {"に", {0xb1}}, // ni {"ぬ", {0xb2}}, // nu {"ね", {0xb3}}, // ne {"の", {0xb4}}, // no {"は", {0xb5}}, // ha {"ひ", {0xb6}}, // hi {"ふ", {0xb7}}, // hu {"へ", {0xb8}}, // he {"ほ", {0xb9}}, // ho {"ま", {0xba}}, // ma {"み", {0xbb}}, // mi {"む", {0xbc}}, // mu {"め", {0xbd}}, // me {"も", {0xbe}}, // mo {"ゃ", {0xbf}}, // youon ya {"や", {0xc0}}, // ya {"ゅ", {0xc1}}, // youon yu {"ゆ", {0xc2}}, // yu {"ょ", {0xc3}}, // youon yo {"よ", {0xc4}}, // yo {"ら", {0xc5}}, // ra {"り", {0xc6}}, // ri {"る", {0xc7}}, // ru {"れ", {0xc8}}, // re {"ろ", {0xc9}}, // ro {"ゎ", {0xca}}, // -wa {"わ", {0xcb}}, // wa {"を", {0xcc}}, // wo {"ん", {0xcd}}, // -n // katakana {"ァ", {0xce}}, // -a {"ア", {0xcf}}, // a {"ィ", {0xd0}}, // -i {"イ", {0xd1}}, // i {"ゥ", {0xd2}}, // -u {"ウ", {0xd3}}, // u {"ェ", {0xd4}}, // -e {"エ", {0xd5}}, // e {"ォ", {0xd6}}, // -o {"オ", {0xd7}}, // o {"カ", {0xd8}}, // ka {"キ", {0xd9}}, // ki {"ク", {0xda}}, // ku {"ケ", {0xdb}}, // ke {"コ", {0xdc}}, // ko {"サ", {0xdd}}, // sa {"シ", {0xde}}, // shi {"ス", {0xdf}}, // su {"セ", {0xe0}}, // se {"ソ", {0xe1}}, // so {"タ", {0xe2}}, // ta {"チ", {0xe3}}, // chi {"ッ", {0xe4}}, // sokuon {"ツ", {0xe5}}, // tsu {"テ", {0xe6}}, // te {"ト", {0xe7}}, // to {"ナ", {0xe8}}, // na {"ニ", {0xe9}}, // ni {"ヌ", {0xea}}, // nu {"ネ", {0xeb}}, // ne {"ノ", {0xec}}, // no {"ハ", {0xed}}, // ha {"ヒ", {0xee}}, // hi {"フ", {0xef}}, // hu {"ヘ", {0xf0}}, // he {"ホ", {0xf1}}, // ho {"マ", {0xf2}}, // ma {"ミ", {0xf3}}, // mi {"ム", {0xf4}}, // mu {"メ", {0xf5}}, // me {"モ", {0xf6}}, // mo {"ャ", {0xf7}}, // youon ya {"ヤ", {0xf8}}, // ya {"ュ", {0xf9}}, // youon yu {"ユ", {0xfa}}, // yu {"ョ", {0xfb}}, // youon yo {"ヨ", {0xfc}}, // yo {"ラ", {0xfd}}, // ra {"リ", {0xfe}}, // ri {"ル", {0xff}}, // ru // kanji 2 {"宝", {1, 0x01}}, // takara {"石", {1, 0x10}}, // ishi {"赤", {1, 0x11}}, // aka {"跡", {1, 0x12}}, // ato {"川", {1, 0x13}}, // kawa {"戦", {1, 0x14}}, // ikusa {"村", {1, 0x15}}, // mura {"隊", {1, 0x16}}, // tai {"台", {1, 0x17}}, // utena {"長", {1, 0x18}}, // osa {"鳥", {1, 0x19}}, // tori {"艇", {1, 0x1a}}, // tei {"洞", {1, 0x1b}}, // hora {"道", {1, 0x1c}}, // michi {"発", {1, 0x1d}}, // hatsu {"飛", {1, 0x1e}}, // tobu {"噴", {1, 0x1f}}, // fuku {"池", {1, 0xa0}}, // ike {"中", {1, 0xa1}}, // naka {"塔", {1, 0xa2}}, // tou {"島", {1, 0xa3}}, // shima {"部", {1, 0xa4}}, // bu {"砲", {1, 0xa5}}, // hou {"産", {1, 0xa6}}, // san {"眷", {1, 0xa7}}, // kaerimiru {"力", {1, 0xa8}}, // chikara {"緑", {1, 0xa9}}, // midori {"岸", {1, 0xaa}}, // kishi {"像", {1, 0xab}}, // zou {"谷", {1, 0xac}}, // tani {"心", {1, 0xad}}, // kokoro {"森", {1, 0xae}}, // mori {"水", {1, 0xaf}}, // mizu {"船", {1, 0xb0}}, // fune {"™", {1, 0xb1}}, // trademark }; static std::vector s_replace_info_jak1 = { // other {"A~Y~-21H~-5Vº~Z", "Å"}, {"N~Y~-6Hº~Z~+10H", "Nº"}, {"O~Y~-16H~-1V/~Z", "Ø"}, {"A~Y~-6H~+3V,~Z", "Ą"}, {"E~Y~-6H~+2V,~Z", "Ę"}, {"L~Y~-16H~+0V/~Z", "Ł"}, {"Z~Y~-21H~-5Vº~Z", "Ż"}, {"E~Y~-20H~-5Vº~Z", "Ė"}, {"C~Y~-20H~-4Vˇ~Z", "Č"}, {"S~Y~-22H~-4Vˇ~Z", "Š"}, {"Z~Y~-22H~-4Vˇ~Z", "Ž"}, {"U~Y~-13H~+2V,~Z", "Ų"}, {"U~Y~-18H~-10V-~Z", "Ū"}, {"I~Y~-8H~+1V,~Z", "Į"}, // tildes {"N~Y~-22H~-4V~Z", "Ñ"}, {"A~Y~-21H~-5V~Z", "Ã"}, // custom {"O~Y~-22H~-4V~Z", "Õ"}, // custom // acute accents {"A~Y~-21H~-5V'~Z", "Á"}, {"E~Y~-22H~-5V'~Z", "É"}, {"I~Y~-19H~-5V'~Z", "Í"}, {"O~Y~-22H~-4V'~Z", "Ó"}, {"U~Y~-24H~-3V'~Z", "Ú"}, {"C~Y~-21H~-5V'~Z", "Ć"}, {"N~Y~-21H~-5V'~Z", "Ń"}, {"S~Y~-21H~-5V'~Z", "Ś"}, {"Z~Y~-21H~-5V'~Z", "Ź"}, // double acute accents {"O~Y~-28H~-4V'~-9H'~Z", "Ő"}, // custom {"U~Y~-27H~-4V'~-12H'~Z", "Ű"}, // custom // circumflex {"A~Y~-20H~-4V^~Z", "Â"}, // custom {"E~Y~-20H~-5V^~Z", "Ê"}, {"I~Y~-19H~-5V^~Z", "Î"}, {"O~Y~-20H~-4V^~Z", "Ô"}, // custom {"U~Y~-24H~-3V^~Z", "Û"}, // grave accents {"A~Y~-21H~-5V`~Z", "À"}, {"E~Y~-22H~-5V`~Z", "È"}, {"I~Y~-19H~-5V`~Z", "Ì"}, {"O~Y~-22H~-4V`~Z", "Ò"}, // custom {"U~Y~-24H~-3V`~Z", "Ù"}, // umlaut {"A~Y~-21H~-5V¨~Z", "Ä"}, {"E~Y~-20H~-5V¨~Z", "Ë"}, {"I~Y~-19H~-5V¨~Z", "Ï"}, // custom {"O~Y~-22H~-4V¨~Z", "Ö"}, {"O~Y~-22H~-3V¨~Z", "ö"}, // dumb {"U~Y~-22H~-3V¨~Z", "Ü"}, // dakuten katakana {"~Yウ~Z゛", "ヴ"}, {"~Yカ~Z゛", "ガ"}, {"~Yキ~Z゛", "ギ"}, {"~Yク~Z゛", "グ"}, {"~Yケ~Z゛", "ゲ"}, {"~Yコ~Z゛", "ゴ"}, {"~Yサ~Z゛", "ザ"}, {"~Yシ~Z゛", "ジ"}, {"~Yス~Z゛", "ズ"}, {"~Yセ~Z゛", "ゼ"}, {"~Yソ~Z゛", "ゾ"}, {"~Yタ~Z゛", "ダ"}, {"~Yチ~Z゛", "ヂ"}, {"~Yツ~Z゛", "ヅ"}, {"~Yテ~Z゛", "デ"}, {"~Yト~Z゛", "ド"}, {"~Yハ~Z゛", "バ"}, {"~Yヒ~Z゛", "ビ"}, {"~Yフ~Z゛", "ブ"}, {"~Yヘ~Z゛", "ベ"}, {"~Yホ~Z゛", "ボ"}, // handakuten katakana {"~Yハ~Z゜", "パ"}, {"~Yヒ~Z゜", "ピ"}, {"~Yフ~Z゜", "プ"}, {"~Yヘ~Z゜", "ペ"}, {"~Yホ~Z゜", "ポ"}, // dakuten hiragana {"~Yか~Z゛", "が"}, {"~Yき~Z゛", "ぎ"}, {"~Yく~Z゛", "ぐ"}, {"~Yけ~Z゛", "げ"}, {"~Yこ~Z゛", "ご"}, {"~Yさ~Z゛", "ざ"}, {"~Yし~Z゛", "じ"}, {"~Yす~Z゛", "ず"}, {"~Yせ~Z゛", "ぜ"}, {"~Yそ~Z゛", "ぞ"}, {"~Yた~Z゛", "だ"}, {"~Yち~Z゛", "ぢ"}, {"~Yつ~Z゛", "づ"}, {"~Yて~Z゛", "で"}, {"~Yと~Z゛", "ど"}, {"~Yは~Z゛", "ば"}, {"~Yひ~Z゛", "び"}, {"~Yふ~Z゛", "ぶ"}, {"~Yへ~Z゛", "べ"}, {"~Yほ~Z゛", "ぼ"}, // handakuten hiragana {"~Yは~Z゜", "ぱ"}, {"~Yひ~Z゜", "ぴ"}, {"~Yふ~Z゜", "ぷ"}, {"~Yへ~Z゜", "ぺ"}, {"~Yほ~Z゜", "ぽ"}, // japanese punctuation {",~+8H", "、"}, {"~+8H ", " "}, // (hack) special case kanji {"~~", "世"}, // playstation buttons {"~Y~22L<~Z~Y~27L*~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, {"~Y~22L<~Z~Y~26L;~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, {"~Y~22L<~Z~Y~25L@~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, {"~Y~22L<~Z~Y~24L#~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, // custom }; GameTextFontBank g_font_bank_jak1_v1(GameTextVersion::JAK1_V1, &s_encode_info_jak1, &s_replace_info_jak1, &s_passthrus_jak1); /*! * ================================ * GAME TEXT FONT BANK - JAK 1 (v2) * ================================ * This font is used in: * - Jak & Daxter: The Precursor Legacy (PAL) * - ジャックXダクスター ~ 旧世界の遺産 * - Jak & Daxter: The Precursor Legacy (NTSC-U v2) * * It is the same as v1, but _ has been fixed and no longer overlaps 掘 */ static std::vector s_encode_info_jak1_v2 = { // random {"_", {0x03}}, // large space {"ˇ", {0x10}}, // caron {"`", {0x11}}, // grave accent {"'", {0x12}}, // apostrophe {"^", {0x13}}, // circumflex {"", {0x14}}, // tilde {"¨", {0x15}}, // umlaut {"º", {0x16}}, // numero/overring {"¡", {0x17}}, // inverted exclamation mark {"¿", {0x18}}, // inverted question mark {"海", {0x1a}}, // umi {"Æ", {0x1b}}, // aesc {"界", {0x1c}}, // kai {"Ç", {0x1d}}, // c-cedilla {"学", {0x1e}}, // gaku {"ß", {0x1f}}, // eszett {"ワ", {0x24}}, // wa {"ヲ", {0x26}}, // wo {"ン", {0x27}}, // -n {"岩", {0x5c}}, // iwa {"旧", {0x5d}}, // kyuu {"空", {0x5e}}, // sora {"掘", {0x5f}}, // horu {"ヮ", {0x60}}, // -wa {"撃", {0x61}}, // utsu {"賢", {0x62}}, // kashikoi {"湖", {0x63}}, // mizuumi {"口", {0x64}}, // kuchi {"行", {0x65}}, // iku {"合", {0x66}}, // ai {"士", {0x67}}, // shi {"寺", {0x68}}, // tera {"山", {0x69}}, // yama {"者", {0x6a}}, // mono {"所", {0x6b}}, // tokoro {"書", {0x6c}}, // kaku {"小", {0x6d}}, // shou {"沼", {0x6e}}, // numa {"上", {0x6f}}, // ue {"城", {0x70}}, // shiro {"場", {0x71}}, // ba {"出", {0x72}}, // shutsu {"闇", {0x73}}, // yami {"遺", {0x74}}, // nokosu {"黄", {0x75}}, // ki {"屋", {0x76}}, // ya {"下", {0x77}}, // shita {"家", {0x78}}, // ie {"火", {0x79}}, // hi {"花", {0x7a}}, // hana {"レ", {0x7b}}, // re {"Œ", {0x7c}}, // oe {"ロ", {0x7d}}, // ro {"青", {0x7f}}, // ao {"・", {0x90}}, // nakaguro {"゛", {0x91}}, // dakuten {"゜", {0x92}}, // handakuten {"ー", {0x93}}, // chouompu {"『", {0x94}}, // nijuukagikakko left {"』", {0x95}}, // nijuukagikakko right // hiragana {"ぁ", {0x96}}, // -a {"あ", {0x97}}, // a {"ぃ", {0x98}}, // -i {"い", {0x99}}, // i {"ぅ", {0x9a}}, // -u {"う", {0x9b}}, // u {"ぇ", {0x9c}}, // -e {"え", {0x9d}}, // e {"ぉ", {0x9e}}, // -o {"お", {0x9f}}, // o {"か", {0xa0}}, // ka {"き", {0xa1}}, // ki {"く", {0xa2}}, // ku {"け", {0xa3}}, // ke {"こ", {0xa4}}, // ko {"さ", {0xa5}}, // sa {"し", {0xa6}}, // shi {"す", {0xa7}}, // su {"せ", {0xa8}}, // se {"そ", {0xa9}}, // so {"た", {0xaa}}, // ta {"ち", {0xab}}, // chi {"っ", {0xac}}, // sokuon {"つ", {0xad}}, // tsu {"て", {0xae}}, // te {"と", {0xaf}}, // to {"な", {0xb0}}, // na {"に", {0xb1}}, // ni {"ぬ", {0xb2}}, // nu {"ね", {0xb3}}, // ne {"の", {0xb4}}, // no {"は", {0xb5}}, // ha {"ひ", {0xb6}}, // hi {"ふ", {0xb7}}, // hu {"へ", {0xb8}}, // he {"ほ", {0xb9}}, // ho {"ま", {0xba}}, // ma {"み", {0xbb}}, // mi {"む", {0xbc}}, // mu {"め", {0xbd}}, // me {"も", {0xbe}}, // mo {"ゃ", {0xbf}}, // youon ya {"や", {0xc0}}, // ya {"ゅ", {0xc1}}, // youon yu {"ゆ", {0xc2}}, // yu {"ょ", {0xc3}}, // youon yo {"よ", {0xc4}}, // yo {"ら", {0xc5}}, // ra {"り", {0xc6}}, // ri {"る", {0xc7}}, // ru {"れ", {0xc8}}, // re {"ろ", {0xc9}}, // ro {"ゎ", {0xca}}, // -wa {"わ", {0xcb}}, // wa {"を", {0xcc}}, // wo {"ん", {0xcd}}, // -n // katakana {"ァ", {0xce}}, // -a {"ア", {0xcf}}, // a {"ィ", {0xd0}}, // -i {"イ", {0xd1}}, // i {"ゥ", {0xd2}}, // -u {"ウ", {0xd3}}, // u {"ェ", {0xd4}}, // -e {"エ", {0xd5}}, // e {"ォ", {0xd6}}, // -o {"オ", {0xd7}}, // o {"カ", {0xd8}}, // ka {"キ", {0xd9}}, // ki {"ク", {0xda}}, // ku {"ケ", {0xdb}}, // ke {"コ", {0xdc}}, // ko {"サ", {0xdd}}, // sa {"シ", {0xde}}, // shi {"ス", {0xdf}}, // su {"セ", {0xe0}}, // se {"ソ", {0xe1}}, // so {"タ", {0xe2}}, // ta {"チ", {0xe3}}, // chi {"ッ", {0xe4}}, // sokuon {"ツ", {0xe5}}, // tsu {"テ", {0xe6}}, // te {"ト", {0xe7}}, // to {"ナ", {0xe8}}, // na {"ニ", {0xe9}}, // ni {"ヌ", {0xea}}, // nu {"ネ", {0xeb}}, // ne {"ノ", {0xec}}, // no {"ハ", {0xed}}, // ha {"ヒ", {0xee}}, // hi {"フ", {0xef}}, // hu {"ヘ", {0xf0}}, // he {"ホ", {0xf1}}, // ho {"マ", {0xf2}}, // ma {"ミ", {0xf3}}, // mi {"ム", {0xf4}}, // mu {"メ", {0xf5}}, // me {"モ", {0xf6}}, // mo {"ャ", {0xf7}}, // youon ya {"ヤ", {0xf8}}, // ya {"ュ", {0xf9}}, // youon yu {"ユ", {0xfa}}, // yu {"ョ", {0xfb}}, // youon yo {"ヨ", {0xfc}}, // yo {"ラ", {0xfd}}, // ra {"リ", {0xfe}}, // ri {"ル", {0xff}}, // ru // kanji 2 {"宝", {1, 0x01}}, // takara {"石", {1, 0x10}}, // ishi {"赤", {1, 0x11}}, // aka {"跡", {1, 0x12}}, // ato {"川", {1, 0x13}}, // kawa {"戦", {1, 0x14}}, // ikusa {"村", {1, 0x15}}, // mura {"隊", {1, 0x16}}, // tai {"台", {1, 0x17}}, // utena {"長", {1, 0x18}}, // osa {"鳥", {1, 0x19}}, // tori {"艇", {1, 0x1a}}, // tei {"洞", {1, 0x1b}}, // hora {"道", {1, 0x1c}}, // michi {"発", {1, 0x1d}}, // hatsu {"飛", {1, 0x1e}}, // tobu {"噴", {1, 0x1f}}, // fuku {"池", {1, 0xa0}}, // ike {"中", {1, 0xa1}}, // naka {"塔", {1, 0xa2}}, // tou {"島", {1, 0xa3}}, // shima {"部", {1, 0xa4}}, // bu {"砲", {1, 0xa5}}, // hou {"産", {1, 0xa6}}, // san {"眷", {1, 0xa7}}, // kaerimiru {"力", {1, 0xa8}}, // chikara {"緑", {1, 0xa9}}, // midori {"岸", {1, 0xaa}}, // kishi {"像", {1, 0xab}}, // zou {"谷", {1, 0xac}}, // tani {"心", {1, 0xad}}, // kokoro {"森", {1, 0xae}}, // mori {"水", {1, 0xaf}}, // mizu {"船", {1, 0xb0}}, // fune {"™", {1, 0xb1}}, // trademark }; GameTextFontBank g_font_bank_jak1_v2(GameTextVersion::JAK1_V2, &s_encode_info_jak1_v2, &s_replace_info_jak1, &s_passthrus_jak1); /*! * ================================ * GAME TEXT FONT BANK - JAK 2 * ================================ * This font is used in: * - Jak II * - Jak II: Renegade * - ジャックXダクスター2 */ static std::unordered_set s_passthrus_jak2 = {'~', ' ', ',', '.', '-', '+', '(', ')', '!', ':', '?', '=', '%', '*', '/', '#', ';', '<', '>', '@', '[', '_', ']'}; static std::vector s_replace_info_jak2 = { // other {"A~Y~-21H~-5Vº~Z", "Å"}, {"N~Y~-6Hº~Z~+10H", "Nº"}, {"~+4Vç~-4V", ",c"}, // added for translations TODO - check these for jak 2 {"O~Y~-25H~-1V/~Z", "Ø"}, {"o~Y~-23H~+4V/~Z", "ø"}, {"A~Y~-13H~+8V,~Z", "Ą"}, {"a~Y~-8H~+6V,~Z", "ą"}, {"E~Y~-6H~+8V,~Z", "Ę"}, {"e~Y~-10H~+7V,~Z", "ę"}, {"L~Y~-21H~+0V/~Z", "Ł"}, {"l~Y~-16H~+0V/~Z", "ł"}, // TODO - this one is ugly, font character addition (small slash) {"Z~Y~-25H~-11Vº~Z", "Ż"}, {"z~Y~-23H~-5Vº~Z", "ż"}, {"a~Y~-25H~-5Vº~Z", "å"}, {"S~Y~-21H~-5V'~Z", "Ś"}, {"s~Y~-25H~-5V'~Z", "ś"}, {"n~Y~-25H~-5V'~Z", "ń"}, {"c~Y~-25H~-5V'~Z", "ć"}, {"o~Y~-24H~-4V~Z", "õ"}, {"a~Y~-24H~-4V~Z", "ã"}, {"O~Y~-28H~-4V'~-9H'~Z", "Ő"}, {"U~Y~-27H~-4V'~-12H'~Z", "Ű"}, {"o~Y~-28H~-4V'~-9H'~Z", "ő"}, {"u~Y~-28H~-4V'~-9H'~Z", "ű"}, {"E~Y~-22H~-11Vº~Z", "Ė"}, {"e~Y~-25H~-5Vº~Z", "ė"}, {"C~Y~-27H~-10Vˇ~Z", "Č"}, {"c~Y~-25H~-5Vˇ~Z", "č"}, {"S~Y~-24H~-10Vˇ~Z", "Š"}, {"s~Y~-22H~-4Vˇ~Z", "š"}, {"Z~Y~-25H~-10Vˇ~Z", "Ž"}, {"z~Y~-23H~-4Vˇ~Z", "ž"}, {"U~Y~-15H~+5V,~Z", "Ų"}, {"u~Y~-15H~+5V,~Z", "ų"}, {"U~Y~-20H~-18V-~Z", "Ū"}, {"u~Y~-18H~-15V-~Z", "ū"}, {"I~Y~-8H~+4V,~Z", "Į"}, {"i~Y~-8H~+4V,~Z", "į"}, // tildes {"N~Y~-22H~-4V~Z", "Ñ"}, {"n~Y~-24H~-4V~Z", "ñ"}, {"A~Y~-21H~-5V~Z", "Ã"}, {"O~Y~-22H~-4V~Z", "Õ"}, // acute accents {"A~Y~-21H~-5V'~Z", "Á"}, {"A~Y~-26H~-8V'~Z", "<Á_V2>"}, // unfortunate... {"a~Y~-25H~-5V'~Z", "á"}, {"E~Y~-23H~-9V'~Z", "É"}, {"e~Y~-26H~-5V'~Z", "é"}, {"I~Y~-19H~-5V'~Z", "Í"}, {"i~Y~-19H~-8V'~Z", "í"}, {"O~Y~-22H~-4V'~Z", "Ó"}, {"o~Y~-26H~-4V'~Z", "ó"}, {"U~Y~-24H~-3V'~Z", "Ú"}, {"u~Y~-24H~-3V'~Z", "ú"}, {"Z~Y~-24H~-3V'~Z", "Ź"}, {"z~Y~-24H~-3V'~Z", "ź"}, // circumflex {"A~Y~-20H~-4V^~Z", "Â"}, {"a~Y~-24H~-5V^~Z", "â"}, {"E~Y~-20H~-5V^~Z", "Ê"}, {"e~Y~-25H~-4V^~Z", "ê"}, {"I~Y~-19H~-5V^~Z", "Î"}, {"i~Y~-19H~-8V^~Z", "î"}, {"O~Y~-20H~-4V^~Z", "Ô"}, {"o~Y~-25H~-4V^~Z", "ô"}, {"U~Y~-24H~-3V^~Z", "Û"}, {"u~Y~-23H~-3V^~Z", "û"}, // grave accents {"A~Y~-26H~-8V`~Z", "À"}, {"a~Y~-25H~-5V`~Z", "à"}, {"E~Y~-23H~-9V`~Z", "È"}, {"e~Y~-26H~-5V`~Z", "è"}, {"I~Y~-19H~-5V`~Z", "Ì"}, {"i~Y~-19H~-8V`~Z", "ì"}, {"O~Y~-22H~-4V`~Z", "Ò"}, {"o~Y~-26H~-4V`~Z", "ò"}, {"U~Y~-24H~-3V`~Z", "Ù"}, {"u~Y~-24H~-3V`~Z", "ù"}, // umlaut {"A~Y~-26H~-8V¨~Z", "Ä"}, {"a~Y~-25H~-5V¨~Z", "ä"}, {"E~Y~-20H~-5V¨~Z", "Ë"}, {"I~Y~-19H~-5V¨~Z", "Ï"}, {"i~Y~-26H~-4V¨~Z", "ï"}, {"O~Y~-26H~-8V¨~Z", "Ö"}, {"o~Y~-26H~-4V¨~Z", "ö"}, {"U~Y~-25H~-8V¨~Z", "Ü"}, {"u~Y~-24H~-3V¨~Z", "ü"}, // dakuten katakana {"~Yウ~Z゛", "ヴ"}, {"~Yカ~Z゛", "ガ"}, {"~Yキ~Z゛", "ギ"}, {"~Yク~Z゛", "グ"}, {"~Yケ~Z゛", "ゲ"}, {"~Yコ~Z゛", "ゴ"}, {"~Yサ~Z゛", "ザ"}, {"~Yシ~Z゛", "ジ"}, {"~Yス~Z゛", "ズ"}, {"~Yセ~Z゛", "ゼ"}, {"~Yソ~Z゛", "ゾ"}, {"~Yタ~Z゛", "ダ"}, {"~Yチ~Z゛", "ヂ"}, {"~Yツ~Z゛", "ヅ"}, {"~Yテ~Z゛", "デ"}, {"~Yト~Z゛", "ド"}, {"~Yハ~Z゛", "バ"}, {"~Yヒ~Z゛", "ビ"}, {"~Yフ~Z゛", "ブ"}, {"~Yヘ~Z゛", "ベ"}, {"~Yホ~Z゛", "ボ"}, // handakuten katakana {"~Yハ~Z゜", "パ"}, {"~Yヒ~Z゜", "ピ"}, {"~Yフ~Z゜", "プ"}, {"~Yヘ~Z゜", "ペ"}, {"~Yホ~Z゜", "ポ"}, // dakuten hiragana {"~Yか~Z゛", "が"}, {"~Yき~Z゛", "ぎ"}, {"~Yく~Z゛", "ぐ"}, {"~Yけ~Z゛", "げ"}, {"~Yこ~Z゛", "ご"}, {"~Yさ~Z゛", "ざ"}, {"~Yし~Z゛", "じ"}, {"~Yす~Z゛", "ず"}, {"~Yせ~Z゛", "ぜ"}, {"~Yそ~Z゛", "ぞ"}, {"~Yた~Z゛", "だ"}, {"~Yち~Z゛", "ぢ"}, {"~Yつ~Z゛", "づ"}, {"~Yて~Z゛", "で"}, {"~Yと~Z゛", "ど"}, {"~Yは~Z゛", "ば"}, {"~Yひ~Z゛", "び"}, {"~Yふ~Z゛", "ぶ"}, {"~Yへ~Z゛", "べ"}, {"~Yほ~Z゛", "ぼ"}, // handakuten hiragana {"~Yは~Z゜", "ぱ"}, {"~Yひ~Z゜", "ぴ"}, {"~Yふ~Z゜", "ぷ"}, {"~Yへ~Z゜", "ぺ"}, {"~Yほ~Z゜", "ぽ"}, // japanese punctuation {",~+8H", "、"}, {"~+8H ", " "}, // playstation buttons // - face {"~Y~22L<~Z~Y~27L*~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, {"~Y~22L<~Z~Y~26L;~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, {"~Y~22L<~Z~Y~25L@~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, {"~Y~22L<~Z~Y~24L#~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, // - dpad {"~Y~22L~Z~3L~+17H~-13V~Z~22L~+17H~+14V~Z~" "22L~+32H~Z~+56H", ""}, {"~Y~22L~Z~3L~+17H~-13V~Z~3L~+17H~+14V~Z~" "22L~+32H~Z~+56H", ""}, {"~Y~22L~Z~22L~+17H~-13V~Z~22L~+17H~+14V~Z~" "22L~+32H~Z~+56H", ""}, // - shoulder {"~Y~22L~-2H~-12V~Z~22L~-2H~+17V~Z~1L~+4H~+3V~Z~+" "38H", ""}, {"~Y~22L~-2H~-12V~Z~22L~-2H~+17V~Z~1L~+6H~+3V~Z~+" "38H", ""}, {"~Y~22L~-2H~-6V~Z~22L~-2H~+16V~Z~1L~+5H~-2V~Z~+" "38H", ""}, {"~Y~22L~-2H~-6V~Z~22L~-2H~+16V~Z~1L~+5H~-2V~Z~+" "38H", ""}, // - analog {"~1L~+8H~Y~Z~6L~-16H~Z~+16h~6L~Z~" "6L~-15V~Z~+13V~6L~Z~-10H~+9V~6L~Z~+10H~+9V~6L~Z~-10H~-11V~6L~Z~+10H~" "-11V~6L~Z~+32H", ""}, {"~Y~1L~+8H~Z~6L~-8H~Z~+24H~6L~Z~+" "40H", ""}, {"~Y~1L~Z~6L~-15V~Z~+13V~6L~Z~+26H", ""}, // icons {"~Y~6L<~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, {"~Y~3L<~Z~Y~1L>~Z~Y~23L[~Z~+26H", ""}, // flags {"~Y~6L~Z~+15H~1L~Z~+30H~3L~Z~+45H", ""}, {"~Y~5L~Z~3L~]~-1H~Y~5L~Z~3L~Z~+26H", ""}, {"~Y~39L~~~Z~3L~Z~5L~]~-1H~Y~39L~~~" "Z~3L~Z~5L~Z~+26H", ""}, {"~Y~7L~Z~+15H~1L~Z~+30H~3L~Z~+47H", ""}, {"~Y~1L~Z~3L~Z~7L~]~-1H~Y~1L<" "FLAG_PART_FILL>~Z~3L~Z~7L~Z~+26H", ""}, {"~Y~1L~Z~3L~Z~7L~]~-1H~Y~1L<" "FLAG_PART_FILL>~Z~3L~Z~+26H", ""}, {"~Y~1L~Z~39L~]~-1H~Y~1L~Z~39L<" "FLAG_PART_KOREA_TRIGRAMS_RIGHT>~Z~-11H~7L~Z~-11H~3L~Z~+26H", ""}, {"~Y~1L~]~-1H~Y~1L~Z~-11H~3L~Z~+26H", ""}, {"~Y~1L~Z~7L~Z~7L~]" "~-1H~Y~1L~Z~7L~Z~+26H", ""}, {"~Y~7L~Z~5L~Z~5L~]" "~-1H~Y~7L~Z~5L~Z~+26H", ""}, {"~Y~3L~Z~1L~Z~1L~]" "~-1H~Y~3L~Z~1L~Z~+26H", ""}, {"~Y~1L~Z~3L~]~-1H~Y~1L~Z~3L~Z~-19H~1L~Z~-23H~7L~Z~-23H~7L~Z~7L~Z~" "+26H", ""}, {"~Y~1L~Z~7L~]~-1H~Y~1L~Z~7L~Z~-19H~1L~Z~-23H~3L~Z~-23H~3L~Z~3L~Z~" "+26H", ""}, // weird stuff // - descenders {"~+7Vp~-7V", "p"}, {"~+7Vy~-7V", "y"}, {"~+7Vg~-7V", "g"}, {"~+7Vq~-7V", "q"}, {"~+1Vj~-1V", "j"}, {"\\\\", "~%"}, // this is 2 slashes, duplicated because we use an escape sequence when decompiling // - symbols and ligatures {"~-4H~-3V~+3V~-4H", ""}, // used for the 4<__> place in spanish. the 5th uses the same // character but looks different...? {"~Y~-6Hº~Z~+10H", "°"}, // Color / Emphasis {"~[~0L", ""}, {"~[~1L", ""}, {"~[~2L", ""}, {"~[~3L", ""}, {"~[~4L", ""}, {"~[~5L", ""}, {"~[~6L", ""}, {"~[~7L", ""}, {"~[~8L", ""}, {"~[~9L", ""}, {"~[~10L", ""}, {"~[~11L", ""}, {"~[~12L", ""}, {"~[~13L", ""}, {"~[~14L", ""}, {"~[~15L", ""}, {"~[~16L", ""}, {"~[~17L", ""}, {"~[~18L", ""}, {"~[~19L", ""}, {"~[~20L", ""}, {"~[~21L", ""}, {"~[~22L", ""}, {"~[~23L", ""}, {"~[~24L", ""}, {"~[~25L", ""}, {"~[~26L", ""}, {"~[~27L", ""}, {"~[~28L", ""}, {"~[~29L", ""}, {"~[~30L", ""}, {"~[~31L", ""}, {"~[~32L", ""}, {"~[~33L", ""}, {"~[~34L", ""}, {"~[~35L", ""}, {"~[~36L", ""}, {"~[~37L", ""}, {"~[~38L", ""}, {"~[~39L", ""}}; static std::vector s_encode_info_jak2 = { {"ˇ", {0x10}}, // caron {"`", {0x11}}, // grave accent {"'", {0x12}}, // apostrophe {"^", {0x13}}, // circumflex {"", {0x14}}, // tilde {"¨", {0x15}}, // umlaut {"º", {0x16}}, // numero/overring {"¡", {0x17}}, // inverted exclamation mark {"¿", {0x18}}, // inverted question mark {"", {0x19}}, {"ç", {0x1d}}, // c-cedilla {"Ç", {0x1e}}, // c-cedilla {"ß", {0x1f}}, // eszett {"œ", {0x5e}}, // ligature o+e {"", {0x7f}}, {"", {0x80}}, {"", {0x81}}, {"", {0x82}}, {"", {0x83}}, {"", {0x84}}, {"", {0x85}}, {"", {0x86}}, {"", {0x87}}, {"", {0x88}}, {"", {0x89}}, {"", {0x8a}}, {"", {0x8b}}, {"", {0x8c}}, {"", {0x8d}}, {"", {0x8e}}, {"", {0x8f}}, {"", {0x90}}, {"", {0x91}}, {"", {0x92}}, {"", {0x93}}, {"", {0x94}}, {"", {0x95}}, {"", {0x96}}, {"", {0x97}}, {"", {0x98}}, {"", {0x99}}, {"", {0x9a}}, {"", {0x9b}}, {"", {0x9c}}, {"", {0x9d}}, {"", {0x9e}}, {"", {0x9f}}, {"", {0xa0}}, {"", {0xa1}}, {"", {0xa2}}, {"", {0xa3}}, {"", {0xa4}}, {"", {0xa5}}, {"", {0xa6}}, {"", {0xa7}}, {"", {0xa8}}, {"", {0xa9}}, {"", {0xaa}}, {"", {0xab}}, {"", {0xac}}, {"", {0xb0}}, {"", {0xb1}}, {"", {0xb2}}, {"", {0xb3}}, // {"入", {1, 0x00}}, // {"年", {1, 0x01}}, // punctuation {"・", {1, 0x10}}, {"゛", {1, 0x11}}, {"゜", {1, 0x12}}, {"ー", {1, 0x13}}, {"『", {1, 0x14}}, {"』", {1, 0x15}}, // hiragana {"ぁ", {1, 0x16}}, // -a {"あ", {1, 0x17}}, // a {"ぃ", {1, 0x18}}, // -i {"い", {1, 0x19}}, // i {"ぅ", {1, 0x1a}}, // -u {"う", {1, 0x1b}}, // u {"ぇ", {1, 0x1c}}, // -e {"え", {1, 0x1d}}, // e {"ぉ", {1, 0x1e}}, // -o {"お", {1, 0x1f}}, // o {"か", {1, 0x20}}, // ka {"き", {1, 0x21}}, // ki {"く", {1, 0x22}}, // ku {"け", {1, 0x23}}, // ke {"こ", {1, 0x24}}, // ko {"さ", {1, 0x25}}, // sa {"し", {1, 0x26}}, // shi {"す", {1, 0x27}}, // su {"せ", {1, 0x28}}, // se {"そ", {1, 0x29}}, // so {"た", {1, 0x2a}}, // ta {"ち", {1, 0x2b}}, // chi {"っ", {1, 0x2c}}, // sokuon {"つ", {1, 0x2d}}, // tsu {"て", {1, 0x2e}}, // te {"と", {1, 0x2f}}, // to {"な", {1, 0x30}}, // na {"に", {1, 0x31}}, // ni {"ぬ", {1, 0x32}}, // nu {"ね", {1, 0x33}}, // ne {"の", {1, 0x34}}, // no {"は", {1, 0x35}}, // ha {"ひ", {1, 0x36}}, // hi {"ふ", {1, 0x37}}, // fu {"へ", {1, 0x38}}, // he {"ほ", {1, 0x39}}, // ho {"ま", {1, 0x3a}}, // ma {"み", {1, 0x3b}}, // mi {"む", {1, 0x3c}}, // mu {"め", {1, 0x3d}}, // me {"も", {1, 0x3e}}, // mo {"ゃ", {1, 0x3f}}, // youon ya {"や", {1, 0x40}}, // ya {"ゅ", {1, 0x41}}, // youon yu {"ゆ", {1, 0x42}}, // yu {"ょ", {1, 0x43}}, // youon yo {"よ", {1, 0x44}}, // yo {"ら", {1, 0x45}}, // ra {"り", {1, 0x46}}, // ri {"る", {1, 0x47}}, // ru {"れ", {1, 0x48}}, // re {"ろ", {1, 0x49}}, // ro {"ゎ", {1, 0x4a}}, // -wa {"わ", {1, 0x4b}}, // wa {"を", {1, 0x4c}}, // wo {"ん", {1, 0x4d}}, // -n // katakana {"ァ", {1, 0x4e}}, // -a {"ア", {1, 0x4f}}, // a {"ィ", {1, 0x50}}, // -i {"イ", {1, 0x51}}, // i {"ゥ", {1, 0x52}}, // -u {"ウ", {1, 0x53}}, // u {"ェ", {1, 0x54}}, // -e {"エ", {1, 0x55}}, // e {"ォ", {1, 0x56}}, // -o {"オ", {1, 0x57}}, // o {"カ", {1, 0x58}}, // ka {"キ", {1, 0x59}}, // ki {"ク", {1, 0x5a}}, // ku {"ケ", {1, 0x5b}}, // ke {"コ", {1, 0x5c}}, // ko {"サ", {1, 0x5d}}, // sa {"シ", {1, 0x5e}}, // shi {"ス", {1, 0x5f}}, // su {"セ", {1, 0x60}}, // se {"ソ", {1, 0x61}}, // so {"タ", {1, 0x62}}, // ta {"チ", {1, 0x63}}, // chi {"ッ", {1, 0x64}}, // sokuon {"ツ", {1, 0x65}}, // tsu {"テ", {1, 0x66}}, // te {"ト", {1, 0x67}}, // to {"ナ", {1, 0x68}}, // na {"ニ", {1, 0x69}}, // ni {"ヌ", {1, 0x6a}}, // nu {"ネ", {1, 0x6b}}, // ne {"ノ", {1, 0x6c}}, // no {"ハ", {1, 0x6d}}, // ha {"ヒ", {1, 0x6e}}, // hi {"フ", {1, 0x6f}}, // fu {"ヘ", {1, 0x70}}, // he {"ホ", {1, 0x71}}, // ho {"マ", {1, 0x72}}, // ma {"ミ", {1, 0x73}}, // mi {"ム", {1, 0x74}}, // mu {"メ", {1, 0x75}}, // me {"モ", {1, 0x76}}, // mo {"ャ", {1, 0x77}}, // youon ya {"ヤ", {1, 0x78}}, // ya {"ュ", {1, 0x79}}, // youon yu {"ユ", {1, 0x7a}}, // yu {"ョ", {1, 0x7b}}, // youon yo {"ヨ", {1, 0x7c}}, // yo {"ラ", {1, 0x7d}}, // ra {"リ", {1, 0x7e}}, // ri {"ル", {1, 0x7f}}, // ru {"レ", {1, 0x80}}, // re {"ロ", {1, 0x81}}, // ro {"ヮ", {1, 0x82}}, // -wa {"ワ", {1, 0x83}}, // wa {"ヲ", {1, 0x84}}, // wo {"ン", {1, 0x85}}, // -n {"位", {1, 0x8c}}, {"遺", {1, 0x8d}}, {"院", {1, 0x8e}}, {"映", {1, 0x8f}}, {"衛", {1, 0x90}}, {"応", {1, 0x91}}, {"下", {1, 0x92}}, {"画", {1, 0x93}}, {"解", {1, 0x94}}, {"開", {1, 0x95}}, {"外", {1, 0x96}}, {"害", {1, 0x97}}, {"蓋", {1, 0x98}}, {"完", {1, 0x99}}, {"換", {1, 0x9a}}, {"監", {1, 0x9b}}, {"間", {1, 0x9c}}, {"器", {1, 0x9d}}, {"記", {1, 0x9e}}, {"逆", {1, 0x9f}}, {"救", {1, 0xa0}}, {"金", {1, 0xa1}}, {"空", {1, 0xa2}}, {"掘", {1, 0xa3}}, {"警", {1, 0xa4}}, {"迎", {1, 0xa5}}, {"撃", {1, 0xa6}}, {"建", {1, 0xa7}}, {"源", {1, 0xa8}}, {"現", {1, 0xa9}}, {"言", {1, 0xaa}}, {"限", {1, 0xab}}, {"個", {1, 0xac}}, {"庫", {1, 0xad}}, {"後", {1, 0xae}}, {"語", {1, 0xaf}}, {"護", {1, 0xb0}}, {"交", {1, 0xb1}}, {"功", {1, 0xb2}}, {"向", {1, 0xb3}}, {"工", {1, 0xb4}}, {"攻", {1, 0xb5}}, {"溝", {1, 0xb6}}, {"行", {1, 0xb7}}, {"鉱", {1, 0xb8}}, {"降", {1, 0xb9}}, {"合", {1, 0xba}}, {"告", {1, 0xbb}}, {"獄", {1, 0xbc}}, {"彩", {1, 0xbd}}, {"作", {1, 0xbe}}, {"山", {1, 0xbf}}, {"使", {1, 0xc0}}, {"始", {1, 0xc1}}, {"試", {1, 0xc2}}, {"字", {1, 0xc3}}, {"寺", {1, 0xc4}}, {"時", {1, 0xc5}}, {"示", {1, 0xc6}}, {"自", {1, 0xc7}}, {"式", {1, 0xc8}}, {"矢", {1, 0xc9}}, {"射", {1, 0xca}}, {"者", {1, 0xcb}}, {"守", {1, 0xcc}}, {"手", {1, 0xcd}}, {"終", {1, 0xce}}, {"週", {1, 0xcf}}, {"出", {1, 0xd0}}, {"所", {1, 0xd1}}, {"書", {1, 0xd2}}, {"勝", {1, 0xd3}}, {"章", {1, 0xd4}}, {"上", {1, 0xd5}}, {"乗", {1, 0xd6}}, {"場", {1, 0xd7}}, {"森", {1, 0xd8}}, {"進", {1, 0xd9}}, {"人", {1, 0xda}}, {"水", {1, 0xdb}}, {"数", {1, 0xdc}}, {"制", {1, 0xdd}}, {"性", {1, 0xde}}, {"成", {1, 0xdf}}, {"聖", {1, 0xe0}}, {"石", {1, 0xe1}}, {"跡", {1, 0xe2}}, {"先", {1, 0xe3}}, {"戦", {1, 0xe4}}, {"船", {1, 0xe5}}, {"選", {1, 0xe6}}, {"走", {1, 0xe7}}, {"送", {1, 0xe8}}, {"像", {1, 0xe9}}, {"造", {1, 0xea}}, {"続", {1, 0xeb}}, {"対", {1, 0xec}}, {"袋", {1, 0xed}}, {"台", {1, 0xee}}, {"弾", {1, 0xef}}, {"地", {1, 0xf0}}, {"中", {1, 0xf1}}, {"敵", {1, 0xf2}}, {"転", {1, 0xf3}}, {"電", {1, 0xf4}}, {"塔", {1, 0xf5}}, {"頭", {1, 0xf6}}, {"動", {1, 0xf7}}, {"内", {1, 0xf8}}, {"日", {1, 0xf9}}, {"入", {1, 0xfa}}, {"年", {1, 0xfb}}, {"能", {1, 0xfc}}, {"廃", {1, 0xfd}}, {"排", {1, 0xfe}}, {"敗", {1, 0xff}}, {"発", {2, 0x10}}, {"反", {2, 0x11}}, {"必", {2, 0x12}}, {"表", {2, 0x13}}, {"武", {2, 0x14}}, {"壁", {2, 0x15}}, {"墓", {2, 0x16}}, {"放", {2, 0x17}}, {"方", {2, 0x18}}, {"砲", {2, 0x19}}, {"妨", {2, 0x1a}}, {"北", {2, 0x1b}}, {"本", {2, 0x1c}}, {"幕", {2, 0x1d}}, {"無", {2, 0x1e}}, {"迷", {2, 0x1f}}, {"面", {2, 0x20}}, {"戻", {2, 0x21}}, {"紋", {2, 0x22}}, {"薬", {2, 0x23}}, {"輸", {2, 0x24}}, {"勇", {2, 0x25}}, {"友", {2, 0x26}}, {"遊", {2, 0x27}}, {"容", {2, 0x28}}, {"要", {2, 0x29}}, {"利", {2, 0x2a}}, {"了", {2, 0x2b}}, {"量", {2, 0x2c}}, {"力", {2, 0x2d}}, {"練", {2, 0x2e}}, {"連", {2, 0x2f}}, {"録", {2, 0x30}}, {"話", {2, 0x31}}, {"墟", {2, 0x32}}, {"脱", {2, 0x33}}, // {"成", {2, 0x34}}, {"旗", {2, 0x35}}, {"破", {2, 0x36}}, {"壊", {2, 0x37}}, {"全", {2, 0x38}}, {"滅", {2, 0x39}}, {"機", {2, 0x3a}}, {"仲", {2, 0x3b}}, {"渓", {2, 0x3c}}, {"谷", {2, 0x3d}}, {"優", {2, 0x3e}}, {"探", {2, 0x3f}}, {"部", {2, 0x40}}, {"索", {2, 0x41}}, // {"乗", {2, 0x42}}, {"前", {2, 0x43}}, {"右", {2, 0x44}}, {"左", {2, 0x45}}, {"会", {2, 0x46}}, {"高", {2, 0x47}}, {"低", {2, 0x48}}, {"押", {2, 0x49}}, {"切", {2, 0x4a}}, {"替", {2, 0x4b}}, // {"対", {2, 0x4c}}, {"秒", {2, 0x4d}}, {"箱", {2, 0x4e}}, {"泳", {2, 0x4f}}, {"~", {2, 0x50}}, {"闇", {2, 0x56}}, {"以", {2, 0x57}}, {"屋", {2, 0x58}}, {"俺", {2, 0x59}}, {"化", {2, 0x5a}}, {"界", {2, 0x5b}}, {"感", {2, 0x5c}}, {"気", {2, 0x5d}}, {"却", {2, 0x5e}}, {"曲", {2, 0x5f}}, {"継", {2, 0x60}}, {"権", {2, 0x61}}, {"見", {2, 0x62}}, {"古", {2, 0x63}}, {"好", {2, 0x64}}, // {"高", {2, 0x65}}, {"才", {2, 0x66}}, {"士", {2, 0x67}}, {"子", {2, 0x68}}, {"次", {2, 0x69}}, {"主", {2, 0x6a}}, {"種", {2, 0x6b}}, {"讐", {2, 0x6c}}, {"女", {2, 0x6d}}, {"小", {2, 0x6e}}, {"焼", {2, 0x6f}}, {"証", {2, 0x70}}, {"神", {2, 0x71}}, {"身", {2, 0x72}}, {"寸", {2, 0x73}}, {"世", {2, 0x74}}, {"想", {2, 0x75}}, {"退", {2, 0x76}}, {"第", {2, 0x77}}, {"着", {2, 0x78}}, {"天", {2, 0x79}}, {"倒", {2, 0x7a}}, {"到", {2, 0x7b}}, {"突", {2, 0x7c}}, {"爆", {2, 0x7d}}, {"番", {2, 0x7e}}, {"負", {2, 0x7f}}, {"復", {2, 0x80}}, {"物", {2, 0x81}}, {"眠", {2, 0x82}}, {"予", {2, 0x83}}, {"用", {2, 0x84}}, {"落", {2, 0x85}}, {"緑", {2, 0x86}}, {"封", {2, 0x88}}, {"印", {2, 0x89}}, {"扉", {2, 0x8a}}, {"最", {2, 0x8b}}, {"刻", {2, 0x8c}}, {"足", {2, 0x8d}}, {"", {3, 0x00}}, {"", {3, 0x01}}, {"", {3, 0x02}}, {"", {3, 0x03}}, {"", {3, 0x04}}, {"", {3, 0x05}}, {"", {3, 0x06}}, {"", {3, 0x07}}, {"", {3, 0x08}}, {"", {3, 0x09}}, {"", {3, 0x0a}}, {"", {3, 0x0b}}, {"", {3, 0x0c}}, {"", {3, 0x0d}}, {"", {3, 0x0e}}, {"", {3, 0x0f}}, {"", {3, 0x10}}, {"", {3, 0x11}}, {"", {3, 0x12}}, {"", {3, 0x13}}, {"", {3, 0x14}}, {"", {3, 0x15}}, {"", {3, 0x16}}, {"", {3, 0x17}}, {"", {3, 0x18}}, {"", {3, 0x19}}, {"", {3, 0x1a}}, {"", {3, 0x1b}}, {"", {3, 0x1c}}, {"", {3, 0x1d}}, {"", {3, 0x1e}}, {"", {3, 0x1f}}, {"", {3, 0x20}}, {"", {3, 0x21}}, {"", {3, 0x22}}, {"", {3, 0x23}}, {"", {3, 0x24}}, {"", {3, 0x25}}, {"", {3, 0x26}}, {"", {3, 0x27}}, {"", {3, 0x28}}, {"", {3, 0x29}}, {"", {3, 0x2a}}, {"", {3, 0x2b}}, {"", {3, 0x2c}}, {"", {3, 0x2d}}, {"", {3, 0x2e}}, {"", {3, 0x2f}}, {"", {3, 0x30}}, {"", {3, 0x31}}, {"", {3, 0x32}}, {"", {3, 0x33}}, {"", {3, 0x34}}, {"", {3, 0x35}}, {"", {3, 0x36}}, {"", {3, 0x37}}, {"", {3, 0x38}}, {"", {3, 0x39}}, {"", {3, 0x3a}}, {"", {3, 0x3b}}, {"", {3, 0x3c}}, {"", {3, 0x3d}}, {"", {3, 0x3e}}, {"", {3, 0x3f}}, {"", {3, 0x40}}, {"", {3, 0x41}}, {"", {3, 0x42}}, {"", {3, 0x43}}, {"", {3, 0x44}}, {"", {3, 0x45}}, {"", {3, 0x46}}, {"", {3, 0x47}}, {"", {3, 0x48}}, {"", {3, 0x49}}, {"", {3, 0x4a}}, {"", {3, 0x4b}}, {"", {3, 0x4c}}, {"", {3, 0x4d}}, {"", {3, 0x4e}}, {"", {3, 0x4f}}, {"", {3, 0x50}}, {"", {3, 0x51}}, {"", {3, 0x52}}, {"", {3, 0x53}}, {"", {3, 0x54}}, {"", {3, 0x55}}, {"", {3, 0x56}}, {"", {3, 0x57}}, {"", {3, 0x58}}, {"", {3, 0x59}}, {"", {3, 0x5a}}, {"", {3, 0x5b}}, {"", {3, 0x5c}}, {"", {3, 0x5d}}, {"", {3, 0x5e}}, {"", {3, 0x5f}}, {"", {3, 0x60}}, {"", {3, 0x61}}, {"", {3, 0x62}}, {"", {3, 0x63}}, {"", {3, 0x64}}, {"", {3, 0x65}}, {"", {3, 0x66}}, {"", {3, 0x67}}, {"", {3, 0x68}}, {"", {3, 0x69}}, {"", {3, 0x6a}}, {"", {3, 0x6b}}, {"", {3, 0x6c}}, {"", {3, 0x6d}}, {"", {3, 0x6e}}, {"", {3, 0x6f}}, {"", {3, 0x70}}, {"", {3, 0x71}}, {"", {3, 0x72}}, {"", {3, 0x73}}, {"", {3, 0x74}}, {"", {3, 0x75}}, {"", {3, 0x76}}, {"", {3, 0x77}}, {"", {3, 0x78}}, {"", {3, 0x79}}, {"", {3, 0x7a}}, {"", {3, 0x7b}}, {"", {3, 0x7c}}, {"", {3, 0x7d}}, {"", {3, 0x7e}}, {"", {3, 0x7f}}, {"", {3, 0x80}}, {"", {3, 0x81}}, {"", {3, 0x82}}, {"", {3, 0x83}}, {"", {3, 0x84}}, {"", {3, 0x85}}, {"", {3, 0x86}}, {"", {3, 0x87}}, {"", {3, 0x88}}, {"", {3, 0x89}}, {"", {3, 0x8a}}, {"", {3, 0x8b}}, {"", {3, 0x8c}}, {"", {3, 0x8d}}, {"", {3, 0x8e}}, {"", {3, 0x8f}}, {"", {3, 0x90}}, {"", {3, 0x91}}, {"", {3, 0x92}}, {"", {3, 0x93}}, {"", {3, 0x94}}, {"", {3, 0x95}}, {"", {3, 0x96}}, {"", {3, 0x97}}, {"", {3, 0x98}}, {"", {3, 0x99}}, {"", {3, 0x9a}}, {"", {3, 0x9b}}, {"", {3, 0x9c}}, {"", {3, 0x9d}}, {"", {3, 0x9e}}, {"", {3, 0x9f}}, {"", {3, 0xa0}}, {"", {3, 0xa1}}, {"", {3, 0xa2}}, {"", {3, 0xa3}}, {"", {3, 0xa4}}, {"", {3, 0xa5}}, {"", {3, 0xa6}}, {"", {3, 0xa7}}, {"", {3, 0xa8}}, {"", {3, 0xa9}}, {"", {3, 0xaa}}, {"", {3, 0xab}}, {"", {3, 0xac}}, {"", {3, 0xad}}, {"", {3, 0xae}}, {"", {3, 0xaf}}, {"", {3, 0xb0}}, {"", {3, 0xb1}}, {"", {3, 0xb2}}, {"", {3, 0xb3}}, {"", {3, 0xb4}}, {"", {3, 0xb5}}, {"", {3, 0xb6}}, {"", {3, 0xb7}}, {"", {3, 0xb8}}, {"", {3, 0xb9}}, {"", {3, 0xba}}, {"", {3, 0xbb}}, {"", {3, 0xbc}}, {"", {3, 0xbd}}, {"", {3, 0xbe}}, {"", {3, 0xbf}}, {"", {3, 0xc0}}, {"", {3, 0xc1}}, {"", {3, 0xc2}}, {"", {3, 0xc3}}, {"", {3, 0xc4}}, {"", {3, 0xc5}}, {"", {3, 0xc6}}, {"", {3, 0xc7}}, {"", {3, 0xc8}}, {"", {3, 0xc9}}, {"", {3, 0xca}}, {"", {3, 0xcb}}, {"", {3, 0xcc}}, {"", {3, 0xcd}}, {"", {3, 0xce}}, {"", {3, 0xcf}}, {"", {3, 0xd0}}, {"", {3, 0xd1}}, {"", {3, 0xd2}}, {"", {3, 0xd3}}, {"", {3, 0xd4}}, {"", {3, 0xd5}}, {"", {3, 0xd6}}, {"", {3, 0xd7}}, {"", {3, 0xd8}}, {"", {3, 0xd9}}, {"", {3, 0xda}}, {"", {3, 0xdb}}, {"", {3, 0xdc}}, {"", {3, 0xdd}}, {"", {3, 0xde}}, {"", {3, 0xdf}}, {"", {3, 0xe0}}, {"", {3, 0xe1}}, {"", {3, 0xe2}}, {"", {3, 0xe3}}, {"", {3, 0xe4}}, {"", {3, 0xe5}}, {"", {3, 0xe6}}, {"", {3, 0xe7}}, {"", {3, 0xe8}}, {"", {3, 0xe9}}, {"", {3, 0xea}}, {"", {3, 0xeb}}, {"", {3, 0xec}}, {"", {3, 0xed}}, {"", {3, 0xee}}, {"", {3, 0xef}}, {"", {3, 0xf0}}, {"", {3, 0xf1}}, {"", {3, 0xf2}}, {"", {3, 0xf3}}, {"", {3, 0xf4}}, {"", {3, 0xf5}}, {"", {3, 0xf6}}, {"", {3, 0xf7}}, {"", {3, 0xf8}}, {"", {3, 0xf9}}, {"", {3, 0xfa}}, {"", {3, 0xfb}}, {"", {3, 0xfc}}, {"", {3, 0xfd}}, {"", {3, 0xfe}}, {"", {3, 0xff}}, }; GameTextFontBank g_font_bank_jak2(GameTextVersion::JAK2, &s_encode_info_jak2, &s_replace_info_jak2, &s_passthrus_jak2); /*! * ================================ * GAME TEXT FONT BANK - JAK 3 * ================================ * This font is used in: * - Jak 3 */ // TODO cyrillic GameTextFontBank g_font_bank_jak3(GameTextVersion::JAK3, &s_encode_info_jak2, &s_replace_info_jak2, &s_passthrus_jak2); /*! * ======================== * GAME TEXT FONT BANK LIST * ======================== * The list of available font banks and a couple of helper functions. */ std::map g_font_banks = { {GameTextVersion::JAK1_V1, &g_font_bank_jak1_v1}, {GameTextVersion::JAK1_V2, &g_font_bank_jak1_v2}, {GameTextVersion::JAK2, &g_font_bank_jak2}, {GameTextVersion::JAK3, &g_font_bank_jak3}}; const GameTextFontBank* get_font_bank(GameTextVersion version) { return g_font_banks.at(version); } const GameTextFontBank* get_font_bank_from_game_version(GameVersion version) { // Jak 1 has been patched to use V2 switch (version) { case GameVersion::Jak1: return get_font_bank(GameTextVersion::JAK1_V2); case GameVersion::Jak2: return get_font_bank(GameTextVersion::JAK2); case GameVersion::Jak3: return get_font_bank(GameTextVersion::JAK3); default: ASSERT_MSG(false, "Unsupported game for get_font_bank_from_game_version"); } } const GameTextFontBank* get_font_bank(const std::string& name) { if (auto it = sTextVerEnumMap.find(name); it == sTextVerEnumMap.end()) { throw std::runtime_error(fmt::format("unknown text version {}", name)); } else { return get_font_bank(it->second); } } bool font_bank_exists(GameTextVersion version) { return g_font_banks.find(version) != g_font_banks.cend(); }