mirror of
https://github.com/open-goal/jak-project
synced 2026-08-09 10:54:39 -04:00
d/jak2: first pass of jak 2's font (no japanese or korean support yet)
This commit is contained in:
@@ -152,6 +152,18 @@
|
||||
"${workspaceRoot}/decompiler_out"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "default",
|
||||
"project": "CMakeLists.txt",
|
||||
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
|
||||
"name": "Decompiler - Jak 2 - Extract",
|
||||
"args": [
|
||||
"${workspaceRoot}/decompiler/config/jak2_ntsc_v1.jsonc",
|
||||
"${workspaceRoot}/iso_data",
|
||||
"${workspaceRoot}/decompiler_out",
|
||||
"--config-override \"{\\\"decompile_code\\\": false}\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "default",
|
||||
"project": "CMakeLists.txt",
|
||||
|
||||
@@ -42,15 +42,15 @@ add_library(common
|
||||
util/DgoWriter.cpp
|
||||
util/diff.cpp
|
||||
util/FileUtil.cpp
|
||||
util/FontUtils.cpp
|
||||
util/json_util.cpp
|
||||
util/read_iso_file.cpp
|
||||
util/SimpleThreadGroup.cpp
|
||||
util/Timer.cpp
|
||||
util/os.cpp
|
||||
util/print_float.cpp
|
||||
util/FontUtils.cpp
|
||||
util/FrameLimiter.cpp
|
||||
util/unicode_util.cpp)
|
||||
util/unicode_util.cpp )
|
||||
|
||||
target_link_libraries(common fmt lzokay replxx libzstd_static)
|
||||
|
||||
|
||||
+232
-16
@@ -29,7 +29,8 @@ bool hex_char(char c) {
|
||||
|
||||
const std::unordered_map<std::string, GameTextVersion> sTextVerEnumMap = {
|
||||
{"jak1-v1", GameTextVersion::JAK1_V1},
|
||||
{"jak1-v2", GameTextVersion::JAK1_V2}};
|
||||
{"jak1-v2", GameTextVersion::JAK1_V2},
|
||||
{"jak2", GameTextVersion::JAK2}};
|
||||
|
||||
const std::string& get_text_version_name(GameTextVersion version) {
|
||||
for (auto& [name, ver] : sTextVerEnumMap) {
|
||||
@@ -157,6 +158,19 @@ std::string GameTextFontBank::convert_utf8_to_game(std::string str) const {
|
||||
return str;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Turn a normal readable string into a string readable in the in-game font encoding and converts
|
||||
* \cXX escape sequences
|
||||
@@ -219,9 +233,7 @@ std::string GameTextFontBank::convert_game_to_utf8(const char* in) const {
|
||||
if (remap != nullptr) {
|
||||
result.append(remap->chars);
|
||||
in += remap->bytes.size() - 1;
|
||||
} else if (((*in >= '0' && *in <= '9') || (*in >= 'A' && *in <= 'Z') ||
|
||||
m_passthrus->find(*in) != m_passthrus->end()) &&
|
||||
*in != '\\') {
|
||||
} else if (valid_char_range(*in)) {
|
||||
result.push_back(*in);
|
||||
} else if (*in == '\n') {
|
||||
result += "\\n";
|
||||
@@ -250,9 +262,9 @@ static std::vector<ReplaceInfo> s_replace_info_null = {};
|
||||
* - Jak & Daxter: The Precursor Legacy (Black Label)
|
||||
*/
|
||||
|
||||
static std::unordered_set<char> s_passthrus = {'~', ' ', ',', '.', '-', '+', '(', ')',
|
||||
'!', ':', '?', '=', '%', '*', '/', '#',
|
||||
';', '<', '>', '@', '[', '_'};
|
||||
static std::unordered_set<char> s_passthrus_jak1 = {'~', ' ', ',', '.', '-', '+', '(', ')',
|
||||
'!', ':', '?', '=', '%', '*', '/', '#',
|
||||
';', '<', '>', '@', '[', '_'};
|
||||
|
||||
static std::vector<EncodeInfo> s_encode_info_jak1 = {
|
||||
// random
|
||||
@@ -578,10 +590,10 @@ static std::vector<ReplaceInfo> s_replace_info_jak1 = {
|
||||
{"~Y~22L<~Z~Y~24L#~Z~Y~1L>~Z~Y~23L[~Z~+26H", "<PAD_SQUARE>"}, // custom
|
||||
};
|
||||
|
||||
GameTextFontBank g_font_bank_jak1(GameTextVersion::JAK1_V1,
|
||||
&s_encode_info_jak1,
|
||||
&s_replace_info_jak1,
|
||||
&s_passthrus);
|
||||
GameTextFontBank g_font_bank_jak1_v1(GameTextVersion::JAK1_V1,
|
||||
&s_encode_info_jak1,
|
||||
&s_replace_info_jak1,
|
||||
&s_passthrus_jak1);
|
||||
|
||||
/*!
|
||||
* ================================
|
||||
@@ -815,12 +827,216 @@ static std::vector<EncodeInfo> s_encode_info_jak1_v2 = {
|
||||
GameTextFontBank g_font_bank_jak1_v2(GameTextVersion::JAK1_V2,
|
||||
&s_encode_info_jak1_v2,
|
||||
&s_replace_info_jak1,
|
||||
&s_passthrus);
|
||||
&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", "Nº"},
|
||||
{"~+4VÇ~-4V", "ç"},
|
||||
|
||||
// tildes
|
||||
{"N~Y~-22H~-4V<TIL>~Z", "Ñ"},
|
||||
{"n~Y~-24H~-4V<TIL>~Z", "ñ"},
|
||||
{"A~Y~-21H~-5V<TIL>~Z", "Ã"}, // custom
|
||||
{"O~Y~-22H~-4V<TIL>~Z", "Õ"}, // custom
|
||||
|
||||
// acute accents
|
||||
{"A~Y~-21H~-5V'~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", "ú"},
|
||||
|
||||
// circumflex
|
||||
{"A~Y~-20H~-4V^~Z", "Â"}, // custom
|
||||
{"a~Y~-24H~-5V^~Z", "â"},
|
||||
{"E~Y~-20H~-5V^~Z", "Ê"},
|
||||
{"e~Y~-25H~-4V^~Zt", "ê"},
|
||||
{"I~Y~-19H~-5V^~Z", "Î"},
|
||||
{"i~Y~-19H~-8V^~Z", "î"},
|
||||
{"O~Y~-20H~-4V^~Z", "Ô"}, // custom
|
||||
{"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", "Ò"}, // custom
|
||||
{"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", "Ï"}, // custom
|
||||
{"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 ", " "},
|
||||
|
||||
// (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
|
||||
{"~Y~22L~-2H~-12V\\ca6\\ca7~Z~22L~-2H~+17V\\cb0\\cb1~Z~1L~+4H~+3V\\c95~Z~+38H", "<PAD_L1>"},
|
||||
{"~Y~22L~-2H~-12V\\ca6\\ca7~Z~22L~-2H~+17V\\cb0\\cb1~Z~1L~+6H~+3V\\c94~Z~+38H", "<PAD_R1>"},
|
||||
{"~Y~22L\\ca1~Z~3L~+17H~-13V\\ca2~Z~22L~+17H~+14V\\ca0~Z~22L~+32H\\ca3~Z~+56H",
|
||||
"<PAD_DPAD_UP>"},
|
||||
{"~Y~22L\\ca1~Z~3L~+17H~-13V\\ca2~Z~3L~+17H~+14V\\ca0~Z~22L~+32H\\ca3~Z~+56H",
|
||||
"<PAD_DPAD_DOWN>"},
|
||||
{"~Y~22L~-2H~-6V\\ca8\\ca9~Z~22L~-2H~+16V\\cb2\\cb3~Z~1L~+5H~-2V\\c96~Z~+38H", "<PAD_R2>"},
|
||||
{"~Y~22L~-2H~-6V\\ca8\\ca9~Z~22L~-2H~+16V\\cb2\\cb3~Z~1L~+5H~-2V\\c97~Z~+38H", "<PAD_L2>"},
|
||||
{"~1L~+8H~Y\\c91~Z~6L~-16H\\c9e~Z~+16h~6L\\ca4~Z~6L~-15V\\c9c~Z~+13V~6L\\c98~Z~-10H~+9V~"
|
||||
"6L\\c9f~Z~+10H~+9V~6L\\c99~Z~-10H~-11V~6L\\c9d~Z~+10H~-11V~6L\\ca5~Z~+32H",
|
||||
"<PAD_ANALOG_ANY>"},
|
||||
{"~Y~1L~+8H\\c91~Z~6L~-8H\\c9e~Z~+24H~6L\\ca4~Z~+40H", "<PAD_ANALOG_LEFT_RIGHT>"},
|
||||
{"~Y~1L\\c91~Z~6L~-15V\\c9c~Z~+13V~6L\\c98~Z~+26H", "<PAD_ANALOG_UP_DOWN>"},
|
||||
// TODO
|
||||
// - ~Y~22L\ca1~Z~22L~+17H~-13V\ca2~Z~22L~+17H~+14V\ca0~Z~22L~+32H\ca3~Z~+56H
|
||||
// - ~Y~6L<~Z~Y~1L>~Z~Y~23L[~Z~+26H
|
||||
// - ~Y~3L<~Z~Y~1L>~Z~Y~23L[~Z~+26H
|
||||
// - ~Y~1L\c85~Z~3L\c8c~Z~7L\c8e~\c5d~-1H~Y~1L\c85~Z~3L\c8d~Z~7L\c8f~Z~+26H
|
||||
// - ~Y~3L<~Z~Y~1L>~Z~Y~23L[~Z~+26H
|
||||
// - ~Y~1L\c85~\c5d~-1H~Y~1L\c85~Z~-11H~3L\c86~Z~+26H
|
||||
|
||||
// flags
|
||||
{"~Y~6L\\c81~Z~+15H~1L\\c81~Z~+30H~3L\\c81~Z~+45H", "<FLAG_ITALIAN>"},
|
||||
{"~Y~5L\\c85~Z~3L\\c8b~\\c5d~-1H~Y~5L\\c85~Z~3L\\c8b~Z~+26H", "<FLAG_SPAIN>"},
|
||||
{"~Y~39L~~~Z~3L\\c7f~Z~5L\\c80~\\c5d~-1H~Y~39L~~~Z~3L\\c7f~Z~5L\\c80~Z~+26H",
|
||||
"<FLAG_GERMAN>"},
|
||||
{"~Y~7L\\c81~Z~+15H~1L\\c81~Z~+30H~3L\\c81~Z~+47H", "<FLAG_FRANCE>"},
|
||||
{"~Y~1L\\c85~Z~3L\\c9a~Z~7L\\c9b~\\c5d~-1H~Y~1L\\c85~Z~3L\\c90~Z~+26H", "<FLAG_UK>"},
|
||||
{"~Y~1L\\c85~Z~39L\\c87~\\c5d~-1H~Y~1L\\c85~Z~39L\\c88~Z~-11H~7L\\c8a~Z~-11H~3L\\c89~Z~+26H", "<FLAG_JAPAN>"},
|
||||
{"~Y~1L\\c85~\\c5d~-1H~Y~1L\\c85~Z~-11H~3L\\c86~Z~+26H", "<FLAG_SOUTH_KOREA>"},
|
||||
|
||||
// weird stuff
|
||||
// - some sort of control character to adjust kerning, ie after `i` and `o`?
|
||||
{"~+7V", ""},
|
||||
// - preceeding character has a descender?
|
||||
{"~-7V", ""},
|
||||
// - i wonder if this is just a generic code to say "push the next character up or down
|
||||
// vertically"?
|
||||
{"~+1V", ""},
|
||||
{"~-1V", ""},
|
||||
|
||||
{"~-4H~-3V\\c19~+3V~-4H",
|
||||
"<SUPERSCRIPT_QUOTE>"}, // used for the 4<__> place in spanish. the 5th uses the same
|
||||
// character but looks different...?
|
||||
{"~Y~-6Hº~Z~+10H", "°"},
|
||||
{"\\c5e", "œ"}, // ligature o+e
|
||||
|
||||
// Color / Emphasis
|
||||
{"~[~1L", "<COLOR_WHITE>"},
|
||||
{"~[~32L", "<COLOR_DEFAULT>"}};
|
||||
|
||||
static std::vector<EncodeInfo> s_encode_info_jak2 = {
|
||||
{"_", {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
|
||||
{"Ç", {0x1d}}, // c-cedilla
|
||||
|
||||
{"ß", {0x1f}}, // eszett
|
||||
|
||||
};
|
||||
|
||||
GameTextFontBank g_font_bank_jak2(GameTextVersion::JAK2,
|
||||
&s_encode_info_null,
|
||||
&s_replace_info_null,
|
||||
&s_passthrus);
|
||||
&s_encode_info_jak2,
|
||||
&s_replace_info_jak2,
|
||||
&s_passthrus_jak2);
|
||||
|
||||
/*!
|
||||
* ========================
|
||||
@@ -830,7 +1046,7 @@ GameTextFontBank g_font_bank_jak2(GameTextVersion::JAK2,
|
||||
*/
|
||||
|
||||
std::map<GameTextVersion, GameTextFontBank*> g_font_banks = {
|
||||
{GameTextVersion::JAK1_V1, &g_font_bank_jak1},
|
||||
{GameTextVersion::JAK1_V1, &g_font_bank_jak1_v1},
|
||||
{GameTextVersion::JAK1_V2, &g_font_bank_jak1_v2},
|
||||
{GameTextVersion::JAK2, &g_font_bank_jak2}};
|
||||
|
||||
|
||||
@@ -75,6 +75,10 @@ class GameTextFontBank {
|
||||
|
||||
GameTextVersion version() const { return m_version; }
|
||||
|
||||
// TODO - methods would help make this code a lot better for different game versions
|
||||
// hacking it for now
|
||||
bool valid_char_range(const char in) const;
|
||||
|
||||
std::string convert_utf8_to_game_with_escape(const std::string& str) const;
|
||||
std::string convert_utf8_to_game(std::string str) const;
|
||||
std::string convert_game_to_utf8(const char* in) const;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
// unpack textures to assets folder
|
||||
"process_tpages": false,
|
||||
// unpack game text to assets folder
|
||||
"process_game_text": false,
|
||||
"process_game_text": true,
|
||||
// unpack game count to assets folder
|
||||
"process_game_count": true,
|
||||
// write goal imports for art groups
|
||||
|
||||
Reference in New Issue
Block a user