jak-project/common/util/FontUtils.cpp
2023-11-22 18:45:08 -05:00

1946 lines
57 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* @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 <algorithm>
#include <stdexcept>
#include "string_util.h"
#include "common/util/Assert.h"
#include "third-party/fmt/core.h"
#include "third-party/fmt/format.h"
const std::unordered_map<std::string, GameTextVersion> sTextVerEnumMap = {
{"jak1-v1", GameTextVersion::JAK1_V1},
{"jak1-v2", GameTextVersion::JAK1_V2},
{"jak2", GameTextVersion::JAK2}};
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<EncodeInfo>* encode_info,
std::vector<ReplaceInfo>* replace_info,
std::unordered_set<char>* 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) {
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<EncodeInfo> s_encode_info_null = {};
static std::vector<ReplaceInfo> 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<char> s_passthrus_jak1 = {'~', ' ', ',', '.', '-', '+', '(', ')',
'!', ':', '?', '=', '%', '*', '/', '#',
';', '<', '>', '@', '[', '_'};
static std::vector<EncodeInfo> s_encode_info_jak1 = {
// random
{"ˇ", {0x10}}, // caron
{"`", {0x11}}, // grave accent
{"'", {0x12}}, // apostrophe
{"^", {0x13}}, // circumflex
{"<TIL>", {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<ReplaceInfo> s_replace_info_jak1 = {
// other
{"A~Y~-21H~-5Vº~Z", "Å"},
{"N~Y~-6Hº~Z~+10H", ""},
{"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<TIL>~Z", "Ñ"},
{"A~Y~-21H~-5V<TIL>~Z", "Ã"}, // custom
{"O~Y~-22H~-4V<TIL>~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", "<PAD_X>"},
{"~Y~22L<~Z~Y~26L;~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<PAD_TRIANGLE>"},
{"~Y~22L<~Z~Y~25L@~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<PAD_CIRCLE>"},
{"~Y~22L<~Z~Y~24L#~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<PAD_SQUARE>"}, // 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<EncodeInfo> s_encode_info_jak1_v2 = {
// random
{"_", {0x03}}, // large space
{"ˇ", {0x10}}, // caron
{"`", {0x11}}, // grave accent
{"'", {0x12}}, // apostrophe
{"^", {0x13}}, // circumflex
{"<TIL>", {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 2 - NTSC - v1
*/
static std::unordered_set<char> s_passthrus_jak2 = {'~', ' ', ',', '.', '-', '+', '(', ')',
'!', ':', '?', '=', '%', '*', '/', '#',
';', '<', '>', '@', '[', '_', ']'};
static std::vector<ReplaceInfo> s_replace_info_jak2 = {
// other
{"A~Y~-21H~-5Vº~Z", "Å"},
{"N~Y~-6Hº~Z~+10H", ""},
{"~+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<TIL>~Z", "õ"},
{"a~Y~-24H~-4V<TIL>~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<TIL>~Z", "Ñ"},
{"n~Y~-24H~-4V<TIL>~Z", "ñ"},
{"A~Y~-21H~-5V<TIL>~Z", "Ã"},
{"O~Y~-22H~-4V<TIL>~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", "ú"},
// 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", "Ï"},
{"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", "<PAD_X>"},
{"~Y~22L<~Z~Y~26L;~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<PAD_TRIANGLE>"},
{"~Y~22L<~Z~Y~25L@~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<PAD_CIRCLE>"},
{"~Y~22L<~Z~Y~24L#~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<PAD_SQUARE>"},
// - dpad
{"~Y~22L<PAD_PART_DPAD_L>~Z~3L~+17H~-13V<PAD_PART_DPAD_U>~Z~22L~+17H~+14V<PAD_PART_DPAD_D>~Z~"
"22L~+32H<PAD_PART_DPAD_R>~Z~+56H",
"<PAD_DPAD_UP>"},
{"~Y~22L<PAD_PART_DPAD_L>~Z~3L~+17H~-13V<PAD_PART_DPAD_U>~Z~3L~+17H~+14V<PAD_PART_DPAD_D>~Z~"
"22L~+32H<PAD_PART_DPAD_R>~Z~+56H",
"<PAD_DPAD_DOWN>"},
{"~Y~22L<PAD_PART_DPAD_L>~Z~22L~+17H~-13V<PAD_PART_DPAD_U>~Z~22L~+17H~+14V<PAD_PART_DPAD_D>~Z~"
"22L~+32H<PAD_PART_DPAD_R>~Z~+56H",
"<PAD_DPAD_ANY>"},
// - shoulder
{"~Y~22L~-2H~-12V<PAD_PART_SHOULDER_TOP_LEFT><PAD_PART_SHOULDER_TOP_RIGHT>~Z~22L~-2H~+17V<PAD_"
"PART_SHOULDER_BOTTOM_LEFT><PAD_PART_SHOULDER_BOTTOM_RIGHT>~Z~1L~+4H~+3V<PAD_PART_L1_NAME>~Z~+"
"38H",
"<PAD_L1>"},
{"~Y~22L~-2H~-12V<PAD_PART_SHOULDER_TOP_LEFT><PAD_PART_SHOULDER_TOP_RIGHT>~Z~22L~-2H~+17V<PAD_"
"PART_SHOULDER_BOTTOM_LEFT><PAD_PART_SHOULDER_BOTTOM_RIGHT>~Z~1L~+6H~+3V<PAD_PART_R1_NAME>~Z~+"
"38H",
"<PAD_R1>"},
{"~Y~22L~-2H~-6V<PAD_PART_TRIGGER_TOP_LEFT><PAD_PART_TRIGGER_TOP_RIGHT>~Z~22L~-2H~+16V<PAD_"
"PART_TRIGGER_BOTTOM_LEFT><PAD_PART_TRIGGER_BOTTOM_RIGHT>~Z~1L~+5H~-2V<PAD_PART_R2_NAME>~Z~+"
"38H",
"<PAD_R2>"},
{"~Y~22L~-2H~-6V<PAD_PART_TRIGGER_TOP_LEFT><PAD_PART_TRIGGER_TOP_RIGHT>~Z~22L~-2H~+16V<PAD_"
"PART_TRIGGER_BOTTOM_LEFT><PAD_PART_TRIGGER_BOTTOM_RIGHT>~Z~1L~+5H~-2V<PAD_PART_L2_NAME>~Z~+"
"38H",
"<PAD_L2>"},
// - analog
{"~1L~+8H~Y<PAD_PART_STICK>~Z~6L~-16H<PAD_PART_STICK_LEFT>~Z~+16h~6L<PAD_PART_STICK_RIGHT>~Z~"
"6L~-15V<PAD_PART_STICK_DOWN>~Z~+13V~6L<PAD_PART_STICK_UP>~Z~-10H~+9V~6L<PAD_PART_STICK_UP_"
"LEFT>~Z~+10H~+9V~6L<PAD_PART_STICK_UP_RIGHT>~Z~-10H~-11V~6L<PAD_PART_STICK_DOWN_LEFT>~Z~+10H~"
"-11V~6L<PAD_PART_STICK_DOWN_RIGHT>~Z~+32H",
"<PAD_ANALOG_ANY>"},
{"~Y~1L~+8H<PAD_PART_STICK>~Z~6L~-8H<PAD_PART_STICK_LEFT>~Z~+24H~6L<PAD_PART_STICK_RIGHT>~Z~+"
"40H",
"<PAD_ANALOG_LEFT_RIGHT>"},
{"~Y~1L<PAD_PART_STICK>~Z~6L~-15V<PAD_PART_STICK_DOWN>~Z~+13V~6L<PAD_PART_STICK_UP>~Z~+26H",
"<PAD_ANALOG_UP_DOWN>"},
// icons
{"~Y~6L<~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<ICON_MISSION_COMPLETE>"},
{"~Y~3L<~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<ICON_MISSION_TODO>"},
// flags
{"~Y~6L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+15H~1L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+30H~3L<FLAG_"
"PART_VERT_STRIPE_LARGE>~Z~+45H",
"<FLAG_ITALIAN>"},
{"~Y~5L<FLAG_PART_FILL>~Z~3L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-1H~Y~5L<FLAG_PART_FILL>~Z~3L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~+26H",
"<FLAG_SPAIN>"},
{"~Y~39L~~~Z~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~5L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-1H~Y~39L~~~"
"Z~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~5L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_GERMAN>"},
{"~Y~7L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+15H~1L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+30H~3L<FLAG_"
"PART_VERT_STRIPE_LARGE>~Z~+47H",
"<FLAG_FRANCE>"},
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_UK_CROSS_LEFT>~Z~7L<FLAG_PART_UK_FILL_LEFT>~]~-1H~Y~1L<"
"FLAG_PART_FILL>~Z~3L<FLAG_PART_UK_CROSS_RIGHT>~Z~7L<FLAG_PART_UK_FILL_RIGHT>~Z~+26H",
"<FLAG_UK>"},
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_USA_STRIPES_LEFT>~Z~7L<FLAG_PART_USA_STARS>~]~-1H~Y~1L<"
"FLAG_PART_FILL>~Z~3L<FLAG_PART_USA_STRIPES_RIGHT>~Z~+26H",
"<FLAG_USA>"},
{"~Y~1L<FLAG_PART_FILL>~Z~39L<FLAG_PART_KOREA_TRIGRAMS_LEFT>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~39L<"
"FLAG_PART_KOREA_TRIGRAMS_RIGHT>~Z~-11H~7L<FLAG_PART_KOREA_CIRCLE_FILL>~Z~-11H~3L<FLAG_PART_"
"KOREA_CIRCLE_TOP>~Z~+26H",
"<FLAG_KOREA>"},
{"~Y~1L<FLAG_PART_FILL>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~-11H~3L<FLAG_PART_JAPAN_SUN>~Z~+26H",
"<FLAG_JAPAN>"},
// 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<SOMETHING>~+3V~-4H",
"<SUPERSCRIPT_QUOTE>"}, // used for the 4<__> place in spanish. the 5th uses the same
// character but looks different...?
{"~Y~-6Hº~Z~+10H", "°"},
// Color / Emphasis
{"~[~0L", "<COLOR_DEFAULT>"},
{"~[~1L", "<COLOR_WHITE>"},
{"~[~2L", "<COLOR_TRANSPARENT>"},
{"~[~3L", "<COLOR_RED>"},
{"~[~4L", "<COLOR_ORANGE>"},
{"~[~5L", "<COLOR_YELLOW>"},
{"~[~6L", "<COLOR_GREEN>"},
{"~[~7L", "<COLOR_BLUE>"},
{"~[~8L", "<COLOR_CYAN>"},
{"~[~9L", "<COLOR_PINK>"},
{"~[~10L", "<COLOR_MENU-SELECTED>"},
{"~[~11L", "<COLOR_MENU-SELECTED-PARENT>"},
{"~[~12L", "<COLOR_MENU>"},
{"~[~13L", "<COLOR_MENU-PARENT>"},
{"~[~14L", "<COLOR_MENU-FUNC-BAD>"},
{"~[~15L", "<COLOR_MENU-FLAG-ON>"},
{"~[~16L", "<COLOR_MENU-FLAG-ON-PARENT>"},
{"~[~17L", "<COLOR_MENU-FLAG-OFF>"},
{"~[~18L", "<COLOR_MENU-FLAG-OFF-PARENT>"},
{"~[~19L", "<COLOR_MENU-INVALID>"},
{"~[~20L", "<COLOR_FLAT-YELLOW>"},
{"~[~21L", "<COLOR_COLOR-21>"},
{"~[~22L", "<COLOR_PAD-BACK>"},
{"~[~23L", "<COLOR_PAD-SHINE>"},
{"~[~24L", "<COLOR_PAD-SQUARE>"},
{"~[~25L", "<COLOR_PAD-CIRCLE>"},
{"~[~26L", "<COLOR_PAD-TRIANGLE>"},
{"~[~27L", "<COLOR_PAD-CROSS>"},
{"~[~28L", "<COLOR_PROGRESS-OLD-BLUE>"},
{"~[~29L", "<COLOR_PROGRESS-OLD-YELLOW>"},
{"~[~30L", "<COLOR_PROGRESS-OLD-SELECTED>"},
{"~[~31L", "<COLOR_PROGRESS-OLD-PERCENT>"},
{"~[~32L", "<COLOR_PROGRESS>"},
{"~[~33L", "<COLOR_PROGRESS-SELECTED>"},
{"~[~34L", "<COLOR_PROGRESS-FORCE-SELECTED>"},
{"~[~35L", "<COLOR_PROGRESS-OPTION-OFF>"},
{"~[~36L", "<COLOR_COLOR-36>"},
{"~[~37L", "<COLOR_CREDITS-STAFF-TITLE-1>"},
{"~[~38L", "<COLOR_CREDITS-STAFF-TITLE-2>"},
{"~[~39L", "<COLOR_COLOR-39>"}};
static std::vector<EncodeInfo> s_encode_info_jak2 = {
{"ˇ", {0x10}}, // caron
{"`", {0x11}}, // grave accent
{"'", {0x12}}, // apostrophe
{"^", {0x13}}, // circumflex
{"<TIL>", {0x14}}, // tilde
{"¨", {0x15}}, // umlaut
{"º", {0x16}}, // numero/overring
{"¡", {0x17}}, // inverted exclamation mark
{"¿", {0x18}}, // inverted question mark
{"<SOMETHING>", {0x19}},
{"ç", {0x1d}}, // c-cedilla
{"Ç", {0x1e}}, // c-cedilla
{"ß", {0x1f}}, // eszett
{"œ", {0x5e}}, // ligature o+e
{"<FLAG_PART_HORZ_STRIPE_MIDDLE>", {0x7f}},
{"<FLAG_PART_HORZ_STRIPE_BOTTOM>", {0x80}},
{"<FLAG_PART_VERT_STRIPE_LARGE>", {0x81}},
{"<FLAG_PART_VERT_STRIPE_RIGHT>", {0x82}},
{"<FLAG_PART_VERT_STRIPE_LEFT>", {0x83}},
{"<FLAG_PART_VERT_STRIPE_MIDDLE>", {0x84}},
{"<FLAG_PART_FILL>", {0x85}},
{"<FLAG_PART_JAPAN_SUN>", {0x86}},
{"<FLAG_PART_KOREA_TRIGRAMS_LEFT>", {0x87}},
{"<FLAG_PART_KOREA_TRIGRAMS_RIGHT>", {0x88}},
{"<FLAG_PART_KOREA_CIRCLE_TOP>", {0x89}},
{"<FLAG_PART_KOREA_CIRCLE_FILL>", {0x8a}},
{"<FLAG_PART_TOP_BOTTOM_STRIPE>", {0x8b}},
{"<FLAG_PART_UK_CROSS_LEFT>", {0x8c}},
{"<FLAG_PART_UK_CROSS_RIGHT>", {0x8d}},
{"<FLAG_PART_UK_FILL_LEFT>", {0x8e}},
{"<FLAG_PART_UK_FILL_RIGHT>", {0x8f}},
{"<FLAG_PART_USA_STRIPES_RIGHT>", {0x90}},
{"<PAD_PART_STICK>", {0x91}},
{"<PAD_PART_SELECT>", {0x92}},
{"<PAD_PART_TRIGGER_BACK>", {0x93}},
{"<PAD_PART_R1_NAME>", {0x94}},
{"<PAD_PART_L1_NAME>", {0x95}},
{"<PAD_PART_R2_NAME>", {0x96}},
{"<PAD_PART_L2_NAME>", {0x97}},
{"<PAD_PART_STICK_UP>", {0x98}},
{"<PAD_PART_STICK_UP_RIGHT>", {0x99}},
{"<FLAG_PART_USA_STRIPES_LEFT>", {0x9a}},
{"<FLAG_PART_USA_STARS>", {0x9b}},
{"<PAD_PART_STICK_DOWN>", {0x9c}},
{"<PAD_PART_STICK_DOWN_LEFT>", {0x9d}},
{"<PAD_PART_STICK_LEFT>", {0x9e}},
{"<PAD_PART_STICK_UP_LEFT>", {0x9f}},
{"<PAD_PART_DPAD_D>", {0xa0}},
{"<PAD_PART_DPAD_L>", {0xa1}},
{"<PAD_PART_DPAD_U>", {0xa2}},
{"<PAD_PART_DPAD_R>", {0xa3}},
{"<PAD_PART_STICK_RIGHT>", {0xa4}},
{"<PAD_PART_STICK_DOWN_RIGHT>", {0xa5}},
{"<PAD_PART_SHOULDER_TOP_LEFT>", {0xa6}},
{"<PAD_PART_SHOULDER_TOP_RIGHT>", {0xa7}},
{"<PAD_PART_TRIGGER_TOP_LEFT>", {0xa8}},
{"<PAD_PART_TRIGGER_TOP_RIGHT>", {0xa9}},
{"<PAD_PART_TRIGGER_SHIM1>", {0xaa}},
{"<PAD_PART_TRIGGER_SHIM2>", {0xab}},
{"<PAD_PART_SHOULDER_SHIM2>", {0xac}},
{"<PAD_PART_SHOULDER_BOTTOM_LEFT>", {0xb0}},
{"<PAD_PART_SHOULDER_BOTTOM_RIGHT>", {0xb1}},
{"<PAD_PART_TRIGGER_BOTTOM_LEFT>", {0xb2}},
{"<PAD_PART_TRIGGER_BOTTOM_RIGHT>", {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}},
{"<K300>", {3, 0x00}},
{"<K301>", {3, 0x01}},
{"<K302>", {3, 0x02}},
{"<K303>", {3, 0x03}},
{"<K304>", {3, 0x04}},
{"<K305>", {3, 0x05}},
{"<K306>", {3, 0x06}},
{"<K307>", {3, 0x07}},
{"<K308>", {3, 0x08}},
{"<K309>", {3, 0x09}},
{"<K30a>", {3, 0x0a}},
{"<K30b>", {3, 0x0b}},
{"<K30c>", {3, 0x0c}},
{"<K30d>", {3, 0x0d}},
{"<K30e>", {3, 0x0e}},
{"<K30f>", {3, 0x0f}},
{"<K310>", {3, 0x10}},
{"<K311>", {3, 0x11}},
{"<K312>", {3, 0x12}},
{"<K313>", {3, 0x13}},
{"<K314>", {3, 0x14}},
{"<K315>", {3, 0x15}},
{"<K316>", {3, 0x16}},
{"<K317>", {3, 0x17}},
{"<K318>", {3, 0x18}},
{"<K319>", {3, 0x19}},
{"<K31a>", {3, 0x1a}},
{"<K31b>", {3, 0x1b}},
{"<K31c>", {3, 0x1c}},
{"<K31d>", {3, 0x1d}},
{"<K31e>", {3, 0x1e}},
{"<K31f>", {3, 0x1f}},
{"<K320>", {3, 0x20}},
{"<K321>", {3, 0x21}},
{"<K322>", {3, 0x22}},
{"<K323>", {3, 0x23}},
{"<K324>", {3, 0x24}},
{"<K325>", {3, 0x25}},
{"<K326>", {3, 0x26}},
{"<K327>", {3, 0x27}},
{"<K328>", {3, 0x28}},
{"<K329>", {3, 0x29}},
{"<K32a>", {3, 0x2a}},
{"<K32b>", {3, 0x2b}},
{"<K32c>", {3, 0x2c}},
{"<K32d>", {3, 0x2d}},
{"<K32e>", {3, 0x2e}},
{"<K32f>", {3, 0x2f}},
{"<K330>", {3, 0x30}},
{"<K331>", {3, 0x31}},
{"<K332>", {3, 0x32}},
{"<K333>", {3, 0x33}},
{"<K334>", {3, 0x34}},
{"<K335>", {3, 0x35}},
{"<K336>", {3, 0x36}},
{"<K337>", {3, 0x37}},
{"<K338>", {3, 0x38}},
{"<K339>", {3, 0x39}},
{"<K33a>", {3, 0x3a}},
{"<K33b>", {3, 0x3b}},
{"<K33c>", {3, 0x3c}},
{"<K33d>", {3, 0x3d}},
{"<K33e>", {3, 0x3e}},
{"<K33f>", {3, 0x3f}},
{"<K340>", {3, 0x40}},
{"<K341>", {3, 0x41}},
{"<K342>", {3, 0x42}},
{"<K343>", {3, 0x43}},
{"<K344>", {3, 0x44}},
{"<K345>", {3, 0x45}},
{"<K346>", {3, 0x46}},
{"<K347>", {3, 0x47}},
{"<K348>", {3, 0x48}},
{"<K349>", {3, 0x49}},
{"<K34a>", {3, 0x4a}},
{"<K34b>", {3, 0x4b}},
{"<K34c>", {3, 0x4c}},
{"<K34d>", {3, 0x4d}},
{"<K34e>", {3, 0x4e}},
{"<K34f>", {3, 0x4f}},
{"<K350>", {3, 0x50}},
{"<K351>", {3, 0x51}},
{"<K352>", {3, 0x52}},
{"<K353>", {3, 0x53}},
{"<K354>", {3, 0x54}},
{"<K355>", {3, 0x55}},
{"<K356>", {3, 0x56}},
{"<K357>", {3, 0x57}},
{"<K358>", {3, 0x58}},
{"<K359>", {3, 0x59}},
{"<K35a>", {3, 0x5a}},
{"<K35b>", {3, 0x5b}},
{"<K35c>", {3, 0x5c}},
{"<K35d>", {3, 0x5d}},
{"<K35e>", {3, 0x5e}},
{"<K35f>", {3, 0x5f}},
{"<K360>", {3, 0x60}},
{"<K361>", {3, 0x61}},
{"<K362>", {3, 0x62}},
{"<K363>", {3, 0x63}},
{"<K364>", {3, 0x64}},
{"<K365>", {3, 0x65}},
{"<K366>", {3, 0x66}},
{"<K367>", {3, 0x67}},
{"<K368>", {3, 0x68}},
{"<K369>", {3, 0x69}},
{"<K36a>", {3, 0x6a}},
{"<K36b>", {3, 0x6b}},
{"<K36c>", {3, 0x6c}},
{"<K36d>", {3, 0x6d}},
{"<K36e>", {3, 0x6e}},
{"<K36f>", {3, 0x6f}},
{"<K370>", {3, 0x70}},
{"<K371>", {3, 0x71}},
{"<K372>", {3, 0x72}},
{"<K373>", {3, 0x73}},
{"<K374>", {3, 0x74}},
{"<K375>", {3, 0x75}},
{"<K376>", {3, 0x76}},
{"<K377>", {3, 0x77}},
{"<K378>", {3, 0x78}},
{"<K379>", {3, 0x79}},
{"<K37a>", {3, 0x7a}},
{"<K37b>", {3, 0x7b}},
{"<K37c>", {3, 0x7c}},
{"<K37d>", {3, 0x7d}},
{"<K37e>", {3, 0x7e}},
{"<K37f>", {3, 0x7f}},
{"<K380>", {3, 0x80}},
{"<K381>", {3, 0x81}},
{"<K382>", {3, 0x82}},
{"<K383>", {3, 0x83}},
{"<K384>", {3, 0x84}},
{"<K385>", {3, 0x85}},
{"<K386>", {3, 0x86}},
{"<K387>", {3, 0x87}},
{"<K388>", {3, 0x88}},
{"<K389>", {3, 0x89}},
{"<K38a>", {3, 0x8a}},
{"<K38b>", {3, 0x8b}},
{"<K38c>", {3, 0x8c}},
{"<K38d>", {3, 0x8d}},
{"<K38e>", {3, 0x8e}},
{"<K38f>", {3, 0x8f}},
{"<K390>", {3, 0x90}},
{"<K391>", {3, 0x91}},
{"<K392>", {3, 0x92}},
{"<K393>", {3, 0x93}},
{"<K394>", {3, 0x94}},
{"<K395>", {3, 0x95}},
{"<K396>", {3, 0x96}},
{"<K397>", {3, 0x97}},
{"<K398>", {3, 0x98}},
{"<K399>", {3, 0x99}},
{"<K39a>", {3, 0x9a}},
{"<K39b>", {3, 0x9b}},
{"<K39c>", {3, 0x9c}},
{"<K39d>", {3, 0x9d}},
{"<K39e>", {3, 0x9e}},
{"<K39f>", {3, 0x9f}},
{"<K3a0>", {3, 0xa0}},
{"<K3a1>", {3, 0xa1}},
{"<K3a2>", {3, 0xa2}},
{"<K3a3>", {3, 0xa3}},
{"<K3a4>", {3, 0xa4}},
{"<K3a5>", {3, 0xa5}},
{"<K3a6>", {3, 0xa6}},
{"<K3a7>", {3, 0xa7}},
{"<K3a8>", {3, 0xa8}},
{"<K3a9>", {3, 0xa9}},
{"<K3aa>", {3, 0xaa}},
{"<K3ab>", {3, 0xab}},
{"<K3ac>", {3, 0xac}},
{"<K3ad>", {3, 0xad}},
{"<K3ae>", {3, 0xae}},
{"<K3af>", {3, 0xaf}},
{"<K3b0>", {3, 0xb0}},
{"<K3b1>", {3, 0xb1}},
{"<K3b2>", {3, 0xb2}},
{"<K3b3>", {3, 0xb3}},
{"<K3b4>", {3, 0xb4}},
{"<K3b5>", {3, 0xb5}},
{"<K3b6>", {3, 0xb6}},
{"<K3b7>", {3, 0xb7}},
{"<K3b8>", {3, 0xb8}},
{"<K3b9>", {3, 0xb9}},
{"<K3ba>", {3, 0xba}},
{"<K3bb>", {3, 0xbb}},
{"<K3bc>", {3, 0xbc}},
{"<K3bd>", {3, 0xbd}},
{"<K3be>", {3, 0xbe}},
{"<K3bf>", {3, 0xbf}},
{"<K3c0>", {3, 0xc0}},
{"<K3c1>", {3, 0xc1}},
{"<K3c2>", {3, 0xc2}},
{"<K3c3>", {3, 0xc3}},
{"<K3c4>", {3, 0xc4}},
{"<K3c5>", {3, 0xc5}},
{"<K3c6>", {3, 0xc6}},
{"<K3c7>", {3, 0xc7}},
{"<K3c8>", {3, 0xc8}},
{"<K3c9>", {3, 0xc9}},
{"<K3ca>", {3, 0xca}},
{"<K3cb>", {3, 0xcb}},
{"<K3cc>", {3, 0xcc}},
{"<K3cd>", {3, 0xcd}},
{"<K3ce>", {3, 0xce}},
{"<K3cf>", {3, 0xcf}},
{"<K3d0>", {3, 0xd0}},
{"<K3d1>", {3, 0xd1}},
{"<K3d2>", {3, 0xd2}},
{"<K3d3>", {3, 0xd3}},
{"<K3d4>", {3, 0xd4}},
{"<K3d5>", {3, 0xd5}},
{"<K3d6>", {3, 0xd6}},
{"<K3d7>", {3, 0xd7}},
{"<K3d8>", {3, 0xd8}},
{"<K3d9>", {3, 0xd9}},
{"<K3da>", {3, 0xda}},
{"<K3db>", {3, 0xdb}},
{"<K3dc>", {3, 0xdc}},
{"<K3dd>", {3, 0xdd}},
{"<K3de>", {3, 0xde}},
{"<K3df>", {3, 0xdf}},
{"<K3e0>", {3, 0xe0}},
{"<K3e1>", {3, 0xe1}},
{"<K3e2>", {3, 0xe2}},
{"<K3e3>", {3, 0xe3}},
{"<K3e4>", {3, 0xe4}},
{"<K3e5>", {3, 0xe5}},
{"<K3e6>", {3, 0xe6}},
{"<K3e7>", {3, 0xe7}},
{"<K3e8>", {3, 0xe8}},
{"<K3e9>", {3, 0xe9}},
{"<K3ea>", {3, 0xea}},
{"<K3eb>", {3, 0xeb}},
{"<K3ec>", {3, 0xec}},
{"<K3ed>", {3, 0xed}},
{"<K3ee>", {3, 0xee}},
{"<K3ef>", {3, 0xef}},
{"<K3f0>", {3, 0xf0}},
{"<K3f1>", {3, 0xf1}},
{"<K3f2>", {3, 0xf2}},
{"<K3f3>", {3, 0xf3}},
{"<K3f4>", {3, 0xf4}},
{"<K3f5>", {3, 0xf5}},
{"<K3f6>", {3, 0xf6}},
{"<K3f7>", {3, 0xf7}},
{"<K3f8>", {3, 0xf8}},
{"<K3f9>", {3, 0xf9}},
{"<K3fa>", {3, 0xfa}},
{"<K3fb>", {3, 0xfb}},
{"<K3fc>", {3, 0xfc}},
{"<K3fd>", {3, 0xfd}},
{"<K3fe>", {3, 0xfe}},
{"<K3ff>", {3, 0xff}},
};
GameTextFontBank g_font_bank_jak2(GameTextVersion::JAK2,
&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<GameTextVersion, GameTextFontBank*> 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}};
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);
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();
}