jak-project/common/util/FontUtils.cpp

1945 lines
57 KiB
C++
Raw Normal View History

/*!
* @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>
i18n: subtitle code cleanup and update new subtitle JSON files to be compatible with Crowdin (#2802) The main thing that was done here was to slightly modify the new subtitle-v2 JSON schema to be more similar to the existing one so that it can properly be used in Crowdin. Draft while I double-check the diff myself Along the way the following was also done (among other things): - got rid of as much duplication as was feasible in the serialization and editor code - separated the text serialization code from the subtitle code for better organization - simplified "base language" in the editor. The new subtitle format has built-in support for defining a base language so the editor doesn't have to be used as a crutch. Also, cutscenes only defined in the base come first in the list now as that is generally the order you'd work from (what you havn't done first) - got rid of the GOAL subtitle format code completely - switched jak 2 text translations to the JSON format as well - found a few mistakes in the jak 1 subtitle metadata files - added a couple minor features to the editor - consolidate and removed complexity, ie. recently all jak 1 hints were forced to the `named` type, so I got rid of the two types as there isn't a need anymore. - removed subtitle editor groups for jak 1, the only reason they existed was so when the GOAL file was manually written out they were somewhat organized, the editor has a decent filter control, there's no need for them. - removed the GOAL -> JSON python script helper, it's been a month or so and no one has come forward with existing translations that they need help with migrating. If they do need it, the script will be in the git history. I did some reasonably through testing in Jak1/Jak 2 and everything seemed to work. But more testing is always a good idea. --------- Co-authored-by: ManDude <7569514+ManDude@users.noreply.github.com>
2023-07-08 21:53:39 -04:00
#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
*/
i18n: subtitle code cleanup and update new subtitle JSON files to be compatible with Crowdin (#2802) The main thing that was done here was to slightly modify the new subtitle-v2 JSON schema to be more similar to the existing one so that it can properly be used in Crowdin. Draft while I double-check the diff myself Along the way the following was also done (among other things): - got rid of as much duplication as was feasible in the serialization and editor code - separated the text serialization code from the subtitle code for better organization - simplified "base language" in the editor. The new subtitle format has built-in support for defining a base language so the editor doesn't have to be used as a crutch. Also, cutscenes only defined in the base come first in the list now as that is generally the order you'd work from (what you havn't done first) - got rid of the GOAL subtitle format code completely - switched jak 2 text translations to the JSON format as well - found a few mistakes in the jak 1 subtitle metadata files - added a couple minor features to the editor - consolidate and removed complexity, ie. recently all jak 1 hints were forced to the `named` type, so I got rid of the two types as there isn't a need anymore. - removed subtitle editor groups for jak 1, the only reason they existed was so when the GOAL file was manually written out they were somewhat organized, the editor has a decent filter control, there's no need for them. - removed the GOAL -> JSON python script helper, it's been a month or so and no one has come forward with existing translations that they need help with migrating. If they do need it, the script will be in the git history. I did some reasonably through testing in Jak1/Jak 2 and everything seemed to work. But more testing is always a good idea. --------- Co-authored-by: ManDude <7569514+ManDude@users.noreply.github.com>
2023-07-08 21:53:39 -04:00
// 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);
i18n: subtitle code cleanup and update new subtitle JSON files to be compatible with Crowdin (#2802) The main thing that was done here was to slightly modify the new subtitle-v2 JSON schema to be more similar to the existing one so that it can properly be used in Crowdin. Draft while I double-check the diff myself Along the way the following was also done (among other things): - got rid of as much duplication as was feasible in the serialization and editor code - separated the text serialization code from the subtitle code for better organization - simplified "base language" in the editor. The new subtitle format has built-in support for defining a base language so the editor doesn't have to be used as a crutch. Also, cutscenes only defined in the base come first in the list now as that is generally the order you'd work from (what you havn't done first) - got rid of the GOAL subtitle format code completely - switched jak 2 text translations to the JSON format as well - found a few mistakes in the jak 1 subtitle metadata files - added a couple minor features to the editor - consolidate and removed complexity, ie. recently all jak 1 hints were forced to the `named` type, so I got rid of the two types as there isn't a need anymore. - removed subtitle editor groups for jak 1, the only reason they existed was so when the GOAL file was manually written out they were somewhat organized, the editor has a decent filter control, there's no need for them. - removed the GOAL -> JSON python script helper, it's been a month or so and no one has come forward with existing translations that they need help with migrating. If they do need it, the script will be in the git history. I did some reasonably through testing in Jak1/Jak 2 and everything seemed to work. But more testing is always a good idea. --------- Co-authored-by: ManDude <7569514+ManDude@users.noreply.github.com>
2023-07-08 21:53:39 -04:00
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", "Ż"},
2023-11-04 13:58:38 -04:00
{"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)
* -   
* - 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", "ő"},
2023-11-04 13:58:38 -04:00
{"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();
}